24 Containers library [containers]

24.6 Container adaptors [container.adaptors]

24.6.1 In general [container.adaptors.general]

The headers <queue>, <stack>, <flat_­map>, and <flat_­set> define the container adaptors queue and priority_­queue, stack, flat_­map and flat_­multimap, and flat_­set and flat_­multiset, respectively.
Each container adaptor takes one or more template parameters named Container, KeyContainer, or MappedContainer that denote the types of containers that the container adaptor adapts.
Each container adaptor has at least one constructor that takes a reference argument to one or more such template parameters.
For each constructor reference argument to a container C, the constructor copies the container into the container adaptor.
If C takes an allocator, then a compatible allocator may be passed in to the adaptor's constructor.
Otherwise, normal copy or move construction is used for the container argument.
For the container adaptors that take a single container template parameter Container, the first template parameter T of the container adaptor shall denote the same type as Container​::​value_­type.
For container adaptors, no swap function throws an exception unless that exception is thrown by the swap of the adaptor's Container, KeyContainer, MappedContainer, or Compare object (if any).
A constructor template of a container adaptor shall not participate in overload resolution if it has an InputIterator template parameter and a type that does not qualify as an input iterator is deduced for that parameter.
For container adaptors that have them, the insert, emplace, and erase members affect the validity of iterators, references, and pointers to the adaptor's container(s) in the same way that the containers' respective insert, emplace, and erase members do.
[Example 1:
A call to flat_­map<Key, T>​::​insert can invalidate all iterators to the flat_­map.
— end example]
A deduction guide for a container adaptor shall not participate in overload resolution if any of the following are true:
  • It has an InputIterator template parameter and a type that does not qualify as an input iterator is deduced for that parameter.
  • It has a Compare template parameter and a type that qualifies as an allocator is deduced for that parameter.
  • It has a Container, KeyContainer, or MappedContainer template parameter and a type that qualifies as an allocator is deduced for that parameter.
  • It has no Container, KeyContainer, or MappedContainer template parameter, and it has an Allocator template parameter, and a type that does not qualify as an allocator is deduced for that parameter.
  • It has both Container and Allocator template parameters, and uses_­allocator_­v<Container, Allocator> is false.
  • It has both KeyContainer and Allocator template parameters, and uses_­allocator_­v<KeyContainer, Allocator> is false.
  • It has both MappedContainer and Allocator template parameters, and uses_­allocator_­v<MappedContainer, Allocator> is false.
The exposition-only alias template iter-value-type defined in [sequences.general] and the exposition-only alias templates iter-key-type and iter-mapped-type defined in [associative.general] may appear in deduction guides for container adaptors.
The following exposition-only alias templates may appear in deduction guides for container adaptors: template<class Container> using cont-key-type = // exposition only remove_const_t<typename Container::value_type::first_type>; template<class Container> using cont-mapped-type = // exposition only typename Container::value_type::second_type;

24.6.2 Header <queue> synopsis [queue.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { template<class T, class Container = deque<T>> class queue; template<class T, class Container> bool operator==(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container> bool operator!=(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container> bool operator< (const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container> bool operator> (const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container> bool operator<=(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container> bool operator>=(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, three_­way_­comparable Container> compare_three_way_result_t<Container> operator<=>(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container> void swap(queue<T, Container>& x, queue<T, Container>& y) noexcept(noexcept(x.swap(y))); template<class T, class Container, class Alloc> struct uses_allocator<queue<T, Container>, Alloc>; template<class T, class Container = vector<T>, class Compare = less<typename Container::value_type>> class priority_queue; template<class T, class Container, class Compare> void swap(priority_queue<T, Container, Compare>& x, priority_queue<T, Container, Compare>& y) noexcept(noexcept(x.swap(y))); template<class T, class Container, class Compare, class Alloc> struct uses_allocator<priority_queue<T, Container, Compare>, Alloc>; }

24.6.3 Header <stack> synopsis [stack.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { template<class T, class Container = deque<T>> class stack; template<class T, class Container> bool operator==(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container> bool operator!=(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container> bool operator< (const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container> bool operator> (const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container> bool operator<=(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container> bool operator>=(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, three_­way_­comparable Container> compare_three_way_result_t<Container> operator<=>(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container> void swap(stack<T, Container>& x, stack<T, Container>& y) noexcept(noexcept(x.swap(y))); template<class T, class Container, class Alloc> struct uses_allocator<stack<T, Container>, Alloc>; }

24.6.4 Header <flat_­map> synopsis [flat.map.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [flat.map], class template flat_­map template<class Key, class T, class Compare = less<Key>, class KeyContainer = vector<Key>, class MappedContainer = vector<T>> class flat_map; struct sorted_unique_t { explicit sorted_unique_t() = default; }; inline constexpr sorted_unique_t sorted_unique{}; template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Allocator> struct uses_allocator<flat_map<Key, T, Compare, KeyContainer, MappedContainer>, Allocator>; // [flat.map.erasure], erasure for flat_­map template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Predicate> typename flat_map<Key, T, Compare, KeyContainer, MappedContainer>::size_type erase_if(flat_map<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred); // [flat.multimap], class template flat_­multimap template<class Key, class T, class Compare = less<Key>, class KeyContainer = vector<Key>, class MappedContainer = vector<T>> class flat_multimap; struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; }; inline constexpr sorted_equivalent_t sorted_equivalent{}; template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Allocator> struct uses_allocator<flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>, Allocator>; // [flat.multimap.erasure], erasure for flat_­multimap template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Predicate> typename flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>::size_type erase_if(flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred); }

24.6.5 Header <flat_­set> synopsis [flat.set.syn]

#include <initializer_list> // see [initializer.list.syn] namespace std { // [flat.set], class template flat_­set template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>> class flat_set; struct sorted_unique_t { explicit sorted_unique_t() = default; }; inline constexpr sorted_unique_t sorted_unique{}; template<class Key, class Compare, class KeyContainer, class Allocator> struct uses_allocator<flat_set<Key, Compare, KeyContainer>, Allocator>; // [flat.set.erasure], erasure for flat_­set template<class Key, class Compare, class KeyContainer, class Predicate> typename flat_set<Key, Compare, KeyContainer>::size_type erase_if(flat_set<Key, Compare, KeyContainer>& c, Predicate pred); // [flat.multiset], class template flat_­multiset template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>> class flat_multiset; struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; }; inline constexpr sorted_equivalent_t sorted_equivalent{}; template<class Key, class Compare, class KeyContainer, class Allocator> struct uses_allocator<flat_multiset<Key, Compare, KeyContainer>, Allocator>; // [flat.multiset.erasure], erasure for flat_­multiset template<class Key, class Compare, class KeyContainer, class Predicate> typename flat_multiset<Key, Compare, KeyContainer>::size_type erase_if(flat_multiset<Key, Compare, KeyContainer>& c, Predicate pred); }

24.6.6 Class template queue [queue]

24.6.6.1 Definition [queue.defn]

Any sequence container supporting operations front(), back(), push_­back() and pop_­front() can be used to instantiate queue.
In particular, list and deque can be used.
namespace std { template<class T, class Container = deque<T>> class queue { public: using value_type = typename Container::value_type; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using size_type = typename Container::size_type; using container_type = Container; protected: Container c; public: queue() : queue(Container()) {} explicit queue(const Container&); explicit queue(Container&&); template<class InputIterator> queue(InputIterator first, InputIterator last); template<container-compatible-range<T> R> queue(from_range_t, R&& rg); template<class Alloc> explicit queue(const Alloc&); template<class Alloc> queue(const Container&, const Alloc&); template<class Alloc> queue(Container&&, const Alloc&); template<class Alloc> queue(const queue&, const Alloc&); template<class Alloc> queue(queue&&, const Alloc&); template<class InputIterator, class Alloc> queue(InputIterator first, InputIterator last, const Alloc&); template<container-compatible-range<T> R, class Alloc> queue(from_range_t, R&& rg, const Alloc&); [[nodiscard]] bool empty() const { return c.empty(); } size_type size() const { return c.size(); } reference front() { return c.front(); } const_reference front() const { return c.front(); } reference back() { return c.back(); } const_reference back() const { return c.back(); } void push(const value_type& x) { c.push_back(x); } void push(value_type&& x) { c.push_back(std::move(x)); } template<container-compatible-range<T> R> void push_range(R&& rg); template<class... Args> decltype(auto) emplace(Args&&... args) { return c.emplace_back(std::forward<Args>(args)...); } void pop() { c.pop_front(); } void swap(queue& q) noexcept(is_nothrow_swappable_v<Container>) { using std::swap; swap(c, q.c); } }; template<class Container> queue(Container) -> queue<typename Container::value_type, Container>; template<class InputIterator> queue(InputIterator, InputIterator) -> queue<iter-value-type<InputIterator>>; template<ranges::input_­range R> queue(from_range_t, R&&) -> queue<ranges::range_value_t<R>>; template<class Container, class Allocator> queue(Container, Allocator) -> queue<typename Container::value_type, Container>; template<class InputIterator, class Allocator> queue(InputIterator, InputIterator, Allocator) -> queue<iter-value-type<InputIterator>, deque<iter-value-type<InputIterator>, Allocator>>; template<ranges::input_­range R, class Allocator> queue(from_range_t, R&&, Allocator) -> queue<ranges::range_value_t<R>, deque<ranges::range_value_t<R>, Allocator>>; template<class T, class Container, class Alloc> struct uses_allocator<queue<T, Container>, Alloc> : uses_allocator<Container, Alloc>::type { }; }

24.6.6.2 Constructors [queue.cons]

explicit queue(const Container& cont);
Effects: Initializes c with cont.
explicit queue(Container&& cont);
Effects: Initializes c with std​::​move(cont).
template<class InputIterator> queue(InputIterator first, InputIterator last);
Effects: Initializes c with first as the first argument and last as the second argument.
template<container-compatible-range<T> R> queue(from_range_t, R&& rg);
Effects: Initializes c with ranges​::​to<Container>(std​::​forward<R>(rg)).

24.6.6.3 Constructors with allocators [queue.cons.alloc]

If uses_­allocator_­v<container_­type, Alloc> is false the constructors in this subclause shall not participate in overload resolution.
template<class Alloc> explicit queue(const Alloc& a);
Effects: Initializes c with a.
template<class Alloc> queue(const container_type& cont, const Alloc& a);
Effects: Initializes c with cont as the first argument and a as the second argument.
template<class Alloc> queue(container_type&& cont, const Alloc& a);
Effects: Initializes c with std​::​move(cont) as the first argument and a as the second argument.
template<class Alloc> queue(const queue& q, const Alloc& a);
Effects: Initializes c with q.c as the first argument and a as the second argument.
template<class Alloc> queue(queue&& q, const Alloc& a);
Effects: Initializes c with std​::​move(q.c) as the first argument and a as the second argument.
template<class InputIterator, class Alloc> queue(InputIterator first, InputIterator last, const Alloc& alloc);
Effects: Initializes c with first as the first argument, last as the second argument, and alloc as the third argument.
template<container-compatible-range<T> R, class Alloc> queue(from_range_t, R&& rg, const Alloc& a);
Effects: Initializes c with ranges​::​to<Container>(std​::​forward<R>(rg), a).

24.6.6.4 Modifiers [queue.mod]

template<container-compatible-range<T> R> void push_range(R&& rg);
Effects: Equivalent to c.append_­range(std​::​forward<R>(rg)) if that is a valid expression, otherwise ranges​::​copy(rg, back_­inserter(c)).

24.6.6.5 Operators [queue.ops]

template<class T, class Container> bool operator==(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c == y.c.
template<class T, class Container> bool operator!=(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c != y.c.
template<class T, class Container> bool operator< (const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c < y.c.
template<class T, class Container> bool operator> (const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c > y.c.
template<class T, class Container> bool operator<=(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c <= y.c.
template<class T, class Container> bool operator>=(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c >= y.c.
template<class T, three_­way_­comparable Container> compare_three_way_result_t<Container> operator<=>(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c <=> y.c.

24.6.6.6 Specialized algorithms [queue.special]

template<class T, class Container> void swap(queue<T, Container>& x, queue<T, Container>& y) noexcept(noexcept(x.swap(y)));
Constraints: is_­swappable_­v<Container> is true.
Effects: As if by x.swap(y).

24.6.7 Class template priority_­queue [priority.queue]

24.6.7.1 Overview [priqueue.overview]

Any sequence container with random access iterator and supporting operations front(), push_­back() and pop_­back() can be used to instantiate priority_­queue.
In particular, vector and deque can be used.
Instantiating priority_­queue also involves supplying a function or function object for making priority comparisons; the library assumes that the function or function object defines a strict weak ordering.
namespace std { template<class T, class Container = vector<T>, class Compare = less<typename Container::value_type>> class priority_queue { public: using value_type = typename Container::value_type; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using size_type = typename Container::size_type; using container_type = Container; using value_compare = Compare; protected: Container c; Compare comp; public: priority_queue() : priority_queue(Compare()) {} explicit priority_queue(const Compare& x) : priority_queue(x, Container()) {} priority_queue(const Compare& x, const Container&); priority_queue(const Compare& x, Container&&); template<class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare()); template<class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x, const Container&); template<class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x, Container&&); template<container-compatible-range<T> R> priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); template<class Alloc> explicit priority_queue(const Alloc&); template<class Alloc> priority_queue(const Compare&, const Alloc&); template<class Alloc> priority_queue(const Compare&, const Container&, const Alloc&); template<class Alloc> priority_queue(const Compare&, Container&&, const Alloc&); template<class Alloc> priority_queue(const priority_queue&, const Alloc&); template<class Alloc> priority_queue(priority_queue&&, const Alloc&); template<class InputIterator, class Alloc> priority_queue(InputIterator, InputIterator, const Alloc&); template<class InputIterator, class Alloc> priority_queue(InputIterator, InputIterator, const Compare&, const Alloc&); template<class InputIterator, class Alloc> priority_queue(InputIterator, InputIterator, const Compare&, const Container&, const Alloc&); template<class InputIterator, class Alloc> priority_queue(InputIterator, InputIterator, const Compare&, Container&&, const Alloc&); template<container-compatible-range<T> R, class Alloc> priority_queue(from_range_t, R&& rg, const Compare&, const Alloc&); template<container-compatible-range<T> R, class Alloc> priority_queue(from_range_t, R&& rg, const Alloc&); [[nodiscard]] bool empty() const { return c.empty(); } size_type size() const { return c.size(); } const_reference top() const { return c.front(); } void push(const value_type& x); void push(value_type&& x); template<container-compatible-range<T> R> void push_range(R&& rg); template<class... Args> void emplace(Args&&... args); void pop(); void swap(priority_queue& q) noexcept(is_nothrow_swappable_v<Container> && is_nothrow_swappable_v<Compare>) { using std::swap; swap(c, q.c); swap(comp, q.comp); } }; template<class Compare, class Container> priority_queue(Compare, Container) -> priority_queue<typename Container::value_type, Container, Compare>; template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>, class Container = vector<iter-value-type<InputIterator>>> priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) -> priority_queue<iter-value-type<InputIterator>, Container, Compare>; template<ranges::input_­range R, class Compare = less<ranges::range_value_t<R>>> priority_queue(from_range_t, R&&, Compare = Compare()) -> priority_queue<ranges::range_value_t<R>, vector<ranges::range_value_t<R>>, Compare>; template<class Compare, class Container, class Allocator> priority_queue(Compare, Container, Allocator) -> priority_queue<typename Container::value_type, Container, Compare>; template<class InputIterator, class Allocator> priority_queue(InputIterator, InputIterator, Allocator) -> priority_queue<iter-value-type<InputIterator>, vector<iter-value-type<InputIterator>, Allocator>, less<iter-value-type<InputIterator>>>; template<class InputIterator, class Compare, class Allocator> priority_queue(InputIterator, InputIterator, Compare, Allocator) -> priority_queue<iter-value-type<InputIterator>, vector<iter-value-type<InputIterator>, Allocator>, Compare>; template<class InputIterator, class Compare, class Container, class Allocator> priority_queue(InputIterator, InputIterator, Compare, Container, Allocator) -> priority_queue<typename Container::value_type, Container, Compare>; template<ranges::input_­range R, class Compare, class Allocator> priority_queue(from_range_t, R&&, Compare, Allocator) -> priority_queue<ranges::range_value_t<R>, vector<ranges::range_value_t<R>, Allocator>, Compare>; template<ranges::input_­range R, class Allocator> priority_queue(from_range_t, R&&, Allocator) -> priority_queue<ranges::range_value_t<R>, vector<ranges::range_value_t<R>, Allocator>>; // no equality is provided template<class T, class Container, class Compare, class Alloc> struct uses_allocator<priority_queue<T, Container, Compare>, Alloc> : uses_allocator<Container, Alloc>::type { }; }

24.6.7.2 Constructors [priqueue.cons]

priority_queue(const Compare& x, const Container& y); priority_queue(const Compare& x, Container&& y);
Preconditions: x defines a strict weak ordering ([alg.sorting]).
Effects: Initializes comp with x and c with y (copy constructing or move constructing as appropriate); calls make_­heap(c.begin(), c.end(), comp).
template<class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare());
Preconditions: x defines a strict weak ordering ([alg.sorting]).
Effects: Initializes c with first as the first argument and last as the second argument, and initializes comp with x; then calls make_­heap(c.begin(), c.end(), comp).
template<class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x, const Container& y); template<class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x, Container&& y);
Preconditions: x defines a strict weak ordering ([alg.sorting]).
Effects: Initializes comp with x and c with y (copy constructing or move constructing as appropriate); calls c.insert(c.end(), first, last); and finally calls make_­heap(c.begin(), c.end(), comp).
template<container-compatible-range<T> R> priority_queue(from_range_t, R&& rg, const Compare& x = Compare());
Preconditions: x defines a strict weak ordering ([alg.sorting]).
Effects: Initializes comp with x and c with ranges​::​to<Container>(std​::​forward<R>(rg)) and finally calls make_­heap(c.begin(), c.end(), comp).

24.6.7.3 Constructors with allocators [priqueue.cons.alloc]

If uses_­allocator_­v<container_­type, Alloc> is false the constructors in this subclause shall not participate in overload resolution.
template<class Alloc> explicit priority_queue(const Alloc& a);
Effects: Initializes c with a and value-initializes comp.
template<class Alloc> priority_queue(const Compare& compare, const Alloc& a);
Effects: Initializes c with a and initializes comp with compare.
template<class Alloc> priority_queue(const Compare& compare, const Container& cont, const Alloc& a);
Effects: Initializes c with cont as the first argument and a as the second argument, and initializes comp with compare; calls make_­heap(c.begin(), c.end(), comp).
template<class Alloc> priority_queue(const Compare& compare, Container&& cont, const Alloc& a);
Effects: Initializes c with std​::​move(cont) as the first argument and a as the second argument, and initializes comp with compare; calls make_­heap(c.begin(), c.end(), comp).
template<class Alloc> priority_queue(const priority_queue& q, const Alloc& a);
Effects: Initializes c with q.c as the first argument and a as the second argument, and initializes comp with q.comp.
template<class Alloc> priority_queue(priority_queue&& q, const Alloc& a);
Effects: Initializes c with std​::​move(q.c) as the first argument and a as the second argument, and initializes comp with std​::​move(q.comp).
template<class InputIterator, class Alloc> priority_queue(InputIterator first, InputIterator last, const Alloc& a);
Effects: Initializes c with first as the first argument, last as the second argument, and a as the third argument, and value-initializes comp; calls make_­heap(c.begin(), c.end(), comp).
template<class InputIterator, class Alloc> priority_queue(InputIterator first, InputIterator last, const Compare& compare, const Alloc& a);
Effects: Initializes c with first as the first argument, last as the second argument, and a as the third argument, and initializes comp with compare; calls make_­heap(c.begin(), c.end(), comp).
template<class InputIterator, class Alloc> priority_queue(InputIterator first, InputIterator last, const Compare& compare, const Container& cont, const Alloc& a);
Effects: Initializes c with cont as the first argument and a as the second argument, and initializes comp with compare; calls c.insert(c.end(), first, last); and finally calls make_­heap(c.begin(), c.end(), comp).
template<class InputIterator, class Alloc> priority_queue(InputIterator first, InputIterator last, const Compare& compare, Container&& cont, const Alloc& a);
Effects: Initializes c with std​::​move(cont) as the first argument and a as the second argument, and initializes comp with compare; calls c.insert(c.end(), first, last); and finally calls make_­heap(c.begin(), c.end(), comp).
template<container-compatible-range<T> R, class Alloc> priority_queue(from_range_t, R&& rg, const Compare& compare, const Alloc& a);
Effects: Initializes comp with compare and c with ranges​::​to<Container>(std​::​forward<R>(rg), a); calls make_­heap(c.begin(), c.end(), comp).
template<container-compatible-range<T> R, class Alloc> priority_queue(from_range_t, R&& rg, const Alloc& a);
Effects: Initializes c with ranges​::​to<Container>(std​::​forward<R>(rg), a); calls make_­heap(c.
begin(), c.end(), comp)
.

24.6.7.4 Members [priqueue.members]

void push(const value_type& x);
Effects: As if by: c.push_back(x); push_heap(c.begin(), c.end(), comp);
void push(value_type&& x);
Effects: As if by: c.push_back(std::move(x)); push_heap(c.begin(), c.end(), comp);
template<container-compatible-range<T> R> void push_range(R&& rg);
Effects: Insert all elements of rg in c.
Postconditions: is_­heap(c.begin(), c.end(), comp) is true.
template<class... Args> void emplace(Args&&... args);
Effects: As if by: c.emplace_back(std::forward<Args>(args)...); push_heap(c.begin(), c.end(), comp);
void pop();
Effects: As if by: pop_heap(c.begin(), c.end(), comp); c.pop_back();

24.6.7.5 Specialized algorithms [priqueue.special]

template<class T, class Container, class Compare> void swap(priority_queue<T, Container, Compare>& x, priority_queue<T, Container, Compare>& y) noexcept(noexcept(x.swap(y)));
Constraints: is_­swappable_­v<Container> is true and is_­swappable_­v<Compare> is true.
Effects: As if by x.swap(y).

24.6.8 Class template stack [stack]

24.6.8.1 General [stack.general]

Any sequence container supporting operations back(), push_­back() and pop_­back() can be used to instantiate stack.
In particular, vector, list and deque can be used.

24.6.8.2 Definition [stack.defn]

namespace std { template<class T, class Container = deque<T>> class stack { public: using value_type = typename Container::value_type; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using size_type = typename Container::size_type; using container_type = Container; protected: Container c; public: stack() : stack(Container()) {} explicit stack(const Container&); explicit stack(Container&&); template<class InputIterator> stack(InputIterator first, InputIterator last); template<container-compatible-range<T> R> stack(from_range_t, R&& rg); template<class Alloc> explicit stack(const Alloc&); template<class Alloc> stack(const Container&, const Alloc&); template<class Alloc> stack(Container&&, const Alloc&); template<class Alloc> stack(const stack&, const Alloc&); template<class Alloc> stack(stack&&, const Alloc&); template<class InputIterator, class Alloc> stack(InputIterator first, InputIterator last, const Alloc&); template<container-compatible-range<T> R, class Alloc> stack(from_range_t, R&& rg, const Alloc&); [[nodiscard]] bool empty() const { return c.empty(); } size_type size() const { return c.size(); } reference top() { return c.back(); } const_reference top() const { return c.back(); } void push(const value_type& x) { c.push_back(x); } void push(value_type&& x) { c.push_back(std::move(x)); } template<container-compatible-range<T> R> void push_range(R&& rg); template<class... Args> decltype(auto) emplace(Args&&... args) { return c.emplace_back(std::forward<Args>(args)...); } void pop() { c.pop_back(); } void swap(stack& s) noexcept(is_nothrow_swappable_v<Container>) { using std::swap; swap(c, s.c); } }; template<class Container> stack(Container) -> stack<typename Container::value_type, Container>; template<class InputIterator> stack(InputIterator, InputIterator) -> stack<iter-value-type<InputIterator>>; template<ranges::input_­range R> stack(from_range_t, R&&) -> stack<ranges::range_value_t<R>>; template<class Container, class Allocator> stack(Container, Allocator) -> stack<typename Container::value_type, Container>; template<class InputIterator, class Allocator> stack(InputIterator, InputIterator, Allocator) -> stack<iter-value-type<InputIterator>, deque<iter-value-type<InputIterator>, Allocator>>; template<ranges::input_­range R, class Allocator> stack(from_range_t, R&&, Allocator) -> stack<ranges::range_value_t<R>, deque<ranges::range_value_t<R>, Allocator>>; template<class T, class Container, class Alloc> struct uses_allocator<stack<T, Container>, Alloc> : uses_allocator<Container, Alloc>::type { }; }

24.6.8.3 Constructors [stack.cons]

explicit stack(const Container& cont);
Effects: Initializes c with cont.
explicit stack(Container&& cont);
Effects: Initializes c with std​::​move(cont).
template<class InputIterator> stack(InputIterator first, InputIterator last);
Effects: Initializes c with first as the first argument and last as the second argument.
template<container-compatible-range<T> R> stack(from_range_t, R&& rg);
Effects: Initializes c with ranges​::​to<Container>(std​::​forward<R>(rg)).

24.6.8.4 Constructors with allocators [stack.cons.alloc]

If uses_­allocator_­v<container_­type, Alloc> is false the constructors in this subclause shall not participate in overload resolution.
template<class Alloc> explicit stack(const Alloc& a);
Effects: Initializes c with a.
template<class Alloc> stack(const container_type& cont, const Alloc& a);
Effects: Initializes c with cont as the first argument and a as the second argument.
template<class Alloc> stack(container_type&& cont, const Alloc& a);
Effects: Initializes c with std​::​move(cont) as the first argument and a as the second argument.
template<class Alloc> stack(const stack& s, const Alloc& a);
Effects: Initializes c with s.c as the first argument and a as the second argument.
template<class Alloc> stack(stack&& s, const Alloc& a);
Effects: Initializes c with std​::​move(s.c) as the first argument and a as the second argument.
template<class InputIterator, class Alloc> stack(InputIterator first, InputIterator last, const Alloc& alloc);
Effects: Initializes c with first as the first argument, last as the second argument, and alloc as the third argument.
template<container-compatible-range<T> R, class Alloc> stack(from_range_t, R&& rg, const Alloc& a);
Effects: Initializes c with ranges​::​to<Container>(std​::​forward<R>(rg), a).

24.6.8.5 Modifiers [stack.mod]

template<container-compatible-range<T> R> void push_range(R&& rg);
Effects: Equivalent to c.append_­range(std​::​forward<R>(rg)) if that is a valid expression, otherwise ranges​::​copy(rg, back_­inserter(c)).

24.6.8.6 Operators [stack.ops]

template<class T, class Container> bool operator==(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c == y.c.
template<class T, class Container> bool operator!=(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c != y.c.
template<class T, class Container> bool operator< (const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c < y.c.
template<class T, class Container> bool operator> (const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c > y.c.
template<class T, class Container> bool operator<=(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c <= y.c.
template<class T, class Container> bool operator>=(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c >= y.c.
template<class T, three_­way_­comparable Container> compare_three_way_result_t<Container> operator<=>(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c <=> y.c.

24.6.8.7 Specialized algorithms [stack.special]

template<class T, class Container> void swap(stack<T, Container>& x, stack<T, Container>& y) noexcept(noexcept(x.swap(y)));
Constraints: is_­swappable_­v<Container> is true.
Effects: As if by x.swap(y).

24.6.9 Class template flat_­map [flat.map]

24.6.9.1 Overview [flat.map.overview]

A flat_­map is a container adaptor that provides an associative container interface 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.
flat_­map supports iterators that meet the Cpp17InputIterator requirements and model the random_­access_­iterator concept ([iterator.concept.random.access]).
A flat_­map meets all of the requirements of a container ([container.reqmts]) and of a reversible container ([container.rev.reqmts]), plus the optional container requirements ([container.opt.reqmts]).
flat_­map meets the requirements of an associative container ([associative.reqmts]), except that:
  • it does not meet the requirements related to node handles ([container.node]),
  • it does not meet the requirements related to iterator invalidation, and
  • the time complexity of the operations that insert or erase a single element from the map is linear, including the ones that take an insertion position iterator.
[Note 1:
A flat_­map does not meet the additional requirements of an allocator-aware container ([container.alloc.reqmts]).
— end note]
A flat_­map also provides most operations described in [associative.reqmts] for unique keys.
This means that a flat_­map supports the a_­uniq operations in [associative.reqmts] but not the a_­eq operations.
For a flat_­map<Key, T> the key_­type is Key and the value_­type is pair<Key, T>.
Descriptions are provided here only for operations on flat_­map that are not described in one of those sets of requirements or for operations where there is additional semantic information.
A flat_­map maintains the following invariants:
  • it contains the same number of keys and values;
  • the keys are sorted with respect to the comparison object; and
  • the value at offset off within the value container is the value associated with the key at offset off within the key container.
If any member function in [flat.map.defn] exits via an exception the invariants are restored.
[Note 2:
This can result in the flat_­map being emptied.
— end note]
Any sequence container ([sequence.reqmts]) C supporting Cpp17RandomAccessIterator can be used to instantiate flat_­map, as long as invocations of member functions C​::​size and C​::​max_­size do not exit via an exception.
In particular, vector ([vector]) and deque ([deque]) can be used.
[Note 3:
vector<bool> is not a sequence container.
— end note]
The program is ill-formed if Key is not the same type as KeyContainer​::​value_­type or T is not the same type as MappedContainer​::​value_­type.
The effect of calling a constructor that takes both key_­container_­type and mapped_­container_­type arguments with containers of different sizes is undefined.
The effect of calling a constructor or member function that takes a sorted_­unique_­t argument with a container, containers, or range that is not sorted with respect to key_­comp(), or that contains equal elements, is undefined.

24.6.9.2 Definition [flat.map.defn]

namespace std { template<class Key, class T, class Compare = less<Key>, class KeyContainer = vector<Key>, class MappedContainer = vector<T>> class flat_map { public: // types using key_type = Key; using mapped_type = T; using value_type = pair<key_type, mapped_type>; using key_compare = Compare; using reference = pair<const key_type&, mapped_type&>; using const_reference = pair<const key_type&, const mapped_type&>; using size_type = size_t; using difference_type = ptrdiff_t; using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using key_container_type = KeyContainer; using mapped_container_type = MappedContainer; class value_compare { private: key_compare comp; // exposition only value_compare(key_compare c) : comp(c) { } // exposition only public: bool operator()(const_reference x, const_reference y) const { return comp(x.first, y.first); } }; struct containers { key_container_type keys; mapped_container_type values; }; // [flat.map.cons], construct/copy/destroy flat_map() : flat_map(key_compare()) { } flat_map(key_container_type key_cont, mapped_container_type mapped_cont); template<class Allocator> flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Allocator& a); flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont); template<class Allocator> flat_map(sorted_unique_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Allocator& a); explicit flat_map(const key_compare& comp) : c(), compare(comp) { } template<class Allocator> flat_map(const key_compare& comp, const Allocator& a); template<class Allocator> explicit flat_map(const Allocator& a); template<class InputIterator> flat_map(InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(), compare(comp) { insert(first, last); } template<class InputIterator, class Allocator> flat_map(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_map(InputIterator first, InputIterator last, const Allocator& a); template<container-compatible-range<value_type> R> flat_map(from_range_t fr, R&& rg) : flat_map(fr, std::forward<R>(rg), key_compare()) { } template<container-compatible-range<value_type> R, class Allocator> flat_map(from_range_t, R&& rg, const Allocator& a); template<container-compatible-range<value_type> R> flat_map(from_range_t, R&& rg, const key_compare& comp) : flat_map(comp) { insert_range(std::forward<R>(rg)); } template<container-compatible-range<value_type> R, class Allocator> flat_map(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); template<class InputIterator> flat_map(sorted_unique_t s, InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(), compare(comp) { insert(s, first, last); } template<class InputIterator, class Allocator> flat_map(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_map(sorted_unique_t, InputIterator first, InputIterator last, const Allocator& a); flat_map(initializer_list<value_type> il, const key_compare& comp = key_compare()) : flat_map(il.begin(), il.end(), comp) { } template<class Allocator> flat_map(initializer_list<value_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_map(initializer_list<value_type> il, const Allocator& a); flat_map(sorted_unique_t s, initializer_list<value_type> il, const key_compare& comp = key_compare()) : flat_map(s, il.begin(), il.end(), comp) { } template<class Allocator> flat_map(sorted_unique_t, initializer_list<value_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_map(sorted_unique_t, initializer_list<value_type> il, const Allocator& a); flat_map& operator=(initializer_list<value_type> il); // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // [flat.map.capacity], capacity [[nodiscard]] bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // [flat.map.access], element access mapped_type& operator[](const key_type& x); mapped_type& operator[](key_type&& x); template<class K> mapped_type& operator[](K&& x); mapped_type& at(const key_type& x); const mapped_type& at(const key_type& x) const; template<class K> mapped_type& at(const K& x); template<class K> const mapped_type& at(const K& x) const; // [flat.map.modifiers], modifiers template<class... Args> pair<iterator, bool> emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); pair<iterator, bool> insert(const value_type& x) { return emplace(x); } pair<iterator, bool> insert(value_type&& x) { return emplace(std::move(x)); } iterator insert(const_iterator position, const value_type& x) { return emplace_hint(position, x); } iterator insert(const_iterator position, value_type&& x) { return emplace_hint(position, std::move(x)); } template<class P> pair<iterator, bool> insert(P&& x); template<class P> iterator insert(const_iterator position, P&&); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<class InputIterator> void insert(sorted_unique_t, InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type> il) { insert(il.begin(), il.end()); } void insert(sorted_unique_t s, initializer_list<value_type> il) { insert(s, il.begin(), il.end()); } containers extract() &&; void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); template<class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template<class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template<class K, class... Args> pair<iterator, bool> try_emplace(K&& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); template<class K, class... Args> iterator try_emplace(const_iterator hint, K&& k, Args&&... args); template<class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); template<class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template<class K, class M> pair<iterator, bool> insert_or_assign(K&& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); template<class K, class M> iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(flat_map& y) noexcept; void clear() noexcept; // observers key_compare key_comp() const; value_compare value_comp() const; const key_container_type& keys() const noexcept { return c.keys; } const mapped_container_type& values() const noexcept { return c.values; } // map operations iterator find(const key_type& x); const_iterator find(const key_type& x) const; template<class K> iterator find(const K& x); template<class K> const_iterator find(const K& x) const; size_type count(const key_type& x) const; template<class K> size_type count(const K& x) const; bool contains(const key_type& x) const; template<class K> bool contains(const K& x) const; iterator lower_bound(const key_type& x); const_iterator lower_bound(const key_type& x) const; template<class K> iterator lower_bound(const K& x); template<class K> const_iterator lower_bound(const K& x) const; iterator upper_bound(const key_type& x); const_iterator upper_bound(const key_type& x) const; template<class K> iterator upper_bound(const K& x); template<class K> const_iterator upper_bound(const K& x) const; pair<iterator, iterator> equal_range(const key_type& x); pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K> pair<iterator, iterator> equal_range(const K& x); template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const; friend bool operator==(const flat_map& x, const flat_map& y); friend synth-three-way-result<value_type> operator<=>(const flat_map& x, const flat_map& y); friend void swap(flat_map& x, flat_map& y) noexcept { x.swap(y); } private: containers c; // exposition only key_compare compare; // exposition only struct key_equiv { // exposition only key_equiv(key_compare c) : comp(c) { } bool operator()(const_reference x, const_reference y) const { return !comp(x.first, y.first) && !comp(y.first, x.first); } key_compare comp; }; }; template<class KeyContainer, class MappedContainer> flat_map(KeyContainer, MappedContainer) -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Allocator> flat_map(KeyContainer, MappedContainer, Allocator) -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer> flat_map(sorted_unique_t, KeyContainer, MappedContainer) -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Allocator> flat_map(sorted_unique_t, KeyContainer, MappedContainer, Allocator) -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer, MappedContainer>; template<class InputIterator, class Compare = less<iter-key-type<InputIterator>>> flat_map(InputIterator, InputIterator, Compare = Compare()) -> flat_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Compare>; template<class InputIterator, class Compare = less<iter-key-type<InputIterator>>> flat_map(sorted_unique_t, InputIterator, InputIterator, Compare = Compare()) -> flat_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Compare>; template<ranges::input_­range R, class Compare = less<range-key-type<R>>, class Allocator> flat_map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) -> flat_map<range-key-type<R>, range-mapped-type<R>, Compare>; template<ranges::input_­range R, class Allocator> flat_map(from_range_t, R&&, Allocator) -> flat_map<range-key-type<R>, range-mapped-type<R>>; template<class Key, class T, class Compare = less<Key>> flat_map(initializer_list<pair<Key, T>>, Compare = Compare()) -> flat_map<Key, T, Compare>; template<class Key, class T, class Compare = less<Key>> flat_map(sorted_unique_t, initializer_list<pair<Key, T>>, Compare = Compare()) -> flat_map<Key, T, Compare>; template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Allocator> struct uses_allocator<flat_map<Key, T, Compare, KeyContainer, MappedContainer>, Allocator> : bool_constant<uses_allocator_v<KeyContainer, Allocator> && uses_allocator_v<MappedContainer, Allocator>> { }; }
The member type containers has the data members and special members specified above.
It has no base classes or members other than those specified.

24.6.9.3 Constructors [flat.map.cons]

flat_map(key_container_type key_cont, mapped_container_type mapped_cont);
Effects: Initializes c.keys with std​::​move(key_­cont) and c.values with std​::​move(mapped_­cont); value-initializes compare; sorts the range [begin(), end()) with respect to value_­comp(); and finally erases the duplicate elements as if by: auto zv = ranges::zip_view(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());
Complexity: Linear in N if the container arguments are already sorted with respect to value_­comp() and otherwise , where N is the value of key_­cont.size() before this call.
template<class Allocator> flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Allocator& a);
Constraints: uses_­allocator_­v<key_­container_­type, Allocator> is true and uses_­allocator_­v<mapped_­container_­type, Allocator> is true.
Effects: Equivalent to flat_­map(key_­cont, mapped_­cont), except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Same as flat_­map(key_­cont, mapped_­cont).
flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont);
Effects: Initializes c.keys with std​::​move(key_­cont) and c.values with std​::​move(mapped_­cont); value-initializes compare.
Complexity: Constant.
template<class Allocator> flat_map(sorted_unique_t s, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Allocator& a);
Constraints: uses_­allocator_­v<key_­container_­type, Allocator> is true and uses_­allocator_­v<mapped_­container_­type, Allocator> is true.
Effects: Equivalent to flat_­map(s, key_­cont, mapped_­cont), except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Linear.
template<class Allocator> flat_map(const key_compare& comp, const Allocator& a); template<class Allocator> explicit flat_map(const Allocator& a); template<class InputIterator, class Allocator> flat_map(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_map(InputIterator first, InputIterator last, const Allocator& a); template<container-compatible-range<value_type> R, class Allocator> flat_map(from_range_t, R&& rg, const Allocator& a); template<container-compatible-range<value_type> R, class Allocator> flat_map(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_map(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_map(sorted_unique_t, InputIterator first, InputIterator last, const Allocator& a); template<class Allocator> flat_map(initializer_list<value_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_map(initializer_list<value_type> il, const Allocator& a); template<class Allocator> flat_map(sorted_unique_t, initializer_list<value_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_map(sorted_unique_t, initializer_list<value_type> il, const Allocator& a);
Constraints: uses_­allocator_­v<key_­container_­type, Allocator is true and uses_­allocator_­v<mapped_­container_­type, Allocator> is true.
Effects: Equivalent to the corresponding non-allocator constructors except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).

24.6.9.4 Capacity [flat.map.capacity]

size_type size() const noexcept;
Returns: c.keys.size().
size_type max_size() const noexcept;
Returns: min<size_­type>(c.keys.max_­size(), c.values.max_­size()).

24.6.9.5 Access [flat.map.access]

mapped_type& operator[](const key_type& x);
Effects: Equivalent to: return try_­emplace(x).first->second;
mapped_type& operator[](key_type&& x);
Effects: Equivalent to: return try_­emplace(std​::​move(x)).first->second;
template<class K> mapped_type& operator[](K&& x);
Constraints: The qualified-id Compare​::​is_­transparent is valid and denotes a type.
Effects: Equivalent to: return try_­emplace(std​::​forward<K>(x)).first->second;
mapped_type& at(const key_type& x); const mapped_type& at(const key_type& x) const;
Returns: A reference to the mapped_­type corresponding to x in *this.
Throws: An exception object of type out_­of_­range if no such element is present.
Complexity: Logarithmic.
template<class K> mapped_type& at(const K& x); template<class K> const mapped_type& at(const K& x) const;
Constraints: The qualified-id Compare​::​is_­transparent is valid and denotes a type.
Preconditions: The expression find(x) is well-formed and has well-defined behavior.
Returns: A reference to the mapped_­type corresponding to x in *this.
Throws: An exception object of type out_­of_­range if no such element is present.
Complexity: Logarithmic.

24.6.9.6 Modifiers [flat.map.modifiers]

template<class... Args> pair<iterator, bool> emplace(Args&&... args);
Constraints: is_­constructible_­v<pair<key_­type, mapped_­type>, Arg...> is true.
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.
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));
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.
template<class P> pair<iterator, bool> insert(P&& x); template<class P> iterator insert(const_iterator position, P&& x);
Constraints: is_­constructible_­v<pair<key_­type, mapped_­type>, P> is true.
Effects: The first form is equivalent to return emplace(std​::​forward<P>(x));.
The second form is equivalent to return emplace_­hint(position, std​::​forward<P>(x));.
template<class InputIterator> void insert(InputIterator first, InputIterator last);
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 = ranges::zip_view(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());
Complexity: N + , where N is size() before the operation and M is distance(first, last).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<class InputIterator> void insert(sorted_unique_t, InputIterator first, InputIterator last);
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 = ranges::zip_view(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());
Complexity: Linear in N, where N is size() after the operation.
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<container-compatible-range<value_type> R> void insert_range(R&& rg);
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 = ranges::zip_view(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());
Complexity: N + , where N is size() before the operation and M is ranges​::​distance(rg).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template<class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
Constraints: is_­constructible_­v<mapped_­type, Args...> is true.
Effects: If the map already contains an element whose key is equivalent to k, *this and args... are unchanged.
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)...);
Returns: In the first two overloads, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace for the first two overloads, and the same as emplace_­hint for the last two overloads.
template<class K, class... Args> pair<iterator, bool> try_emplace(K&& k, Args&&... args); template<class K, class... Args> iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
Constraints:
  • The qualified-id Compare​::​is_­transparent is valid and denotes a type.
  • is_­constructible_­v<key_­type, K> is true.
  • is_­constructible_­v<mapped_­type, Args...> is true.
  • For the first overload, is_­convertible_­v<K&&, const_­iterator> and is_­convertible_­v<K&&, iterator> are both false.
Preconditions: The conversion from k into key_­type constructs an object u, for which find(k) == find(u) is true.
Effects: If the map already contains an element whose key is equivalent to k, *this and args... are unchanged.
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.emplace(key_it, std::forward<K>(k)); c.values.emplace(value_it, std::forward<Args>(args)...);
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_­hint, respectively.
template<class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); template<class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
Constraints: is_­assignable_­v<mapped_­type&, M> is true and is_­constructible_­v<mapped_­type, M> is true.
Effects: If the map already contains an element e whose key is equivalent to k, assigns std​::​forward<
M>(obj)
to e.second.
Otherwise, equivalent to try_emplace(std::forward<decltype(k)>(k), std::forward<M>(obj)) for the first two overloads or try_emplace_hint(hint, std::forward<decltype(k)>(k), std::forward<M>(obj)) for the last two overloads.
Returns: In the first two overloads, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace for the first two overloads and the same as emplace_­hint for the last two overloads.
template<class K, class M> pair<iterator, bool> insert_or_assign(K&& k, M&& obj); template<class K, class M> iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);
Constraints:
  • The qualified-id Compare​::​is_­transparent is valid and denotes a type.
  • is_­constructible_­v<key_­type, K> is true.
  • is_­assignable_­v<mapped_­type&, M> is true.
  • is_­constructible_­v<mapped_­type, M> is true.
Preconditions: The conversion from k into key_­type constructs an object u, for which find(k) == find(u) is true.
Effects: If the map already contains an element e whose key is equivalent to k, assigns std​::​forward<
M>(obj)
to e.second.
Otherwise, equivalent to try_emplace(std::forward<decltype(k)>(k), std::forward<M>(obj)) for the first overload or try_emplace_hint(hint, std::forward<decltype(k)>(k), std::forward<M>(obj)) for the second overload.
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_­hint, respectively.
void swap(flat_map& y) noexcept;
Effects: Equivalent to: ranges::swap(compare, y.compare); ranges::swap(c.keys, y.c.keys); ranges::swap(c.values, y.c.values);
containers extract() &&;
Postconditions: *this is emptied, even if the function exits via an exception.
Returns: std​::​move(c).
void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont);
Preconditions: key_­cont.size() == mapped_­cont.size() is true, the elements of key_­cont are sorted with respect to compare, and key_­cont contains no equal elements.
Effects: Equivalent to: c.keys = std::move(key_cont); c.values = std::move(mapped_cont);

24.6.9.7 Erasure [flat.map.erasure]

template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Predicate> typename flat_map<Key, T, Compare, KeyContainer, MappedContainer>::size_type erase_if(flat_map<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred);
Preconditions: Key and T meet the Cpp17MoveAssignable requirements.
Effects: Let E be bool(pred(pair<const Key&, const T&>(e))).
Erases all elements e in c for which E holds.
Returns: The number of elements erased.
Complexity: Exactly c.size() applications of the predicate.
Remarks: Stable ([algorithm.stable]).
If an invocation of erase_­if exits via an exception, c is in a valid but unspecified state ([defns.valid]).
[Note 1:
c still meets its invariants, but can be empty.
— end note]

24.6.10 Class template flat_­multimap [flat.multimap]

24.6.10.1 Overview [flat.multimap.overview]

A flat_­multimap is a container adaptor that provides an associative container interface that supports equivalent keys (i.e., possibly containing multiple copies of the same key value) and provides for fast retrieval of values of another type T based on the keys.
flat_­multimap supports iterators that meet the Cpp17InputIterator requirements and model the random_­access_­iterator concept ([iterator.concept.random.access]).
A flat_­multimap meets all of the requirements for a container ([container.reqmts]) and for a reversible container ([container.rev.reqmts]), plus the optional container requirements ([container.opt.reqmts]).
flat_­multimap meets the requirements of an associative container ([associative.reqmts]), except that:
  • it does not meet the requirements related to node handles ([container.node]),
  • it does not meet the requirements related to iterator invalidation, and
  • the time complexity of the operations that insert or erase a single element from the map is linear, including the ones that take an insertion position iterator.
[Note 1:
A flat_­multimap does not meet the additional requirements of an allocator-aware container ([container.alloc.reqmts]).
— end note]
A flat_­multimap also provides most operations described in [associative.reqmts] for equal keys.
This means that a flat_­multimap supports the a_­eq operations in [associative.reqmts] but not the a_­uniq operations.
For a flat_­multimap<Key, T> the key_­type is Key and the value_­type is pair<Key, T>.
Except as otherwise noted, operations on flat_­multimap are equivalent to those of flat_­map, except that flat_­multimap operations do not remove or replace elements with equal keys.
[Example 1:
flat_­multimap constructors and emplace do not erase non-unique elements after sorting them.
— end example]
A flat_­multimap maintains the following invariants:
  • it contains the same number of keys and values;
  • the keys are sorted with respect to the comparison object; and
  • the value at offset off within the value container is the value associated with the key at offset off within the key container.
If any member function in [flat.multimap.defn] exits via an exception, the invariants are restored.
[Note 2:
This can result in the flat_­multimap being emptied.
— end note]
Any sequence container ([sequence.reqmts]) C supporting Cpp17RandomAccessIterator can be used to instantiate flat_­multimap, as long as invocations of member functions C​::​size and C​::​max_­size do not exit via an exception.
In particular, vector ([vector]) and deque ([deque]) can be used.
[Note 3:
vector<bool> is not a sequence container.
— end note]
The program is ill-formed if Key is not the same type as KeyContainer​::​value_­type or T is not the same type as MappedContainer​::​value_­type.
The effect of calling a constructor that takes both key_­container_­type and mapped_­container_­type arguments with containers of different sizes is undefined.
The effect of calling a constructor or member function that takes a sorted_­equivalent_­t argument with a container, containers, or range that are not sorted with respect to key_­comp() is undefined.

24.6.10.2 Definition [flat.multimap.defn]

namespace std { template<class Key, class T, class Compare = less<Key>, class KeyContainer = vector<Key>, class MappedContainer = vector<T>> class flat_multimap { public: // types using key_type = Key; using mapped_type = T; using value_type = pair<key_type, mapped_type>; using key_compare = Compare; using reference = pair<const key_type&, mapped_type&>; using const_reference = pair<const key_type&, const mapped_type&>; using size_type = size_t; using difference_type = ptrdiff_t; using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using key_container_type = KeyContainer; using mapped_container_type = MappedContainer; class value_compare { private: key_compare comp; // exposition only value_compare(key_compare c) : comp(c) { } // exposition only public: bool operator()(const_reference x, const_reference y) const { return comp(x.first, y.first); } }; struct containers { key_container_type keys; mapped_container_type values; }; // [flat.multimap.cons], construct/copy/destroy flat_multimap() : flat_multimap(key_compare()) { } flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont); template<class Allocator> flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Allocator& a); flat_multimap(sorted_equivalent_t, key_container_type key_cont, mapped_container_type mapped_cont); template<class Allocator> flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Allocator& a); explicit flat_multimap(const key_compare& comp) : c(), compare(comp) { } template<class Allocator> flat_multimap(const key_compare& comp, const Allocator& a); template<class Allocator> explicit flat_multimap(const Allocator& a); template<class InputIterator> flat_multimap(InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(), compare(comp) { insert(first, last); } template<class InputIterator, class Allocator> flat_multimap(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_multimap(InputIterator first, InputIterator last, const Allocator& a); template<container-compatible-range<value_type> R> flat_multimap(from_range_t fr, R&& rg) : flat_multimap(fr, std::forward<R>(rg), key_compare()) { } template<container-compatible-range<value_type> R, class Allocator> flat_multimap(from_range_t, R&& rg, const Allocator& a); template<container-compatible-range<value_type> R> flat_multimap(from_range_t, R&& rg, const key_compare& comp) : flat_multimap(comp) { insert_range(std::forward<R>(rg)); } template<container-compatible-range<value_type> R, class Allocator> flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); template<class InputIterator> flat_multimap(sorted_equivalent_t s, InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(), compare(comp) { insert(s, first, last); } template<class InputIterator, class Allocator> flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, const Allocator& a); flat_multimap(initializer_list<value_type> il, const key_compare& comp = key_compare()) : flat_multimap(il.begin(), il.end(), comp) { } template<class Allocator> flat_multimap(initializer_list<value_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_multimap(initializer_list<value_type> il, const Allocator& a); flat_multimap(sorted_equivalent_t s, initializer_list<value_type> il, const key_compare& comp = key_compare()) : flat_multimap(s, il.begin(), il.end(), comp) { } template<class Allocator> flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const Allocator& a); flat_multimap& operator=(initializer_list<value_type> il); // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity [[nodiscard]] bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // modifiers template<class... Args> iterator emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); iterator insert(const value_type& x) { return emplace(x); } iterator insert(value_type&& x) { return emplace(std::move(x)); } iterator insert(const_iterator position, const value_type& x) { return emplace_hint(position, x); } iterator insert(const_iterator position, value_type&& x) { return emplace_hint(position, std::move(x)); } template<class P> iterator insert(P&& x); template<class P> iterator insert(const_iterator position, P&&); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<class InputIterator> void insert(sorted_equivalent_t, InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type> il) { insert(il.begin(), il.end()); } void insert(sorted_equivalent_t s, initializer_list<value_type> il) { insert(s, il.begin(), il.end()); } containers extract() &&; void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(flat_multimap&) noexcept; void clear() noexcept; // observers key_compare key_comp() const; value_compare value_comp() const; const key_container_type& keys() const noexcept { return c.keys; } const mapped_container_type& values() const noexcept { return c.values; } // map operations iterator find(const key_type& x); const_iterator find(const key_type& x) const; template<class K> iterator find(const K& x); template<class K> const_iterator find(const K& x) const; size_type count(const key_type& x) const; template<class K> size_type count(const K& x) const; bool contains(const key_type& x) const; template<class K> bool contains(const K& x) const; iterator lower_bound(const key_type& x); const_iterator lower_bound(const key_type& x) const; template<class K> iterator lower_bound(const K& x); template<class K> const_iterator lower_bound(const K& x) const; iterator upper_bound(const key_type& x); const_iterator upper_bound(const key_type& x) const; template<class K> iterator upper_bound(const K& x); template<class K> const_iterator upper_bound(const K& x) const; pair<iterator, iterator> equal_range(const key_type& x); pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K> pair<iterator, iterator> equal_range(const K& x); template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const; friend bool operator==(const flat_multimap& x, const flat_multimap& y); friend synth-three-way-result<value_type> operator<=>(const flat_multimap& x, const flat_multimap& y); friend void swap(flat_multimap& x, flat_multimap& y) noexcept { x.swap(y); } private: containers c; // exposition only key_compare compare; // exposition only }; template<class KeyContainer, class MappedContainer> flat_multimap(KeyContainer, MappedContainer) -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Allocator> flat_multimap(KeyContainer, MappedContainer, Allocator) -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer> flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer) -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Allocator> flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Allocator) -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer, MappedContainer>; template<class InputIterator, class Compare = less<iter-key-type<InputIterator>>> flat_multimap(InputIterator, InputIterator, Compare = Compare()) -> flat_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Compare>; template<class InputIterator, class Compare = less<iter-key-type<InputIterator>>> flat_multimap(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare()) -> flat_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Compare>; template<ranges::input_­range R, class Compare = less<range-key-type<R>>, class Allocator> flat_multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) -> flat_multimap<range-key-type<R>, range-mapped-type<R>, Compare>; template<ranges::input_­range R, class Allocator> flat_multimap(from_range_t, R&&, Allocator) -> flat_multimap<range-key-type<R>, range-mapped-type<R>>; template<class Key, class T, class Compare = less<Key>> flat_multimap(initializer_list<pair<Key, T>>, Compare = Compare()) -> flat_multimap<Key, T, Compare>; template<class Key, class T, class Compare = less<Key>> flat_multimap(sorted_equivalent_t, initializer_list<pair<Key, T>>, Compare = Compare()) -> flat_multimap<Key, T, Compare>; template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Allocator> struct uses_allocator<flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>, Allocator> : bool_constant<uses_allocator_v<KeyContainer, Allocator> && uses_allocator_v<MappedContainer, Allocator>> { }; }
The member type containers has the data members and special members specified above.
It has no base classes or members other than those specified.

24.6.10.3 Constructors [flat.multimap.cons]

flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont);
Effects: Initializes c.keys with std​::​move(key_­cont) and c.values with std​::​move(mapped_­cont); value-initializes compare; and sorts the range [begin(), end()) with respect to value_­comp().
Complexity: Linear in N if the container arguments are already sorted with respect to value_­comp() and otherwise , where N is the value of key_­cont.size() before this call.
template<class Allocator> flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Allocator& a);
Constraints: uses_­allocator_­v<key_­container_­type, Allocator> is true and uses_­allocator_­v<mapped_­container_­type, Allocator> is true.
Effects: Equivalent to flat_­multimap(key_­cont, mapped_­cont), except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Same as flat_­multimap(key_­cont, mapped_­cont).
flat_multimap(sorted_equivalent_t, key_container_type key_cont, mapped_container_type mapped_cont);
Effects: Initializes c.keys with std​::​move(key_­cont) and c.values with std​::​move(mapped_­cont); value-initializes compare.
Complexity: Constant.
template<class Allocator> flat_multimap(sorted_equivalent_t s, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Allocator& a);
Constraints: uses_­allocator_­v<key_­container_­type, Allocator> is true and uses_­allocator_­v<mapped_­container_­type, Allocator> is true.
Effects: Equivalent to flat_­multimap(s, key_­cont, mapped_­cont), except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Linear.
template<class Allocator> flat_multimap(const key_compare& comp, const Allocator& a); template<class Allocator> explicit flat_multimap(const Allocator& a); template<class InputIterator, class Allocator> flat_multimap(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_multimap(InputIterator first, InputIterator last, const Allocator& a); template<container-compatible-range<value_type> R, class Allocator> flat_multimap(from_range_t, R&& rg, const Allocator& a); template<container-compatible-range<value_type> R, class Allocator> flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, const Allocator& a); template<class Allocator> flat_multimap(initializer_list<value_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_multimap(initializer_list<value_type> il, const Allocator& a); template<class Allocator> flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const Allocator& a);
Constraints: uses_­allocator_­v<key_­container_­type, Allocator> is true and uses_­allocator_­v<mapped_­container_­type, Allocator> is true.
Effects: Equivalent to the corresponding non-allocator constructors except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).

24.6.10.4 Erasure [flat.multimap.erasure]

template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Predicate> typename flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>::size_type erase_if(flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred);
Preconditions: Key and T meet the Cpp17MoveAssignable requirements.
Effects: Let E be bool(pred(pair<const Key&, const T&>(e))).
Erases all elements e in c for which E holds.
Returns: The number of elements erased.
Complexity: Exactly c.size() applications of the predicate.
Remarks: Stable ([algorithm.stable]).
If an invocation of erase_­if exits via an exception, c is in a valid but unspecified state ([defns.valid]).
[Note 1:
c still meets its invariants, but can be empty.
— end note]

24.6.11 Class template flat_­set [flat.set]

24.6.11.1 Overview [flat.set.overview]

A flat_­set is a container adaptor that provides an associative container interface that supports unique keys (i.e., contains at most one of each key value) and provides for fast retrieval of the keys themselves.
flat_­set supports iterators that model the random_­access_­iterator concept ([iterator.concept.random.access]).
A flat_­set meets all of the requirements for a container ([container.reqmts]) and for a reversible container ([container.rev.reqmts]), plus the optional container requirements ([container.opt.reqmts]).
flat_­set meets the requirements of an associative container ([associative.reqmts]), except that:
  • it does not meet the requirements related to node handles ([container.node.overview]),
  • it does not meet the requirements related to iterator invalidation, and
  • the time complexity of the operations that insert or erase a single element from the set is linear, including the ones that take an insertion position iterator.
[Note 1:
A flat_­set does not meet the additional requirements of an allocator-aware container, as described in [container.alloc.reqmts].
— end note]
A flat_­set also provides most operations described in [associative.reqmts] for unique keys.
This means that a flat_­set supports the a_­uniq operations in [associative.reqmts] but not the a_­eq operations.
For a flat_­set<Key>, both the key_­type and value_­type are Key.
Descriptions are provided here only for operations on flat_­set that are not described in one of those sets of requirements or for operations where there is additional semantic information.
A flat_­set maintains the invariant that the keys are sorted with respect to the comparison object.
If any member function in [flat.set.defn] exits via an exception, the invariant is restored.
[Note 2:
This can result in the flat_­set's being emptied.
— end note]
Any sequence container ([sequence.reqmts]) supporting Cpp17RandomAccessIterator can be used to instantiate flat_­set.
In particular, vector ([vector]) and deque ([deque]) can be used.
[Note 3:
vector<bool> is not a sequence container.
— end note]
The program is ill-formed if Key is not the same type as KeyContainer​::​value_­type.
The effect of calling a constructor or member function that takes a sorted_­unique_­t argument with a range that is not sorted with respect to key_­comp(), or that contains equal elements, is undefined.

24.6.11.2 Definition [flat.set.defn]

namespace std { template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>> class flat_set { public: // types using key_type = Key; using value_type = Key; using key_compare = Compare; using value_compare = Compare; using reference = value_type&; using const_reference = const value_type&; using size_type = typename KeyContainer::size_type; using difference_type = typename KeyContainer::difference_type; using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using container_type = KeyContainer; // [flat.set.cons], constructors flat_set() : flat_set(key_compare()) { } explicit flat_set(container_type cont); template<class Allocator> flat_set(const container_type& cont, const Allocator& a); flat_set(sorted_unique_t, container_type cont) : c(std::move(cont)), compare(key_compare()) { } template<class Allocator> flat_set(sorted_unique_t, const container_type& cont, const Allocator& a); explicit flat_set(const key_compare& comp) : c(), compare(comp) { } template<class Allocator> flat_set(const key_compare& comp, const Allocator& a); template<class Allocator> explicit flat_set(const Allocator& a); template<class InputIterator> flat_set(InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(), compare(comp) { insert(first, last); } template<class InputIterator, class Allocator> flat_set(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_set(InputIterator first, InputIterator last, const Allocator& a); template<container-compatible-range<value_type> R> flat_set(from_range_t fr, R&& rg) : flat_set(fr, std::forward<R>(rg), key_compare()) { } template<container-compatible-range<value_type> R, class Allocator> flat_set(from_range_t, R&& rg, const Allocator& a); template<container-compatible-range<value_type> R> flat_set(from_range_t, R&& rg, const key_compare& comp) : flat_set(comp) { insert_range(std::forward<R>(rg)); } template<container-compatible-range<value_type> R, class Allocator> flat_set(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); template<class InputIterator> flat_set(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(first, last), compare(comp) { } template<class InputIterator, class Allocator> flat_set(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_set(sorted_unique_t, InputIterator first, InputIterator last, const Allocator& a); flat_set(initializer_list<key_type> il, const key_compare& comp = key_compare()) : flat_set(il.begin(), il.end(), comp) { } template<class Allocator> flat_set(initializer_list<key_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_set(initializer_list<key_type> il, const Allocator& a); flat_set(sorted_unique_t s, initializer_list<key_type> il, const key_compare& comp = key_compare()) : flat_set(s, il.begin(), il.end(), comp) { } template<class Allocator> flat_set(sorted_unique_t, initializer_list<key_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_set(sorted_unique_t, initializer_list<key_type> il, const Allocator& a); flat_set& operator=(initializer_list<key_type>); // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity [[nodiscard]] bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // [flat.set.modifiers], modifiers template<class... Args> pair<iterator, bool> emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); pair<iterator, bool> insert(const value_type& x) { return emplace(x); } pair<iterator, bool> insert(value_type&& x) { return emplace(std::move(x)); } template<class K> pair<iterator, bool> insert(K&& x); iterator insert(const_iterator position, const value_type& x) { return emplace_hint(position, x); } iterator insert(const_iterator position, value_type&& x) { return emplace_hint(position, std::move(x)); } template<class K> iterator insert(const_iterator hint, K&& x); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<class InputIterator> void insert(sorted_unique_t, InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<key_type> il) { insert(il.begin(), il.end()); } void insert(sorted_unique_t s, initializer_list<key_type> il) { insert(s, il.begin(), il.end()); } container_type extract() &&; void replace(container_type&&); iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(flat_set& y) noexcept; void clear() noexcept; // observers key_compare key_comp() const; value_compare value_comp() const; // set operations iterator find(const key_type& x); const_iterator find(const key_type& x) const; template<class K> iterator find(const K& x); template<class K> const_iterator find(const K& x) const; size_type count(const key_type& x) const; template<class K> size_type count(const K& x) const; bool contains(const key_type& x) const; template<class K> bool contains(const K& x) const; iterator lower_bound(const key_type& x); const_iterator lower_bound(const key_type& x) const; template<class K> iterator lower_bound(const K& x); template<class K> const_iterator lower_bound(const K& x) const; iterator upper_bound(const key_type& x); const_iterator upper_bound(const key_type& x) const; template<class K> iterator upper_bound(const K& x); template<class K> const_iterator upper_bound(const K& x) const; pair<iterator, iterator> equal_range(const key_type& x); pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K> pair<iterator, iterator> equal_range(const K& x); template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const; friend bool operator==(const flat_set& x, const flat_set& y); friend synth-three-way-result<value_type> operator<=>(const flat_set& x, const flat_set& y); friend void swap(flat_set& x, flat_set& y) noexcept { x.swap(y); } private: container_type c; // exposition only key_compare compare; // exposition only }; template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>> flat_set(InputIterator, InputIterator, Compare = Compare()) -> flat_set<iter-value-type<InputIterator>, Compare>; template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>> flat_set(sorted_unique_t, InputIterator, InputIterator, Compare = Compare()) -> flat_set<iter-value-type<InputIterator>, Compare>; template<ranges::input_­range R, class Compare = less<ranges::range_value_t<R>>, class Allocator = allocator<ranges::range_value_t<R>>> flat_set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) -> flat_set<ranges::range_value_t<R>, Compare>; template<ranges::input_­range R, class Allocator> flat_set(from_range_t, R&&, Allocator) -> flat_set<ranges::range_value_t<R>, less<ranges::range_value_t<R>>>; template<class Key, class Compare = less<Key>> flat_set(initializer_list<Key>, Compare = Compare()) -> flat_set<Key, Compare>; template<class Key, class Compare = less<Key>> flat_set(sorted_unique_t, initializer_list<Key>, Compare = Compare()) -> flat_set<Key, Compare>; template<class Key, class Compare, class KeyContainer, class Allocator> struct uses_allocator<flat_set<Key, Compare, KeyContainer>, Allocator> : bool_constant<uses_allocator_v<KeyContainer, Allocator>> { }; }

24.6.11.3 Constructors [flat.set.cons]

explicit flat_set(container_type cont);
Effects: Initializes c with std​::​move(cont), value-initializes compare, sorts the range [begin(), end()) with respect to compare, and finally erases all but the first element from each group of consecutive equivalent elements.
Complexity: Linear in N if cont is sorted with respect to compare and otherwise , where N is the value of cont.size() before this call.
template<class Allocator> flat_set(const container_type& cont, const Allocator& a);
Constraints: uses_­allocator_­v<container_­type, Allocator> is true.
Effects: Equivalent to flat_­set(cont), except that c is constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Same as flat_­set(cont).
template<class Allocator> flat_set(sorted_unique_t s, const container_type& cont, const Allocator& a);
Constraints: uses_­allocator_­v<container_­type, Allocator> is true.
Effects: Equivalent to flat_­set(s, cont), except that c is constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Linear.
template<class Allocator> flat_set(const key_compare& comp, const Allocator& a); template<class Allocator> explicit flat_set(const Allocator& a); template<class InputIterator, class Allocator> flat_set(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_set(InputIterator first, InputIterator last, const Allocator& a); template<container-compatible-range<value_type> R, class Allocator> flat_set(from_range_t, R&& rg, const Allocator& a); template<container-compatible-range<value_type> R, class Allocator> flat_set(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_set(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_set(sorted_unique_t, InputIterator first, InputIterator last, const Allocator& a); template<class Allocator> flat_set(initializer_list<key_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_set(initializer_list<key_type> il, const Allocator& a); template<class Allocator> flat_set(sorted_unique_t, initializer_list<key_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_set(sorted_unique_t, initializer_list<key_type> il, const Allocator& a);
Constraints: uses_­allocator_­v<container_­type, Allocator> is true.
Effects: Equivalent to the corresponding non-allocator constructors except that c is constructed with uses-allocator construction ([allocator.uses.construction]).

24.6.11.4 Modifiers [flat.set.modifiers]

template<class K> pair<iterator, bool> insert(K&& x); template<class K> iterator insert(const_iterator hint, K&& x);
Constraints: The qualified-id Compare​::​is_­transparent is valid and denotes a type.
is_­constructible_­v<value_­type, K> is true.
Preconditions: The conversion from x into value_­type constructs an object u, for which find(x) == find(u) is true.
Effects: If the set already contains an element equivalent to x, *this and x are unchanged.
Otherwise, inserts a new element as if by emplace(std​::​forward<K>(x)).
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the element whose key is equivalent to x.
template<class InputIterator> void insert(InputIterator first, InputIterator last);
Effects: Adds elements to c as if by: c.insert(c.end(), first, last);
Then, sorts the range of newly inserted elements with respect to compare; merges the resulting sorted range and the sorted range of pre-existing elements into a single sorted range; and finally erases all but the first element from each group of consecutive equivalent elements.
Complexity: N + , where N is size() before the operation and M is distance(first, last).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<class InputIterator> void insert(sorted_unique_t, InputIterator first, InputIterator last);
Effects: Equivalent to insert(first, last).
Complexity: Linear.
template<container-compatible-range<value_type> R> void insert_range(R&& rg);
Effects: Adds elements to c as if by: for (const auto& e : rg) { c.insert(c.end(), e); }
Then, sorts the range of newly inserted elements with respect to compare; merges the resulting sorted range and the sorted range of pre-existing elements into a single sorted range; and finally erases all but the first element from each group of consecutive equivalent elements.
Complexity: N + , where N is size() before the operation and M is distance(first, last).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
void swap(flat_set& y) noexcept;
Effects: Equivalent to: ranges::swap(compare, y.compare); ranges::swap(c, y.c);
container_type extract() &&;
Postconditions: *this is emptied, even if the function exits via an exception.
Returns: std​::​move(c).
void replace(container_type&& cont);
Preconditions: The elements of cont are sorted with respect to compare, and cont contains no equal elements.
Effects: Equivalent to: c = std​::​move(cont);

24.6.11.5 Erasure [flat.set.erasure]

template<class Key, class Compare, class KeyContainer, class Predicate> typename flat_set<Key, Compare, KeyContainer>::size_type erase_if(flat_set<Key, Compare, KeyContainer>& c, Predicate pred);
Effects: Equivalent to: auto [erase_first, erase_last] = ranges::remove_if(c, pred); auto n = erase_last - erase_first; c.erase(erase_first, erase_last); return n;

24.6.12 Class template flat_­multiset [flat.multiset]

24.6.12.1 Overview [flat.multiset.overview]

A flat_­multiset is a container adaptor that provides an associative container interface that supports equivalent keys (i.e., possibly containing multiple copies of the same key value) and provides for fast retrieval of the keys themselves.
flat_­multiset supports iterators that model the random_­access_­iterator concept ([iterator.concept.random.access]).
A flat_­multiset meets all of the requirements for a container ([container.reqmts]) and for a reversible container ([container.rev.reqmts]), plus the optional container requirements ([container.opt.reqmts]).
flat_­multiset meets the requirements of an associative container ([associative.reqmts]), except that:
  • it does not meet the requirements related to node handles ([container.node.overview]),
  • it does not meet the requirements related to iterator invalidation, and
  • the time complexity of the operations that insert or erase a single element from the set is linear, including the ones that take an insertion position iterator.
[Note 1:
A flat_­multiset does not meet the additional requirements of an allocator-aware container, as described in [container.alloc.reqmts].
— end note]
A flat_­multiset also provides most operations described in [associative.reqmts] for equal keys.
This means that a flat_­multiset supports the a_­eq operations in [associative.reqmts] but not the a_­uniq operations.
For a flat_­multiset<Key>, both the key_­type and value_­type are Key.
Descriptions are provided here only for operations on flat_­multiset that are not described in one of the general sections or for operations where there is additional semantic information.
A flat_­multiset maintains the invariant that the keys are sorted with respect to the comparison object.
If any member function in [flat.multiset.defn] exits via an exception, the invariant is restored.
[Note 2:
This can result in the flat_­multiset's being emptied.
— end note]
Any sequence container ([sequence.reqmts]) supporting Cpp17RandomAccessIterator can be used to instantiate flat_­multiset.
In particular, vector ([vector]) and deque ([deque]) can be used.
[Note 3:
vector<bool> is not a sequence container.
— end note]
The program is ill-formed if Key is not the same type as KeyContainer​::​value_­type.
The effect of calling a constructor or member function that takes a sorted_­equivalent_­t argument with a range that is not sorted with respect to key_­comp() is undefined.

24.6.12.2 Definition [flat.multiset.defn]

namespace std { template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>> class flat_multiset { public: // types using key_type = Key; using value_type = Key; using key_compare = Compare; using value_compare = Compare; using reference = value_type&; using const_reference = const value_type&; using size_type = typename KeyContainer::size_type; using difference_type = typename KeyContainer::difference_type; using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using container_type = KeyContainer; // [flat.multiset.cons], constructors flat_multiset() : flat_multiset(key_compare()) { } explicit flat_multiset(container_type cont); template<class Allocator> flat_multiset(const container_type& cont, const Allocator& a); flat_multiset(sorted_equivalent_t, container_type cont) : c(std::move(cont)), compare(key_compare()) { } template<class Allocator> flat_multiset(sorted_equivalent_t, const container_type&, const Allocator& a); explicit flat_multiset(const key_compare& comp) : c(), compare(comp) { } template<class Allocator> flat_multiset(const key_compare& comp, const Allocator& a); template<class Allocator> explicit flat_multiset(const Allocator& a); template<class InputIterator> flat_multiset(InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(), compare(comp) { insert(first, last); } template<class InputIterator, class Allocator> flat_multiset(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_multiset(InputIterator first, InputIterator last, const Allocator& a); template<container-compatible-range<value_type> R> flat_multiset(from_range_t fr, R&& rg) : flat_multiset(fr, std::forward<R>(rg), key_compare()) { } template<container-compatible-range<value_type> R, class Allocator> flat_multiset(from_range_t, R&& rg, const Allocator& a); template<container-compatible-range<value_type> R> flat_multiset(from_range_t, R&& rg, const key_compare& comp) : flat_multiset(comp) { insert_range(std::forward<R>(rg)); } template<container-compatible-range<value_type> R, class Allocator> flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); template<class InputIterator> flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(first, last), compare(comp) { } template<class InputIterator, class Allocator> flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const Allocator& a); flat_multiset(initializer_list<key_type> il, const key_compare& comp = key_compare()) : flat_multiset(il.begin(), il.end(), comp) { } template<class Allocator> flat_multiset(initializer_list<key_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_multiset(initializer_list<key_type> il, const Allocator& a); flat_multiset(sorted_equivalent_t s, initializer_list<key_type> il, const key_compare& comp = key_compare()) : flat_multiset(s, il.begin(), il.end(), comp) { } template<class Allocator> flat_multiset(sorted_equivalent_t, initializer_list<key_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_multiset(sorted_equivalent_t, initializer_list<key_type> il, const Allocator& a); flat_multiset& operator=(initializer_list<key_type>); // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity [[nodiscard]] bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // [flat.multiset.modifiers], modifiers template<class... Args> iterator emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); iterator insert(const value_type& x) { return emplace(x); } iterator insert(value_type&& x) { return emplace(std::move(x)); } iterator insert(const_iterator position, const value_type& x) { return emplace_hint(position, x); } iterator insert(const_iterator position, value_type&& x) { return emplace_hint(position, std::move(x)); } template<class InputIterator> void insert(InputIterator first, InputIterator last); template<class InputIterator> void insert(sorted_equivalent_t, InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<key_type> il) { insert(il.begin(), il.end()); } void insert(sorted_equivalent_t s, initializer_list<key_type> il) { insert(s, il.begin(), il.end()); } container_type extract() &&; void replace(container_type&&); iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(flat_multiset& y) noexcept; void clear() noexcept; // observers key_compare key_comp() const; value_compare value_comp() const; // set operations iterator find(const key_type& x); const_iterator find(const key_type& x) const; template<class K> iterator find(const K& x); template<class K> const_iterator find(const K& x) const; size_type count(const key_type& x) const; template<class K> size_type count(const K& x) const; bool contains(const key_type& x) const; template<class K> bool contains(const K& x) const; iterator lower_bound(const key_type& x); const_iterator lower_bound(const key_type& x) const; template<class K> iterator lower_bound(const K& x); template<class K> const_iterator lower_bound(const K& x) const; iterator upper_bound(const key_type& x); const_iterator upper_bound(const key_type& x) const; template<class K> iterator upper_bound(const K& x); template<class K> const_iterator upper_bound(const K& x) const; pair<iterator, iterator> equal_range(const key_type& x); pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K> pair<iterator, iterator> equal_range(const K& x); template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const; friend bool operator==(const flat_multiset& x, const flat_multiset& y); friend synth-three-way-result<value_type> operator<=>(const flat_multiset& x, const flat_multiset& y); friend void swap(flat_multiset& x, flat_multiset& y) noexcept { x.swap(y); } private: container_type c; // exposition only key_compare compare; // exposition only }; template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>> flat_multiset(InputIterator, InputIterator, Compare = Compare()) -> flat_multiset<iter-value-type<InputIterator>, iter-value-type<InputIterator>, Compare>; template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>> flat_multiset(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare()) -> flat_multiset<iter-value-type<InputIterator>, iter-value-type<InputIterator>, Compare>; template<ranges::input_­range R, class Compare = less<ranges::range_value_t<R>>, class Allocator = allocator<ranges::range_value_t<R>>> flat_multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) -> flat_multiset<ranges::range_value_t<R>, Compare>; template<ranges::input_­range R, class Allocator> flat_multiset(from_range_t, R&&, Allocator) -> flat_multiset<ranges::range_value_t<R>, less<ranges::range_value_t<R>>>; template<class Key, class Compare = less<Key>> flat_multiset(initializer_list<Key>, Compare = Compare()) -> flat_multiset<Key, Compare>; template<class Key, class Compare = less<Key>> flat_multiset(sorted_equivalent_t, initializer_list<Key>, Compare = Compare()) -> flat_multiset<Key, Compare>; template<class Key, class Compare, class KeyContainer, class Allocator> struct uses_allocator<flat_multiset<Key, Compare, KeyContainer>, Allocator> : bool_constant<uses_allocator_v<KeyContainer, Allocator>> { }; }

24.6.12.3 Constructors [flat.multiset.cons]

explicit flat_multiset(container_type cont);
Effects: Initializes c with std​::​move(cont), value-initializes compare, and sorts the range [begin(), end()) with respect to compare.
Complexity: Linear in N if cont is sorted with respect to compare and otherwise , where N is the value of cont.size() before this call.
template<class Allocator> flat_multiset(const container_type& cont, const Allocator& a);
Constraints: uses_­allocator_­v<container_­type, Allocator> is true.
Effects: Equivalent to flat_­multiset(cont), except that c is constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Same as flat_­multiset(cont).
template<class Allocator> flat_multiset(sorted_equivalent_t s, const container_type& cont, const Allocator& a);
Constraints: uses_­allocator_­v<container_­type, Allocator> is true.
Effects: Equivalent to flat_­multiset(s, cont), except that c is constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Linear.
template<class Allocator> flat_multiset(const key_compare& comp, const Allocator& a); template<class Allocator> explicit flat_multiset(const Allocator& a); template<class InputIterator, class Allocator> flat_multiset(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_multiset(InputIterator first, InputIterator last, const Allocator& a); template<container-compatible-range<value_type> R, class Allocator> flat_multiset(from_range_t, R&& rg, const Allocator& a); template<container-compatible-range<value_type> R, class Allocator> flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); template<class InputIterator, class Allocator> flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const Allocator& a); template<class Allocator> flat_multiset(initializer_list<key_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_multiset(initializer_list<key_type> il, const Allocator& a); template<class Allocator> flat_multiset(sorted_equivalent_t, initializer_list<key_type> il, const key_compare& comp, const Allocator& a); template<class Allocator> flat_multiset(sorted_equivalent_t, initializer_list<key_type> il, const Allocator& a);
Constraints: uses_­allocator_­v<container_­type, Allocator> is true.
Effects: Equivalent to the corresponding non-allocator constructors except that c is constructed with uses-allocator construction ([allocator.uses.construction]).

24.6.12.4 Modifiers [flat.multiset.modifiers]

template<class... Args> iterator emplace(Args&&... args);
Constraints: is_­constructible_­v<key_­type, Args...> is true.
Effects: First, initializes an object t of type key_­type with std​::​forward<Args>(args)..., then inserts t as if by: auto it = ranges::upper_bound(c, t, compare); c.insert(it, std::move(t));
Returns: An iterator that points to the inserted element.
template<class InputIterator> void insert(InputIterator first, InputIterator last);
Effects: Adds elements to c as if by: c.insert(c.end(), first, last);
Then, sorts the range of newly inserted elements with respect to compare, and merges the resulting sorted range and the sorted range of pre-existing elements into a single sorted range.
Complexity: N + , where N is size() before the operation and M is distance(first, last).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<class InputIterator> void insert(sorted_equivalent_t, InputIterator first, InputIterator last);
Effects: Equivalent to insert(first, last).
Complexity: Linear.
void swap(flat_multiset& y) noexcept;
Effects: Equivalent to: ranges::swap(compare, y.compare); ranges::swap(c, y.c);
container_type extract() &&;
Postconditions: *this is emptied, even if the function exits via an exception.
Returns: std​::​move(c).
void replace(container_type&& cont);
Preconditions: The elements of cont are sorted with respect to compare.
Effects: Equivalent to: c = std​::​move(cont);

24.6.12.5 Erasure [flat.multiset.erasure]

template<class Key, class Compare, class KeyContainer, class Predicate> typename flat_multiset<Key, Compare, KeyContainer>::size_type erase_if(flat_multiset<Key, Compare, KeyContainer>& c, Predicate pred);
Effects: Equivalent to: auto [erase_first, erase_last] = ranges::remove_if(c, pred); auto n = erase_last - erase_first; c.erase(erase_first, erase_last); return n;

24.6.13 Container adaptors formatting [container.adaptors.format]

For each of queue, priority_­queue, and stack, the library provides the following formatter specialization where adaptor-type is the name of the template:
namespace std { template<class charT, class T, formattable<charT> Container, class... U> struct formatter<adaptor-type<T, Container, U...>, charT> { private: using maybe-const-adaptor = // exposition only fmt-maybe-const<adaptor-type<T, Container, U...>, charT>; formatter<Container, charT> underlying_; // exposition only public: template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> typename FormatContext::iterator format(maybe-const-adaptor& r, FormatContext& ctx) const; }; }
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);
Effects: Equivalent to: return underlying_­.parse(ctx);
template<class FormatContext> typename FormatContext::iterator format(maybe-const-adaptor& r, FormatContext& ctx) const;
Effects: Equivalent to: return underlying_­.format(r.c, ctx);