The headers
,
,
,
and 
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  KeyContainer-  and  Compare-  template parameters, and
 is_invocable_v<const Compare&,
               const typename KeyContainer::value_type&,
               const typename KeyContainer::value_type&>- 
is not a valid expression or 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, 
iter-mapped-type,
range-key-type, and 
range-mapped-type
defined in 
[associative.general]
may appear in deduction guides for container adaptors
.The following exposition-only alias template
may appear in deduction guides for container adaptors:
template<class Allocator, class T>
  using alloc-rebind =                      
    typename allocator_traits<Allocator>::template rebind_alloc<T>;
Any sequence container supporting operations
front(),
back(),
push_back()
and
pop_front()
can be used to instantiate
queue.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:
    constexpr queue() : queue(Container()) {}
    constexpr explicit queue(const Container&);
    constexpr explicit queue(Container&&);
    template<class InputIterator> constexpr queue(InputIterator first, InputIterator last);
    template<container-compatible-range<T> R> constexpr queue(from_range_t, R&& rg);
    template<class Alloc> constexpr explicit queue(const Alloc&);
    template<class Alloc> constexpr queue(const Container&, const Alloc&);
    template<class Alloc> constexpr queue(Container&&, const Alloc&);
    template<class Alloc> constexpr queue(const queue&, const Alloc&);
    template<class Alloc> constexpr queue(queue&&, const Alloc&);
    template<class InputIterator, class Alloc>
      constexpr queue(InputIterator first, InputIterator last, const Alloc&);
    template<container-compatible-range<T> R, class Alloc>
      constexpr queue(from_range_t, R&& rg, const Alloc&);
    constexpr bool              empty() const     { return c.empty(); }
    constexpr size_type         size()  const     { return c.size(); }
    constexpr reference         front()           { return c.front(); }
    constexpr const_reference   front() const     { return c.front(); }
    constexpr reference         back()            { return c.back(); }
    constexpr const_reference   back() const      { return c.back(); }
    constexpr void push(const value_type& x)      { c.push_back(x); }
    constexpr void push(value_type&& x)           { c.push_back(std::move(x)); }
    template<container-compatible-range<T> R> constexpr void push_range(R&& rg);
    template<class... Args>
      constexpr decltype(auto) emplace(Args&&... args)
        { return c.emplace_back(std::forward<Args>(args)...); }
    constexpr void pop()                          { c.pop_front(); }
    constexpr 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 { };
}
 constexpr explicit queue(const Container& cont);
Effects: Initializes 
c with 
cont. constexpr explicit queue(Container&& cont);
Effects: Initializes 
c with 
std::move(cont). template<class InputIterator>
  constexpr queue(InputIterator first, InputIterator last);
Effects: Initializes 
c with
first as the first argument and 
last as the second argument
. Effects: Initializes 
c with 
ranges::to<Container>(std::forward<R>(rg)). If 
uses_allocator_v<container_type, Alloc> is 
false
the constructors in this subclause shall not participate in overload resolution
.template<class Alloc> constexpr explicit queue(const Alloc& a);
Effects: Initializes 
c with 
a. template<class Alloc> constexpr 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> constexpr 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> constexpr 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> constexpr 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>
  constexpr 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
. Effects: Initializes 
c with
ranges::to<Container>(std::forward<R>(rg), a). Effects: Equivalent to 
c.append_range(std::forward<R>(rg))
if that is a valid expression,
otherwise 
ranges::copy(rg, back_inserter(c)). template<class T, class Container>
  constexpr bool operator==(const queue<T, Container>& x, const queue<T, Container>& y);
template<class T, class Container>
  constexpr bool operator!=(const queue<T, Container>& x,  const queue<T, Container>& y);
template<class T, class Container>
  constexpr bool operator< (const queue<T, Container>& x, const queue<T, Container>& y);
template<class T, class Container>
  constexpr bool operator> (const queue<T, Container>& x, const queue<T, Container>& y);
template<class T, class Container>
  constexpr bool operator<=(const queue<T, Container>& x, const queue<T, Container>& y);
template<class T, class Container>
  constexpr bool operator>=(const queue<T, Container>& x, const queue<T, Container>& y);
template<class T, three_way_comparable Container>
  constexpr compare_three_way_result_t<Container>
    operator<=>(const queue<T, Container>& x, const queue<T, Container>& y);
template<class T, class Container>
  constexpr 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). Any sequence container with random access iterator and supporting operations
front(),
push_back()
and
pop_back()
can be used to instantiate
priority_queue.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:
    constexpr priority_queue() : priority_queue(Compare()) {}
    constexpr explicit priority_queue(const Compare& x) : priority_queue(x, Container()) {}
    constexpr priority_queue(const Compare& x, const Container&);
    constexpr priority_queue(const Compare& x, Container&&);
    template<class InputIterator>
      constexpr priority_queue(InputIterator first, InputIterator last,
                               const Compare& x = Compare());
    template<class InputIterator>
      constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x,
                               const Container&);
    template<class InputIterator>
      constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x,
                               Container&&);
    template<container-compatible-range<T> R>
      constexpr priority_queue(from_range_t, R&& rg, const Compare& x = Compare());
    template<class Alloc> constexpr explicit priority_queue(const Alloc&);
    template<class Alloc> constexpr priority_queue(const Compare&, const Alloc&);
    template<class Alloc>
      constexpr priority_queue(const Compare&, const Container&, const Alloc&);
    template<class Alloc> constexpr priority_queue(const Compare&, Container&&, const Alloc&);
    template<class Alloc> constexpr priority_queue(const priority_queue&, const Alloc&);
    template<class Alloc> constexpr priority_queue(priority_queue&&, const Alloc&);
    template<class InputIterator, class Alloc>
      constexpr priority_queue(InputIterator, InputIterator, const Alloc&);
    template<class InputIterator, class Alloc>
      constexpr priority_queue(InputIterator, InputIterator, const Compare&, const Alloc&);
    template<class InputIterator, class Alloc>
      constexpr priority_queue(InputIterator, InputIterator, const Compare&, const Container&,
                               const Alloc&);
    template<class InputIterator, class Alloc>
      constexpr priority_queue(InputIterator, InputIterator, const Compare&, Container&&,
                               const Alloc&);
    template<container-compatible-range<T> R, class Alloc>
      constexpr priority_queue(from_range_t, R&& rg, const Compare&, const Alloc&);
    template<container-compatible-range<T> R, class Alloc>
      constexpr priority_queue(from_range_t, R&& rg, const Alloc&);
    constexpr bool            empty() const { return c.empty(); }
    constexpr size_type       size()  const { return c.size(); }
    constexpr const_reference top()   const { return c.front(); }
    constexpr void push(const value_type& x);
    constexpr void push(value_type&& x);
    template<container-compatible-range<T> R>
      constexpr void push_range(R&& rg);
    template<class... Args> constexpr void emplace(Args&&... args);
    constexpr void pop();
    constexpr 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>>;
  
  template<class T, class Container, class Compare, class Alloc>
    struct uses_allocator<priority_queue<T, Container, Compare>, Alloc>
      : uses_allocator<Container, Alloc>::type { };
}
 constexpr priority_queue(const Compare& x, const Container& y);
constexpr priority_queue(const Compare& x, Container&& y);
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>
  constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare());
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>
  constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x,
                           const Container& y);
template<class InputIterator>
  constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x,
                           Container&& y);
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). 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). If 
uses_allocator_v<container_type, Alloc> is 
false
the constructors in this subclause shall not participate in overload resolution
.template<class Alloc> constexpr explicit priority_queue(const Alloc& a);
Effects: Initializes 
c with 
a and value-initializes 
comp. template<class Alloc> constexpr priority_queue(const Compare& compare, const Alloc& a);
Effects: Initializes 
c with 
a and initializes 
comp with 
compare. template<class Alloc>
  constexpr 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>
  constexpr 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> constexpr 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> constexpr 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>
  constexpr 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>
  constexpr 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>
  constexpr 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>
  constexpr 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>
  constexpr 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). Effects: Initializes
c with 
ranges::to<Container>(std::forward<R>(rg), a)
and value-initializes 
comp;
calls 
make_heap(c.begin(), c.end(), comp). constexpr void push(const value_type& x);
Effects: As if by:
c.push_back(x);
push_heap(c.begin(), c.end(), comp);
constexpr void push(value_type&& x);
Effects: As if by:
c.push_back(std::move(x));
push_heap(c.begin(), c.end(), comp);
Effects: Inserts all elements of 
rg in 
c via
c.append_range(std::forward<R>(rg)) if that is a valid expression, or
ranges::copy(rg, back_inserter(c)) otherwise
.  Then restores the heap property as if by
make_heap(c.begin(), c.end(), comp).Postconditions: 
is_heap(c.begin(), c.end(), comp) is 
true. template<class... Args> constexpr void emplace(Args&&... args);
Effects: As if by:
c.emplace_back(std::forward<Args>(args)...);
push_heap(c.begin(), c.end(), comp);
Effects: As if by:
pop_heap(c.begin(), c.end(), comp);
c.pop_back();
template<class T, class Container, class Compare>
  constexpr 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). Any sequence container supporting operations
back(),
push_back()
and
pop_back()
can be used to instantiate
stack.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:
    constexpr stack() : stack(Container()) {}
    constexpr explicit stack(const Container&);
    constexpr explicit stack(Container&&);
    template<class InputIterator> constexpr stack(InputIterator first, InputIterator last);
    template<container-compatible-range<T> R>
      constexpr stack(from_range_t, R&& rg);
    template<class Alloc> constexpr explicit stack(const Alloc&);
    template<class Alloc> constexpr stack(const Container&, const Alloc&);
    template<class Alloc> constexpr stack(Container&&, const Alloc&);
    template<class Alloc> constexpr stack(const stack&, const Alloc&);
    template<class Alloc> constexpr stack(stack&&, const Alloc&);
    template<class InputIterator, class Alloc>
      constexpr stack(InputIterator first, InputIterator last, const Alloc&);
    template<container-compatible-range<T> R, class Alloc>
      constexpr stack(from_range_t, R&& rg, const Alloc&);
    constexpr bool              empty() const     { return c.empty(); }
    constexpr size_type         size()  const     { return c.size(); }
    constexpr reference         top()             { return c.back(); }
    constexpr const_reference   top()   const     { return c.back(); }
    constexpr void push(const value_type& x)      { c.push_back(x); }
    constexpr void push(value_type&& x)           { c.push_back(std::move(x)); }
    template<container-compatible-range<T> R>
      constexpr void push_range(R&& rg);
    template<class... Args>
      constexpr decltype(auto) emplace(Args&&... args)
        { return c.emplace_back(std::forward<Args>(args)...); }
    constexpr void pop()                          { c.pop_back(); }
    constexpr 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 { };
}
 constexpr explicit stack(const Container& cont);
Effects: Initializes 
c with 
cont. constexpr explicit stack(Container&& cont);
Effects: Initializes 
c with 
std::move(cont). template<class InputIterator>
  constexpr stack(InputIterator first, InputIterator last);
Effects: Initializes 
c with
first as the first argument and 
last as the second argument
. Effects: Initializes 
c with 
ranges::to<Container>(std::forward<R>(rg)). If 
uses_allocator_v<container_type, Alloc> is 
false
the constructors in this subclause shall not participate in overload resolution
.template<class Alloc> constexpr explicit stack(const Alloc& a);
Effects: Initializes 
c with 
a. template<class Alloc> constexpr 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> constexpr 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> constexpr 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> constexpr 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>
  constexpr 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
. Effects: Initializes
c with 
ranges::to<Container>(std::forward<R>(rg), a). Effects: Equivalent to 
c.append_range(std::forward<R>(rg))
if that is a valid expression,
otherwise 
ranges::copy(rg, back_inserter(c)). template<class T, class Container>
  constexpr bool operator==(const stack<T, Container>& x, const stack<T, Container>& y);
template<class T, class Container>
  constexpr bool operator!=(const stack<T, Container>& x, const stack<T, Container>& y);
template<class T, class Container>
  constexpr bool operator< (const stack<T, Container>& x, const stack<T, Container>& y);
template<class T, class Container>
  constexpr bool operator> (const stack<T, Container>& x, const stack<T, Container>& y);
template<class T, class Container>
  constexpr bool operator<=(const stack<T, Container>& x, const stack<T, Container>& y);
template<class T, class Container>
  constexpr bool operator>=(const stack<T, Container>& x, const stack<T, Container>& y);
template<class T, three_way_comparable Container>
  constexpr compare_three_way_result_t<Container>
    operator<=>(const stack<T, Container>& x, const stack<T, Container>& y);
template<class T, class Container>
  constexpr 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). 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 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.
    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 type 
C
that meets the sequence container requirements (
[sequence.reqmts])
can be used to instantiate 
flat_map,
as long as
C::iterator meets the 
Cpp17RandomAccessIterator requirements and
invocations of
member functions 
C::size and 
C::max_size do not exit via an exception
.[
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
.namespace std {
  template<class Key, class T, class Compare = less<Key>,
           class KeyContainer = vector<Key>, class MappedContainer = vector<T>>
  class flat_map {
  public:
    
    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; 
    using const_iterator         = implementation-defined; 
    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;                                         
      constexpr value_compare(key_compare c) : comp(c) { }      
    public:
      constexpr 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;
    };
    
    constexpr flat_map() : flat_map(key_compare()) { }
    constexpr explicit flat_map(const key_compare& comp)
      : c(), compare(comp) { }
    constexpr flat_map(key_container_type key_cont, mapped_container_type mapped_cont,
                       const key_compare& comp = key_compare());
    constexpr flat_map(sorted_unique_t, key_container_type key_cont,
                       mapped_container_type mapped_cont,
                       const key_compare& comp = key_compare());
    template<class InputIterator>
      constexpr flat_map(InputIterator first, InputIterator last,
                         const key_compare& comp = key_compare())
        : c(), compare(comp) { insert(first, last); }
    template<class InputIterator>
      constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last,
                         const key_compare& comp = key_compare())
        : c(), compare(comp) { insert(sorted_unique, first, last); }
    template<container-compatible-range<value_type> R>
      constexpr flat_map(from_range_t, R&& rg)
        : flat_map(from_range, std::forward<R>(rg), key_compare()) { }
    template<container-compatible-range<value_type> R>
      constexpr flat_map(from_range_t, R&& rg, const key_compare& comp)
        : flat_map(comp) { insert_range(std::forward<R>(rg)); }
    constexpr flat_map(initializer_list<value_type> il, const key_compare& comp = key_compare())
        : flat_map(il.begin(), il.end(), comp) { }
    constexpr flat_map(sorted_unique_t, initializer_list<value_type> il,
                       const key_compare& comp = key_compare())
        : flat_map(sorted_unique, il.begin(), il.end(), comp) { }
    
    template<class Alloc>
      constexpr explicit flat_map(const Alloc& a);
    template<class Alloc>
      constexpr flat_map(const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_map(const key_container_type& key_cont,
                         const mapped_container_type& mapped_cont,
                         const Alloc& a);
    template<class Alloc>
      constexpr flat_map(const key_container_type& key_cont,
                         const mapped_container_type& mapped_cont,
                         const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_map(sorted_unique_t, const key_container_type& key_cont,
                         const mapped_container_type& mapped_cont, const Alloc& a);
    template<class Alloc>
      constexpr flat_map(sorted_unique_t, const key_container_type& key_cont,
                         const mapped_container_type& mapped_cont, const key_compare& comp,
                         const Alloc& a);
    template<class Alloc>
      constexpr flat_map(const flat_map&, const Alloc& a);
    template<class Alloc>
      constexpr flat_map(flat_map&&, const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_map(InputIterator first, InputIterator last, const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_map(InputIterator first, InputIterator last,
                         const key_compare& comp, const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last,
                         const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last,
                         const key_compare& comp, const Alloc& a);
    template<container-compatible-range<value_type> R, class Alloc>
      constexpr flat_map(from_range_t, R&& rg, const Alloc& a);
    template<container-compatible-range<value_type> R, class Alloc>
      constexpr flat_map(from_range_t, R&& rg, const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_map(initializer_list<value_type> il, const Alloc& a);
    template<class Alloc>
      constexpr flat_map(initializer_list<value_type> il, const key_compare& comp,
                         const Alloc& a);
    template<class Alloc>
      constexpr flat_map(sorted_unique_t, initializer_list<value_type> il, const Alloc& a);
    template<class Alloc>
      constexpr flat_map(sorted_unique_t, initializer_list<value_type> il,
                         const key_compare& comp, const Alloc& a);
    constexpr flat_map& operator=(initializer_list<value_type>);
    
    constexpr iterator               begin() noexcept;
    constexpr const_iterator         begin() const noexcept;
    constexpr iterator               end() noexcept;
    constexpr const_iterator         end() const noexcept;
    constexpr reverse_iterator       rbegin() noexcept;
    constexpr const_reverse_iterator rbegin() const noexcept;
    constexpr reverse_iterator       rend() noexcept;
    constexpr const_reverse_iterator rend() const noexcept;
    constexpr const_iterator         cbegin() const noexcept;
    constexpr const_iterator         cend() const noexcept;
    constexpr const_reverse_iterator crbegin() const noexcept;
    constexpr const_reverse_iterator crend() const noexcept;
    
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;
    
    constexpr mapped_type& operator[](const key_type& x);
    constexpr mapped_type& operator[](key_type&& x);
    template<class K> constexpr mapped_type& operator[](K&& x);
    constexpr mapped_type& at(const key_type& x);
    constexpr const mapped_type& at(const key_type& x) const;
    template<class K> constexpr mapped_type& at(const K& x);
    template<class K> constexpr const mapped_type& at(const K& x) const;
    
    template<class... Args> constexpr pair<iterator, bool> emplace(Args&&... args);
    template<class... Args>
      constexpr iterator emplace_hint(const_iterator position, Args&&... args);
    constexpr pair<iterator, bool> insert(const value_type& x)
      { return emplace(x); }
    constexpr pair<iterator, bool> insert(value_type&& x)
      { return emplace(std::move(x)); }
    constexpr iterator insert(const_iterator position, const value_type& x)
      { return emplace_hint(position, x); }
    constexpr iterator insert(const_iterator position, value_type&& x)
      { return emplace_hint(position, std::move(x)); }
    template<class P> constexpr pair<iterator, bool> insert(P&& x);
    template<class P>
      constexpr iterator insert(const_iterator position, P&&);
    template<class InputIterator>
      constexpr void insert(InputIterator first, InputIterator last);
    template<class InputIterator>
      constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last);
    template<container-compatible-range<value_type> R>
      constexpr void insert_range(R&& rg);
    constexpr void insert(initializer_list<value_type> il)
      { insert(il.begin(), il.end()); }
    constexpr void insert(sorted_unique_t, initializer_list<value_type> il)
      { insert(sorted_unique, il.begin(), il.end()); }
    constexpr containers extract() &&;
    constexpr void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont);
    template<class... Args>
      constexpr pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
    template<class... Args>
      constexpr pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
    template<class K, class... Args>
      constexpr pair<iterator, bool> try_emplace(K&& k, Args&&... args);
    template<class... Args>
      constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
    template<class... Args>
      constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
    template<class K, class... Args>
      constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
    template<class M>
      constexpr pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
    template<class M>
      constexpr pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
    template<class K, class M>
      constexpr pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
    template<class M>
      constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
    template<class M>
      constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
    template<class K, class M>
      constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);
    constexpr iterator erase(iterator position);
    constexpr iterator erase(const_iterator position);
    constexpr size_type erase(const key_type& x);
    template<class K> constexpr size_type erase(K&& x);
    constexpr iterator erase(const_iterator first, const_iterator last);
    constexpr void swap(flat_map& y) noexcept;
    constexpr void clear() noexcept;
    
    constexpr key_compare key_comp() const;
    constexpr value_compare value_comp() const;
    constexpr const key_container_type& keys() const noexcept      { return c.keys; }
    constexpr const mapped_container_type& values() const noexcept { return c.values; }
    
    constexpr iterator find(const key_type& x);
    constexpr const_iterator find(const key_type& x) const;
    template<class K> constexpr iterator find(const K& x);
    template<class K> constexpr const_iterator find(const K& x) const;
    constexpr size_type count(const key_type& x) const;
    template<class K> constexpr size_type count(const K& x) const;
    constexpr bool contains(const key_type& x) const;
    template<class K> constexpr bool contains(const K& x) const;
    constexpr iterator lower_bound(const key_type& x);
    constexpr const_iterator lower_bound(const key_type& x) const;
    template<class K> constexpr iterator lower_bound(const K& x);
    template<class K> constexpr const_iterator lower_bound(const K& x) const;
    constexpr iterator upper_bound(const key_type& x);
    constexpr const_iterator upper_bound(const key_type& x) const;
    template<class K> constexpr iterator upper_bound(const K& x);
    template<class K> constexpr const_iterator upper_bound(const K& x) const;
    constexpr pair<iterator, iterator> equal_range(const key_type& x);
    constexpr pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
    template<class K> constexpr pair<iterator, iterator> equal_range(const K& x);
    template<class K>
      constexpr pair<const_iterator, const_iterator> equal_range(const K& x) const;
    friend constexpr bool operator==(const flat_map& x, const flat_map& y);
    friend constexpr synth-three-way-result<value_type>
      operator<=>(const flat_map& x, const flat_map& y);
    friend constexpr void swap(flat_map& x, flat_map& y) noexcept
      { x.swap(y); }
  private:
    containers c;               
    key_compare compare;        
    struct key-equiv {  
      constexpr key-equiv(key_compare c) : comp(c) { }
      constexpr 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,
           class Compare = less<typename KeyContainer::value_type>>
    flat_map(KeyContainer, MappedContainer, Compare = Compare())
      -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type,
                  Compare, 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, class Compare, class Allocator>
    flat_map(KeyContainer, MappedContainer, Compare, Allocator)
      -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type,
                  Compare, KeyContainer, MappedContainer>;
  template<class KeyContainer, class MappedContainer,
           class Compare = less<typename KeyContainer::value_type>>
    flat_map(sorted_unique_t, KeyContainer, MappedContainer, Compare = Compare())
      -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type,
                  Compare, 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 KeyContainer, class MappedContainer, class Compare, class Allocator>
    flat_map(sorted_unique_t, KeyContainer, MappedContainer, Compare, Allocator)
      -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type,
                  Compare, 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 = allocator<byte>>
    flat_map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())
      -> flat_map<range-key-type<R>, range-mapped-type<R>, Compare,
                  vector<range-key-type<R>, alloc-rebind<Allocator, range-key-type<R>>>,
                  vector<range-mapped-type<R>, alloc-rebind<Allocator, range-mapped-type<R>>>>;
  template<ranges::input_range R, class Allocator>
    flat_map(from_range_t, R&&, Allocator)
      -> flat_map<range-key-type<R>, range-mapped-type<R>, less<range-key-type<R>>,
                  vector<range-key-type<R>, alloc-rebind<Allocator, range-key-type<R>>>,
                  vector<range-mapped-type<R>, alloc-rebind<Allocator, 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
.constexpr flat_map(key_container_type key_cont, mapped_container_type mapped_cont,
                   const key_compare& comp = key_compare());
Effects: Initializes
c.keys with std::move(key_cont),
c.values with std::move(mapped_cont), and
compare with comp;
sorts the range [begin(), end()) with respect to value_comp(); and
finally erases the duplicate elements as if by:
auto zv = views::zip(c.keys, c.values);
auto it = ranges::unique(zv, key-equiv(compare)).begin();
auto dist = distance(zv.begin(), it);
c.keys.erase(c.keys.begin() + dist, c.keys.end());
c.values.erase(c.values.begin() + dist, c.values.end());
Complexity: Linear in 
N if the container arguments are already sorted
with respect to 
value_comp() and otherwise 
NlogN,
where 
N is the value of 
key_cont.size() before this call
. constexpr flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont,
                   const key_compare& comp = key_compare());
Effects: Initializes
c.keys with 
std::move(key_cont),
c.values with 
std::move(mapped_cont), and
compare with 
comp. The constructors in this subclause shall not participate in overload resolution
unless 
uses_allocator_v<key_container_type, Alloc> is 
true
and 
uses_allocator_v<mapped_container_type, Alloc> is 
true.template<class Alloc>
  constexpr flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont,
                     const Alloc& a);
template<class Alloc>
  constexpr flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont,
                     const key_compare& comp, const Alloc& a);
Effects: Equivalent to 
flat_map(key_cont, mapped_cont) and
flat_map(key_cont, mapped_cont, comp), respectively,
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) and
flat_map(key_cont, mapped_cont, comp), respectively
. template<class Alloc>
  constexpr flat_map(sorted_unique_t, const key_container_type& key_cont,
                     const mapped_container_type& mapped_cont, const Alloc& a);
template<class Alloc>
  constexpr flat_map(sorted_unique_t, const key_container_type& key_cont,
                     const mapped_container_type& mapped_cont, const key_compare& comp,
                     const Alloc& a);
Effects: Equivalent to 
flat_map(sorted_unique, key_cont, mapped_cont) and
flat_map(sorted_unique, key_cont, mapped_cont, comp), respectively,
except that 
c.keys and 
c.values are constructed
with uses-allocator construction (
[allocator.uses.construction])
. template<class Alloc>
  constexpr explicit flat_map(const Alloc& a);
template<class Alloc>
  constexpr flat_map(const key_compare& comp, const Alloc& a);
template<class Alloc>
  constexpr flat_map(const flat_map&, const Alloc& a);
template<class Alloc>
  constexpr flat_map(flat_map&&, const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_map(InputIterator first, InputIterator last, const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_map(InputIterator first, InputIterator last, const key_compare& comp,
                     const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last, const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last,
                     const key_compare& comp, const Alloc& a);
template<container-compatible-range<value_type> R, class Alloc>
  constexpr flat_map(from_range_t, R&& rg, const Alloc& a);
template<container-compatible-range<value_type> R, class Alloc>
  constexpr flat_map(from_range_t, R&& rg, const key_compare& comp, const Alloc& a);
template<class Alloc>
  constexpr flat_map(initializer_list<value_type> il, const Alloc& a);
template<class Alloc>
  constexpr flat_map(initializer_list<value_type> il, const key_compare& comp, const Alloc& a);
template<class Alloc>
  constexpr flat_map(sorted_unique_t, initializer_list<value_type> il, const Alloc& a);
template<class Alloc>
  constexpr flat_map(sorted_unique_t, initializer_list<value_type> il,
                     const key_compare& comp, const Alloc& a);
Effects: Equivalent to the corresponding non-allocator constructors
except that 
c.keys and 
c.values are constructed
with uses-allocator construction (
[allocator.uses.construction])
. constexpr size_type size() const noexcept;
constexpr size_type max_size() const noexcept;
Returns: 
min<size_type>(c.keys.max_size(), c.values.max_size()). constexpr mapped_type& operator[](const key_type& x);
Effects: Equivalent to: return try_emplace(x).first->second;
constexpr mapped_type& operator[](key_type&& x);
Effects: Equivalent to: return try_emplace(std::move(x)).first->second;
template<class K> constexpr 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;
constexpr mapped_type&       at(const key_type& x);
constexpr 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
. template<class K> constexpr mapped_type&       at(const K& x);
template<class K> constexpr 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
. template<class... Args> constexpr pair<iterator, bool> emplace(Args&&... args);
Constraints: 
is_constructible_v<pair<key_type, mapped_type>, Args...> 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> constexpr pair<iterator, bool> insert(P&& x);
template<class P> constexpr 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>
  constexpr 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 = views::zip(c.keys, c.values);
auto it = ranges::unique(zv, key-equiv(compare)).begin();
auto dist = distance(zv.begin(), it);
c.keys.erase(c.keys.begin() + dist, c.keys.end());
c.values.erase(c.values.begin() + dist, c.values.end());
Complexity: 
N + 
MlogM,
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>
  constexpr 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 = views::zip(c.keys, c.values);
auto it = ranges::unique(zv, key-equiv(compare)).begin();
auto dist = distance(zv.begin(), it);
c.keys.erase(c.keys.begin() + dist, c.keys.end());
c.values.erase(c.values.begin() + dist, c.values.end());
Complexity: Linear in 
N, where 
N is 
size() after the operation
. Remarks: Since this operation performs an in-place merge, it may allocate memory
. Effects: Adds elements to c as if by:
for (const auto& e : rg) {
  c.keys.insert(c.keys.end(), e.first);
  c.values.insert(c.values.end(), e.second);
}
 
Then, sorts the range of newly inserted elements
with respect to value_comp();
merges the resulting sorted range and
the sorted range of pre-existing elements into a single sorted range; and
finally erases the duplicate elements as if by:
auto zv = views::zip(c.keys, c.values);
auto it = ranges::unique(zv, key-equiv(compare)).begin();
auto dist = distance(zv.begin(), it);
c.keys.erase(c.keys.begin() + dist, c.keys.end());
c.values.erase(c.values.begin() + dist, c.values.end());
Complexity: 
N + 
MlogM,
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>
  constexpr pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
template<class... Args>
  constexpr pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
template<class... Args>
  constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
template<class... Args>
  constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
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>
  constexpr pair<iterator, bool> try_emplace(K&& k, Args&&... args);
template<class K, class... Args>
  constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
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 = upper_bound(c.keys.begin(), c.keys.end(), k, compare);
auto value_it = c.values.begin() + distance(c.keys.begin(), key_it);
c.keys.emplace(key_it, std::forward<K>(k));
c.values.emplace(value_it, std::forward<Args>(args)...);
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>
  constexpr pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
template<class M>
  constexpr pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
template<class M>
  constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
template<class M>
  constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
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, 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>
  constexpr pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
template<class K, class M>
  constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);
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<K>(k), std::forward<M>(obj))
for the first overload or
try_emplace(hint, std::forward<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
. constexpr 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);
Postconditions: 
*this is emptied, even if the function exits via an exception
. constexpr 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);
template<class Key, class T, class Compare, class KeyContainer, class MappedContainer,
         class Predicate>
  constexpr 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
.  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]
 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 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.
    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.
 [
Note 2: 
This can result in the 
flat_multimap being emptied
. — 
end note]
 Any type 
C
that meets the sequence container requirements (
[sequence.reqmts])
can be used to instantiate 
flat_multimap,
as long as
C::iterator meets the 
Cpp17RandomAccessIterator requirements and
invocations of
member functions 
C::size and 
C::max_size do not exit via an exception
.[
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
.namespace std {
  template<class Key, class T, class Compare = less<Key>,
           class KeyContainer = vector<Key>, class MappedContainer = vector<T>>
  class flat_multimap {
  public:
    
    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;     
    using const_iterator         = implementation-defined;     
    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;                                         
      constexpr value_compare(key_compare c) : comp(c) { }      
    public:
      constexpr 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;
    };
    
    constexpr flat_multimap() : flat_multimap(key_compare()) { }
    constexpr explicit flat_multimap(const key_compare& comp)
      : c(), compare(comp) { }
    constexpr flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont,
                            const key_compare& comp = key_compare());
    constexpr flat_multimap(sorted_equivalent_t,
                            key_container_type key_cont, mapped_container_type mapped_cont,
                  const key_compare& comp = key_compare());
    template<class InputIterator>
      constexpr flat_multimap(InputIterator first, InputIterator last,
                              const key_compare& comp = key_compare())
        : c(), compare(comp)
        { insert(first, last); }
    template<class InputIterator>
      constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last,
                              const key_compare& comp = key_compare())
        : c(), compare(comp) { insert(sorted_equivalent, first, last); }
    template<container-compatible-range<value_type> R>
      constexpr flat_multimap(from_range_t, R&& rg)
        : flat_multimap(from_range, std::forward<R>(rg), key_compare()) { }
    template<container-compatible-range<value_type> R>
      constexpr flat_multimap(from_range_t, R&& rg, const key_compare& comp)
        : flat_multimap(comp) { insert_range(std::forward<R>(rg)); }
    constexpr flat_multimap(initializer_list<value_type> il,
                            const key_compare& comp = key_compare())
        : flat_multimap(il.begin(), il.end(), comp) { }
    constexpr flat_multimap(sorted_equivalent_t, initializer_list<value_type> il,
                            const key_compare& comp = key_compare())
        : flat_multimap(sorted_equivalent, il.begin(), il.end(), comp) { }
    
    template<class Alloc>
      constexpr explicit flat_multimap(const Alloc& a);
    template<class Alloc>
      constexpr flat_multimap(const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_multimap(const key_container_type& key_cont,
                              const mapped_container_type& mapped_cont, const Alloc& a);
    template<class Alloc>
      constexpr flat_multimap(const key_container_type& key_cont,
                              const mapped_container_type& mapped_cont,
                              const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_multimap(sorted_equivalent_t, const key_container_type& key_cont,
                              const mapped_container_type& mapped_cont, const Alloc& a);
    template<class Alloc>
      constexpr flat_multimap(sorted_equivalent_t, const key_container_type& key_cont,
                              const mapped_container_type& mapped_cont,
                              const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_multimap(const flat_multimap&, const Alloc& a);
    template<class Alloc>
      constexpr flat_multimap(flat_multimap&&, const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_multimap(InputIterator first, InputIterator last, const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_multimap(InputIterator first, InputIterator last,
                              const key_compare& comp, const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last,
                              const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last,
                              const key_compare& comp, const Alloc& a);
    template<container-compatible-range<value_type> R, class Alloc>
      constexpr flat_multimap(from_range_t, R&& rg, const Alloc& a);
    template<container-compatible-range<value_type> R, class Alloc>
      constexpr flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_multimap(initializer_list<value_type> il, const Alloc& a);
    template<class Alloc>
      constexpr flat_multimap(initializer_list<value_type> il, const key_compare& comp,
                              const Alloc& a);
    template<class Alloc>
      constexpr flat_multimap(sorted_equivalent_t, initializer_list<value_type> il,
                              const Alloc& a);
    template<class Alloc>
      constexpr flat_multimap(sorted_equivalent_t, initializer_list<value_type> il,
                              const key_compare& comp, const Alloc& a);
    flat_multimap& operator=(initializer_list<value_type>);
    
    constexpr iterator               begin() noexcept;
    constexpr const_iterator         begin() const noexcept;
    constexpr iterator               end() noexcept;
    constexpr const_iterator         end() const noexcept;
    constexpr reverse_iterator       rbegin() noexcept;
    constexpr const_reverse_iterator rbegin() const noexcept;
    constexpr reverse_iterator       rend() noexcept;
    constexpr const_reverse_iterator rend() const noexcept;
    constexpr const_iterator         cbegin() const noexcept;
    constexpr const_iterator         cend() const noexcept;
    constexpr const_reverse_iterator crbegin() const noexcept;
    constexpr const_reverse_iterator crend() const noexcept;
    
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;
    
    template<class... Args> constexpr iterator emplace(Args&&... args);
    template<class... Args>
      constexpr iterator emplace_hint(const_iterator position, Args&&... args);
    constexpr iterator insert(const value_type& x)
      { return emplace(x); }
    constexpr iterator insert(value_type&& x)
      { return emplace(std::move(x)); }
    constexpr iterator insert(const_iterator position, const value_type& x)
      { return emplace_hint(position, x); }
    constexpr iterator insert(const_iterator position, value_type&& x)
      { return emplace_hint(position, std::move(x)); }
    template<class P> constexpr iterator insert(P&& x);
    template<class P>
      constexpr iterator insert(const_iterator position, P&&);
    template<class InputIterator>
      constexpr void insert(InputIterator first, InputIterator last);
    template<class InputIterator>
      constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last);
    template<container-compatible-range<value_type> R>
      constexpr void insert_range(R&& rg);
    constexpr void insert(initializer_list<value_type> il)
      { insert(il.begin(), il.end()); }
    constexpr void insert(sorted_equivalent_t, initializer_list<value_type> il)
      { insert(sorted_equivalent, il.begin(), il.end()); }
    constexpr containers extract() &&;
    constexpr void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont);
    constexpr iterator erase(iterator position);
    constexpr iterator erase(const_iterator position);
    constexpr size_type erase(const key_type& x);
    template<class K> constexpr size_type erase(K&& x);
    constexpr iterator erase(const_iterator first, const_iterator last);
    constexpr void swap(flat_multimap&) noexcept;
    constexpr void clear() noexcept;
    
    constexpr key_compare key_comp() const;
    constexpr value_compare value_comp() const;
    constexpr const key_container_type& keys() const noexcept { return c.keys; }
    constexpr const mapped_container_type& values() const noexcept { return c.values; }
    
    constexpr iterator find(const key_type& x);
    constexpr const_iterator find(const key_type& x) const;
    template<class K> constexpr iterator find(const K& x);
    template<class K> constexpr const_iterator find(const K& x) const;
    constexpr size_type count(const key_type& x) const;
    template<class K> constexpr size_type count(const K& x) const;
    constexpr bool contains(const key_type& x) const;
    template<class K> constexpr bool contains(const K& x) const;
    constexpr iterator lower_bound(const key_type& x);
    constexpr const_iterator lower_bound(const key_type& x) const;
    template<class K> constexpr iterator lower_bound(const K& x);
    template<class K> constexpr const_iterator lower_bound(const K& x) const;
    constexpr iterator upper_bound(const key_type& x);
    constexpr const_iterator upper_bound(const key_type& x) const;
    template<class K> constexpr iterator upper_bound(const K& x);
    template<class K> constexpr const_iterator upper_bound(const K& x) const;
    constexpr pair<iterator, iterator> equal_range(const key_type& x);
    constexpr pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
    template<class K>
      constexpr pair<iterator, iterator> equal_range(const K& x);
    template<class K>
      constexpr pair<const_iterator, const_iterator> equal_range(const K& x) const;
    friend constexpr bool operator==(const flat_multimap& x, const flat_multimap& y);
    friend constexpr synth-three-way-result<value_type>
      operator<=>(const flat_multimap& x, const flat_multimap& y);
    friend constexpr void swap(flat_multimap& x, flat_multimap& y) noexcept
      { x.swap(y); }
  private:
    containers c;               
    key_compare compare;        
  };
  template<class KeyContainer, class MappedContainer,
           class Compare = less<typename KeyContainer::value_type>>
    flat_multimap(KeyContainer, MappedContainer, Compare = Compare())
      -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type,
                       Compare, 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, class Compare, class Allocator>
    flat_multimap(KeyContainer, MappedContainer, Compare, Allocator)
      -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type,
                       Compare, KeyContainer, MappedContainer>;
  template<class KeyContainer, class MappedContainer,
           class Compare = less<typename KeyContainer::value_type>>
    flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Compare = Compare())
      -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type,
                       Compare, 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 KeyContainer, class MappedContainer, class Compare, class Allocator>
    flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Compare, Allocator)
      -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type,
                       Compare, 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 = allocator<byte>>
    flat_multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())
      -> flat_multimap<range-key-type<R>, range-mapped-type<R>, Compare,
                       vector<range-key-type<R>,
                              alloc-rebind<Allocator, range-key-type<R>>>,
                       vector<range-mapped-type<R>,
                              alloc-rebind<Allocator, range-mapped-type<R>>>>;
  template<ranges::input_range R, class Allocator>
    flat_multimap(from_range_t, R&&, Allocator)
      -> flat_multimap<range-key-type<R>, range-mapped-type<R>, less<range-key-type<R>>,
                       vector<range-key-type<R>,
                              alloc-rebind<Allocator, range-key-type<R>>>,
                       vector<range-mapped-type<R>,
                              alloc-rebind<Allocator, 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
.constexpr flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont,
                        const key_compare& comp = key_compare());
Effects: Initializes
c.keys with 
std::move(key_cont),
c.values with 
std::move(mapped_cont), and
compare with 
comp;
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 
NlogN,
where 
N is the value of 
key_cont.size() before this call
. constexpr flat_multimap(sorted_equivalent_t, key_container_type key_cont,
                        mapped_container_type mapped_cont,
                        const key_compare& comp = key_compare());
Effects: Initializes
c.keys with 
std::move(key_cont),
c.values with 
std::move(mapped_cont), and
compare with 
comp. The constructors in this subclause shall not participate in overload resolution
unless 
uses_allocator_v<key_container_type, Alloc> is 
true
and 
uses_allocator_v<mapped_container_type, Alloc> is 
true.template<class Alloc>
  constexpr flat_multimap(const key_container_type& key_cont,
                          const mapped_container_type& mapped_cont, const Alloc& a);
template<class Alloc>
  constexpr flat_multimap(const key_container_type& key_cont,
                          const mapped_container_type& mapped_cont,
                          const key_compare& comp, const Alloc& a);
Effects: Equivalent to 
flat_multimap(key_cont, mapped_cont) and
flat_multimap(key_cont, mapped_cont, comp), respectively,
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) and
flat_multimap(key_cont, mapped_cont, comp), respectively
. template<class Alloc>
  constexpr flat_multimap(sorted_equivalent_t, const key_container_type& key_cont,
                const mapped_container_type& mapped_cont, const Alloc& a);
template<class Alloc>
  constexpr flat_multimap(sorted_equivalent_t, const key_container_type& key_cont,
                const mapped_container_type& mapped_cont, const key_compare& comp,
                const Alloc& a);
Effects: Equivalent to 
flat_multimap(sorted_equivalent, key_cont, mapped_cont) and
flat_multimap(sorted_equivalent, key_cont, mapped_cont, comp), respectively,
except that 
c.keys and 
c.values are constructed
with uses-allocator construction (
[allocator.uses.construction])
. template<class Alloc>
  constexpr explicit flat_multimap(const Alloc& a);
template<class Alloc>
  constexpr flat_multimap(const key_compare& comp, const Alloc& a);
template<class Alloc>
  constexpr flat_multimap(const flat_multimap&, const Alloc& a);
template<class Alloc>
  constexpr flat_multimap(flat_multimap&&, const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_multimap(InputIterator first, InputIterator last, const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_multimap(InputIterator first, InputIterator last, const key_compare& comp,
                          const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last,
                          const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last,
                          const key_compare& comp, const Alloc& a);
template<container-compatible-range<value_type> R, class Alloc>
  constexpr flat_multimap(from_range_t, R&& rg, const Alloc& a);
template<container-compatible-range<value_type> R, class Alloc>
  constexpr flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Alloc& a);
template<class Alloc>
  constexpr flat_multimap(initializer_list<value_type> il, const Alloc& a);
template<class Alloc>
  constexpr flat_multimap(initializer_list<value_type> il, const key_compare& comp,
                          const Alloc& a);
template<class Alloc>
  constexpr flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const Alloc& a);
template<class Alloc>
  constexpr flat_multimap(sorted_equivalent_t, initializer_list<value_type> il,
                          const key_compare& comp, const Alloc& a);
Effects: Equivalent to the corresponding non-allocator constructors
except that 
c.keys and 
c.values are constructed
with uses-allocator construction (
[allocator.uses.construction])
. template<class Key, class T, class Compare, class KeyContainer, class MappedContainer,
         class Predicate>
  constexpr 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
.  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]
 
#include <compare>              
#include <initializer_list>     
namespace std {
  
  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>;
  
  template<class Key, class Compare, class KeyContainer, class Predicate>
    constexpr typename flat_set<Key, Compare, KeyContainer>::size_type
      erase_if(flat_set<Key, Compare, KeyContainer>& c, Predicate pred);
  
  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>;
  
  template<class Key, class Compare, class KeyContainer, class Predicate>
    constexpr typename flat_multiset<Key, Compare, KeyContainer>::size_type
      erase_if(flat_multiset<Key, Compare, KeyContainer>& c, Predicate pred);
}
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 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]
  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.[
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
.namespace std {
  template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>>
  class flat_set {
  public:
    
    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;  
    using const_iterator            = implementation-defined;  
    using reverse_iterator          = std::reverse_iterator<iterator>;
    using const_reverse_iterator    = std::reverse_iterator<const_iterator>;
    using container_type            = KeyContainer;
    
    constexpr flat_set() : flat_set(key_compare()) { }
    constexpr explicit flat_set(const key_compare& comp)
      : c(), compare(comp) { }
    constexpr explicit flat_set(container_type cont, const key_compare& comp = key_compare());
    constexpr flat_set(sorted_unique_t, container_type cont,
                       const key_compare& comp = key_compare())
      : c(std::move(cont)), compare(comp) { }
    template<class InputIterator>
      constexpr flat_set(InputIterator first, InputIterator last,
                         const key_compare& comp = key_compare())
        : c(), compare(comp)
        { insert(first, last); }
    template<class InputIterator>
      constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last,
               const key_compare& comp = key_compare())
        : c(first, last), compare(comp) { }
    template<container-compatible-range<value_type> R>
      constexpr flat_set(from_range_t, R&& rg)
        : flat_set(from_range, std::forward<R>(rg), key_compare()) { }
    template<container-compatible-range<value_type> R>
      constexpr flat_set(from_range_t, R&& rg, const key_compare& comp)
        : flat_set(comp)
        { insert_range(std::forward<R>(rg)); }
    constexpr flat_set(initializer_list<value_type> il, const key_compare& comp = key_compare())
        : flat_set(il.begin(), il.end(), comp) { }
    constexpr flat_set(sorted_unique_t, initializer_list<value_type> il,
             const key_compare& comp = key_compare())
        : flat_set(sorted_unique, il.begin(), il.end(), comp) { }
    
    template<class Alloc>
      constexpr explicit flat_set(const Alloc& a);
    template<class Alloc>
      constexpr flat_set(const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_set(const container_type& cont, const Alloc& a);
    template<class Alloc>
      constexpr flat_set(const container_type& cont, const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_set(sorted_unique_t, const container_type& cont, const Alloc& a);
    template<class Alloc>
      constexpr flat_set(sorted_unique_t, const container_type& cont,
                         const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_set(const flat_set&, const Alloc& a);
    template<class Alloc>
      constexpr flat_set(flat_set&&, const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_set(InputIterator first, InputIterator last, const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_set(InputIterator first, InputIterator last,
                         const key_compare& comp, const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last,
                         const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last,
                         const key_compare& comp, const Alloc& a);
    template<container-compatible-range<value_type> R, class Alloc>
      constexpr flat_set(from_range_t, R&& rg, const Alloc& a);
    template<container-compatible-range<value_type> R, class Alloc>
      constexpr flat_set(from_range_t, R&& rg, const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_set(initializer_list<value_type> il, const Alloc& a);
    template<class Alloc>
      constexpr flat_set(initializer_list<value_type> il, const key_compare& comp,
                         const Alloc& a);
    template<class Alloc>
      constexpr flat_set(sorted_unique_t, initializer_list<value_type> il, const Alloc& a);
    template<class Alloc>
      constexpr flat_set(sorted_unique_t, initializer_list<value_type> il,
                         const key_compare& comp, const Alloc& a);
    constexpr flat_set& operator=(initializer_list<value_type>);
    
    constexpr iterator               begin() noexcept;
    constexpr const_iterator         begin() const noexcept;
    constexpr iterator               end() noexcept;
    constexpr const_iterator         end() const noexcept;
    constexpr reverse_iterator       rbegin() noexcept;
    constexpr const_reverse_iterator rbegin() const noexcept;
    constexpr reverse_iterator       rend() noexcept;
    constexpr const_reverse_iterator rend() const noexcept;
    constexpr const_iterator         cbegin() const noexcept;
    constexpr const_iterator         cend() const noexcept;
    constexpr const_reverse_iterator crbegin() const noexcept;
    constexpr const_reverse_iterator crend() const noexcept;
    
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;
    
    template<class... Args> constexpr pair<iterator, bool> emplace(Args&&... args);
    template<class... Args>
      constexpr iterator emplace_hint(const_iterator position, Args&&... args);
    constexpr pair<iterator, bool> insert(const value_type& x)
      { return emplace(x); }
    constexpr pair<iterator, bool> insert(value_type&& x)
      { return emplace(std::move(x)); }
    template<class K> constexpr pair<iterator, bool> insert(K&& x);
    constexpr iterator insert(const_iterator position, const value_type& x)
      { return emplace_hint(position, x); }
    constexpr iterator insert(const_iterator position, value_type&& x)
      { return emplace_hint(position, std::move(x)); }
    template<class K> constexpr iterator insert(const_iterator hint, K&& x);
    template<class InputIterator>
      constexpr void insert(InputIterator first, InputIterator last);
    template<class InputIterator>
      constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last);
    template<container-compatible-range<value_type> R>
      constexpr void insert_range(R&& rg);
    constexpr void insert(initializer_list<value_type> il)
      { insert(il.begin(), il.end()); }
    constexpr void insert(sorted_unique_t, initializer_list<value_type> il)
      { insert(sorted_unique, il.begin(), il.end()); }
    constexpr container_type extract() &&;
    constexpr void replace(container_type&&);
    constexpr iterator erase(iterator position);
    constexpr iterator erase(const_iterator position);
    constexpr size_type erase(const key_type& x);
    template<class K> constexpr size_type erase(K&& x);
    constexpr iterator erase(const_iterator first, const_iterator last);
    constexpr void swap(flat_set& y) noexcept;
    constexpr void clear() noexcept;
    
    constexpr key_compare key_comp() const;
    constexpr value_compare value_comp() const;
    
    constexpr iterator find(const key_type& x);
    constexpr const_iterator find(const key_type& x) const;
    template<class K> constexpr iterator find(const K& x);
    template<class K> constexpr const_iterator find(const K& x) const;
    constexpr size_type count(const key_type& x) const;
    template<class K> constexpr size_type count(const K& x) const;
    constexpr bool contains(const key_type& x) const;
    template<class K> constexpr bool contains(const K& x) const;
    constexpr iterator lower_bound(const key_type& x);
    constexpr const_iterator lower_bound(const key_type& x) const;
    template<class K> constexpr iterator lower_bound(const K& x);
    template<class K> constexpr const_iterator lower_bound(const K& x) const;
    constexpr iterator upper_bound(const key_type& x);
    constexpr const_iterator upper_bound(const key_type& x) const;
    template<class K> constexpr iterator upper_bound(const K& x);
    template<class K> constexpr const_iterator upper_bound(const K& x) const;
    constexpr pair<iterator, iterator> equal_range(const key_type& x);
    constexpr pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
    template<class K>
      constexpr pair<iterator, iterator> equal_range(const K& x);
    template<class K>
      constexpr pair<const_iterator, const_iterator> equal_range(const K& x) const;
    friend constexpr bool operator==(const flat_set& x, const flat_set& y);
    friend constexpr synth-three-way-result<value_type>
      operator<=>(const flat_set& x, const flat_set& y);
    friend constexpr void swap(flat_set& x, flat_set& y) noexcept { x.swap(y); }
  private:
    container_type c;           
    key_compare compare;        
  };
  template<class KeyContainer, class Compare = less<typename KeyContainer::value_type>>
    flat_set(KeyContainer, Compare = Compare())
      -> flat_set<typename KeyContainer::value_type, Compare, KeyContainer>;
  template<class KeyContainer, class Allocator>
    flat_set(KeyContainer, Allocator)
      -> flat_set<typename KeyContainer::value_type,
                  less<typename KeyContainer::value_type>, KeyContainer>;
  template<class KeyContainer, class Compare, class Allocator>
    flat_set(KeyContainer, Compare, Allocator)
      -> flat_set<typename KeyContainer::value_type, Compare, KeyContainer>;
  template<class KeyContainer, class Compare = less<typename KeyContainer::value_type>>
    flat_set(sorted_unique_t, KeyContainer, Compare = Compare())
      -> flat_set<typename KeyContainer::value_type, Compare, KeyContainer>;
  template<class KeyContainer, class Allocator>
    flat_set(sorted_unique_t, KeyContainer, Allocator)
      -> flat_set<typename KeyContainer::value_type,
                  less<typename KeyContainer::value_type>, KeyContainer>;
  template<class KeyContainer, class Compare, class Allocator>
    flat_set(sorted_unique_t, KeyContainer, Compare, Allocator)
      -> flat_set<typename KeyContainer::value_type, Compare, KeyContainer>;
  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,
                  vector<ranges::range_value_t<R>,
                         alloc-rebind<Allocator, ranges::range_value_t<R>>>>;
  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>>,
                  vector<ranges::range_value_t<R>,
                         alloc-rebind<Allocator, 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>> { };
}
 constexpr explicit flat_set(container_type cont, const key_compare& comp = key_compare());
Effects: Initializes 
c with 
std::move(cont) and
compare with 
comp,
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 already sorted with respect to 
compare and
otherwise 
NlogN, where 
N is the value of 
cont.size() before this call
. The constructors in this subclause shall not participate in overload resolution
unless 
uses_allocator_v<container_type, Alloc> is 
true.template<class Alloc>
  constexpr flat_set(const container_type& cont, const Alloc& a);
template<class Alloc>
  constexpr flat_set(const container_type& cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to
flat_set(cont) and 
flat_set(cont, comp), respectively,
except that 
c is constructed with
uses-allocator construction (
[allocator.uses.construction])
. Complexity: Same as 
flat_set(cont) and 
flat_set(cont, comp), respectively
. template<class Alloc>
  constexpr flat_set(sorted_unique_t, const container_type& cont, const Alloc& a);
template<class Alloc>
  constexpr flat_set(sorted_unique_t, const container_type& cont,
                     const key_compare& comp, const Alloc& a);
Effects: Equivalent to
flat_set(sorted_unique, cont) and
flat_set(sorted_unique, cont,
comp), respectively,
except that 
c is constructed with
uses-allocator construction (
[allocator.uses.construction])
. template<class Alloc>
  constexpr explicit flat_set(const Alloc& a);
template<class Alloc>
  constexpr flat_set(const key_compare& comp, const Alloc& a);
template<class Alloc>
  constexpr flat_set(const flat_set&, const Alloc& a);
template<class Alloc>
  constexpr flat_set(flat_set&&, const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_set(InputIterator first, InputIterator last, const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_set(InputIterator first, InputIterator last, const key_compare& comp,
                     const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last, const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last,
                     const key_compare& comp, const Alloc& a);
template<container-compatible-range<value_type> R, class Alloc>
  constexpr flat_set(from_range_t, R&& rg, const Alloc& a);
template<container-compatible-range<value_type> R, class Alloc>
  constexpr flat_set(from_range_t, R&& rg, const key_compare& comp, const Alloc& a);
template<class Alloc>
  constexpr flat_set(initializer_list<value_type> il, const Alloc& a);
template<class Alloc>
  constexpr flat_set(initializer_list<value_type> il, const key_compare& comp, const Alloc& a);
template<class Alloc>
  constexpr flat_set(sorted_unique_t, initializer_list<value_type> il, const Alloc& a);
template<class Alloc>
  constexpr flat_set(sorted_unique_t, initializer_list<value_type> il,
                     const key_compare& comp, const Alloc& a);
Effects: Equivalent to the corresponding non-allocator constructors
except that 
c is constructed with
uses-allocator construction (
[allocator.uses.construction])
. template<class K> constexpr pair<iterator, bool> insert(K&& x);
template<class K> constexpr 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>
  constexpr 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 + 
MlogM, 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>
  constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last);
Effects: Equivalent to 
insert(first, last). 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 + 
MlogM, 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
. constexpr void swap(flat_set& y) noexcept;
Effects: Equivalent to:
ranges::swap(compare, y.compare);
ranges::swap(c, y.c);
Postconditions: 
*this is emptied, even if the function exits via an exception
. constexpr 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);
template<class Key, class Compare, class KeyContainer, class Predicate>
  constexpr typename flat_set<Key, Compare, KeyContainer>::size_type
    erase_if(flat_set<Key, Compare, KeyContainer>& c, Predicate pred);
Preconditions: 
Key meets the 
Cpp17MoveAssignable requirements
. Effects: Let 
E be 
bool(pred(as_const(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
.  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]
 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 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]
  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
. [
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.[
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
.namespace std {
  template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>>
  class flat_multiset {
  public:
    
    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;  
    using const_iterator            = implementation-defined;  
    using reverse_iterator          = std::reverse_iterator<iterator>;
    using const_reverse_iterator    = std::reverse_iterator<const_iterator>;
    using container_type            = KeyContainer;
    
    constexpr flat_multiset() : flat_multiset(key_compare()) { }
    constexpr explicit flat_multiset(const key_compare& comp)
      : c(), compare(comp) { }
    constexpr explicit flat_multiset(container_type cont,
                                     const key_compare& comp = key_compare());
    constexpr flat_multiset(sorted_equivalent_t, container_type cont,
                            const key_compare& comp = key_compare())
      : c(std::move(cont)), compare(comp) { }
    template<class InputIterator>
      constexpr flat_multiset(InputIterator first, InputIterator last,
                              const key_compare& comp = key_compare())
        : c(), compare(comp)
        { insert(first, last); }
    template<class InputIterator>
      constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last,
                              const key_compare& comp = key_compare())
        : c(first, last), compare(comp) { }
    template<container-compatible-range<value_type> R>
      constexpr flat_multiset(from_range_t, R&& rg)
        : flat_multiset(from_range, std::forward<R>(rg), key_compare()) { }
    template<container-compatible-range<value_type> R>
      constexpr flat_multiset(from_range_t, R&& rg, const key_compare& comp)
        : flat_multiset(comp)
        { insert_range(std::forward<R>(rg)); }
    constexpr flat_multiset(initializer_list<value_type> il,
                            const key_compare& comp = key_compare())
      : flat_multiset(il.begin(), il.end(), comp) { }
    constexpr flat_multiset(sorted_equivalent_t, initializer_list<value_type> il,
                            const key_compare& comp = key_compare())
        : flat_multiset(sorted_equivalent, il.begin(), il.end(), comp) { }
    
    template<class Alloc>
      constexpr explicit flat_multiset(const Alloc& a);
    template<class Alloc>
      constexpr flat_multiset(const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_multiset(const container_type& cont, const Alloc& a);
    template<class Alloc>
      constexpr flat_multiset(const container_type& cont, const key_compare& comp,
                              const Alloc& a);
    template<class Alloc>
      constexpr flat_multiset(sorted_equivalent_t, const container_type& cont, const Alloc& a);
    template<class Alloc>
      constexpr flat_multiset(sorted_equivalent_t, const container_type& cont,
                              const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_multiset(const flat_multiset&, const Alloc& a);
    template<class Alloc>
      constexpr flat_multiset(flat_multiset&&, const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_multiset(InputIterator first, InputIterator last, const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_multiset(InputIterator first, InputIterator last,
                              const key_compare& comp, const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last,
                              const Alloc& a);
    template<class InputIterator, class Alloc>
      constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last,
                              const key_compare& comp, const Alloc& a);
    template<container-compatible-range<value_type> R, class Alloc>
      constexpr flat_multiset(from_range_t, R&& rg, const Alloc& a);
    template<container-compatible-range<value_type> R, class Alloc>
      constexpr flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Alloc& a);
    template<class Alloc>
      constexpr flat_multiset(initializer_list<value_type> il, const Alloc& a);
    template<class Alloc>
      constexpr flat_multiset(initializer_list<value_type> il, const key_compare& comp,
                              const Alloc& a);
    template<class Alloc>
      constexpr flat_multiset(sorted_equivalent_t, initializer_list<value_type> il,
                              const Alloc& a);
    template<class Alloc>
      constexpr flat_multiset(sorted_equivalent_t, initializer_list<value_type> il,
                              const key_compare& comp, const Alloc& a);
    constexpr flat_multiset& operator=(initializer_list<value_type>);
    
    constexpr iterator               begin() noexcept;
    constexpr const_iterator         begin() const noexcept;
    constexpr iterator               end() noexcept;
    constexpr const_iterator         end() const noexcept;
    constexpr reverse_iterator       rbegin() noexcept;
    constexpr const_reverse_iterator rbegin() const noexcept;
    constexpr reverse_iterator       rend() noexcept;
    constexpr const_reverse_iterator rend() const noexcept;
    constexpr const_iterator         cbegin() const noexcept;
    constexpr const_iterator         cend() const noexcept;
    constexpr const_reverse_iterator crbegin() const noexcept;
    constexpr const_reverse_iterator crend() const noexcept;
    
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;
    
    template<class... Args> constexpr iterator emplace(Args&&... args);
    template<class... Args>
      constexpr iterator emplace_hint(const_iterator position, Args&&... args);
    constexpr iterator insert(const value_type& x)
      { return emplace(x); }
    constexpr iterator insert(value_type&& x)
      { return emplace(std::move(x)); }
    constexpr iterator insert(const_iterator position, const value_type& x)
      { return emplace_hint(position, x); }
    constexpr iterator insert(const_iterator position, value_type&& x)
      { return emplace_hint(position, std::move(x)); }
    template<class InputIterator>
      constexpr void insert(InputIterator first, InputIterator last);
    template<class InputIterator>
      constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last);
    template<container-compatible-range<value_type> R>
      constexpr void insert_range(R&& rg);
    constexpr void insert(initializer_list<value_type> il)
      { insert(il.begin(), il.end()); }
    constexpr void insert(sorted_equivalent_t, initializer_list<value_type> il)
      { insert(sorted_equivalent, il.begin(), il.end()); }
    constexpr container_type extract() &&;
    constexpr void replace(container_type&&);
    constexpr iterator erase(iterator position);
    constexpr iterator erase(const_iterator position);
    constexpr size_type erase(const key_type& x);
    template<class K> constexpr size_type erase(K&& x);
    constexpr iterator erase(const_iterator first, const_iterator last);
    constexpr void swap(flat_multiset& y) noexcept;
    constexpr void clear() noexcept;
    
    constexpr key_compare key_comp() const;
    constexpr value_compare value_comp() const;
    
    constexpr iterator find(const key_type& x);
    constexpr const_iterator find(const key_type& x) const;
    template<class K> constexpr iterator find(const K& x);
    template<class K> constexpr const_iterator find(const K& x) const;
    constexpr size_type count(const key_type& x) const;
    template<class K> constexpr size_type count(const K& x) const;
    constexpr bool contains(const key_type& x) const;
    template<class K> constexpr bool contains(const K& x) const;
    constexpr iterator lower_bound(const key_type& x);
    constexpr const_iterator lower_bound(const key_type& x) const;
    template<class K> constexpr iterator lower_bound(const K& x);
    template<class K> constexpr const_iterator lower_bound(const K& x) const;
    constexpr iterator upper_bound(const key_type& x);
    constexpr const_iterator upper_bound(const key_type& x) const;
    template<class K> constexpr iterator upper_bound(const K& x);
    template<class K> constexpr const_iterator upper_bound(const K& x) const;
    constexpr pair<iterator, iterator> equal_range(const key_type& x);
    constexpr pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
    template<class K>
      constexpr pair<iterator, iterator> equal_range(const K& x);
    template<class K>
      constexpr pair<const_iterator, const_iterator> equal_range(const K& x) const;
    friend constexpr bool operator==(const flat_multiset& x, const flat_multiset& y);
    friend constexpr synth-three-way-result<value_type>
      operator<=>(const flat_multiset& x, const flat_multiset& y);
    friend constexpr void swap(flat_multiset& x, flat_multiset& y) noexcept
      { x.swap(y); }
  private:
    container_type c;           
    key_compare compare;        
  };
  template<class KeyContainer, class Compare = less<typename KeyContainer::value_type>>
    flat_multiset(KeyContainer, Compare = Compare())
      -> flat_multiset<typename KeyContainer::value_type, Compare, KeyContainer>;
  template<class KeyContainer, class Allocator>
    flat_multiset(KeyContainer, Allocator)
      -> flat_multiset<typename KeyContainer::value_type,
                       less<typename KeyContainer::value_type>, KeyContainer>;
  template<class KeyContainer, class Compare, class Allocator>
    flat_multiset(KeyContainer, Compare, Allocator)
      -> flat_multiset<typename KeyContainer::value_type, Compare, KeyContainer>;
  template<class KeyContainer, class Compare = less<typename KeyContainer::value_type>>
    flat_multiset(sorted_equivalent_t, KeyContainer, Compare = Compare())
      -> flat_multiset<typename KeyContainer::value_type, Compare, KeyContainer>;
  template<class KeyContainer, class Allocator>
    flat_multiset(sorted_equivalent_t, KeyContainer, Allocator)
      -> flat_multiset<typename KeyContainer::value_type,
                       less<typename KeyContainer::value_type>, KeyContainer>;
  template<class KeyContainer, class Compare, class Allocator>
    flat_multiset(sorted_equivalent_t, KeyContainer, Compare, Allocator)
      -> flat_multiset<typename KeyContainer::value_type, Compare, KeyContainer>;
  template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>>
    flat_multiset(InputIterator, InputIterator, Compare = Compare())
      -> flat_multiset<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>, 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,
                       vector<ranges::range_value_t<R>,
                              alloc-rebind<Allocator, ranges::range_value_t<R>>>>;
  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>>,
                       vector<ranges::range_value_t<R>,
                              alloc-rebind<Allocator, 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>> { };
}
 constexpr explicit flat_multiset(container_type cont, const key_compare& comp = key_compare());
Effects: Initializes 
c with 
std::move(cont) and
compare with 
comp, and
sorts the range [
begin(), end()) with respect to 
compare. Complexity: Linear in 
N if 
cont is already sorted with respect to 
compare and
otherwise 
NlogN, where 
N is the value of 
cont.size() before this call
. The constructors in this subclause shall not participate in overload resolution
unless 
uses_allocator_v<container_type, Alloc> is 
true.template<class Alloc>
  constexpr flat_multiset(const container_type& cont, const Alloc& a);
template<class Alloc>
  constexpr flat_multiset(const container_type& cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to 
flat_multiset(cont) and
flat_multiset(cont, comp), respectively,
except that 
c is constructed with
uses-allocator construction (
[allocator.uses.construction])
. Complexity: Same as 
flat_multiset(cont) and
flat_multiset(cont, comp), respectively
. template<class Alloc>
  constexpr flat_multiset(sorted_equivalent_t, const container_type& cont, const Alloc& a);
template<class Alloc>
  constexpr flat_multiset(sorted_equivalent_t, const container_type& cont,
                          const key_compare& comp, const Alloc& a);
Effects: Equivalent to 
flat_multiset(sorted_equivalent, cont) and
flat_multiset(sorted_equivalent, cont, comp), respectively,
except that 
c is constructed with
uses-allocator construction (
[allocator.uses.construction])
. template<class Alloc>
  constexpr explicit flat_multiset(const Alloc& a);
template<class Alloc>
  constexpr flat_multiset(const key_compare& comp, const Alloc& a);
template<class Alloc>
  constexpr flat_multiset(const flat_multiset&, const Alloc& a);
template<class Alloc>
  constexpr flat_multiset(flat_multiset&&, const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_multiset(InputIterator first, InputIterator last, const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_multiset(InputIterator first, InputIterator last,
                          const key_compare& comp, const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last,
                          const Alloc& a);
template<class InputIterator, class Alloc>
  constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last,
                          const key_compare& comp, const Alloc& a);
template<container-compatible-range<value_type> R, class Alloc>
  constexpr flat_multiset(from_range_t, R&& rg, const Alloc& a);
template<container-compatible-range<value_type> R, class Alloc>
  constexpr flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Alloc& a);
template<class Alloc>
  constexpr flat_multiset(initializer_list<value_type> il, const Alloc& a);
template<class Alloc>
  constexpr flat_multiset(initializer_list<value_type> il, const key_compare& comp,
                          const Alloc& a);
template<class Alloc>
  constexpr flat_multiset(sorted_equivalent_t, initializer_list<value_type> il, const Alloc& a);
template<class Alloc>
  constexpr flat_multiset(sorted_equivalent_t, initializer_list<value_type> il,
                          const key_compare& comp, const Alloc& a);
Effects: Equivalent to the corresponding non-allocator constructors
except that 
c is constructed with
uses-allocator construction (
[allocator.uses.construction])
. template<class... Args> constexpr iterator emplace(Args&&... args);
Constraints: 
is_constructible_v<value_type, Args...> is 
true. Effects: First, initializes an object t of type value_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>
  constexpr 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 + 
MlogM, 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>
  constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last);
Effects: Equivalent to 
insert(first, last). constexpr void swap(flat_multiset& y) noexcept;
Effects: Equivalent to:
ranges::swap(compare, y.compare);
ranges::swap(c, y.c);
Postconditions: 
*this is emptied, even if the function exits via an exception
. constexpr void replace(container_type&& cont);
Preconditions: The elements of 
cont are sorted with respect to 
compare. Effects: Equivalent to: c = std::move(cont);
template<class Key, class Compare, class KeyContainer, class Predicate>
  constexpr typename flat_multiset<Key, Compare, KeyContainer>::size_type
    erase_if(flat_multiset<Key, Compare, KeyContainer>& c, Predicate pred);
Preconditions: 
Key meets the 
Cpp17MoveAssignable requirements
. Effects: Let 
E be 
bool(pred(as_const(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
.  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]