%!TEX root = std.tex
\rSec0[containers]{Containers library}

\rSec1[containers.general]{General}

\pnum
This Clause describes components that \Cpp{} programs may use to
organize collections of information.

\pnum
The following subclauses describe
container requirements,
and components for
sequence containers and
associative containers,
as summarized in
\tref{containers.summary}.

\begin{libsumtab}{Containers library summary}{containers.summary}
\ref{container.requirements} & Requirements                     &                           \\ \rowsep
\ref{sequences}              & Sequence containers              &
  \tcode{<array>}, \tcode{<deque>}, \tcode{<forward_list>},
  \tcode{<hive>}, \\ & &
  \tcode{<inplace_vector>}, \tcode{<list>}, \tcode{<vector>} \\ \rowsep
\ref{associative}            & Associative containers           &
  \tcode{<map>}, \tcode{<set>}     \\ \rowsep
\ref{unord}                  & Unordered associative containers &
  \tcode{<unordered_map>}, \tcode{<unordered_set>}    \\ \rowsep
\ref{container.adaptors}     & Container adaptors               &
  \tcode{<queue>}, \tcode{<stack>}, \tcode{<flat_map>}, \tcode{<flat_set>}  \\ \rowsep
\ref{views}                  & Views                            &
  \tcode{<span>}, \tcode{<mdspan>} \\
\end{libsumtab}

\rSec1[container.requirements]{Requirements}%
\indextext{requirements!container}

\rSec2[container.requirements.pre]{Preamble}

\pnum
Containers are objects that store other objects.
They control allocation and deallocation of these objects
through constructors, destructors, insert and erase operations.

\pnum
All of the complexity requirements in this Clause are stated solely
in terms of the number of operations on the contained objects.
\begin{example}
The copy constructor of type
\tcode{vector<vector<int>>}
has linear complexity,
even though the complexity of copying each contained
\tcode{vector<int>}
is itself linear.
\end{example}

\pnum
Allocator-aware containers\iref{container.alloc.reqmts}
other than \tcode{basic_string} construct elements using the function
\tcode{allocator_traits<allocator_type>::rebind_traits<U>::\brk{}construct}
and destroy elements using the function
\tcode{allocator_traits<allocator_type>::rebind_traits<U>::\brk{}destroy}\iref{allocator.traits.members},
where \tcode{U} is either \tcode{allocator_type::value_type} or
an internal type used by the container.
These functions are called only for the
container's element type, not for internal types used by the container.
\begin{note}
This
means, for example, that a node-based container would need to construct nodes containing
aligned buffers and call \tcode{construct} to place the element into the buffer.
\end{note}

\rSec2[container.requirements.general]{General containers}

\rSec3[container.intro.reqmts]{Introduction}

\pnum
In \ref{container.requirements.general},
\begin{itemize}
\item
\tcode{X} denotes a container class containing objects of type \tcode{T},
\item
\tcode{a} denotes a value of type \tcode{X},
\item
\tcode{b} and \tcode{c} denote values of type (possibly const) \tcode{X},
\item
\tcode{i} and \tcode{j} denote values of type (possibly const) \tcode{X::iterator},
\item
\tcode{u} denotes an identifier,
\item
\tcode{v} denotes an lvalue of type (possibly const) \tcode{X} or
an rvalue of type \tcode{const X},
\item
\tcode{s} and \tcode{t} denote non-const lvalues of type \tcode{X}, and
\item
\tcode{rv} denotes a non-const rvalue of type \tcode{X}.
\end{itemize}

\pnum
The following exposition-only concept is used in the definition of containers:
\begin{codeblock}
template<class R, class T>
concept @\defexposconcept{container-compatible-range}@ =    // \expos
  ranges::@\libconcept{input_range}@<R> && @\libconcept{convertible_to}@<ranges::range_reference_t<R>, T>;
\end{codeblock}

\rSec3[container.reqmts]{Container requirements}

% Local command to index names as members of all containers.
\newcommand{\indexcont}[1]{%
\indexlibrarymisc{\idxcode{#1}}{containers}%
\indexlibrarymemberx{array}{#1}%
\indexlibrarymemberx{deque}{#1}%
\indexlibrarymemberx{forward_list}{#1}%
\indexlibrarymemberx{hive}{#1}%
\indexlibrarymemberx{list}{#1}%
\indexlibrarymemberx{vector}{#1}%
\indexlibrarymemberx{inplace_vector}{#1}%
\indexlibrarymemberx{map}{#1}%
\indexlibrarymemberx{set}{#1}%
\indexlibrarymemberx{multiset}{#1}%
\indexlibrarymemberx{multimap}{#1}%
\indexlibrarymemberx{unordered_map}{#1}%
\indexlibrarymemberx{unordered_set}{#1}%
\indexlibrarymemberx{unordered_multiset}{#1}%
\indexlibrarymemberx{unordered_multimap}{#1}%
\indexlibrarymemberx{flat_map}{#1}%
\indexlibrarymemberx{flat_set}{#1}%
\indexlibrarymemberx{flat_multiset}{#1}%
\indexlibrarymemberx{flat_multimap}{#1}%
}

\pnum
A type \tcode{X} meets the \defn{container} requirements
if the following types, statements, and expressions are well-formed and
have the specified semantics.

\indexcont{value_type}%
\begin{itemdecl}
typename X::value_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{T}

\pnum
\expects
\tcode{T} is \oldconcept{Erasable} from \tcode{X}
(see~\ref{container.alloc.reqmts}, below).
\end{itemdescr}

\indexcont{reference}%
\begin{itemdecl}
typename X::reference
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{T\&}
\end{itemdescr}

\indexcont{const_reference}%
\begin{itemdecl}
typename X::const_reference
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const T\&}
\end{itemdescr}

\indexcont{iterator}%
\begin{itemdecl}
typename X::iterator
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A type that meets the forward iterator requirements\iref{forward.iterators}
with value type \tcode{T}.
The type \tcode{X::iterator} is convertible to \tcode{X::const_iterator}.
\end{itemdescr}

\indexcont{const_iterator}%
\begin{itemdecl}
typename X::const_iterator
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A type that meets the requirements of a constant iterator and
those of a forward iterator with value type \tcode{T}.
\end{itemdescr}

\indexcont{difference_type}%
\begin{itemdecl}
typename X::difference_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A signed integer type,
identical to the difference type of
\tcode{X::iterator} and \tcode{X::const_iterator}.
\end{itemdescr}

\indexcont{size_type}%
\begin{itemdecl}
typename X::size_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
An unsigned integer type
that can represent any non-negative value of \tcode{X::difference_type}.
\end{itemdescr}

\begin{itemdecl}
X u;
X u = X();
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{u.empty()}

\pnum
\complexity
Constant.
\end{itemdescr}

\begin{itemdecl}
X u(v);
X u = v;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X} (see below).

\pnum
\ensures
\tcode{u == v}.

\pnum
\complexity
Linear.
\end{itemdescr}

\begin{itemdecl}
X u(rv);
X u = rv;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{u} is equal to the value that \tcode{rv} had before this construction.

\pnum
\complexity
Linear for \tcode{array} and \tcode{inplace_vector} and constant for all other standard containers.
\end{itemdescr}

\indexcont{operator=}%
\begin{itemdecl}
t = v
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{X\&}.

\pnum
\ensures
\tcode{t == v}.

\pnum
\complexity
Linear.
\end{itemdescr}

\begin{itemdecl}
t = rv
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{X\&}.

\pnum
\effects
All existing elements of \tcode{t} are either move assigned to or destroyed.

\pnum
\ensures
If \tcode{t} and \tcode{rv} do not refer to the same object,
\tcode{t} is equal to the value that \tcode{rv} had before this assignment.

\pnum
\complexity
Linear.
\end{itemdescr}

\begin{itemdecl}
a.~X()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}.

\pnum
\effects
Destroys every element of \tcode{a}; any memory obtained is deallocated.

\pnum
\complexity
Linear.
\end{itemdescr}

\indexcont{begin}%
\begin{itemdecl}
b.begin()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_iterator} if \tcode{b} is of type \tcode{const X};
\tcode{iterator} otherwise.

\pnum
\returns
An iterator referring to the first element in the container.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexcont{end}%
\begin{itemdecl}
b.end()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_iterator} if \tcode{b} is of type \tcode{const X};
\tcode{iterator} otherwise.

\pnum
\returns
An iterator which is the past-the-end value for the container.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexcont{cbegin}%
\begin{itemdecl}
b.cbegin()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_iterator}.

\pnum
\returns
\tcode{const_cast<X const\&>(b).begin()}

\pnum
\complexity
Constant.
\end{itemdescr}

\indexcont{cend}%
\begin{itemdecl}
b.cend()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_iterator}.

\pnum
\returns
\tcode{const_cast<X const\&>(b).end()}

\pnum
\complexity
Constant.
\end{itemdescr}

\begin{itemdecl}
i <=> j
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{strong_ordering}.

\pnum
\constraints
\tcode{X::iterator} meets the random access iterator requirements.

\pnum
\complexity
Constant.
\end{itemdescr}

% hive is excluded here
\indexlibrarymisc{\idxcode{operator==}}{containers}%
\indexlibrarymemberx{array}{operator==}%
\indexlibrarymemberx{deque}{operator==}%
\indexlibrarymemberx{forward_list}{operator==}%
\indexlibrarymemberx{list}{operator==}%
\indexlibrarymemberx{vector}{operator==}%
\indexlibrarymemberx{inplace_vector}{operator==}%
\indexlibrarymemberx{map}{operator==}%
\indexlibrarymemberx{set}{operator==}%
\indexlibrarymemberx{multiset}{operator==}%
\indexlibrarymemberx{multimap}{operator==}%
\indexlibrarymemberx{unordered_map}{operator==}%
\indexlibrarymemberx{unordered_set}{operator==}%
\indexlibrarymemberx{unordered_multiset}{operator==}%
\indexlibrarymemberx{unordered_multimap}{operator==}%
\indexlibrarymemberx{flat_map}{operator==}%
\indexlibrarymemberx{flat_set}{operator==}%
\indexlibrarymemberx{flat_multiset}{operator==}%
\indexlibrarymemberx{flat_multimap}{operator==}%
\begin{itemdecl}
c == b
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} meets the \oldconcept{EqualityComparable} requirements.

\pnum
\result
\tcode{bool}.

\pnum
\returns
\tcode{equal(c.begin(), c.end(), b.begin(), b.end())}

\begin{note}
The algorithm \tcode{equal} is defined in \ref{alg.equal}.
\end{note}

\pnum
\complexity
Constant if \tcode{c.size() != b.size()}, linear otherwise.

\pnum
\remarks
\tcode{==} is an equivalence relation.
\end{itemdescr}

% hive is excluded here
\indexlibrarymisc{\idxcode{operator"!=}}{containers}%
\indexlibrarymemberx{array}{operator"!=}%
\indexlibrarymemberx{deque}{operator"!=}%
\indexlibrarymemberx{forward_list}{operator"!=}%
\indexlibrarymemberx{list}{operator"!=}%
\indexlibrarymemberx{vector}{operator"!=}%
\indexlibrarymemberx{inplace_vector}{operator"!=}%
\indexlibrarymemberx{map}{operator"!=}%
\indexlibrarymemberx{set}{operator"!=}%
\indexlibrarymemberx{multiset}{operator"!=}%
\indexlibrarymemberx{multimap}{operator"!=}%
\indexlibrarymemberx{unordered_map}{operator"!=}%
\indexlibrarymemberx{unordered_set}{operator"!=}%
\indexlibrarymemberx{unordered_multiset}{operator"!=}%
\indexlibrarymemberx{unordered_multimap}{operator"!=}%
\indexlibrarymemberx{flat_map}{operator"!=}%
\indexlibrarymemberx{flat_set}{operator"!=}%
\indexlibrarymemberx{flat_multiset}{operator"!=}%
\indexlibrarymemberx{flat_multimap}{operator"!=}%
\begin{itemdecl}
c != b
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{!(c == b)}.
\end{itemdescr}

\indexcont{swap}%
\begin{itemdecl}
t.swap(s)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}.

\pnum
\effects
Exchanges the contents of \tcode{t} and \tcode{s}.

\pnum
\complexity
Linear for \tcode{array} and \tcode{inplace_vector}, and
constant for all other standard containers.
\end{itemdescr}

\begin{itemdecl}
swap(t, s)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{t.swap(s)}.
\end{itemdescr}

\indexcont{size}%
\begin{itemdecl}
c.size()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}.

\pnum
\returns
\tcode{distance(c.begin(), c.end())},
i.e., the number of elements in the container.

\pnum
\complexity
Constant.

\pnum
\remarks
The number of elements is defined by the rules of
constructors, inserts, and erases.
\end{itemdescr}

\indexcont{max_size}%
\begin{itemdecl}
c.max_size()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}.

\pnum
\returns
\tcode{distance(begin(), end())} for the largest possible container.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexcont{empty}%
\begin{itemdecl}
c.empty()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{bool}.

\pnum
\returns
\tcode{c.begin() == c.end()}

\pnum
\complexity
Constant.

\pnum
\remarks
If the container is empty, then \tcode{c.empty()} is \tcode{true}.
\end{itemdescr}

\pnum
In the expressions
\begin{codeblock}
i == j
i != j
i < j
i <= j
i >= j
i > j
i <=> j
i - j
\end{codeblock}
where \tcode{i} and \tcode{j} denote objects of a container's \tcode{iterator}
type, either or both may be replaced by an object of the container's
\tcode{const_iterator} type referring to the same element with no change in semantics.

\pnum
Unless otherwise specified, all containers defined in this Clause obtain memory
using an allocator (see~\ref{allocator.requirements}).
\begin{note}
In particular, containers and iterators do not store references
to allocated elements other than through the allocator's pointer type,
i.e., as objects of type \tcode{P} or
\tcode{pointer_traits<P>::template re\-bind<\unspec>},
where \tcode{P} is \tcode{allocator_traits<allocator_type>::pointer}.
\end{note}
Copy constructors for these container types obtain an allocator by calling
\tcode{allocator_traits<allocator_type>::select_on_container_copy_construction}
on the allocator belonging to the container being copied.
Move constructors obtain an allocator by move construction from the allocator belonging to
the container being moved. Such move construction of the allocator shall not exit via an
exception.
All other constructors for these container types take a
\tcode{const allocator_type\&} argument.
\begin{note}
If an invocation of a constructor uses the default value of an optional
allocator argument, then the allocator type must support value-initialization.
\end{note}
A copy of this allocator is used for any memory allocation and element construction
performed, by these constructors and by all other member functions,
during the lifetime of each container object
or until the allocator is replaced. The allocator may be replaced only via assignment or
\tcode{swap()}. Allocator replacement is performed by
copy assignment, move assignment, or swapping of the allocator only if
\begin{itemize}
\item \tcode{allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value},
\item \tcode{allocator_traits<allocator_type>::propagate_on_container_move_assignment::value},
or
\item \tcode{allocator_traits<allocator_type>::propagate_on_container_swap::value}
\end{itemize}
is \tcode{true}
within the implementation of the corresponding container operation.
In all container types defined in this Clause, the member \tcode{get_allocator()}
returns a copy of the allocator used to construct the container or, if that allocator
has been replaced, a copy of the most recent replacement.

\pnum
The expression \tcode{a.swap(b)}, for containers \tcode{a} and \tcode{b} of a standard
container type other than \tcode{array} and \tcode{inplace_vector},
shall exchange the values of \tcode{a} and
\tcode{b} without invoking any move, copy, or swap operations on the individual
container elements.
Any \tcode{Compare}, \tcode{Pred}, or \tcode{Hash} types
belonging to \tcode{a} and \tcode{b} shall meet the \oldconcept{Swappable} requirements
and shall be exchanged by calling \tcode{swap}
as described in~\ref{swappable.requirements}. If
\tcode{allocator_traits<allocator_type>::propagate_on_container_swap::value} is
\tcode{true}, then
\tcode{allocator_type} shall meet the \oldconcept{Swap\-pable} requirements and
the allocators of \tcode{a} and \tcode{b} shall also be exchanged
by calling \tcode{swap} as described in~\ref{swappable.requirements}.
Otherwise, the allocators shall not be swapped, and the behavior is
undefined unless \tcode{a.get_allocator() == b.get_allocator()}. Every iterator
referring to an element in one container before the swap shall refer to the same
element in the other container after the swap. It is unspecified whether an iterator
with value \tcode{a.end()} before the swap will have value \tcode{b.end()} after the
swap.

\pnum
Unless otherwise specified (see~\ref{associative.reqmts.except}, \ref{unord.req.except}, \ref{deque.modifiers}, \ref{inplace.vector.modifiers}, and
\ref{vector.modifiers})
all container types defined in this Clause meet
the following additional requirements:

\begin{itemize}
\item
If an exception is thrown by an
\tcode{insert()} or \tcode{emplace()}
function while inserting a single element, that
function has no effects.
\item
If an exception is thrown by a
\tcode{push_back()},
\tcode{push_front()},
\tcode{emplace_back()}, or \tcode{emplace_front()}
function, that function has no effects.
\item
No
\tcode{erase()},
\tcode{clear()},
\tcode{pop_back()}
or
\tcode{pop_front()}
function throws an exception.
\item
No copy constructor or assignment operator of a returned iterator
throws an exception.
\item
No
\tcode{swap()}
function throws an exception.
\item
No
\tcode{swap()}
function invalidates any references,
pointers, or iterators referring to the elements
of the containers being swapped.
\begin{note}
The \tcode{end()} iterator does not refer to any element, so it can be invalidated.
\end{note}
\end{itemize}

\pnum
Unless otherwise specified (either explicitly or by defining a
function in terms of other functions), invoking a container member
function or passing a container as an argument to a library function
shall not invalidate iterators to, or change the values of, objects
within that container.

\pnum
A \defnadj{contiguous}{container}
is a container
whose member types \tcode{iterator} and \tcode{const_iterator}
meet the
\oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators} and
model \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}.

\pnum
The behavior of certain container member functions and deduction guides
depends on whether types qualify as input iterators or allocators.
The extent to which an implementation determines that a type cannot be an input
iterator is unspecified, except that as a minimum integral types shall not qualify
as input iterators.
Likewise, the extent to which an implementation determines that a type cannot be
an allocator is unspecified, except that as a minimum a type \tcode{A} shall not qualify
as an allocator unless it meets both of the following conditions:

\begin{itemize}
\item The \grammarterm{qualified-id} \tcode{A::value_type}
is valid and denotes a type\iref{temp.deduct}.

\item The expression \tcode{declval<A\&>().allocate(size_t\{\})}
is well-formed when treated as an unevaluated operand.
\end{itemize}

\rSec3[container.rev.reqmts]{Reversible container requirements}

% Local command to index names as members of all containers.
\renewcommand{\indexcont}[1]{%
\indexlibrarymisc{\idxcode{#1}}{reversible containers}%
\indexlibrarymemberx{array}{#1}%
\indexlibrarymemberx{deque}{#1}%
\indexlibrarymemberx{hive}{#1}%
\indexlibrarymemberx{list}{#1}%
\indexlibrarymemberx{vector}{#1}%
\indexlibrarymemberx{inplace_vector}{#1}%
\indexlibrarymemberx{map}{#1}%
\indexlibrarymemberx{set}{#1}%
\indexlibrarymemberx{multiset}{#1}%
\indexlibrarymemberx{multimap}{#1}%
\indexlibrarymemberx{unordered_map}{#1}%
\indexlibrarymemberx{unordered_set}{#1}%
\indexlibrarymemberx{unordered_multiset}{#1}%
\indexlibrarymemberx{unordered_multimap}{#1}%
\indexlibrarymemberx{flat_map}{#1}%
\indexlibrarymemberx{flat_set}{#1}%
\indexlibrarymemberx{flat_multiset}{#1}%
\indexlibrarymemberx{flat_multimap}{#1}%
}

\pnum
A type \tcode{X} meets the \defnadj{reversible}{container} requirements if
\tcode{X} meets the container requirements,
the iterator type of \tcode{X} belongs to the
bidirectional or random access iterator categories\iref{iterator.requirements},
and
the following types and expressions are well-formed and have
the specified semantics.

\indexcont{reverse_iterator}%
\begin{itemdecl}
typename X::reverse_iterator
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
The type \tcode{reverse_iterator<X::iterator>},
an iterator type whose value type is \tcode{T}.
\end{itemdescr}

\indexcont{const_reverse_iterator}%
\begin{itemdecl}
typename X::const_reverse_iterator
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
The type \tcode{reverse_iterator<X::const_iterator>},
a constant iterator type whose value type is \tcode{T}.
\end{itemdescr}

\indexcont{rbegin}%
\begin{itemdecl}
a.rbegin()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_reverse_iterator} if \tcode{a} is of type \tcode{const X};
\tcode{reverse_iterator} otherwise.

\pnum
\returns
\tcode{reverse_iterator(end())}

\pnum
\complexity
Constant.
\end{itemdescr}

\indexcont{rend}%
\begin{itemdecl}
a.rend()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_reverse_iterator} if \tcode{a} is of type \tcode{const X};
\tcode{reverse_iterator} otherwise.

\pnum
\returns
\tcode{reverse_iterator(begin())}

\pnum
\complexity
Constant.
\end{itemdescr}

\indexcont{crbegin}%
\begin{itemdecl}
a.crbegin()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_reverse_iterator}.

\pnum
\returns
\tcode{\keyword{const_cast}<X \keyword{const}\&>(a).rbegin()}

\pnum
\complexity
Constant.
\end{itemdescr}

\indexcont{crend}%
\begin{itemdecl}
a.crend()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_reverse_iterator}.

\pnum
\returns
\tcode{\keyword{const_cast}<X \keyword{const}\&>(a).rend()}

\pnum
\complexity
Constant.
\end{itemdescr}


\rSec3[container.opt.reqmts]{Optional container requirements}

\pnum
The following operations are provided
for some types of containers but not others. Those containers for which the
listed operations are provided shall implement the semantics as described
unless otherwise stated.
If the iterators passed to \tcode{lexicographical_compare_three_way}
meet the constexpr iterator requirements\iref{iterator.requirements.general}
then the operations described below
are implemented by constexpr functions.

% Local command to index a name as a member of all containers.
\renewcommand{\indexcont}[1]{%
\indexlibrarymisc{\idxcode{#1}}{optional container requirements}%
\indexlibrarymemberx{array}{#1}%
\indexlibrarymemberx{deque}{#1}%
\indexlibrarymemberx{forward_list}{#1}%
\indexlibrarymemberx{list}{#1}%
\indexlibrarymemberx{vector}{#1}%
\indexlibrarymemberx{map}{#1}%
\indexlibrarymemberx{set}{#1}%
\indexlibrarymemberx{multiset}{#1}%
\indexlibrarymemberx{multimap}{#1}%
\indexlibrarymemberx{flat_map}{#1}%
\indexlibrarymemberx{flat_set}{#1}%
\indexlibrarymemberx{flat_multiset}{#1}%
\indexlibrarymemberx{flat_multimap}{#1}%
\indexlibrarymemberx{basic_string}{#1}%
}

\indexcont{operator<=>}%
\begin{itemdecl}
a <=> b
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{\exposid{synth-three-way-result}<X::value_type>}.

\pnum
\expects
Either \tcode{T} models \libconcept{three_way_comparable},
or \tcode{<} is defined for values of type (possibly const) \tcode{T} and
\tcode{<} is a total ordering relationship.

\pnum
\returns
\tcode{lexicographical_compare_three_way(a.begin(), a.end(),
b.begin(), b.end(),\newline \exposidnc{synth-three-way})}
\begin{note}
The algorithm \tcode{lexicographical_compare_three_way}
is defined in \ref{algorithms}.
\end{note}

\pnum
\complexity
Linear.
\end{itemdescr}

\rSec3[container.alloc.reqmts]{Allocator-aware containers}

\pnum
Except for \tcode{array} and \tcode{inplace_vector},
all of the containers defined in \ref{containers},
\ref{stacktrace.basic}, \ref{basic.string}, and \ref{re.results}
meet the additional requirements of an \defnadj{allocator-aware}{container},
as described below.

\pnum
Given an allocator type \tcode{A}
and given a container type \tcode{X} having a \tcode{value_type} identical to \tcode{T}
and an \tcode{allocator_type} identical to \tcode{allocator_traits<A>::rebind_alloc<T>}
and given an lvalue \tcode{m} of type \tcode{A},
a pointer \tcode{p} of type \tcode{T*},
an expression \tcode{v} that denotes
an lvalue of type \tcode{T} or \tcode{const T} or
an rvalue of type \tcode{const T},
and an rvalue \tcode{rv} of type \tcode{T},
the following terms are defined. If \tcode{X}
is not allocator-aware or is a specialization of \tcode{basic_string},
the terms below are defined as if \tcode{A} were
\tcode{allocator<T>} --- no allocator object needs to be created
and user specializations of \tcode{allocator<T>} are not instantiated:

\begin{itemize}
\item
\tcode{T} is \defnx{\oldconcept{DefaultInsertable} into \tcode{X}}
{\oldconceptname{DefaultInsertable} into X@\oldconcept{DefaultInsertable} into \tcode{X}}
means that the following expression is well-formed:
\begin{codeblock}
allocator_traits<A>::construct(m, p)
\end{codeblock}

\item
An element of \tcode{X} is \defn{default-inserted} if it is initialized
by evaluation of the expression
\begin{codeblock}
allocator_traits<A>::construct(m, p)
\end{codeblock}
where \tcode{p} is the address of the uninitialized storage for the element
allocated within \tcode{X}.

\item
\tcode{T} is \defnx{\oldconcept{MoveInsertable} into \tcode{X}}
{\oldconceptname{MoveInsertable} into X@\oldconcept{MoveInsertable} into \tcode{X}}
means that the following expression
is well-formed:
\begin{codeblock}
allocator_traits<A>::construct(m, p, rv)
\end{codeblock}
and its evaluation causes the following postcondition to hold: The value
of \tcode{*p} is equivalent to the value of \tcode{rv} before the evaluation.
\begin{note}
\tcode{rv} remains a valid object. Its state is unspecified.
\end{note}

\item
\tcode{T} is \defnx{\oldconcept{CopyInsertable} into \tcode{X}}
{\oldconceptname{CopyInsertable} into X@\oldconcept{CopyInsertable} into \tcode{X}}
means that, in addition to \tcode{T} being \oldconcept{MoveInsertable} into
\tcode{X}, the following expression is well-formed:
\begin{codeblock}
allocator_traits<A>::construct(m, p, v)
\end{codeblock}
and its evaluation causes the following postcondition to hold:
The value of \tcode{v} is unchanged and is equivalent to \tcode{*p}.

\item
\tcode{T} is
\defnx{\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}}
{\oldconceptname{EmplaceConstructible} into X from args@\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}},
for zero
or more arguments \tcode{args}, means that the following expression is well-formed:
\begin{codeblock}
allocator_traits<A>::construct(m, p, args)
\end{codeblock}

\item
\tcode{T} is
\defnx{\oldconcept{Erasable} from \tcode{X}}
{\oldconceptname{Erasable} from X@\oldconcept{Erasable} from \tcode{X}}
means that the following expression is well-formed:
\begin{codeblock}
allocator_traits<A>::destroy(m, p)
\end{codeblock}
\end{itemize}

\begin{note}
A container calls \tcode{allocator_traits<A>::construct(m, p, args)}
to construct an element at \tcode{p} using \tcode{args},
with \tcode{m == get_allocator()}.
The default \tcode{construct} in \tcode{allocator} will
call \tcode{::new((void*)p) T(args)},
but specialized allocators can choose a different definition.
\end{note}

\pnum
In this subclause,
\begin{itemize}
\item
\tcode{X} denotes an allocator-aware container class
with a \tcode{value_type} of \tcode{T} using an allocator of type \tcode{A},
\item
\tcode{u} denotes a variable,
\item
\tcode{a} and \tcode{b} denote non-const lvalues of type \tcode{X},
\item
\tcode{c} denotes an lvalue of type \tcode{\keyword{const} X},
\item
\tcode{t} denotes an lvalue or a const rvalue of type \tcode{X},
\item
\tcode{rv} denotes a non-const rvalue of type \tcode{X}, and
\item
\tcode{m} is a value of type \tcode{A}.
\end{itemize}

% Local command to index names as members of all containers.
\renewcommand{\indexcont}[1]{%
\indexlibrarymisc{\idxcode{#1}}{allocator-aware containers}%
\indexlibrarymemberx{deque}{#1}%
\indexlibrarymemberx{forward_list}{#1}%
\indexlibrarymemberx{hive}{#1}%
\indexlibrarymemberx{list}{#1}%
\indexlibrarymemberx{vector}{#1}%
\indexlibrarymemberx{map}{#1}%
\indexlibrarymemberx{set}{#1}%
\indexlibrarymemberx{multiset}{#1}%
\indexlibrarymemberx{multimap}{#1}%
\indexlibrarymemberx{unordered_map}{#1}%
\indexlibrarymemberx{unordered_set}{#1}%
\indexlibrarymemberx{unordered_multiset}{#1}%
\indexlibrarymemberx{unordered_multimap}{#1}%
}

A type \tcode{X} meets the allocator-aware container requirements
if \tcode{X} meets the container requirements and
the following types, statements, and expressions are well-formed and have
the specified semantics.

\indexcont{allocator_type}%
\begin{itemdecl}
typename X::allocator_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{A}

\pnum
\mandates
\tcode{allocator_type::value_type} is the same as \tcode{X::value_type}.
\end{itemdescr}

\indexcont{get_allocator}%
\begin{itemdecl}
c.get_allocator()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{A}

\pnum
\complexity
Constant.
\end{itemdescr}

\begin{itemdecl}
X u;
X u = X();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{A} meets the \oldconcept{DefaultConstructible} requirements.

\pnum
\ensures
\tcode{u.empty()} returns \tcode{true}, \tcode{u.get_allocator() == A()}.

\pnum
\complexity
Constant.
\end{itemdescr}

\begin{itemdecl}
X u(m);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{u.empty()} returns \tcode{true}, \tcode{u.get_allocator() == m}.

\pnum
\complexity
Constant.
\end{itemdescr}

\begin{itemdecl}
X u(t, m);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}.

\pnum
\ensures
\tcode{u == t}, \tcode{u.get_allocator() == m}.

\pnum
\complexity
Linear.
\end{itemdescr}

\begin{itemdecl}
X u(rv);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{u} has the same elements as \tcode{rv} had before this construction;
the value of \tcode{u.get_allocator()} is the same as
the value of \tcode{rv.get_allocator()} before this construction.

\pnum
\complexity
Constant.
\end{itemdescr}

\begin{itemdecl}
X u(rv, m);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X}.

\pnum
\ensures
\tcode{u} has the same elements, or copies of the elements,
that \tcode{rv} had before this construction,
\tcode{u.get_allocator() == m}.

\pnum
\complexity
Constant if \tcode{m == rv.get_allocator()}, otherwise linear.
\end{itemdescr}

\begin{itemdecl}
a = t
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{X\&}.

\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X} and
\oldconcept{CopyAssignable}.

\pnum
\ensures
\tcode{a == t} is \tcode{true}.

\pnum
\complexity
Linear.
\end{itemdescr}

\indexcont{operator=}%
\begin{itemdecl}
a = rv
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{X\&}.

\pnum
\expects
If
\tcode{allocator_traits<allocator_type>::propagate_on_container_move_assign\-ment::value}
is \tcode{false},
\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X} and
\oldconcept{MoveAssignable}.

\pnum
\effects
All existing elements of \tcode{a} are either move assigned to or destroyed.

\pnum
\ensures
If \tcode{a} and \tcode{rv} do not refer to the same object,
\tcode{a} is equal to the value that \tcode{rv} had before this assignment.

\pnum
\complexity
Linear.
\end{itemdescr}

\indexcont{swap}%
\begin{itemdecl}
a.swap(b)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\effects
Exchanges the contents of \tcode{a} and \tcode{b}.

\pnum
\complexity
Constant.
\end{itemdescr}


\rSec2[container.requirements.dataraces]{Container data races}

\pnum
For purposes of avoiding data races\iref{res.on.data.races}, implementations shall
consider the following functions to be \keyword{const}: \tcode{begin}, \tcode{end},
\tcode{rbegin}, \tcode{rend}, \tcode{front}, \tcode{back}, \tcode{data}, \tcode{find},
\tcode{lower_bound}, \tcode{upper_bound}, \tcode{equal_range}, \tcode{at} and, except in
associative or unordered associative containers, \tcode{operator[]}.

\pnum
Notwithstanding~\ref{res.on.data.races}, implementations are required to avoid data
races when the contents of the contained object in different elements in the same
container, excepting \tcode{vector<bool>}, are modified concurrently.

\pnum
\begin{note}
For a \tcode{vector<int> x} with a size greater than one, \tcode{x[1] = 5}
and \tcode{*x.begin() = 10} can be executed concurrently without a data race, but
\tcode{x[0] = 5} and \tcode{*x.begin() = 10} executed concurrently can result in a data
race.
As an exception to the general rule, for a \tcode{vector<bool> y}, \tcode{y[0] = true}
can race with \tcode{y[1] = true}.
\end{note}

\rSec2[sequence.reqmts]{Sequence containers}

\pnum
A sequence container organizes a finite set of objects, all of the same type, into a strictly
linear arrangement. The library provides the following basic kinds of sequence containers:
\tcode{vector}, \tcode{inplace_vector},
\tcode{forward_list}, \tcode{list}, and \tcode{deque}.
In addition,
\tcode{array} and \tcode{hive} are provided as sequence containers
which provide limited sequence operations,
in \tcode{array}'s case because it has a fixed number of elements, and
in \tcode{hive}'s case because insertion order is unspecified.
The library also provides container adaptors that
make it easy to construct abstract data types,
such as \tcode{stack}s,
\tcode{queue}s,
\tcode{flat_map}s,
\tcode{flat_multimap}s,
\tcode{flat_set}s, or
\tcode{flat_multiset}s, out of
the basic sequence container kinds (or out of other program-defined sequence containers).

\pnum
In this subclause,
\begin{itemize}
\item
\tcode{X} denotes a sequence container class,
\item
\tcode{a} denotes a value of type \tcode{X} containing elements of type \tcode{T},
\item
\tcode{u} denotes the name of a variable being declared,
\item
\tcode{A} denotes \tcode{X::allocator_type} if
the \grammarterm{qualified-id} \tcode{X::allocator_type} is valid and denotes a
type\iref{temp.deduct} and
\tcode{allocator<T>} if it doesn't,
\item
\tcode{i} and \tcode{j}
denote iterators that meet the \oldconcept{InputIterator} requirements
and refer to elements implicitly convertible to \tcode{value_type},
\item
\range{i}{j} denotes a valid range,
\item
\tcode{rg} denotes a value of a type \tcode{R}
that models \tcode{\exposconcept{container-compatible-range}<T>},
\item
\tcode{il} designates an object of type \tcode{initializer_list<value_type>},
\item
\tcode{n} denotes a value of type \tcode{X::size_type},
\item
\tcode{p} denotes a valid constant iterator to \tcode{a},
\item
\tcode{q} denotes a valid dereferenceable constant iterator to \tcode{a},
\item
\range{q1}{q2} denotes a valid range of constant iterators in \tcode{a},
\item
\tcode{t} denotes an lvalue or a const rvalue of \tcode{X::value_type}, and
\item
\tcode{rv} denotes a non-const rvalue of \tcode{X::value_type}.
\item
\tcode{Args} denotes a template parameter pack;
\item
\tcode{args} denotes a function parameter pack with the pattern \tcode{Args\&\&}.
\end{itemize}

\pnum
The complexities of the expressions are sequence dependent.

% Local command to index names as members of all containers.
\renewcommand{\indexcont}[1]{%
\indexlibrarymisc{\idxcode{#1}}{sequence containers}%
\indexlibrarymemberx{deque}{#1}%
\indexlibrarymemberx{forward_list}{#1}%
\indexlibrarymemberx{list}{#1}%
\indexlibrarymemberx{vector}{#1}%
\indexlibrarymemberx{inplace_vector}{#1}%
}

\pnum
A type \tcode{X} meets the \defnadj{sequence}{container} requirements
if \tcode{X} meets the container requirements and
the following statements and expressions are well-formed and have
the specified semantics.

\begin{itemdecl}
X u(n, t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}.

\pnum
\effects
Constructs a sequence container with \tcode{n} copies of \tcode{t}.

\pnum
\ensures
\tcode{distance(u.begin(), u.end()) == n} is \tcode{true}.
\end{itemdescr}

\begin{itemdecl}
X u(i, j);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.
For \tcode{vector},
if the iterator does not meet
the \oldconcept{ForwardIterator} requirements\iref{forward.iterators},
\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}.

\pnum
\effects
Constructs a sequence container equal to the range \range{i}{j}.
Each iterator in the range \range{i}{j} is dereferenced exactly once.

\pnum
\ensures
\tcode{distance(u.begin(), u.end()) == distance(i, j)} is \tcode{true}.
\end{itemdescr}

\begin{itemdecl}
X(from_range, rg)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.
For \tcode{vector},
if \tcode{R} models
\tcode{ranges::\libconcept{approximately_sized_range}}
but not \tcode{ranges::\libconcept{sized_range}} or models
\tcode{ranges::\libconcept{input_range}}
but not \tcode{ranges::\libconcept{forward_range}},
\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}.

\pnum
\effects
Constructs a sequence container equal to the range \tcode{rg}.
Each iterator in the range \tcode{rg} is dereferenced exactly once.

\pnum
\recommended
If \tcode{R} models \tcode{ranges::\libconcept{approximately_sized_range}} and
\tcode{ranges::distance(\linebreak{}rg) <= ranges::reserve_hint(rg)} is \tcode{true},
an implementation should not perform more than a single reallocation.

\pnum
\ensures
\tcode{distance(begin(), end()) == ranges::distance(rg)} is \tcode{true}.
\end{itemdescr}

\begin{itemdecl}
X(il)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{X(il.begin(), il.end())}.
\end{itemdescr}

\begin{itemdecl}
a = il
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{X\&}.

\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X} and
\oldconcept{CopyAssignable}.

\pnum
\effects
Assigns the range \range{il.begin()}{il.end()} into \tcode{a}.
All existing elements of \tcode{a} are either assigned to or destroyed.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexcont{emplace}%
\begin{itemdecl}
a.emplace(p, args)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}.

\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.
For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque},
\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X} and
\oldconcept{MoveAssignable}.

\pnum
\effects
Inserts an object of type \tcode{T}
constructed with \tcode{std::forward<Args>(args)...}
before \tcode{p}.
\begin{note}
\tcode{args} can directly or indirectly refer to a value in \tcode{a}.
\end{note}

\pnum
\returns
An iterator that points to the new element.
\end{itemdescr}

\indexcont{insert}%
\begin{itemdecl}
a.insert(p, t)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}.

\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}.
For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque},
\tcode{T} is also \oldconcept{CopyAssignable}.

\pnum
\effects
Inserts a copy of \tcode{t} before \tcode{p}.

\pnum
\returns
An iterator that points to the copy of \tcode{t} inserted into \tcode{a}.
\end{itemdescr}

\begin{itemdecl}
a.insert(p, rv)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}.

\pnum
\expects
\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X}.
For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque},
\tcode{T} is also \oldconcept{MoveAssignable}.

\pnum
\effects
Inserts a copy of \tcode{rv} before \tcode{p}.

\pnum
\returns
An iterator that points to the copy of \tcode{rv} inserted into \tcode{a}.
\end{itemdescr}

\begin{itemdecl}
a.insert(p, n, t)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}.

\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}
and \oldconcept{CopyAssignable}.

\pnum
\effects
Inserts \tcode{n} copies of \tcode{t} before \tcode{p}.

\pnum
\returns
An iterator
that points to the copy of the first element inserted into \tcode{a}, or
\tcode{p} if \tcode{n == 0}.
\end{itemdescr}

\begin{itemdecl}
a.insert(p, i, j)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}.

\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.
For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque},
\tcode{T} is also
\oldconcept{MoveInsertable} into \tcode{X},
and \tcode{T} meets the
\oldconcept{MoveConstructible},
\oldconcept{MoveAs\-signable}, and
\oldconcept{Swappable}\iref{swappable.requirements} requirements.
Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}.

\pnum
\effects
Inserts copies of elements in \range{i}{j} before \tcode{p}.
Each iterator in the range \range{i}{j} shall be dereferenced exactly once.

\pnum
\returns
An iterator
that points to the copy of the first element inserted into \tcode{a}, or
\tcode{p} if \tcode{i == j}.
\end{itemdescr}

\indexcont{insert_range}%
\begin{itemdecl}
a.insert_range(p, rg)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}.

\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.
For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque},
\tcode{T} is also
\oldconcept{MoveInsertable} into \tcode{X},
and \tcode{T} meets the
\oldconcept{Move\-Constructible},
\oldconcept{MoveAssignable}, and
\oldconcept{Swappable}\iref{swappable.requirements} requirements.
\tcode{rg} and \tcode{a} do not overlap.

\pnum
\effects
Inserts copies of elements in \tcode{rg} before \tcode{p}.
Each iterator in the range \tcode{rg} is dereferenced exactly once.

\pnum
\returns
An iterator
that points to the copy of the first element inserted into \tcode{a}, or
\tcode{p} if \tcode{rg} is empty.
\end{itemdescr}

\begin{itemdecl}
a.insert(p, il)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{a.insert(p, il.begin(), il.end())}.
\end{itemdescr}

\indexcont{erase}%
\begin{itemdecl}
a.erase(q)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}.

\pnum
\expects
For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque},
\tcode{T} is \oldconcept{MoveAssignable}.

\pnum
\effects
Erases the element pointed to by \tcode{q}.

\pnum
\returns
An iterator that points to the element immediately following \tcode{q}
prior to the element being erased.
If no such element exists, \tcode{a.end()} is returned.
\end{itemdescr}

\begin{itemdecl}
a.erase(q1, q2)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}.

\pnum
\expects
For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque},
\tcode{T} is \oldconcept{MoveAssignable}.

\pnum
\effects
Erases the elements in the range \range{q1}{q2}.

\pnum
\returns
An iterator that points to the element pointed to by \tcode{q2}
prior to any elements being erased.
If no such element exists, \tcode{a.end()} is returned.
\end{itemdescr}

\indexcont{clear}%
\begin{itemdecl}
a.clear()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\effects
Destroys all elements in \tcode{a}.
Invalidates all references, pointers, and iterators
referring to the elements of \tcode{a} and
may invalidate the past-the-end iterator.

\pnum
\ensures
\tcode{a.empty()} is \tcode{true}.

\pnum
\complexity
Linear.
\end{itemdescr}

\indexcont{assign}%
\begin{itemdecl}
a.assign(i, j)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}
and assignable from \tcode{*i}.
For \tcode{vector},
if the iterator does not meet
the forward iterator requirements\iref{forward.iterators},
\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}.
Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}.

\pnum
\effects
Replaces elements in \tcode{a} with a copy of \range{i}{j}.
Invalidates all references, pointers and iterators
referring to the elements of \tcode{a}.
For \tcode{vector} and \tcode{deque},
also invalidates the past-the-end iterator.
Each iterator in the range \range{i}{j} is dereferenced exactly once.
\end{itemdescr}

\indexcont{assign_range}%
\begin{itemdecl}
a.assign_range(rg)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\mandates
\tcode{\libconcept{assignable_from}<T\&, ranges::range_reference_t<R>>}
is modeled.
For \tcode{inplace_vector},
if \tcode{ranges::size(rg)} is a constant expression,
then $\tcode{ranges::size(rg)} \le \tcode{a.max_size()}$.

\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.
For \tcode{vector},
if \tcode{R} models
\tcode{ranges::\libconcept{approximately_sized_range}}
but not \tcode{ranges::\libconcept{sized_range}} or models
\tcode{ranges::\libconcept{input_range}}
but not \tcode{ranges::\libconcept{forward_range}},
\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}.
\tcode{rg} and \tcode{a} do not overlap.

\pnum
\effects
Replaces elements in \tcode{a} with a copy of each element in \tcode{rg}.
Invalidates all references, pointers, and iterators
referring to the elements of \tcode{a}.
For \tcode{vector} and \tcode{deque},
also invalidates the past-the-end iterator.
Each iterator in the range \tcode{rg} is dereferenced exactly once.

\pnum
\recommended
If \tcode{R} models \tcode{ranges::\libconcept{approximately_sized_range}} and
\tcode{ranges::distance(\linebreak{}rg) <= ranges::reserve_hint(rg)} is \tcode{true},
an implementation should not perform any reallocation.
\end{itemdescr}

\begin{itemdecl}
a.assign(il)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{a.assign(il.begin(), il.end())}.
\end{itemdescr}

\begin{itemdecl}
a.assign(n, t)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}
and \oldconcept{CopyAssignable}.
\tcode{t} is not a reference into \tcode{a}.

\pnum
\effects
Replaces elements in \tcode{a} with \tcode{n} copies of \tcode{t}.
Invalidates all references, pointers and iterators
referring to the elements of \tcode{a}.
For \tcode{vector} and \tcode{deque},
also invalidates the past-the-end iterator.
\end{itemdescr}

\pnum
For every sequence container defined in this Clause and in \ref{strings}:
\begin{itemize}
\item If the constructor
\begin{codeblock}
template<class InputIterator>
  X(InputIterator first, InputIterator last,
    const allocator_type& alloc = allocator_type());
\end{codeblock}
is called with a type \tcode{InputIterator} that does not qualify as an input
iterator, then the constructor
shall not participate in overload resolution.

\item If the member functions of the forms:
\begin{codeblock}
template<class InputIterator>
  @\placeholdernc{return-type}@ @\placeholdernc{F}@(const_iterator p,
                InputIterator first, InputIterator last);       // such as \tcode{insert}

template<class InputIterator>
  @\placeholdernc{return-type}@ @\placeholdernc{F}@(InputIterator first, InputIterator last);       // such as \tcode{append}, \tcode{assign}

template<class InputIterator>
  @\placeholdernc{return-type}@ @\placeholdernc{F}@(const_iterator i1, const_iterator i2,
                InputIterator first, InputIterator last);       // such as \tcode{replace}
\end{codeblock}
are called with a type \tcode{InputIterator} that does not qualify as an input
iterator, then these functions
shall not participate in overload resolution.

\item A deduction guide for a sequence container shall not participate in overload resolution
if it has an \tcode{InputIterator} template parameter and a type that does not
qualify as an input iterator is deduced for that parameter,
or if it has an \tcode{Allocator} template parameter and a type that does not
qualify as an allocator is deduced for that parameter.
\end{itemize}

\pnum
The following operations are provided for
some types of sequence containers but not others.
Operations other than \tcode{prepend_range} and \tcode{append_range}
are implemented so as to take amortized constant time.

\begin{itemdecl}
a.front()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_reference} if \tcode{a} is of type \tcode{const X};
\tcode{reference} otherwise.

\pnum
\hardexpects
\tcode{a.empty()} is \tcode{false}.

\pnum
\returns
\tcode{*a.begin()}

\pnum
\remarks
Required for
\tcode{basic_string},
\tcode{array},
\tcode{deque},
\tcode{forward_list},
\tcode{inplace_vector},
\tcode{list}, and
\tcode{vector}.
\end{itemdescr}

\begin{itemdecl}
a.back()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_reference} if \tcode{a} is of type \tcode{const X};
\tcode{reference} otherwise.

\pnum
\hardexpects
\tcode{a.empty()} is \tcode{false}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
auto tmp = a.end();
--tmp;
return *tmp;
\end{codeblock}

\pnum
\remarks
Required for
\tcode{basic_string},
\tcode{array},
\tcode{deque},
\tcode{inplace_vector},
\tcode{list}, and
\tcode{vector}.
\end{itemdescr}

\begin{itemdecl}
a.emplace_front(args)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{reference}

\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.

\pnum
\effects
Prepends an object of type \tcode{T}
constructed with \tcode{std::forward<Args>(args)...}.

\pnum
\returns
\tcode{a.front()}.

\pnum
\remarks
Required for
\tcode{deque},
\tcode{forward_list}, and
\tcode{list}.
\end{itemdescr}

\begin{itemdecl}
a.emplace_back(args)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{reference}

\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.
For \tcode{vector},
\tcode{T} is also \oldconcept{MoveIn\-sert\-able} into \tcode{X}.

\pnum
\effects
Appends an object of type \tcode{T}
constructed with \tcode{std::forward<Args>(args)...}.

\pnum
\returns
\tcode{a.back()}.

\pnum
\remarks
Required for
\tcode{deque},
\tcode{inplace_vector},
\tcode{list}, and
\tcode{vector}.
\end{itemdescr}

\begin{itemdecl}
a.push_front(t)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}.

\pnum
\effects
Prepends a copy of \tcode{t}.

\pnum
\remarks
Required for
\tcode{deque},
\tcode{forward_list}, and
\tcode{list}.
\end{itemdescr}

\begin{itemdecl}
a.push_front(rv)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X}.

\pnum
\effects
Prepends a copy of \tcode{rv}.

\pnum
\remarks
Required for
\tcode{deque},
\tcode{forward_list}, and
\tcode{list}.
\end{itemdescr}

\begin{itemdecl}
a.prepend_range(rg)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.
For \tcode{deque},
\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}, and
\tcode{T} meets the
\oldconcept{MoveConstructible},
\oldconcept{MoveAssignable}, and
\oldconcept{Swappable}\iref{swappable.requirements} requirements.

\pnum
\effects
Inserts copies of elements in \tcode{rg} before \tcode{begin()}.
Each iterator in the range \tcode{rg} is dereferenced exactly once.
\begin{note}
The order of elements in \tcode{rg} is not reversed.
\end{note}

\pnum
\remarks
Required for
\tcode{deque},
\tcode{forward_list}, and
\tcode{list}.
\end{itemdescr}

\begin{itemdecl}
a.push_back(t)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}.

\pnum
\effects
Appends a copy of \tcode{t}.

\pnum
\remarks
Required for
\tcode{basic_string},
\tcode{deque},
\tcode{inplace_vector},
\tcode{list}, and
\tcode{vector}.
\end{itemdescr}

\begin{itemdecl}
a.push_back(rv)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X}.

\pnum
\effects
Appends a copy of \tcode{rv}.

\pnum
\remarks
Required for
\tcode{basic_string},
\tcode{deque},
\tcode{inplace_vector},
\tcode{list}, and
\tcode{vector}.
\end{itemdescr}

\begin{itemdecl}
a.append_range(rg)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.
For \tcode{vector},
\tcode{T} is also
\oldconcept{MoveInsertable} into \tcode{X}.

\pnum
\effects
Inserts copies of elements in \tcode{rg} before \tcode{end()}.
Each iterator in the range \tcode{rg} is dereferenced exactly once.

\pnum
\remarks
Required for
\tcode{deque},
\tcode{inplace_vector},
\tcode{list}, and
\tcode{vector}.
\end{itemdescr}

\begin{itemdecl}
a.pop_front()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\hardexpects
\tcode{a.empty()} is \tcode{false}.

\pnum
\effects
Destroys the first element.

\pnum
\remarks
Required for
\tcode{deque},
\tcode{forward_list}, and
\tcode{list}.
\end{itemdescr}

\begin{itemdecl}
a.pop_back()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\hardexpects
\tcode{a.empty()} is \tcode{false}.

\pnum
\effects
Destroys the last element.

\pnum
\remarks
Required for
\tcode{basic_string},
\tcode{deque},
\tcode{inplace_vector},
\tcode{list}, and
\tcode{vector}.
\end{itemdescr}

\begin{itemdecl}
a[n]
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_reference} if \tcode{a} is of type \tcode{const X};
\tcode{reference} otherwise.

\pnum
\hardexpects
\tcode{n < a.size()} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return *(a.begin() + n);}

\pnum
\remarks
Required for
\tcode{basic_string},
\tcode{array},
\tcode{deque},
\tcode{inplace_vector}, and
\tcode{vector}.
\end{itemdescr}

\begin{itemdecl}
a.at(n)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_reference} if \tcode{a} is of type \tcode{const X};
\tcode{reference} otherwise.

\pnum
\returns
\tcode{*(a.begin() + n)}

\pnum
\throws
\tcode{out_of_range} if \tcode{n >= a.size()}.

\pnum
\remarks
Required for
\tcode{basic_string},
\tcode{array},
\tcode{deque},
\tcode{inplace_vector}, and
\tcode{vector}.
\end{itemdescr}

\rSec2[container.node]{Node handles}

\rSec3[container.node.overview]{Overview}

\pnum
A \defn{node handle} is an object that accepts ownership of a single element
from an associative container\iref{associative.reqmts} or an unordered
associative container\iref{unord.req}. It may be used to transfer that
ownership to another container with compatible nodes.  Containers with
compatible nodes have the same node handle type. Elements may be transferred in
either direction between container types in the same row of
\tref{container.node.compat}.

\begin{floattable}{Container types with compatible nodes}{container.node.compat}
{ll}
\topline
\tcode{map<K, T, C1, A>}               & \tcode{map<K, T, C2, A>}                    \\
\rowsep
\tcode{map<K, T, C1, A>}               & \tcode{multimap<K, T, C2, A>}               \\
\rowsep
\tcode{set<K, C1, A>}                  & \tcode{set<K, C2, A>}                       \\
\rowsep
\tcode{set<K, C1, A>}                  & \tcode{multiset<K, C2, A>}                  \\
\rowsep
\tcode{unordered_map<K, T, H1, E1, A>} & \tcode{unordered_map<K, T, H2, E2, A>}      \\
\rowsep
\tcode{unordered_map<K, T, H1, E1, A>} & \tcode{unordered_multimap<K, T, H2, E2, A>} \\
\rowsep
\tcode{unordered_set<K, H1, E1, A>}    & \tcode{unordered_set<K, H2, E2, A>}         \\
\rowsep
\tcode{unordered_set<K, H1, E1, A>}    & \tcode{unordered_multiset<K, H2, E2, A>}    \\
\end{floattable}

\pnum
If a node handle is not empty, then it contains an allocator that is equal to
the allocator of the container when the element was extracted. If a node handle
is empty, it contains no allocator.

\pnum
Class \exposid{node-handle} is for exposition only.

\pnum
If a user-defined specialization of \tcode{pair} exists for
\tcode{pair<const Key, T>} or \tcode{pair<Key, T>}, where \tcode{Key} is the
container's \tcode{key_type} and \tcode{T} is the container's
\tcode{mapped_type}, the behavior of operations involving node handles is
undefined.

\begin{codeblock}
template<@\unspecnc@>
class @\placeholder{node-handle}@ {
public:
  // These type declarations are described in \ref{associative.reqmts} and \ref{unord.req}.
  using value_type     = @\seebelownc{}@;     // not present for map containers
  using key_type       = @\seebelownc{}@;     // not present for set containers
  using mapped_type    = @\seebelownc{}@;     // not present for set containers
  using allocator_type = @\seebelownc{}@;

private:
  using @\exposid{container-node-type}@ = @\unspecnc@;                  // \expos
  using @\exposid{ator-traits}@ = allocator_traits<allocator_type>;     // \expos

  typename @\exposid{ator-traits}@::template
    rebind_traits<@\exposid{container-node-type}@>::pointer @\exposid{ptr_}@;       // \expos
  optional<allocator_type> @\exposid{alloc_}@;                          // \expos

public:
  // \ref{container.node.cons}, constructors, copy, and assignment
  constexpr @\placeholdernc{node-handle}@() noexcept : @\exposid{ptr_}@(), @\exposid{alloc_}@() {}
  constexpr @\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&&) noexcept;
  constexpr @\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&&);

  // \ref{container.node.dtor}, destructor
  constexpr ~@\placeholdernc{node-handle}@();

  // \ref{container.node.observers}, observers
  constexpr value_type& value() const;          // not present for map containers
  key_type& key() const;                        // not present for set containers
  constexpr mapped_type& mapped() const;        // not present for set containers

  constexpr allocator_type get_allocator() const;
  constexpr explicit operator bool() const noexcept;
  constexpr bool empty() const noexcept;

  // \ref{container.node.modifiers}, modifiers
  constexpr void swap(@\placeholdernc{node-handle}@&)
    noexcept(@\exposid{ator-traits}@::propagate_on_container_swap::value ||
             @\exposid{ator-traits}@::is_always_equal::value);

  friend constexpr void swap(@\placeholdernc{node-handle}@& x, @\placeholdernc{node-handle}@& y) noexcept(noexcept(x.swap(y))) {
    x.swap(y);
  }
};
\end{codeblock}

\rSec3[container.node.cons]{Constructors, copy, and assignment}

\begin{itemdecl}
constexpr @\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&& nh) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \exposid{node-handle} object initializing
\exposid{ptr_} with \tcode{nh.\exposid{ptr_}}.  Move constructs \exposid{alloc_} with
\tcode{nh.\exposid{alloc_}}.  Assigns \keyword{nullptr} to \tcode{nh.\exposid{ptr_}} and assigns
\tcode{nullopt} to \tcode{nh.\exposid{alloc_}}.
\end{itemdescr}

\begin{itemdecl}
constexpr @\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&& nh);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
Either \tcode{!\exposid{alloc_}} is \tcode{true}, or
\tcode{\exposidnc{ator-traits}::propagate_on_container_move_assign\-ment::value}
is \tcode{true}, or \tcode{\exposid{alloc_} == nh.\exposid{alloc_}} is \tcode{true}.

\pnum
\effects
\begin{itemize}
\item
If \tcode{\exposid{ptr_} != nullptr} is \tcode{true}, destroys the \tcode{value_type}
subobject in the \exposid{container-node-type} object pointed to by \exposid{ptr_}
by calling \tcode{\exposid{ator-traits}::destroy}, then deallocates \exposid{ptr_} by
calling \tcode{\exposid{ator-\-traits}::template rebind_traits<\exposid{container-node-type}>::deallocate}.
\item
Assigns \tcode{nh.\exposid{ptr_}} to \exposid{ptr_}.
\item
If \tcode{!\exposid{alloc_}} is \tcode{true} or
\tcode{\exposid{ator-traits}::propagate_on_container_move_assignment::value}
is \tcode{true}, \linebreak
move assigns \tcode{nh.\exposid{alloc_}} to \exposid{alloc_}.
\item
Assigns
\keyword{nullptr} to \tcode{nh.\exposid{ptr_}} and assigns \tcode{nullopt} to
\tcode{nh.\exposid{alloc_}}.
\end{itemize}

\pnum
\returns
\tcode{*this}.

\pnum
\throws
Nothing.
\end{itemdescr}

\rSec3[container.node.dtor]{Destructor}

\begin{itemdecl}
constexpr ~@\placeholdernc{node-handle}@();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
If \tcode{\exposid{ptr_} != nullptr} is \tcode{true}, destroys the \tcode{value_type} subobject
in the \exposid{container-node-type} object pointed to by \exposid{ptr_} by calling
\tcode{\exposid{ator-traits}::destroy}, then deallocates \exposid{ptr_} by calling
\tcode{\exposid{ator-\-traits}::template rebind_traits<\exposid{container-node-type}>::deallocate}.
\end{itemdescr}

\rSec3[container.node.observers]{Observers}

\begin{itemdecl}
constexpr value_type& value() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{empty() == false}.

\pnum
\returns
A reference to the \tcode{value_type} subobject in the
\exposid{container-node-type} object pointed to by \exposid{ptr_}.

\pnum
\throws
Nothing.
\end{itemdescr}

\begin{itemdecl}
key_type& key() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{empty() == false}.

\pnum
\returns
A non-const reference to the \tcode{key_type} member of the
\tcode{value_type} subobject in the \exposid{contain\-er-node-type} object
pointed to by \exposid{ptr_}.

\pnum
\throws
Nothing.

\pnum
\remarks
Modifying the key through the returned reference is permitted.
\end{itemdescr}

\begin{itemdecl}
constexpr mapped_type& mapped() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{empty() == false}.

\pnum
\returns
A reference to the \tcode{mapped_type} member of the
\tcode{value_type} subobject in the \exposid{container-\-node-type} object
pointed to by \exposid{ptr_}.

\pnum
\throws
Nothing.
\end{itemdescr}

\begin{itemdecl}
constexpr allocator_type get_allocator() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{empty() == false}.

\pnum
\returns
\tcode{*\exposid{alloc_}}.

\pnum
\throws
Nothing.
\end{itemdescr}

\begin{itemdecl}
constexpr explicit operator bool() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{ptr_} != nullptr}.
\end{itemdescr}

\begin{itemdecl}
constexpr bool empty() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{ptr_} == nullptr}.
\end{itemdescr}

\rSec3[container.node.modifiers]{Modifiers}

\begin{itemdecl}
constexpr void swap(@\placeholdernc{node-handle}@& nh)
  noexcept(@\exposid{ator-traits}@::propagate_on_container_swap::value ||
           @\exposid{ator-traits}@::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{!\exposid{alloc_}} is \tcode{true}, or \tcode{!nh.\exposid{alloc_}}, or
\tcode{\exposid{ator-traits}::propagate_on_container_swap::\-value} is \tcode{true},
or \tcode{\exposid{alloc_} == nh.\exposid{alloc_}} is \tcode{true}.

\pnum
\effects
Calls \tcode{swap(\exposid{ptr_}, nh.\exposid{ptr_})}. If \tcode{!\exposid{alloc_}} is \tcode{true}, or
\tcode{!nh.\exposid{alloc_}} is \tcode{true}, or \tcode{\exposid{ator-traits}::\-propagate_on_container_swap::value}
is \tcode{true} calls \tcode{swap(\exposid{alloc_}, nh.\exposid{alloc_})}.
\end{itemdescr}

\rSec2[container.insert.return]{Insert return type}

\pnum
The associative containers with unique keys and the unordered containers with unique keys
have a member function \tcode{insert} that returns a nested type \tcode{insert_return_type}.
That return type is a specialization of the template specified in this subclause.

\begin{codeblock}
template<class Iterator, class NodeType>
struct @\placeholder{insert-return-type}@
{
  Iterator position;
  bool     inserted;
  NodeType node;
};
\end{codeblock}

\pnum
The name \exposid{insert-return-type} is for exposition only.
\exposid{insert-return-type} has the template parameters,
data members, and special members specified above.
It has no base classes or members other than those specified.

\rSec2[associative.reqmts]{Associative containers}

\rSec3[associative.reqmts.general]{General}

\pnum
Associative containers provide fast retrieval of data based on keys.
The library provides four basic kinds of associative containers:
\tcode{set},
\tcode{multiset},
\tcode{map}
and
\tcode{multimap}.
The library also provides container adaptors
that make it easy to construct abstract data types,
such as \tcode{flat_map}s, \tcode{flat_multimap}s,
\tcode{flat_set}s, or \tcode{flat_multiset}s,
out of the basic sequence container kinds
(or out of other program-defined sequence containers).

\pnum
Each associative container is parameterized on
\tcode{Key}
and an ordering relation
\tcode{Compare}
that induces a strict weak ordering\iref{alg.sorting} on
elements of
\tcode{Key}.
In addition,
\tcode{map}
and
\tcode{multimap}
associate an arbitrary \term{mapped type}
\tcode{T}
with the
\tcode{Key}.
The object of type
\tcode{Compare}
is called the
\term{comparison object}
of a container.

\pnum
The phrase ``equivalence of keys'' means the equivalence relation imposed by the
comparison object.
That is, two keys
\tcode{k1}
and
\tcode{k2}
are considered to be equivalent if for the
comparison object
\tcode{comp},
\tcode{comp(k1, k2) == false \&\& comp(k2, k1) == false}.
\begin{note}
This is not necessarily the same as the result of \tcode{k1 == k2}.
\end{note}
For any two keys
\tcode{k1}
and
\tcode{k2}
in the same container, calling
\tcode{comp(k1, k2)}
shall always return the same value.

\pnum
An associative container supports \term{unique keys} if it may contain at
most one element for each key. Otherwise, it supports \term{equivalent keys}.
The \tcode{set} and \tcode{map} classes support unique keys; the \tcode{multiset}
and \tcode{multimap} classes support equivalent keys.
For \tcode{multiset} and \tcode{multimap},
\tcode{insert}, \tcode{emplace}, and \tcode{erase} preserve the relative ordering
of equivalent elements.

\pnum
For \tcode{set} and \tcode{multiset} the value type is the same as the key type.
For \tcode{map} and \tcode{multimap} it is equal to \tcode{pair<const Key, T>}.

\pnum
\tcode{iterator}
of an associative container is of the bidirectional iterator category.
For associative containers where the value type is the same as the key type, both
\tcode{iterator}
and
\tcode{const_iterator}
are constant iterators. It is unspecified whether or not
\tcode{iterator}
and
\tcode{const_iterator}
are the same type.
\begin{note}
\tcode{iterator} and \tcode{const_iterator} have identical semantics in this case, and \tcode{iterator} is convertible to \tcode{const_iterator}. Users can avoid violating the one-definition rule by always using \tcode{const_iterator} in their function parameter lists.
\end{note}

\pnum
In this subclause,
\begin{itemize}
\item
\tcode{X} denotes an associative container class,
\item
\tcode{a} denotes a value of type \tcode{X},
\item
\tcode{a2} denotes a value of a type with nodes compatible with type
\tcode{X} (\tref{container.node.compat}),
\item
\tcode{b} denotes a value of type \tcode{X} or \tcode{const X},
\item
\tcode{u} denotes the name of a variable being declared,
\item
\tcode{a_uniq} denotes a value of type \tcode{X}
when \tcode{X} supports unique keys,
\item
\tcode{a_eq} denotes a value of type \tcode{X}
when \tcode{X} supports equivalent keys,
\item
\tcode{a_tran} denotes a value of type \tcode{X} or \tcode{const X}
when the \grammarterm{qualified-id}
\tcode{X::key_compare::is_transparent} is valid
and denotes a type\iref{temp.deduct},
\item
\tcode{i} and \tcode{j}
meet the \oldconcept{InputIterator} requirements and refer to elements
implicitly convertible to
\tcode{value_type},
\item
\range{i}{j} denotes a valid range,
\item
\tcode{rg} denotes a value of a type \tcode{R}
that models \tcode{\exposconcept{container-compatible-range}<value_type>},
\item
\tcode{p} denotes a valid constant iterator to \tcode{a},
\item
\tcode{q} denotes a valid dereferenceable constant iterator to \tcode{a},
\item
\tcode{r} denotes a valid dereferenceable iterator to \tcode{a},
\item
\range{q1}{q2} denotes a valid range of constant iterators in \tcode{a},
\item
\tcode{il} designates an object of type \tcode{initializer_list<value_type>},
\item
\tcode{t} denotes a value of type \tcode{X::value_type},
\item
\tcode{k} denotes a value of type \tcode{X::key_type}, and
\item
\tcode{c} denotes a value of type \tcode{X::key_compare} or \tcode{const X::key_compare};
\item
\tcode{kl} is a value such that \tcode{a} is partitioned\iref{alg.sorting}
with respect to \tcode{c(x, kl)},
with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a};
\item
\tcode{ku} is a value such that \tcode{a} is partitioned with respect to
\tcode{!c(ku, x)},
with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a};
\item
\tcode{ke} is a value such that \tcode{a} is partitioned with respect to
\tcode{c(x, ke)} and \tcode{!c(ke, x)}, with \tcode{c(x, ke)} implying
\tcode{!c(ke, x)} and
with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a};
\item
\tcode{kx} is a value such that
\begin{itemize}
\item
\tcode{a} is partitioned with respect to \tcode{c(x, kx)} and \tcode{!c(kx, x)},
with \tcode{c(x, kx)} implying \tcode{!c(kx, x)} and
with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}, and
\item
\tcode{kx} is not convertible to
either \tcode{iterator} or \tcode{const_iterator}; and
\end{itemize}
\item
\tcode{A} denotes the storage allocator used by \tcode{X}, if any, or \tcode{allocator<X::value_type>} otherwise,
\item
\tcode{m} denotes an allocator of a type convertible to \tcode{A},
and \tcode{nh} denotes a non-const rvalue of type \tcode{X::node_type}.
\end{itemize}

\pnum
A type \tcode{X} meets the \defnadj{associative}{container} requirements
if \tcode{X} meets all the requirements of an allocator-aware
container\iref{container.alloc.reqmts} and
the following types, statements, and expressions are well-formed and
have the specified semantics,
except that for
\tcode{map} and \tcode{multimap}, the requirements placed on \tcode{value_type}
in \ref{container.reqmts} apply instead to \tcode{key_type}
and \tcode{mapped_type}.
\begin{note}
For example, in some cases \tcode{key_type} and \tcode{mapped_type}
need to be \oldconcept{CopyAssignable} even though the associated
\tcode{value_type}, \tcode{pair<const key_type, mapped_type>}, is not
\oldconcept{CopyAssignable}.
\end{note}

% Local command to index names as members of all ordered containers.
\newcommand{\indexordmem}[1]{%
\indexlibrary{\idxcode{#1}!ordered associative containers}%
\indexlibrary{\idxcode{set}!\idxcode{#1}}%
\indexlibrary{\idxcode{map}!\idxcode{#1}}%
\indexlibrary{\idxcode{multiset}!\idxcode{#1}}%
\indexlibrary{\idxcode{multimap}!\idxcode{#1}}%
\indexlibrary{\idxcode{flat_set}!\idxcode{#1}}%
\indexlibrary{\idxcode{flat_map}!\idxcode{#1}}%
\indexlibrary{\idxcode{flat_multiset}!\idxcode{#1}}%
\indexlibrary{\idxcode{flat_multimap}!\idxcode{#1}}%
}

\indexordmem{key_type}%
\begin{itemdecl}
typename X::key_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{Key}.
\end{itemdescr}

\indexordmem{mapped_type}%
\begin{itemdecl}
typename X::mapped_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{T}.

\pnum
\remarks
For \tcode{map} and \tcode{multimap} only.
\end{itemdescr}

\indexordmem{value_type}%
\begin{itemdecl}
typename X::value_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{Key} for \tcode{set} and \tcode{multiset} only;
\tcode{pair<const Key, T>} for \tcode{map} and \tcode{multimap} only.

\pnum
\expects
\tcode{X::value_type} is \oldconcept{Erasable} from \tcode{X}.
\end{itemdescr}

\indexordmem{key_compare}%
\begin{itemdecl}
typename X::key_compare
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{Compare}.

\pnum
\expects
\tcode{key_compare} is \oldconcept{CopyConstructible}.
\end{itemdescr}

\indexordmem{value_compare}%
\begin{itemdecl}
typename X::value_compare
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A binary predicate type.
It is the same as \tcode{key_compare} for \tcode{set} and
\tcode{multiset}; is an ordering relation on pairs induced by the
first component (i.e., \tcode{Key}) for \tcode{map} and \tcode{multimap}.
\end{itemdescr}

\indexordmem{node_type}%
\begin{itemdecl}
typename X::node_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A specialization of
the \exposid{node-handle} class template\iref{container.node},
such that the public nested types are
the same types as the corresponding types in \tcode{X}.
\end{itemdescr}

\indexlibraryctor{set}%
\indexlibraryctor{map}%
\indexlibraryctor{multiset}%
\indexlibraryctor{multimap}%
\begin{itemdecl}
X(c)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty container.
Uses a copy of \tcode{c} as a comparison object.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{set}%
\indexlibraryctor{map}%
\indexlibraryctor{multiset}%
\indexlibraryctor{multimap}%
\begin{itemdecl}
X u = X();
X u;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements.

\pnum
\effects
Constructs an empty container.
Uses \tcode{Compare()} as a comparison object.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{set}%
\indexlibraryctor{map}%
\indexlibraryctor{multiset}%
\indexlibraryctor{multimap}%
\begin{itemdecl}
X(i, j, c)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.

\pnum
\effects
Constructs an empty container and
inserts elements from the range \range{i}{j} into it;
uses \tcode{c} as a comparison object.

\pnum
\complexity
$N \log N$ in general, where $N$ has the value \tcode{distance(i, j)};
linear if \range{i}{j} is sorted with respect to \tcode{value_comp()}.
\end{itemdescr}

\indexlibraryctor{set}%
\indexlibraryctor{map}%
\indexlibraryctor{multiset}%
\indexlibraryctor{multimap}%
\begin{itemdecl}
X(i, j)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements.
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.

\pnum
\effects
Constructs an empty container and
inserts elements from the range \range{i}{j} into it;
uses \tcode{Compare()} as a comparison object.

\pnum
\complexity
$N \log N$ in general, where $N$ has the value \tcode{distance(i, j)};
linear if \range{i}{j} is sorted with respect to \tcode{value_comp()}.
\end{itemdescr}

\indexlibraryctor{set}%
\indexlibraryctor{map}%
\indexlibraryctor{multiset}%
\indexlibraryctor{multimap}%
\begin{itemdecl}
X(from_range, rg, c)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.

\pnum
\effects
Constructs an empty container and
inserts each element from \tcode{rg} into it.
Uses \tcode{c} as the comparison object.

\pnum
\complexity
$N \log N$ in general, where $N$ has the value \tcode{ranges::distance(rg)};
linear if \tcode{rg} is sorted with respect to \tcode{value_comp()}.
\end{itemdescr}

\indexlibraryctor{set}%
\indexlibraryctor{map}%
\indexlibraryctor{multiset}%
\indexlibraryctor{multimap}%
\begin{itemdecl}
X(from_range, rg)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements.
\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.

\pnum
\effects
Constructs an empty container and
inserts each element from \tcode{rg} into it.
Uses \tcode{Compare()} as the comparison object.

\pnum
\complexity
Same as \tcode{X(from_range, rg, c)}.
\end{itemdescr}

\indexlibraryctor{set}%
\indexlibraryctor{map}%
\indexlibraryctor{multiset}%
\indexlibraryctor{multimap}%
\begin{itemdecl}
X(il, c)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{X(il.begin(), il.end(), c)}.
\end{itemdescr}

\indexlibraryctor{set}%
\indexlibraryctor{map}%
\indexlibraryctor{multiset}%
\indexlibraryctor{multimap}%
\begin{itemdecl}
X(il)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{X(il.begin(), il.end())}.
\end{itemdescr}

\begin{itemdecl}
a = il
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{X\&}

\pnum
\expects
\tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}
and \oldconcept{CopyAssignable}.

\pnum
\effects
Assigns the range \range{il.begin()}{il.end()} into \tcode{a}.
All existing elements of \tcode{a} are either assigned to or destroyed.

\pnum
\complexity
$N \log N$ in general, where $N$ has the value \tcode{il.size() + a.size()};
linear if \range{il.begin()}{il.end()} is sorted with respect to \tcode{value_comp()}.
\end{itemdescr}

\indexordmem{key_comp}%
\begin{itemdecl}
b.key_comp()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{X::key_compare}

\pnum
\returns
The comparison object out of which \tcode{b} was constructed.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexordmem{value_comp}%
\begin{itemdecl}
b.value_comp()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{X::value_compare}

\pnum
\returns
An object of \tcode{value_compare} constructed out of the comparison object.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexordmem{emplace}%
\begin{itemdecl}
a_uniq.emplace(args)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{pair<iterator, bool>}

\pnum
\expects
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.

\pnum
\effects
Inserts a \tcode{value_type} object \tcode{t}
constructed with \tcode{std::forward<Args>(args)...}
if and only if there is no element in the container
with key equivalent to the key of \tcode{t}.

\pnum
\returns
The \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion takes place, and
the iterator component of the pair points to
the element with key equivalent to the key of \tcode{t}.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexordmem{emplace}%
\begin{itemdecl}
a_eq.emplace(args)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\expects
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.

\pnum
\effects
Inserts a \tcode{value_type} object \tcode{t}
constructed with \tcode{std::forward<Args>(args)...}.
If a range containing elements equivalent to \tcode{t} exists in \tcode{a_eq},
\tcode{t} is inserted at the end of that range.

\pnum
\returns
An iterator pointing to the newly inserted element.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexordmem{emplace_hint}%
\begin{itemdecl}
a.emplace_hint(p, args)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\effects
Equivalent to \tcode{a.emplace(std::forward<Args>(args)...)},
except that the element is inserted as close as possible to
the position just prior to \tcode{p}.

\pnum
\returns
The iterator returned by \tcode{emplace}.

\pnum
\complexity
Logarithmic in general, but
amortized constant if the element is inserted right before \tcode{p}.
\end{itemdescr}

\indexordmem{insert}%
\begin{itemdecl}
a_uniq.insert(t)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{pair<iterator, bool>}

\pnum
\expects
If \tcode{t} is a non-const rvalue,
\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X};
otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}.

\pnum
\effects
Inserts \tcode{t} if and only if there is no element in the container
with key equivalent to the key of \tcode{t}.

\pnum
\returns
The \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion takes place, and
the \tcode{iterator} component of the pair points to
the element with key equivalent to the key of \tcode{t}.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexordmem{insert}%
\begin{itemdecl}
a_eq.insert(t)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\expects
If \tcode{t} is a non-const rvalue,
\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X};
otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}.

\pnum
\effects
Inserts \tcode{t} and returns the iterator pointing to
the newly inserted element.
If a range containing elements equivalent to \tcode{t} exists in \tcode{a_eq},
\tcode{t} is inserted at the end of that range.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexordmem{insert}%
\begin{itemdecl}
a.insert(p, t)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\expects
If \tcode{t} is a non-const rvalue,
\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X};
otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}.

\pnum
\effects
Inserts \tcode{t} if and only if there is no element
with key equivalent to the key of \tcode{t} in containers with unique keys;
always inserts \tcode{t} in containers with equivalent keys.
\tcode{t} is inserted as close as possible to
the position just prior to \tcode{p}.

\pnum
\returns
An iterator pointing to the element with key equivalent to the key of \tcode{t}.

\pnum
\complexity
Logarithmic in general, but
amortized constant if \tcode{t} is inserted right before \tcode{p}.
\end{itemdescr}

\indexordmem{insert}%
\begin{itemdecl}
a.insert(i, j)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.
Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}.

\pnum
\effects
Inserts each element from the range \range{i}{j}
if and only if there is no element
with key equivalent to the key of that element in containers with unique keys;
always inserts that element in containers with equivalent keys.

\pnum
\complexity
$N \log (\tcode{a.size()} + N)$, where $N$ has the value \tcode{distance(i, j)}.
\end{itemdescr}

\indexordmem{insert}%
\begin{itemdecl}
a.insert_range(rg)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.
\tcode{rg} and \tcode{a} do not overlap.

\pnum
\effects
Inserts each element from \tcode{rg} if and only if
there is no element with key equivalent to the key of that element
in containers with unique keys;
always inserts that element in containers with equivalent keys.

\pnum
\complexity
$N \log (\tcode{a.size()} + N)$,
where $N$ has the value \tcode{ranges::distance(rg)}.
\end{itemdescr}

\indexordmem{insert}%
\begin{itemdecl}
a.insert(il)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{a.insert(il.begin(), il.end())}.
\end{itemdescr}

\indexordmem{insert}%
\begin{itemdecl}
a_uniq.insert(nh)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{insert_return_type}

\pnum
\expects
\tcode{nh} is empty or
\tcode{a_uniq.get_allocator() == nh.get_allocator()} is \tcode{true}.

\pnum
\effects
If \tcode{nh} is empty, has no effect.
Otherwise, inserts the element owned by \tcode{nh} if and only if
there is no element in the container with a key equivalent to \tcode{nh.key()}.

\pnum
\returns
If \tcode{nh} is empty, \tcode{inserted} is \tcode{false},
\tcode{position} is \tcode{end()}, and \tcode{node} is empty.
Otherwise if the insertion took place, \tcode{inserted} is \tcode{true},
\tcode{position} points to the inserted element, and \tcode{node} is empty;
if the insertion failed, \tcode{inserted} is \tcode{false},
\tcode{node} has the previous value of \tcode{nh}, and
\tcode{position} points to an element with a key equivalent to \tcode{nh.key()}.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexordmem{insert}%
\begin{itemdecl}
a_eq.insert(nh)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\expects
\tcode{nh} is empty or
\tcode{a_eq.get_allocator() == nh.get_allocator()} is \tcode{true}.

\pnum
\effects
If \tcode{nh} is empty, has no effect and returns \tcode{a_eq.end()}.
Otherwise, inserts the element owned by \tcode{nh} and
returns an iterator pointing to the newly inserted element.
If a range containing elements with keys equivalent to \tcode{nh.key()}
exists in \tcode{a_eq},
the element is inserted at the end of that range.

\pnum
\ensures
\tcode{nh} is empty.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexordmem{insert}%
\begin{itemdecl}
a.insert(p, nh)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\expects
\tcode{nh} is empty or
\tcode{a.get_allocator() == nh.get_allocator()} is \tcode{true}.

\pnum
\effects
If \tcode{nh} is empty, has no effect and returns \tcode{a.end()}.
Otherwise, inserts the element owned by \tcode{nh} if and only if
there is no element with key equivalent to \tcode{nh.key()}
in containers with unique keys;
always inserts the element owned by \tcode{nh}
in containers with equivalent keys.
The element is inserted as close as possible to
the position just prior to \tcode{p}.

\pnum
\ensures
\tcode{nh} is empty if insertion succeeds, unchanged if insertion fails.

\pnum
\returns
An iterator pointing to the element with key equivalent to \tcode{nh.key()}.

\pnum
\complexity
Logarithmic in general, but
amortized constant if the element is inserted right before \tcode{p}.
\end{itemdescr}


\indexordmem{extract}%
\begin{itemdecl}
a.extract(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{node_type}

\pnum
\effects
Removes the first element in the container with key equivalent to \tcode{k}.

\pnum
\returns
A \tcode{node_type} owning the element if found,
otherwise an empty \tcode{node_type}.

\pnum
\complexity
$\log (\tcode{a.size()})$
\end{itemdescr}

\indexordmem{extract}%
\begin{itemdecl}
a_tran.extract(kx)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{node_type}

\pnum
\effects
Removes the first element in the container with key \tcode{r}
such that \tcode{!c(r, kx) \&\& !c(kx, r)} is \tcode{true}.

\pnum
\returns
A \tcode{node_type} owning the element if found,
otherwise an empty \tcode{node_type}.

\pnum
\complexity
$\log(\tcode{a_tran.size()})$
\end{itemdescr}

\indexordmem{extract}%
\begin{itemdecl}
a.extract(q)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{node_type}

\pnum
\effects
Removes the element pointed to by \tcode{q}.

\pnum
\returns
A \tcode{node_type} owning that element.

\pnum
\complexity
Amortized constant.
\end{itemdescr}

\indexordmem{merge}%
\begin{itemdecl}
a.merge(a2)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{a.get_allocator() == a2.get_allocator()} is \tcode{true}.

\pnum
\effects
Attempts to extract each element in \tcode{a2} and insert it into \tcode{a}
using the comparison object of \tcode{a}.
In containers with unique keys,
if there is an element in \tcode{a} with key equivalent to
the key of an element from \tcode{a2},
then that element is not extracted from \tcode{a2}.

\pnum
\ensures
Pointers and references to the transferred elements of \tcode{a2}
refer to those same elements but as members of \tcode{a}.
If \tcode{a.begin()} and \tcode{a2.begin()} have the same type,
iterators referring to the transferred elements
will continue to refer to their elements,
but they now behave as iterators into \tcode{a}, not into \tcode{a2}.

\pnum
\throws
Nothing unless the comparison object throws.

\pnum
\complexity
$N \log(\tcode{a.size()+} N)$, where $N$ has the value \tcode{a2.size()}.
\end{itemdescr}

\indexordmem{erase}%
\begin{itemdecl}
a.erase(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}

\pnum
\effects
Erases all elements in the container with key equivalent to \tcode{k}.

\pnum
\returns
The number of erased elements.

\pnum
\complexity
$\log (\tcode{a.size()}) + \tcode{a.count(k)}$
\end{itemdescr}

\indexordmem{erase}%
\begin{itemdecl}
a_tran.erase(kx)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}

\pnum
\effects
Erases all elements in the container with key \tcode{r}
such that \tcode{!c(r, kx) \&\& !c(kx, r)} is \tcode{true}.

\pnum
\returns
The number of erased elements.

\pnum
\complexity
$\log(\tcode{a_tran.size())} + \tcode{a_tran.count(kx)}$
\end{itemdescr}

\indexordmem{erase}%
\begin{itemdecl}
a.erase(q)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\effects
Erases the element pointed to by \tcode{q}.

\pnum
\returns
An iterator pointing to the element immediately following \tcode{q}
prior to the element being erased.
If no such element exists, returns \tcode{a.end()}.

\pnum
\complexity
Amortized constant.
\end{itemdescr}

\indexordmem{erase}%
\begin{itemdecl}
a.erase(r)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\effects
Erases the element pointed to by \tcode{r}.

\pnum
\returns
An iterator pointing to the element immediately following \tcode{r}
prior to the element being erased.
If no such element exists, returns \tcode{a.end()}.

\pnum
\complexity
Amortized constant.
\end{itemdescr}

\indexordmem{erase}%
\begin{itemdecl}
a.erase(q1, q2)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\effects
Erases all the elements in the range \range{q1}{q2}.

\pnum
\returns
An iterator pointing to the element pointed to by \tcode{q2}
prior to any elements being erased.
If no such element exists, \tcode{a.end()} is returned.

\pnum
\complexity
$\log(\tcode{a.size()}) + N$, where $N$ has the value \tcode{distance(q1, q2)}.
\end{itemdescr}

\indexordmem{clear}%
\begin{itemdecl}
a.clear()
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{a.erase(a.begin(), a.end())}.

\pnum
\ensures
\tcode{a.empty()} is \tcode{true}.

\pnum
\complexity
Linear in \tcode{a.size()}.
\end{itemdescr}

\indexordmem{find}%
\begin{itemdecl}
b.find(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_iterator} if \tcode{b} is of type \tcode{const X};
\tcode{iterator} otherwise.

\pnum
\returns
An iterator pointing to an element with the key equivalent to \tcode{k}, or
\tcode{b.end()} if such an element is not found.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexordmem{find}%
\begin{itemdecl}
a_tran.find(ke)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_iterator} if \tcode{a_tran} is of type \tcode{const X};
\tcode{iterator} otherwise.

\pnum
\returns
An iterator pointing to an element with key \tcode{r}
such that \tcode{!c(r, ke) \&\& !c(ke, r)} is \tcode{true}, or
\tcode{a_tran.end()} if such an element is not found.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexordmem{count}%
\begin{itemdecl}
b.count(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}

\pnum
\returns
The number of elements with key equivalent to \tcode{k}.

\pnum
\complexity
$\log (\tcode{b.size()}) + \tcode{b.count(k)}$
\end{itemdescr}

\indexordmem{count}%
\begin{itemdecl}
a_tran.count(ke)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}

\pnum
\returns
The number of elements with key \tcode{r}
such that \tcode{!c(r, ke) \&\& !c(ke, r)}.

\pnum
\complexity
$\log (\tcode{a_tran.size()}) + \tcode{a_tran.count(ke)}$
\end{itemdescr}

\indexordmem{contains}%
\begin{itemdecl}
b.contains(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{bool}

\pnum
\effects
Equivalent to: \tcode{return b.find(k) != b.end();}
\end{itemdescr}

\indexordmem{contains}%
\begin{itemdecl}
a_tran.contains(ke)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{bool}

\pnum
\effects
Equivalent to: \tcode{return a_tran.find(ke) != a_tran.end();}
\end{itemdescr}

\indexordmem{lower_bound}%
\begin{itemdecl}
b.lower_bound(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_iterator} if \tcode{b} is of type \tcode{const X};
\tcode{iterator} otherwise.

\pnum
\returns
An iterator pointing to the first element with key not less than \tcode{k},
or \tcode{b.end()} if such an element is not found.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexordmem{lower_bound}%
\begin{itemdecl}
a_tran.lower_bound(kl)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_iterator} if \tcode{a_tran} is of type \tcode{const X};
\tcode{iterator} otherwise.

\pnum
\returns
An iterator pointing to the first element with key \tcode{r}
such that \tcode{!c(r, kl)},
or \tcode{a_tran.end()} if such an element is not found.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexordmem{upper_bound}%
\begin{itemdecl}
b.upper_bound(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_iterator} if \tcode{b} is of type \tcode{const X};
\tcode{iterator} otherwise.

\pnum
\returns
An iterator pointing to the first element with key greater than \tcode{k},
or \tcode{b.end()} if such an element is not found.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexordmem{upper_bound}%
\begin{itemdecl}
a_tran.upper_bound(ku)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_iterator} if \tcode{a_tran} is of type \tcode{const X};
\tcode{iterator} otherwise.

\pnum
\returns
An iterator pointing to the first element with key \tcode{r}
such that \tcode{c(ku, r)},
or \tcode{a_tran.end()} if such an element is not found.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexordmem{equal_range}%
\begin{itemdecl}
b.equal_range(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{pair<const_iterator, const_iterator>}
if \tcode{b} is of type \tcode{const X};
\tcode{pair<iter\-ator, iter\-ator>} otherwise.

\pnum
\effects
Equivalent to: \tcode{return make_pair(b.lower_bound(k), b.upper_bound(k));}

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexordmem{equal_range}%
\begin{itemdecl}
a_tran.equal_range(ke)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{pair<const_iterator, const_iterator>}
if \tcode{a_tran} is of type \tcode{const X};
\tcode{pair<iter\-ator, iter\-ator>} otherwise.

\pnum
\effects
Equivalent to:
\tcode{return make_pair(a_tran.lower_bound(ke), a_tran.upper_bound(ke));}

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\pnum
The \tcode{insert}, \tcode{insert_range}, and \tcode{emplace} members
shall not affect the validity of
iterators and references to the container,
and the \tcode{erase} members shall invalidate only iterators and
references to the erased elements.

\pnum
The \tcode{extract} members invalidate only iterators to the removed element;
pointers and references to the removed element remain valid. However, accessing
the element through such pointers and references while the element is owned by
a \tcode{node_type} is undefined behavior. References and pointers to an element
obtained while it is owned by a \tcode{node_type} are invalidated if the element
is successfully inserted.

\pnum
The fundamental property of iterators of associative containers is that they iterate through the containers
in the non-descending order of keys where non-descending is defined by the comparison that was used to
construct them.
For any two dereferenceable iterators
\tcode{i}
and
\tcode{j}
such that distance from
\tcode{i}
to
\tcode{j}
is positive, the following condition holds:

\begin{codeblock}
value_comp(*j, *i) == false
\end{codeblock}

\pnum
For associative containers with unique keys the stronger condition holds:

\begin{codeblock}
value_comp(*i, *j) != false
\end{codeblock}

\pnum
When an associative container is constructed by passing a comparison object the
container shall not store a pointer or reference to the passed object,
even if that object is passed by reference.
When an associative container is copied, through either a copy constructor
or an assignment operator,
the target container shall then use the comparison object from the container
being copied,
as if that comparison object had been passed to the target container in
its constructor.

\pnum
The member function templates
\tcode{find}, \tcode{count}, \tcode{contains},
\tcode{lower_bound}, \tcode{upper_bound}, \tcode{equal_range},
\tcode{erase}, and \tcode{extract}
shall not participate in overload resolution unless
the \grammarterm{qualified-id} \tcode{Compare::is_transparent} is valid
and denotes a type\iref{temp.deduct}.
Additionally, the member function templates \tcode{extract} and \tcode{erase}
shall not participate in overload resolution if
\tcode{is_convertible_v<K\&\&, iterator> || is_convertible_v<K\&\&, const_iterator>}
is \tcode{true},
where \tcode{K} is the type substituted as the first template argument.

\pnum
A deduction guide for an associative container shall not participate in overload resolution
if any of the following are true:
\begin{itemize}
\item It has an \tcode{InputIterator} template parameter
and a type that does not qualify as an input iterator is deduced for that parameter.

\item It has an \tcode{Allocator} template parameter
and a type that does not qualify as an allocator is deduced for that parameter.

\item It has a \tcode{Compare} template parameter
and a type that qualifies as an allocator is deduced for that parameter.
\end{itemize}

\rSec3[associative.reqmts.except]{Exception safety guarantees}%
\indextext{associative containers!exception safety}%
\indextext{associative containers!requirements}%

\pnum
For associative containers, no \tcode{clear()} function throws an exception.
\tcode{erase(k)} does not throw an exception unless that exception is thrown
by the container's \tcode{Compare} object (if any).

\pnum
For associative containers, if an exception is thrown by any operation from
within an \tcode{insert} or \tcode{emplace} function inserting a single element, the
insertion has no effect.

\pnum
For associative containers, no \tcode{swap} function throws an exception unless
that exception is thrown by the
swap of the container's \tcode{Compare} object (if any).

\rSec2[unord.req]{Unordered associative containers}%
\indextext{associative containers!unordered|see{unordered associative containers}}
\indextext{hash tables|see{unordered associative containers}}

\rSec3[unord.req.general]{General}

\pnum
\indextext{unordered associative containers!complexity}%
Unordered associative containers provide an ability for fast retrieval
of data based on keys.  The worst-case complexity for most operations
is linear, but the average case is much faster.  The library provides
four unordered associative containers: \tcode{unordered_set},
\tcode{unordered_map}, \tcode{unordered_multiset}, and
\tcode{unordered_multimap}.

\pnum
\indextext{unordered associative containers!lack of comparison functions}%
\indextext{unordered associative containers!requirements}%
\indextext{requirements!container!not required for unordered associated containers}%
Unordered associative containers conform to the requirements for
Containers\iref{container.requirements}, except that
the expressions
\tcode{a == b} and \tcode{a != b} have different semantics than for the other
container types.

\pnum
Each unordered associative container is parameterized by \tcode{Key},
by a function object type \tcode{Hash} that meets the \oldconcept{Hash}
requirements\iref{hash.requirements} and acts as a hash function for
argument values of type \tcode{Key}, and by a binary predicate \tcode{Pred}
that induces an equivalence relation on values of type \tcode{Key}.
Additionally, \tcode{unordered_map} and \tcode{unordered_multimap} associate
an arbitrary \textit{mapped type} \tcode{T} with the \tcode{Key}.

\pnum
\indextext{unordered associative containers!hash function}%
\indextext{hash function}%
The container's object of type \tcode{Hash} --- denoted by
\tcode{hash} --- is called the \term{hash function} of the
container. The container's object of type \tcode{Pred} ---
denoted by \tcode{pred} --- is called the
\term{key equality predicate} of the container.

\pnum
\indextext{unordered associative containers!equality function}%
Two values \tcode{k1} and \tcode{k2} are
considered equivalent if the container's
key equality predicate
\tcode{pred(k1, k2)} is valid and returns
\tcode{true} when passed those values.  If \tcode{k1} and
\tcode{k2} are equivalent, the container's hash function shall
return the same value for both.
\begin{note}
Thus, when an unordered associative container is instantiated with
a non-default \tcode{Pred} parameter it usually needs a non-default \tcode{Hash}
parameter as well.
\end{note}
For any two keys \tcode{k1} and \tcode{k2} in the same container,
calling \tcode{pred(k1, k2)} shall always return the same value.
For any key \tcode{k} in a container, calling \tcode{hash(k)}
shall always return the same value.

\pnum
\indextext{unordered associative containers!unique keys}%
\indextext{unordered associative containers!equivalent keys}%
An unordered associative container supports \textit{unique keys} if it
may contain at most one element for each key.  Otherwise, it supports
\textit{equivalent keys}.  \tcode{unordered_set} and \tcode{unordered_map}
support unique keys. \tcode{unordered_multiset} and \tcode{unordered_multimap}
support equivalent keys.  In containers that support equivalent keys,
elements with equivalent keys are adjacent to each other
in the iteration order of the container. Thus, although the absolute order
of elements in an unordered container is not specified, its elements are
grouped into \defnx{equivalent-key groups}{equivalent-key group} such that all elements of each
group have equivalent keys. Mutating operations on unordered containers shall
preserve the relative order of elements within each equivalent-key group
unless otherwise specified.

\pnum
For \tcode{unordered_set} and \tcode{unordered_multiset} the value type is
the same as the key type.  For \tcode{unordered_map} and
\tcode{unordered_multimap} it is \tcode{pair<const Key,
T>}.

\pnum
For unordered containers where the value type is the same as the key
type, both \tcode{iterator} and \tcode{const_iterator} are constant
iterators. It is unspecified whether or not \tcode{iterator} and
\tcode{const_iterator} are the same type.
\begin{note}
\tcode{iterator} and \tcode{const_iterator} have identical
semantics in this case, and \tcode{iterator} is convertible to
\tcode{const_iterator}. Users can avoid violating the one-definition rule
by always using \tcode{const_iterator} in their function parameter lists.
\end{note}

\pnum
\indextext{buckets}%
\indextext{hash code}%
The elements of an unordered associative container are organized into
\textit{buckets}.  Keys with the same hash code appear in the same
bucket.  The number of buckets is automatically increased as elements
are added to an unordered associative container, so that the average
number of elements per bucket is kept below a bound.  Rehashing
invalidates iterators, changes ordering between elements, and changes
which buckets elements appear in, but does not invalidate pointers or
references to elements. For \tcode{unordered_multiset} and
\tcode{unordered_multimap}, rehashing preserves the relative ordering of
equivalent elements.

\pnum
\indextext{unordered associative containers}%
\indextext{unordered associative containers!requirements}%
\indextext{requirements!unordered associative container}%
\indextext{unordered associative containers!unique keys}%
\indextext{unordered associative containers!equivalent keys}%
\indextext{requirements!container}%
In this subclause,
\begin{itemize}
\item
\tcode{X} denotes an unordered associative container class,
\item
\tcode{a} denotes a value of type \tcode{X},
\item
\tcode{a2} denotes a value of a type with nodes compatible
  with type \tcode{X} (\tref{container.node.compat}),
\item
\tcode{b} denotes a value of type \tcode{X} or \tcode{const X},
\item
\tcode{a_uniq} denotes a value of type \tcode{X}
  when \tcode{X} supports unique keys,
\item
\tcode{a_eq} denotes a value of type \tcode{X}
  when \tcode{X} supports equivalent keys,
\item
\tcode{a_tran} denotes a value of type \tcode{X} or \tcode{const X}
  when the \grammarterm{qualified-id}s
  \tcode{X::key_equal::is_transparent} and
  \tcode{X::hasher::is_transparent}
  are both valid and denote types\iref{temp.deduct},
\item
\tcode{i} and \tcode{j} denote input iterators
  that refer to \tcode{value_type},
\item
\range{i}{j} denotes a valid range,
\item
\tcode{rg} denotes a value of a type \tcode{R}
that models \tcode{\exposconcept{container-compatible-range}<value_type>},
\item
\tcode{p} and \tcode{q2} denote valid constant iterators to \tcode{a},
\item
\tcode{q} and \tcode{q1} denote
  valid dereferenceable constant iterators to \tcode{a},
\item
\tcode{r} denotes a valid dereferenceable iterator to \tcode{a},
\item
\range{q1}{q2} denotes a valid range in \tcode{a},
\item
\tcode{il} denotes a value of type \tcode{initializer_list<value_type>},
\item
\tcode{t} denotes a value of type \tcode{X::value_type},
\item
\tcode{k} denotes a value of type \tcode{key_type},
\item
\tcode{hf} denotes a value of type \tcode{hasher} or \tcode{const hasher},
\item
\tcode{eq} denotes a value of type \tcode{key_equal} or \tcode{const key_equal},
\item
\tcode{ke} is a value such that
  \begin{itemize}
  \item \tcode{eq(r1, ke) == eq(ke, r1)},
  \item \tcode{hf(r1) == hf(ke)} if \tcode{eq(r1, ke)} is \tcode{true}, and
  \item if any two of
    \tcode{eq(r1, ke)}, \tcode{eq(r2, ke)}, and \tcode{eq(r1, r2)}
    are \tcode{true}, then all three are \tcode{true},
  \end{itemize}
  where \tcode{r1} and \tcode{r2} are keys of elements in \tcode{a_tran},
\item
\tcode{kx} is a value such that
  \begin{itemize}
  \item \tcode{eq(r1, kx) == eq(kx, r1)},
  \item \tcode{hf(r1) == hf(kx)} if \tcode{eq(r1, kx)} is \tcode{true},
  \item if any two of
    \tcode{eq(r1, kx)}, \tcode{eq(r2, kx)}, and \tcode{eq(r1, r2)}
    are \tcode{true}, then all three are \tcode{true}, and
  \item \tcode{kx} is not convertible to
    either \tcode{iterator} or \tcode{const_iterator},
  \end{itemize}
  where \tcode{r1} and \tcode{r2} are keys of elements in \tcode{a_tran},
\item
\tcode{n} denotes a value of type \tcode{size_type},
\item
\tcode{z} denotes a value of type \tcode{float}, and
\item
\tcode{nh} denotes an rvalue of type \tcode{X::node_type}.
\end{itemize}

\pnum
A type \tcode{X} meets
the \defnadj{unordered associative}{container} requirements
if \tcode{X} meets all the requirements of
an allocator-aware container\iref{container.alloc.reqmts} and
the following types, statements, and expressions are well-formed and
have the specified semantics,
except that for \tcode{unordered_map} and \tcode{unordered_multimap},
the requirements placed on \tcode{value_type} in \ref{container.reqmts}
apply instead to \tcode{key_type} and \tcode{mapped_type}.
\begin{note}
For example, \tcode{key_type} and \tcode{mapped_type}
sometimes need to be \oldconcept{CopyAssignable}
even though the associated \tcode{value_type},
\tcode{pair<const key_type, mapped_type>},
is not \oldconcept{CopyAssignable}.
\end{note}

% Local command to index names as members of all unordered containers.
\newcommand{\indexunordmem}[1]{%
\indexlibrary{\idxcode{#1}!unordered associative containers}%
\indexlibrary{\idxcode{unordered_set}!\idxcode{#1}}%
\indexlibrary{\idxcode{unordered_map}!\idxcode{#1}}%
\indexlibrary{\idxcode{unordered_multiset}!\idxcode{#1}}%
\indexlibrary{\idxcode{unordered_multimap}!\idxcode{#1}}%
}

\indexunordmem{key_type}%
\begin{itemdecl}
typename X::key_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{Key}.
\end{itemdescr}

\indexunordmem{mapped_type}%
\begin{itemdecl}
typename X::mapped_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{T}.

\pnum
\remarks
For \tcode{unordered_map} and \tcode{unordered_multimap} only.
\end{itemdescr}

\indexunordmem{value_type}%
\begin{itemdecl}
typename X::value_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{Key} for \tcode{unordered_set} and \tcode{unordered_multiset} only;
\tcode{pair<const Key, T>}
for \tcode{unordered_map} and \tcode{unordered_multimap} only.

\pnum
\expects
\tcode{value_type} is \oldconcept{Erasable} from \tcode{X}.
\end{itemdescr}

\indexunordmem{hasher}%
\begin{itemdecl}
typename X::hasher
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{Hash}.

\pnum
\expects
\tcode{Hash} is a unary function object type
such that the expression \tcode{hf(k)} has type \tcode{size_t}.
\end{itemdescr}

\indexunordmem{key_equal}%
\begin{itemdecl}
typename X::key_equal
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{Pred}.

\pnum
\expects
\tcode{Pred} meets the \oldconcept{CopyConstructible} requirements.
\tcode{Pred} is a binary predicate that takes two arguments of type \tcode{Key}.
\tcode{Pred} is an equivalence relation.
\end{itemdescr}

\indexunordmem{local_iterator}%
\begin{itemdecl}
typename X::local_iterator
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
An iterator type
whose category, value type, difference type, and pointer and reference types
are the same as \tcode{X::iterator}'s.
\begin{note}
A \tcode{local_iterator} object can be used to iterate through a single bucket,
but cannot be used to iterate across buckets.
\end{note}
\end{itemdescr}

\indexunordmem{const_local_iterator}%
\begin{itemdecl}
typename X::const_local_iterator
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
An iterator type
whose category, value type, difference type, and pointer and reference types
are the same as \tcode{X::const_iterator}'s.
\begin{note}
A \tcode{const_local_iterator} object can be used to iterate
through a single bucket,
but cannot be used to iterate across buckets.
\end{note}
\end{itemdescr}

\indexunordmem{node_type}%
\begin{itemdecl}
typename X::node_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A specialization of a \exposid{node-handle} class template\iref{container.node},
such that the public nested types are the same types
as the corresponding types in \tcode{X}.
\end{itemdescr}

\indexlibraryctor{unordered_set}%
\indexlibraryctor{unordered_map}%
\indexlibraryctor{unordered_multiset}%
\indexlibraryctor{unordered_multimap}%
\begin{itemdecl}
X(n, hf, eq)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty container with at least \tcode{n} buckets,
using \tcode{hf} as the hash function and
\tcode{eq} as the key equality predicate.

\pnum
\complexity
\bigoh{\tcode{n}}
\end{itemdescr}

\begin{itemdecl}
X(n, hf)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements.

\pnum
\effects
Constructs an empty container with at least \tcode{n} buckets,
using \tcode{hf} as the hash function and
\tcode{key_equal()} as the key equality predicate.

\pnum
\complexity
\bigoh{\tcode{n}}
\end{itemdescr}

\begin{itemdecl}
X(n)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{hasher} and \tcode{key_equal}
meet the \oldconcept{DefaultConstructible} requirements.

\pnum
\effects
Constructs an empty container with at least \tcode{n} buckets,
using \tcode{hasher()} as the hash function and
\tcode{key_equal()} as the key equality predicate.

\pnum
\complexity
\bigoh{\tcode{n}}
\end{itemdescr}

\begin{itemdecl}
X a = X();
X a;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{hasher} and \tcode{key_equal} meet
the \oldconcept{DefaultConstructible} requirements.

\pnum
\effects
Constructs an empty container with an unspecified number of buckets,
using \tcode{hasher()} as the hash function and
\tcode{key_equal()} as the key equality predicate.

\pnum
\complexity
Constant.
\end{itemdescr}

\begin{itemdecl}
X(i, j, n, hf, eq)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.

\pnum
\effects
Constructs an empty container with at least \tcode{n} buckets,
using \tcode{hf} as the hash function and
\tcode{eq} as the key equality predicate, and
inserts elements from \range{i}{j} into it.

\pnum
\complexity
Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}.
\end{itemdescr}

\begin{itemdecl}
X(i, j, n, hf)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements.
\tcode{value_type} is
\oldconcept{\-EmplaceConstructible} into \tcode{X} from \tcode{*i}.

\pnum
\effects
Constructs an empty container with at least \tcode{n} buckets,
using \tcode{hf} as the hash function and
\tcode{key_equal()} as the key equality predicate, and
inserts elements from \range{i}{j} into it.

\pnum
\complexity
Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}.
\end{itemdescr}

\begin{itemdecl}
X(i, j, n)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{hasher} and \tcode{key_equal} meet
the \oldconcept{DefaultConstructible} requirements.
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.

\pnum
\effects
Constructs an empty container with at least \tcode{n} buckets,
using \tcode{hasher()} as the hash function and
\tcode{key_equal()} as the key equality predicate, and
inserts elements from \range{i}{j} into it.

\pnum
\complexity
Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}.
\end{itemdescr}

\begin{itemdecl}
X(i, j)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{hasher} and \tcode{key_equal} meet
the \oldconcept{DefaultConstructible} requirements.
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.

\pnum
\effects
Constructs an empty container with an unspecified number of buckets,
using \tcode{hasher()} as the hash function and
\tcode{key_equal()} as the key equality predicate, and
inserts elements from \range{i}{j} into it.

\pnum
\complexity
Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}.
\end{itemdescr}

\begin{itemdecl}
X(from_range, rg, n, hf, eq)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.

\pnum
\effects
Constructs an empty container with at least \tcode{n} buckets,
using \tcode{hf} as the hash function and
\tcode{eq} as the key equality predicate, and
inserts elements from \tcode{rg} into it.

\pnum
\complexity
Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}),
worst case \bigoh{N^2}.
\end{itemdescr}

\begin{itemdecl}
X(from_range, rg, n, hf)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements.
\tcode{value_type} is
\oldconcept{\-EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.

\pnum
\effects
Constructs an empty container with at least \tcode{n} buckets,
using \tcode{hf} as the hash function and
\tcode{key_equal()} as the key equality predicate, and
inserts elements from \tcode{rg} into it.

\pnum
\complexity
Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}),
worst case \bigoh{N^2}.
\end{itemdescr}

\begin{itemdecl}
X(from_range, rg, n)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{hasher} and \tcode{key_equal} meet
the \oldconcept{DefaultConstructible} requirements.
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.

\pnum
\effects
Constructs an empty container with at least \tcode{n} buckets,
using \tcode{hasher()} as the hash function and
\tcode{key_equal()} as the key equality predicate, and
inserts elements from \tcode{rg} into it.

\pnum
\complexity
Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}),
worst case \bigoh{N^2}.
\end{itemdescr}

\begin{itemdecl}
X(from_range, rg)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{hasher} and \tcode{key_equal} meet
the \oldconcept{DefaultConstructible} requirements.
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.

\pnum
\effects
Constructs an empty container with an unspecified number of buckets,
using \tcode{hasher()} as the hash function and
\tcode{key_equal()} as the key equality predicate, and
inserts elements from \tcode{rg} into it.

\pnum
\complexity
Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}),
worst case \bigoh{N^2}.
\end{itemdescr}

\begin{itemdecl}
X(il)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{X(il.begin(), il.end())}.
\end{itemdescr}

\begin{itemdecl}
X(il, n)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to  \tcode{X(il.begin(), il.end(), n)}.
\end{itemdescr}

\begin{itemdecl}
X(il, n, hf)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{X(il.begin(), il.end(), n, hf)}.
\end{itemdescr}

\begin{itemdecl}
X(il, n, hf, eq)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{X(il.begin(), il.end(), n, hf, eq)}.
\end{itemdescr}

\begin{itemdecl}
X(b)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
In addition to the container requirements\iref{container.reqmts},
copies the hash function, predicate, and maximum load factor.

\pnum
\complexity
Average case linear in \tcode{b.size()}, worst case quadratic.
\end{itemdescr}

\begin{itemdecl}
a = b
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{X\&}

\pnum
\effects
In addition to the container requirements,
copies the hash function, predicate, and maximum load factor.

\pnum
\complexity
Average case linear in \tcode{b.size()}, worst case quadratic.
\end{itemdescr}

\begin{itemdecl}
a = il
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{X\&}

\pnum
\expects
\tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}
and \oldconcept{CopyAssignable}.

\pnum
\effects
Assigns the range \range{il.begin()}{il.end()} into \tcode{a}.
All existing elements of \tcode{a} are either assigned to or destroyed.

\pnum
\complexity
Average case linear in \tcode{il.size()}, worst case quadratic.
\end{itemdescr}

\indexunordmem{hash_function}%
\begin{itemdecl}
b.hash_function()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{hasher}

\pnum
\returns
\tcode{b}'s hash function.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexunordmem{key_eq}%
\begin{itemdecl}
b.key_eq()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{key_equal}

\pnum
\returns
\tcode{b}'s key equality predicate.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexunordmem{emplace}%
\begin{itemdecl}
a_uniq.emplace(args)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{pair<iterator,} \tcode{bool>}

\pnum
\expects
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.

\pnum
\effects
Inserts a \tcode{value_type} object \tcode{t}
constructed with \tcode{std::forward<Args>(args)...} if and only if
there is no element in the container
with key equivalent to the key of \tcode{t}.

\pnum
\returns
The \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion takes place, and
the iterator component of the pair points to
the element with key equivalent to the key of \tcode{t}.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a_uniq.size()}}.
\end{itemdescr}

\indexunordmem{emplace}%
\begin{itemdecl}
a_eq.emplace(args)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\expects
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.

\pnum
\effects
Inserts a \tcode{value_type} object \tcode{t}
constructed with \tcode{std::forward<Args>(args)...}.

\pnum
\returns
An iterator pointing to the newly inserted element.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a_eq.size()}}.
\end{itemdescr}

\indexunordmem{emplace_hint}%
\begin{itemdecl}
a.emplace_hint(p, args)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\effects
Equivalent to \tcode{a.emplace(std::forward<Args>(args)...)},
except that the \tcode{const_iterator} \tcode{p} is a hint
pointing to where the search should start.
Implementations are permitted to ignore the hint.

\pnum
\returns
The iterator returned by \tcode{emplace}.
\end{itemdescr}

\indexunordmem{insert}%
\begin{itemdecl}
a_uniq.insert(t)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{pair<iterator, bool>}

\pnum
\expects
If \tcode{t} is a non-const rvalue,
\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X};
otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}.

\pnum
\effects
Inserts \tcode{t} if and only if there is no element in the container
with key equivalent to the key of \tcode{t}.

\pnum
\returns
The \tcode{bool} component of the returned pair indicates
whether the insertion takes place, and
the \tcode{iterator} component points to
the element with key equivalent to the key of \tcode{t}.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a_uniq.size()}}.
\end{itemdescr}

\indexunordmem{insert}%
\begin{itemdecl}
a_eq.insert(t)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\expects
If \tcode{t} is a non-const rvalue,
\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X};
otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}.

\pnum
\effects
Inserts \tcode{t}.

\pnum
\returns
An iterator pointing to the newly inserted element.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a_eq.size()}}.
\end{itemdescr}

\indexunordmem{insert}%
\begin{itemdecl}
a.insert(p, t)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\expects
If \tcode{t} is a non-const rvalue,
\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X};
otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}.

\pnum
\effects
Equivalent to \tcode{a.insert(t)}.
The iterator \tcode{p} is a hint pointing to where the search should start.
Implementations are permitted to ignore the hint.

\pnum
\returns
An iterator pointing to
the element with the key equivalent to that of \tcode{t}.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}.
\end{itemdescr}

\indexunordmem{insert}%
\begin{itemdecl}
a.insert(i, j)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.
Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}.

\pnum
\effects
Equivalent to \tcode{a.insert(t)} for each element in \range{i}{j}.

\pnum
\complexity
Average case \bigoh{N}, where $N$ is \tcode{distance(i, j)},
worst case \bigoh{N(\tcode{a.size()} + 1)}.
\end{itemdescr}

\indexunordmem{insert_range}%
\begin{itemdecl}
a.insert_range(rg)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.
\tcode{rg} and \tcode{a} do not overlap.

\pnum
\effects
Equivalent to \tcode{a.insert(t)} for each element \tcode{t} in \tcode{rg}.

\pnum
\complexity
Average case \bigoh{N}, where $N$ is \tcode{ranges::distance(rg)},
worst case \bigoh{N(\tcode{a.size()} + 1)}.
\end{itemdescr}

\indexunordmem{insert}%
\begin{itemdecl}
a.insert(il)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{a.insert(il.begin(), il.end())}.
\end{itemdescr}

\indexunordmem{insert}%
\begin{itemdecl}
a_uniq.insert(nh)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{insert_return_type}

\pnum
\expects
\tcode{nh} is empty or
\tcode{a_uniq.get_allocator() == nh.get_allocator()} is \tcode{true}.

\pnum
\effects
If \tcode{nh} is empty, has no effect.
Otherwise, inserts the element owned by \tcode{nh} if and only if
there is no element in the container with a key equivalent to \tcode{nh.key()}.

\pnum
\ensures
If \tcode{nh} is empty, \tcode{inserted} is \tcode{false},
\tcode{position} is \tcode{end()}, and \tcode{node} is empty.
Otherwise if the insertion took place, \tcode{inserted} is \tcode{true},
\tcode{position} points to the inserted element, and \tcode{node} is empty;
if the insertion failed, \tcode{inserted} is \tcode{false},
\tcode{node} has the previous value of \tcode{nh}, and \tcode{position}
points to an element with a key equivalent to \tcode{nh.key()}.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a_uniq.size()}}.
\end{itemdescr}

\indexunordmem{insert}%
\begin{itemdecl}
a_eq.insert(nh)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\expects
\tcode{nh} is empty or
\tcode{a_eq.get_allocator() == nh.get_allocator()} is \tcode{true}.

\pnum
\effects
If \tcode{nh} is empty, has no effect and returns \tcode{a_eq.end()}.
Otherwise, inserts the element owned by \tcode{nh} and
returns an iterator  pointing to the newly inserted element.

\pnum
\ensures
\tcode{nh} is empty.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a_eq.size()}}.
\end{itemdescr}

\indexunordmem{insert}%
\begin{itemdecl}
a.insert(q, nh)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\expects
\tcode{nh} is empty or
\tcode{a.get_allocator() == nh.get_allocator()} is \tcode{true}.

\pnum
\effects
If \tcode{nh} is empty, has no effect and returns \tcode{a.end()}.
Otherwise, inserts the element owned by \tcode{nh} if and only if
there is no element with key equivalent to \tcode{nh.key()}
in containers with unique keys;
always inserts the element owned by \tcode{nh}
in containers with equivalent keys.
The iterator \tcode{q} is a hint pointing to where the search should start.
Implementations are permitted to ignore the hint.

\pnum
\ensures
\tcode{nh} is empty if insertion succeeds, unchanged if insertion fails.

\pnum
\returns
An iterator pointing to the element with key equivalent to \tcode{nh.key()}.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}.
\end{itemdescr}

\indexunordmem{extract}%
\begin{itemdecl}
a.extract(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{node_type}

\pnum
\effects
Removes an element in the container with key equivalent to \tcode{k}.

\pnum
\returns
A \tcode{node_type} owning the element if found,
otherwise an empty \tcode{node_type}.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}.
\end{itemdescr}

\indexunordmem{extract}%
\begin{itemdecl}
a_tran.extract(kx)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{node_type}

\pnum
\effects
Removes an element in the container with key equivalent to \tcode{kx}.

\pnum
\returns
A \tcode{node_type} owning the element if found,
otherwise an empty \tcode{node_type}.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a_tran.size()}}.
\end{itemdescr}

\indexunordmem{extract}%
\begin{itemdecl}
a.extract(q)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{node_type}

\pnum
\effects
Removes the element pointed to by \tcode{q}.

\pnum
\returns
A \tcode{node_type} owning that element.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}.
\end{itemdescr}

\indexunordmem{merge}%
\begin{itemdecl}
a.merge(a2)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{a.get_allocator() == a2.get_allocator()}.

\pnum
\effects
Attempts to extract each element in \tcode{a2} and insert it into \tcode{a}
using the hash function and key equality predicate of \tcode{a}.
In containers with unique keys, if there is an element in \tcode{a}
with key equivalent to the key of an element from \tcode{a2},
then that element is not extracted from \tcode{a2}.

\pnum
\ensures
Pointers and references to the transferred elements of \tcode{a2} refer to
those same elements but as members of \tcode{a}.
Iterators referring to the transferred elements and
all iterators referring to \tcode{a} will be invalidated,
but iterators to elements remaining in \tcode{a2} will remain valid.

\pnum
\complexity
Average case \bigoh{N}, where $N$ is \tcode{a2.size()},
worst case \bigoh{N\tcode{*a.size() + N}}.
\end{itemdescr}

\indexunordmem{erase}%
\begin{itemdecl}
a.erase(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}

\pnum
\effects
Erases all elements with key equivalent to \tcode{k}.

\pnum
\returns
The number of elements erased.

\pnum
\complexity
Average case \bigoh{\tcode{a.count(k)}}, worst case \bigoh{\tcode{a.size()}}.
\end{itemdescr}

\indexunordmem{erase}%
\begin{itemdecl}
a_tran.erase(kx)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}

\pnum
\effects
Erases all elements with key equivalent to \tcode{kx}.

\pnum
\returns
The number of elements erased.

\pnum
\complexity
Average case \bigoh{\tcode{a_tran.count(kx)}},
worst case \bigoh{\tcode{a_tran.size()}}.
\end{itemdescr}

\indexunordmem{erase}%
\begin{itemdecl}
a.erase(q)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\effects
Erases the element pointed to by \tcode{q}.

\pnum
\returns
The iterator immediately following \tcode{q} prior to the erasure.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}.
\end{itemdescr}

\indexunordmem{erase}%
\begin{itemdecl}
a.erase(r)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\effects
Erases the element pointed to by \tcode{r}.

\pnum
\returns
The iterator immediately following \tcode{r} prior to the erasure.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}.
\end{itemdescr}

\indexunordmem{erase}%
\begin{itemdecl}
a.erase(q1, q2)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{iterator}

\pnum
\effects
Erases all elements in the range \range{q1}{q2}.

\pnum
\returns
The iterator immediately following the erased elements prior to the erasure.

\pnum
\complexity
Average case linear in \tcode{distance(q1, q2)},
worst case \bigoh{\tcode{a.size()}}.
\end{itemdescr}

\indexunordmem{clear}%
\begin{itemdecl}
a.clear()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\effects
Erases all elements in the container.

\pnum
\ensures
\tcode{a.empty()} is \tcode{true}.

\pnum
\complexity
Linear in \tcode{a.size()}.
\end{itemdescr}

\indexunordmem{find}%
\begin{itemdecl}
b.find(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_iterator} if \tcode{b} is of type \tcode{const X};
\tcode{iterator} otherwise.

\pnum
\returns
An iterator pointing to an element with key equivalent to \tcode{k}, or
\tcode{b.end()} if no such element exists.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{b.size()}}.
\end{itemdescr}

\indexunordmem{find}%
\begin{itemdecl}
a_tran.find(ke)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_iterator} if \tcode{a_tran} is of type \tcode{const X};
\tcode{iterator} otherwise.

\pnum
\returns
An iterator pointing to an element with key equivalent to \tcode{ke}, or
\tcode{a_tran.end()} if no such element exists.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a_tran.size()}}.
\end{itemdescr}

\indexunordmem{count}%
\begin{itemdecl}
b.count(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}

\pnum
\returns
The number of elements with key equivalent to \tcode{k}.

\pnum
\complexity
Average case \bigoh{\tcode{b.count(k)}}, worst case \bigoh{\tcode{b.size()}}.
\end{itemdescr}

\indexunordmem{count}%
\begin{itemdecl}
a_tran.count(ke)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}

\pnum
\returns
The number of elements with key equivalent to \tcode{ke}.

\pnum
\complexity
Average case \bigoh{\tcode{a_tran.count(ke)}},
worst case \bigoh{\tcode{a_tran.size()}}.
\end{itemdescr}

\indexunordmem{contains}%
\begin{itemdecl}
b.contains(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{b.find(k) != b.end()}.
\end{itemdescr}

\indexunordmem{contains}%
\begin{itemdecl}
a_tran.contains(ke)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{a_tran.find(ke) != a_tran.end()}.
\end{itemdescr}

\indexunordmem{equal_range}%
\begin{itemdecl}
b.equal_range(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{pair<const_iterator, const_iterator>}
if \tcode{b} is of type \tcode{const X};
\tcode{pair<iter\-ator, iter\-ator>} otherwise.

\pnum
\returns
A range containing all elements with keys equivalent to \tcode{k}.
Returns \tcode{make_pair(b.end(), b.end())} if no such elements exist.

\pnum
\complexity
Average case \bigoh{\tcode{b.count(k)}}, worst case \bigoh{\tcode{b.size()}}.
\end{itemdescr}

\indexunordmem{equal_range}%
\begin{itemdecl}
a_tran.equal_range(ke)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{pair<const_iterator, const_iterator>}
if \tcode{a_tran} is of type \tcode{const X};
\tcode{pair<iter\-ator, iter\-ator>} otherwise.

\pnum
\returns
A range containing all elements with keys equivalent to \tcode{ke}.
Returns \tcode{make_pair(a_tran.end(), a_tran.end())} if no such elements exist.

\pnum
\complexity
Average case \bigoh{\tcode{a_tran.count(ke)}},
worst case \bigoh{\tcode{a_tran.size()}}.
\end{itemdescr}

\indexunordmem{bucket_count}%
\begin{itemdecl}
b.bucket_count()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}

\pnum
\returns
The number of buckets that \tcode{b} contains.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexunordmem{max_bucket_count}%
\begin{itemdecl}
b.max_bucket_count()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}

\pnum
\returns
An upper bound on the number of buckets that \tcode{b} can ever contain.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexunordmem{bucket}%
\begin{itemdecl}
b.bucket(k)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}

\pnum
\expects
\tcode{b.bucket_count() > 0}.

\pnum
\returns
The index of the bucket
in which elements with keys equivalent to \tcode{k} would be found,
if any such element existed.
The return value is in the range \range{0}{b.bucket_count()}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexunordmem{bucket}%
\begin{itemdecl}
a_tran.bucket(ke)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}

\pnum
\expects
\tcode{a_tran.bucket_count() > 0}.

\pnum
\ensures
The return value is in the range \range{0}{a_tran.bucket_count()}.

\pnum
\returns
The index of the bucket
in which elements with keys equivalent to \tcode{ke} would be found,
if any such element existed.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexunordmem{bucket_size}%
\begin{itemdecl}
b.bucket_size(n)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{size_type}

\pnum
\expects
\tcode{n} shall be in the range \range{0}{b.bucket_count()}.

\pnum
\returns
The number of elements in the $\tcode{n}^\text{th}$ bucket.

\pnum
\complexity
\bigoh{\tcode{b.bucket_size(n)}}
\end{itemdescr}

\indexunordmem{begin}%
\begin{itemdecl}
b.begin(n)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_local_iterator} if \tcode{b} is of type \tcode{const X};
\tcode{local_iterator} otherwise.

\pnum
\expects
\tcode{n} is in the range \range{0}{b.bucket_count()}.

\pnum
\returns
An iterator referring to the first element in the bucket.
If the bucket is empty, then \tcode{b.begin(n) == b.end(n)}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexunordmem{end}%
\begin{itemdecl}
b.end(n)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_local_iterator} if \tcode{b} is of type \tcode{const X};
\tcode{local_iterator} otherwise.

\pnum
\expects
\tcode{n} is in the range \range{0}{b.bucket_count()}.

\pnum
\returns
An iterator which is the past-the-end value for the bucket.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexunordmem{cbegin}%
\begin{itemdecl}
b.cbegin(n)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_local_iterator}

\pnum
\expects
\tcode{n} shall be in the range \range{0}{b.bucket_count()}.

\pnum
\returns
An iterator referring to the first element in the bucket.
If the bucket is empty, then \tcode{b.cbegin(n) == b.cend(n)}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexunordmem{cend}%
\begin{itemdecl}
b.cend(n)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const_local_iterator}

\pnum
\expects
\tcode{n} is in the range \range{0}{b.bucket_count()}.

\pnum
\returns
An iterator which is the past-the-end value for the bucket.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexunordmem{load_factor}%
\begin{itemdecl}
b.load_factor()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{float}

\pnum
\returns
The average number of elements per bucket.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexunordmem{max_load_factor}%
\begin{itemdecl}
b.max_load_factor()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{float}

\pnum
\returns
A positive number
that the container attempts to keep the load factor less than or equal to.
The container automatically increases the number of buckets as necessary
to keep the load factor below this number.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexunordmem{max_load_factor}%
\begin{itemdecl}
a.max_load_factor(z)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\expects
\tcode{z} is positive.
May change the container's maximum load factor, using \tcode{z} as a hint.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexunordmem{rehash}%
\begin{itemdecl}
a.rehash(n)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\keyword{void}

\pnum
\ensures
\tcode{a.bucket_count() >= a.size() / a.max_load_factor()} and
\tcode{a.bucket_count() >= n}.%

\pnum
\complexity
Average case linear in \tcode{a.size()}, worst case quadratic.
\end{itemdescr}

\indexunordmem{reserve}%
\begin{itemdecl}
a.reserve(n)
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{a.rehash(ceil(n / a.max_load_factor()))}.
\end{itemdescr}

\pnum
Two unordered containers \tcode{a} and \tcode{b} compare equal if
\tcode{a.size() == b.size()} and, for every equivalent-key group
\range{Ea1}{Ea2} obtained from \tcode{a.equal_range(Ea1)}, there exists an
equivalent-key group \range{Eb1}{Eb2} obtained from \tcode{b.equal_range(Ea1)},
such that
\tcode{is_permutation(Ea1, Ea2, Eb1, Eb2)} returns \tcode{true}. For
\tcode{unordered_set} and \tcode{unordered_map}, the complexity of
\tcode{operator==} (i.e., the number of calls to the \tcode{==} operator
of the \tcode{value_type}, to the predicate returned by \tcode{key_eq()},
and to the hasher returned by \tcode{hash_function()}) is proportional to
$N$ in the average case and to $N^2$ in the worst case, where $N$ is
\tcode{a.size()}. For \tcode{unordered_multiset} and \tcode{unordered_multimap},
the complexity of \tcode{operator==} is proportional to $\sum E_i^2$
in the average case and to $N^2$ in the worst case, where $N$ is \tcode{a.size()},
and $E_i$ is the size of the $i^\text{th}$ equivalent-key group in \tcode{a}.
However, if the respective elements of each corresponding pair of
equivalent-key groups $Ea_i$ and $Eb_i$ are arranged in the same order
(as is commonly the case, e.g., if \tcode{a} and \tcode{b} are unmodified copies
of the same container), then the average-case complexity for
\tcode{unordered_multiset} and \tcode{unordered_multimap} becomes
proportional to $N$ (but worst-case complexity remains \bigoh{N^2}, e.g., for
a pathologically bad hash function). The behavior of a program that uses
\tcode{operator==} or \tcode{operator!=} on unordered containers is undefined
unless the \tcode{Pred} function object has
the same behavior for both containers and the equality comparison function
for \tcode{Key} is a refinement
\begin{footnote}
Equality comparison is a refinement
of partitioning if no two objects that
compare equal fall into different partitions.
\end{footnote}
of the partition into equivalent-key groups produced by \tcode{Pred}.

\pnum
\indextext{unordered associative containers!iterators}%
The iterator types \tcode{iterator} and \tcode{const_iterator} of
an unordered associative container are of at least the forward iterator
category.  For unordered associative containers where the key type and
value type are the same, both \tcode{iterator} and
\tcode{const_iterator} are constant iterators.

\pnum
\indextext{unordered associative containers!iterator invalidation}%
The \tcode{insert}, \tcode{insert_range}, and \tcode{emplace} members
shall not affect the validity of references to
container elements, but may invalidate all iterators to the
container.  The \tcode{erase} members shall invalidate only iterators and
references to the erased elements, and preserve the relative order of the
elements that are not erased.

\pnum
\indextext{unordered associative containers!iterator invalidation}%
\indextext{unordered associative containers!requirements}%
The \tcode{insert}, \tcode{insert_range}, and \tcode{emplace} members
shall not affect the validity of iterators if
\tcode{(N + n) <= z * B}, where \tcode{N} is the number of elements in
the container prior to the insert operation, \tcode{n} is the
number of elements inserted, \tcode{B} is the container's bucket count, and
\tcode{z} is the container's maximum load factor.

\pnum
The \tcode{extract} members invalidate only iterators to the removed element,
and preserve the relative order of the elements that are not erased; pointers
and references to the removed element remain valid. However, accessing the
element through such pointers and references while the element is owned by a
\tcode{node_type} is undefined behavior. References and pointers to an element
obtained while it is owned by a \tcode{node_type} are invalidated if the
element is successfully inserted.

\pnum
The member function templates
\tcode{find}, \tcode{count}, \tcode{equal_range}, \tcode{contains},
\tcode{extract}, \tcode{erase}, and \tcode{bucket}
shall not participate in overload resolution unless
the \grammarterm{qualified-id}s
\tcode{Pred::is_transparent} and
\tcode{Hash::is_transparent}
are both valid and denote types\iref{temp.deduct}.
Additionally, the member function templates \tcode{extract} and \tcode{erase}
shall not participate in overload resolution if
\tcode{is_convertible_v<K\&\&, iterator> || is_convertible_v<K\&\&, const_iterator>}
is \tcode{true},
where \tcode{K} is the type substituted as the first template argument.

\pnum
A deduction guide for an unordered associative container shall not participate in overload resolution
if any of the following are true:
\begin{itemize}
\item It has an \tcode{InputIterator} template parameter
and a type that does not qualify as an input iterator is deduced for that parameter.

\item It has an \tcode{Allocator} template parameter
and a type that does not qualify as an allocator is deduced for that parameter.

\item It has a \tcode{Hash} template parameter
and an integral type or a type that qualifies as an allocator is deduced for that parameter.

\item It has a \tcode{Pred} template parameter
and a type that qualifies as an allocator is deduced for that parameter.
\end{itemize}

\rSec3[unord.req.except]{Exception safety guarantees}

\pnum
\indextext{unordered associative containers!exception safety}%
\indextext{unordered associative containers!requirements}%
For unordered associative containers, no \tcode{clear()} function
throws an exception. \tcode{erase(k)} does not throw an
exception unless that exception is thrown by the container's \tcode{Hash} or
\tcode{Pred} object (if any).

\pnum
For unordered associative containers, if an exception is thrown by any
operation other than the container's hash function from within an
\tcode{insert} or \tcode{emplace} function inserting a single element,
the insertion has no effect.

\pnum
For unordered associative containers, no \tcode{swap} function throws
an exception unless that exception is thrown by the swap of the container's
\tcode{Hash} or \tcode{Pred} object (if any).

\pnum
\indextext{unordered associative containers!exception safety}%
\indextext{unordered associative containers!requirements}%
For unordered associative containers, if an exception is thrown
from within a \tcode{rehash()} function other than by the container's hash
function or comparison function, the \tcode{rehash()} function has no effect.

\rSec1[sequences]{Sequence containers}

\rSec2[sequences.general]{General}

\pnum
The headers
\libheaderref{array},
\libheaderref{deque},
\libheaderrefx{forward_list}{forward.list.syn},
\libheaderref{hive},
\libheaderrefx{inplace_vector}{inplace.vector.syn},
\libheaderref{list}, and
\libheaderref{vector}
define class templates that meet the requirements for sequence containers.

\pnum
The following exposition-only alias template may appear in deduction guides for sequence containers:

\begin{codeblock}
template<class InputIterator>
  using @\placeholdernc{iter-value-type}@ = iterator_traits<InputIterator>::value_type;  // \expos
\end{codeblock}

\rSec2[array.syn]{Header \tcode{<array>} synopsis}

\indexheader{array}%
\begin{codeblock}
// mostly freestanding
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{array}, class template \tcode{array}
  template<class T, size_t N> struct array;                             // partially freestanding

  template<class T, size_t N>
    constexpr bool operator==(const array<T, N>& x, const array<T, N>& y);
  template<class T, size_t N>
    constexpr @\exposid{synth-three-way-result}@<T>
      operator<=>(const array<T, N>& x, const array<T, N>& y);

  // \ref{array.special}, specialized algorithms
  template<class T, size_t N>
    constexpr void swap(array<T, N>& x, array<T, N>& y) noexcept(noexcept(x.swap(y)));

  // \ref{array.creation}, array creation functions
  template<class T, size_t N>
    constexpr array<remove_cv_t<T>, N> to_array(T (&a)[N]);
  template<class T, size_t N>
    constexpr array<remove_cv_t<T>, N> to_array(T (&&a)[N]);

  // \ref{array.tuple}, tuple interface
  template<class T> struct tuple_size;
  template<size_t I, class T> struct tuple_element;
  template<class T, size_t N>
    struct tuple_size<array<T, N>>;
  template<size_t I, class T, size_t N>
    struct tuple_element<I, array<T, N>>;
  template<size_t I, class T, size_t N>
    constexpr T& get(array<T, N>&) noexcept;
  template<size_t I, class T, size_t N>
    constexpr T&& get(array<T, N>&&) noexcept;
  template<size_t I, class T, size_t N>
    constexpr const T& get(const array<T, N>&) noexcept;
  template<size_t I, class T, size_t N>
    constexpr const T&& get(const array<T, N>&&) noexcept;
}
\end{codeblock}

\rSec2[array]{Class template \tcode{array}}
\indexlibraryglobal{array}%

\rSec3[array.overview]{Overview}

\pnum
\indextext{\idxcode{array}!contiguous storage}%
The header \libheader{array} defines a class template for storing fixed-size
sequences of objects.
An \tcode{array} is a contiguous container\iref{container.reqmts}.
An instance of \tcode{array<T, N>} stores \tcode{N} elements of type \tcode{T},
so that \tcode{size() == N} is an invariant.

\pnum
\indextext{\idxcode{array}!initialization}%
\indextext{\idxcode{array}!as aggregate}%
An \tcode{array} is an aggregate\iref{dcl.init.aggr} that can be
list-initialized with up
to \tcode{N} elements whose types are convertible to \tcode{T}.

\pnum
\indextext{requirements!container}%
An \tcode{array} meets all of the requirements
of a container\iref{container.reqmts} and
of a reversible container\iref{container.rev.reqmts},
except that a default
constructed \tcode{array} object is not empty if $\tcode{N} > 0$.
An \tcode{array} meets some of the requirements of a sequence
container\iref{sequence.reqmts}.
Descriptions are provided here
only for operations on \tcode{array} that are not described in
one of these tables and
for operations where there is additional semantic information.

\pnum
\tcode{array<T, N>} is a structural type\iref{term.structural.type} if
\tcode{T} is a structural type.
Two values \tcode{a1} and \tcode{a2} of type \tcode{array<T, N>}
are template-argument-equivalent\iref{temp.type} if and only if
each pair of corresponding elements in \tcode{a1} and \tcode{a2}
are template-argument-equivalent.

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\indexlibraryglobal{array}%
\indexlibrarymember{array}{begin}%
\indexlibrarymember{array}{end}%
\indexlibrarymember{array}{size}%
\indexlibrarymember{array}{max_size}%
\begin{codeblock}
namespace std {
  template<class T, size_t N>
  struct array {
    // types
    using value_type             = T;
    using pointer                = T*;
    using const_pointer          = const T*;
    using reference              = T&;
    using const_reference        = const T&;
    using size_type              = size_t;
    using difference_type        = ptrdiff_t;
    using iterator               = @\impdefx{type of \tcode{array::iterator}}@; // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{array::const_iterator}}@; // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // no explicit construct/copy/destroy for aggregate type

    constexpr void fill(const T& u);
    constexpr void swap(array&) noexcept(is_nothrow_swappable_v<T>);

    // iterators
    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;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // element access
    constexpr reference       operator[](size_type n);
    constexpr const_reference operator[](size_type n) const;
    constexpr reference       at(size_type n);                          // freestanding-deleted
    constexpr const_reference at(size_type n) const;                    // freestanding-deleted
    constexpr reference       front();
    constexpr const_reference front() const;
    constexpr reference       back();
    constexpr const_reference back() const;

    constexpr T*       data() noexcept;
    constexpr const T* data() const noexcept;
  };

  template<class T, class... U>
    array(T, U...) -> array<T, 1 + sizeof...(U)>;
}
\end{codeblock}

\rSec3[array.cons]{Constructors, copy, and assignment}

\pnum
\indextext{\idxcode{array}!initialization}%
\indextext{requirements!container}%
An \tcode{array} relies on the implicitly-declared special
member functions\iref{class.default.ctor,class.dtor,class.copy.ctor} to
conform to the container requirements table in~\ref{container.requirements}.
In addition to the requirements specified in the container requirements table,
the implicitly-declared move constructor and move assignment operator for \tcode{array}
require that \tcode{T} be \oldconcept{MoveConstructible} or \oldconcept{MoveAssignable},
respectively.

\begin{itemdecl}
template<class T, class... U>
  array(T, U...) -> array<T, 1 + sizeof...(U)>;
\end{itemdecl}
\begin{itemdescr}
\pnum
\mandates
\tcode{(is_same_v<T, U> \&\& ...)} is \tcode{true}.
\end{itemdescr}

\rSec3[array.members]{Member functions}

\indexlibrarymember{array}{size}%
\begin{itemdecl}
constexpr size_type size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{N}.
\end{itemdescr}

\indexlibrarymember{array}{data}%
\begin{itemdecl}
constexpr T* data() noexcept;
constexpr const T* data() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A pointer such that \range{data()}{data() + size()} is a valid range. For a
non-empty array, \tcode{data() == addressof(front())} is \keyword{true}.
\end{itemdescr}

\indexlibrarymember{array}{fill}%
\begin{itemdecl}
constexpr void fill(const T& u);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
As if by \tcode{fill_n(begin(), N, u)}.
\end{itemdescr}

\indexlibrarymember{array}{swap}%
\begin{itemdecl}
constexpr void swap(array& y) noexcept(is_nothrow_swappable_v<T>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{swap_ranges(begin(), end(), y.begin())}.

\pnum
\begin{note}
Unlike the \tcode{swap} function for other containers, \tcode{array::swap}
takes linear time, can exit via an exception, and does not cause iterators to
become associated with the other container.
\end{note}
\end{itemdescr}

\rSec3[array.special]{Specialized algorithms}

\indexlibrarymember{array}{swap}%
\begin{itemdecl}
template<class T, size_t N>
  constexpr void swap(array<T, N>& x, array<T, N>& y) noexcept(noexcept(x.swap(y)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{N == 0} or \tcode{is_swappable_v<T>} is \tcode{true}.

\pnum
\effects
As if by \tcode{x.swap(y)}.

\pnum
\complexity
Linear in \tcode{N}.
\end{itemdescr}

\rSec3[array.zero]{Zero-sized arrays}

\indextext{\idxcode{array}!zero sized}%
\pnum
\tcode{array} shall provide support for the special case \tcode{N == 0}.

\pnum
In the case that \tcode{N == 0}, \tcode{begin() == end() ==} unique value.
The return value of \tcode{data()} is unspecified.

\pnum
Member function \tcode{swap()} shall have a
non-throwing exception specification.

\rSec3[array.creation]{Array creation functions}
\indextext{\idxcode{array}!creation}%

\indexlibraryglobal{to_array}%
\begin{itemdecl}
template<class T, size_t N>
  constexpr array<remove_cv_t<T>, N> to_array(T (&a)[N]);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_array_v<T>} is \tcode{false} and
\tcode{is_constructible_v<remove_cv_t<T>, T\&>} is \tcode{true}.

\pnum
\expects
\tcode{T} meets the \oldconcept{CopyConstructible} requirements.

\pnum
\returns
\tcode{\{\{ a[0], $\dotsc$, a[N - 1] \}\}}.
\end{itemdescr}

\indexlibraryglobal{to_array}%
\begin{itemdecl}
template<class T, size_t N>
  constexpr array<remove_cv_t<T>, N> to_array(T (&&a)[N]);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_array_v<T>} is \tcode{false} and
\tcode{is_constructible_v<remove_cv_t<T>, T>} is \tcode{true}.

\pnum
\expects
\tcode{T} meets the \oldconcept{MoveConstructible} requirements.

\pnum
\returns
\tcode{\{\{ std::move(a[0]), $\dotsc$, std::move(a[N - 1]) \}\}}.
\end{itemdescr}

\rSec3[array.tuple]{Tuple interface}
\indexlibraryglobal{array}%
\indexlibraryglobal{tuple}%
\indextext{\idxcode{array}!tuple interface to}%
\indexlibraryglobal{tuple_size}%
\begin{itemdecl}
template<class T, size_t N>
  struct tuple_size<array<T, N>> : integral_constant<size_t, N> { };
\end{itemdecl}

\indexlibraryglobal{tuple_element}%
\begin{itemdecl}
template<size_t I, class T, size_t N>
  struct tuple_element<I, array<T, N>> {
    using type = T;
  };
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{I < N} is \tcode{true}.
\end{itemdescr}

\indexlibrarymember{array}{get}%
\begin{itemdecl}
template<size_t I, class T, size_t N>
  constexpr T& get(array<T, N>& a) noexcept;
template<size_t I, class T, size_t N>
  constexpr T&& get(array<T, N>&& a) noexcept;
template<size_t I, class T, size_t N>
  constexpr const T& get(const array<T, N>& a) noexcept;
template<size_t I, class T, size_t N>
  constexpr const T&& get(const array<T, N>&& a) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{I < N} is \tcode{true}.

\pnum
\returns
A reference to the $\tcode{I}^\text{th}$ element of \tcode{a},
where indexing is zero-based.
\end{itemdescr}

\rSec2[deque.syn]{Header \tcode{<deque>} synopsis}

\indexheader{deque}%
\begin{codeblock}
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{deque}, class template \tcode{deque}
  template<class T, class Allocator = allocator<T>> class deque;

  template<class T, class Allocator>
    constexpr bool operator==(const deque<T, Allocator>& x, const deque<T, Allocator>& y);
  template<class T, class Allocator>
    constexpr @\exposid{synth-three-way-result}@<T>
      operator<=>(const deque<T, Allocator>& x, const deque<T, Allocator>& y);

  template<class T, class Allocator>
    constexpr void swap(deque<T, Allocator>& x, deque<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  // \ref{deque.erasure}, erasure
  template<class T, class Allocator, class U = T>
    constexpr typename deque<T, Allocator>::size_type
      erase(deque<T, Allocator>& c, const U& value);
  template<class T, class Allocator, class Predicate>
    constexpr typename deque<T, Allocator>::size_type
      erase_if(deque<T, Allocator>& c, Predicate pred);

  namespace pmr {
    template<class T>
      using deque = std::deque<T, polymorphic_allocator<T>>;
  }
}
\end{codeblock}

\rSec2[deque]{Class template \tcode{deque}}

\rSec3[deque.overview]{Overview}

\pnum
A
\indexlibraryglobal{deque}%
\tcode{deque}
is a sequence container that supports random access iterators\iref{random.access.iterators}.
In addition, it supports constant time insert and erase operations at the beginning or the end;
insert and erase in the middle take linear time.
That is, a deque is especially optimized for pushing and popping elements at the beginning and end.
Storage management is handled automatically.

\pnum
A \tcode{deque} meets all of the requirements
of a container\iref{container.reqmts},
of a reversible container\iref{container.rev.reqmts},
of an allocator-aware container\iref{container.alloc.reqmts}, and
of a sequence container,
including the optional sequence container requirements\iref{sequence.reqmts}.
Descriptions are provided here only for operations on
\tcode{deque}
that are not described in one of these tables
or for operations where there is additional semantic information.

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\begin{codeblock}
namespace std {
  template<class T, class Allocator = allocator<T>>
  class deque {
  public:
    // types
    using value_type             = T;
    using allocator_type         = Allocator;
    using pointer                = allocator_traits<Allocator>::pointer;
    using const_pointer          = allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\impdefx{type of \tcode{deque::size_type}}@; // see \ref{container.requirements}
    using difference_type        = @\impdefx{type of \tcode{deque::difference_type}}@; // see \ref{container.requirements}
    using iterator               = @\impdefx{type of \tcode{deque::iterator}}@; // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{deque::const_iterator}}@; // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // \ref{deque.cons}, construct/copy/destroy
    constexpr deque() : deque(Allocator()) { }
    constexpr explicit deque(const Allocator&);
    constexpr explicit deque(size_type n, const Allocator& = Allocator());
    constexpr deque(size_type n, const T& value, const Allocator& = Allocator());
    template<class InputIterator>
      constexpr deque(InputIterator first, InputIterator last, const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr deque(from_range_t, R&& rg, const Allocator& = Allocator());
    constexpr deque(const deque& x);
    constexpr deque(deque&&);
    constexpr deque(const deque&, const type_identity_t<Allocator>&);
    constexpr deque(deque&&, const type_identity_t<Allocator>&);
    constexpr deque(initializer_list<T>, const Allocator& = Allocator());

    constexpr ~deque();
    constexpr deque& operator=(const deque& x);
    constexpr deque& operator=(deque&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    constexpr deque& operator=(initializer_list<T>);
    template<class InputIterator>
      constexpr void assign(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr void assign_range(R&& rg);
    constexpr void assign(size_type n, const T& t);
    constexpr void assign(initializer_list<T>);
    constexpr allocator_type get_allocator() const noexcept;

    // iterators
    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;

    // \ref{deque.capacity}, capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;
    constexpr void      resize(size_type sz);
    constexpr void      resize(size_type sz, const T& c);
    constexpr void      shrink_to_fit();

    // element access
    constexpr reference       operator[](size_type n);
    constexpr const_reference operator[](size_type n) const;
    constexpr reference       at(size_type n);
    constexpr const_reference at(size_type n) const;
    constexpr reference       front();
    constexpr const_reference front() const;
    constexpr reference       back();
    constexpr const_reference back() const;

    // \ref{deque.modifiers}, modifiers
    template<class... Args> constexpr reference emplace_front(Args&&... args);
    template<class... Args> constexpr reference emplace_back(Args&&... args);
    template<class... Args> constexpr iterator emplace(const_iterator position, Args&&... args);

    constexpr void push_front(const T& x);
    constexpr void push_front(T&& x);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr void prepend_range(R&& rg);
    constexpr void push_back(const T& x);
    constexpr void push_back(T&& x);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr void append_range(R&& rg);

    constexpr iterator insert(const_iterator position, const T& x);
    constexpr iterator insert(const_iterator position, T&& x);
    constexpr iterator insert(const_iterator position, size_type n, const T& x);
    template<class InputIterator>
      constexpr iterator insert(const_iterator position,
                                InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr iterator insert_range(const_iterator position, R&& rg);
    constexpr iterator insert(const_iterator position, initializer_list<T>);

    constexpr void pop_front();
    constexpr void pop_back();

    constexpr iterator erase(const_iterator position);
    constexpr iterator erase(const_iterator first, const_iterator last);
    constexpr void     swap(deque&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    constexpr void     clear() noexcept;
  };

  template<class InputIterator, class Allocator = allocator<@\placeholder{iter-value-type}@<InputIterator>>>
    deque(InputIterator, InputIterator, Allocator = Allocator())
      -> deque<@\placeholder{iter-value-type}@<InputIterator>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator = allocator<ranges::range_value_t<R>>>
    deque(from_range_t, R&&, Allocator = Allocator())
      -> deque<ranges::range_value_t<R>, Allocator>;
}
\end{codeblock}

\rSec3[deque.cons]{Constructors, copy, and assignment}

\indexlibraryctor{deque}%
\begin{itemdecl}
constexpr explicit deque(const Allocator&);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty
\tcode{deque},
using the specified allocator.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{deque}%
\begin{itemdecl}
constexpr explicit deque(size_type n, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{deque}.

\pnum
\effects
Constructs a \tcode{deque} with
\tcode{n} default-inserted elements using the specified allocator.

\pnum
\complexity
Linear in \tcode{n}.
\end{itemdescr}

\indexlibraryctor{deque}%
\begin{itemdecl}
constexpr deque(size_type n, const T& value, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{deque}.

\pnum
\effects
Constructs a
\tcode{deque}
with \tcode{n} copies of \tcode{value},
using the specified allocator.

\pnum
\complexity
Linear in \tcode{n}.
\end{itemdescr}

\indexlibraryctor{deque}%
\begin{itemdecl}
template<class InputIterator>
  constexpr deque(InputIterator first, InputIterator last, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a
\tcode{deque}
equal to the range
\range{first}{last},
using the specified allocator.

\pnum
\complexity
Linear in \tcode{distance(first, last)}.
\end{itemdescr}

\indexlibraryctor{deque}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr deque(from_range_t, R&& rg, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{deque} with the elements of the range \tcode{rg},
using the specified allocator.

\pnum
\complexity
Linear in \tcode{ranges::distance(rg)}.
\end{itemdescr}

\rSec3[deque.capacity]{Capacity}

\indexlibrarymember{resize}{deque}%
\begin{itemdecl}
constexpr void resize(size_type sz);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{MoveInsertable} and \oldconcept{DefaultInsertable} into \tcode{deque}.

\pnum
\effects
If \tcode{sz < size()}, erases the last \tcode{size() - sz} elements
from the sequence. Otherwise,
appends \tcode{sz - size()} default-inserted elements to the sequence.
\end{itemdescr}

\indexlibrarymember{resize}{deque}%
\begin{itemdecl}
constexpr void resize(size_type sz, const T& c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{deque}.

\pnum
\effects
If \tcode{sz < size()}, erases the last \tcode{size() - sz} elements
from the sequence. Otherwise,
appends \tcode{sz - size()} copies of \tcode{c} to the sequence.
\end{itemdescr}

\indexlibrarymember{shrink_to_fit}{deque}%
\begin{itemdecl}
constexpr void shrink_to_fit();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{MoveInsertable} into \tcode{deque}.

\pnum
\effects
\tcode{shrink_to_fit} is a non-binding request to reduce memory use
but does not change the size of the sequence.
\begin{note}
The request is non-binding to allow latitude for
implementation-specific optimizations.
\end{note}
If the size is equal to the old capacity, or
if an exception is thrown other than by the move constructor
of a non-\oldconcept{CopyInsertable} \tcode{T},
then there are no effects.

\pnum
\complexity
If the size is not equal to the old capacity,
linear in the size of the sequence;
otherwise constant.

\pnum
\remarks
If the size is not equal to the old capacity,
then invalidates all the references, pointers, and iterators
referring to the elements in the sequence,
as well as the past-the-end iterator.
\end{itemdescr}

\rSec3[deque.modifiers]{Modifiers}

\indexlibrarymember{insert}{deque}%
\indexlibrarymember{push_front}{deque}%
\indexlibrarymember{push_back}{deque}%
\indexlibrarymember{emplace}{deque}%
\begin{itemdecl}
constexpr iterator insert(const_iterator position, const T& x);
constexpr iterator insert(const_iterator position, T&& x);
constexpr iterator insert(const_iterator position, size_type n, const T& x);
template<class InputIterator>
  constexpr iterator insert(const_iterator position,
                            InputIterator first, InputIterator last);
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr iterator insert_range(const_iterator position, R&& rg);
constexpr iterator insert(const_iterator position, initializer_list<T>);

template<class... Args> constexpr reference emplace_front(Args&&... args);
template<class... Args> constexpr reference emplace_back(Args&&... args);
template<class... Args> constexpr iterator emplace(const_iterator position, Args&&... args);
constexpr void push_front(const T& x);
constexpr void push_front(T&& x);
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr void prepend_range(R&& rg);
constexpr void push_back(const T& x);
constexpr void push_back(T&& x);
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr void append_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
An insertion in the middle of the deque invalidates all the iterators and
references to elements of the deque.
An insertion at either end of the
deque invalidates all the iterators to the deque, but has no effect on
the validity of references to elements of the deque.

\pnum
\complexity
The complexity is linear in the number of elements inserted plus the lesser
of the distances to the beginning and end of the deque.
Inserting a single element at either the beginning or end of a deque always takes constant time
and causes a single call to a constructor of
\tcode{T}.

\pnum
\remarks
If an exception is thrown other than by the
copy constructor, move constructor,
assignment operator, or move assignment operator of
\tcode{T},
there are no effects.
If an exception is thrown while inserting a single element at either end,
there are no effects.
Otherwise, if an exception is thrown by the move constructor of a
non-\oldconcept{CopyInsertable}
\tcode{T}, the effects are unspecified.
\end{itemdescr}

\indexlibrarymember{erase}{deque}%
\begin{itemdecl}
constexpr iterator erase(const_iterator position);
constexpr iterator erase(const_iterator first, const_iterator last);
constexpr void pop_front();
constexpr void pop_back();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
An erase operation that erases the last element of a deque invalidates only the past-the-end iterator
and all iterators and references to the erased elements. An erase operation that erases the first
element of a deque but not the last element invalidates only iterators
and references to the erased elements. An erase operation
that erases neither the first element nor the last element of a deque invalidates the past-the-end
iterator and all iterators and references to all the elements of the deque.
\begin{note}
\tcode{pop_front} and \tcode{pop_back} are erase operations.
\end{note}

\pnum
\throws
Nothing unless an exception is thrown by the assignment operator of
\tcode{T}.

\pnum
\complexity
The number of calls to the destructor of \tcode{T} is the same as the
number of elements erased, but the number of calls to the assignment operator of \tcode{T} is
no more than the lesser of the number of elements before the erased elements and the number of elements after the erased elements.
\end{itemdescr}

\rSec3[deque.erasure]{Erasure}

\indexlibrarymember{erase}{deque}%
\begin{itemdecl}
template<class T, class Allocator, class U = T>
  constexpr typename deque<T, Allocator>::size_type
    erase(deque<T, Allocator>& c, const U& value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto it = remove(c.begin(), c.end(), value);
auto r = distance(it, c.end());
c.erase(it, c.end());
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{erase_if}{deque}%
\begin{itemdecl}
template<class T, class Allocator, class Predicate>
  constexpr typename deque<T, Allocator>::size_type
    erase_if(deque<T, Allocator>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto it = remove_if(c.begin(), c.end(), pred);
auto r = distance(it, c.end());
c.erase(it, c.end());
return r;
\end{codeblock}
\end{itemdescr}

\rSec2[forward.list.syn]{Header \tcode{<forward_list>} synopsis}

\indexheader{forward_list}%
\begin{codeblock}
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{forward.list}, class template \tcode{forward_list}
  template<class T, class Allocator = allocator<T>> class forward_list;

  template<class T, class Allocator>
    constexpr bool operator==(const forward_list<T, Allocator>& x,
                              const forward_list<T, Allocator>& y);
  template<class T, class Allocator>
    constexpr @\exposid{synth-three-way-result}@<T>
      operator<=>(const forward_list<T, Allocator>& x,
                  const forward_list<T, Allocator>& y);

  template<class T, class Allocator>
    constexpr void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  // \ref{forward.list.erasure}, erasure
  template<class T, class Allocator, class U = T>
    constexpr typename forward_list<T, Allocator>::size_type
      erase(forward_list<T, Allocator>& c, const U& value);
  template<class T, class Allocator, class Predicate>
    constexpr typename forward_list<T, Allocator>::size_type
      erase_if(forward_list<T, Allocator>& c, Predicate pred);

  namespace pmr {
    template<class T>
      using forward_list = std::forward_list<T, polymorphic_allocator<T>>;
  }
}
\end{codeblock}

\rSec2[forward.list]{Class template \tcode{forward_list}}

\rSec3[forward.list.overview]{Overview}

\pnum
A \tcode{forward_list} is a container that supports forward iterators and allows
constant time insert and erase operations anywhere within the sequence, with storage
management handled automatically. Fast random access to list elements is not supported.
\begin{note}
It is intended that \tcode{forward_list} have zero space or time overhead
relative to a hand-written C-style singly linked list. Features that would conflict with
that goal have been omitted.
\end{note}

\pnum
A \tcode{forward_list} meets all of the requirements
of a container\iref{container.reqmts},
except that the \tcode{size()} member function is not provided and
\tcode{operator==} has linear complexity.
A \tcode{forward_list} also meets all of the requirements
for an allocator-aware container\iref{container.alloc.reqmts}.
In addition, a \tcode{forward_list}
provides the \tcode{assign} member functions and
several of the optional sequence container requirements\iref{sequence.reqmts}.
Descriptions are provided here only for operations on
\tcode{forward_list} that are not described in that table or for operations where there
is additional semantic information.

\pnum
\begin{note}
Modifying any list requires access to the element preceding the first element
of interest, but in a \tcode{forward_list} there is no constant-time way to access a
preceding element.
For this reason, \tcode{erase_after} and \tcode{splice_after}
take fully-open ranges, not semi-open ranges.
\end{note}

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\begin{codeblock}
namespace std {
  template<class T, class Allocator = allocator<T>>
  class forward_list {
  public:
    // types
    using value_type      = T;
    using allocator_type  = Allocator;
    using pointer         = allocator_traits<Allocator>::pointer;
    using const_pointer   = allocator_traits<Allocator>::const_pointer;
    using reference       = value_type&;
    using const_reference = const value_type&;
    using size_type       = @\impdefx{type of \tcode{forward_list::size_type}}@; // see \ref{container.requirements}
    using difference_type = @\impdefx{type of \tcode{forward_list::difference_type}}@; // see \ref{container.requirements}
    using iterator        = @\impdefx{type of \tcode{forward_list::iterator}}@; // see \ref{container.requirements}
    using const_iterator  = @\impdefx{type of \tcode{forward_list::const_iterator}}@; // see \ref{container.requirements}

    // \ref{forward.list.cons}, construct/copy/destroy
    constexpr forward_list() : forward_list(Allocator()) { }
    constexpr explicit forward_list(const Allocator&);
    constexpr explicit forward_list(size_type n, const Allocator& = Allocator());
    constexpr forward_list(size_type n, const T& value, const Allocator& = Allocator());
    template<class InputIterator>
      constexpr forward_list(InputIterator first, InputIterator last,
                             const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr forward_list(from_range_t, R&& rg, const Allocator& = Allocator());
    constexpr forward_list(const forward_list& x);
    constexpr forward_list(forward_list&& x);
    constexpr forward_list(const forward_list& x, const type_identity_t<Allocator>&);
    constexpr forward_list(forward_list&& x, const type_identity_t<Allocator>&);
    constexpr forward_list(initializer_list<T>, const Allocator& = Allocator());
    constexpr ~forward_list();
    constexpr forward_list& operator=(const forward_list& x);
    constexpr forward_list& operator=(forward_list&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    constexpr forward_list& operator=(initializer_list<T>);
    template<class InputIterator>
      constexpr void assign(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr void assign_range(R&& rg);
    constexpr void assign(size_type n, const T& t);
    constexpr void assign(initializer_list<T>);
    constexpr allocator_type get_allocator() const noexcept;

    // \ref{forward.list.iter}, iterators
    constexpr iterator before_begin() noexcept;
    constexpr const_iterator before_begin() const noexcept;
    constexpr iterator begin() noexcept;
    constexpr const_iterator begin() const noexcept;
    constexpr iterator end() noexcept;
    constexpr const_iterator end() const noexcept;

    constexpr const_iterator cbegin() const noexcept;
    constexpr const_iterator cbefore_begin() const noexcept;
    constexpr const_iterator cend() const noexcept;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type max_size() const noexcept;

    // \ref{forward.list.access}, element access
    constexpr reference front();
    constexpr const_reference front() const;

    // \ref{forward.list.modifiers}, modifiers
    template<class... Args> constexpr reference emplace_front(Args&&... args);
    constexpr void push_front(const T& x);
    constexpr void push_front(T&& x);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr void prepend_range(R&& rg);
    constexpr void pop_front();

    template<class... Args>
      constexpr iterator emplace_after(const_iterator position, Args&&... args);
    constexpr iterator insert_after(const_iterator position, const T& x);
    constexpr iterator insert_after(const_iterator position, T&& x);

    constexpr iterator insert_after(const_iterator position, size_type n, const T& x);
    template<class InputIterator>
      constexpr iterator insert_after(const_iterator position,
                                      InputIterator first, InputIterator last);
    constexpr iterator insert_after(const_iterator position, initializer_list<T> il);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr iterator insert_range_after(const_iterator position, R&& rg);

    constexpr iterator erase_after(const_iterator position);
    constexpr iterator erase_after(const_iterator position, const_iterator last);
    constexpr void swap(forward_list&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);

    constexpr void resize(size_type sz);
    constexpr void resize(size_type sz, const value_type& c);
    constexpr void clear() noexcept;

    // \ref{forward.list.ops}, \tcode{forward_list} operations
    constexpr void splice_after(const_iterator position, forward_list& x);
    constexpr void splice_after(const_iterator position, forward_list&& x);
    constexpr void splice_after(const_iterator position, forward_list& x, const_iterator i);
    constexpr void splice_after(const_iterator position, forward_list&& x, const_iterator i);
    constexpr void splice_after(const_iterator position, forward_list& x,
                                const_iterator first, const_iterator last);
    constexpr void splice_after(const_iterator position, forward_list&& x,
                                const_iterator first, const_iterator last);

    constexpr size_type remove(const T& value);
    template<class Predicate> constexpr size_type remove_if(Predicate pred);

    constexpr size_type unique();
    template<class BinaryPredicate> constexpr size_type unique(BinaryPredicate binary_pred);

    constexpr void merge(forward_list& x);
    constexpr void merge(forward_list&& x);
    template<class Compare> constexpr void merge(forward_list& x, Compare comp);
    template<class Compare> constexpr void merge(forward_list&& x, Compare comp);

    constexpr void sort();
    template<class Compare> constexpr void sort(Compare comp);

    constexpr void reverse() noexcept;
  };

  template<class InputIterator, class Allocator = allocator<@\placeholder{iter-value-type}@<InputIterator>>>
    forward_list(InputIterator, InputIterator, Allocator = Allocator())
      -> forward_list<@\placeholder{iter-value-type}@<InputIterator>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator = allocator<ranges::range_value_t<R>>>
    forward_list(from_range_t, R&&, Allocator = Allocator())
      -> forward_list<ranges::range_value_t<R>, Allocator>;
}
\end{codeblock}

\pnum
An incomplete type \tcode{T} may be used when instantiating \tcode{forward_list}
if the allocator meets the
allocator completeness requirements\iref{allocator.requirements.completeness}.
\tcode{T} shall be complete before any member of the resulting specialization
of \tcode{forward_list} is referenced.

\rSec3[forward.list.cons]{Constructors, copy, and assignment}

\indexlibraryctor{forward_list}%
\begin{itemdecl}
constexpr explicit forward_list(const Allocator&);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{forward_list} object using the specified allocator.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{forward_list}%
\begin{itemdecl}
constexpr explicit forward_list(size_type n, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{forward_list}.

\pnum
\effects
Constructs a \tcode{forward_list} object with \tcode{n}
default-inserted elements using the specified allocator.

\pnum
\complexity
Linear in \tcode{n}.
\end{itemdescr}

\indexlibraryctor{forward_list}%
\begin{itemdecl}
constexpr forward_list(size_type n, const T& value, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{forward_list}.

\pnum
\effects
Constructs a \tcode{forward_list} object with \tcode{n} copies of \tcode{value} using the specified allocator.

\pnum
\complexity
Linear in \tcode{n}.
\end{itemdescr}

\indexlibraryctor{forward_list}%
\begin{itemdecl}
template<class InputIterator>
  constexpr forward_list(InputIterator first, InputIterator last, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{forward_list} object equal to the range \range{first}{last}.

\pnum
\complexity
Linear in \tcode{distance(first, last)}.
\end{itemdescr}

\indexlibraryctor{forward_list}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr forward_list(from_range_t, R&& rg, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{forward_list} object
with the elements of the range \tcode{rg}.

\pnum
\complexity
Linear in \tcode{ranges::distance(rg)}.
\end{itemdescr}

\rSec3[forward.list.iter]{Iterators}

\indexlibrarymember{before_begin}{forward_list}%
\indexlibrarymember{cbefore_begin}{forward_list}%
\begin{itemdecl}
constexpr iterator before_begin() noexcept;
constexpr const_iterator before_begin() const noexcept;
constexpr const_iterator cbefore_begin() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\tcode{cbefore_begin()} is equivalent to
\tcode{const_cast<forward_list const\&>(*this).before_begin()}.

\pnum
\returns
A non-dereferenceable iterator that, when incremented, is equal to the iterator
returned by \tcode{begin()}.

\pnum
\remarks
\tcode{before_begin() == end()} shall equal \tcode{false}.
\end{itemdescr}

\rSec3[forward.list.access]{Element access}

\indexlibrarymember{front}{forward_list}%
\begin{itemdecl}
constexpr reference front();
constexpr const_reference front() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{*begin()}
\end{itemdescr}

\rSec3[forward.list.modifiers]{Modifiers}

\pnum
The member functions in this subclause
do not affect the validity of iterators and references
when inserting elements, and when erasing elements
invalidate iterators and references to the erased elements only.
If an exception is thrown by any of these member functions
there is no effect on the container.
Inserting \tcode{n} elements into a \tcode{forward_list} is linear in
\tcode{n}, and the number of calls to the copy or move constructor of \tcode{T} is
exactly equal to \tcode{n}. Erasing \tcode{n} elements from a \tcode{forward_list} is
linear in \tcode{n} and the number of calls to the destructor of type \tcode{T} is
exactly equal to \tcode{n}.

\indexlibrarymember{emplace_front}{forward_list}%
\begin{itemdecl}
template<class... Args> constexpr reference emplace_front(Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Inserts an object of type \tcode{value_type} constructed with
\tcode{value_type(std::forward<Args>(\brk{}args)...)} at the beginning of the list.
\end{itemdescr}

\indexlibrarymember{push_front}{forward_list}%
\begin{itemdecl}
constexpr void push_front(const T& x);
constexpr void push_front(T&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Inserts a copy of \tcode{x} at the beginning of the list.
\end{itemdescr}

\indexlibrarymember{prepend_range}{forward_list}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr void prepend_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Inserts a copy of each element of \tcode{rg} at the beginning of the list.
\begin{note}
The order of elements is not reversed.
\end{note}
\end{itemdescr}

\indexlibrarymember{pop}{forward_list}%
\begin{itemdecl}
constexpr void pop_front();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
As if by \tcode{erase_after(before_begin())}.
\end{itemdescr}

\indexlibrarymember{insert_after}{forward_list}%
\begin{itemdecl}
constexpr iterator insert_after(const_iterator position, const T& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{forward_list}.
\tcode{position} is \tcode{before_begin()} or is a dereferenceable
iterator in the range \range{begin()}{end()}.

\pnum
\effects
Inserts a copy of \tcode{x} after \tcode{position}.

\pnum
\returns
An iterator pointing to the copy of \tcode{x}.
\end{itemdescr}

\indexlibrarymember{insert_after}{forward_list}%
\begin{itemdecl}
constexpr iterator insert_after(const_iterator position, T&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{MoveInsertable} into \tcode{forward_list}.
\tcode{position} is \tcode{before_begin()} or is a dereferenceable
iterator in the range \range{begin()}{end()}.

\pnum
\effects
Inserts a copy of \tcode{x} after \tcode{position}.

\pnum
\returns
An iterator pointing to the copy of \tcode{x}.
\end{itemdescr}

\indexlibrarymember{insert_after}{forward_list}%
\begin{itemdecl}
constexpr iterator insert_after(const_iterator position, size_type n, const T& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{forward_list}.
\tcode{position} is \tcode{before_begin()} or is a dereferenceable
iterator in the range \range{begin()}{end()}.

\pnum
\effects
Inserts \tcode{n} copies of \tcode{x} after \tcode{position}.

\pnum
\returns
An iterator pointing to the last inserted copy of \tcode{x}, or
\tcode{position} if \tcode{n == 0} is \tcode{true}.
\end{itemdescr}

\indexlibrarymember{insert_after}{forward_list}%
\begin{itemdecl}
template<class InputIterator>
  constexpr iterator insert_after(const_iterator position,
                                  InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{forward_list}
from \tcode{*first}.
\tcode{position} is \tcode{before_begin()} or is a dereferenceable
iterator in the range \range{begin()}{end()}.
Neither \tcode{first} nor \tcode{last} are iterators in \tcode{*this}.

\pnum
\effects
Inserts copies of elements in \range{first}{last} after \tcode{position}.

\pnum
\returns
An iterator pointing to the last inserted element, or
\tcode{position} if \tcode{first == last} is \tcode{true}.
\end{itemdescr}

\indexlibrarymember{insert_range_after}{forward_list}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr iterator insert_range_after(const_iterator position, R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{forward_list}
from \tcode{*ranges::begin(rg)}.
\tcode{posi\-tion} is \tcode{before_begin()} or
is a dereferenceable iterator in the range \range{begin()}{end()}.
\tcode{rg} and \tcode{*this} do not overlap.

\pnum
\effects
Inserts copies of elements in the range \tcode{rg} after \tcode{position}.

\pnum
\returns
An iterator pointing to the last inserted element,
or \tcode{position} if \tcode{rg} is empty.
\end{itemdescr}

\indexlibrarymember{insert_after}{forward_list}%
\begin{itemdecl}
constexpr iterator insert_after(const_iterator position, initializer_list<T> il);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return insert_after(position, il.begin(), il.end());}
\end{itemdescr}


\indexlibrarymember{emplace_after}{forward_list}%
\begin{itemdecl}
template<class... Args>
  constexpr iterator emplace_after(const_iterator position, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{forward_list}
from \tcode{std::forward<Args>(\linebreak args)...}.
\tcode{position} is \tcode{before_begin()} or is a dereferenceable
iterator in the range \range{begin()}{end()}.

\pnum
\effects
Inserts an object of type \tcode{value_type} direct-non-list-initialized with
\tcode{std::forward<Args>(\linebreak args)...} after \tcode{position}.

\pnum
\returns
An iterator pointing to the new object.
\end{itemdescr}

\indexlibrarymember{erase_after}{forward_list}%
\begin{itemdecl}
constexpr iterator erase_after(const_iterator position);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
The iterator following \tcode{position} is dereferenceable.

\pnum
\effects
Erases the element pointed to by the iterator following \tcode{position}.

\pnum
\returns
An iterator pointing to the element following the one that was
erased, or \tcode{end()} if no such element exists.

\pnum
\throws
Nothing.
\end{itemdescr}

\begin{itemdecl}
constexpr iterator erase_after(const_iterator position, const_iterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
All iterators in the range \orange{position}{last} are dereferenceable.

\pnum
\effects
Erases the elements in the range \orange{position}{last}.

\pnum
\returns
\tcode{last}.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{resize}{forward_list}%
\begin{itemdecl}
constexpr void resize(size_type sz);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{forward_list}.

\pnum
\effects
If \tcode{sz < distance(begin(), end())}, erases the last \tcode{distance(begin(),
end()) - sz} elements from the list. Otherwise, inserts \tcode{sz - distance(begin(), end())} default-inserted
elements at the end of the list.
\end{itemdescr}

\begin{itemdecl}
constexpr void resize(size_type sz, const value_type& c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{forward_list}.

\pnum
\effects
If \tcode{sz < distance(begin(), end())}, erases the last \tcode{distance(begin(),
end()) - sz} elements from the list. Otherwise, inserts \tcode{sz - distance(begin(), end())}
copies of \tcode{c} at the end of the list.
\end{itemdescr}


\indexlibrarymember{clear}{forward_list}%
\begin{itemdecl}
constexpr void clear() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Erases all elements in the range \range{begin()}{end()}.

\pnum
\remarks
Does not invalidate past-the-end iterators.
\end{itemdescr}

\rSec3[forward.list.ops]{Operations}

\pnum
In this subclause,
arguments for a template parameter
named \tcode{Predicate} or \tcode{BinaryPredicate}
shall meet the corresponding requirements in \ref{algorithms.requirements}.
The semantics of \tcode{i + n},
where \tcode{i} is an iterator into the list and \tcode{n} is an integer,
are the same as those of \tcode{next(i, n)}.
The expression \tcode{i - n},
where \tcode{i} is an iterator into the list and \tcode{n} is an integer,
means an iterator \tcode{j} such that \tcode{j + n == i} is \tcode{true}.
For \tcode{merge} and \tcode{sort},
the definitions and requirements in \ref{alg.sorting} apply.

\indexlibrarymember{splice_after}{forward_list}%
\begin{itemdecl}
constexpr void splice_after(const_iterator position, forward_list& x);
constexpr void splice_after(const_iterator position, forward_list&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{position} is \tcode{before_begin()} or is a dereferenceable
iterator in the range \range{begin()}{end()}.
\tcode{get_allocator() == x.get_allocator()} is \tcode{true}.
\tcode{addressof(x) != this} is \tcode{true}.

\pnum
\effects
Inserts the contents of \tcode{x} after
\tcode{position}, and \tcode{x} becomes empty. Pointers and references to the moved
elements of \tcode{x} now refer to those same elements but as members of \tcode{*this}.
Iterators referring to the moved elements will continue to refer to their elements, but
they now behave as iterators into \tcode{*this}, not into \tcode{x}.

\pnum
\throws
Nothing.

\pnum
\complexity
\bigoh{\tcode{distance(x.begin(), x.end())}}
\end{itemdescr}

\indexlibrarymember{splice_after}{forward_list}%
\begin{itemdecl}
constexpr void splice_after(const_iterator position, forward_list& x, const_iterator i);
constexpr void splice_after(const_iterator position, forward_list&& x, const_iterator i);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{position} is \tcode{before_begin()} or is a dereferenceable
iterator in the range \range{begin()}{end()}.
The iterator following \tcode{i} is a dereferenceable iterator in \tcode{x}.
\tcode{get_allocator() == x.get_allocator()} is \tcode{true}.

\pnum
\effects
Inserts the element following \tcode{i} into \tcode{*this}, following
\tcode{position}, and removes it from \tcode{x}.
The result is unchanged if \tcode{position == i} or \tcode{position == ++i}. Pointers
and references to \tcode{*++i} continue to refer to the same element but as a member of
\tcode{*this}. Iterators to \tcode{*++i} continue to refer to
the same element, but now behave as iterators into \tcode{*this}, not into \tcode{x}.

\pnum
\throws
Nothing.

\pnum
\complexity
\bigoh{1}
\end{itemdescr}

\indexlibrarymember{splice_after}{forward_list}%
\begin{itemdecl}
constexpr void splice_after(const_iterator position, forward_list& x,
                            const_iterator first, const_iterator last);
constexpr void splice_after(const_iterator position, forward_list&& x,
                            const_iterator first, const_iterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{position} is \tcode{before_begin()} or is a
dereferenceable iterator in the range \range{begin()}{end()}. \orange{first}{last} is a
valid range in \tcode{x}, and all iterators in the range \orange{first}{last} are
dereferenceable. \tcode{position} is not an iterator in the range \orange{first}{last}.
\tcode{get_allocator() == x.get_allocator()} is \tcode{true}.

\pnum
\effects
Inserts elements in the range \orange{first}{last} after \tcode{position} and
removes the elements from \tcode{x}. Pointers and references to the moved elements of
\tcode{x} now refer to those same elements but as members of \tcode{*this}. Iterators
referring to the moved elements will continue to refer to their elements, but they now
behave as iterators into \tcode{*this}, not into \tcode{x}.

\pnum
\complexity
\bigoh{\tcode{distance(first, last)}}
\end{itemdescr}

\indexlibrarymember{remove}{forward_list}%
\indexlibrarymember{remove_if}{forward_list}%
\begin{itemdecl}
constexpr size_type remove(const T& value);
template<class Predicate> constexpr size_type remove_if(Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Erases all the elements in the list referred to by a list iterator \tcode{i} for
which the following conditions hold: \tcode{*i == value} (for \tcode{remove()}),
\tcode{pred(*i)} is \tcode{true} (for \tcode{remove_if()}).
Invalidates only the iterators and references to the erased elements.

\pnum
\returns
The number of elements erased.

\pnum
\throws
Nothing unless an exception is thrown by the equality comparison or the
predicate.

\pnum
\complexity
Exactly \tcode{distance(begin(), end())} applications of the corresponding
predicate.

\pnum
\remarks
Stable\iref{algorithm.stable}.
\end{itemdescr}

\indexlibrarymember{unique}{forward_list}%
\begin{itemdecl}
constexpr size_type unique();
template<class BinaryPredicate> constexpr size_type unique(BinaryPredicate binary_pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{binary_pred} be \tcode{equal_to<>\{\}} for the first overload.

\pnum
\expects
\tcode{binary_pred} is an equivalence relation.

\pnum
\effects
Erases all but the first element from every consecutive
group of equivalent elements.
That is, for a nonempty list, erases all elements referred to
by the iterator \tcode{i} in the range \range{begin() + 1}{end()}
for which \tcode{binary_pred(*i, *(i - 1))} is \tcode{true}.
Invalidates only the iterators and references to the erased elements.

\pnum
\returns
The number of elements erased.

\pnum
\throws
Nothing unless an exception is thrown by the predicate.

\pnum
\complexity
If \tcode{empty()} is \tcode{false},
exactly \tcode{distance(begin(), end()) - 1} applications of
the corresponding predicate,
otherwise no applications of the predicate.
\end{itemdescr}

\indexlibrarymember{merge}{forward_list}%
\begin{itemdecl}
constexpr void merge(forward_list& x);
constexpr void merge(forward_list&& x);
template<class Compare> constexpr void merge(forward_list& x, Compare comp);
template<class Compare> constexpr void merge(forward_list&& x, Compare comp);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{comp} be \tcode{less<>{}} for the first two overloads.

\pnum
\expects
\tcode{*this} and \tcode{x} are both sorted
with respect to the comparator \tcode{comp}, and
\tcode{get_allocator() == x.get_allocator()} is \tcode{true}.

\pnum
\effects
If \tcode{addressof(x) == this}, there are no effects.
Otherwise, merges
the two sorted ranges \range{begin()}{end()} and \range{x.begin()}{x.end()}.
The result is a range
that is sorted with respect to the comparator \tcode{comp}.
Pointers and references to the moved elements of \tcode{x} now refer to those same elements
but as members of \tcode{*this}. Iterators referring to the moved elements will continue to
refer to their elements, but they now behave as iterators into \tcode{*this}, not into
\tcode{x}.

\pnum
\complexity
At most \tcode{distance(begin(),
end()) + distance(x.begin(), x.end()) - 1} comparisons
if \tcode{addressof(x) != this}; otherwise, no comparisons are performed.

\pnum
\remarks
Stable\iref{algorithm.stable}.
If \tcode{addressof(x) != this}, \tcode{x} is empty after the merge.
No elements are copied by this operation.
If an exception is thrown other than by a comparison, there are no effects.
\end{itemdescr}

\indexlibrarymember{sort}{forward_list}%
\begin{itemdecl}
constexpr void sort();
template<class Compare> constexpr void sort(Compare comp);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Sorts the list according to the \tcode{operator<} or the \tcode{comp} function object.
If an exception is thrown, the order of the elements in \tcode{*this} is unspecified.
Does not affect the validity of iterators and references.

\pnum
\complexity
Approximately $N \log N$ comparisons, where $N$ is \tcode{distance(begin(), end())}.

\pnum
\remarks
Stable\iref{algorithm.stable}.
\end{itemdescr}

\indexlibrarymember{reverse}{forward_list}%
\begin{itemdecl}
constexpr void reverse() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Reverses the order of the elements in the list.
Does not affect the validity of iterators and references.

\pnum
\complexity
Linear time.
\end{itemdescr}

\rSec3[forward.list.erasure]{Erasure}

\indexlibrarymember{erase}{forward_list}%
\begin{itemdecl}
template<class T, class Allocator, class U = T>
  constexpr typename forward_list<T, Allocator>::size_type
    erase(forward_list<T, Allocator>& c, const U& value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return erase_if(c, [&](const auto& elem) -> bool { return elem == value; });
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{erase_if}{forward_list}%
\begin{itemdecl}
template<class T, class Allocator, class Predicate>
  constexpr typename forward_list<T, Allocator>::size_type
    erase_if(forward_list<T, Allocator>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return c.remove_if(pred);}
\end{itemdescr}

\rSec2[hive.syn]{Header \tcode{<hive>} synopsis}

\indexheader{hive}%
\begin{codeblock}

#include <initializer_list>     // see \ref{initializer.list.syn}
#include <compare>              // see \ref{compare.syn}

namespace std {
  struct @\libglobal{hive_limits}@ {
    size_t @\libmember{min}{hive_limits}@;
    size_t @\libmember{max}{hive_limits}@;
    constexpr hive_limits(size_t minimum, size_t maximum) noexcept
      : min(minimum), max(maximum) {}
  };

  // \ref {hive}, class template \tcode{hive}
  template<class T, class Allocator = allocator<T>> class hive;

  template<class T, class Allocator>
    void swap(hive<T, Allocator>& x, hive<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  template<class T, class Allocator, class U = T>
    typename hive<T, Allocator>::size_type
      erase(hive<T, Allocator>& c, const U& value);

  template<class T, class Allocator, class Predicate>
    typename hive<T, Allocator>::size_type
      erase_if(hive<T, Allocator>& c, Predicate pred);

  namespace pmr {
    template<class T>
      using hive = std::hive<T, polymorphic_allocator<T>>;
  }
}
\end{codeblock}

\rSec2[hive]{Class template \tcode{hive}}

\rSec3[hive.overview]{Overview}

\pnum
A \tcode{hive} is a type of sequence container
that provides constant-time insertion and erasure operations.
Storage is automatically managed in multiple memory blocks,
referred to as \defnx{element blocks}{element block}.
Insertion\iref{hive.modifiers} position is determined by the container, and insertion
may re-use the memory locations of erased elements.
\begin{note}
Construction and assignment are not considered to involve insertion operations.
\end{note}

\pnum
Element blocks which contain elements are referred to
as \defnadjx{active}{blocks}{block},
those which do not are referred to as \defnadjx{reserved}{blocks}{block}.
Active blocks which become empty of elements are
either deallocated or become reserved blocks.
Reserved blocks become active blocks when they are used to store elements.
A user can create additional reserved blocks by calling \tcode{reserve}.

\pnum
Erasures use unspecified techniques of constant time complexity
to identify the memory locations of erased elements,
which are subsequently skipped during iteration,
as opposed to relocating subsequent elements during erasure.

\pnum
Active block capacities have
an \impldef{growth factor of \tcode{hive} active block capacities} growth factor
(which need not be integral),
for example a new active block's capacity could be equal to
the summed capacities of the pre-existing active blocks.

\pnum
Limits can be placed on
both the minimum and maximum element capacities of element blocks,
both by users and implementations.
\begin{itemize}
\item
The minimum limit shall be no larger than the maximum limit.
\item
When limits are not specified by a user during construction,
the implementation's default limits are used.
\item
The default limits of an implementation are not guaranteed to be the same as
the minimum and maximum possible capacities
for an implementation's element blocks.
\begin{note}
To allow latitude for
both implementation-specific and user-directed optimization.
\end{note}
The latter are defined as hard limits.
The maximum hard limit shall be no larger than
\tcode{std::allocator_traits<Allocator>::max_size()}.
\item
If user-specified limits passed to
a \tcode{hive} constructor or \tcode{reshape}
are not within hard limits, or
if the specified minimum limit is greater than the specified maximum limit,
the behavior is erroneous and the effects are
\impldef{effects of invalid \tcode{hive} limits}.
\begin{tailnote}
This condition can be checked using \tcode{is_within_hard_limits}.
\end{tailnote}
\item
An element block is said to be \defnx{within the bounds}{element block!bounds}
of a pair of minimum/maximum limits
when its capacity is greater-or-equal-to the minimum limit and
less-than-or-equal-to the maximum limit.
\end{itemize}

\pnum
A \tcode{hive} conforms to
the requirements for containers\iref{container.reqmts},
with the exception of operators \tcode{==} and \tcode{!=}.
A \tcode{hive} also meets the requirements
of a reversible container\iref{container.rev.reqmts},
of an allocator-aware container\iref{container.alloc.reqmts}, and
some of the requirements of a sequence container\iref{sequence.reqmts}.
Descriptions are provided here only for operations on \tcode{hive}
that are not described in that table or for operations
where there is additional semantic information.

\pnum
The iterators of \tcode{hive} meet
the \oldconcept{BidirectionalIterator} requirements
but also model \tcode{\libconcept{three_way_comparable}<strong_ordering>}.

\begin{codeblock}
namespace std {
  template<class T, class Allocator = allocator<T>>
  class @\libglobal{hive}@ {
  public:
    // types
    using value_type = T;
    using allocator_type = Allocator;
    using pointer = allocator_traits<Allocator>::pointer;
    using const_pointer = allocator_traits<Allocator>::const_pointer;
    using reference = value_type&;
    using const_reference = const value_type&;
    using size_type = @\impdef@;                               // see \ref{container.requirements}
    using difference_type = @\impdef@;                         // see \ref{container.requirements}
    using iterator = @\impdef@;                                // see \ref{container.requirements}
    using const_iterator = @\impdef@;                          // see \ref{container.requirements}
    using reverse_iterator = std::reverse_iterator<iterator>;               // see \ref{container.requirements}
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;   // see \ref{container.requirements}

    // \ref{hive.cons}, construct/copy/destroy
    constexpr hive() noexcept(noexcept(Allocator())) : hive(Allocator()) {}
    constexpr explicit hive(const Allocator&) noexcept;
    constexpr explicit hive(hive_limits block_limits) : hive(block_limits, Allocator()) {}
    constexpr hive(hive_limits block_limits, const Allocator&);
    explicit hive(size_type n, const Allocator& = Allocator());
    hive(size_type n, hive_limits block_limits, const Allocator& = Allocator());
    hive(size_type n, const T& value, const Allocator& = Allocator());
    hive(size_type n, const T& value, hive_limits block_limits, const Allocator& = Allocator());
    template<class InputIterator>
      hive(InputIterator first, InputIterator last, const Allocator& = Allocator());
    template<class InputIterator>
      hive(InputIterator first, InputIterator last, hive_limits block_limits,
           const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<T> R>
      hive(from_range_t, R&& rg, const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<T> R>
      hive(from_range_t, R&& rg, hive_limits block_limits, const Allocator& = Allocator());
    hive(const hive& x);
    hive(hive&&) noexcept;
    hive(const hive& x, const type_identity_t<Allocator>& alloc);
    hive(hive&&, const type_identity_t<Allocator>& alloc);
    hive(initializer_list<T> il, const Allocator& = Allocator());
    hive(initializer_list<T> il, hive_limits block_limits, const Allocator& = Allocator());
    ~hive();

    hive& operator=(const hive& x);
    hive& operator=(hive&& x) noexcept(@\seebelow@);
    hive& operator=(initializer_list<T>);
    template<class InputIterator>
      void assign(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<T> R>
      void assign_range(R&& rg);
    void assign(size_type n, const T& t);
    void assign(initializer_list<T>);
    allocator_type get_allocator() const noexcept;

    // iterators
    iterator               begin() noexcept;
    const_iterator         begin() const noexcept;
    iterator               end() noexcept;
    const_iterator         end() const noexcept;
    reverse_iterator       rbegin() noexcept;
    const_reverse_iterator rbegin() const noexcept;
    reverse_iterator       rend() noexcept;
    const_reverse_iterator rend() const noexcept;
    const_iterator         cbegin() const noexcept;
    const_iterator         cend() const noexcept;
    const_reverse_iterator crbegin() const noexcept;
    const_reverse_iterator crend() const noexcept;

    // \ref{hive.capacity}, capacity
    bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;
    size_type capacity() const noexcept;
    void reserve(size_type n);
    void shrink_to_fit();
    void trim_capacity() noexcept;
    void trim_capacity(size_type n) noexcept;
    constexpr hive_limits block_capacity_limits() const noexcept;
    static constexpr hive_limits block_capacity_default_limits() noexcept;
    static constexpr hive_limits block_capacity_hard_limits() noexcept;
    static constexpr bool is_within_hard_limits(hive_limits) noexcept;
    void reshape(hive_limits block_limits);

    // \ref{hive.modifiers}, modifiers
    template<class... Args> iterator emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator hint, Args&&... args);
    iterator insert(const T& x);
    iterator insert(T&& x);
    iterator insert(const_iterator hint, const T& x);
    iterator insert(const_iterator hint, T&& x);
    void insert(initializer_list<T> il);
    template<@\exposconcept{container-compatible-range}@<T> R>
      void insert_range(R&& rg);
    template<class InputIterator>
      void insert(InputIterator first, InputIterator last);
    void insert(size_type n, const T& x);

    iterator erase(const_iterator position);
    iterator erase(const_iterator first, const_iterator last);
    void swap(hive&) noexcept(@\seebelow@);
    void clear() noexcept;

    // \ref{hive.operations}, hive operations
    void splice(hive& x);
    void splice(hive&& x);
    template<class BinaryPredicate = equal_to<T>>
      size_type unique(BinaryPredicate binary_pred = BinaryPredicate());

    template<class Compare = less<T>>
      void sort(Compare comp = Compare());

    iterator get_iterator(const_pointer p) noexcept;
    const_iterator get_iterator(const_pointer p) const noexcept;

  private:
    hive_limits @\exposid{current-limits}@ = @\impdef@;     // \expos
  };

  template<class InputIterator, class Allocator = allocator<@\exposid{iter-value-type}@<InputIterator>>>
    hive(InputIterator, InputIterator, Allocator = Allocator())
      -> hive<@\exposid{iter-value-type}@<InputIterator>, Allocator>;

  template<class InputIterator, class Allocator = allocator<@\exposid{iter-value-type}@<InputIterator>>>
    hive(InputIterator, InputIterator, hive_limits, Allocator = Allocator())
      -> hive<@\exposid{iter-value-type}@<InputIterator>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator = allocator<ranges::range_value_t<R>>>
    hive(from_range_t, R&&, Allocator = Allocator())
      -> hive<ranges::range_value_t<R>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator = allocator<ranges::range_value_t<R>>>
    hive(from_range_t, R&&, hive_limits, Allocator = Allocator())
      -> hive<ranges::range_value_t<R>, Allocator>;
}
\end{codeblock}

\rSec3[hive.cons]{Constructors, copy, and assignment}

\indexlibraryctor{hive}%
\begin{itemdecl}
constexpr explicit hive(const Allocator&) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{hive}, using the specified allocator.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{hive}%
\begin{itemdecl}
constexpr hive(hive_limits block_limits, const Allocator&);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{hive}, using the specified allocator.
Initializes \exposid{current-limits} with \tcode{block_limits}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{hive}%
\begin{itemdecl}
explicit hive(size_type n, const Allocator& = Allocator());
hive(size_type n, hive_limits block_limits, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{hive}.

\pnum
\effects
Constructs a \tcode{hive} with \tcode{n} default-inserted elements,
using the specified allocator.
If the second overload is called,
also initializes \exposid{current-limits} with \tcode{block_limits}.

\pnum
\complexity
Linear in \tcode{n}.
\end{itemdescr}

\indexlibraryctor{hive}%
\begin{itemdecl}
hive(size_type n, const T& value, const Allocator& = Allocator());
hive(size_type n, const T& value, hive_limits block_limits, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{hive}.

\pnum
\effects
Constructs a \tcode{hive} with \tcode{n} copies of \tcode{value},
using the specified allocator.
If the second overload is called,
also initializes \exposid{current-limits} with \tcode{block_limits}.

\pnum
\complexity
Linear in \tcode{n}.
\end{itemdescr}

\indexlibraryctor{hive}%
\begin{itemdecl}
template<class InputIterator>
  hive(InputIterator first, InputIterator last, const Allocator& = Allocator());
template<class InputIterator>
  hive(InputIterator first, InputIterator last, hive_limits block_limits,
       const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{hive} equal to the range \range{first}{last},
using the specified allocator.
If the second overload is called,
also initializes \exposid{current-limits} with \tcode{block_limits}.

\pnum
\complexity
Linear in \tcode{distance(first, last)}.
\end{itemdescr}

\indexlibraryctor{hive}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  hive(from_range_t, R&& rg, const Allocator& = Allocator());
template<@\exposconcept{container-compatible-range}@<T> R>
  hive(from_range_t, R&& rg, hive_limits block_limits, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{hive} object equal to the range \tcode{rg},
using the specified allocator.
If the second overload is called,
also initializes \exposid{current-limits} with \tcode{block_limits}.

\pnum
\complexity
Linear in \tcode{ranges::distance(rg)}.
\end{itemdescr}

\indexlibraryctor{hive}%
\begin{itemdecl}
hive(const hive& x);
hive(const hive& x, const type_identity_t<Allocator>& alloc);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{hive}.

\pnum
\effects
Constructs a \tcode{hive} object equal to \tcode{x}.
If the second overload is called, uses \tcode{alloc}.
Initializes \exposid{current-limits} with \tcode{x.\exposid{current-limits}}.

\pnum
\complexity
Linear in \tcode{x.size()}.
\end{itemdescr}

\indexlibraryctor{hive}%
\begin{itemdecl}
hive(hive&& x) noexcept;
hive(hive&& x, const type_identity_t<Allocator>& alloc);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
For the second overload,
when \tcode{allocator_traits<Allocator>::is_always_equal::\-value} is \tcode{false},
\tcode{T} meets the \oldconcept{MoveInsertable} requirements.

\pnum
\effects
When the first overload is called, or
the second overload is called and
\tcode{alloc == x.get_allocator()} is \tcode{true},
\exposid{current-limits} is set to \tcode{x.\exposid{current-limits}} and
each element block is moved from \tcode{x} into \tcode{*this}.
Pointers and references to the elements of \tcode{x} now refer to
those same elements but as members of \tcode{*this}.
Iterators referring to the elements of \tcode{x}
will continue to refer to their elements,
but they now behave as iterators into \tcode{*this}.

If the second overload is called and
\tcode{alloc == x.get_allocator()} is \tcode{false},
each element in \tcode{x} is moved into \tcode{*this}.
References, pointers and iterators referring to the elements of \tcode{x}, as well as the past-the-end iterator of \tcode{x}, are invalidated.

\pnum
\ensures
\tcode{x.empty()} is \tcode{true}.
The relative order of the elements of \tcode{*this}
is the same as that of the elements of \tcode{x} prior to the call.

\pnum
\complexity
If the second overload is called and
\tcode{alloc == x.get_allocator()} is \tcode{false}, linear in \tcode{x.size()}.
Otherwise constant.
\end{itemdescr}

\indexlibraryctor{hive}%
\begin{itemdecl}
hive(initializer_list<T> il, const Allocator& = Allocator());
hive(initializer_list<T> il, hive_limits block_limits, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{hive}.

\pnum
\effects
Constructs a \tcode{hive} object equal to \tcode{il},
using the specified allocator.
If the second overload is called,
also initializes \exposid{current-limits} with \tcode{block_limits}.

\pnum
\complexity
Linear in \tcode{il.size()}.
\end{itemdescr}

\indexlibrarymember{operator=}{hive}%
\begin{itemdecl}
hive& operator=(const hive& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{hive} and
\oldconcept{CopyAssignable}.

\pnum
\effects
All elements in \tcode{*this} are either copy-assigned to, or destroyed.
All elements in \tcode{x} are copied into \tcode{*this},
maintaining their relative order.
\begin{note}
\exposid{current-limits} is unchanged.
\end{note}

\pnum
\complexity
Linear in \tcode{size() + x.size()}.
\end{itemdescr}

\indexlibrarymember{operator=}{hive}%
\begin{itemdecl}
hive& operator=(hive&& x)
  noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
           allocator_traits<Allocator>::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
When
\begin{codeblock}
(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
 allocator_traits<Allocator>::is_always_equal::value)
\end{codeblock}
is \tcode{false},
\tcode{T} is \oldconcept{MoveInsertable} into \tcode{hive} and
\oldconcept{MoveAssignable}.

\pnum
\effects
Each element in \tcode{*this} is either move-assigned to, or destroyed.
When
\begin{codeblock}
(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
 get_allocator() == x.get_allocator())
\end{codeblock}
is \tcode{true},
\exposid{current-limits} is set to \tcode{x.\exposid{current-limits}} and
each element block is moved from \tcode{x} into \tcode{*this}.
Pointers and references to the elements of \tcode{x}
now refer to those same elements but as members of \tcode{*this}.
Iterators referring to the elements of \tcode{x}
will continue to refer to their elements,
but they now behave as iterators into \tcode{*this}, not into \tcode{x}.

When
\begin{codeblock}
(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
 get_allocator() == x.get_allocator())
\end{codeblock}
is \tcode{false},
each element in \tcode{x} is moved into \tcode{*this}.
References, pointers and iterators referring to the elements of \tcode{x},
as well as the past-the-end iterator of \tcode{x}, are invalidated.

\pnum
\ensures
\tcode{x.empty()} is \tcode{true}.
The relative order of the elements of \tcode{*this}
is the same as that of the elements of \tcode{x} prior to this call.

\pnum
\complexity
Linear in \tcode{size()}.
If
\begin{codeblock}
(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
 get_allocator() == x.get_allocator())
\end{codeblock}
is \tcode{false}, also linear in \tcode{x.size()}.
\end{itemdescr}

\rSec3[hive.capacity]{Capacity}

\indexlibrarymember{capacity}{hive}%
\begin{itemdecl}
size_type capacity() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The total number of elements that \tcode{*this} can hold
without requiring allocation of more element blocks.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibrarymember{reserve}{hive}%
\begin{itemdecl}
void reserve(size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
If \tcode{n <= capacity()} is \tcode{true}, there are no effects.
Otherwise increases \tcode{capacity()} by allocating reserved blocks.

\pnum
\ensures
\tcode{capacity() >= n} is \tcode{true}.

\pnum
\throws
\tcode{length_error} if
satisfying the postcondition
would cause \tcode{capacity()} to exceed \tcode{max_size()},
as well as any exceptions thrown by the allocator.

\pnum
\complexity
Linear in the number of reserved blocks allocated.

\pnum
\remarks
All references, pointers, and iterators referring to elements in \tcode{*this},
as well as the past-the-end iterator, remain valid.
\end{itemdescr}

\indexlibrarymember{shrink_to_fit}{hive}%
\begin{itemdecl}
void shrink_to_fit();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{MoveInsertable} into \tcode{hive}.

\pnum
\effects
\tcode{shrink_to_fit} is a non-binding request
to reduce \tcode{capacity()} to be closer to \tcode{size()}.
\begin{note}
The request is non-binding
to allow latitude for implementation-specific optimizations.
\end{note}
It does not increase \tcode{capacity()}, but may reduce \tcode{capacity()}.
It may reallocate elements.
If \tcode{capacity()} is already equal to \tcode{size()}, there are no effects.
If an exception is thrown during allocation of a new element block,
\tcode{capacity()} may be reduced and reallocation may occur.
Otherwise if an exception is thrown, the effects are unspecified.

\pnum
\complexity
If reallocation happens, linear in the size of the sequence.

\pnum
\remarks
If reallocation happens,
the order of the elements in \tcode{*this} may change and
all references, pointers, and iterators
referring to the elements in \tcode{*this},
as well as the past-the-end iterator, are invalidated.
\end{itemdescr}

\indexlibrarymember{trim_capacity}{hive}%
\begin{itemdecl}
void trim_capacity() noexcept;
void trim_capacity(size_type n) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
For the first overload, all reserved blocks are deallocated, and
\tcode{capacity()} is reduced accordingly.
For the second overload,
if \tcode{n >= capacity()} is \tcode{true},
there are no effects;
otherwise, \tcode{capacity()} is reduced to no less than \tcode{n}.

\pnum
\complexity
Linear in the number of reserved blocks deallocated.

\pnum
\remarks
All references, pointers, and iterators referring to elements in \tcode{*this},
as well as the past-the-end iterator, remain valid.
\end{itemdescr}

\indexlibrarymember{block_capacity_limits}{hive}%
\begin{itemdecl}
constexpr hive_limits block_capacity_limits() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{current-limits}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibrarymember{block_capacity_default_limits}{hive}%
\begin{itemdecl}
static constexpr hive_limits block_capacity_default_limits() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{hive_limits} struct
with the \tcode{min} and \tcode{max} members set to
the implementation's default limits.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibrarymember{block_capacity_hard_limits}{hive}%
\begin{itemdecl}
static constexpr hive_limits block_capacity_hard_limits() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{hive_limits} struct
with the \tcode{min} and \tcode{max} members set to
the implementation's hard limits.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibrarymember{is_within_hard_limits}{hive}%
\begin{itemdecl}
static constexpr bool is_within_hard_limits(hive_limits lim) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{hl} be \tcode{block_capacity_hard_limits()}.

\pnum
\returns
\tcode{hl.min <= lim.min \&\& lim.min <= lim.max \&\& lim.max <= hl.max}.
\end{itemdescr}

\indexlibrarymember{reshape}{hive}%
\begin{itemdecl}
void reshape(hive_limits block_limits);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{MoveInsertable} into \tcode{hive}.

\pnum
\effects
For any active blocks not within the bounds of \tcode{block_limits},
the elements within those active blocks are reallocated
to new or existing element blocks which are within the bounds.
Any element blocks not within the bounds of \tcode{block_limits}
are deallocated.
If an exception is thrown during allocation of a new element block,
\tcode{capacity()} may be reduced,
reallocation may occur, and
\exposid{current-limits} may be assigned
a value other than \tcode{block_limits}.
Otherwise \tcode{block_limits} is assigned to \exposid{current-limits}.
If any other exception is thrown the effects are unspecified.

\pnum
\ensures
\tcode{size()} is unchanged.

\pnum
\complexity
Linear in the number of element blocks in \tcode{*this}.
If reallocation happens, also linear in the number of elements reallocated.

\pnum
\remarks
This operation may change \tcode{capacity()}.
If reallocation happens, the order of the elements in \tcode{*this} may change.
Reallocation invalidates all references, pointers, and iterators
referring to the elements in \tcode{*this},
as well as the past-the-end iterator.
\begin{note}
If no reallocation happens, they remain valid.
\end{note}
\end{itemdescr}

\rSec3[hive.modifiers]{Modifiers}

\indexlibrarymember{emplace}{hive}%
\begin{itemdecl}
template<class... Args> iterator emplace(Args&&... args);
template<class... Args> iterator emplace_hint(const_iterator hint, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{hive} from \tcode{args}.

\pnum
\effects
Inserts an object of type \tcode{T}
constructed with \tcode{std::forward<Args>(args)...}.
The \tcode{hint} parameter is ignored.
If an exception is thrown, there are no effects.
\begin{note}
\tcode{args} can directly or indirectly refer to a value in \tcode{*this}.
\end{note}

\pnum
\returns
An iterator that points to the new element.

\pnum
\complexity
Constant. Exactly one object of type \tcode{T} is constructed.

\pnum
\remarks
Invalidates the past-the-end iterator.
\end{itemdescr}

\indexlibrarymember{insert}{hive}%
\begin{itemdecl}
iterator insert(const T& x);
iterator insert(const_iterator hint, const T& x);
iterator insert(T&& x);
iterator insert(const_iterator hint, T&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return emplace(std::forward<decltype(x)>(x));}
\begin{note}
The \tcode{hint} parameter is ignored.
\end{note}
\end{itemdescr}

\indexlibrarymember{insert}{hive}%
\begin{itemdecl}
void insert(initializer_list<T> rg);
template<@\exposconcept{container-compatible-range}@<T> R>
  void insert_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{EmplaceInsertable} into \tcode{hive}
from \tcode{*ranges::begin(rg)}.
\tcode{rg} and \tcode{*this} do not overlap.

\pnum
\effects
Inserts copies of elements in \tcode{rg}.
Each iterator in the range \tcode{rg} is dereferenced exactly once.

\pnum
\complexity
Linear in the number of elements inserted.
Exactly one object of type \tcode{T} is constructed for each element inserted.

\pnum
\remarks
If an element is inserted, invalidates the past-the-end iterator.
\end{itemdescr}

\indexlibrarymember{insert}{hive}%
\begin{itemdecl}
void insert(size_type n, const T& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{hive}.

\pnum
\effects
Inserts \tcode{n} copies of \tcode{x}.

\pnum
\complexity
Linear in \tcode{n}.
Exactly one object of type \tcode{T} is constructed for each element inserted.

\pnum
\remarks
If an element is inserted, invalidates the past-the-end iterator.
\end{itemdescr}

\indexlibrarymember{insert}{hive}%
\begin{itemdecl}
template<class InputIterator>
  void insert(InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{insert_range(ranges::subrange(first, last))}.
\end{itemdescr}

\indexlibrarymember{erase}{hive}%
\begin{itemdecl}
iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\complexity
Linear in the number of elements erased.
Additionally, if any active blocks become empty of elements
as a result of the function call,
at worst linear in the number of element blocks.

\pnum
\remarks
Invalidates references, pointers and iterators
referring to the erased elements.
An erase operation that erases the last element in \tcode{*this}
also invalidates the past-the-end iterator.
\end{itemdescr}

\indexlibrarymember{swap}{hive}%
\begin{itemdecl}
void swap(hive& x)
  noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
           allocator_traits<Allocator>::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Exchanges the contents, \tcode{capacity()}, and \exposid{current-limits}
of \tcode{*this} with that of \tcode{x}.

\pnum
\complexity
Constant.
\end{itemdescr}

\rSec3[hive.operations]{Operations}

\pnum
In this subclause,
arguments for a template parameter
named \tcode{Predicate} or \tcode{BinaryPredicate}
shall meet the corresponding requirements in \ref{algorithms.requirements}.
The semantics of \tcode{i + n} and \tcode{i - n},
where \tcode{i} is an iterator into the \tcode{hive} and \tcode{n} is an integer,
are the same as those of \tcode{next(i, n)} and \tcode{prev(i, n)}, respectively.
For \tcode{sort}, the definitions and requirements in \ref{alg.sorting} apply.

\indexlibrarymember{splice}{hive}%
\begin{itemdecl}
void splice(hive& x);
void splice(hive&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{get_allocator() == x.get_allocator()} is \tcode{true}.

\pnum
\effects
If \tcode{addressof(x) == this} is \tcode{true},
the behavior is erroneous and there are no effects.
If an exception is thrown,
there are no effects.
Otherwise, inserts the contents of \tcode{x} into \tcode{*this} and
\tcode{x} becomes empty.
Pointers and references to the moved elements of \tcode{x}
now refer to those same elements but as members of \tcode{*this}.
Iterators referring to the moved elements continue to refer to their elements,
but they now behave as iterators into \tcode{*this}, not into \tcode{x}.

\pnum
\throws
\tcode{length_error} if any of \tcode{x}'s active blocks
are not within the bounds of \exposid{current-limits},
as well as any exceptions thrown by the allocator.

\pnum
\complexity
Linear in the sum of
all element blocks in \tcode{x} plus all element blocks in \tcode{*this}.

\pnum
\remarks
Reserved blocks in \tcode{x} are not transferred into \tcode{*this}.
If \tcode{addressof(x) == this} is \tcode{false},
invalidates the past-the-end iterator for both \tcode{x} and \tcode{*this}.
\end{itemdescr}

\indexlibrarymember{unique}{hive}%
\begin{itemdecl}
template<class BinaryPredicate = equal_to<T>>
  size_type unique(BinaryPredicate binary_pred = BinaryPredicate());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{binary_pred} is an equivalence relation.

\pnum
\effects
Erases all but the first element
from every consecutive group of equivalent elements.
That is, for a nonempty \tcode{hive},
erases all elements referred to by the iterator \tcode{i}
in the range \range{begin() + 1}{end()}
for which \tcode{binary_pred(*i, *(i - 1))} is \tcode{true}.

\pnum
\returns
The number of elements erased.

\pnum
\throws
Nothing unless an exception is thrown by the predicate.

\pnum
\complexity
If \tcode{empty()} is \tcode{false},
exactly \tcode{size() - 1} applications of the corresponding predicate,
otherwise no applications of the predicate.

\pnum
\remarks
Invalidates references, pointers, and iterators
referring to the erased elements.
If the last element in \tcode{*this} is erased,
also invalidates the past-the-end iterator.
\end{itemdescr}

\indexlibrarymember{sort}{hive}%
\begin{itemdecl}
template<class Compare = less<T>>
  void sort(Compare comp = Compare());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{MoveInsertable} into \tcode{hive},
\oldconcept{MoveAssignable}, and \oldconcept{Swappable}.

\pnum
\effects
Sorts \tcode{*this} according to the \tcode{comp} function object.
If an exception is thrown,
the order of the elements in \tcode{*this} is unspecified.

\pnum
\complexity
\bigoh{N \log N} comparisons, where $N$ is \tcode{size()}.

\pnum
\remarks
May allocate.
References, pointers, and iterators referring to elements in \tcode{*this},
as well as the past-the-end iterator, may be invalidated.
\begin{note}
Not required to be stable\iref{algorithm.stable}.
\end{note}
\end{itemdescr}

\indexlibrarymember{get_iterator}{hive}%
\begin{itemdecl}
iterator get_iterator(const_pointer p) noexcept;
const_iterator get_iterator(const_pointer p) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{p} points to an element in \tcode{*this}.

\pnum
\returns
An \tcode{iterator} or \tcode{const_iterator}
pointing to the same element as \tcode{p}.

\pnum
\complexity
Linear in the number of active blocks in \tcode{*this}.
\end{itemdescr}

\rSec3[hive.erasure]{Erasure}

\indexlibrarymember{erase}{hive}%
\begin{itemdecl}
template<class T, class Allocator, class U = T>
  typename hive<T, Allocator>::size_type
    erase(hive<T, Allocator>& c, const U& value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return erase_if(c, [&](const auto& elem) -> bool { return elem == value; });
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{erase_if}{hive}%
\begin{itemdecl}
template<class T, class Allocator, class Predicate>
  typename hive<T, Allocator>::size_type
    erase_if(hive<T, Allocator>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto original_size = c.size();
for (auto i = c.begin(); i != c.end(); ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();
\end{codeblock}
\end{itemdescr}

\rSec2[list.syn]{Header \tcode{<list>} synopsis}

\indexheader{list}%
\begin{codeblock}
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{list}, class template \tcode{list}
  template<class T, class Allocator = allocator<T>> class list;

  template<class T, class Allocator>
    constexpr bool operator==(const list<T, Allocator>& x, const list<T, Allocator>& y);
  template<class T, class Allocator>
    constexpr @\exposid{synth-three-way-result}@<T>
      operator<=>(const list<T, Allocator>& x, const list<T, Allocator>& y);

  template<class T, class Allocator>
    constexpr void swap(list<T, Allocator>& x, list<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  // \ref{list.erasure}, erasure
  template<class T, class Allocator, class U = T>
    constexpr typename list<T, Allocator>::size_type
      erase(list<T, Allocator>& c, const U& value);
  template<class T, class Allocator, class Predicate>
    constexpr typename list<T, Allocator>::size_type
      erase_if(list<T, Allocator>& c, Predicate pred);

  namespace pmr {
    template<class T>
      using list = std::list<T, polymorphic_allocator<T>>;
  }
}
\end{codeblock}

\rSec2[list]{Class template \tcode{list}}

\rSec3[list.overview]{Overview}

\pnum
\indexlibraryglobal{list}%
A
\tcode{list}
is a sequence container that supports
bidirectional iterators and allows constant time insert and erase
operations anywhere within the sequence, with storage management handled
automatically. Unlike vectors\iref{vector} and deques\iref{deque},
fast random access to list elements is not supported, but many
algorithms only need sequential access anyway.

\pnum
A \tcode{list} meets all of the requirements
of a container\iref{container.reqmts},
of a reversible container\iref{container.rev.reqmts},
of an allocator-aware container\iref{container.alloc.reqmts}, and
of a sequence container,
including most of the optional sequence container
requirements\iref{sequence.reqmts}.
The exceptions are the
\tcode{operator[]}
and
\tcode{at}
member functions, which are not provided.
\begin{footnote}
These member functions
are only provided by containers whose iterators
are random access iterators.
\end{footnote}
Descriptions are provided here only for operations on
\tcode{list}
that are not described in one of these tables
or for operations where there is additional semantic information.

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\begin{codeblock}
namespace std {
  template<class T, class Allocator = allocator<T>>
  class list {
  public:
    // types
    using value_type             = T;
    using allocator_type         = Allocator;
    using pointer                = allocator_traits<Allocator>::pointer;
    using const_pointer          = allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\impdefx{type of \tcode{list::size_type}}@; // see \ref{container.requirements}
    using difference_type        = @\impdefx{type of \tcode{list::difference_type}}@; // see \ref{container.requirements}
    using iterator               = @\impdefx{type of \tcode{list::iterator}}@; // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{list::const_iterator}}@; // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // \ref{list.cons}, construct/copy/destroy
    constexpr list() : list(Allocator()) { }
    constexpr explicit list(const Allocator&);
    constexpr explicit list(size_type n, const Allocator& = Allocator());
    constexpr list(size_type n, const T& value, const Allocator& = Allocator());
    template<class InputIterator>
      constexpr list(InputIterator first, InputIterator last, const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr list(from_range_t, R&& rg, const Allocator& = Allocator());
    constexpr list(const list& x);
    constexpr list(list&& x);
    constexpr list(const list&, const type_identity_t<Allocator>&);
    constexpr list(list&&, const type_identity_t<Allocator>&);
    constexpr list(initializer_list<T>, const Allocator& = Allocator());
    constexpr ~list();
    constexpr list& operator=(const list& x);
    constexpr list& operator=(list&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    constexpr list& operator=(initializer_list<T>);
    template<class InputIterator>
      constexpr void assign(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr void assign_range(R&& rg);
    constexpr void assign(size_type n, const T& t);
    constexpr void assign(initializer_list<T>);
    constexpr allocator_type get_allocator() const noexcept;

    // iterators
    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;

    // \ref{list.capacity}, capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;
    constexpr void      resize(size_type sz);
    constexpr void      resize(size_type sz, const T& c);

    // element access
    constexpr reference       front();
    constexpr const_reference front() const;
    constexpr reference       back();
    constexpr const_reference back() const;

    // \ref{list.modifiers}, modifiers
    template<class... Args> constexpr reference emplace_front(Args&&... args);
    template<class... Args> constexpr reference emplace_back(Args&&... args);
    constexpr void push_front(const T& x);
    constexpr void push_front(T&& x);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr void prepend_range(R&& rg);
    constexpr void pop_front();
    constexpr void push_back(const T& x);
    constexpr void push_back(T&& x);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr void append_range(R&& rg);
    constexpr void pop_back();

    template<class... Args> constexpr iterator emplace(const_iterator position, Args&&... args);
    constexpr iterator insert(const_iterator position, const T& x);
    constexpr iterator insert(const_iterator position, T&& x);
    constexpr iterator insert(const_iterator position, size_type n, const T& x);
    template<class InputIterator>
      constexpr iterator insert(const_iterator position,
                                InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr iterator insert_range(const_iterator position, R&& rg);
    constexpr iterator insert(const_iterator position, initializer_list<T> il);

    constexpr iterator erase(const_iterator position);
    constexpr iterator erase(const_iterator position, const_iterator last);
    constexpr void     swap(list&) noexcept(allocator_traits<Allocator>::is_always_equal::value);
    constexpr void     clear() noexcept;

    // \ref{list.ops}, list operations
    constexpr void splice(const_iterator position, list& x);
    constexpr void splice(const_iterator position, list&& x);
    constexpr void splice(const_iterator position, list& x, const_iterator i);
    constexpr void splice(const_iterator position, list&& x, const_iterator i);
    constexpr void splice(const_iterator position, list& x,
                          const_iterator first, const_iterator last);
    constexpr void splice(const_iterator position, list&& x,
                          const_iterator first, const_iterator last);

    constexpr size_type remove(const T& value);
    template<class Predicate> constexpr size_type remove_if(Predicate pred);

    constexpr size_type unique();
    template<class BinaryPredicate>
      constexpr size_type unique(BinaryPredicate binary_pred);

    constexpr void merge(list& x);
    constexpr void merge(list&& x);
    template<class Compare> constexpr void merge(list& x, Compare comp);
    template<class Compare> constexpr void merge(list&& x, Compare comp);

    constexpr void sort();
    template<class Compare> constexpr void sort(Compare comp);

    constexpr void reverse() noexcept;
  };

  template<class InputIterator, class Allocator = allocator<@\placeholder{iter-value-type}@<InputIterator>>>
    list(InputIterator, InputIterator, Allocator = Allocator())
      -> list<@\placeholder{iter-value-type}@<InputIterator>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator = allocator<ranges::range_value_t<R>>>
    list(from_range_t, R&&, Allocator = Allocator())
      -> list<ranges::range_value_t<R>, Allocator>;
}
\end{codeblock}

\pnum
An incomplete type \tcode{T} may be used when instantiating \tcode{list}
if the allocator meets the
allocator completeness requirements\iref{allocator.requirements.completeness}.
\tcode{T} shall be complete before any member of the resulting specialization
of \tcode{list} is referenced.

\rSec3[list.cons]{Constructors, copy, and assignment}

\indexlibraryctor{list}%
\begin{itemdecl}
constexpr explicit list(const Allocator&);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{list}, using the specified allocator.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{list}%
\begin{itemdecl}
constexpr explicit list(size_type n, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{list}.

\pnum
\effects
Constructs a \tcode{list} with
\tcode{n} default-inserted elements using the specified allocator.

\pnum
\complexity
Linear in
\tcode{n}.
\end{itemdescr}

\indexlibraryctor{list}%
\begin{itemdecl}
constexpr list(size_type n, const T& value, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{list}.

\pnum
\effects
Constructs a
\tcode{list}
with
\tcode{n}
copies of
\tcode{value},
using the specified allocator.

\pnum
\complexity
Linear in
\tcode{n}.
\end{itemdescr}

\indexlibraryctor{list}%
\begin{itemdecl}
template<class InputIterator>
  constexpr list(InputIterator first, InputIterator last, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a
\tcode{list}
equal to the range
\range{first}{last}.

\pnum
\complexity
Linear in
\tcode{distance(first, last)}.
\end{itemdescr}

\indexlibraryctor{list}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr list(from_range_t, R&& rg, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{list} object with the elements of the range \tcode{rg}.

\pnum
\complexity
Linear in \tcode{ranges::distance(rg)}.
\end{itemdescr}

\rSec3[list.capacity]{Capacity}

\indexlibrarymember{resize}{list}%
\begin{itemdecl}
constexpr void resize(size_type sz);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{list}.

\pnum
\effects
If \tcode{size() < sz},
appends \tcode{sz - size()} default-inserted elements to the
sequence.
If \tcode{sz <= size()}, equivalent to:

\begin{codeblock}
list<T>::iterator it = begin();
advance(it, sz);
erase(it, end());
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{resize}{list}%
\begin{itemdecl}
constexpr void resize(size_type sz, const T& c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{list}.

\pnum
\effects
As if by:
\begin{codeblock}
if (sz > size())
  insert(end(), sz-size(), c);
else if (sz < size()) {
  iterator i = begin();
  advance(i, sz);
  erase(i, end());
}
else
  ;                 // do nothing
\end{codeblock}
\end{itemdescr}

\rSec3[list.modifiers]{Modifiers}

\indexlibrarymember{insert}{list}%
\begin{itemdecl}
constexpr iterator insert(const_iterator position, const T& x);
constexpr iterator insert(const_iterator position, T&& x);
constexpr iterator insert(const_iterator position, size_type n, const T& x);
template<class InputIterator>
  constexpr iterator insert(const_iterator position,
                            InputIterator first, InputIterator last);
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr iterator insert_range(const_iterator position, R&& rg);
constexpr iterator insert(const_iterator position, initializer_list<T>);

template<class... Args> constexpr reference emplace_front(Args&&... args);
template<class... Args> constexpr reference emplace_back(Args&&... args);
template<class... Args> constexpr iterator emplace(const_iterator position, Args&&... args);
constexpr void push_front(const T& x);
constexpr void push_front(T&& x);
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr void prepend_range(R&& rg);
constexpr void push_back(const T& x);
constexpr void push_back(T&& x);
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr void append_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\complexity
Insertion of a single element into a list takes constant time and
exactly one call to a constructor of
\tcode{T}. Insertion of multiple elements into a list is linear in the
number of elements inserted, and the number of calls to the copy
constructor or move constructor of \tcode{T} is exactly equal
to the number of elements inserted.

\pnum
\remarks
Does not affect the validity of iterators and references.
If an exception is thrown, there are no effects.
\end{itemdescr}

\indexlibrarymember{erase}{list}%
\begin{itemdecl}
constexpr iterator erase(const_iterator position);
constexpr iterator erase(const_iterator first, const_iterator last);
constexpr void pop_front();
constexpr void pop_back();
constexpr void clear() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Invalidates only the iterators and references to the erased elements.

\pnum
\throws
Nothing.

\pnum
\complexity
Erasing a single element is a constant time operation with a single call to the destructor of
\tcode{T}.
Erasing a range in a list is linear time in the
size of the range and the number of calls to the destructor of type
\tcode{T}
is exactly equal to the size of the range.
\end{itemdescr}

\rSec3[list.ops]{Operations}

\pnum
Since lists allow fast insertion and erasing from the middle of a list, certain
operations are provided specifically for them.
\begin{footnote}
As specified
in~\ref{allocator.requirements}, the requirements in this Clause apply only to
lists whose allocators compare equal.
\end{footnote}
In this subclause,
arguments for a template parameter
named \tcode{Predicate} or \tcode{BinaryPredicate}
shall meet the corresponding requirements in \ref{algorithms.requirements}.
The semantics of \tcode{i + n} and \tcode{i - n},
where \tcode{i} is an iterator into the list and \tcode{n} is an integer,
are the same as those of \tcode{next(i, n)} and \tcode{prev(i, n)},
respectively.
For \tcode{merge} and \tcode{sort},
the definitions and requirements in \ref{alg.sorting} apply.

\pnum
\tcode{list} provides three splice operations that destructively move elements from one list to
another. The behavior of splice operations is undefined if \tcode{get_allocator() !=
x.get_allocator()}.

\indexlibrarymember{splice}{list}%
\begin{itemdecl}
constexpr void splice(const_iterator position, list& x);
constexpr void splice(const_iterator position, list&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{addressof(x) != this} is \tcode{true}.

\pnum
\effects
Inserts the contents of
\tcode{x}
before
\tcode{position}
and
\tcode{x}
becomes empty.
Pointers and references to the moved elements of
\tcode{x}
now refer to those same elements but as members of
\tcode{*this}.
Iterators referring to the moved elements will continue to refer to their
elements, but they now behave as iterators into
\tcode{*this},
not into
\tcode{x}.

\pnum
\throws
Nothing.

\pnum
\complexity
Constant time.
\end{itemdescr}

\indexlibrarymember{splice}{list}%
\begin{itemdecl}
constexpr void splice(const_iterator position, list& x, const_iterator i);
constexpr void splice(const_iterator position, list&& x, const_iterator i);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{i} is a valid dereferenceable iterator of \tcode{x}.

\pnum
\effects
Inserts an element pointed to by
\tcode{i}
from list
\tcode{x}
before \tcode{position} and removes the element from
\tcode{x}.
The result is unchanged if
\tcode{position == i}
or
\tcode{position == ++i}.
Pointers and references to
\tcode{*i}
continue to refer to this same element but as a member of
\tcode{*this}.
Iterators
to
\tcode{*i}
(including
\tcode{i}
itself) continue to refer to the same element, but now behave as iterators into
\tcode{*this},
not into
\tcode{x}.

\pnum
\throws
Nothing.

\pnum
\complexity
Constant time.
\end{itemdescr}

\indexlibrarymember{splice}{list}%
\begin{itemdecl}
constexpr void splice(const_iterator position, list& x,
                      const_iterator first, const_iterator last);
constexpr void splice(const_iterator position, list&& x,
                      const_iterator first, const_iterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\range{first}{last} is a valid range in \tcode{x}.
\tcode{position} is not an iterator in the range \range{first}{last}.

\pnum
\effects
Inserts elements in the range
\range{first}{last}
before
\tcode{position}
and removes the elements from
\tcode{x}.
Pointers and references to the moved elements of
\tcode{x}
now refer to those same elements but as members of
\tcode{*this}.
Iterators referring to the moved elements will continue to refer to their
elements, but they now behave as iterators into
\tcode{*this},
not into
\tcode{x}.

\pnum
\throws
Nothing.

\pnum
\complexity
Constant time if
\tcode{addressof(x) == this};
otherwise, linear time.
\end{itemdescr}

\indexlibrarymember{remove}{list}%
\begin{itemdecl}
constexpr size_type remove(const T& value);
template<class Predicate> constexpr size_type remove_if(Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Erases all the elements in the list referred to by a list iterator \tcode{i} for which the
following conditions hold: \tcode{*i == value}, \tcode{pred(*i) != false}.
Invalidates only the iterators and references to the erased elements.

\pnum
\returns
The number of elements erased.

\pnum
\throws
Nothing unless an exception is thrown by
\tcode{*i == value}
or
\tcode{pred(*i) != false}.

\pnum
\complexity
Exactly
\tcode{size()}
applications of the corresponding predicate.

\pnum
\remarks
Stable\iref{algorithm.stable}.
\end{itemdescr}

\indexlibrarymember{unique}{list}%
\begin{itemdecl}
constexpr size_type unique();
template<class BinaryPredicate> constexpr size_type unique(BinaryPredicate binary_pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{binary_pred} be \tcode{equal_to<>\{\}} for the first overload.

\pnum
\expects
\tcode{binary_pred} is an equivalence relation.

\pnum
\effects
Erases all but the first element from every
consecutive group of equivalent elements.
That is, for a nonempty list, erases all elements referred to
by the iterator \tcode{i} in the range \range{begin() + 1}{end()}
for which \tcode{binary_pred(*i, *(i - 1))} is \tcode{true}.
Invalidates only the iterators and references to the erased elements.

\pnum
\returns
The number of elements erased.

\pnum
\throws
Nothing unless an exception is thrown by the predicate.

\pnum
\complexity
If \tcode{empty()} is \tcode{false},
exactly \tcode{size() - 1} applications of the corresponding predicate,
otherwise no applications of the predicate.
\end{itemdescr}

\indexlibrarymember{merge}{list}%
\begin{itemdecl}
constexpr void merge(list& x);
constexpr void merge(list&& x);
template<class Compare> constexpr void merge(list& x, Compare comp);
template<class Compare> constexpr void merge(list&& x, Compare comp);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{comp} be \tcode{less<>{}} for the first two overloads.

\pnum
\expects
\tcode{*this} and \tcode{x} are both sorted
with respect to the comparator \tcode{comp}, and
\tcode{get_allocator() == x.get_allocator()} is \tcode{true}.

\pnum
\effects
If \tcode{addressof(x) == this}, there are no effects.
Otherwise, merges
the two sorted ranges \range{begin()}{end()} and \range{x.begin()}{x.end()}.
The result is a range
that is sorted with respect to the comparator \tcode{comp}.
Pointers and references to the moved elements of \tcode{x} now refer to those same elements
but as members of \tcode{*this}. Iterators referring to the moved elements will continue to
refer to their elements, but they now behave as iterators into \tcode{*this}, not into
\tcode{x}.

\pnum
\complexity
At most \tcode{size() + x.size() - 1} comparisons
if \tcode{addressof(x) != this};
otherwise, no comparisons are performed.

\pnum
\remarks
Stable\iref{algorithm.stable}.
If \tcode{addressof(x) != this}, \tcode{x} is empty after the merge.
No elements are copied by this operation.
If an exception is thrown other than by a comparison, there are no effects.
\end{itemdescr}

\indexlibrarymember{reverse}{list}%
\begin{itemdecl}
constexpr void reverse() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Reverses the order of the elements in the list.
Does not affect the validity of iterators and references.

\pnum
\complexity
Linear time.
\end{itemdescr}

\indexlibrarymember{sort}{list}%
\begin{itemdecl}
void sort();
template<class Compare> void sort(Compare comp);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Sorts the list according to the \tcode{operator<} or a \tcode{Compare} function object.
If an exception is thrown,
the order of the elements in \tcode{*this} is unspecified.
Does not affect the validity of iterators and references.

\pnum
\complexity
Approximately
$N \log N$
comparisons, where $N$ is \tcode{size()}.

\pnum
\remarks
Stable\iref{algorithm.stable}.
\end{itemdescr}

\rSec3[list.erasure]{Erasure}

\indexlibrarymember{erase}{list}%
\begin{itemdecl}
template<class T, class Allocator, class U = T>
  typename list<T, Allocator>::size_type
    constexpr erase(list<T, Allocator>& c, const U& value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return erase_if(c, [&](const auto& elem) -> bool { return elem == value; });
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{erase_if}{list}%
\begin{itemdecl}
template<class T, class Allocator, class Predicate>
  typename list<T, Allocator>::size_type
    constexpr erase_if(list<T, Allocator>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return c.remove_if(pred);}
\end{itemdescr}

\rSec2[vector.syn]{Header \tcode{<vector>} synopsis}

\indexheader{vector}%
\begin{codeblock}
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{vector}, class template \tcode{vector}
  template<class T, class Allocator = allocator<T>> class vector;

  template<class T, class Allocator>
    constexpr bool operator==(const vector<T, Allocator>& x, const vector<T, Allocator>& y);
  template<class T, class Allocator>
    constexpr @\exposid{synth-three-way-result}@<T>
      operator<=>(const vector<T, Allocator>& x, const vector<T, Allocator>& y);

  template<class T, class Allocator>
    constexpr void swap(vector<T, Allocator>& x, vector<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  // \ref{vector.erasure}, erasure
  template<class T, class Allocator, class U = T>
    constexpr typename vector<T, Allocator>::size_type
      erase(vector<T, Allocator>& c, const U& value);
  template<class T, class Allocator, class Predicate>
    constexpr typename vector<T, Allocator>::size_type
      erase_if(vector<T, Allocator>& c, Predicate pred);

  namespace pmr {
    template<class T>
      using vector = std::vector<T, polymorphic_allocator<T>>;
  }

  // \ref{vector.bool}, specialization of \tcode{vector} for \tcode{bool}
  // \ref{vector.bool.pspc}, partial class template specialization \tcode{vector<bool, Allocator>}
  template<class Allocator>
    class vector<bool, Allocator>;

  template<class T>
    constexpr bool @\exposid{is-vector-bool-reference}@ = @\seebelow@;          // \expos

  // hash support
  template<class T> struct hash;
  template<class Allocator> struct hash<vector<bool, Allocator>>;

  // \ref{vector.bool.fmt}, formatter specialization for \tcode{vector<bool>}
  template<class T, class charT> requires @\exposid{is-vector-bool-reference}@<T>
    struct formatter<T, charT>;
}
\end{codeblock}

\rSec2[vector]{Class template \tcode{vector}}

\rSec3[vector.overview]{Overview}

\pnum
\indexlibraryglobal{vector}%
A
\tcode{vector}
is a sequence container that supports
(amortized) constant time insert and erase operations at the end;
insert and erase in the middle take linear time.
Storage management is handled automatically, though hints can be given
to improve efficiency.

\pnum
A \tcode{vector} meets all of the requirements
of a container\iref{container.reqmts},
of a reversible container\iref{container.rev.reqmts},
of an allocator-aware container\iref{container.alloc.reqmts},
of a sequence container, including most of the optional sequence container
requirements\iref{sequence.reqmts},
and, for an element type other than \tcode{bool},
of a contiguous container\iref{container.reqmts}.
The exceptions are the
\tcode{push_front}, \tcode{prepend_range}, \tcode{pop_front}, and \tcode{emplace_front} member functions, which are not
provided. Descriptions are provided here only for operations on \tcode{vector}
that are not described in one of these tables or for operations where there is
additional semantic information.

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\begin{codeblock}
namespace std {
  template<class T, class Allocator = allocator<T>>
  class vector {
  public:
    // types
    using value_type             = T;
    using allocator_type         = Allocator;
    using pointer                = allocator_traits<Allocator>::pointer;
    using const_pointer          = allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\impdefx{type of \tcode{vector::size_type}}@; // see \ref{container.requirements}
    using difference_type        = @\impdefx{type of \tcode{vector::difference_type}}@; // see \ref{container.requirements}
    using iterator               = @\impdefx{type of \tcode{vector::iterator}}@; // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{vector::const_iterator}}@; // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // \ref{vector.cons}, construct/copy/destroy
    constexpr vector() noexcept(noexcept(Allocator())) : vector(Allocator()) { }
    constexpr explicit vector(const Allocator&) noexcept;
    constexpr explicit vector(size_type n, const Allocator& = Allocator());
    constexpr vector(size_type n, const T& value, const Allocator& = Allocator());
    template<class InputIterator>
      constexpr vector(InputIterator first, InputIterator last, const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator());
    constexpr vector(const vector& x);
    constexpr vector(vector&&) noexcept;
    constexpr vector(const vector&, const type_identity_t<Allocator>&);
    constexpr vector(vector&&, const type_identity_t<Allocator>&);
    constexpr vector(initializer_list<T>, const Allocator& = Allocator());
    constexpr ~vector();
    constexpr vector& operator=(const vector& x);
    constexpr vector& operator=(vector&& x)
      noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
               allocator_traits<Allocator>::is_always_equal::value);
    constexpr vector& operator=(initializer_list<T>);
    template<class InputIterator>
      constexpr void assign(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr void assign_range(R&& rg);
    constexpr void assign(size_type n, const T& u);
    constexpr void assign(initializer_list<T>);
    constexpr allocator_type get_allocator() const noexcept;

    // iterators
    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;

    // \ref{vector.capacity}, capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;
    constexpr size_type capacity() const noexcept;
    constexpr void      resize(size_type sz);
    constexpr void      resize(size_type sz, const T& c);
    constexpr void      reserve(size_type n);
    constexpr void      shrink_to_fit();

    // element access
    constexpr reference       operator[](size_type n);
    constexpr const_reference operator[](size_type n) const;
    constexpr reference       at(size_type n);
    constexpr const_reference at(size_type n) const;
    constexpr reference       front();
    constexpr const_reference front() const;
    constexpr reference       back();
    constexpr const_reference back() const;

    // \ref{vector.data}, data access
    constexpr T*       data() noexcept;
    constexpr const T* data() const noexcept;

    // \ref{vector.modifiers}, modifiers
    template<class... Args> constexpr reference emplace_back(Args&&... args);
    constexpr void push_back(const T& x);
    constexpr void push_back(T&& x);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr void append_range(R&& rg);
    constexpr void pop_back();

    template<class... Args> constexpr iterator emplace(const_iterator position, Args&&... args);
    constexpr iterator insert(const_iterator position, const T& x);
    constexpr iterator insert(const_iterator position, T&& x);
    constexpr iterator insert(const_iterator position, size_type n, const T& x);
    template<class InputIterator>
      constexpr iterator insert(const_iterator position,
                                InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr iterator insert_range(const_iterator position, R&& rg);
    constexpr iterator insert(const_iterator position, initializer_list<T> il);
    constexpr iterator erase(const_iterator position);
    constexpr iterator erase(const_iterator first, const_iterator last);
    constexpr void     swap(vector&)
      noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
               allocator_traits<Allocator>::is_always_equal::value);
    constexpr void     clear() noexcept;
  };

  template<class InputIterator, class Allocator = allocator<@\placeholder{iter-value-type}@<InputIterator>>>
    vector(InputIterator, InputIterator, Allocator = Allocator())
      -> vector<@\placeholder{iter-value-type}@<InputIterator>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator = allocator<ranges::range_value_t<R>>>
    vector(from_range_t, R&&, Allocator = Allocator())
      -> vector<ranges::range_value_t<R>, Allocator>;
}
\end{codeblock}%
\indexlibrarymember{vector}{operator==}%
\indexlibrarymember{vector}{operator<}

\pnum
An incomplete type \tcode{T} may be used when instantiating \tcode{vector}
if the allocator meets the
allocator completeness requirements\iref{allocator.requirements.completeness}.
\tcode{T} shall be complete before any member of the resulting specialization
of \tcode{vector} is referenced.

\rSec3[vector.cons]{Constructors}

\indexlibraryctor{vector}
\begin{itemdecl}
constexpr explicit vector(const Allocator&) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{vector}, using the
specified allocator.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{vector}
\begin{itemdecl}
constexpr explicit vector(size_type n, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{vector}.

\pnum
\effects
Constructs a \tcode{vector} with \tcode{n}
default-inserted elements using the specified allocator.

\pnum
\complexity
Linear in \tcode{n}.
\end{itemdescr}

\indexlibraryctor{vector}
\begin{itemdecl}
constexpr vector(size_type n, const T& value,
                 const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is
\oldconcept{CopyInsertable} into \tcode{vector}.

\pnum
\effects
Constructs a \tcode{vector} with \tcode{n}
copies of \tcode{value}, using the specified allocator.

\pnum
\complexity
Linear in \tcode{n}.
\end{itemdescr}

\indexlibraryctor{vector}
\begin{itemdecl}
template<class InputIterator>
  constexpr vector(InputIterator first, InputIterator last,
                   const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{vector} equal to the
range \range{first}{last}, using the specified allocator.

\pnum
\complexity
Makes only $N$
calls to the copy constructor of
\tcode{T}
(where $N$
is the distance between
\tcode{first}
and
\tcode{last})
and no reallocations if
\tcode{InputIterator} meets the \oldconcept{ForwardIterator} requirements.
It makes order
$N$
calls to the copy constructor of
\tcode{T}
and order
$\log N$
reallocations if they are just input iterators.
\end{itemdescr}

\indexlibraryctor{vector}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{vector} object with the elements of the range \tcode{rg},
using the specified allocator.

\pnum
\complexity
Initializes exactly $N$ elements
from the results of dereferencing successive iterators of \tcode{rg},
where $N$ is \tcode{ranges::distance(rg)}.

\pnum
Performs no reallocations if:
\begin{itemize}
\item
\tcode{R} models \tcode{ranges::\libconcept{approximately_sized_range}}, and
\tcode{ranges::distance(rg) <= ranges::re\-serve_hint(rg)} is \tcode{true}, or
\item
\tcode{R} models \tcode{ranges::\libconcept{forward_range}} and
\tcode{R} does not model \tcode{ranges::\libconcept{approximately_sized_range}}.
\end{itemize}
Otherwise, performs order $\log N$ reallocations and
order $N$ calls to the copy or move constructor of \tcode{T}.
\end{itemdescr}

\rSec3[vector.capacity]{Capacity}

\indexlibrarymember{capacity}{vector}%
\begin{itemdecl}
constexpr size_type capacity() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The total number of elements that the vector can hold
without requiring reallocation.

\pnum
\complexity
Constant time.
\end{itemdescr}

\indexlibrarymember{reserve}{vector}%
\begin{itemdecl}
constexpr void reserve(size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{MoveInsertable} into \tcode{vector}.

\pnum
\effects
A directive that informs a
\tcode{vector}
of a planned change in size, so that it can manage the storage allocation accordingly.
After
\tcode{reserve()},
\tcode{capacity()}
is greater or equal to the argument of
\tcode{reserve}
if reallocation happens; and equal to the previous value of
\tcode{capacity()}
otherwise.
Reallocation happens at this point if and only if the current capacity is less than the
argument of
\tcode{reserve()}. If an exception is thrown
other than by the move constructor of a non-\oldconcept{CopyInsertable} type,
there are no effects.

\pnum
\throws
\tcode{length_error} if \tcode{n >
max_size()}.
\begin{footnote}
\tcode{reserve()} uses \tcode{Allocator::allocate()} which
can throw an appropriate exception.
\end{footnote}

\pnum
\complexity
Linear in the size of the sequence.

\pnum
\remarks
The size of the sequence is not changed.
Reallocation invalidates all the references, pointers, and iterators
referring to the elements in the sequence, as well as the past-the-end iterator.
\begin{note}
If no reallocation happens, they remain valid.
\end{note}
No reallocation shall take place during insertions that happen
after a call to \tcode{reserve()}
until an insertion would make the size of the vector
greater than the value of \tcode{capacity()}.
\end{itemdescr}

\indexlibrarymember{shrink_to_fit}{vector}%
\begin{itemdecl}
constexpr void shrink_to_fit();
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{MoveInsertable} into \tcode{vector}.

\pnum
\effects
\tcode{shrink_to_fit} is a non-binding request to reduce
\tcode{capacity()} to \tcode{size()}.
\begin{note}
The request is non-binding to allow latitude for
implementation-specific optimizations.
\end{note}
It does not increase \tcode{capacity()}, but may reduce \tcode{capacity()}
by causing reallocation.
If an exception is thrown other than by the move constructor
of a non-\oldconcept{CopyInsertable} \tcode{T}, there are no effects.

\pnum
\complexity
If reallocation happens,
linear in the size of the sequence.

\pnum
\remarks
Reallocation invalidates all the references, pointers, and iterators
referring to the elements in the sequence as well as the past-the-end iterator.
\begin{note}
If no reallocation happens, they remain valid.
\end{note}
\end{itemdescr}

\indexlibrarymember{swap}{vector}%
\begin{itemdecl}
constexpr void swap(vector& x)
  noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
           allocator_traits<Allocator>::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Exchanges the contents and
\tcode{capacity()}
of
\tcode{*this}
with that of \tcode{x}.

\pnum
\complexity
Constant time.
\end{itemdescr}

\indexlibrarymember{resize}{vector}%
\begin{itemdecl}
constexpr void resize(size_type sz);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is
\oldconcept{MoveInsertable} and \oldconcept{DefaultInsertable} into \tcode{vector}.

\pnum
\effects
If \tcode{sz < size()}, erases the last \tcode{size() - sz} elements
from the sequence. Otherwise,
appends \tcode{sz - size()} default-inserted elements to the sequence.

\pnum
\remarks
If an exception is thrown other than by the move constructor of a non-\oldconcept{CopyInsertable}
\tcode{T}, there are no effects.
\end{itemdescr}

\indexlibrarymember{resize}{vector}%
\begin{itemdecl}
constexpr void resize(size_type sz, const T& c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is
\oldconcept{CopyInsertable} into \tcode{vector}.

\pnum
\effects
If \tcode{sz < size()}, erases the last \tcode{size() - sz} elements
from the sequence. Otherwise,
appends \tcode{sz - size()} copies of \tcode{c} to the sequence.

\pnum
\remarks
If an exception is thrown, there are no effects.
\end{itemdescr}

\rSec3[vector.data]{Data}

\indexlibrarymember{data}{vector}%
\begin{itemdecl}
constexpr T*       data() noexcept;
constexpr const T* data() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A pointer such that \range{data()}{data() + size()} is a valid range. For a
non-empty vector, \tcode{data() == addressof(front())} is \keyword{true}.

\pnum
\complexity
Constant time.
\end{itemdescr}

\rSec3[vector.modifiers]{Modifiers}

\indexlibrarymember{insert}{vector}%
\begin{itemdecl}
constexpr iterator insert(const_iterator position, const T& x);
constexpr iterator insert(const_iterator position, T&& x);
constexpr iterator insert(const_iterator position, size_type n, const T& x);
template<class InputIterator>
  constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last);
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr iterator insert_range(const_iterator position, R&& rg);
constexpr iterator insert(const_iterator position, initializer_list<T>);

template<class... Args> constexpr reference emplace_back(Args&&... args);
template<class... Args> constexpr iterator emplace(const_iterator position, Args&&... args);
constexpr void push_back(const T& x);
constexpr void push_back(T&& x);
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr void append_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\complexity
If reallocation happens,
linear in the number of elements of the resulting vector;
otherwise,
linear in the number of elements inserted plus the distance
to the end of the vector.

\pnum
\remarks
Causes reallocation if the new size is greater than the old capacity.
Reallocation invalidates all the references, pointers, and iterators
referring to the elements in the sequence, as well as the past-the-end iterator.
If no reallocation happens, then
references, pointers, and iterators
before the insertion point remain valid
but those at or after the insertion point,
including the past-the-end iterator,
are invalidated.
If an exception is thrown other than by
the copy constructor, move constructor,
assignment operator, or move assignment operator of
\tcode{T} or by any \tcode{InputIterator} operation,
there are no effects.
If an exception is thrown while inserting a single element at the end and
\tcode{T} is \oldconcept{CopyInsertable} or \tcode{is_nothrow_move_constructible_v<T>}
is \tcode{true}, there are no effects.
Otherwise, if an exception is thrown by the move constructor of a non-\oldconcept{CopyInsertable}
\tcode{T}, the effects are unspecified.

\pnum
For the declarations taking a range \tcode{R},
performs at most one reallocation if:
\begin{itemize}
\item
\tcode{R} models \tcode{ranges::\libconcept{approximately_sized_range}} and
\tcode{ranges::distance(rg) <= ranges::re\-serve_hint(rg)} is \tcode{true}, or
\item
\tcode{R} models \tcode{ranges::\libconcept{forward_range}} and
\tcode{R} does not model \tcode{ranges::\libconcept{approximately_sized_range}}.
\end{itemize}
For the declarations taking a pair of \tcode{InputIterator},
performs at most one reallocation if
\tcode{InputItera\-tor} meets the \oldconcept{ForwardIterator} requirements.
\end{itemdescr}

\indexlibrarymember{erase}{vector}%
\begin{itemdecl}
constexpr iterator erase(const_iterator position);
constexpr iterator erase(const_iterator first, const_iterator last);
constexpr void pop_back();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Invalidates iterators and references at or after the point of the erase.

\pnum
\throws
Nothing unless an exception is thrown by the
assignment operator or move assignment operator of
\tcode{T}.

\pnum
\complexity
The destructor of \tcode{T} is called the number of times equal to the
number of the elements erased, but the assignment operator
of \tcode{T} is called the number of times equal to the number of
elements in the vector after the erased elements.
\end{itemdescr}

\rSec3[vector.erasure]{Erasure}

\indexlibrarymember{erase}{vector}%
\begin{itemdecl}
template<class T, class Allocator, class U = T>
  constexpr typename vector<T, Allocator>::size_type
    erase(vector<T, Allocator>& c, const U& value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto it = remove(c.begin(), c.end(), value);
auto r = distance(it, c.end());
c.erase(it, c.end());
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{erase_if}{vector}%
\begin{itemdecl}
template<class T, class Allocator, class Predicate>
  constexpr typename vector<T, Allocator>::size_type
    erase_if(vector<T, Allocator>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto it = remove_if(c.begin(), c.end(), pred);
auto r = distance(it, c.end());
c.erase(it, c.end());
return r;
\end{codeblock}
\end{itemdescr}

\rSec2[vector.bool]{Specialization of \tcode{vector} for \tcode{bool}}

\rSec3[vector.bool.pspc]{Partial class template specialization \tcode{vector<bool, Allocator>}}

\pnum
\indexlibraryglobal{vector<bool>}%
To optimize space allocation, a partial specialization of \tcode{vector} for
\tcode{bool} elements is provided:
\begin{codeblock}
namespace std {
  template<class Allocator>
  class vector<bool, Allocator> {
  public:
    // types
    using value_type             = bool;
    using allocator_type         = Allocator;
    using pointer                = @\impdefx{type of \tcode{vector<bool>::pointer}}@;
    using const_pointer          = @\impdefx{type of \tcode{vector<bool>::const_pointer}}@;
    using const_reference        = bool;
    using size_type              = @\impdefx{type of \tcode{vector<bool>::size_type}}@; // see \ref{container.requirements}
    using difference_type        = @\impdefx{type of \tcode{vector<bool>::difference_type}}@; // see \ref{container.requirements}
    using iterator               = @\impdefx{type of \tcode{vector<bool>::iterator}}@; // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{vector<bool>::const_iterator}}@; // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // bit reference
    class @\libmember{reference}{vector<bool>}@ {
    public:
      constexpr reference(const reference& x) noexcept;
      constexpr ~reference();
      constexpr reference& operator=(bool x) noexcept;
      constexpr reference& operator=(const reference& x) noexcept;
      constexpr const reference& operator=(bool x) const noexcept;
      constexpr operator bool() const noexcept;
      constexpr void flip() noexcept;   // flips the bit

      friend constexpr void swap(reference x, reference y) noexcept;
      friend constexpr void swap(reference x, bool& y) noexcept;
      friend constexpr void swap(bool& x, reference y) noexcept;
    };

    // construct/copy/destroy
    constexpr vector() noexcept(noexcept(Allocator())) : vector(Allocator()) { }
    constexpr explicit vector(const Allocator&) noexcept;
    constexpr explicit vector(size_type n, const Allocator& = Allocator());
    constexpr vector(size_type n, const bool& value, const Allocator& = Allocator());
    template<class InputIterator>
      constexpr vector(InputIterator first, InputIterator last, const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<bool> R>
      constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator());
    constexpr vector(const vector& x);
    constexpr vector(vector&& x) noexcept;
    constexpr vector(const vector&, const type_identity_t<Allocator>&);
    constexpr vector(vector&&, const type_identity_t<Allocator>&);
    constexpr vector(initializer_list<bool>, const Allocator& = Allocator());
    constexpr ~vector();
    constexpr vector& operator=(const vector& x);
    constexpr vector& operator=(vector&& x)
      noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
               allocator_traits<Allocator>::is_always_equal::value);
    constexpr vector& operator=(initializer_list<bool>);
    template<class InputIterator>
      constexpr void assign(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<bool> R>
      constexpr void assign_range(R&& rg);
    constexpr void assign(size_type n, const bool& t);
    constexpr void assign(initializer_list<bool>);
    constexpr allocator_type get_allocator() const noexcept;

    // iterators
    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;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;
    constexpr size_type capacity() const noexcept;
    constexpr void      resize(size_type sz, bool c = false);
    constexpr void      reserve(size_type n);
    constexpr void      shrink_to_fit();

    // element access
    constexpr reference       operator[](size_type n);
    constexpr const_reference operator[](size_type n) const;
    constexpr reference       at(size_type n);
    constexpr const_reference at(size_type n) const;
    constexpr reference       front();
    constexpr const_reference front() const;
    constexpr reference       back();
    constexpr const_reference back() const;

    // modifiers
    template<class... Args> constexpr reference emplace_back(Args&&... args);
    constexpr void push_back(const bool& x);
    template<@\exposconcept{container-compatible-range}@<bool> R>
      constexpr void append_range(R&& rg);
    constexpr void pop_back();
    template<class... Args> constexpr iterator emplace(const_iterator position, Args&&... args);
    constexpr iterator insert(const_iterator position, const bool& x);
    constexpr iterator insert(const_iterator position, size_type n, const bool& x);
    template<class InputIterator>
      constexpr iterator insert(const_iterator position,
                                InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<bool> R>
      constexpr iterator insert_range(const_iterator position, R&& rg);
    constexpr iterator insert(const_iterator position, initializer_list<bool> il);

    constexpr iterator erase(const_iterator position);
    constexpr iterator erase(const_iterator first, const_iterator last);
    constexpr void swap(vector&)
      noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
               allocator_traits<Allocator>::is_always_equal::value);
    constexpr void flip() noexcept;     // flips all bits
    constexpr void clear() noexcept;
  };
}
\end{codeblock}%

\pnum
Unless described below, all operations have the same requirements and
semantics as the \tcode{vector} primary template, except that operations
dealing with the \tcode{bool} value type map to bit values in the
container storage and
\tcode{allocator_traits::construct}\iref{allocator.traits.members}
is not used to construct these values.

\pnum
There is no requirement that the data be stored as a contiguous allocation
of \tcode{bool} values. A space-optimized representation of bits is
recommended instead.

\pnum
\tcode{reference}
is a class that simulates a reference to a single bit in the sequence.

\indexlibraryctor{vector<bool>::reference}%
\begin{itemdecl}
constexpr reference::reference(const reference& x) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{*this} to refer to the same bit as \tcode{x}.
\end{itemdescr}

\indexlibrarydtor{vector<bool>::reference}%
\begin{itemdecl}
constexpr reference::~reference();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
None.
\end{itemdescr}

\indexlibrarymember{operator=}{vector<bool>::reference}%
\begin{itemdecl}
constexpr reference& reference::operator=(bool x) noexcept;
constexpr reference& reference::operator=(const reference& x) noexcept;
constexpr const reference& reference::operator=(bool x) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Sets the bit referred to by \tcode{*this} when \tcode{bool(x)} is \tcode{true},
and clears it otherwise.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator bool}{vector<bool>::reference}%
\begin{itemdecl}
constexpr reference::operator bool() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if the value of the bit referred to by \tcode{*this} is one,
\tcode{false} otherwise.
\end{itemdescr}

\indexlibrarymember{flip}{vector<bool>::reference}%
\begin{itemdecl}
constexpr void reference::flip() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{*this = !*this}.
\end{itemdescr}

\indexlibrarymember{swap}{vector<bool>::reference}%
\begin{itemdecl}
constexpr void swap(reference x, reference y) noexcept;
constexpr void swap(reference x, bool& y) noexcept;
constexpr void swap(bool& x, reference y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Exchanges the values denoted by \tcode{x} and \tcode{y} as if by:

\begin{codeblock}
bool b = x;
x = y;
y = b;
\end{codeblock}
\end{itemdescr}



\indexlibrarymember{flip}{vector<bool>}%
\begin{itemdecl}
constexpr void flip() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Replaces each element in the container with its complement.
\end{itemdescr}

\begin{itemdecl}
template<class Allocator> struct hash<vector<bool, Allocator>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
The specialization is enabled\iref{unord.hash}.
\end{itemdescr}

\indexlibrary{is-vector-bool-reference@\exposid{is-vector-bool-reference}}%
\begin{itemdecl}
template<class T>
  constexpr bool @\exposid{is-vector-bool-reference}@ = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
The expression
\tcode{\exposid{is-vector-bool-reference}<T>} is \tcode{true}
if \tcode{T} denotes the type \tcode{vector<bool, Alloc>::\linebreak{}reference}
for some type \tcode{Alloc} and
\tcode{vector<bool, Alloc>} is not a program-defined specialization.
\end{itemdescr}

\rSec3[vector.bool.fmt]{Formatter specialization for \tcode{vector<bool>}}

\indexlibraryglobal{formatter}%
\begin{codeblock}
namespace std {
  template<class T, class charT>
    requires @\exposid{is-vector-bool-reference}@<T>
  struct formatter<T, charT> {
  private:
    formatter<bool, charT> @\exposid{underlying_}@;       // \expos

  public:
    template<class ParseContext>
      constexpr typename ParseContext::iterator
        parse(ParseContext& ctx);

    template<class FormatContext>
      constexpr typename FormatContext::iterator
        format(const T& ref, FormatContext& ctx) const;
  };
}
\end{codeblock}

\indexlibrarymember{parse}{formatter}%
\begin{itemdecl}
template<class ParseContext>
  constexpr typename ParseContext::iterator
    parse(ParseContext& ctx);
\end{itemdecl}

\begin{itemdescr}
\pnum
Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);}
\end{itemdescr}

\indexlibrarymember{format}{formatter}%
\begin{itemdecl}
template<class FormatContext>
  constexpr typename FormatContext::iterator
    format(const T& ref, FormatContext& ctx) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
Equivalent to: \tcode{return \exposid{underlying_}.format(ref, ctx);}
\end{itemdescr}

\rSec2[inplace.vector.syn]{Header \tcode{<inplace_vector>} synopsis}

\indexheader{inplace_vector}%
\begin{codeblock}
// mostly freestanding
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{inplace.vector}, class template \tcode{inplace_vector}
  template<class T, size_t N> class inplace_vector;             // partially freestanding

  // \ref{inplace.vector.erasure}, erasure
  template<class T, size_t N, class U = T>
    constexpr typename inplace_vector<T, N>::size_type
      erase(inplace_vector<T, N>& c, const U& value);
  template<class T, size_t N, class Predicate>
    constexpr typename inplace_vector<T, N>::size_type
      erase_if(inplace_vector<T, N>& c, Predicate pred);
}
\end{codeblock}

\rSec2[inplace.vector]{Class template \tcode{inplace_vector}}

\rSec3[inplace.vector.overview]{Overview}

\pnum
\indexlibraryglobal{inplace_vector}%
An \tcode{inplace_vector} is a contiguous container.
Its capacity is fixed and
its elements are stored within the \tcode{inplace_vector} object itself.

\pnum
An \tcode{inplace_vector} meets all of the requirements
of a container\iref{container.reqmts},
of a reversible container\iref{container.rev.reqmts},
of a contiguous container, and
of a sequence container,
including most of the optional sequence container requirements\iref{sequence.reqmts}.
The exceptions are the
\tcode{push_front},
\tcode{prepend_range},
\tcode{pop_front}, and
\tcode{emplace_front}
member functions, which are not provided.
Descriptions are provided here only
for operations on \tcode{inplace_vector} that
are not described in one of these tables or
for operations where there is additional semantic information.

\pnum
For any \tcode{N},
\tcode{inplace_vector<T, N>::iterator} and
\tcode{inplace_vector<T, N>::const_iterator}
meet the constexpr iterator requirements.

\pnum
Any member function of \tcode{inplace_vector<T, N>} that
would cause the size to exceed \tcode{N}
throws an exception of type \tcode{bad_alloc}.

\pnum
Let \tcode{IV} denote a specialization of \tcode{inplace_vector<T, N>}.
If \tcode{N} is zero, then
\tcode{IV} is trivially copyable and empty, and
\tcode{std::is_trivially_default_constructible_v<IV>} is \tcode{true}.
Otherwise:
\begin{itemize}
\item
If \tcode{is_trivially_copy_constructible_v<T>} is \tcode{true}, then
\tcode{IV} has a trivial copy constructor.
\item
If \tcode{is_trivially_move_constructible_v<T>} is \tcode{true}, then
\tcode{IV} has a trivial move constructor.
\item
If \tcode{is_trivially_destructible_v<T>} is \tcode{true}, then:
  \begin{itemize}
  \item
  \tcode{IV} has a trivial destructor.
  \item
  If
\begin{codeblock}
  is_trivially_copy_constructible_v<T> && is_trivially_copy_assignable_v<T>
\end{codeblock}
  is \tcode{true}, then
  \tcode{IV} has a trivial copy assignment operator.
  \item
  If
\begin{codeblock}
  is_trivially_move_constructible_v<T> && is_trivially_move_assignable_v<T>
\end{codeblock}
  is \tcode{true}, then
  \tcode{IV} has a trivial move assignment operator.
  \end{itemize}
\end{itemize}

\begin{codeblock}
namespace std {
  template<class T, size_t N>
  class inplace_vector {
  public:
    // types:
    using value_type             = T;
    using pointer                = T*;
    using const_pointer          = const T*;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = size_t;
    using difference_type        = ptrdiff_t;
    using iterator               = @\impdefx{type of \tcode{inplace_vector::iterator}}@; // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{inplace_vector::const_iterator}}@; // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // \ref{inplace.vector.cons}, construct/copy/destroy
    constexpr inplace_vector() noexcept;
    constexpr explicit inplace_vector(size_type n);                         // freestanding-deleted
    constexpr inplace_vector(size_type n, const T& value);                  // freestanding-deleted
    template<class InputIterator>
      constexpr inplace_vector(InputIterator first, InputIterator last);    // freestanding-deleted
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr inplace_vector(from_range_t, R&& rg);                       // freestanding-deleted
    constexpr inplace_vector(const inplace_vector&);
    constexpr inplace_vector(inplace_vector&&)
      noexcept(N == 0 || is_nothrow_move_constructible_v<T>);
    constexpr inplace_vector(initializer_list<T> il);                       // freestanding-deleted
    constexpr ~inplace_vector();
    constexpr inplace_vector& operator=(const inplace_vector& other);
    constexpr inplace_vector& operator=(inplace_vector&& other)
      noexcept(N == 0 || (is_nothrow_move_assignable_v<T> &&
                          is_nothrow_move_constructible_v<T>));
    constexpr inplace_vector& operator=(initializer_list<T>);               // freestanding-deleted
    template<class InputIterator>
      constexpr void assign(InputIterator first, InputIterator last);       // freestanding-deleted
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr void assign_range(R&& rg);                                  // freestanding-deleted
    constexpr void assign(size_type n, const T& u);                         // freestanding-deleted
    constexpr void assign(initializer_list<T> il);                          // freestanding-deleted

    // iterators
    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;

    // \ref{inplace.vector.capacity}, capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    static constexpr size_type max_size() noexcept;
    static constexpr size_type capacity() noexcept;
    constexpr void resize(size_type sz);                                    // freestanding-deleted
    constexpr void resize(size_type sz, const T& c);                        // freestanding-deleted
    static constexpr void reserve(size_type n);                             // freestanding-deleted
    static constexpr void shrink_to_fit() noexcept;

    // element access
    constexpr reference       operator[](size_type n);
    constexpr const_reference operator[](size_type n) const;
    constexpr reference       at(size_type n);                              // freestanding-deleted
    constexpr const_reference at(size_type n) const;                        // freestanding-deleted
    constexpr reference       front();
    constexpr const_reference front() const;
    constexpr reference       back();
    constexpr const_reference back() const;

    // \ref{inplace.vector.data}, data access
    constexpr       T* data()       noexcept;
    constexpr const T* data() const noexcept;

    // \ref{inplace.vector.modifiers}, modifiers
    template<class... Args>
      constexpr reference emplace_back(Args&&... args);                     // freestanding-deleted
    constexpr reference push_back(const T& x);                              // freestanding-deleted
    constexpr reference push_back(T&& x);                                   // freestanding-deleted
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr void append_range(R&& rg);                                  // freestanding-deleted
    constexpr void pop_back();

    template<class... Args>
      constexpr optional<reference> try_emplace_back(Args&&... args);
    constexpr optional<reference> try_push_back(const T& x);
    constexpr optional<reference> try_push_back(T&& x);

    template<class... Args>
      constexpr reference unchecked_emplace_back(Args&&... args);
    constexpr reference unchecked_push_back(const T& x);
    constexpr reference unchecked_push_back(T&& x);

    template<class... Args>
      constexpr iterator emplace(const_iterator position, Args&&... args);  // freestanding-deleted
    constexpr iterator insert(const_iterator position, const T& x);         // freestanding-deleted
    constexpr iterator insert(const_iterator position, T&& x);              // freestanding-deleted
    constexpr iterator insert(const_iterator position, size_type n,         // freestanding-deleted
                              const T& x);
    template<class InputIterator>
      constexpr iterator insert(const_iterator position,                    // freestanding-deleted
                                InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<T> R>
      constexpr iterator insert_range(const_iterator position, R&& rg);     // freestanding-deleted
    constexpr iterator insert(const_iterator position,                      // freestanding-deleted
                              initializer_list<T> il);
    constexpr iterator erase(const_iterator position);
    constexpr iterator erase(const_iterator first, const_iterator last);
    constexpr void swap(inplace_vector& x)
      noexcept(N == 0 || (is_nothrow_swappable_v<T> &&
                          is_nothrow_move_constructible_v<T>));
    constexpr void clear() noexcept;

    friend constexpr bool operator==(const inplace_vector& x,
                                     const inplace_vector& y);
    friend constexpr auto
      operator<=>(const inplace_vector& x, const inplace_vector& y)
        requires requires (const T t) { @\exposid{synth-three-way}@(t, t); }
      {
        return lexicographical_compare_three_way(x.begin(), x.end(), y.begin(), y.end(),
                                                 @\exposid{synth-three-way}@);
      }
    friend constexpr void swap(inplace_vector& x, inplace_vector& y)
      noexcept(N == 0 || (is_nothrow_swappable_v<T> &&
                          is_nothrow_move_constructible_v<T>))
      { x.swap(y); }
  };
}
\end{codeblock}

\rSec3[inplace.vector.cons]{Constructors}

\indexlibraryctor{inplace_vector}
\begin{itemdecl}
constexpr explicit inplace_vector(size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{inplace_vector}.

\pnum
\effects
Constructs an \tcode{inplace_vector} with \tcode{n} default-inserted elements.

\pnum
\complexity
Linear in \tcode{n}.
\end{itemdescr}

\indexlibraryctor{inplace_vector}
\begin{itemdecl}
constexpr inplace_vector(size_type n, const T& value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{inplace_vector}.

\pnum
\effects
Constructs an \tcode{inplace_vector} with \tcode{n} copies of \tcode{value}.

\pnum
\complexity
Linear in \tcode{n}.
\end{itemdescr}

\indexlibraryctor{inplace_vector}
\begin{itemdecl}
template<class InputIterator>
  constexpr inplace_vector(InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an \tcode{inplace_vector} equal to the range \range{first}{last}.

\pnum
\complexity
Linear in \tcode{distance(first, last)}.
\end{itemdescr}

\indexlibraryctor{inplace_vector}
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr inplace_vector(from_range_t, R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
If \tcode{ranges::size(rg)} is a constant expression,
then $\tcode{ranges::size(rg)} \le \tcode{N}$.

\pnum
\effects
Constructs an \tcode{inplace_vector} with
the elements of the range \tcode{rg}.

\pnum
\complexity
Linear in \tcode{ranges::distance(rg)}.
\end{itemdescr}

\rSec3[inplace.vector.capacity]{Capacity}

\indexlibrarymember{capacity}{inplace_vector}%
\indexlibrarymember{max_size}{inplace_vector}%
\begin{itemdecl}
static constexpr size_type capacity() noexcept;
static constexpr size_type max_size() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{N}.
\end{itemdescr}

\indexlibrarymember{resize}{inplace_vector}%
\begin{itemdecl}
constexpr void resize(size_type sz);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{inplace_vector}.

\pnum
\effects
%FIXME: Should "is \tcode{true}" be appended here?
If \tcode{sz < size()},
erases the last \tcode{size() - sz} elements from the sequence.
Otherwise,
appends \tcode{sz - size()} default-inserted elements to the sequence.

\pnum
\remarks
If an exception is thrown, there are no effects on \tcode{*this}.
\end{itemdescr}

\indexlibrarymember{resize}{inplace_vector}%
\begin{itemdecl}
constexpr void resize(size_type sz, const T& c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{CopyInsertable} into \tcode{inplace_vector}.

\pnum
\effects
%FIXME: Should "is \tcode{true}" be appended here?
If \tcode{sz < size()},
erases the last \tcode{size() - sz} elements from the sequence.
Otherwise,
appends \tcode{sz - size()} copies of \tcode{c} to the sequence.

\pnum
\remarks
If an exception is thrown, there are no effects on \tcode{*this}.
\end{itemdescr}

\indexlibrarymember{reserve}{inplace_vector}%
\begin{itemdecl}
static constexpr void reserve(size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
None.

\pnum
\throws
\tcode{bad_alloc} if \tcode{n > capacity()} is \tcode{true}.
\end{itemdescr}

\indexlibrarymember{shrink_to_fit}{inplace_vector}%
\begin{itemdecl}
static constexpr void shrink_to_fit() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
None.
\end{itemdescr}

\rSec3[inplace.vector.data]{Data}

\indexlibrarymember{data}{inplace_vector}%
\begin{itemdecl}
constexpr       T* data()       noexcept;
constexpr const T* data() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A pointer such that \range{data()}{data() + size()} is a valid range.
For a non-empty \tcode{inplace_vector},
\tcode{data() == addressof(front())} is \tcode{true}.

\pnum
\complexity
Constant time.
\end{itemdescr}

\rSec3[inplace.vector.modifiers]{Modifiers}

\indexlibrarymember{insert}{inplace_vector}%
\indexlibrarymember{insert_range}{inplace_vector}%
\indexlibrarymember{emplace}{inplace_vector}%
\indexlibrarymember{append_range}{inplace_vector}%
\begin{itemdecl}
constexpr iterator insert(const_iterator position, const T& x);
constexpr iterator insert(const_iterator position, T&& x);
constexpr iterator insert(const_iterator position, size_type n, const T& x);
template<class InputIterator>
  constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last);
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr iterator insert_range(const_iterator position, R&& rg);
constexpr iterator insert(const_iterator position, initializer_list<T> il);

template<class... Args>
  constexpr iterator emplace(const_iterator position, Args&&... args);
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr void append_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let $n$ be the value of \tcode{size()} before this call for
the \tcode{append_range} overload, and
\tcode{distance(begin, position)} otherwise.

\pnum
\complexity
Linear in the number of elements inserted plus
the distance to the end of the vector.

\pnum
\remarks
If an exception is thrown other than by the
copy constructor,
move constructor,
assignment operator, or
move assignment operator
of \tcode{T} or by
any \tcode{InputIterator} operation,
there are no effects.
Otherwise,
if an exception is thrown, then
$\tcode{size()} \ge n$ and
elements in the range \tcode{begin() + \range{0}{$n$}} are not modified.
\end{itemdescr}

\indexlibrarymember{push_back}{inplace_vector}%
\indexlibrarymember{emplace_back}{inplace_vector}%
\begin{itemdecl}
constexpr reference push_back(const T& x);
constexpr reference push_back(T&& x);
template<class... Args>
  constexpr reference emplace_back(Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{back()}.

\pnum
\throws
\tcode{bad_alloc} or
any exception thrown by the initialization of the inserted element.

\pnum
\complexity
Constant.

\pnum
\remarks
If an exception is thrown, there are no effects on \tcode{*this}.
\end{itemdescr}

\indexlibrarymember{try_emplace_back}{inplace_vector}%
\indexlibrarymember{try_push_back}{inplace_vector}%
\begin{itemdecl}
template<class... Args>
  constexpr optional<reference> try_emplace_back(Args&&... args);
constexpr optional<reference> try_push_back(const T& x);
constexpr optional<reference> try_push_back(T&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{vals} denote a pack:
\begin{itemize}
\item \tcode{std::forward<Args>(args)...} for the first overload,
\item \tcode{x} for the second overload,
\item \tcode{std::move(x)} for the third overload.
\end{itemize}

\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible}
into \tcode{inplace_vector} from \tcode{vals...}.

\pnum
\effects
If \tcode{size() < capacity()} is \tcode{true},
appends an object of type \tcode{T}
direct-non-list-initialized with \tcode{vals...}.
Otherwise, there are no effects.

\pnum
\returns
\keyword{nullopt} if \tcode{size() == capacity()} is \tcode{true},
otherwise \tcode{optional<reference>(in_place, back())}.

\pnum
\throws
Nothing unless an exception is thrown by the initialization of the inserted element.

\pnum
\complexity
Constant.

\pnum
\remarks
If an exception is thrown, there are no effects on \tcode{*this}.
\end{itemdescr}

\indexlibrarymember{unchecked_emplace_back}{inplace_vector}%
\begin{itemdecl}
template<class... Args>
  constexpr reference unchecked_emplace_back(Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{size() < capacity()} is \tcode{true}.

\pnum
\effects
Equivalent to:
\tcode{return *try_emplace_back(std::forward<Args>(args)...);}
\end{itemdescr}

\indexlibrarymember{unchecked_push_back}{inplace_vector}%
\begin{itemdecl}
constexpr reference unchecked_push_back(const T& x);
constexpr reference unchecked_push_back(T&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{size() < capacity()} is \tcode{true}.

\pnum
\effects
Equivalent to:
\tcode{return *try_push_back(std::forward<decltype(x)>(x));}
\end{itemdescr}

\indexlibrarymember{erase}{inplace_vector}%
\indexlibrarymember{pop_back}{inplace_vector}%
\begin{itemdecl}
constexpr iterator erase(const_iterator position);
constexpr iterator erase(const_iterator first, const_iterator last);
constexpr void pop_back();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Invalidates iterators and references at or after the point of the erase.

\pnum
\throws
Nothing unless an exception is thrown by
the assignment operator or move assignment operator of \tcode{T}.

\pnum
\complexity
The destructor of \tcode{T} is called the number of times
equal to the number of the elements erased, but
the assignment operator of \tcode{T} is called the number of times
equal to the number of elements after the erased elements.
\end{itemdescr}

\indexlibrarymember{swap}{inplace_vector}%
\begin{itemdecl}
constexpr void swap(inplace_vector& x) noexcept(
  N == 0 || (is_nothrow_swappable_v<T> && is_nothrow_move_constructible_v<T>));
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} meets the \oldconcept{MoveConstructible} requirements.
Let $M$ be \tcode{min(size(), x.size())}.
For each non-negative integer $n < M$,
\tcode{(*this)[$n$]} is swappable
with \tcode{x[$n$]}\iref{swappable.requirements}.

\pnum
\effects
Exchanges the contents of \tcode{*this} and \tcode{x}.
\end{itemdescr}

\rSec3[inplace.vector.erasure]{Erasure}

\indexlibrarymember{erase}{inplace_vector}%
\begin{itemdecl}
template<class T, size_t N, class U = T>
  constexpr size_t erase(inplace_vector<T, N>& c, const U& value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto it = remove(c.begin(), c.end(), value);
auto r = distance(it, c.end());
c.erase(it, c.end());
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{erase_if}{inplace_vector}%
\begin{itemdecl}
template<class T, size_t N, class Predicate>
  constexpr size_t erase_if(inplace_vector<T, N>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto it = remove_if(c.begin(), c.end(), pred);
auto r = distance(it, c.end());
c.erase(it, c.end());
return r;
\end{codeblock}
\end{itemdescr}

\rSec1[associative]{Associative containers}

\rSec2[associative.general]{General}

\pnum
The header \libheaderrefx{map}{associative.map.syn} defines the class templates
\tcode{map} and \tcode{multimap};
the header \libheaderrefx{set}{associative.set.syn} defines the class templates
\tcode{set} and \tcode{multiset}.

\pnum
The following exposition-only alias templates may appear in deduction guides for associative containers:
\begin{codeblock}
template<class InputIterator>
  using @\placeholder{iter-value-type}@ = iterator_traits<InputIterator>::value_type;   // \expos
template<class InputIterator>
  using @\placeholder{iter-key-type}@ = remove_cvref_t<
    tuple_element_t<0, @\exposid{iter-value-type}@<InputIterator>>>;                // \expos
template<class InputIterator>
  using @\placeholder{iter-mapped-type}@ = remove_cvref_t<
    tuple_element_t<1, @\exposid{iter-value-type}@<InputIterator>>>;                // \expos
template<class InputIterator>
  using @\placeholder{iter-to-alloc-type}@ = pair<
    const @\exposid{iter-key-type}@<InputIterator>,
    @\exposid{iter-mapped-type}@<InputIterator>>;                                   // \expos
template<ranges::@\libconcept{input_range}@ Range>
  using @\exposid{range-key-type}@ =
    remove_cvref_t<tuple_element_t<0, ranges::range_value_t<Range>>>;   // \expos
template<ranges::@\libconcept{input_range}@ Range>
  using @\exposid{range-mapped-type}@ =
    remove_cvref_t<tuple_element_t<1, ranges::range_value_t<Range>>>;   // \expos
template<ranges::@\libconcept{input_range}@ Range>
  using @\exposid{range-to-alloc-type}@ =
    pair<const @\exposid{range-key-type}@<Range>,
         @\exposid{range-mapped-type}@<Range>>;                                     // \expos
\end{codeblock}

\rSec2[associative.map.syn]{Header \tcode{<map>} synopsis}

\indexheader{map}%
\begin{codeblock}
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{map}, class template \tcode{map}
  template<class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key, T>>>
    class map;

  template<class Key, class T, class Compare, class Allocator>
    constexpr bool operator==(const map<Key, T, Compare, Allocator>& x,
                              const map<Key, T, Compare, Allocator>& y);
  template<class Key, class T, class Compare, class Allocator>
    constexpr @\exposid{synth-three-way-result}@<pair<const Key, T>>
      operator<=>(const map<Key, T, Compare, Allocator>& x,
                  const map<Key, T, Compare, Allocator>& y);

  template<class Key, class T, class Compare, class Allocator>
    constexpr void swap(map<Key, T, Compare, Allocator>& x,
                        map<Key, T, Compare, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  // \ref{map.erasure}, erasure for \tcode{map}
  template<class Key, class T, class Compare, class Allocator, class Predicate>
    constexpr typename map<Key, T, Compare, Allocator>::size_type
      erase_if(map<Key, T, Compare, Allocator>& c, Predicate pred);

  // \ref{multimap}, class template \tcode{multimap}
  template<class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key, T>>>
    class multimap;

  template<class Key, class T, class Compare, class Allocator>
    constexpr bool operator==(const multimap<Key, T, Compare, Allocator>& x,
                              const multimap<Key, T, Compare, Allocator>& y);
  template<class Key, class T, class Compare, class Allocator>
    constexpr @\exposid{synth-three-way-result}@<pair<const Key, T>>
      operator<=>(const multimap<Key, T, Compare, Allocator>& x,
                  const multimap<Key, T, Compare, Allocator>& y);

  template<class Key, class T, class Compare, class Allocator>
    constexpr void swap(multimap<Key, T, Compare, Allocator>& x,
                        multimap<Key, T, Compare, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  // \ref{multimap.erasure}, erasure for \tcode{multimap}
  template<class Key, class T, class Compare, class Allocator, class Predicate>
    constexpr typename multimap<Key, T, Compare, Allocator>::size_type
      erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred);

  namespace pmr {
    template<class Key, class T, class Compare = less<Key>>
      using map = std::map<Key, T, Compare,
                           polymorphic_allocator<pair<const Key, T>>>;

    template<class Key, class T, class Compare = less<Key>>
      using multimap = std::multimap<Key, T, Compare,
                                     polymorphic_allocator<pair<const Key, T>>>;
  }
}
\end{codeblock}

\rSec2[map]{Class template \tcode{map}}

\rSec3[map.overview]{Overview}

\indexlibraryglobal{map}%
\pnum
A \tcode{map} is an associative container that
supports unique keys (i.e., contains at most one of each key value) and
provides for fast retrieval of values of another type \tcode{T} based
on the keys. The \tcode{map} class supports bidirectional iterators.

\pnum
A \tcode{map} meets all of the requirements of
a container\iref{container.reqmts},
of a reversible container\iref{container.rev.reqmts},
of an allocator-aware container\iref{container.alloc.reqmts}, and
of an associative container\iref{associative.reqmts}.
A
\tcode{map}
also provides most operations described in~\ref{associative.reqmts}
for unique keys.
This means that a
\tcode{map}
supports the
\tcode{a_uniq}
operations in~\ref{associative.reqmts}
but not the
\tcode{a_eq}
operations.
For a
\tcode{map<Key,T>}
the
\tcode{key_type}
is
\tcode{Key}
and the
\tcode{value_type}
is
\tcode{pair<const Key,T>}.
Descriptions are provided here only for operations on
\tcode{map}
that are not described in one of those tables
or for operations where there is additional semantic information.

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\indexlibrarymember{comp}{map::value_compare}%
\indexlibrarymember{operator()}{map::value_compare}%
\begin{codeblock}
namespace std {
  template<class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key, T>>>
  class map {
  public:
    // types
    using key_type               = Key;
    using mapped_type            = T;
    using value_type             = pair<const Key, T>;
    using key_compare            = Compare;
    using allocator_type         = Allocator;
    using pointer                = allocator_traits<Allocator>::pointer;
    using const_pointer          = allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\impdefx{type of \tcode{map::size_type}}@; // see \ref{container.requirements}
    using difference_type        = @\impdefx{type of \tcode{map::difference_type}}@; // see \ref{container.requirements}
    using iterator               = @\impdefx{type of \tcode{map::iterator}}@; // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{map::const_iterator}}@; // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using node_type              = @\unspec@;
    using insert_return_type     = @\placeholdernc{insert-return-type}@<iterator, node_type>;

    class value_compare {
    protected:
      Compare comp;
      constexpr value_compare(Compare c) : comp(c) {}

    public:
      constexpr bool operator()(const value_type& x, const value_type& y) const {
        return comp(x.first, y.first);
      }
    };

    // \ref{map.cons}, construct/copy/destroy
    constexpr map() : map(Compare()) { }
    constexpr explicit map(const Compare& comp, const Allocator& = Allocator());
    template<class InputIterator>
      constexpr map(InputIterator first, InputIterator last,
                    const Compare& comp = Compare(), const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr map(from_range_t, R&& rg, const Compare& comp = Compare(),
                    const Allocator& = Allocator());
    constexpr map(const map& x);
    constexpr map(map&& x);
    constexpr explicit map(const Allocator&);
    constexpr map(const map&, const type_identity_t<Allocator>&);
    constexpr map(map&&, const type_identity_t<Allocator>&);
    constexpr map(initializer_list<value_type>, const Compare& = Compare(),
                  const Allocator& = Allocator());
    template<class InputIterator>
      constexpr map(InputIterator first, InputIterator last, const Allocator& a)
        : map(first, last, Compare(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr map(from_range_t, R&& rg, const Allocator& a)
        : map(from_range, std::forward<R>(rg), Compare(), a) { }
    constexpr map(initializer_list<value_type> il, const Allocator& a)
      : map(il, Compare(), a) { }
    constexpr ~map();
    constexpr map& operator=(const map& x);
    constexpr map& operator=(map&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Compare>);
    constexpr map& operator=(initializer_list<value_type>);
    constexpr allocator_type get_allocator() const noexcept;

    // iterators
    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;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // \ref{map.access}, element access
    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;

    // \ref{map.modifiers}, modifiers
    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);
    constexpr pair<iterator, bool> insert(value_type&& x);
    template<class P> constexpr pair<iterator, bool> insert(P&& x);
    constexpr iterator insert(const_iterator position, const value_type& x);
    constexpr iterator insert(const_iterator position, value_type&& x);
    template<class P>
      constexpr iterator insert(const_iterator position, P&&);
    template<class InputIterator>
      constexpr void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(R&& rg);
    constexpr void insert(initializer_list<value_type>);

    constexpr node_type extract(const_iterator position);
    constexpr node_type extract(const key_type& x);
    template<class K> constexpr node_type extract(K&& x);
    constexpr insert_return_type insert(node_type&& nh);
    constexpr iterator           insert(const_iterator hint, node_type&& nh);

    template<class... Args>
      constexpr pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
    template<class... Args>
      constexpr pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
    template<class K, class... Args>
      constexpr pair<iterator, bool> try_emplace(K&& k, Args&&... args);
    template<class... Args>
      constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
    template<class... Args>
      constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
    template<class K, class... Args>
      constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
    template<class M>
      constexpr pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
    template<class M>
      constexpr pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
    template<class K, class M>
      constexpr pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
    template<class M>
      constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
    template<class M>
      constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
    template<class K, class M>
      constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);

    constexpr iterator  erase(iterator position);
    constexpr iterator  erase(const_iterator position);
    constexpr size_type erase(const key_type& x);
    template<class K> constexpr size_type erase(K&& x);
    constexpr iterator  erase(const_iterator first, const_iterator last);
    constexpr void      swap(map&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Compare>);
    constexpr void      clear() noexcept;

    template<class C2>
      constexpr void merge(map<Key, T, C2, Allocator>& source);
    template<class C2>
      constexpr void merge(map<Key, T, C2, Allocator>&& source);
    template<class C2>
      constexpr void merge(multimap<Key, T, C2, Allocator>& source);
    template<class C2>
      constexpr void merge(multimap<Key, T, C2, Allocator>&& source);

    // observers
    constexpr key_compare key_comp() const;
    constexpr value_compare value_comp() const;

    // map operations
    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;
  };

  template<class InputIterator, class Compare = less<@\placeholder{iter-key-type}@<InputIterator>>,
           class Allocator = allocator<@\placeholder{iter-to-alloc-type}@<InputIterator>>>
    map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
      -> map<@\placeholder{iter-key-type}@<InputIterator>, @\placeholder{iter-mapped-type}@<InputIterator>, Compare, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Compare = less<@\exposid{range-key-type}@<R>>,
           class Allocator = allocator<@\exposid{range-to-alloc-type}@<R>>>
    map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())
      -> map<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, Compare, Allocator>;

  template<class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key, T>>>
    map(initializer_list<pair<Key, T>>, Compare = Compare(), Allocator = Allocator())
      -> map<Key, T, Compare, Allocator>;

  template<class InputIterator, class Allocator>
    map(InputIterator, InputIterator, Allocator)
      -> map<@\placeholder{iter-key-type}@<InputIterator>, @\placeholder{iter-mapped-type}@<InputIterator>,
             less<@\placeholder{iter-key-type}@<InputIterator>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    map(from_range_t, R&&, Allocator)
      -> map<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, less<@\exposid{range-key-type}@<R>>, Allocator>;

  template<class Key, class T, class Allocator>
    map(initializer_list<pair<Key, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>;
}
\end{codeblock}


\rSec3[map.cons]{Constructors, copy, and assignment}%
\indexlibrarymember{map}{operator==}%
\indexlibrarymember{map}{operator<}

\indexlibraryctor{map}%
\begin{itemdecl}
constexpr explicit map(const Compare& comp, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty
\tcode{map}
using the specified comparison object and allocator.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{map}%
\begin{itemdecl}
template<class InputIterator>
  constexpr map(InputIterator first, InputIterator last,
                const Compare& comp = Compare(), const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty
\tcode{map}
using the specified comparison object and allocator,
and inserts elements from the range
\range{first}{last}.

\pnum
\complexity
Linear in $N$ if the range
\range{first}{last}
is already sorted with respect to \tcode{comp}
and otherwise $N \log N$, where $N$
is \tcode{last - first}.
\end{itemdescr}

\indexlibraryctor{map}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr map(from_range_t, R&& rg, const Compare& comp = Compare(),
                const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{map}
using the specified comparison object and allocator,
and inserts elements from the range \tcode{rg}.

\pnum
\complexity
Linear in $N$ if \tcode{rg} is already sorted with respect to \tcode{comp} and
otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}.
\end{itemdescr}

\rSec3[map.access]{Element access}

\indexlibrary{\idxcode{operator[]}!\idxcode{map}}%
\begin{itemdecl}
constexpr mapped_type& operator[](const key_type& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return try_emplace(x).first->second;}
\end{itemdescr}

\indexlibrary{\idxcode{operator[]}!\idxcode{map}}%
\begin{itemdecl}
constexpr mapped_type& operator[](key_type&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return try_emplace(std::move(x)).first->second;}
\end{itemdescr}

\indexlibrary{\idxcode{operator[]}!\idxcode{map}}%
\begin{itemdecl}
template<class K> constexpr mapped_type& operator[](K&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The \grammarterm{qualified-id} \tcode{Compare::is_transparent}
is valid and denotes a type.

\pnum
\effects
Equivalent to: \tcode{return try_emplace(std::forward<K>(x)).first->second;}
\end{itemdescr}

\indexlibrarymember{at}{map}%
\begin{itemdecl}
constexpr mapped_type&       at(const key_type& x);
constexpr const mapped_type& at(const key_type& x) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A reference to the \tcode{mapped_type} corresponding to \tcode{x} in \tcode{*this}.

\pnum
\throws
An exception object of type \tcode{out_of_range} if
no such element is present.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexlibrarymember{at}{map}%
\begin{itemdecl}
template<class K> constexpr mapped_type&       at(const K& x);
template<class K> constexpr const mapped_type& at(const K& x) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The \grammarterm{qualified-id} \tcode{Compare::is_transparent}
is valid and denotes a type.

\pnum
\expects
The expression \tcode{find(x)} is well-formed and has well-defined behavior.

\pnum
\returns
A reference to \tcode{find(x)->second}.

\pnum
\throws
An exception object of type \tcode{out_of_range} if
\tcode{find(x) == end()} is \tcode{true}.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\rSec3[map.modifiers]{Modifiers}

\indexlibrarymember{insert}{map}%
\begin{itemdecl}
template<class P>
  constexpr pair<iterator, bool> insert(P&& x);
template<class P>
  constexpr iterator insert(const_iterator position, P&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<value_type, P\&\&>} is \tcode{true}.

\pnum
\effects
The first form is equivalent to
\tcode{return emplace(std::forward<P>(x))}. The second form is
equivalent to \tcode{return emplace_hint(position, std::forward<P>(x))}.
\end{itemdescr}

\indexlibrarymember{try_emplace}{map}%
\begin{itemdecl}
template<class... Args>
  constexpr pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
template<class... Args>
  constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map}
from \tcode{piecewise_construct}, \tcode{for\-ward_as_tuple(k)},
\tcode{forward_as_tuple(std::forward<Args>(args)...)}.

\pnum
\effects
If the map already contains an element
whose key is equivalent to \tcode{k},
there is no effect.
Otherwise inserts an object of type \tcode{value_type}
constructed with \tcode{piecewise_construct}, \tcode{forward_as_tuple(k)},
\tcode{forward_as_tuple(std::forward<Args>(args)...)}.

\pnum
\returns
In the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint},
respectively.
\end{itemdescr}

\indexlibrarymember{try_emplace}{map}%
\begin{itemdecl}
template<class... Args>
  constexpr pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
template<class... Args>
  constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map}
from \tcode{piecewise_construct}, \tcode{for\-ward_as_tuple(std::move(k))},
\tcode{forward_as_tuple(std::forward<Args>(args)...)}.

\pnum
\effects
If the map already contains an element
whose key is equivalent to \tcode{k},
there is no effect.
Otherwise inserts an object of type \tcode{value_type}
constructed with \tcode{piecewise_construct}, \tcode{forward_as_tuple(std::move(k))},
\tcode{forward_as_tuple(std::forward<Args>(args)...)}.

\pnum
\returns
In the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint},
respectively.
\end{itemdescr}

\indexlibrarymember{try_emplace}{map}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The \grammarterm{qualified-id} \tcode{Compare::is_transparent}
is valid and denotes a type.
For the first overload,
\tcode{is_convertible_v<K\&\&, const_iterator>} and
\tcode{is_convertible_v<K\&\&, iterator>}
are both \tcode{false}.

\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} from
\tcode{piecewise_construct, forward_as_tuple(std::forward<K>(k)),
forward_as_tuple(std::forward<Args>(args)...)}.

\pnum
\effects
If the map already contains an element whose key is equivalent to \tcode{k},
there is no effect.
Otherwise, let \tcode{r} be \tcode{equal_range(k)}.
Constructs an object \tcode{u} of type \tcode{value_type} with
\tcode{piecewise_construct, forward_as_tuple(std::forward<K>(k)),
forward_as_tuple(std::forward<Args>(args)...)}.\linebreak
If \tcode{equal_range(u.first) == r} is \tcode{false},
the behavior is undefined.
Inserts \tcode{u} into \tcode{*this}.

\pnum
\returns
For the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint}, respectively.
\end{itemdescr}

\indexlibrarymember{insert_or_assign}{map}%
\begin{itemdecl}
template<class M>
  constexpr pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
template<class M>
  constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_assignable_v<mapped_type\&, M\&\&>} is \tcode{true}.

\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map}
from \tcode{k}, \tcode{std::forward<M>(obj)}.

\pnum
\effects
If the map already contains an element \tcode{e}
whose key is equivalent to \tcode{k},
assigns \tcode{std::for\-ward<M>(obj)} to \tcode{e.second}.
Otherwise inserts an object of type \tcode{value_type}
constructed with \tcode{k}, \tcode{std::forward<M>(obj)}.

\pnum
\returns
In the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint},
respectively.
\end{itemdescr}

\indexlibrarymember{insert_or_assign}{map}%
\begin{itemdecl}
template<class M>
  constexpr pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
template<class M>
  constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_assignable_v<mapped_type\&, M\&\&>} is \tcode{true}.

\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map}
from \tcode{std::move(k)}, \tcode{std::for\-ward<M>(obj)}.

\pnum
\effects
If the map already contains an element \tcode{e}
whose key is equivalent to \tcode{k},
assigns \tcode{std::for\-ward<M>(obj)} to \tcode{e.second}.
Otherwise inserts an object of type \tcode{value_type}
constructed with \tcode{std::\brk{}move(k)}, \tcode{std::forward<M>(obj)}.

\pnum
\returns
In the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint},
respectively.
\end{itemdescr}

\indexlibrarymember{insert_or_assign}{map}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The \grammarterm{qualified-id} \tcode{Compare::is_transparent}
is valid and denotes a type.

\pnum
\mandates
\tcode{is_assignable_v<mapped_type\&, M\&\&>} is \tcode{true}.

\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} from
\tcode{std::forward<K>(k), std::\newline forward<M>(obj)}.

\pnum
\effects
If the map already contains an element \tcode{e}
whose key is equivalent to \tcode{k},
assigns \tcode{std::forward<M>\newline (obj)} to \tcode{e.second}.
Otherwise, let \tcode{r} be \tcode{equal_range(k)}.
Constructs an object \tcode{u} of type \tcode{value_type}
with \tcode{std::forward<K>(k), std::forward<M>(obj)}.
If \tcode{equal_range(u.first) == r} is \tcode{false},
the behavior is undefined.
Inserts \tcode{u} into \tcode{*this}.

\pnum
\returns
For the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint}, respectively.
\end{itemdescr}

\rSec3[map.erasure]{Erasure}

\indexlibrarymember{erase_if}{map}%
\begin{itemdecl}
template<class Key, class T, class Compare, class Allocator, class Predicate>
  typename map<Key, T, Compare, Allocator>::size_type
    constexpr erase_if(map<Key, T, Compare, Allocator>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();
\end{codeblock}
\end{itemdescr}

\rSec2[multimap]{Class template \tcode{multimap}}

\rSec3[multimap.overview]{Overview}

\pnum
\indexlibraryglobal{multimap}%
A
\tcode{multimap}
is an associative container 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
\tcode{T}
based on the keys.
The
\tcode{multimap}
class
supports bidirectional iterators.

\pnum
A \tcode{multimap} meets all of the requirements
of a container\iref{container.reqmts},
of a reversible container\iref{container.rev.reqmts},
of an allocator-aware container\iref{container.alloc.reqmts}, and
of an associative container\iref{associative.reqmts}.
A
\tcode{multimap}
also provides most operations described in~\ref{associative.reqmts}
for equal keys.
This means that a
\tcode{multimap}
supports the
\tcode{a_eq}
operations in~\ref{associative.reqmts}
but not the
\tcode{a_uniq}
operations.
For a
\tcode{multimap<Key,T>}
the
\tcode{key_type}
is
\tcode{Key}
and the
\tcode{value_type}
is
\tcode{pair<const Key,T>}.
Descriptions are provided here only for operations on
\tcode{multimap}
that are not described in one of those tables
or for operations where there is additional semantic information.

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\indexlibrarymember{comp}{multimap::value_compare}%
\indexlibrarymember{operator()}{multimap::value_compare}%
\begin{codeblock}
namespace std {
  template<class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key, T>>>
  class multimap {
  public:
    // types
    using key_type               = Key;
    using mapped_type            = T;
    using value_type             = pair<const Key, T>;
    using key_compare            = Compare;
    using allocator_type         = Allocator;
    using pointer                = allocator_traits<Allocator>::pointer;
    using const_pointer          = allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\impdefx{type of \tcode{multimap::size_type}}@; // see \ref{container.requirements}
    using difference_type        = @\impdefx{type of \tcode{multimap::difference_type}}@; // see \ref{container.requirements}
    using iterator               = @\impdefx{type of \tcode{multimap::iterator}}@; // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{multimap::const_iterator}}@; // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using node_type              = @\unspec@;

    class value_compare {
    protected:
      Compare comp;
      constexpr value_compare(Compare c) : comp(c) { }

    public:
      constexpr bool operator()(const value_type& x, const value_type& y) const {
        return comp(x.first, y.first);
      }
    };

    // \ref{multimap.cons}, construct/copy/destroy
    constexpr multimap() : multimap(Compare()) { }
    constexpr explicit multimap(const Compare& comp, const Allocator& = Allocator());
    template<class InputIterator>
      constexpr multimap(InputIterator first, InputIterator last,
                         const Compare& comp = Compare(), const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr multimap(from_range_t, R&& rg,
                         const Compare& comp = Compare(), const Allocator& = Allocator());
    constexpr multimap(const multimap& x);
    constexpr multimap(multimap&& x);
    constexpr explicit multimap(const Allocator&);
    constexpr multimap(const multimap&, const type_identity_t<Allocator>&);
    constexpr multimap(multimap&&, const type_identity_t<Allocator>&);
    constexpr multimap(initializer_list<value_type>,
                       const Compare& = Compare(), const Allocator& = Allocator());
    template<class InputIterator>
      constexpr multimap(InputIterator first, InputIterator last, const Allocator& a)
        : multimap(first, last, Compare(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr multimap(from_range_t, R&& rg, const Allocator& a)
        : multimap(from_range, std::forward<R>(rg), Compare(), a) { }
    constexpr multimap(initializer_list<value_type> il, const Allocator& a)
      : multimap(il, Compare(), a) { }
    constexpr ~multimap();
    constexpr multimap& operator=(const multimap& x);
    constexpr multimap& operator=(multimap&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Compare>);
    constexpr multimap& operator=(initializer_list<value_type>);
    constexpr allocator_type get_allocator() const noexcept;

    // iterators
    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;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // \ref{multimap.modifiers}, modifiers
    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);
    constexpr iterator insert(value_type&& x);
    template<class P> constexpr iterator insert(P&& x);
    constexpr iterator insert(const_iterator position, const value_type& x);
    constexpr iterator insert(const_iterator position, value_type&& x);
    template<class P> constexpr iterator insert(const_iterator position, P&& x);
    template<class InputIterator>
      constexpr void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(R&& rg);
    constexpr void insert(initializer_list<value_type>);

    constexpr node_type extract(const_iterator position);
    constexpr node_type extract(const key_type& x);
    template<class K> node_type extract(K&& x);
    constexpr iterator insert(node_type&& nh);
    constexpr iterator insert(const_iterator hint, node_type&& nh);

    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(multimap&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Compare>);
    constexpr void      clear() noexcept;

    template<class C2>
      constexpr void merge(multimap<Key, T, C2, Allocator>& source);
    template<class C2>
      constexpr void merge(multimap<Key, T, C2, Allocator>&& source);
    template<class C2>
      constexpr void merge(map<Key, T, C2, Allocator>& source);
    template<class C2>
      constexpr void merge(map<Key, T, C2, Allocator>&& source);

    // observers
    constexpr key_compare key_comp() const;
    constexpr value_compare value_comp() const;

    // map operations
    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;
  };

  template<class InputIterator, class Compare = less<@\placeholder{iter-key-type}@<InputIterator>>,
           class Allocator = allocator<@\placeholder{iter-to-alloc-type}@<InputIterator>>>
    multimap(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
      -> multimap<@\placeholder{iter-key-type}@<InputIterator>, @\placeholder{iter-mapped-type}@<InputIterator>,
                  Compare, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Compare = less<@\exposid{range-key-type}@<R>>,
           class Allocator = allocator<@\exposid{range-to-alloc-type}@<R>>>
    multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())
      -> multimap<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, Compare, Allocator>;

  template<class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key, T>>>
    multimap(initializer_list<pair<Key, T>>, Compare = Compare(), Allocator = Allocator())
      -> multimap<Key, T, Compare, Allocator>;

  template<class InputIterator, class Allocator>
    multimap(InputIterator, InputIterator, Allocator)
      -> multimap<@\placeholder{iter-key-type}@<InputIterator>, @\placeholder{iter-mapped-type}@<InputIterator>,
                  less<@\placeholder{iter-key-type}@<InputIterator>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    multimap(from_range_t, R&&, Allocator)
      -> multimap<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, less<@\exposid{range-key-type}@<R>>, Allocator>;

  template<class Key, class T, class Allocator>
    multimap(initializer_list<pair<Key, T>>, Allocator)
      -> multimap<Key, T, less<Key>, Allocator>;
}
\end{codeblock}%
\indexlibrarymember{multimap}{operator==}%
\indexlibrarymember{multimap}{operator<}

\rSec3[multimap.cons]{Constructors}

\indexlibraryctor{multimap}%
\begin{itemdecl}
constexpr explicit multimap(const Compare& comp, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty
\tcode{multimap}
using the specified comparison object and allocator.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{multimap}%
\begin{itemdecl}
template<class InputIterator>
  constexpr multimap(InputIterator first, InputIterator last,
                     const Compare& comp = Compare(), const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty
\tcode{multimap}
using the specified comparison object and allocator,
and inserts elements from the range
\range{first}{last}.

\pnum
\complexity
Linear in $N$ if the range
\range{first}{last}
is already sorted with respect to \tcode{comp}
and otherwise $N \log N$,
where $N$ is
\tcode{last - first}.
\end{itemdescr}

\indexlibraryctor{multimap}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr multimap(from_range_t, R&& rg,
                     const Compare& comp = Compare(), const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{multimap}
using the specified comparison object and allocator, and
inserts elements from the range \tcode{rg}.

\pnum
\complexity
Linear in $N$ if \tcode{rg} is already sorted with respect to \tcode{comp} and
otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}.
\end{itemdescr}

\rSec3[multimap.modifiers]{Modifiers}

\indexlibrarymember{insert}{multimap}%
\begin{itemdecl}
template<class P> constexpr iterator insert(P&& x);
template<class P> constexpr iterator insert(const_iterator position, P&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<value_type, P\&\&>} is \tcode{true}.

\pnum
\effects
The first form is equivalent to
\tcode{return emplace(std::forward<P>(x))}. The second form is
equivalent to \tcode{return emplace_hint(position, std::forward<P>(x))}.
\end{itemdescr}

\rSec3[multimap.erasure]{Erasure}

\indexlibrarymember{erase_if}{multimap}%
\begin{itemdecl}
template<class Key, class T, class Compare, class Allocator, class Predicate>
  typename multimap<Key, T, Compare, Allocator>::size_type
    constexpr erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();
\end{codeblock}
\end{itemdescr}

\rSec2[associative.set.syn]{Header \tcode{<set>} synopsis}%

\indexheader{set}%
\begin{codeblock}
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{set}, class template \tcode{set}
  template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
    class set;

  template<class Key, class Compare, class Allocator>
    constexpr bool operator==(const set<Key, Compare, Allocator>& x,
                              const set<Key, Compare, Allocator>& y);
  template<class Key, class Compare, class Allocator>
    constexpr @\exposid{synth-three-way-result}@<Key>
      operator<=>(const set<Key, Compare, Allocator>& x,
                  const set<Key, Compare, Allocator>& y);

  template<class Key, class Compare, class Allocator>
    constexpr void swap(set<Key, Compare, Allocator>& x,
                        set<Key, Compare, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  // \ref{set.erasure}, erasure for \tcode{set}
  template<class Key, class Compare, class Allocator, class Predicate>
    constexpr typename set<Key, Compare, Allocator>::size_type
      erase_if(set<Key, Compare, Allocator>& c, Predicate pred);

  // \ref{multiset}, class template \tcode{multiset}
  template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
    class multiset;

  template<class Key, class Compare, class Allocator>
    constexpr bool operator==(const multiset<Key, Compare, Allocator>& x,
                              const multiset<Key, Compare, Allocator>& y);
  template<class Key, class Compare, class Allocator>
    constexpr @\exposid{synth-three-way-result}@<Key>
      operator<=>(const multiset<Key, Compare, Allocator>& x,
                  const multiset<Key, Compare, Allocator>& y);

  template<class Key, class Compare, class Allocator>
    constexpr void swap(multiset<Key, Compare, Allocator>& x,
                        multiset<Key, Compare, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  // \ref{multiset.erasure}, erasure for \tcode{multiset}
  template<class Key, class Compare, class Allocator, class Predicate>
    constexpr typename multiset<Key, Compare, Allocator>::size_type
      erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred);

  namespace pmr {
    template<class Key, class Compare = less<Key>>
      using set = std::set<Key, Compare, polymorphic_allocator<Key>>;

    template<class Key, class Compare = less<Key>>
      using multiset = std::multiset<Key, Compare, polymorphic_allocator<Key>>;
  }
}
\end{codeblock}

\rSec2[set]{Class template \tcode{set}}

\rSec3[set.overview]{Overview}

\pnum
\indexlibraryglobal{set}%
A
\tcode{set}
is an associative container that supports unique keys (i.e., contains at most one of each key value) and
provides for fast retrieval of the keys themselves.
The
\tcode{set} class
supports bidirectional iterators.

\pnum
A \tcode{set} meets all of the requirements
of a container\iref{container.reqmts},
of a reversible container\iref{container.rev.reqmts},
of an allocator-aware container\iref{container.alloc.reqmts}, and
of an associative container\iref{associative.reqmts}.
A
\tcode{set}
also provides most operations described in~\ref{associative.reqmts}
for unique keys.
This means that a
\tcode{set}
supports the
\tcode{a_uniq}
operations in~\ref{associative.reqmts}
but not the
\tcode{a_eq}
operations.
For a
\tcode{set<Key>}
both the
\tcode{key_type}
and
\tcode{value_type}
are
\tcode{Key}.
Descriptions are provided here only for operations on
\tcode{set}
that are not described in one of these tables
and for operations where there is additional semantic information.

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\begin{codeblock}
namespace std {
  template<class Key, class Compare = less<Key>,
           class Allocator = allocator<Key>>
  class set {
  public:
    // types
    using key_type               = Key;
    using key_compare            = Compare;
    using value_type             = Key;
    using value_compare          = Compare;
    using allocator_type         = Allocator;
    using pointer                = allocator_traits<Allocator>::pointer;
    using const_pointer          = allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\impdefx{type of \tcode{set::size_type}}@; // see \ref{container.requirements}
    using difference_type        = @\impdefx{type of \tcode{set::difference_type}}@; // see \ref{container.requirements}
    using iterator               = @\impdefx{type of \tcode{set::iterator}}@; // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{set::const_iterator}}@; // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using node_type              = @\unspec@;
    using insert_return_type     = @\placeholdernc{insert-return-type}@<iterator, node_type>;

    // \ref{set.cons}, construct/copy/destroy
    constexpr set() : set(Compare()) { }
    constexpr explicit set(const Compare& comp, const Allocator& = Allocator());
    template<class InputIterator>
      constexpr set(InputIterator first, InputIterator last,
                    const Compare& comp = Compare(), const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr set(from_range_t, R&& rg,
                    const Compare& comp = Compare(), const Allocator& = Allocator());
    constexpr set(const set& x);
    constexpr set(set&& x);
    constexpr explicit set(const Allocator&);
    constexpr set(const set&, const type_identity_t<Allocator>&);
    constexpr set(set&&, const type_identity_t<Allocator>&);
    constexpr set(initializer_list<value_type>,
                  const Compare& = Compare(), const Allocator& = Allocator());
    template<class InputIterator>
      constexpr set(InputIterator first, InputIterator last, const Allocator& a)
        : set(first, last, Compare(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr set(from_range_t, R&& rg, const Allocator& a)
        : set(from_range, std::forward<R>(rg), Compare(), a) { }
    constexpr set(initializer_list<value_type> il, const Allocator& a)
      : set(il, Compare(), a) { }
    constexpr ~set();
    constexpr set& operator=(const set& x);
    constexpr set& operator=(set&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Compare>);
    constexpr set& operator=(initializer_list<value_type>);
    constexpr allocator_type get_allocator() const noexcept;

    // iterators
    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;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // \ref{set.modifiers}, modifiers
    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);
    constexpr pair<iterator,bool> insert(value_type&& x);
    template<class K> constexpr pair<iterator, bool> insert(K&& x);
    constexpr iterator insert(const_iterator position, const value_type& x);
    constexpr iterator insert(const_iterator position, value_type&& x);
    template<class K> constexpr iterator insert(const_iterator position, K&& x);
    template<class InputIterator>
      constexpr void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(R&& rg);
    constexpr void insert(initializer_list<value_type>);

    constexpr node_type extract(const_iterator position);
    constexpr node_type extract(const key_type& x);
    template<class K> constexpr node_type extract(K&& x);
    constexpr insert_return_type insert(node_type&& nh);
    constexpr iterator           insert(const_iterator hint, node_type&& nh);

    constexpr iterator  erase(iterator position)
      requires (!@\libconcept{same_as}@<iterator, const_iterator>);
    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(set&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Compare>);
    constexpr void      clear() noexcept;

    template<class C2>
      constexpr void merge(set<Key, C2, Allocator>& source);
    template<class C2>
      constexpr void merge(set<Key, C2, Allocator>&& source);
    template<class C2>
      constexpr void merge(multiset<Key, C2, Allocator>& source);
    template<class C2>
      constexpr void merge(multiset<Key, C2, Allocator>&& source);

    // observers
    constexpr key_compare key_comp() const;
    constexpr value_compare value_comp() const;

    // set operations
    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;
  };

  template<class InputIterator,
           class Compare = less<@\placeholder{iter-value-type}@<InputIterator>>,
           class Allocator = allocator<@\placeholder{iter-value-type}@<InputIterator>>>
    set(InputIterator, InputIterator,
        Compare = Compare(), Allocator = Allocator())
      -> set<@\placeholder{iter-value-type}@<InputIterator>, Compare, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Compare = less<ranges::range_value_t<R>>,
           class Allocator = allocator<ranges::range_value_t<R>>>
    set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())
      -> set<ranges::range_value_t<R>, Compare, Allocator>;

  template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
    set(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
      -> set<Key, Compare, Allocator>;

  template<class InputIterator, class Allocator>
    set(InputIterator, InputIterator, Allocator)
      -> set<@\placeholder{iter-value-type}@<InputIterator>,
             less<@\placeholder{iter-value-type}@<InputIterator>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    set(from_range_t, R&&, Allocator)
      -> set<ranges::range_value_t<R>, less<ranges::range_value_t<R>>, Allocator>;

  template<class Key, class Allocator>
    set(initializer_list<Key>, Allocator) -> set<Key, less<Key>, Allocator>;
}
\end{codeblock}%
\indexlibrarymember{set}{operator==}%
\indexlibrarymember{set}{operator<}

\rSec3[set.cons]{Constructors, copy, and assignment}

\indexlibraryctor{set}%
\begin{itemdecl}
constexpr explicit set(const Compare& comp, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{set} using the specified comparison object and allocator.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{set}%
\begin{itemdecl}
template<class InputIterator>
  constexpr set(InputIterator first, InputIterator last,
                const Compare& comp = Compare(), const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty
\tcode{set}
using the specified comparison object and allocator,
and inserts elements from the range
\range{first}{last}.

\pnum
\complexity
Linear in $N$ if the range
\range{first}{last}
is already sorted with respect to \tcode{comp}
and otherwise $N \log N$,
where $N$ is
\tcode{last - first}.
\end{itemdescr}

\indexlibraryctor{set}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr set(from_range_t, R&& rg, const Compare& comp = Compare(),
                const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{set} using the specified comparison object and allocator,
and inserts elements from the range \tcode{rg}.

\pnum
\complexity
Linear in $N$ if \tcode{rg} is already sorted with respect to \tcode{comp} and
otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}.
\end{itemdescr}

\rSec3[set.erasure]{Erasure}

\indexlibrarymember{erase_if}{set}%
\begin{itemdecl}
template<class Key, class Compare, class Allocator, class Predicate>
  constexpr typename set<Key, Compare, Allocator>::size_type
    erase_if(set<Key, Compare, Allocator>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();
\end{codeblock}
\end{itemdescr}

\rSec3[set.modifiers]{Modifiers}

\indexlibrarymember{insert}{set}%
\begin{itemdecl}
template<class K> constexpr pair<iterator, bool> insert(K&& x);
template<class K> constexpr iterator insert(const_iterator hint, K&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The \grammarterm{qualified-id} \tcode{Compare::is_transparent}
is valid and denotes a type.
For the second overload,
\tcode{is_convertible_v<K\&\&, const_iterator>} and
\tcode{is_convertible_v<K\&\&, iterator>} are both \tcode{false}.

\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{set} from
\tcode{std::forward<K>(x)}.

\pnum
\effects
If the set already contains an element that is equivalent to \tcode{x},
there is no effect.
Otherwise, let \tcode{r} be \tcode{equal_range(x)}.
Constructs an object \tcode{u} of type \tcode{value_type}
with \tcode{std::forward<K>(x)}.
If \tcode{equal_range(u) == r} is \tcode{false}, the behavior is undefined.
Inserts \tcode{u} into \tcode{*this}.

\pnum
\returns
For the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the set element that is equivalent to \tcode{x}.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\rSec2[multiset]{Class template \tcode{multiset}}

\rSec3[multiset.overview]{Overview}

\pnum
\indexlibraryglobal{multiset}%
A
\tcode{multiset}
is an associative container that supports equivalent keys (i.e., possibly contains multiple copies of
the same key value) and provides for fast retrieval of the keys themselves.
The
\tcode{multiset} class
supports bidirectional iterators.

\pnum
A \tcode{multiset} meets all of the requirements
of a container\iref{container.reqmts},
of a reversible container\iref{container.rev.reqmts},
of an allocator-aware container\iref{container.alloc.reqmts}, and
of an associative container\iref{associative.reqmts}.
\tcode{multiset}
also provides most operations described in~\ref{associative.reqmts}
for duplicate keys.
This means that a
\tcode{multiset}
supports the
\tcode{a_eq}
operations in~\ref{associative.reqmts}
but not the
\tcode{a_uniq}
operations.
For a
\tcode{multiset<Key>}
both the
\tcode{key_type}
and
\tcode{value_type}
are
\tcode{Key}.
Descriptions are provided here only for operations on
\tcode{multiset}
that are not described in one of these tables
and for operations where there is additional semantic information.

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\begin{codeblock}
namespace std {
  template<class Key, class Compare = less<Key>,
           class Allocator = allocator<Key>>
  class multiset {
  public:
    // types
    using key_type               = Key;
    using key_compare            = Compare;
    using value_type             = Key;
    using value_compare          = Compare;
    using allocator_type         = Allocator;
    using pointer                = allocator_traits<Allocator>::pointer;
    using const_pointer          = allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\impdefx{type of \tcode{multiset::size_type}}@; // see \ref{container.requirements}
    using difference_type        = @\impdefx{type of \tcode{multiset::difference_type}}@; // see \ref{container.requirements}
    using iterator               = @\impdefx{type of \tcode{multiset::iterator}}@; // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{multiset::const_iterator}}@; // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using node_type              = @\unspec@;

    // \ref{multiset.cons}, construct/copy/destroy
    constexpr multiset() : multiset(Compare()) { }
    constexpr explicit multiset(const Compare& comp, const Allocator& = Allocator());
    template<class InputIterator>
      constexpr multiset(InputIterator first, InputIterator last,
                         const Compare& comp = Compare(), const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr multiset(from_range_t, R&& rg,
                         const Compare& comp = Compare(), const Allocator& = Allocator());
    constexpr multiset(const multiset& x);
    constexpr multiset(multiset&& x);
    constexpr explicit multiset(const Allocator&);
    constexpr multiset(const multiset&, const type_identity_t<Allocator>&);
    constexpr multiset(multiset&&, const type_identity_t<Allocator>&);
    constexpr multiset(initializer_list<value_type>, const Compare& = Compare(),
                       const Allocator& = Allocator());
    template<class InputIterator>
      constexpr multiset(InputIterator first, InputIterator last, const Allocator& a)
        : multiset(first, last, Compare(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr multiset(from_range_t, R&& rg, const Allocator& a)
        : multiset(from_range, std::forward<R>(rg), Compare(), a) { }
    constexpr multiset(initializer_list<value_type> il, const Allocator& a)
      : multiset(il, Compare(), a) { }
    constexpr ~multiset();
    constexpr multiset& operator=(const multiset& x);
    constexpr multiset& operator=(multiset&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Compare>);
    constexpr multiset& operator=(initializer_list<value_type>);
    constexpr allocator_type get_allocator() const noexcept;

    // iterators
    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;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // modifiers
    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);
    constexpr iterator insert(value_type&& x);
    constexpr iterator insert(const_iterator position, const value_type& x);
    constexpr iterator insert(const_iterator position, value_type&& x);
    template<class InputIterator>
      constexpr void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(R&& rg);
    constexpr void insert(initializer_list<value_type>);

    constexpr node_type extract(const_iterator position);
    constexpr node_type extract(const key_type& x);
    template<class K> constexpr node_type extract(K&& x);
    constexpr iterator insert(node_type&& nh);
    constexpr iterator insert(const_iterator hint, node_type&& nh);

    constexpr iterator  erase(iterator position)
      requires (!@\libconcept{same_as}@<iterator, const_iterator>);
    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(multiset&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Compare>);
    constexpr void      clear() noexcept;

    template<class C2>
      constexpr void merge(multiset<Key, C2, Allocator>& source);
    template<class C2>
      constexpr void merge(multiset<Key, C2, Allocator>&& source);
    template<class C2>
      constexpr void merge(set<Key, C2, Allocator>& source);
    template<class C2>
      constexpr void merge(set<Key, C2, Allocator>&& source);

    // observers
    constexpr key_compare key_comp() const;
    constexpr value_compare value_comp() const;

    // set operations
    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;
  };

  template<class InputIterator,
           class Compare = less<@\placeholder{iter-value-type}@<InputIterator>>,
           class Allocator = allocator<@\placeholder{iter-value-type}@<InputIterator>>>
    multiset(InputIterator, InputIterator,
             Compare = Compare(), Allocator = Allocator())
      -> multiset<@\placeholder{iter-value-type}@<InputIterator>, Compare, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Compare = less<ranges::range_value_t<R>>,
           class Allocator = allocator<ranges::range_value_t<R>>>
    multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())
      -> multiset<ranges::range_value_t<R>, Compare, Allocator>;

  template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
    multiset(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
      -> multiset<Key, Compare, Allocator>;

  template<class InputIterator, class Allocator>
    multiset(InputIterator, InputIterator, Allocator)
      -> multiset<@\placeholder{iter-value-type}@<InputIterator>,
                  less<@\placeholder{iter-value-type}@<InputIterator>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    multiset(from_range_t, R&&, Allocator)
      -> multiset<ranges::range_value_t<R>, less<ranges::range_value_t<R>>, Allocator>;

  template<class Key, class Allocator>
    multiset(initializer_list<Key>, Allocator) -> multiset<Key, less<Key>, Allocator>;
}
\end{codeblock}%
\indexlibrarymember{multiset}{operator==}%
\indexlibrarymember{multiset}{operator<}

\rSec3[multiset.cons]{Constructors}

\indexlibraryctor{multiset}%
\begin{itemdecl}
constexpr explicit multiset(const Compare& comp, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{multiset} using the specified comparison object and allocator.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{multiset}%
\begin{itemdecl}
template<class InputIterator>
  constexpr multiset(InputIterator first, InputIterator last,
                     const Compare& comp = Compare(), const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty
\tcode{multiset}
using the specified comparison object and allocator,
and inserts elements from the range
\range{first}{last}.

\pnum
\complexity
Linear in $N$
if the range
\range{first}{last}
is already sorted with respect to \tcode{comp} and otherwise $N \log N$,
where $N$ is
\tcode{last - first}.
\end{itemdescr}

\indexlibraryctor{multiset}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr multiset(from_range_t, R&& rg, const Compare& comp = Compare(),
                     const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{multiset}
using the specified comparison object and allocator, and
inserts elements from the range \tcode{rg}.

\pnum
\complexity
Linear in $N$ if \tcode{rg} is already sorted with respect to \tcode{comp} and
otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}.
\end{itemdescr}

\rSec3[multiset.erasure]{Erasure}

\indexlibrarymember{erase_if}{multiset}%
\begin{itemdecl}
template<class Key, class Compare, class Allocator, class Predicate>
  constexpr typename multiset<Key, Compare, Allocator>::size_type
    erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();
\end{codeblock}
\end{itemdescr}

\rSec1[unord]{Unordered associative containers}

\rSec2[unord.general]{General}

\pnum
The header \libheaderrefx{unordered_map}{unord.map.syn} defines the class
templates \tcode{unordered_map} and \tcode{unordered_multimap};
the header \libheaderrefx{unordered_set}{unord.set.syn} defines the class
templates \tcode{unordered_set} and \tcode{unordered_multiset}.

\pnum
The exposition-only alias templates
\exposid{iter-value-type}, \exposid{iter-key-type},
\exposid{iter-mapped-type}, \exposid{iter-to\--alloc-type},
\exposid{range-key-type}, \exposid{range-mapped-type},
and \exposid{range-to-alloc-type}
defined in \ref{associative.general} may appear in deduction guides for unordered containers.

\rSec2[unord.map.syn]{Header \tcode{<unordered_map>} synopsis}

\indexheader{unordered_map}%
\indexlibraryglobal{unordered_map}%
\indexlibraryglobal{unordered_multimap}%
\begin{codeblock}
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{unord.map}, class template \tcode{unordered_map}
  template<class Key,
           class T,
           class Hash = hash<Key>,
           class Pred = equal_to<Key>,
           class Alloc = allocator<pair<const Key, T>>>
    class unordered_map;

  // \ref{unord.multimap}, class template \tcode{unordered_multimap}
  template<class Key,
           class T,
           class Hash = hash<Key>,
           class Pred = equal_to<Key>,
           class Alloc = allocator<pair<const Key, T>>>
    class unordered_multimap;

  template<class Key, class T, class Hash, class Pred, class Alloc>
    constexpr bool operator==(const unordered_map<Key, T, Hash, Pred, Alloc>& a,
                              const unordered_map<Key, T, Hash, Pred, Alloc>& b);

  template<class Key, class T, class Hash, class Pred, class Alloc>
    constexpr bool operator==(const unordered_multimap<Key, T, Hash, Pred, Alloc>& a,
                              const unordered_multimap<Key, T, Hash, Pred, Alloc>& b);

  template<class Key, class T, class Hash, class Pred, class Alloc>
    constexpr void swap(unordered_map<Key, T, Hash, Pred, Alloc>& x,
                        unordered_map<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  template<class Key, class T, class Hash, class Pred, class Alloc>
    constexpr void swap(unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
                        unordered_multimap<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // \ref{unord.map.erasure}, erasure for \tcode{unordered_map}
  template<class K, class T, class H, class P, class A, class Predicate>
    constexpr typename unordered_map<K, T, H, P, A>::size_type
      erase_if(unordered_map<K, T, H, P, A>& c, Predicate pred);

  // \ref{unord.multimap.erasure}, erasure for \tcode{unordered_multimap}
  template<class K, class T, class H, class P, class A, class Predicate>
    constexpr typename unordered_multimap<K, T, H, P, A>::size_type
      erase_if(unordered_multimap<K, T, H, P, A>& c, Predicate pred);

  namespace pmr {
    template<class Key,
             class T,
             class Hash = hash<Key>,
             class Pred = equal_to<Key>>
      using unordered_map =
        std::unordered_map<Key, T, Hash, Pred,
                           polymorphic_allocator<pair<const Key, T>>>;
    template<class Key,
             class T,
             class Hash = hash<Key>,
             class Pred = equal_to<Key>>
      using unordered_multimap =
        std::unordered_multimap<Key, T, Hash, Pred,
                                polymorphic_allocator<pair<const Key, T>>>;

  }
}
\end{codeblock}

\rSec2[unord.map]{Class template \tcode{unordered_map}}%
\indexlibraryglobal{unordered_map}

\rSec3[unord.map.overview]{Overview}

\pnum
\indextext{\idxcode{unordered_map}!unique keys}%
\indextext{unordered associative containers!unique keys}%
An \tcode{unordered_map} is an unordered associative container that
supports unique keys (an \tcode{unordered_map} contains at most one of each
key value) and that associates values of another type
\tcode{mapped_type} with the keys.
The \tcode{unordered_map} class
supports forward iterators.

\pnum
An \tcode{unordered_map} meets all of the requirements
of a container\iref{container.reqmts},
of an allocator-aware container\iref{container.alloc.reqmts}, and
of an unordered associative container\iref{unord.req}.
It provides the operations described in the preceding requirements table for unique keys;
that is, an \tcode{unordered_map} supports the \tcode{a_uniq} operations in that table,
not the \tcode{a_eq} operations.
For an \tcode{unordered_map<Key, T>} the \tcode{key_type} is \tcode{Key},
the \tcode{mapped_type} is \tcode{T},
and the \tcode{value_type} is \tcode{pair<const Key, T>}.

\pnum
Subclause~\ref{unord.map} only describes operations on \tcode{unordered_map} that
are not described in one of the requirement tables, or for which there
is additional semantic information.

\pnum
The types \tcode{iterator}, \tcode{const_iterator},
\tcode{local_iterator}, and \tcode{const_local_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\indexlibraryglobal{unordered_map}%
\begin{codeblock}
namespace std {
  template<class Key,
           class T,
           class Hash = hash<Key>,
           class Pred = equal_to<Key>,
           class Allocator = allocator<pair<const Key, T>>>
  class unordered_map {
  public:
    // types
    using key_type             = Key;
    using mapped_type          = T;
    using value_type           = pair<const Key, T>;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = allocator_traits<Allocator>::pointer;
    using const_pointer        = allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = @\impdefx{type of \tcode{unordered_map::size_type}}@; // see \ref{container.requirements}
    using difference_type      = @\impdefx{type of \tcode{unordered_map::difference_type}}@; // see \ref{container.requirements}

    using iterator             = @\impdefx{type of \tcode{unordered_map::iterator}}@; // see \ref{container.requirements}
    using const_iterator       = @\impdefx{type of \tcode{unordered_map::const_iterator}}@; // see \ref{container.requirements}
    using local_iterator       = @\impdefx{type of \tcode{unordered_map::local_iterator}}@; // see \ref{container.requirements}
    using const_local_iterator = @\impdefx{type of \tcode{unordered_map::const_local_iterator}}@; // see \ref{container.requirements}
    using node_type            = @\unspec@;
    using insert_return_type   = @\placeholdernc{insert-return-type}@<iterator, node_type>;

    // \ref{unord.map.cnstr}, construct/copy/destroy
    constexpr unordered_map();
    constexpr explicit unordered_map(size_type n, const hasher& hf = hasher(),
                                     const key_equal& eql = key_equal(),
                                     const allocator_type& a = allocator_type());
    template<class InputIterator>
      constexpr unordered_map(InputIterator f, InputIterator l,
                              size_type n = @\seebelow@, const hasher& hf = hasher(),
                              const key_equal& eql = key_equal(),
                              const allocator_type& a = allocator_type());

    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr unordered_map(from_range_t, R&& rg, size_type n = @\seebelow@,
                              const hasher& hf = hasher(), const key_equal& eql = key_equal(),
                              const allocator_type& a = allocator_type());
    constexpr unordered_map(const unordered_map&);
    constexpr unordered_map(unordered_map&&);
    constexpr explicit unordered_map(const Allocator&);
    constexpr unordered_map(const unordered_map&, const type_identity_t<Allocator>&);
    constexpr unordered_map(unordered_map&&, const type_identity_t<Allocator>&);
    constexpr unordered_map(initializer_list<value_type> il, size_type n = @\seebelow@,
                            const hasher& hf = hasher(),
                            const key_equal& eql = key_equal(),
                            const allocator_type& a = allocator_type());
    constexpr unordered_map(size_type n, const allocator_type& a)
      : unordered_map(n, hasher(), key_equal(), a) { }
    constexpr unordered_map(size_type n, const hasher& hf, const allocator_type& a)
      : unordered_map(n, hf, key_equal(), a) { }
    template<class InputIterator>
      constexpr unordered_map(InputIterator f, InputIterator l, size_type n,
                              const allocator_type& a)
        : unordered_map(f, l, n, hasher(), key_equal(), a) { }
    template<class InputIterator>
      constexpr unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                              const allocator_type& a)
        : unordered_map(f, l, n, hf, key_equal(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr unordered_map(from_range_t, R&& rg, size_type n, const allocator_type& a)
        : unordered_map(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr unordered_map(from_range_t, R&& rg, size_type n, const hasher& hf,
                              const allocator_type& a)
        : unordered_map(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { }
    constexpr unordered_map(initializer_list<value_type> il, size_type n,
                            const allocator_type& a)
      : unordered_map(il, n, hasher(), key_equal(), a) { }
    constexpr unordered_map(initializer_list<value_type> il, size_type n, const hasher& hf,
                            const allocator_type& a)
      : unordered_map(il, n, hf, key_equal(), a) { }
    constexpr ~unordered_map();
    constexpr unordered_map& operator=(const unordered_map&);
    constexpr unordered_map& operator=(unordered_map&&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Hash> &&
               is_nothrow_move_assignable_v<Pred>);
    constexpr unordered_map& operator=(initializer_list<value_type>);
    constexpr allocator_type get_allocator() const noexcept;

    // iterators
    constexpr iterator       begin() noexcept;
    constexpr const_iterator begin() const noexcept;
    constexpr iterator       end() noexcept;
    constexpr const_iterator end() const noexcept;
    constexpr const_iterator cbegin() const noexcept;
    constexpr const_iterator cend() const noexcept;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // \ref{unord.map.modifiers}, modifiers
    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& obj);
    constexpr pair<iterator, bool> insert(value_type&& obj);
    template<class P> constexpr pair<iterator, bool> insert(P&& obj);
    constexpr iterator       insert(const_iterator hint, const value_type& obj);
    constexpr iterator       insert(const_iterator hint, value_type&& obj);
    template<class P> constexpr iterator insert(const_iterator hint, P&& obj);
    template<class InputIterator> constexpr void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(R&& rg);
    constexpr void insert(initializer_list<value_type>);

    constexpr node_type extract(const_iterator position);
    constexpr node_type extract(const key_type& x);
    template<class K> constexpr node_type extract(K&& x);
    constexpr insert_return_type insert(node_type&& nh);
    constexpr iterator           insert(const_iterator hint, node_type&& nh);

    template<class... Args>
      constexpr pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
    template<class... Args>
      constexpr pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
    template<class K, class... Args>
      constexpr pair<iterator, bool> try_emplace(K&& k, Args&&... args);
    template<class... Args>
      constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
    template<class... Args>
      constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
    template<class K, class... Args>
      constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
    template<class M>
      constexpr pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
    template<class M>
      constexpr pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
    template<class K, class M>
      constexpr pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
    template<class M>
      constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
    template<class M>
      constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
    template<class K, class M>
      constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);

    constexpr iterator  erase(iterator position);
    constexpr iterator  erase(const_iterator position);
    constexpr size_type erase(const key_type& k);
    template<class K> constexpr size_type erase(K&& x);
    constexpr iterator  erase(const_iterator first, const_iterator last);
    constexpr void      swap(unordered_map&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Hash> && is_nothrow_swappable_v<Pred>);
    constexpr void      clear() noexcept;

    template<class H2, class P2>
      constexpr void merge(unordered_map<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      constexpr void merge(unordered_map<Key, T, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      constexpr void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      constexpr void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source);

    // observers
    constexpr hasher hash_function() const;
    constexpr key_equal key_eq() const;

    // map operations
    constexpr iterator         find(const key_type& k);
    constexpr const_iterator   find(const key_type& k) const;
    template<class K>
      constexpr iterator       find(const K& k);
    template<class K>
      constexpr const_iterator find(const K& k) const;
    constexpr size_type        count(const key_type& k) const;
    template<class K>
      constexpr size_type      count(const K& k) const;
    constexpr bool             contains(const key_type& k) const;
    template<class K>
      constexpr bool           contains(const K& k) const;
    constexpr pair<iterator, iterator>               equal_range(const key_type& k);
    constexpr pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      constexpr pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      constexpr pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // \ref{unord.map.elem}, element access
    constexpr mapped_type& operator[](const key_type& k);
    constexpr mapped_type& operator[](key_type&& k);
    template<class K> constexpr mapped_type& operator[](K&& k);
    constexpr mapped_type& at(const key_type& k);
    constexpr const mapped_type& at(const key_type& k) const;
    template<class K> constexpr mapped_type& at(const K& k);
    template<class K> constexpr const mapped_type& at(const K& k) const;

    // bucket interface
    constexpr size_type bucket_count() const noexcept;
    constexpr size_type max_bucket_count() const noexcept;
    constexpr size_type bucket_size(size_type n) const;
    constexpr size_type bucket(const key_type& k) const;
    template<class K> constexpr size_type bucket(const K& k) const;
    constexpr local_iterator begin(size_type n);
    constexpr const_local_iterator begin(size_type n) const;
    constexpr local_iterator end(size_type n);
    constexpr const_local_iterator end(size_type n) const;
    constexpr const_local_iterator cbegin(size_type n) const;
    constexpr const_local_iterator cend(size_type n) const;

    // hash policy
    constexpr float load_factor() const noexcept;
    constexpr float max_load_factor() const noexcept;
    constexpr void max_load_factor(float z);
    constexpr void rehash(size_type n);
    constexpr void reserve(size_type n);
  };

  template<class InputIterator,
           class Hash = hash<@\placeholder{iter-key-type}@<InputIterator>>,
           class Pred = equal_to<@\placeholder{iter-key-type}@<InputIterator>>,
           class Allocator = allocator<@\placeholder{iter-to-alloc-type}@<InputIterator>>>
    unordered_map(InputIterator, InputIterator, typename @\seebelow@::size_type = @\seebelow@,
                  Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_map<@\placeholder{iter-key-type}@<InputIterator>, @\placeholder{iter-mapped-type}@<InputIterator>, Hash, Pred,
                       Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Hash = hash<@\exposid{range-key-type}@<R>>,
           class Pred = equal_to<@\exposid{range-key-type}@<R>>,
           class Allocator = allocator<@\exposid{range-to-alloc-type}@<R>>>
    unordered_map(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@,
                  Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_map<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, Hash, Pred, Allocator>;

  template<class Key, class T, class Hash = hash<Key>,
           class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>>
    unordered_map(initializer_list<pair<Key, T>>,
                  typename @\seebelow@::size_type = @\seebelow@, Hash = Hash(),
                  Pred = Pred(), Allocator = Allocator())
      -> unordered_map<Key, T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_map(InputIterator, InputIterator, typename @\seebelow@::size_type, Allocator)
      -> unordered_map<@\placeholder{iter-key-type}@<InputIterator>, @\placeholder{iter-mapped-type}@<InputIterator>,
                       hash<@\placeholder{iter-key-type}@<InputIterator>>,
                       equal_to<@\placeholder{iter-key-type}@<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_map(InputIterator, InputIterator, Allocator)
      -> unordered_map<@\placeholder{iter-key-type}@<InputIterator>, @\placeholder{iter-mapped-type}@<InputIterator>,
                       hash<@\placeholder{iter-key-type}@<InputIterator>>,
                       equal_to<@\placeholder{iter-key-type}@<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_map(InputIterator, InputIterator, typename @\seebelow@::size_type, Hash, Allocator)
      -> unordered_map<@\placeholder{iter-key-type}@<InputIterator>, @\placeholder{iter-mapped-type}@<InputIterator>, Hash,
                       equal_to<@\placeholder{iter-key-type}@<InputIterator>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    unordered_map(from_range_t, R&&, typename @\seebelow@::size_type, Allocator)
      -> unordered_map<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, hash<@\exposid{range-key-type}@<R>>,
                       equal_to<@\exposid{range-key-type}@<R>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    unordered_map(from_range_t, R&&, Allocator)
      -> unordered_map<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, hash<@\exposid{range-key-type}@<R>>,
                       equal_to<@\exposid{range-key-type}@<R>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Hash, class Allocator>
    unordered_map(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator)
      -> unordered_map<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, Hash,
                       equal_to<@\exposid{range-key-type}@<R>>, Allocator>;

  template<class Key, class T, class Allocator>
    unordered_map(initializer_list<pair<Key, T>>, typename @\seebelow@::size_type,
                  Allocator)
      -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;

  template<class Key, class T, class Allocator>
    unordered_map(initializer_list<pair<Key, T>>, Allocator)
      -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;

  template<class Key, class T, class Hash, class Allocator>
    unordered_map(initializer_list<pair<Key, T>>, typename @\seebelow@::size_type, Hash,
                  Allocator)
      -> unordered_map<Key, T, Hash, equal_to<Key>, Allocator>;
}
\end{codeblock}

\pnum
A \tcode{size_type} parameter type in an \tcode{unordered_map} deduction guide
refers to the \tcode{size_type} member type of the type deduced by the deduction guide.

\rSec3[unord.map.cnstr]{Constructors}

\indexlibraryctor{unordered_map}%
\begin{itemdecl}
constexpr unordered_map() : unordered_map(size_type(@\seebelow@)) { }
constexpr explicit unordered_map(size_type n, const hasher& hf = hasher(),
                                 const key_equal& eql = key_equal(),
                                 const allocator_type& a = allocator_type());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{unordered_map} using the
specified hash function, key equality predicate, and allocator, and
using at least \tcode{n} buckets.  For the default constructor,
the number of buckets is \impldef{default number of buckets in
\tcode{unordered_map}}.
\tcode{max_load_factor()} returns \tcode{1.0}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{unordered_map}%
\begin{itemdecl}
template<class InputIterator>
  constexpr unordered_map(InputIterator f, InputIterator l,
                          size_type n = @\seebelow@, const hasher& hf = hasher(),
                          const key_equal& eql = key_equal(),
                          const allocator_type& a = allocator_type());
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr unordered_map(from_range_t, R&& rg,
                          size_type n = @\seebelow@, const hasher& hf = hasher(),
                          const key_equal& eql = key_equal(),
                          const allocator_type& a = allocator_type());
constexpr unordered_map(initializer_list<value_type> il,
                        size_type n = @\seebelow@, const hasher& hf = hasher(),
                        const key_equal& eql = key_equal(),
                        const allocator_type& a = allocator_type());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{unordered_map} using the
specified hash function, key equality predicate, and allocator, and
using at least \tcode{n} buckets. If \tcode{n} is not
provided, the number of buckets is \impldef{default number of buckets in
\tcode{unordered_map}}. Then
inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il},
respectively.
\tcode{max_load_factor()} returns \tcode{1.0}.

\pnum
\complexity
Average case linear, worst case quadratic.
\end{itemdescr}

\rSec3[unord.map.elem]{Element access}

\indexlibrarymember{unordered_map}{operator[]}%
\indextext{\idxcode{unordered_map}!element access}%
\begin{itemdecl}
constexpr mapped_type& operator[](const key_type& k);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return try_emplace(k).first->second;}
\end{itemdescr}

\indexlibrarymember{unordered_map}{operator[]}%
\indextext{\idxcode{unordered_map}!element access}%
\begin{itemdecl}
constexpr mapped_type& operator[](key_type&& k);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return try_emplace(std::move(k)).first->second;}
\end{itemdescr}

\indexlibrarymember{unordered_map}{operator[]}%
\indextext{\idxcode{unordered_map}!element access}%
\begin{itemdecl}
template<class K> constexpr mapped_type& operator[](K&& k);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and
\tcode{Pred::is_transparent} are valid and denote types.

\pnum
\effects
Equivalent to: \tcode{return try_emplace(std::forward<K>(k)).first->second;}
\end{itemdescr}

\indexlibrarymember{unordered_map}{at}%
\indextext{\idxcode{unordered_map}!element access}%
\begin{itemdecl}
constexpr mapped_type& at(const key_type& k);
constexpr const mapped_type& at(const key_type& k) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A reference to \tcode{x.second}, where \tcode{x} is the (unique) element whose key is equivalent to \tcode{k}.

\pnum
\throws
An exception object of type \tcode{out_of_range} if no such element is present.
\end{itemdescr}

\indexlibrarymember{unordered_map}{at}%
\indextext{\idxcode{unordered_map}!element access}%
\begin{itemdecl}
template<class K> constexpr mapped_type&       at(const K& k);
template<class K> constexpr const mapped_type& at(const K& k) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and
\tcode{Pred::is_transparent} are valid and denote types.

\pnum
\expects
The expression \tcode{find(k)} is well-formed and has well-defined behavior.

\pnum
\returns
A reference to \tcode{find(k)->second}.

\pnum
\throws
An exception object of type \tcode{out_of_range}
if \tcode{find(k) == end()} is \tcode{true}.
\end{itemdescr}

\rSec3[unord.map.modifiers]{Modifiers}

\indexlibrarymember{unordered_map}{insert}%
\begin{itemdecl}
template<class P>
  constexpr pair<iterator, bool> insert(P&& obj);
\end{itemdecl}

\begin{itemdescr}

\pnum
\constraints
\tcode{is_constructible_v<value_type, P\&\&>} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return emplace(std::forward<P>(obj));}
\end{itemdescr}

\indexlibrarymember{unordered_map}{insert}%
\begin{itemdecl}
template<class P>
  constexpr iterator insert(const_iterator hint, P&& obj);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<value_type, P\&\&>} is \tcode{true}.

\pnum
\effects
Equivalent to:
\tcode{return emplace_hint(hint, std::forward<P>(obj));}
\end{itemdescr}

\indexlibrarymember{try_emplace}{unordered_map}%
\begin{itemdecl}
template<class... Args>
  constexpr pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
template<class... Args>
  constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{unordered_map}
from \tcode{piecewise_con\-struct}, \tcode{forward_as_tuple(k)},
\tcode{forward_as_tuple(std::forward<Args>(args)...)}.

\pnum
\effects
If the map already contains an element
whose key is equivalent to \tcode{k},
there is no effect.
Otherwise inserts an object of type \tcode{value_type}
constructed with \tcode{piecewise_construct}, \tcode{forward_as_tuple(k)},
\tcode{forward_as_tuple(std::forward<Args>(args)...)}.

\pnum
\returns
In the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint},
respectively.
\end{itemdescr}

\indexlibrarymember{try_emplace}{unordered_map}%
\begin{itemdecl}
template<class... Args>
  constexpr pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
template<class... Args>
  constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{unordered_map}
from \tcode{piecewise_con\-struct}, \tcode{forward_as_tuple(std::move(k))},
\tcode{forward_as_tuple(std::forward<Args>(args)...)}.

\pnum
\effects
If the map already contains an element
whose key is equivalent to \tcode{k},
there is no effect.
Otherwise inserts an object of type \tcode{value_type}
constructed with \tcode{piecewise_construct}, \tcode{forward_as_tuple(std::move(k))},
\tcode{forward_as_tuple(std::forward<Args>(args)...)}.

\pnum
\returns
In the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint},
respectively.
\end{itemdescr}

\indexlibrarymember{try_emplace}{unordered_map}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and
\tcode{Pred::is_transparent} are valid and denote types.
For the first overload,
\tcode{is_convertible_v<K\&\&, const_iterator>} and
\tcode{is_convertible_v<K\&\&, iterator>} are both \tcode{false}.

\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible}
into \tcode{unordered_map} from
\tcode{piecewise_construct, forward_as_tuple(std::forward<K>(k)),
forward_as_tuple(std::forward<Args>\newline (args)...)}.

\pnum
\effects
If the map already contains an element whose key is equivalent to \tcode{k},
there is no effect.
Otherwise, let \tcode{h} be \tcode{hash_function()(k)}.
Constructs an object \tcode{u} of type \tcode{value_type}
with \tcode{piecewise_construct, forward_as_tuple(std::forward<K>(k)),
forward_as_tuple(std::forward<Args>(args)...)}.\newline
If \tcode{hash_function()(u.first) != h || contains(u.first)} is \tcode{true},
the behavior is undefined.
Inserts \tcode{u} into \tcode{*this}.

\pnum
\returns
For the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint}, respectively.
\end{itemdescr}

\indexlibrarymember{insert_or_assign}{unordered_map}%
\begin{itemdecl}
template<class M>
  constexpr pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
template<class M>
  constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_assignable_v<mapped_type\&, M\&\&>} is \tcode{true}.

\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{unordered_map}
from \tcode{k}, \tcode{std::for\-ward<M>(obj)}.

\pnum
\effects
If the map already contains an element \tcode{e}
whose key is equivalent to \tcode{k},
assigns \tcode{std::for\-ward<M>(obj)} to \tcode{e.second}.
Otherwise inserts an object of type \tcode{value_type}
constructed with \tcode{k}, \tcode{std::forward<M>(obj)}.

\pnum
\returns
In the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint},
respectively.
\end{itemdescr}

\indexlibrarymember{insert_or_assign}{unordered_map}%
\begin{itemdecl}
template<class M>
  constexpr pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
template<class M>
  constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_assignable_v<mapped_type\&, M\&\&>} is \tcode{true}.

\pnum
\expects
\tcode{value_type} is \oldconcept{Emplace\-Constructible} into \tcode{unordered_map}
from \tcode{std::move(k)}, \tcode{std::\brk{}forward<M>(obj)}.

\pnum
\effects
If the map already contains an element \tcode{e}
whose key is equivalent to \tcode{k},
assigns \tcode{std::for\-ward<M>(obj)} to \tcode{e.second}.
Otherwise inserts an object of type \tcode{value_type}
constructed with \tcode{std::\brk{}move(k)}, \tcode{std::forward<M>(obj)}.

\pnum
\returns
In the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint},
respectively.
\end{itemdescr}

\indexlibrarymember{insert_or_assign}{unordered_map}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and
\tcode{Pred::is_transparent} are valid and denote types.

\pnum
\mandates
\tcode{is_assignable_v<mapped_type\&, M\&\&>} is \tcode{true}.

\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible}
into \tcode{unordered_map}
from \tcode{std::forward<K>\newline (k), std::forward<M>(obj)}.

\pnum
\effects
If the map already contains an element \tcode{e}
whose key is equivalent to \tcode{k},
assigns \tcode{std::forward<M>\newline (obj)} to \tcode{e.second}.
Otherwise, let \tcode{h} be \tcode{hash_function()(k)}.
Constructs an object \tcode{u} of type \tcode{value_type}
with \tcode{std::forward<K>(k), std::forward<M>(obj)}.
If \tcode{hash_function()(u.first) != h || contains(u.first)} is \tcode{true},
the behavior is undefined.
Inserts \tcode{u} into \tcode{*this}.

\pnum
\returns
For the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint}, respectively.
\end{itemdescr}

\rSec3[unord.map.erasure]{Erasure}

\indexlibrarymember{erase_if}{unordered_map}%
\begin{itemdecl}
template<class K, class T, class H, class P, class A, class Predicate>
  constexpr typename unordered_map<K, T, H, P, A>::size_type
    erase_if(unordered_map<K, T, H, P, A>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();
\end{codeblock}
\end{itemdescr}

\rSec2[unord.multimap]{Class template \tcode{unordered_multimap}}%
\indexlibraryglobal{unordered_multimap}

\rSec3[unord.multimap.overview]{Overview}

\pnum
\indextext{\idxcode{unordered_multimap}!equivalent keys}%
\indextext{unordered associative containers!equivalent keys}%
An \tcode{unordered_multimap} is an unordered associative container
that supports equivalent keys (an instance of \tcode{unordered_multimap} may contain
multiple copies of each key value) and that associates values of
another type \tcode{mapped_type} with the keys.
The \tcode{unordered_multimap} class
supports forward iterators.

\pnum
An \tcode{unordered_multimap} meets all of the requirements
of a container\iref{container.reqmts},
of an allocator-aware container\iref{container.alloc.reqmts}, and
of an unordered associative container\iref{unord.req}.
It provides the operations described in the
preceding requirements table for equivalent keys; that is, an \tcode{unordered_multimap}
supports the \tcode{a_eq} operations in that table, not the \tcode{a_uniq} operations.
For an \tcode{unordered_multimap<Key, T>} the \tcode{key_type} is \tcode{Key},
the \tcode{mapped_type} is \tcode{T},
and the \tcode{value_type} is \tcode{pair<const Key, T>}.

\pnum
Subclause~\ref{unord.multimap} only describes operations on \tcode{unordered_multimap}
that are not described in one of the requirement tables, or for which
there is additional semantic information.

\pnum
The types \tcode{iterator}, \tcode{const_iterator},
\tcode{local_iterator}, and \tcode{const_local_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\indexlibraryglobal{unordered_multimap}%
\begin{codeblock}
namespace std {
  template<class Key,
           class T,
           class Hash = hash<Key>,
           class Pred = equal_to<Key>,
           class Allocator = allocator<pair<const Key, T>>>
  class unordered_multimap {
  public:
    // types
    using key_type             = Key;
    using mapped_type          = T;
    using value_type           = pair<const Key, T>;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = allocator_traits<Allocator>::pointer;
    using const_pointer        = allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = @\impdefx{type of \tcode{unordered_multimap::size_type}}@; // see \ref{container.requirements}
    using difference_type      = @\impdefx{type of \tcode{unordered_multimap::difference_type}}@; // see \ref{container.requirements}

    using iterator             = @\impdefx{type of \tcode{unordered_multimap::iterator}}@; // see \ref{container.requirements}
    using const_iterator       = @\impdefx{type of \tcode{unordered_multimap::const_iterator}}@; // see \ref{container.requirements}
    using local_iterator       = @\impdefx{type of \tcode{unordered_multimap::local_iterator}}@; // see \ref{container.requirements}
    using const_local_iterator = @\impdefx{type of \tcode{unordered_multimap::const_local_it\-erator}}@; // see \ref{container.requirements}
    using node_type            = @\unspec@;

    // \ref{unord.multimap.cnstr}, construct/copy/destroy
    constexpr unordered_multimap();
    constexpr explicit unordered_multimap(size_type n, const hasher& hf = hasher(),
                                          const key_equal& eql = key_equal(),
                                          const allocator_type& a = allocator_type());
    template<class InputIterator>
      constexpr unordered_multimap(InputIterator f, InputIterator l,
                                   size_type n = @\seebelow@, const hasher& hf = hasher(),
                                   const key_equal& eql = key_equal(),
                                   const allocator_type& a = allocator_type());
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr unordered_multimap(from_range_t, R&& rg,
                                   size_type n = @\seebelow@, const hasher& hf = hasher(),
                                   const key_equal& eql = key_equal(),
                                   const allocator_type& a = allocator_type());
    constexpr unordered_multimap(const unordered_multimap&);
    constexpr unordered_multimap(unordered_multimap&&);
    constexpr explicit unordered_multimap(const Allocator&);
    constexpr unordered_multimap(const unordered_multimap&, const type_identity_t<Allocator>&);
    constexpr unordered_multimap(unordered_multimap&&, const type_identity_t<Allocator>&);
    constexpr unordered_multimap(initializer_list<value_type> il,
                                 size_type n = @\seebelow@, const hasher& hf = hasher(),
                                 const key_equal& eql = key_equal(),
                                 const allocator_type& a = allocator_type());
    constexpr unordered_multimap(size_type n, const allocator_type& a)
      : unordered_multimap(n, hasher(), key_equal(), a) { }
    constexpr unordered_multimap(size_type n, const hasher& hf, const allocator_type& a)
      : unordered_multimap(n, hf, key_equal(), a) { }
    template<class InputIterator>
      constexpr unordered_multimap(InputIterator f, InputIterator l, size_type n,
                                   const allocator_type& a)
        : unordered_multimap(f, l, n, hasher(), key_equal(), a) { }
    template<class InputIterator>
      constexpr unordered_multimap(InputIterator f, InputIterator l, size_type n,
                                   const hasher& hf, const allocator_type& a)
        : unordered_multimap(f, l, n, hf, key_equal(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr unordered_multimap(from_range_t, R&& rg, size_type n, const allocator_type& a)
        : unordered_multimap(from_range, std::forward<R>(rg),
                             n, hasher(), key_equal(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr unordered_multimap(from_range_t, R&& rg, size_type n, const hasher& hf,
                                   const allocator_type& a)
        : unordered_multimap(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { }
    constexpr unordered_multimap(initializer_list<value_type> il, size_type n,
                                 const allocator_type& a)
      : unordered_multimap(il, n, hasher(), key_equal(), a) { }
    constexpr unordered_multimap(initializer_list<value_type> il, size_type n, const hasher& hf,
                                 const allocator_type& a)
      : unordered_multimap(il, n, hf, key_equal(), a) { }
    constexpr ~unordered_multimap();
    constexpr unordered_multimap& operator=(const unordered_multimap&);
    constexpr unordered_multimap& operator=(unordered_multimap&&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Hash> && is_nothrow_move_assignable_v<Pred>);
    constexpr unordered_multimap& operator=(initializer_list<value_type>);
    constexpr allocator_type get_allocator() const noexcept;

    // iterators
    constexpr iterator       begin() noexcept;
    constexpr const_iterator begin() const noexcept;
    constexpr iterator       end() noexcept;
    constexpr const_iterator end() const noexcept;
    constexpr const_iterator cbegin() const noexcept;
    constexpr const_iterator cend() const noexcept;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // \ref{unord.multimap.modifiers}, modifiers
    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& obj);
    constexpr iterator insert(value_type&& obj);
    template<class P> constexpr iterator insert(P&& obj);
    constexpr iterator insert(const_iterator hint, const value_type& obj);
    constexpr iterator insert(const_iterator hint, value_type&& obj);
    template<class P> constexpr iterator insert(const_iterator hint, P&& obj);
    template<class InputIterator> constexpr void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(R&& rg);
    constexpr void insert(initializer_list<value_type>);

    constexpr node_type extract(const_iterator position);
    constexpr node_type extract(const key_type& x);
    template<class K> constexpr node_type extract(K&& x);
    constexpr iterator insert(node_type&& nh);
    constexpr iterator insert(const_iterator hint, node_type&& nh);

    constexpr iterator  erase(iterator position);
    constexpr iterator  erase(const_iterator position);
    constexpr size_type erase(const key_type& k);
    template<class K> constexpr size_type erase(K&& x);
    constexpr iterator  erase(const_iterator first, const_iterator last);
    constexpr void      swap(unordered_multimap&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Hash> && is_nothrow_swappable_v<Pred>);
    constexpr void      clear() noexcept;

    template<class H2, class P2>
      constexpr void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      constexpr void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      constexpr void merge(unordered_map<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      constexpr void merge(unordered_map<Key, T, H2, P2, Allocator>&& source);

    // observers
    constexpr hasher hash_function() const;
    constexpr key_equal key_eq() const;

    // map operations
    constexpr iterator         find(const key_type& k);
    constexpr const_iterator   find(const key_type& k) const;
    template<class K>
      constexpr iterator       find(const K& k);
    template<class K>
      constexpr const_iterator find(const K& k) const;
    constexpr size_type        count(const key_type& k) const;
    template<class K>
      constexpr size_type      count(const K& k) const;
    constexpr bool             contains(const key_type& k) const;
    template<class K>
      constexpr bool           contains(const K& k) const;
    constexpr pair<iterator, iterator>               equal_range(const key_type& k);
    constexpr pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      constexpr pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      constexpr pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // bucket interface
    constexpr size_type bucket_count() const noexcept;
    constexpr size_type max_bucket_count() const noexcept;
    constexpr size_type bucket_size(size_type n) const;
    constexpr size_type bucket(const key_type& k) const;
    template<class K> constexpr size_type bucket(const K& k) const;
    constexpr local_iterator begin(size_type n);
    constexpr const_local_iterator begin(size_type n) const;
    constexpr local_iterator end(size_type n);
    constexpr const_local_iterator end(size_type n) const;
    constexpr const_local_iterator cbegin(size_type n) const;
    constexpr const_local_iterator cend(size_type n) const;

    // hash policy
    constexpr float load_factor() const noexcept;
    constexpr float max_load_factor() const noexcept;
    constexpr void max_load_factor(float z);
    constexpr void rehash(size_type n);
    constexpr void reserve(size_type n);
  };

  template<class InputIterator,
           class Hash = hash<@\placeholder{iter-key-type}@<InputIterator>>,
           class Pred = equal_to<@\placeholder{iter-key-type}@<InputIterator>>,
           class Allocator = allocator<@\placeholder{iter-to-alloc-type}@<InputIterator>>>
    unordered_multimap(InputIterator, InputIterator,
                       typename @\seebelow@::size_type = @\seebelow@,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_multimap<@\placeholder{iter-key-type}@<InputIterator>, @\placeholder{iter-mapped-type}@<InputIterator>,
                            Hash, Pred, Allocator>;

  template<ranges::@\libconcept{input_range}@ R,
           class Hash = hash<@\exposid{range-key-type}@<R>>,
           class Pred = equal_to<@\exposid{range-key-type}@<R>>,
           class Allocator = allocator<@\exposid{range-to-alloc-type}@<R>>>
    unordered_multimap(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_multimap<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, Hash, Pred, Allocator>;

  template<class Key, class T, class Hash = hash<Key>,
           class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>>
    unordered_multimap(initializer_list<pair<Key, T>>,
                       typename @\seebelow@::size_type = @\seebelow@,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_multimap<Key, T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_multimap(InputIterator, InputIterator, typename @\seebelow@::size_type, Allocator)
      -> unordered_multimap<@\placeholder{iter-key-type}@<InputIterator>, @\placeholder{iter-mapped-type}@<InputIterator>,
                            hash<@\placeholder{iter-key-type}@<InputIterator>>,
                            equal_to<@\placeholder{iter-key-type}@<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_multimap(InputIterator, InputIterator, Allocator)
      -> unordered_multimap<@\placeholder{iter-key-type}@<InputIterator>, @\placeholder{iter-mapped-type}@<InputIterator>,
                            hash<@\placeholder{iter-key-type}@<InputIterator>>,
                            equal_to<@\placeholder{iter-key-type}@<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_multimap(InputIterator, InputIterator, typename @\seebelow@::size_type, Hash,
                       Allocator)
      -> unordered_multimap<@\placeholder{iter-key-type}@<InputIterator>, @\placeholder{iter-mapped-type}@<InputIterator>, Hash,
                            equal_to<@\placeholder{iter-key-type}@<InputIterator>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    unordered_multimap(from_range_t, R&&, typename @\seebelow@::size_type, Allocator)
      -> unordered_multimap<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, hash<@\exposid{range-key-type}@<R>>,
                            equal_to<@\exposid{range-key-type}@<R>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    unordered_multimap(from_range_t, R&&, Allocator)
      -> unordered_multimap<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, hash<@\exposid{range-key-type}@<R>>,
                            equal_to<@\exposid{range-key-type}@<R>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Hash, class Allocator>
    unordered_multimap(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator)
      -> unordered_multimap<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, Hash,
                            equal_to<@\exposid{range-key-type}@<R>>, Allocator>;

  template<class Key, class T, class Allocator>
    unordered_multimap(initializer_list<pair<Key, T>>, typename @\seebelow@::size_type,
                       Allocator)
      -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>;

  template<class Key, class T, class Allocator>
    unordered_multimap(initializer_list<pair<Key, T>>, Allocator)
      -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>;

  template<class Key, class T, class Hash, class Allocator>
    unordered_multimap(initializer_list<pair<Key, T>>, typename @\seebelow@::size_type,
                       Hash, Allocator)
      -> unordered_multimap<Key, T, Hash, equal_to<Key>, Allocator>;
}
\end{codeblock}

\pnum
A \tcode{size_type} parameter type in an \tcode{unordered_multimap} deduction guide
refers to the \tcode{size_type} member type of the type deduced by the deduction guide.

\rSec3[unord.multimap.cnstr]{Constructors}

\indexlibraryctor{unordered_multimap}%
\begin{itemdecl}
constexpr unordered_multimap() : unordered_multimap(size_type(@\seebelow@)) { }
constexpr explicit unordered_multimap(size_type n, const hasher& hf = hasher(),
                                      const key_equal& eql = key_equal(),
                                      const allocator_type& a = allocator_type());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{unordered_multimap} using the
specified hash function, key equality predicate, and allocator, and
using at least \tcode{n} buckets.  For the default constructor,
the number of buckets is \impldef{default number of buckets in
\tcode{unordered_multimap}}.
\tcode{max_load_factor()} returns \tcode{1.0}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{unordered_multimap}%
\begin{itemdecl}
template<class InputIterator>
  constexpr unordered_multimap(InputIterator f, InputIterator l,
                               size_type n = @\seebelow@, const hasher& hf = hasher(),
                               const key_equal& eql = key_equal(),
                               const allocator_type& a = allocator_type());
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr unordered_multimap(from_range_t, R&& rg,
                               size_type n = @\seebelow@, const hasher& hf = hasher(),
                               const key_equal& eql = key_equal(),
                               const allocator_type& a = allocator_type());
constexpr unordered_multimap(initializer_list<value_type> il,
                             size_type n = @\seebelow@, const hasher& hf = hasher(),
                             const key_equal& eql = key_equal(),
                             const allocator_type& a = allocator_type());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{unordered_multimap} using the
specified hash function, key equality predicate, and allocator, and
using at least \tcode{n} buckets. If \tcode{n} is not
provided, the number of buckets is \impldef{default number of buckets in
\tcode{unordered_multimap}}. Then
inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il},
respectively.
\tcode{max_load_factor()} returns \tcode{1.0}.

\pnum
\complexity
Average case linear, worst case quadratic.
\end{itemdescr}

\rSec3[unord.multimap.modifiers]{Modifiers}

\indexlibrarymember{unordered_multimap}{insert}%
\begin{itemdecl}
template<class P>
  constexpr iterator insert(P&& obj);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<value_type, P\&\&>} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return emplace(std::forward<P>(obj));}
\end{itemdescr}

\indexlibrarymember{unordered_multimap}{insert}%
\begin{itemdecl}
template<class P>
  constexpr iterator insert(const_iterator hint, P&& obj);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<value_type, P\&\&>} is \tcode{true}.

\pnum
\effects
Equivalent to:
\tcode{return emplace_hint(hint, std::forward<P>(obj));}
\end{itemdescr}

\rSec3[unord.multimap.erasure]{Erasure}

\indexlibrarymember{erase_if}{unordered_multimap}%
\begin{itemdecl}
template<class K, class T, class H, class P, class A, class Predicate>
  constexpr typename unordered_multimap<K, T, H, P, A>::size_type
    erase_if(unordered_multimap<K, T, H, P, A>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();
\end{codeblock}
\end{itemdescr}

\rSec2[unord.set.syn]{Header \tcode{<unordered_set>} synopsis}

\indexheader{unordered_set}%
\indexlibraryglobal{unordered_set}%
\indexlibraryglobal{unordered_multiset}%
\begin{codeblock}
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{unord.set}, class template \tcode{unordered_set}
  template<class Key,
           class Hash = hash<Key>,
           class Pred = equal_to<Key>,
           class Alloc = allocator<Key>>
    class unordered_set;

  // \ref{unord.multiset}, class template \tcode{unordered_multiset}
  template<class Key,
           class Hash = hash<Key>,
           class Pred = equal_to<Key>,
           class Alloc = allocator<Key>>
    class unordered_multiset;

  template<class Key, class Hash, class Pred, class Alloc>
    constexpr bool operator==(const unordered_set<Key, Hash, Pred, Alloc>& a,
                              const unordered_set<Key, Hash, Pred, Alloc>& b);

  template<class Key, class Hash, class Pred, class Alloc>
    constexpr bool operator==(const unordered_multiset<Key, Hash, Pred, Alloc>& a,
                              const unordered_multiset<Key, Hash, Pred, Alloc>& b);

  template<class Key, class Hash, class Pred, class Alloc>
    constexpr void swap(unordered_set<Key, Hash, Pred, Alloc>& x,
                        unordered_set<Key, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  template<class Key, class Hash, class Pred, class Alloc>
    constexpr void swap(unordered_multiset<Key, Hash, Pred, Alloc>& x,
                        unordered_multiset<Key, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // \ref{unord.set.erasure}, erasure for \tcode{unordered_set}
  template<class K, class H, class P, class A, class Predicate>
    constexpr typename unordered_set<K, H, P, A>::size_type
      erase_if(unordered_set<K, H, P, A>& c, Predicate pred);

  // \ref{unord.multiset.erasure}, erasure for \tcode{unordered_multiset}
  template<class K, class H, class P, class A, class Predicate>
    constexpr typename unordered_multiset<K, H, P, A>::size_type
      erase_if(unordered_multiset<K, H, P, A>& c, Predicate pred);

  namespace pmr {
    template<class Key,
             class Hash = hash<Key>,
             class Pred = equal_to<Key>>
      using unordered_set = std::unordered_set<Key, Hash, Pred,
                                               polymorphic_allocator<Key>>;

    template<class Key,
             class Hash = hash<Key>,
             class Pred = equal_to<Key>>
      using unordered_multiset = std::unordered_multiset<Key, Hash, Pred,
                                                         polymorphic_allocator<Key>>;
  }
}
\end{codeblock}

\rSec2[unord.set]{Class template \tcode{unordered_set}}%
\indexlibraryglobal{unordered_set}

\rSec3[unord.set.overview]{Overview}

\pnum
\indextext{\idxcode{unordered_set}!unique keys}%
\indextext{unordered associative containers!unique keys}%
An \tcode{unordered_set} is an unordered associative container that
supports unique keys (an \tcode{unordered_set} contains at most one of each
key value) and in which the elements' keys are the elements
themselves.
The \tcode{unordered_set} class
supports forward iterators.

\pnum
An \tcode{unordered_set} meets all of the requirements
of a container\iref{container.reqmts},
of an allocator-aware container\iref{container.alloc.reqmts}, and
of an unordered associative container\iref{unord.req}.
It provides the operations described in the preceding requirements table for unique keys;
that is, an \tcode{unordered_set} supports the \tcode{a_uniq} operations in that table,
not the \tcode{a_eq} operations.
For an \tcode{unordered_set<Key>} the \tcode{key_type}
and the \tcode{value_type} are both \tcode{Key}.
The \tcode{iterator} and \tcode{const_iterator} types are both constant iterator types.
It is unspecified whether they are the same type.

\pnum
Subclause~\ref{unord.set} only describes operations on \tcode{unordered_set} that
are not described in one of the requirement tables, or for which there
is additional semantic information.

\pnum
The types \tcode{iterator}, \tcode{const_iterator},
\tcode{local_iterator}, and \tcode{const_local_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\indexlibraryglobal{unordered_set}%
\begin{codeblock}
namespace std {
  template<class Key,
           class Hash = hash<Key>,
           class Pred = equal_to<Key>,
           class Allocator = allocator<Key>>
  class unordered_set {
  public:
    // types
    using key_type             = Key;
    using value_type           = Key;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = allocator_traits<Allocator>::pointer;
    using const_pointer        = allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = @\impdefx{type of \tcode{unordered_set::size_type}}@; // see \ref{container.requirements}
    using difference_type      = @\impdefx{type of \tcode{unordered_set::difference_type}}@; // see \ref{container.requirements}

    using iterator             = @\impdefx{type of \tcode{unordered_set::iterator}}@; // see \ref{container.requirements}
    using const_iterator       = @\impdefx{type of \tcode{unordered_set::const_iterator}}@; // see \ref{container.requirements}
    using local_iterator       = @\impdefx{type of \tcode{unordered_set::local_iterator}}@; // see \ref{container.requirements}
    using const_local_iterator = @\impdefx{type of \tcode{unordered_set::const_local_iterator}}@; // see \ref{container.requirements}
    using node_type            = @\unspec@;
    using insert_return_type   = @\placeholdernc{insert-return-type}@<iterator, node_type>;

    // \ref{unord.set.cnstr}, construct/copy/destroy
    constexpr unordered_set();
    constexpr explicit unordered_set(size_type n, const hasher& hf = hasher(),
                                     const key_equal& eql = key_equal(),
                                     const allocator_type& a = allocator_type());
    template<class InputIterator>
      constexpr unordered_set(InputIterator f, InputIterator l,
                              size_type n = @\seebelow@, const hasher& hf = hasher(),
                              const key_equal& eql = key_equal(),
                              const allocator_type& a = allocator_type());
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr unordered_set(from_range_t, R&& rg,
                              size_type n = @\seebelow@, const hasher& hf = hasher(),
                              const key_equal& eql = key_equal(),
                              const allocator_type& a = allocator_type());
    constexpr unordered_set(const unordered_set&);
    constexpr unordered_set(unordered_set&&);
    constexpr explicit unordered_set(const Allocator&);
    constexpr unordered_set(const unordered_set&, const type_identity_t<Allocator>&);
    constexpr unordered_set(unordered_set&&, const type_identity_t<Allocator>&);
    constexpr unordered_set(initializer_list<value_type> il,
                            size_type n = @\seebelow@, const hasher& hf = hasher(),
                            const key_equal& eql = key_equal(),
                            const allocator_type& a = allocator_type());
    constexpr unordered_set(size_type n, const allocator_type& a)
      : unordered_set(n, hasher(), key_equal(), a) { }
    constexpr unordered_set(size_type n, const hasher& hf, const allocator_type& a)
      : unordered_set(n, hf, key_equal(), a) { }
    template<class InputIterator>
      constexpr unordered_set(InputIterator f, InputIterator l, size_type n,
                              const allocator_type& a)
        : unordered_set(f, l, n, hasher(), key_equal(), a) { }
    template<class InputIterator>
      constexpr unordered_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                              const allocator_type& a)
        : unordered_set(f, l, n, hf, key_equal(), a) { }
    constexpr unordered_set(initializer_list<value_type> il, size_type n,
                            const allocator_type& a)
      : unordered_set(il, n, hasher(), key_equal(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr unordered_set(from_range_t, R&& rg, size_type n, const allocator_type& a)
        : unordered_set(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr unordered_set(from_range_t, R&& rg, size_type n, const hasher& hf,
                              const allocator_type& a)
        : unordered_set(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { }
    constexpr unordered_set(initializer_list<value_type> il, size_type n, const hasher& hf,
                            const allocator_type& a)
      : unordered_set(il, n, hf, key_equal(), a) { }
    constexpr ~unordered_set();
    constexpr unordered_set& operator=(const unordered_set&);
    constexpr unordered_set& operator=(unordered_set&&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Hash> && is_nothrow_move_assignable_v<Pred>);
    constexpr unordered_set& operator=(initializer_list<value_type>);
    constexpr allocator_type get_allocator() const noexcept;

    // iterators
    constexpr iterator       begin() noexcept;
    constexpr const_iterator begin() const noexcept;
    constexpr iterator       end() noexcept;
    constexpr const_iterator end() const noexcept;
    constexpr const_iterator cbegin() const noexcept;
    constexpr const_iterator cend() const noexcept;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // \ref{unord.set.modifiers}, modifiers
    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& obj);
    constexpr pair<iterator, bool> insert(value_type&& obj);
    template<class K> constexpr pair<iterator, bool> insert(K&& obj);
    constexpr iterator insert(const_iterator hint, const value_type& obj);
    constexpr iterator insert(const_iterator hint, value_type&& obj);
    template<class K> constexpr iterator insert(const_iterator hint, K&& obj);
    template<class InputIterator> constexpr void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(R&& rg);
    constexpr void insert(initializer_list<value_type>);

    constexpr node_type extract(const_iterator position);
    constexpr node_type extract(const key_type& x);
    template<class K> constexpr node_type extract(K&& x);
    constexpr insert_return_type insert(node_type&& nh);
    constexpr iterator           insert(const_iterator hint, node_type&& nh);

    constexpr iterator  erase(iterator position)
      requires (!@\libconcept{same_as}@<iterator, const_iterator>);
    constexpr iterator  erase(const_iterator position);
    constexpr size_type erase(const key_type& k);
    template<class K> constexpr size_type erase(K&& x);
    constexpr iterator  erase(const_iterator first, const_iterator last);
    constexpr void      swap(unordered_set&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Hash> && is_nothrow_swappable_v<Pred>);
    constexpr void      clear() noexcept;

    template<class H2, class P2>
      constexpr void merge(unordered_set<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      constexpr void merge(unordered_set<Key, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      constexpr void merge(unordered_multiset<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      constexpr void merge(unordered_multiset<Key, H2, P2, Allocator>&& source);

    // observers
    constexpr hasher hash_function() const;
    constexpr key_equal key_eq() const;

    // set operations
    constexpr iterator         find(const key_type& k);
    constexpr const_iterator   find(const key_type& k) const;
    template<class K>
      constexpr iterator       find(const K& k);
    template<class K>
      constexpr const_iterator find(const K& k) const;
    constexpr size_type        count(const key_type& k) const;
    template<class K>
      constexpr size_type      count(const K& k) const;
    constexpr bool             contains(const key_type& k) const;
    template<class K>
      constexpr bool           contains(const K& k) const;
    constexpr pair<iterator, iterator>               equal_range(const key_type& k);
    constexpr pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      constexpr pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      constexpr pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // bucket interface
    constexpr size_type bucket_count() const noexcept;
    constexpr size_type max_bucket_count() const noexcept;
    constexpr size_type bucket_size(size_type n) const;
    constexpr size_type bucket(const key_type& k) const;
    template<class K> constexpr size_type bucket(const K& k) const;
    constexpr local_iterator begin(size_type n);
    constexpr const_local_iterator begin(size_type n) const;
    constexpr local_iterator end(size_type n);
    constexpr const_local_iterator end(size_type n) const;
    constexpr const_local_iterator cbegin(size_type n) const;
    constexpr const_local_iterator cend(size_type n) const;

    // hash policy
    constexpr float load_factor() const noexcept;
    constexpr float max_load_factor() const noexcept;
    constexpr void max_load_factor(float z);
    constexpr void rehash(size_type n);
    constexpr void reserve(size_type n);
  };

  template<class InputIterator,
           class Hash = hash<@\placeholder{iter-value-type}@<InputIterator>>,
           class Pred = equal_to<@\placeholder{iter-value-type}@<InputIterator>>,
           class Allocator = allocator<@\placeholder{iter-value-type}@<InputIterator>>>
    unordered_set(InputIterator, InputIterator, typename @\seebelow@::size_type = @\seebelow@,
                  Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_set<@\placeholder{iter-value-type}@<InputIterator>,
                       Hash, Pred, Allocator>;

  template<ranges::@\libconcept{input_range}@ R,
           class Hash = hash<ranges::range_value_t<R>>,
           class Pred = equal_to<ranges::range_value_t<R>>,
           class Allocator = allocator<ranges::range_value_t<R>>>
    unordered_set(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@,
                  Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_set<ranges::range_value_t<R>, Hash, Pred, Allocator>;

  template<class T, class Hash = hash<T>,
           class Pred = equal_to<T>, class Allocator = allocator<T>>
    unordered_set(initializer_list<T>, typename @\seebelow@::size_type = @\seebelow@,
                  Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_set<T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_set(InputIterator, InputIterator, typename @\seebelow@::size_type, Allocator)
      -> unordered_set<@\placeholder{iter-value-type}@<InputIterator>,
                       hash<@\placeholder{iter-value-type}@<InputIterator>>,
                       equal_to<@\placeholder{iter-value-type}@<InputIterator>>,
                       Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_set(InputIterator, InputIterator, typename @\seebelow@::size_type,
                  Hash, Allocator)
      -> unordered_set<@\placeholder{iter-value-type}@<InputIterator>, Hash,
                       equal_to<@\placeholder{iter-value-type}@<InputIterator>>,
                       Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Allocator)
      -> unordered_set<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>,
                       equal_to<ranges::range_value_t<R>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    unordered_set(from_range_t, R&&, Allocator)
      -> unordered_set<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>,
                       equal_to<ranges::range_value_t<R>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Hash, class Allocator>
    unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator)
      -> unordered_set<ranges::range_value_t<R>, Hash,
                       equal_to<ranges::range_value_t<R>>, Allocator>;

  template<class T, class Allocator>
    unordered_set(initializer_list<T>, typename @\seebelow@::size_type, Allocator)
      -> unordered_set<T, hash<T>, equal_to<T>, Allocator>;

  template<class T, class Hash, class Allocator>
    unordered_set(initializer_list<T>, typename @\seebelow@::size_type, Hash, Allocator)
      -> unordered_set<T, Hash, equal_to<T>, Allocator>;
}
\end{codeblock}

\pnum
A \tcode{size_type} parameter type in an \tcode{unordered_set} deduction guide
refers to the \tcode{size_type} member type of
the type deduced by the deduction guide.

\rSec3[unord.set.cnstr]{Constructors}

\indexlibraryctor{unordered_set}%
\begin{itemdecl}
constexpr unordered_set() : unordered_set(size_type(@\seebelow@)) { }
constexpr explicit unordered_set(size_type n, const hasher& hf = hasher(),
                                 const key_equal& eql = key_equal(),
                                 const allocator_type& a = allocator_type());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{unordered_set} using the
specified hash function, key equality predicate, and allocator, and
using at least \tcode{n} buckets.  For the default constructor,
the number of buckets is \impldef{default number of buckets in
\tcode{unordered_set}}.
\tcode{max_load_factor()} returns \tcode{1.0}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{unordered_set}%
\begin{itemdecl}
template<class InputIterator>
  constexpr unordered_set(InputIterator f, InputIterator l,
                          size_type n = @\seebelow@, const hasher& hf = hasher(),
                          const key_equal& eql = key_equal(),
                          const allocator_type& a = allocator_type());
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr unordered_multiset(from_range_t, R&& rg,
                               size_type n = @\seebelow@, const hasher& hf = hasher(),
                               const key_equal& eql = key_equal(),
                               const allocator_type& a = allocator_type());
constexpr unordered_set(initializer_list<value_type> il,
                        size_type n = @\seebelow@, const hasher& hf = hasher(),
                        const key_equal& eql = key_equal(),
                        const allocator_type& a = allocator_type());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{unordered_set} using the
specified hash function, key equality predicate, and allocator, and
using at least \tcode{n} buckets. If \tcode{n} is not
provided, the number of buckets is \impldef{default number of buckets in
\tcode{unordered_set}}. Then
inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il},
respectively.
\tcode{max_load_factor()} returns \tcode{1.0}.

\pnum
\complexity
Average case linear, worst case quadratic.
\end{itemdescr}

\rSec3[unord.set.erasure]{Erasure}

\indexlibrarymember{erase_if}{unordered_set}%
\begin{itemdecl}
template<class K, class H, class P, class A, class Predicate>
  constexpr typename unordered_set<K, H, P, A>::size_type
    erase_if(unordered_set<K, H, P, A>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();
\end{codeblock}
\end{itemdescr}

\rSec3[unord.set.modifiers]{Modifiers}

\indexlibrarymember{insert}{unordered_set}%
\begin{itemdecl}
template<class K> constexpr pair<iterator, bool> insert(K&& obj);
template<class K> constexpr iterator insert(const_iterator hint, K&& obj);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and
\tcode{Pred::is_transparent} are valid and denote types.
For the second overload,
\tcode{is_convertible_v<K\&\&, const_iterator>} and
\tcode{is_convertible_v<K\&\&, iterator>} are both \tcode{false}.

\pnum
\expects
\tcode{value_type} is \oldconcept{EmplaceConstructible}
into \tcode{unordered_set} from \tcode{std::forward<K>\newline (obj)}.

\pnum
\effects
If the set already contains an element that is equivalent to \tcode{obj},
there is no effect.
Otherwise, let \tcode{h} be \tcode{hash_function()(obj)}.
Constructs an object \tcode{u} of type \tcode{value_type}
with \tcode{std::forward<K>(obj)}.
If \tcode{hash_function()(u) != h || contains(u)} is \tcode{true},
the behavior is undefined.
Inserts \tcode{u} into \tcode{*this}.

\pnum
\returns
For the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the set element
that is equivalent to \tcode{obj}.

\pnum
\complexity
Average case constant, worst case linear.
\end{itemdescr}

\rSec2[unord.multiset]{Class template \tcode{unordered_multiset}}%
\indexlibraryglobal{unordered_multiset}

\rSec3[unord.multiset.overview]{Overview}

\pnum
\indextext{\idxcode{unordered_multiset}!equivalent keys}%
\indextext{unordered associative containers!equivalent keys}%
An \tcode{unordered_multiset} is an unordered associative container
that supports equivalent keys (an instance of \tcode{unordered_multiset} may contain
multiple copies of the same key value) and in which each element's key
is the element itself.
The \tcode{unordered_multiset} class
supports forward iterators.

\pnum
An \tcode{unordered_multiset} meets all of the requirements
of a container\iref{container.reqmts},
of an allocator-aware container\iref{container.alloc.reqmts}, and
of an unordered associative container\iref{unord.req}.
It provides the operations described in the
preceding requirements table for equivalent keys; that is, an \tcode{unordered_multiset}
supports the \tcode{a_eq} operations in that table, not the \tcode{a_uniq} operations.
For an \tcode{unordered_multiset<Key>} the \tcode{key_type} and the \tcode{value_type} are
both \tcode{Key}. The \tcode{iterator} and \tcode{const_iterator} types are both
constant iterator types. It is unspecified whether they are the same type.

\pnum
Subclause~\ref{unord.multiset} only describes operations on \tcode{unordered_multiset} that
are not described in one of the requirement tables, or for which there
is additional semantic information.

\pnum
The types \tcode{iterator}, \tcode{const_iterator},
\tcode{local_iterator}, and \tcode{const_local_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\indexlibraryglobal{unordered_multiset}%
\begin{codeblock}
namespace std {
  template<class Key,
           class Hash = hash<Key>,
           class Pred = equal_to<Key>,
           class Allocator = allocator<Key>>
  class unordered_multiset {
  public:
    // types
    using key_type             = Key;
    using value_type           = Key;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = allocator_traits<Allocator>::pointer;
    using const_pointer        = allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = @\impdefx{type of \tcode{unordered_multiset::size_type}}@; // see \ref{container.requirements}
    using difference_type      = @\impdefx{type of \tcode{unordered_multiset::difference_type}}@; // see \ref{container.requirements}

    using iterator             = @\impdefx{type of \tcode{unordered_multiset::iterator}}@; // see \ref{container.requirements}
    using const_iterator       = @\impdefx{type of \tcode{unordered_multiset::const_iterator}}@; // see \ref{container.requirements}
    using local_iterator       = @\impdefx{type of \tcode{unordered_multiset::local_iterator}}@; // see \ref{container.requirements}
    using const_local_iterator = @\impdefx{type of \tcode{unordered_multiset::const_local_it\-erator}}@; // see \ref{container.requirements}
    using node_type            = @\unspec@;

    // \ref{unord.multiset.cnstr}, construct/copy/destroy
    constexpr unordered_multiset();
    constexpr explicit unordered_multiset(size_type n, const hasher& hf = hasher(),
                                          const key_equal& eql = key_equal(),
                                          const allocator_type& a = allocator_type());
    template<class InputIterator>
      constexpr unordered_multiset(InputIterator f, InputIterator l,
                                   size_type n = @\seebelow@, const hasher& hf = hasher(),
                                   const key_equal& eql = key_equal(),
                                   const allocator_type& a = allocator_type());
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr unordered_multiset(from_range_t, R&& rg,
                                   size_type n = @\seebelow@, const hasher& hf = hasher(),
                                   const key_equal& eql = key_equal(),
                                   const allocator_type& a = allocator_type());
    constexpr unordered_multiset(const unordered_multiset&);
    constexpr unordered_multiset(unordered_multiset&&);
    constexpr explicit unordered_multiset(const Allocator&);
    constexpr unordered_multiset(const unordered_multiset&, const type_identity_t<Allocator>&);
    constexpr unordered_multiset(unordered_multiset&&, const type_identity_t<Allocator>&);
    constexpr unordered_multiset(initializer_list<value_type> il,
                                 size_type n = @\seebelow@, const hasher& hf = hasher(),
                                 const key_equal& eql = key_equal(),
                                 const allocator_type& a = allocator_type());
    constexpr unordered_multiset(size_type n, const allocator_type& a)
      : unordered_multiset(n, hasher(), key_equal(), a) { }
    constexpr unordered_multiset(size_type n, const hasher& hf, const allocator_type& a)
      : unordered_multiset(n, hf, key_equal(), a) { }
    template<class InputIterator>
      constexpr unordered_multiset(InputIterator f, InputIterator l, size_type n,
                                   const allocator_type& a)
        : unordered_multiset(f, l, n, hasher(), key_equal(), a) { }
    template<class InputIterator>
      constexpr unordered_multiset(InputIterator f, InputIterator l, size_type n,
                                   const hasher& hf, const allocator_type& a)
        : unordered_multiset(f, l, n, hf, key_equal(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr unordered_multiset(from_range_t, R&& rg, size_type n, const allocator_type& a)
        : unordered_multiset(from_range, std::forward<R>(rg),
                             n, hasher(), key_equal(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr unordered_multiset(from_range_t, R&& rg, size_type n, const hasher& hf,
                                   const allocator_type& a)
        : unordered_multiset(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { }
    constexpr unordered_multiset(initializer_list<value_type> il, size_type n,
                                 const allocator_type& a)
      : unordered_multiset(il, n, hasher(), key_equal(), a) { }
    constexpr unordered_multiset(initializer_list<value_type> il, size_type n, const hasher& hf,
                                 const allocator_type& a)
      : unordered_multiset(il, n, hf, key_equal(), a) { }
    constexpr ~unordered_multiset();
    constexpr unordered_multiset& operator=(const unordered_multiset&);
    constexpr unordered_multiset& operator=(unordered_multiset&&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Hash> && is_nothrow_move_assignable_v<Pred>);
    constexpr unordered_multiset& operator=(initializer_list<value_type>);
    constexpr allocator_type get_allocator() const noexcept;

    // iterators
    constexpr iterator       begin() noexcept;
    constexpr const_iterator begin() const noexcept;
    constexpr iterator       end() noexcept;
    constexpr const_iterator end() const noexcept;
    constexpr const_iterator cbegin() const noexcept;
    constexpr const_iterator cend() const noexcept;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // modifiers
    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& obj);
    constexpr iterator insert(value_type&& obj);
    constexpr iterator insert(const_iterator hint, const value_type& obj);
    constexpr iterator insert(const_iterator hint, value_type&& obj);
    template<class InputIterator> constexpr void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(R&& rg);
    constexpr void insert(initializer_list<value_type>);

    constexpr node_type extract(const_iterator position);
    constexpr node_type extract(const key_type& x);
    template<class K> constexpr node_type extract(K&& x);
    constexpr iterator insert(node_type&& nh);
    constexpr iterator insert(const_iterator hint, node_type&& nh);

    constexpr iterator  erase(iterator position)
      requires (!@\libconcept{same_as}@<iterator, const_iterator>);
    constexpr iterator  erase(const_iterator position);
    constexpr size_type erase(const key_type& k);
    template<class K> constexpr size_type erase(K&& x);
    constexpr iterator  erase(const_iterator first, const_iterator last);
    constexpr void      swap(unordered_multiset&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Hash> && is_nothrow_swappable_v<Pred>);
    constexpr void      clear() noexcept;

    template<class H2, class P2>
      constexpr void merge(unordered_multiset<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      constexpr void merge(unordered_multiset<Key, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      constexpr void merge(unordered_set<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      constexpr void merge(unordered_set<Key, H2, P2, Allocator>&& source);

    // observers
    constexpr hasher hash_function() const;
    constexpr key_equal key_eq() const;

    // set operations
    constexpr iterator         find(const key_type& k);
    constexpr const_iterator   find(const key_type& k) const;
    template<class K>
      constexpr iterator       find(const K& k);
    template<class K>
      constexpr const_iterator find(const K& k) const;
    constexpr size_type        count(const key_type& k) const;
    template<class K>
      constexpr size_type      count(const K& k) const;
    constexpr bool             contains(const key_type& k) const;
    template<class K>
      constexpr bool           contains(const K& k) const;
    constexpr pair<iterator, iterator>               equal_range(const key_type& k);
    constexpr pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      constexpr pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      constexpr pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // bucket interface
    constexpr size_type bucket_count() const noexcept;
    constexpr size_type max_bucket_count() const noexcept;
    constexpr size_type bucket_size(size_type n) const;
    constexpr size_type bucket(const key_type& k) const;
    template<class K> constexpr size_type bucket(const K& k) const;
    constexpr local_iterator begin(size_type n);
    constexpr const_local_iterator begin(size_type n) const;
    constexpr local_iterator end(size_type n);
    constexpr const_local_iterator end(size_type n) const;
    constexpr const_local_iterator cbegin(size_type n) const;
    constexpr const_local_iterator cend(size_type n) const;

    // hash policy
    constexpr float load_factor() const noexcept;
    constexpr float max_load_factor() const noexcept;
    constexpr void max_load_factor(float z);
    constexpr void rehash(size_type n);
    constexpr void reserve(size_type n);
  };

  template<class InputIterator,
           class Hash = hash<@\placeholder{iter-value-type}@<InputIterator>>,
           class Pred = equal_to<@\placeholder{iter-value-type}@<InputIterator>>,
           class Allocator = allocator<@\placeholder{iter-value-type}@<InputIterator>>>
    unordered_multiset(InputIterator, InputIterator, typename @\seebelow@::size_type = @\seebelow@,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_multiset<@\placeholder{iter-value-type}@<InputIterator>,
                            Hash, Pred, Allocator>;

  template<ranges::@\libconcept{input_range}@ R,
           class Hash = hash<ranges::range_value_t<R>>,
           class Pred = equal_to<ranges::range_value_t<R>>,
           class Allocator = allocator<ranges::range_value_t<R>>>
    unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_multiset<ranges::range_value_t<R>, Hash, Pred, Allocator>;

  template<class T, class Hash = hash<T>,
           class Pred = equal_to<T>, class Allocator = allocator<T>>
    unordered_multiset(initializer_list<T>, typename @\seebelow@::size_type = @\seebelow@,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_multiset<T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_multiset(InputIterator, InputIterator, typename @\seebelow@::size_type, Allocator)
      -> unordered_multiset<@\placeholder{iter-value-type}@<InputIterator>,
                            hash<@\placeholder{iter-value-type}@<InputIterator>>,
                            equal_to<@\placeholder{iter-value-type}@<InputIterator>>,
                            Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_multiset(InputIterator, InputIterator, typename @\seebelow@::size_type,
                       Hash, Allocator)
      -> unordered_multiset<@\placeholder{iter-value-type}@<InputIterator>, Hash,
                            equal_to<@\placeholder{iter-value-type}@<InputIterator>>,
                            Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Allocator)
      -> unordered_multiset<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>,
                            equal_to<ranges::range_value_t<R>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    unordered_multiset(from_range_t, R&&, Allocator)
      -> unordered_multiset<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>,
                            equal_to<ranges::range_value_t<R>>, Allocator>;

  template<ranges::@\libconcept{input_range}@ R, class Hash, class Allocator>
    unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator)
      -> unordered_multiset<ranges::range_value_t<R>, Hash, equal_to<ranges::range_value_t<R>>,
                            Allocator>;

  template<class T, class Allocator>
    unordered_multiset(initializer_list<T>, typename @\seebelow@::size_type, Allocator)
      -> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>;

  template<class T, class Hash, class Allocator>
    unordered_multiset(initializer_list<T>, typename @\seebelow@::size_type, Hash, Allocator)
      -> unordered_multiset<T, Hash, equal_to<T>, Allocator>;
}
\end{codeblock}

\pnum
A \tcode{size_type} parameter type in an \tcode{unordered_multiset} deduction guide
refers to the \tcode{size_type} member type of
the type deduced by the deduction guide.

\rSec3[unord.multiset.cnstr]{Constructors}

\indexlibraryctor{unordered_multiset}%
\begin{itemdecl}
constexpr unordered_multiset() : unordered_multiset(size_type(@\seebelow@)) { }
constexpr explicit unordered_multiset(size_type n, const hasher& hf = hasher(),
                                      const key_equal& eql = key_equal(),
                                      const allocator_type& a = allocator_type());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{unordered_multiset} using the
specified hash function, key equality predicate, and allocator, and
using at least \tcode{n} buckets.  For the default constructor,
the number of buckets is \impldef{default number of buckets in
\tcode{unordered_multiset}}.
\tcode{max_load_factor()} returns \tcode{1.0}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{unordered_multiset}%
\begin{itemdecl}
template<class InputIterator>
  constexpr unordered_multiset(InputIterator f, InputIterator l,
                               size_type n = @\seebelow@, const hasher& hf = hasher(),
                               const key_equal& eql = key_equal(),
                               const allocator_type& a = allocator_type());
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr unordered_multiset(from_range_t, R&& rg,
                               size_type n = @\seebelow@, const hasher& hf = hasher(),
                               const key_equal& eql = key_equal(),
                               const allocator_type& a = allocator_type());
constexpr unordered_multiset(initializer_list<value_type> il,
                             size_type n = @\seebelow@, const hasher& hf = hasher(),
                             const key_equal& eql = key_equal(),
                             const allocator_type& a = allocator_type());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty \tcode{unordered_multiset} using the
specified hash function, key equality predicate, and allocator, and
using at least \tcode{n} buckets. If \tcode{n} is not
provided, the number of buckets is \impldef{default number of buckets in
\tcode{unordered_multiset}}. Then
inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il},
respectively.
\tcode{max_load_factor()} returns \tcode{1.0}.

\pnum
\complexity
Average case linear, worst case quadratic.
\end{itemdescr}

\rSec3[unord.multiset.erasure]{Erasure}

\indexlibrarymember{erase_if}{unordered_multiset}%
\begin{itemdecl}
template<class K, class H, class P, class A, class Predicate>
  constexpr typename unordered_multiset<K, H, P, A>::size_type
    erase_if(unordered_multiset<K, H, P, A>& c, Predicate pred);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();
\end{codeblock}
\end{itemdescr}

\rSec1[container.adaptors]{Container adaptors}

\rSec2[container.adaptors.general]{General}

\pnum
The headers
\libheaderref{queue},
\libheaderref{stack},
\libheaderrefx{flat_map}{flat.map.syn},
and \libheaderrefx{flat_set}{flat.set.syn}
define the container adaptors
\tcode{queue} and \tcode{priority_queue},
\tcode{stack},
\tcode{flat_map} and \tcode{flat_multimap},
and \tcode{flat_set} and \tcode{flat_multiset},
respectively.

\pnum
Each container adaptor takes
one or more template parameters
named \tcode{Container}, \tcode{KeyContainer}, or \tcode{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 \tcode{C},
the constructor copies the container into the container adaptor.
If \tcode{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 \tcode{Container},
the first template parameter \tcode{T} of the container adaptor
shall denote the same type as \tcode{Container::value_type}.

\pnum
For container adaptors, no \tcode{swap} function throws an exception unless that
exception is thrown by the swap of the adaptor's
\tcode{Container},
\tcode{KeyContainer},
\tcode{MappedContainer}, or
\tcode{Compare} object (if any).

\pnum
A constructor template of a container adaptor
shall not participate in overload resolution
if it has an \tcode{InputIterator} template parameter and
a type that does not qualify as an input iterator is deduced for that parameter.

\pnum
For container adaptors that have them,
the \tcode{insert}, \tcode{emplace}, and \tcode{erase} members
affect the validity of iterators, references, and pointers
to the adaptor's container(s) in the same way that
the containers' respective
\tcode{insert}, \tcode{emplace}, and \tcode{erase} members do.
\begin{example}
A call to \tcode{flat_map<Key, T>::insert}
can invalidate all iterators to the \tcode{flat_map}.
\end{example}

\pnum
A deduction guide for a container adaptor shall not participate in overload resolution if any of the following are true:
\begin{itemize}
\item It has an \tcode{InputIterator} template parameter and a type that does not qualify as an input iterator is deduced for that parameter.
\item It has a \tcode{Compare} template parameter and a type that qualifies as an allocator is deduced for that parameter.
\item It has a \tcode{Container}, \tcode{KeyContainer}, or \tcode{MappedContainer} template parameter and a type that qualifies as an allocator is deduced for that parameter.
\item It has no \tcode{Container}, \tcode{KeyContainer}, or \tcode{MappedContainer} template parameter, and it has an \tcode{Allocator} template parameter, and a type that does not qualify as an allocator is deduced for that parameter.
\item It has both \tcode{Container} and \tcode{Allocator} template parameters, and \tcode{uses_allocator_v<Container, Allocator>} is \tcode{false}.
\item It has both \tcode{KeyContainer} and \tcode{Allocator} template parameters, and
\tcode{uses_allocator_v<KeyContai\-ner, Allocator>} is \tcode{false}.
\item It has both \tcode{KeyContainer} and \tcode{Compare} template parameters, and
\begin{codeblock}
is_invocable_v<const Compare&,
               const typename KeyContainer::value_type&,
               const typename KeyContainer::value_type&>
\end{codeblock}
is not a valid expression or is \tcode{false}.
\item It has both \tcode{MappedContainer} and \tcode{Allocator} template parameters, and
\tcode{uses_allocator_v<Mapped\-Container, Allocator>} is \tcode{false}.
\end{itemize}

\pnum
The exposition-only alias template \exposid{iter-value-type}
defined in \ref{sequences.general} and
the exposition-only alias templates \exposid{iter-key-type}, \exposid{iter-mapped-type},
\exposid{range-key-type}, and \exposid{range-mapped-type}
defined in \ref{associative.general}
may appear in deduction guides for container adaptors.

\pnum
The following exposition-only alias template
may appear in deduction guides for container adaptors:
\begin{codeblock}
template<class Allocator, class T>
  using @\exposid{alloc-rebind}@ = allocator_traits<Allocator>::template rebind_alloc<T>;   // \expos
\end{codeblock}

\rSec2[queue.syn]{Header \tcode{<queue>} synopsis}

\indexheader{queue}
\begin{codeblock}
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{queue}, class template \tcode{queue}
  template<class T, class Container = deque<T>> class queue;

  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, @\libconcept{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)));
  template<class T, class Container, class Alloc>
    struct uses_allocator<queue<T, Container>, Alloc>;

  // \ref{container.adaptors.format}, formatter specialization for \tcode{queue}
  template<class charT, class T, @\libconcept{formattable}@<charT> Container>
    struct formatter<queue<T, Container>, charT>;

  template<class T, class Container>
    constexpr bool enable_nonlocking_formatter_optimization<queue<T, Container>> = false;

  // \ref{priority.queue}, class template \tcode{priority_queue}
  template<class T, class Container = vector<T>,
           class Compare = less<typename Container::value_type>>
    class priority_queue;

  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)));
  template<class T, class Container, class Compare, class Alloc>
    struct uses_allocator<priority_queue<T, Container, Compare>, Alloc>;

  // \ref{container.adaptors.format}, formatter specialization for \tcode{priority_queue}
  template<class charT, class T, @\libconcept{formattable}@<charT> Container, class Compare>
    struct formatter<priority_queue<T, Container, Compare>, charT>;

  template<class T, class Container, class Compare>
    constexpr bool
      enable_nonlocking_formatter_optimization<priority_queue<T, Container, Compare>> = false;
}
\end{codeblock}

\rSec2[queue]{Class template \tcode{queue}}

\rSec3[queue.defn]{Definition}

\pnum
\indexlibraryglobal{queue}%
Any sequence container supporting operations
\tcode{front()},
\tcode{back()},
\tcode{push_back()}
and
\tcode{pop_front()}
can be used to instantiate
\tcode{queue}.
In particular,
\tcode{list}\iref{list}
and
\tcode{deque}\iref{deque}
can be used.

\begin{codeblock}
namespace std {
  template<class T, class Container = deque<T>>
  class queue {
  public:
    using value_type      = Container::value_type;
    using reference       = Container::reference;
    using const_reference = Container::const_reference;
    using size_type       = 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<@\exposconcept{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<@\exposconcept{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<@\exposconcept{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<@\exposid{iter-value-type}@<InputIterator>>;

  template<ranges::@\libconcept{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<@\exposid{iter-value-type}@<InputIterator>, deque<@\exposid{iter-value-type}@<InputIterator>,
               Allocator>>;

  template<ranges::@\libconcept{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 { };
}
\end{codeblock}

\rSec3[queue.cons]{Constructors}

\indexlibraryctor{queue}%
\begin{itemdecl}
constexpr explicit queue(const Container& cont);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{cont}.
\end{itemdescr}

\indexlibraryctor{queue}%
\begin{itemdecl}
constexpr explicit queue(Container&& cont);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{std::move(cont)}.
\end{itemdescr}

\indexlibraryctor{queue}%
\begin{itemdecl}
template<class InputIterator>
  constexpr queue(InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with
\tcode{first} as the first argument and \tcode{last} as the second argument.
\end{itemdescr}

\indexlibraryctor{queue}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr queue(from_range_t, R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{ranges::to<Container>(std::forward<R>(rg))}.
\end{itemdescr}

\rSec3[queue.cons.alloc]{Constructors with allocators}

\pnum
If \tcode{uses_allocator_v<container_type, Alloc>} is \tcode{false}
the constructors in this subclause shall not participate in overload resolution.

\indexlibraryctor{queue}%
\begin{itemdecl}
template<class Alloc> constexpr explicit queue(const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{a}.
\end{itemdescr}

\indexlibraryctor{queue}%
\begin{itemdecl}
template<class Alloc> constexpr queue(const container_type& cont, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a}
as the second argument.
\end{itemdescr}

\indexlibraryctor{queue}%
\begin{itemdecl}
template<class Alloc> constexpr queue(container_type&& cont, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{std::move(cont)} as the first argument and \tcode{a}
as the second argument.
\end{itemdescr}

\indexlibraryctor{queue}%
\begin{itemdecl}
template<class Alloc> constexpr queue(const queue& q, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{q.c} as the first argument and \tcode{a} as the
second argument.
\end{itemdescr}

\indexlibraryctor{queue}%
\begin{itemdecl}
template<class Alloc> constexpr queue(queue&& q, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{std::move(q.c)} as the first argument and \tcode{a}
as the second argument.
\end{itemdescr}

\indexlibraryctor{queue}%
\begin{itemdecl}
template<class InputIterator, class Alloc>
  constexpr queue(InputIterator first, InputIterator last, const Alloc& alloc);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with
\tcode{first} as the first argument,
\tcode{last} as the second argument, and
\tcode{alloc} as the third argument.
\end{itemdescr}

\indexlibraryctor{queue}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R, class Alloc>
  constexpr queue(from_range_t, R&& rg, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with
\tcode{ranges::to<Container>(std::forward<R>(rg), a)}.
\end{itemdescr}

\rSec3[queue.mod]{Modifiers}

\indexlibrarymember{push_range}{queue}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr void push_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{c.append_range(std::forward<R>(rg))}
if that is a valid expression,
otherwise \tcode{ranges::copy(rg, back_inserter(c))}.
\end{itemdescr}

\rSec3[queue.ops]{Operators}

\indexlibrarymember{operator==}{queue}%
\begin{itemdecl}
template<class T, class Container>
  constexpr bool operator==(const queue<T, Container>& x, const queue<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c == y.c}.
\end{itemdescr}

\indexlibrary{\idxcode{operator"!=}!\idxcode{queue}}%
\begin{itemdecl}
template<class T, class Container>
  constexpr bool operator!=(const queue<T, Container>& x,  const queue<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c != y.c}.
\end{itemdescr}

\indexlibrarymember{operator<}{queue}%
\begin{itemdecl}
template<class T, class Container>
  constexpr bool operator< (const queue<T, Container>& x, const queue<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c < y.c}.
\end{itemdescr}

\indexlibrarymember{operator>}{queue}%
\begin{itemdecl}
template<class T, class Container>
  constexpr bool operator> (const queue<T, Container>& x, const queue<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c > y.c}.
\end{itemdescr}

\indexlibrarymember{operator<=}{queue}%
\begin{itemdecl}
template<class T, class Container>
  constexpr bool operator<=(const queue<T, Container>& x, const queue<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c <= y.c}.
\end{itemdescr}

\indexlibrarymember{operator>=}{queue}%
\begin{itemdecl}
template<class T, class Container>
  constexpr bool operator>=(const queue<T, Container>& x, const queue<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c >= y.c}.
\end{itemdescr}

\indexlibrarymember{operator<=>}{queue}%
\begin{itemdecl}
template<class T, @\libconcept{three_way_comparable}@ Container>
  constexpr compare_three_way_result_t<Container>
    operator<=>(const queue<T, Container>& x, const queue<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c <=> y.c}.
\end{itemdescr}

\rSec3[queue.special]{Specialized algorithms}

\indexlibrarymember{swap}{queue}%
\begin{itemdecl}
template<class T, class Container>
  constexpr void swap(queue<T, Container>& x, queue<T, Container>& y)
    noexcept(noexcept(x.swap(y)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_swappable_v<Container>} is \tcode{true}.

\pnum
\effects
As if by \tcode{x.swap(y)}.
\end{itemdescr}

\rSec2[priority.queue]{Class template \tcode{priority_queue}}

\rSec3[priqueue.overview]{Overview}

\pnum
\indexlibraryglobal{priority_queue}%
Any sequence container with random access iterator and supporting operations
\tcode{front()},
\tcode{push_back()}
and
\tcode{pop_back()}
can be used to instantiate
\tcode{priority_queue}.
In particular,
\tcode{vector}\iref{vector}
and
\tcode{deque}\iref{deque}
can be used.
Instantiating
\tcode{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\iref{alg.sorting}.

\begin{codeblock}
namespace std {
  template<class T, class Container = vector<T>,
           class Compare = less<typename Container::value_type>>
  class priority_queue {
  public:
    using value_type      = Container::value_type;
    using reference       = Container::reference;
    using const_reference = Container::const_reference;
    using size_type       = 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<@\exposconcept{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<@\exposconcept{container-compatible-range}@<T> R, class Alloc>
      constexpr priority_queue(from_range_t, R&& rg, const Compare&, const Alloc&);
    template<@\exposconcept{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<@\exposconcept{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<@\exposid{iter-value-type}@<InputIterator>>,
           class Container = vector<@\exposid{iter-value-type}@<InputIterator>>>
    priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container())
      -> priority_queue<@\exposid{iter-value-type}@<InputIterator>, Container, Compare>;

  template<ranges::@\libconcept{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<@\exposid{iter-value-type}@<InputIterator>,
                        vector<@\exposid{iter-value-type}@<InputIterator>, Allocator>,
                        less<@\exposid{iter-value-type}@<InputIterator>>>;

  template<class InputIterator, class Compare, class Allocator>
    priority_queue(InputIterator, InputIterator, Compare, Allocator)
      -> priority_queue<@\exposid{iter-value-type}@<InputIterator>,
                        vector<@\exposid{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::@\libconcept{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::@\libconcept{input_range}@ R, class Allocator>
    priority_queue(from_range_t, R&&, Allocator)
      -> priority_queue<ranges::range_value_t<R>, vector<ranges::range_value_t<R>, Allocator>>;

  // no equality is provided

  template<class T, class Container, class Compare, class Alloc>
    struct uses_allocator<priority_queue<T, Container, Compare>, Alloc>
      : uses_allocator<Container, Alloc>::type { };
}
\end{codeblock}

\rSec3[priqueue.cons]{Constructors}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
constexpr priority_queue(const Compare& x, const Container& y);
constexpr priority_queue(const Compare& x, Container&& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{x} defines a strict weak ordering\iref{alg.sorting}.

\pnum
\effects
Initializes
\tcode{comp} with
\tcode{x} and
\tcode{c} with
\tcode{y} (copy constructing or move constructing as appropriate);
calls
\tcode{make_heap(c.begin(), c.end(), comp)}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<class InputIterator>
  constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{x} defines a strict weak ordering\iref{alg.sorting}.

\pnum
\effects
Initializes \tcode{c} with
\tcode{first} as the first argument and
\tcode{last} as the second argument, and
initializes \tcode{comp} with \tcode{x};
then calls \tcode{make_heap(c.begin(), c.end(), comp)}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{x} defines a strict weak ordering\iref{alg.sorting}.

\pnum
\effects
Initializes
\tcode{comp} with
\tcode{x} and
\tcode{c} with
\tcode{y} (copy constructing or move constructing as appropriate);
calls
\tcode{c.insert(c.end(), first, last)};
and finally calls
\tcode{make_heap(c.begin(), c.end(), comp)}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr priority_queue(from_range_t, R&& rg, const Compare& x = Compare());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{x} defines a strict weak ordering\iref{alg.sorting}.

\pnum
\effects
Initializes \tcode{comp} with \tcode{x} and
\tcode{c} with \tcode{ranges::to<Container>(std::forward<R>(rg))} and
finally calls \tcode{make_heap(c.begin(), c.end(), comp)}.
\end{itemdescr}

\rSec3[priqueue.cons.alloc]{Constructors with allocators}

\pnum
If \tcode{uses_allocator_v<container_type, Alloc>} is \tcode{false}
the constructors in this subclause shall not participate in overload resolution.

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<class Alloc> constexpr explicit priority_queue(const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{a} and value-initializes \tcode{comp}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<class Alloc> constexpr priority_queue(const Compare& compare, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{a} and initializes \tcode{comp} with \tcode{compare}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<class Alloc>
  constexpr priority_queue(const Compare& compare, const Container& cont, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a} as the second
argument, and initializes \tcode{comp} with \tcode{compare};
calls \tcode{make_heap(c.begin(), c.end(), comp)}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<class Alloc>
  constexpr priority_queue(const Compare& compare, Container&& cont, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{std::move(cont)} as the first argument and \tcode{a}
as the second argument, and initializes \tcode{comp} with \tcode{compare};
calls \tcode{make_heap(c.begin(), c.end(), comp)}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<class Alloc> constexpr priority_queue(const priority_queue& q, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{q.c} as the first argument and \tcode{a} as
the second argument, and initializes \tcode{comp} with \tcode{q.comp}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<class Alloc> constexpr priority_queue(priority_queue&& q, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{std::move(q.c)} as the first argument and \tcode{a}
as the second argument, and initializes \tcode{comp} with \tcode{std::move(q.comp)}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<class InputIterator, class Alloc>
  constexpr priority_queue(InputIterator first, InputIterator last, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with
\tcode{first} as the first argument,
\tcode{last} as the second argument, and
\tcode{a} as the third argument, and
value-initializes \tcode{comp};
calls \tcode{make_heap(c.begin(), c.end(), comp)}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<class InputIterator, class Alloc>
  constexpr priority_queue(InputIterator first, InputIterator last,
                           const Compare& compare, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with
\tcode{first} as the first argument,
\tcode{last} as the second argument, and
\tcode{a} as the third argument, and
initializes \tcode{comp} with \tcode{compare};
calls \tcode{make_heap(c.begin(), c.end(), comp)}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<class InputIterator, class Alloc>
  constexpr priority_queue(InputIterator first, InputIterator last, const Compare& compare,
                           const Container& cont, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with
\tcode{cont} as the first argument and \tcode{a} as the second argument, and
initializes \tcode{comp} with \tcode{compare};
calls \tcode{c.insert(c.end(), first, last)}; and
finally calls \tcode{make_heap(c.begin(), c.end(), comp)}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<class InputIterator, class Alloc>
  constexpr priority_queue(InputIterator first, InputIterator last, const Compare& compare,
                           Container&& cont, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with
\tcode{std::move(cont)} as the first argument and
\tcode{a} as the second argument, and
initializes \tcode{comp} with \tcode{compare};
calls \tcode{c.insert(c.end(), first, last)}; and
finally calls \tcode{make_heap(c.begin(), c.end(), comp)}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R, class Alloc>
  constexpr priority_queue(from_range_t, R&& rg, const Compare& compare, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{comp} with \tcode{compare} and
\tcode{c} with \tcode{ranges::to<Container>(std::forward<R>(rg), a)};
calls \tcode{make_heap(c.begin(), c.end(), comp)}.
\end{itemdescr}

\indexlibraryctor{priority_queue}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R, class Alloc>
  constexpr priority_queue(from_range_t, R&& rg, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes
\tcode{c} with \tcode{ranges::to<Container>(std::forward<R>(rg), a)}
and value-initializes \tcode{comp};
calls \tcode{make_heap(c.begin(), c.end(), comp)}.
\end{itemdescr}

\rSec3[priqueue.members]{Members}

\indexlibrarymember{push}{priority_queue}%
\begin{itemdecl}
constexpr void push(const value_type& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
As if by:
\begin{codeblock}
c.push_back(x);
push_heap(c.begin(), c.end(), comp);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{push}{priority_queue}%
\begin{itemdecl}
constexpr void push(value_type&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
As if by:
\begin{codeblock}
c.push_back(std::move(x));
push_heap(c.begin(), c.end(), comp);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{push_range}{priority_queue}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr void push_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Inserts all elements of \tcode{rg} in \tcode{c} via
\tcode{c.append_range(std::forward<R>(rg))} if that is a valid expression, or
\tcode{ranges::copy(rg, back_inserter(c))} otherwise.
Then restores the heap property as if by
\tcode{make_heap(c.begin(), c.end(), comp)}.

\pnum
\ensures
\tcode{is_heap(c.begin(), c.end(), comp)} is \tcode{true}.
\end{itemdescr}

\indexlibrarymember{emplace}{priority_queue}%
\begin{itemdecl}
template<class... Args> constexpr void emplace(Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
As if by:
\begin{codeblock}
c.emplace_back(std::forward<Args>(args)...);
push_heap(c.begin(), c.end(), comp);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{pop}{priority_queue}%
\begin{itemdecl}
constexpr void pop();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
As if by:
\begin{codeblock}
pop_heap(c.begin(), c.end(), comp);
c.pop_back();
\end{codeblock}
\end{itemdescr}

\rSec3[priqueue.special]{Specialized algorithms}

\indexlibrarymember{swap}{priority_queue}%
\begin{itemdecl}
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)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_swappable_v<Container>} is \tcode{true} and
\tcode{is_swappable_v<Compare>} is \tcode{true}.

\pnum
\effects
As if by \tcode{x.swap(y)}.
\end{itemdescr}

\rSec2[stack.syn]{Header \tcode{<stack>} synopsis}

\indexheader{stack}%
\begin{codeblock}
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{stack}, class template \tcode{stack}
  template<class T, class Container = deque<T>> class stack;

  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, @\libconcept{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)));
  template<class T, class Container, class Alloc>
    struct uses_allocator<stack<T, Container>, Alloc>;

  // \ref{container.adaptors.format}, formatter specialization for \tcode{stack}
  template<class charT, class T, @\libconcept{formattable}@<charT> Container>
    struct formatter<stack<T, Container>, charT>;

  template<class T, class Container>
    constexpr bool enable_nonlocking_formatter_optimization<stack<T, Container>> = false;
}
\end{codeblock}

\rSec2[stack]{Class template \tcode{stack}}

\rSec3[stack.general]{General}

\pnum
\indexlibraryglobal{stack}%
Any sequence container supporting operations
\tcode{back()},
\tcode{push_back()}
and
\tcode{pop_back()}
can be used to instantiate
\tcode{stack}.
In particular,
\tcode{vector}\iref{vector},
\tcode{list}\iref{list}
and
\tcode{deque}\iref{deque}
can be used.

\rSec3[stack.defn]{Definition}

\begin{codeblock}
namespace std {
  template<class T, class Container = deque<T>>
  class stack {
  public:
    using value_type      = Container::value_type;
    using reference       = Container::reference;
    using const_reference = Container::const_reference;
    using size_type       = 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<@\exposconcept{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<@\exposconcept{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<@\exposconcept{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<@\exposid{iter-value-type}@<InputIterator>>;

  template<ranges::@\libconcept{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<@\exposid{iter-value-type}@<InputIterator>, deque<@\exposid{iter-value-type}@<InputIterator>,
               Allocator>>;

  template<ranges::@\libconcept{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 { };
}
\end{codeblock}

\rSec3[stack.cons]{Constructors}

\indexlibraryctor{stack}%
\begin{itemdecl}
constexpr explicit stack(const Container& cont);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{cont}.
\end{itemdescr}

\indexlibraryctor{stack}%
\begin{itemdecl}
constexpr explicit stack(Container&& cont);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{std::move(cont)}.
\end{itemdescr}

\indexlibraryctor{stack}%
\begin{itemdecl}
template<class InputIterator>
  constexpr stack(InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with
\tcode{first} as the first argument and \tcode{last} as the second argument.
\end{itemdescr}

\indexlibraryctor{stack}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr stack(from_range_t, R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{ranges::to<Container>(std::forward<R>(rg))}.
\end{itemdescr}

\rSec3[stack.cons.alloc]{Constructors with allocators}

\pnum
If \tcode{uses_allocator_v<container_type, Alloc>} is \tcode{false}
the constructors in this subclause shall not participate in overload resolution.

\indexlibraryctor{stack}%
\begin{itemdecl}
template<class Alloc> constexpr explicit stack(const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{a}.
\end{itemdescr}

\indexlibraryctor{stack}%
\begin{itemdecl}
template<class Alloc> constexpr stack(const container_type& cont, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a} as the
second argument.
\end{itemdescr}

\indexlibraryctor{stack}%
\begin{itemdecl}
template<class Alloc> constexpr stack(container_type&& cont, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{std::move(cont)} as the first argument and \tcode{a}
as the second argument.
\end{itemdescr}

\indexlibraryctor{stack}%
\begin{itemdecl}
template<class Alloc> constexpr stack(const stack& s, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{s.c} as the first argument and \tcode{a}
as the second argument.
\end{itemdescr}

\indexlibraryctor{stack}%
\begin{itemdecl}
template<class Alloc> constexpr stack(stack&& s, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{std::move(s.c)} as the first argument and \tcode{a}
as the second argument.
\end{itemdescr}

\indexlibraryctor{stack}%
\begin{itemdecl}
template<class InputIterator, class Alloc>
  constexpr stack(InputIterator first, InputIterator last, const Alloc& alloc);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with
\tcode{first} as the first argument,
\tcode{last} as the second argument, and
\tcode{alloc} as the third argument.
\end{itemdescr}

\indexlibraryctor{stack}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R, class Alloc>
  constexpr stack(from_range_t, R&& rg, const Alloc& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes
\tcode{c} with \tcode{ranges::to<Container>(std::forward<R>(rg), a)}.
\end{itemdescr}

\rSec3[stack.mod]{Modifiers}

\indexlibrarymember{push_range}{stack}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<T> R>
  constexpr void push_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{c.append_range(std::forward<R>(rg))}
if that is a valid expression,
otherwise \tcode{ranges::copy(rg, back_inserter(c))}.
\end{itemdescr}

\rSec3[stack.ops]{Operators}

\indexlibrarymember{operator==}{stack}%
\begin{itemdecl}
template<class T, class Container>
  constexpr bool operator==(const stack<T, Container>& x, const stack<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c == y.c}.
\end{itemdescr}

\indexlibrary{\idxcode{operator"!=}!\idxcode{stack}}%
\begin{itemdecl}
template<class T, class Container>
  constexpr bool operator!=(const stack<T, Container>& x, const stack<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c != y.c}.
\end{itemdescr}

\indexlibrarymember{operator<}{stack}%
\begin{itemdecl}
template<class T, class Container>
  constexpr bool operator< (const stack<T, Container>& x, const stack<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c < y.c}.
\end{itemdescr}

\indexlibrarymember{operator>}{stack}%
\begin{itemdecl}
template<class T, class Container>
  constexpr bool operator> (const stack<T, Container>& x, const stack<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c > y.c}.
\end{itemdescr}

\indexlibrarymember{operator<=}{stack}%
\begin{itemdecl}
template<class T, class Container>
  constexpr bool operator<=(const stack<T, Container>& x, const stack<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c <= y.c}.
\end{itemdescr}

\indexlibrarymember{operator>=}{stack}%
\begin{itemdecl}
template<class T, class Container>
  constexpr bool operator>=(const stack<T, Container>& x, const stack<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c >= y.c}.
\end{itemdescr}

\indexlibrarymember{operator<=>}{stack}%
\begin{itemdecl}
template<class T, @\libconcept{three_way_comparable}@ Container>
  constexpr compare_three_way_result_t<Container>
    operator<=>(const stack<T, Container>& x, const stack<T, Container>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.c <=> y.c}.
\end{itemdescr}

\rSec3[stack.special]{Specialized algorithms}

\indexlibrarymember{swap}{stack}%
\begin{itemdecl}
template<class T, class Container>
  constexpr void swap(stack<T, Container>& x, stack<T, Container>& y)
    noexcept(noexcept(x.swap(y)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_swappable_v<Container>} is \tcode{true}.

\pnum
\effects
As if by \tcode{x.swap(y)}.
\end{itemdescr}

\rSec2[flat.map.syn]{Header \tcode{<flat_map>} synopsis}

\indexheader{flat_map}%
\begin{codeblock}
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{flat.map}, class template \tcode{flat_map}
  template<class Key, class T, class Compare = less<Key>,
           class KeyContainer = vector<Key>, class MappedContainer = vector<T>>
    class flat_map;

  struct sorted_unique_t { explicit sorted_unique_t() = default; };
  inline constexpr sorted_unique_t sorted_unique{};

  template<class Key, class T, class Compare, class KeyContainer, class MappedContainer,
           class Allocator>
    struct uses_allocator<flat_map<Key, T, Compare, KeyContainer, MappedContainer>,
                          Allocator>;

  // \ref{flat.map.erasure}, erasure for \tcode{flat_map}
  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);

  // \ref{flat.multimap}, class template \tcode{flat_multimap}
  template<class Key, class T, class Compare = less<Key>,
           class KeyContainer = vector<Key>, class MappedContainer = vector<T>>
    class flat_multimap;

  struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; };
  inline constexpr sorted_equivalent_t sorted_equivalent{};

  template<class Key, class T, class Compare, class KeyContainer, class MappedContainer,
           class Allocator>
    struct uses_allocator<flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>,
                          Allocator>;

  // \ref{flat.multimap.erasure}, erasure for \tcode{flat_multimap}
  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);
}
\end{codeblock}

\rSec2[flat.map]{Class template \tcode{flat_map}}

\rSec3[flat.map.overview]{Overview}

\pnum
\indexlibraryglobal{flat_map}%
A \tcode{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 \tcode{T}
based on the keys.
\tcode{flat_map} supports iterators
that meet the \oldconcept{InputIterator} requirements and
model the
\libconcept{random_access_iterator} concept\iref{iterator.concept.random.access}.

\pnum
A \tcode{flat_map} meets all of the requirements
of a container\iref{container.reqmts} and
of a reversible container\iref{container.rev.reqmts},
plus the optional container requirements\iref{container.opt.reqmts}.
\tcode{flat_map} meets the requirements of
an associative container\iref{associative.reqmts},
except that:
\begin{itemize}
\item
it does not meet the requirements related to node handles\iref{container.node},
\item
it does not meet the requirements related to iterator invalidation, and
\item
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.
\end{itemize}
\begin{note}
A \tcode{flat_map} does not meet the additional requirements of
an allocator-aware container\iref{container.alloc.reqmts}.
\end{note}

\pnum
A \tcode{flat_map} also provides most operations
described in \ref{associative.reqmts} for unique keys.
This means that a \tcode{flat_map} supports
the \tcode{a_uniq} operations in \ref{associative.reqmts}
but not the \tcode{a_eq} operations.
For a \tcode{flat_map<Key, T>}
the \tcode{key_type} is \tcode{Key} and
the \tcode{value_type} is \tcode{pair<Key, T>}.

\pnum
Descriptions are provided here only for operations on \tcode{flat_map} that
are not described in one of those sets of requirements or for operations where
there is additional semantic information.

\pnum
A \tcode{flat_map} maintains the following invariants:
\begin{itemize}
\item
it contains the same number of keys and values;
\item
the keys are sorted with respect to the comparison object; and
\item
the value at offset \tcode{off} within the value container is
the value associated with the key at offset \tcode{off}
within the key container.
\end{itemize}

\pnum
If any member function in \ref{flat.map.defn} exits via an exception
the invariants of the object argument are restored.
For the move constructor and move assignment operator,
the invariants of both arguments are restored.
\begin{note}
This can result in the \tcode{flat_map} being emptied.
\end{note}

\pnum
Any type \tcode{C}
that meets the sequence container requirements\iref{sequence.reqmts}
can be used to instantiate \tcode{flat_map},
as long as
\tcode{C::iterator} meets the \oldconcept{RandomAccessIterator} requirements and
invocations of
member functions \tcode{C::size} and \tcode{C::max_size} do not exit via an exception.
In particular, \tcode{vector}\iref{vector} and \tcode{deque}\iref{deque}
can be used.
\begin{note}
\tcode{vector<bool>} is not a sequence container.
\end{note}

\pnum
The program is ill-formed if
\tcode{Key} is not the same type as \tcode{KeyContainer::value_type} or
\tcode{T} is not the same type as \tcode{MappedContainer::value_type}.

\pnum
The effect of calling a constructor
that takes
both \tcode{key_container_type} and \tcode{mapped_container_type} arguments with
containers of different sizes is undefined.

\pnum
The effect of calling a member function
that takes a \tcode{sorted_unique_t} argument with
a container, containers, or range
that is not sorted with respect to \tcode{key_comp()}, or
that contains equal elements,
is undefined.

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\rSec3[flat.map.defn]{Definition}

\begin{codeblock}
namespace std {
  template<class Key, class T, class Compare = less<Key>,
           class KeyContainer = vector<Key>, class MappedContainer = vector<T>>
  class flat_map {
  public:
    // types
    using key_type               = Key;
    using mapped_type            = T;
    using value_type             = pair<key_type, mapped_type>;
    using key_compare            = Compare;
    using reference              = pair<const key_type&, mapped_type&>;
    using const_reference        = pair<const key_type&, const mapped_type&>;
    using size_type              = size_t;
    using difference_type        = ptrdiff_t;
    using iterator               = @\impdefx{type of \tcode{flat_map::iterator}}@; // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{flat_map::const_iterator}}@; // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using key_container_type     = KeyContainer;
    using mapped_container_type  = MappedContainer;

    class value_compare {
    private:
      key_compare @\exposid{comp}@;                                         // \expos
      constexpr value_compare(key_compare c) : @\exposid{comp}@(c) { }      // \expos

    public:
      constexpr bool operator()(const_reference x, const_reference y) const {
        return @\exposid{comp}@(x.first, y.first);
      }
    };

    struct containers {
      key_container_type keys;
      mapped_container_type values;
    };

    // \ref{flat.map.cons}, constructors
    constexpr flat_map() : flat_map(key_compare()) { }

    constexpr flat_map(const flat_map&);
    constexpr flat_map(flat_map&&);
    constexpr flat_map& operator=(const flat_map&);
    constexpr flat_map& operator=(flat_map&&);

    constexpr explicit flat_map(const key_compare& comp)
      : @\exposid{c}@(), @\exposid{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())
        : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(first, last); }

    template<class InputIterator>
      constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last,
                         const key_compare& comp = key_compare())
        : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(sorted_unique, first, last); }

    template<@\exposconcept{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<@\exposconcept{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) { }

    // \ref{flat.map.cons.alloc}, constructors with allocators

    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<@\exposconcept{container-compatible-range}@<value_type> R, class Alloc>
      constexpr flat_map(from_range_t, R&& rg, const Alloc& a);
    template<@\exposconcept{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>);

    // iterators
    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;

    // \ref{flat.map.capacity}, capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // \ref{flat.map.access}, element access
    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;

    // \ref{flat.map.modifiers}, modifiers
    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<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(R&& rg);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(sorted_unique_t, 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(@\seebelow@);
    constexpr void clear() noexcept;

    // observers
    constexpr key_compare key_comp() const;
    constexpr value_compare value_comp() const;

    constexpr const key_container_type& keys() const noexcept      { return @\exposid{c}@.keys; }
    constexpr const mapped_container_type& values() const noexcept { return @\exposid{c}@.values; }

    // map operations
    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 @\exposid{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(noexcept(x.swap(y)))
      { x.swap(y); }

  private:
    containers @\exposid{c}@;               // \expos
    key_compare @\exposid{compare}@;        // \expos

    struct @\exposid{key-equiv}@ {  // \expos
      constexpr @\exposid{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<@\exposid{iter-key-type}@<InputIterator>>>
    flat_map(InputIterator, InputIterator, Compare = Compare())
      -> flat_map<@\exposid{iter-key-type}@<InputIterator>, @\exposid{iter-mapped-type}@<InputIterator>, Compare>;

  template<class InputIterator, class Compare = less<@\exposid{iter-key-type}@<InputIterator>>>
    flat_map(sorted_unique_t, InputIterator, InputIterator, Compare = Compare())
      -> flat_map<@\exposid{iter-key-type}@<InputIterator>, @\exposid{iter-mapped-type}@<InputIterator>, Compare>;

  template<ranges::@\libconcept{input_range}@ R, class Compare = less<@\exposid{range-key-type}@<R>>,
           class Allocator = allocator<byte>>
    flat_map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())
      -> flat_map<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, Compare,
                  vector<@\exposid{range-key-type}@<R>, @\exposid{alloc-rebind}@<Allocator, @\exposid{range-key-type}@<R>>>,
                  vector<@\exposid{range-mapped-type}@<R>, @\exposid{alloc-rebind}@<Allocator, @\exposid{range-mapped-type}@<R>>>>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    flat_map(from_range_t, R&&, Allocator)
      -> flat_map<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, less<@\exposid{range-key-type}@<R>>,
                  vector<@\exposid{range-key-type}@<R>, @\exposid{alloc-rebind}@<Allocator, @\exposid{range-key-type}@<R>>>,
                  vector<@\exposid{range-mapped-type}@<R>, @\exposid{alloc-rebind}@<Allocator, @\exposid{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>> { };
}
\end{codeblock}

\pnum
The member type \tcode{containers} has the data members and special members
specified above.
It has no base classes or members other than those specified.

\rSec3[flat.map.cons]{Constructors}

\indexlibraryctor{flat_map}%
\begin{itemdecl}
constexpr flat_map(key_container_type key_cont, mapped_container_type mapped_cont,
                   const key_compare& comp = key_compare());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes
\tcode{\exposid{c}.keys} with \tcode{std::move(key_cont)},
\tcode{\exposid{c}.values} with \tcode{std::move(mapped_cont)}, and
\exposid{compare} with \tcode{comp};
sorts the range \range{begin()}{end()} with respect to \tcode{value_comp()}; and
finally erases the duplicate elements as if by:
\begin{codeblock}
auto zv = views::zip(@\exposid{c}@.keys, @\exposid{c}@.values);
auto it = ranges::unique(zv, @\exposid{key-equiv}@(@\exposid{compare}@)).begin();
auto dist = distance(zv.begin(), it);
@\exposid{c}@.keys.erase(@\exposid{c}@.keys.begin() + dist, @\exposid{c}@.keys.end());
@\exposid{c}@.values.erase(@\exposid{c}@.values.begin() + dist, @\exposid{c}@.values.end());
\end{codeblock}

\pnum
\complexity
Linear in $N$ if the container arguments are already sorted
with respect to \tcode{value_comp()} and otherwise $N \log N$,
where $N$ is the value of \tcode{key_cont.size()} before this call.
\end{itemdescr}

\indexlibraryctor{flat_map}%
\begin{itemdecl}
constexpr flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont,
                   const key_compare& comp = key_compare());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes
\tcode{\exposid{c}.keys} with \tcode{std::move(key_cont)},
\tcode{\exposid{c}.values} with \tcode{std::move(mapped_cont)}, and
\exposid{compare} with \tcode{comp}.

\pnum
\complexity
Constant.
\end{itemdescr}

\rSec3[flat.map.cons.alloc]{Constructors with allocators}

\pnum
The constructors in this subclause shall not participate in overload resolution
unless \tcode{uses_allocator_v<key_container_type, Alloc>} is \tcode{true}
and \tcode{uses_allocator_v<mapped_container_type, Alloc>} is \tcode{true}.

\indexlibraryctor{flat_map}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{flat_map(key_cont, mapped_cont)} and
\tcode{flat_map(key_cont, mapped_cont, comp)}, respectively,
except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed with
uses-allocator construction\iref{allocator.uses.construction}.

\pnum
\complexity
Same as \tcode{flat_map(key_cont, mapped_cont)} and
\tcode{flat_map(key_cont, mapped_cont, comp)}, respectively.
\end{itemdescr}

\indexlibraryctor{flat_map}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{flat_map(sorted_unique, key_cont, mapped_cont)} and
\tcode{flat_map(sorted_unique, key_cont, mapped_cont, comp)}, respectively,
except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed
with uses-allocator construction\iref{allocator.uses.construction}.

\pnum
\complexity
Linear.
\end{itemdescr}

\indexlibraryctor{flat_map}%
\begin{itemdecl}
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<@\exposconcept{container-compatible-range}@<value_type> R, class Alloc>
  constexpr flat_map(from_range_t, R&& rg, const Alloc& a);
template<@\exposconcept{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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to the corresponding non-allocator constructors
except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed
with uses-allocator construction\iref{allocator.uses.construction}.
\end{itemdescr}

\rSec3[flat.map.capacity]{Capacity}

\indexlibrarymember{size}{flat_map}%
\begin{itemdecl}
constexpr size_type size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{c}.keys.size()}.
\end{itemdescr}

\indexlibrarymember{max_size}{flat_map}%
\begin{itemdecl}
constexpr size_type max_size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{min<size_type>(\exposid{c}.keys.max_size(), \exposid{c}.values.max_size())}.
\end{itemdescr}

\rSec3[flat.map.access]{Access}

\indexlibrarymember{operator[]}{flat_map}%
\begin{itemdecl}
constexpr mapped_type& operator[](const key_type& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return try_emplace(x).first->second;}
\end{itemdescr}

\indexlibrarymember{operator[]}{flat_map}%
\begin{itemdecl}
constexpr mapped_type& operator[](key_type&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return try_emplace(std::move(x)).first->second;}
\end{itemdescr}

\indexlibrarymember{operator[]}{flat_map}%
\begin{itemdecl}
template<class K> constexpr mapped_type& operator[](K&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The \grammarterm{qualified-id} \tcode{Compare::is_transparent} is valid and
denotes a type.

\pnum
\effects
Equivalent to: \tcode{return try_emplace(std::forward<K>(x)).first->second;}
\end{itemdescr}

\indexlibrarymember{at}{flat_map}%
\begin{itemdecl}
constexpr mapped_type&       at(const key_type& x);
constexpr const mapped_type& at(const key_type& x) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A reference to the \tcode{mapped_type} corresponding
to \tcode{x} in \tcode{*this}.

\pnum
\throws
An exception object of type \tcode{out_of_range} if
no such element is present.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\indexlibrarymember{at}{flat_map}%
\begin{itemdecl}
template<class K> constexpr mapped_type&       at(const K& x);
template<class K> constexpr const mapped_type& at(const K& x) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The \grammarterm{qualified-id} \tcode{Compare::is_transparent}
is valid and denotes a type.

\pnum
\expects
The expression \tcode{find(x)} is well-formed and has well-defined behavior.

\pnum
\returns
A reference to the \tcode{mapped_type} corresponding to
\tcode{x} in \tcode{*this}.

\pnum
\throws
An exception object of type \tcode{out_of_range}
if no such element is present.

\pnum
\complexity
Logarithmic.
\end{itemdescr}

\rSec3[flat.map.modifiers]{Modifiers}

\indexlibrarymember{emplace}{flat_map}%
\begin{itemdecl}
template<class... Args> constexpr pair<iterator, bool> emplace(Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<pair<key_type, mapped_type>, Args...>} is \tcode{true}.

\pnum
\effects
Initializes an object \tcode{t} of type \tcode{pair<key_type, mapped_type>}
with \tcode{std::forward<Args>(\linebreak args)...};
if the map already contains an element
whose key is equivalent to \tcode{t.first},
\tcode{*this} is unchanged.
Otherwise, equivalent to:
\begin{codeblock}
auto key_it = ranges::upper_bound(@\exposid{c}@.keys, t.first, @\exposid{compare}@);
auto value_it = @\exposid{c}@.values.begin() + distance(@\exposid{c}@.keys.begin(), key_it);
@\exposid{c}@.keys.insert(key_it, std::move(t.first));
@\exposid{c}@.values.insert(value_it, std::move(t.second));
\end{codeblock}

\pnum
\returns
The \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place, and
the iterator component of the pair points to
the element with key equivalent to \tcode{t.first}.
\end{itemdescr}

\indexlibrarymember{insert}{flat_map}%
\begin{itemdecl}
template<class P> constexpr pair<iterator, bool> insert(P&& x);
template<class P> constexpr iterator insert(const_iterator position, P&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<pair<key_type, mapped_type>, P>} is \tcode{true}.

\pnum
\effects
The first form is equivalent to \tcode{return emplace(std::forward<P>(x));}.
The second form is equivalent to
\tcode{return emplace_hint(position, std::forward<P>(x));}.
\end{itemdescr}

\indexlibrarymember{insert}{flat_map}%
\begin{itemdecl}
template<class InputIterator>
  constexpr void insert(InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Adds elements to \exposid{c} as if by:
\begin{codeblock}
for (; first != last; ++first) {
  value_type value = *first;
  @\exposid{c}@.keys.insert(@\exposid{c}@.keys.end(), std::move(value.first));
  @\exposid{c}@.values.insert(@\exposid{c}@.values.end(), std::move(value.second));
}
\end{codeblock}
Then, sorts the range of newly inserted elements
with respect to \tcode{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:
\begin{codeblock}
auto zv = views::zip(@\exposid{c}@.keys, @\exposid{c}@.values);
auto it = ranges::unique(zv, @\exposid{key-equiv}@(@\exposid{compare}@)).begin();
auto dist = distance(zv.begin(), it);
@\exposid{c}@.keys.erase(@\exposid{c}@.keys.begin() + dist, @\exposid{c}@.keys.end());
@\exposid{c}@.values.erase(@\exposid{c}@.values.begin() + dist, @\exposid{c}@.values.end());
\end{codeblock}

\pnum
\complexity
$N$ + $M \log M$,
where $N$ is \tcode{size()} before the operation and
$M$ is \tcode{distance(first, last)}.

\pnum
\remarks
Since this operation performs an in-place merge, it may allocate memory.
\end{itemdescr}

\indexlibrarymember{insert}{flat_map}%
\begin{itemdecl}
template<class InputIterator>
  constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{insert(first, last)}.

\pnum
\complexity
Linear in $N$, where $N$ is \tcode{size()} after the operation.
\end{itemdescr}

\indexlibrarymember{insert_range}{flat_map}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr void insert_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Adds elements to \exposid{c} as if by:
\begin{codeblock}
ranges::for_each(rg, [&](value_type e) {
  @\exposid{c}@.keys.insert(@\exposid{c}@.keys.end(), std::move(e.first));
  @\exposid{c}@.values.insert(@\exposid{c}@.values.end(), std::move(e.second));
});
\end{codeblock}
Then, sorts the range of newly inserted elements
with respect to \tcode{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:
\begin{codeblock}
auto zv = views::zip(@\exposid{c}@.keys, @\exposid{c}@.values);
auto it = ranges::unique(zv, @\exposid{key-equiv}@(@\exposid{compare}@)).begin();
auto dist = distance(zv.begin(), it);
@\exposid{c}@.keys.erase(@\exposid{c}@.keys.begin() + dist, @\exposid{c}@.keys.end());
@\exposid{c}@.values.erase(@\exposid{c}@.values.begin() + dist, @\exposid{c}@.values.end());
\end{codeblock}

\pnum
\complexity
$N$ + $M \log M$,
where $N$ is \tcode{size()} before the operation and
$M$ is \tcode{ranges::distance(rg)}.

\pnum
\remarks
Since this operation performs an in-place merge, it may allocate memory.
\end{itemdescr}

\indexlibrarymember{insert_range}{flat_map}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr void insert_range(sorted_unique_t, R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{insert_range(rg)}.

\pnum
\complexity
Linear in $N$, where $N$ is \tcode{size()} after the operation.
\end{itemdescr}

\indexlibrarymember{try_emplace}{flat_map}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<mapped_type, Args...>} is \tcode{true}.

\pnum
\effects
If the map already contains an element whose key is equivalent to \tcode{k},
\tcode{*this} and \tcode{args...} are unchanged.
Otherwise equivalent to:
\begin{codeblock}
auto key_it = ranges::upper_bound(@\exposid{c}@.keys, k, @\exposid{compare}@);
auto value_it = @\exposid{c}@.values.begin() + distance(@\exposid{c}@.keys.begin(), key_it);
@\exposid{c}@.keys.insert(key_it, std::forward<decltype(k)>(k));
@\exposid{c}@.values.emplace(value_it, std::forward<Args>(args)...);
\end{codeblock}

\pnum
\returns
In the first two overloads,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} for the first two overloads, and
the same as \tcode{emplace_hint} for the last two overloads.
\end{itemdescr}

\indexlibrarymember{try_emplace}{flat_map}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
The \grammarterm{qualified-id} \tcode{Compare::is_transparent}
is valid and denotes a type.
\item
\tcode{is_constructible_v<key_type, K>} is \tcode{true}.
\item
\tcode{is_constructible_v<mapped_type, Args...>} is \tcode{true}.
\item
For the first overload,
\tcode{is_convertible_v<K\&\&, const_iterator>} and
\tcode{is_convertible_v<K\&\&, iterator>} are both \tcode{false}.
\end{itemize}

\pnum
\expects
The conversion from \tcode{k} into \tcode{key_type} constructs
an object \tcode{u},
for which \tcode{find(k) == find(u)} is \tcode{true}.

\pnum
\effects
If the map already contains an element whose key is equivalent to \tcode{k},
\tcode{*this} and \tcode{args...} are unchanged.
Otherwise equivalent to:
\begin{codeblock}
auto key_it = upper_bound(@\exposid{c}@.keys.begin(), @\exposid{c}@.keys.end(), k, @\exposid{compare}@);
auto value_it = @\exposid{c}@.values.begin() + distance(@\exposid{c}@.keys.begin(), key_it);
@\exposid{c}@.keys.emplace(key_it, std::forward<K>(k));
@\exposid{c}@.values.emplace(value_it, std::forward<Args>(args)...);
\end{codeblock}

\pnum
\returns
In the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint}, respectively.
\end{itemdescr}

\indexlibrarymember{insert_or_assign}{flat_map}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_assignable_v<mapped_type\&, M>} is \tcode{true} and
\tcode{is_constructible_v<mapped_type, M>} is \tcode{true}.

\pnum
\effects
If the map already contains an element \tcode{e}
whose key is equivalent to \tcode{k},
assigns \tcode{std::forward<\linebreak M>(obj)} to \tcode{e.second}.
Otherwise, equivalent to
\begin{codeblock}
try_emplace(std::forward<decltype(k)>(k), std::forward<M>(obj))
\end{codeblock}
for the first two overloads or
\begin{codeblock}
try_emplace(hint, std::forward<decltype(k)>(k), std::forward<M>(obj))
\end{codeblock}
for the last two overloads.

\pnum
\returns
In the first two overloads, the \tcode{bool} component of the returned pair
is \tcode{true} if and only if the insertion took place.  The returned
iterator points to the map element whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} for the first two overloads and
the same as \tcode{emplace_hint} for the last two overloads.
\end{itemdescr}

\indexlibrarymember{insert_or_assign}{flat_map}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
The \grammarterm{qualified-id} \tcode{Compare::is_transparent}
is valid and denotes a type.
\item
\tcode{is_constructible_v<key_type, K>} is \tcode{true}.
\item
\tcode{is_assignable_v<mapped_type\&, M>} is \tcode{true}.
\item
\tcode{is_constructible_v<mapped_type, M>} is \tcode{true}.
\end{itemize}

\pnum
\expects
The conversion from \tcode{k} into \tcode{key_type} constructs
an object \tcode{u}, for which \tcode{find(k) == find(u)} is \tcode{true}.

\pnum
\effects
If the map already contains an element \tcode{e}
whose key is equivalent to \tcode{k},
assigns \tcode{std::forward<\linebreak M>(obj)} to \tcode{e.second}.
Otherwise, equivalent to
\begin{codeblock}
try_emplace(std::forward<K>(k), std::forward<M>(obj))
\end{codeblock}
for the first overload or
\begin{codeblock}
try_emplace(hint, std::forward<K>(k), std::forward<M>(obj))
\end{codeblock}
for the second overload.

\pnum
\returns
In the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the map element
whose key is equivalent to \tcode{k}.

\pnum
\complexity
The same as \tcode{emplace} and \tcode{emplace_hint}, respectively.
\end{itemdescr}

\indexlibrarymember{swap}{flat_map}%
\begin{itemdecl}
constexpr void swap(flat_map& y)
  noexcept(is_nothrow_swappable_v<key_container_type> &&
           is_nothrow_swappable_v<mapped_container_type> &&
           is_nothrow_swappable_v<key_compare>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
ranges::swap(@\exposid{compare}@, y.@\exposid{compare}@);
ranges::swap(@\exposid{c}@.keys, y.@\exposid{c}@.keys);
ranges::swap(@\exposid{c}@.values, y.@\exposid{c}@.values);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{extract}{flat_map}%
\begin{itemdecl}
constexpr containers extract() &&;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{*this} is emptied, even if the function exits via an exception.

\pnum
\returns
\tcode{std::move(\exposid{c})}.
\end{itemdescr}

\indexlibrarymember{replace}{flat_map}%
\begin{itemdecl}
constexpr void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{key_cont.size() == mapped_cont.size()} is \tcode{true},
the elements of \tcode{key_cont} are sorted with respect to \exposid{compare}, and
\tcode{key_cont} contains no equal elements.

\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{c}@.keys = std::move(key_cont);
@\exposid{c}@.values = std::move(mapped_cont);
\end{codeblock}
\end{itemdescr}

\rSec3[flat.map.erasure]{Erasure}

\indexlibrarymember{erase_if}{flat_map}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{Key} and \tcode{T} meet the \oldconcept{MoveAssignable} requirements.

\pnum
\effects
Let $E$ be \tcode{bool(pred(pair<const Key\&, const T\&>(e)))}.
Erases all elements \tcode{e} in \tcode{c} for which $E$ holds.

\pnum
\returns
The number of elements erased.

\pnum
\complexity
Exactly \tcode{c.size()} applications of the predicate.

\pnum
\remarks
Stable\iref{algorithm.stable}.
If an invocation of \tcode{erase_if} exits via an exception,
\tcode{c} is in a valid but unspecified state\iref{defns.valid}.
\begin{note}
\tcode{c} still meets its invariants,
but can be empty.
\end{note}
\end{itemdescr}

\rSec2[flat.multimap]{Class template \tcode{flat_multimap}}

\rSec3[flat.multimap.overview]{Overview}

\pnum
\indexlibraryglobal{flat_multimap}%
A \tcode{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 \tcode{T}
based on the keys.
\tcode{flat_multimap} supports iterators that meet
the \oldconcept{InputIterator} requirements and
model the
\libconcept{random_access_iterator} concept\iref{iterator.concept.random.access}.

\pnum
A \tcode{flat_multimap} meets all of the requirements
for a container\iref{container.reqmts} and
for a reversible container\iref{container.rev.reqmts},
plus the optional container requirements\iref{container.opt.reqmts}.
\tcode{flat_multimap} meets the requirements of
an associative container\iref{associative.reqmts}, except that:
\begin{itemize}
\item
it does not meet the requirements related to node handles\iref{container.node},
\item
it does not meet the requirements related to iterator invalidation, and
\item
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.
\end{itemize}
\begin{note}
A \tcode{flat_multimap} does not meet the additional requirements of an
allocator-aware container\iref{container.alloc.reqmts}.
\end{note}

\pnum
A \tcode{flat_multimap} also provides most operations described
in \ref{associative.reqmts} for equal keys.
This means that a \tcode{flat_multimap} supports
the \tcode{a_eq} operations in \ref{associative.reqmts}
but not the \tcode{a_uniq} operations.
For a \tcode{flat_multimap<Key, T>}
the \tcode{key_type} is \tcode{Key} and
the \tcode{value_type} is \tcode{pair<Key, T>}.

\pnum
Except as otherwise noted,
operations on \tcode{flat_multimap} are equivalent to those of \tcode{flat_map},
except that \tcode{flat_multimap} operations
do not remove or replace elements with equal keys.
\begin{example}
\tcode{flat_multimap} constructors and emplace do not erase
non-unique elements after sorting them.
\end{example}

\pnum
A \tcode{flat_multimap} maintains the following invariants:
\begin{itemize}
\item
it contains the same number of keys and values;
\item
the keys are sorted with respect to the comparison object; and
\item
the value at offset \tcode{off} within the value container is the value
associated with the key at offset \tcode{off} within the key container.
\end{itemize}

\pnum
If any member function in \ref{flat.multimap.defn} exits via an exception,
the invariants of the object argument are restored.
For the move constructor and move assignment operator,
the invariants of both arguments are restored.
\begin{note}
This can result in the \tcode{flat_multimap} being emptied.
\end{note}

\pnum
Any type \tcode{C}
that meets the sequence container requirements\iref{sequence.reqmts}
can be used to instantiate \tcode{flat_multimap},
as long as
\tcode{C::iterator} meets the \oldconcept{RandomAccessIterator} requirements and
invocations of
member functions \tcode{C::size} and \tcode{C::max_size} do not exit via an exception.
In particular,
\tcode{vector}\iref{vector} and \tcode{deque}\iref{deque} can be used.
\begin{note}
\tcode{vector<bool>} is not a sequence container.
\end{note}

\pnum
The program is ill-formed if
\tcode{Key} is not the same type as \tcode{KeyContainer::value_type} or
\tcode{T} is not the same type as \tcode{MappedContainer::value_type}.

\pnum
The effect of calling a constructor
that takes both \tcode{key_container_type} and
\tcode{mapped_container_type} arguments
with containers of different sizes is undefined.

\pnum
The effect of calling a member function
that takes a \tcode{sorted_equivalent_t} argument
with a container, containers, or range
that are not sorted with respect to \tcode{key_comp()} is undefined.

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\rSec3[flat.multimap.defn]{Definition}

\begin{codeblock}
namespace std {
  template<class Key, class T, class Compare = less<Key>,
           class KeyContainer = vector<Key>, class MappedContainer = vector<T>>
  class flat_multimap {
  public:
    // types
    using key_type               = Key;
    using mapped_type            = T;
    using value_type             = pair<key_type, mapped_type>;
    using key_compare            = Compare;
    using reference              = pair<const key_type&, mapped_type&>;
    using const_reference        = pair<const key_type&, const mapped_type&>;
    using size_type              = size_t;
    using difference_type        = ptrdiff_t;
    using iterator               = @\impdefx{type of \tcode{flat_multimap::iterator}}@;     // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{flat_multimap::const_iterator}}@;     // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using key_container_type     = KeyContainer;
    using mapped_container_type  = MappedContainer;

    class value_compare {
    private:
      key_compare @\exposid{comp}@;                                         // \expos
      constexpr value_compare(key_compare c) : @\exposid{comp}@(c) { }      // \expos

    public:
      constexpr bool operator()(const_reference x, const_reference y) const {
        return @\exposid{comp}@(x.first, y.first);
      }
    };

    struct containers {
      key_container_type keys;
      mapped_container_type values;
    };

    // \ref{flat.multimap.cons}, constructors
    constexpr flat_multimap() : flat_multimap(key_compare()) { }

    constexpr flat_multimap(const flat_multimap&);
    constexpr flat_multimap(flat_multimap&&);
    constexpr flat_multimap& operator=(const flat_multimap&);
    constexpr flat_multimap& operator=(flat_multimap&&);

    constexpr explicit flat_multimap(const key_compare& comp)
      : @\exposid{c}@(), @\exposid{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())
        : @\exposid{c}@(), @\exposid{compare}@(comp)
        { insert(first, last); }

    template<class InputIterator>
      constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last,
                              const key_compare& comp = key_compare())
        : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(sorted_equivalent, first, last); }

    template<@\exposconcept{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<@\exposconcept{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) { }

    // \ref{flat.multimap.cons.alloc}, constructors with allocators

    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<@\exposconcept{container-compatible-range}@<value_type> R, class Alloc>
      constexpr flat_multimap(from_range_t, R&& rg, const Alloc& a);
    template<@\exposconcept{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>);

    // iterators
    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;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // modifiers
    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<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(R&& rg);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(sorted_equivalent_t, 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(is_nothrow_swappable_v<key_container_type> &&
               is_nothrow_swappable_v<mapped_container_type> &&
               is_nothrow_swappable_v<key_compare>);
    constexpr void clear() noexcept;

    // observers
    constexpr key_compare key_comp() const;
    constexpr value_compare value_comp() const;

    constexpr const key_container_type& keys() const noexcept { return @\exposid{c}@.keys; }
    constexpr const mapped_container_type& values() const noexcept { return @\exposid{c}@.values; }

    // map operations
    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 @\exposid{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(noexcept(x.swap(y)))
      { x.swap(y); }

  private:
    containers @\exposid{c}@;               // \expos
    key_compare @\exposid{compare}@;        // \expos
  };

  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<@\exposid{iter-key-type}@<InputIterator>>>
    flat_multimap(InputIterator, InputIterator, Compare = Compare())
      -> flat_multimap<@\exposid{iter-key-type}@<InputIterator>, @\exposid{iter-mapped-type}@<InputIterator>, Compare>;

  template<class InputIterator, class Compare = less<@\exposid{iter-key-type}@<InputIterator>>>
    flat_multimap(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare())
      -> flat_multimap<@\exposid{iter-key-type}@<InputIterator>, @\exposid{iter-mapped-type}@<InputIterator>, Compare>;

  template<ranges::@\libconcept{input_range}@ R, class Compare = less<@\exposid{range-key-type}@<R>>,
           class Allocator = allocator<byte>>
    flat_multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())
      -> flat_multimap<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, Compare,
                       vector<@\exposid{range-key-type}@<R>,
                              @\exposid{alloc-rebind}@<Allocator, @\exposid{range-key-type}@<R>>>,
                       vector<@\exposid{range-mapped-type}@<R>,
                              @\exposid{alloc-rebind}@<Allocator, @\exposid{range-mapped-type}@<R>>>>;

  template<ranges::@\libconcept{input_range}@ R, class Allocator>
    flat_multimap(from_range_t, R&&, Allocator)
      -> flat_multimap<@\exposid{range-key-type}@<R>, @\exposid{range-mapped-type}@<R>, less<@\exposid{range-key-type}@<R>>,
                       vector<@\exposid{range-key-type}@<R>,
                              @\exposid{alloc-rebind}@<Allocator, @\exposid{range-key-type}@<R>>>,
                       vector<@\exposid{range-mapped-type}@<R>,
                              @\exposid{alloc-rebind}@<Allocator, @\exposid{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>> { };
}
\end{codeblock}

\pnum
The member type \tcode{containers} has the data members and special members
specified above. It has no base classes or members other than those
specified.

\rSec3[flat.multimap.cons]{Constructors}

\indexlibraryctor{flat_multimap}%
\begin{itemdecl}
constexpr flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont,
                        const key_compare& comp = key_compare());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes
\tcode{\exposid{c}.keys} with \tcode{std::move(key_cont)},
\tcode{\exposid{c}.values} with \tcode{std::move(mapped_cont)}, and
\exposid{compare} with \tcode{comp};
sorts the range \range{begin()}{end()} with respect to \tcode{value_comp()}.

\pnum
\complexity
Linear in $N$ if the container arguments are already sorted
with respect to \tcode{value_comp()} and otherwise $N \log N$,
where $N$ is the value of \tcode{key_cont.size()} before this call.
\end{itemdescr}

\indexlibraryctor{flat_multimap}%
\begin{itemdecl}
constexpr flat_multimap(sorted_equivalent_t, key_container_type key_cont,
                        mapped_container_type mapped_cont,
                        const key_compare& comp = key_compare());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes
\tcode{\exposid{c}.keys} with \tcode{std::move(key_cont)},
\tcode{\exposid{c}.values} with \tcode{std::move(mapped_cont)}, and
\exposid{compare} with \tcode{comp}.

\pnum
\complexity
Constant.
\end{itemdescr}

\rSec3[flat.multimap.cons.alloc]{Constructors with allocators}

\pnum
The constructors in this subclause shall not participate in overload resolution
unless \tcode{uses_allocator_v<key_container_type, Alloc>} is \tcode{true}
and \tcode{uses_allocator_v<mapped_container_type, Alloc>} is \tcode{true}.

\indexlibraryctor{flat_multimap}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{flat_multimap(key_cont, mapped_cont)} and
\tcode{flat_multimap(key_cont, \linebreak{}mapped_cont, comp)}, respectively,
except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed
with uses-allocator construction\iref{allocator.uses.construction}.

\pnum
\complexity
Same as \tcode{flat_multimap(key_cont, mapped_cont)} and
\tcode{flat_multimap(key_cont, \linebreak{}mapped_cont, comp)}, respectively.
\end{itemdescr}

\indexlibraryctor{flat_multimap}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{flat_multimap(sorted_equivalent, key_cont, mapped_cont)} and
\tcode{flat_multimap(sorted_equivalent, key_cont, mapped_cont, comp)}, respectively,
except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.val\-ues} are constructed
with uses-allocator construction\iref{allocator.uses.construction}.

\pnum
\complexity
Linear.
\end{itemdescr}

\indexlibraryctor{flat_multimap}%
\begin{itemdecl}
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<@\exposconcept{container-compatible-range}@<value_type> R, class Alloc>
  constexpr flat_multimap(from_range_t, R&& rg, const Alloc& a);
template<@\exposconcept{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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to the corresponding non-allocator constructors
except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed
with uses-allocator construction\iref{allocator.uses.construction}.
\end{itemdescr}

\rSec3[flat.multimap.erasure]{Erasure}

\indexlibrarymember{erase_if}{flat_multimap}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{Key} and \tcode{T} meet the \oldconcept{MoveAssignable} requirements.

\pnum
\effects
Let $E$ be \tcode{bool(pred(pair<const Key\&, const T\&>(e)))}.
Erases all elements \tcode{e} in \tcode{c} for which $E$ holds.

\pnum
\returns
The number of elements erased.

\pnum
\complexity
Exactly \tcode{c.size()} applications of the predicate.

\pnum
\remarks
Stable\iref{algorithm.stable}.
If an invocation of \tcode{erase_if} exits via an exception,
\tcode{c} is in a valid but unspecified state\iref{defns.valid}.
\begin{note}
\tcode{c} still meets its invariants,
but can be empty.
\end{note}
\end{itemdescr}

\rSec2[flat.set.syn]{Header \tcode{<flat_set>} synopsis}%
\indexheader{flat_set}%

\begin{codeblock}
#include <compare>              // see \ref{compare.syn}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{flat.set}, class template \tcode{flat_set}
  template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>>
    class flat_set;

  struct sorted_unique_t { explicit sorted_unique_t() = default; };
  inline constexpr sorted_unique_t sorted_unique{};

  template<class Key, class Compare, class KeyContainer, class Allocator>
    struct uses_allocator<flat_set<Key, Compare, KeyContainer>, Allocator>;

  // \ref{flat.set.erasure}, erasure for \tcode{flat_set}
  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);

  // \ref{flat.multiset}, class template \tcode{flat_multiset}
  template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>>
    class flat_multiset;

  struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; };
  inline constexpr sorted_equivalent_t sorted_equivalent{};

  template<class Key, class Compare, class KeyContainer, class Allocator>
    struct uses_allocator<flat_multiset<Key, Compare, KeyContainer>, Allocator>;

  // \ref{flat.multiset.erasure}, erasure for \tcode{flat_multiset}
  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);
}
\end{codeblock}

\rSec2[flat.set]{Class template \tcode{flat_set}}

\rSec3[flat.set.overview]{Overview}

\pnum
\indexlibraryglobal{flat_set}%
A \tcode{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.
\tcode{flat_set} supports iterators that model
the \libconcept{random_access_iterator} concept\iref{iterator.concept.random.access}.

\pnum
A \tcode{flat_set} meets all of the requirements
for a container\iref{container.reqmts} and
for a reversible container\iref{container.rev.reqmts},
plus the optional container requirements\iref{container.opt.reqmts}.
\tcode{flat_set} meets the requirements of
an associative container\iref{associative.reqmts}, except that:
\begin{itemize}
\item
it does not meet the requirements
related to node handles\iref{container.node.overview},
\item
it does not meet the requirements related to iterator invalidation, and
\item
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.
\end{itemize}
\begin{note}
A \tcode{flat_set} does not meet
the additional requirements of an allocator-aware container,
as described in \ref{container.alloc.reqmts}.
\end{note}

\pnum
A \tcode{flat_set} also provides most operations
described in \ref{associative.reqmts} for unique keys.
This means that a \tcode{flat_set} supports
the \tcode{a_uniq} operations in \ref{associative.reqmts}
but not the \tcode{a_eq} operations.
For a \tcode{flat_set<Key>},
both the \tcode{key_type} and \tcode{value_type} are \tcode{Key}.

\pnum
Descriptions are provided here only for operations on \tcode{flat_set}
that are not described in one of those sets of requirements or
for operations where there is additional semantic information.

\pnum
A \tcode{flat_set} maintains the invariant that the keys are sorted with
respect to the comparison object.

\pnum
If any member function in \ref{flat.set.defn} exits via an exception,
the invariant of the object argument is restored.
For the move constructor and move assignment operator,
the invariants of both arguments are restored.
\begin{note}
This can result in the \tcode{flat_set}'s being emptied.
\end{note}

\pnum
Any sequence container\iref{sequence.reqmts}
supporting \oldconcept{RandomAccessIterator}
can be used to instantiate \tcode{flat_set}.
In particular, \tcode{vector}\iref{vector} and \tcode{deque}\iref{deque}
can be used.
\begin{note}
\tcode{vector<bool>} is not a sequence container.
\end{note}

\pnum
The program is ill-formed if \tcode{Key} is not the same type
as \tcode{KeyContainer::value_type}.

\pnum
The effect of calling a member function
that takes a \tcode{sorted_unique_t} argument
with a range that is not sorted with respect to \tcode{key_comp()}, or
that contains equal elements, is undefined.

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\rSec3[flat.set.defn]{Definition}

\begin{codeblock}
namespace std {
  template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>>
  class @\libglobal{flat_set}@ {
  public:
    // types
    using key_type               = Key;
    using value_type             = Key;
    using key_compare            = Compare;
    using value_compare          = Compare;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = KeyContainer::size_type;
    using difference_type        = KeyContainer::difference_type;
    using iterator               = @\impdefx{type of \tcode{flat_set::iterator}}@;     // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{flat_set::const_iterator}}@;     // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using container_type         = KeyContainer;

    // \ref{flat.set.cons}, constructors
    constexpr flat_set() : flat_set(key_compare()) { }

    constexpr flat_set(const flat_set&);
    constexpr flat_set(flat_set&&);
    constexpr flat_set& operator=(const flat_set&);
    constexpr flat_set& operator=(flat_set&&);

    constexpr explicit flat_set(const key_compare& comp)
      : @\exposid{c}@(), @\exposid{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())
      : @\exposid{c}@(std::move(cont)), @\exposid{compare}@(comp) { }

    template<class InputIterator>
      constexpr flat_set(InputIterator first, InputIterator last,
                         const key_compare& comp = key_compare())
        : @\exposid{c}@(), @\exposid{compare}@(comp)
        { insert(first, last); }

    template<class InputIterator>
      constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last,
                         const key_compare& comp = key_compare())
        : @\exposid{c}@(first, last), @\exposid{compare}@(comp) { }

    template<@\exposconcept{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<@\exposconcept{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) { }

    // \ref{flat.set.cons.alloc}, constructors with allocators

    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<@\exposconcept{container-compatible-range}@<value_type> R, class Alloc>
      constexpr flat_set(from_range_t, R&& rg, const Alloc& a);
    template<@\exposconcept{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>);

    // iterators
    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;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // \ref{flat.set.modifiers}, modifiers
    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<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(R&& rg);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(sorted_unique_t, 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) requires (!@\libconcept{same_as}@<iterator, const_iterator>);
    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(@\seebelow@);
    constexpr void clear() noexcept;

    // observers
    constexpr key_compare key_comp() const;
    constexpr value_compare value_comp() const;

    // set operations
    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 @\exposid{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(noexcept(x.swap(y)))
      { x.swap(y); }

  private:
    container_type @\exposidnc{c}@;           // \expos
    key_compare @\exposidnc{compare}@;        // \expos
  };

  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<@\placeholder{iter-value-type}@<InputIterator>>>
    flat_set(InputIterator, InputIterator, Compare = Compare())
      -> flat_set<@\placeholder{iter-value-type}@<InputIterator>, Compare>;

  template<class InputIterator, class Compare = less<@\placeholder{iter-value-type}@<InputIterator>>>
    flat_set(sorted_unique_t, InputIterator, InputIterator, Compare = Compare())
      -> flat_set<@\placeholder{iter-value-type}@<InputIterator>, Compare>;

  template<ranges::@\libconcept{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>,
                         @\exposid{alloc-rebind}@<Allocator, ranges::range_value_t<R>>>>;

  template<ranges::@\libconcept{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>,
                         @\exposid{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>> { };
}
\end{codeblock}

\rSec3[flat.set.cons]{Constructors}

\indexlibraryctor{flat_set}%
\begin{itemdecl}
constexpr explicit flat_set(container_type cont, const key_compare& comp = key_compare());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{c} with \tcode{std::move(cont)} and
\exposid{compare} with \tcode{comp},
sorts the range \range{begin()}{end()} with respect to \exposid{compare}, and
finally erases all but the first element
from each group of consecutive equivalent elements.

\pnum
\complexity
Linear in $N$ if \tcode{cont} is already sorted with respect to \exposid{compare} and
otherwise $N \log N$, where $N$ is the value of \tcode{cont.size()} before this call.
\end{itemdescr}

\rSec3[flat.set.cons.alloc]{Constructors with allocators}

\pnum
The constructors in this subclause shall not participate in overload resolution
unless \tcode{uses_allocator_v<container_type, Alloc>} is \tcode{true}.

\indexlibraryctor{flat_set}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to
\tcode{flat_set(cont)} and \tcode{flat_set(cont, comp)}, respectively,
except that \exposid{c} is constructed with
uses-allocator construction\iref{allocator.uses.construction}.

\pnum
\complexity
Same as \tcode{flat_set(cont)} and \tcode{flat_set(cont, comp)}, respectively.
\end{itemdescr}

\indexlibraryctor{flat_set}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to
\tcode{flat_set(sorted_unique, cont)} and
\tcode{flat_set(sorted_unique, cont,\linebreak comp)}, respectively,
except that \exposid{c} is constructed with
uses-allocator construction\iref{allocator.uses.construction}.

\pnum
\complexity
Linear.
\end{itemdescr}

\indexlibraryctor{flat_set}%
\begin{itemdecl}
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<@\exposconcept{container-compatible-range}@<value_type> R, class Alloc>
  constexpr flat_set(from_range_t, R&& rg, const Alloc& a);
template<@\exposconcept{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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to the corresponding non-allocator constructors
except that \exposid{c} is constructed with
uses-allocator construction\iref{allocator.uses.construction}.
\end{itemdescr}

\rSec3[flat.set.modifiers]{Modifiers}

\indexlibrarymember{insert}{flat_set}%
\begin{itemdecl}
template<class K> constexpr pair<iterator, bool> insert(K&& x);
template<class K> constexpr iterator insert(const_iterator hint, K&& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The \grammarterm{qualified-id} \tcode{Compare::is_transparent}
is valid and denotes a type.
\tcode{is_constructi\-ble_v<value_type, K>} is \tcode{true}.

\pnum
\expects
The conversion from \tcode{x} into \tcode{value_type} constructs
an object \tcode{u}, for which \tcode{find(x) == find(u)} is \tcode{true}.

\pnum
\effects
If the set already contains an element equivalent to \tcode{x},
\tcode{*this} and \tcode{x} are unchanged.
Otherwise,
inserts a new element as if by \tcode{emplace(std::forward<K>(x))}.

\pnum
\returns
In the first overload,
the \tcode{bool} component of the returned pair is \tcode{true}
if and only if the insertion took place.
The returned iterator points to the element
whose key is equivalent to \tcode{x}.
\end{itemdescr}

\indexlibrarymember{insert}{flat_set}%
\begin{itemdecl}
template<class InputIterator>
  constexpr void insert(InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Adds elements to \exposid{c} as if by:
\begin{codeblock}
@\exposid{c}@.insert(@\exposid{c}@.end(), first, last);
\end{codeblock}
Then,
sorts the range of newly inserted elements with respect to \exposid{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.

\pnum
\complexity
$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and
$M$ is \tcode{distance(first, last)}.

\pnum
\remarks
Since this operation performs an in-place merge, it may allocate memory.
\end{itemdescr}

\indexlibrarymember{insert}{flat_set}%
\begin{itemdecl}
template<class InputIterator>
  constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{insert(first, last)}.

\pnum
\complexity
Linear.
\end{itemdescr}

\indexlibrarymember{insert_range}{flat_set}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr void insert_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Adds elements to \exposid{c} as if by:
\begin{codeblock}
ranges::for_each(rg, [&](value_type e) {
  @\exposid{c}@.insert(@\exposid{c}@.end(), std::move(e));
});
\end{codeblock}
Then,
sorts the range of newly inserted elements with respect to \exposid{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.

\pnum
\complexity
$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and $M$
is \tcode{ranges::distance(rg)}.

\pnum
\remarks
Since this operation performs an in-place merge, it may allocate memory.
\end{itemdescr}

\indexlibrarymember{insert_range}{flat_set}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr void insert_range(sorted_unique_t, R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{insert_range(rg)}.

\pnum
\complexity
Linear in $N$, where $N$ is \tcode{size()} after the operation.
\end{itemdescr}

\indexlibrarymember{swap}{flat_set}%
\begin{itemdecl}
constexpr void swap(flat_set& y)
  noexcept(is_nothrow_swappable_v<container_type> &&
           is_nothrow_swappable_v<key_compare>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
ranges::swap(@\exposid{compare}@, y.@\exposid{compare}@);
ranges::swap(@\exposid{c}@, y.@\exposid{c}@);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{extract}{flat_set}%
\begin{itemdecl}
constexpr container_type extract() &&;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{*this} is emptied, even if the function exits via an exception.

\pnum
\returns
\tcode{std::move(\exposid{c})}.
\end{itemdescr}

\indexlibrarymember{replace}{flat_set}%
\begin{itemdecl}
constexpr void replace(container_type&& cont);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
The elements of \tcode{cont} are sorted with respect to \exposid{compare}, and
\tcode{cont} contains no equal elements.

\pnum
\effects
Equivalent to: \tcode{\exposid{c} = std::move(cont);}
\end{itemdescr}

\rSec3[flat.set.erasure]{Erasure}

\indexlibrarymember{erase_if}{flat_set}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{Key} meets the \oldconcept{MoveAssignable} requirements.

\pnum
\effects
Let $E$ be \tcode{bool(pred(as_const(e)))}.
Erases all elements \tcode{e} in \tcode{c} for which $E$ holds.

\pnum
\returns
The number of elements erased.

\pnum
\complexity
Exactly \tcode{c.size()} applications of the predicate.

\pnum
\remarks
Stable\iref{algorithm.stable}.
If an invocation of \tcode{erase_if} exits via an exception,
\tcode{c} is in a valid but unspecified state\iref{defns.valid}.
\begin{note}
\tcode{c} still meets its invariants, but can be empty.
\end{note}
\end{itemdescr}

\rSec2[flat.multiset]{Class template \tcode{flat_multiset}}

\rSec3[flat.multiset.overview]{Overview}

\pnum
\indexlibraryglobal{flat_multiset}%
A \tcode{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.
\tcode{flat_multiset} supports iterators that model the
\libconcept{random_access_iterator} concept\iref{iterator.concept.random.access}.

\pnum
A \tcode{flat_multiset} meets all of the requirements
for a container\iref{container.reqmts} and
for a reversible container\iref{container.rev.reqmts},
plus the optional container requirements\iref{container.opt.reqmts}.
\tcode{flat_multiset} meets the requirements of
an associative container\iref{associative.reqmts}, except that:
\begin{itemize}
\item
it does not meet the requirements
related to node handles\iref{container.node.overview},
\item
it does not meet the requirements related to iterator invalidation, and
\item
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.
\end{itemize}
\begin{note}
A \tcode{flat_multiset} does not meet
the additional requirements of an allocator-aware container,
as described in \ref{container.alloc.reqmts}.
\end{note}

\pnum
A \tcode{flat_multiset} also provides most operations
described in \ref{associative.reqmts} for equal keys.
This means that a \tcode{flat_multiset} supports
the \tcode{a_eq} operations in \ref{associative.reqmts}
but not the \tcode{a_uniq} operations.
For a \tcode{flat_multiset<Key>},
both the \tcode{key_type} and \tcode{value_type} are \tcode{Key}.

\pnum
Descriptions are provided here only for operations on \tcode{flat_multiset}
that are not described in one of the general sections or
for operations where there is additional semantic information.

\pnum
A \tcode{flat_multiset} maintains the invariant
that the keys are sorted with respect to the comparison object.

\pnum
If any member function in \ref{flat.multiset.defn} exits via an exception,
the invariant of the object argument is restored.
For the move constructor and move assignment operator,
the invariants of both arguments are restored.
\begin{note}
This can result in the \tcode{flat_multiset}'s being emptied.
\end{note}

\pnum
Any sequence container\iref{sequence.reqmts}
supporting \oldconcept{RandomAccessIterator}
can be used to instantiate \tcode{flat_multiset}.
In particular,
\tcode{vector}\iref{vector} and \tcode{deque}\iref{deque} can be used.
\begin{note}
\tcode{vector<bool>} is not a sequence container.
\end{note}

\pnum
The program is ill-formed if \tcode{Key} is not the same type
as \tcode{KeyContainer::value_type}.

\pnum
The effect of calling a member function
that takes a \tcode{sorted_equivalent_t} argument with a range
that is not sorted with respect to \tcode{key_comp()} is undefined.

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\rSec3[flat.multiset.defn]{Definition}

\begin{codeblock}
namespace std {
  template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>>
  class flat_multiset {
  public:
    // types
    using key_type               = Key;
    using value_type             = Key;
    using key_compare            = Compare;
    using value_compare          = Compare;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = KeyContainer::size_type;
    using difference_type        = KeyContainer::difference_type;
    using iterator               = @\impdefx{type of \tcode{flat_multiset::iterator}}@;     // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{flat_multiset::const_iterator}}@;     // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using container_type         = KeyContainer;

    // \ref{flat.multiset.cons}, constructors
    constexpr flat_multiset() : flat_multiset(key_compare()) { }

    constexpr flat_multiset(const flat_multiset&);
    constexpr flat_multiset(flat_multiset&&);
    constexpr flat_multiset& operator=(const flat_multiset&);
    constexpr flat_multiset& operator=(flat_multiset&&);

    constexpr explicit flat_multiset(const key_compare& comp)
      : @\exposid{c}@(), @\exposid{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())
      : @\exposid{c}@(std::move(cont)), @\exposid{compare}@(comp) { }

    template<class InputIterator>
      constexpr flat_multiset(InputIterator first, InputIterator last,
                              const key_compare& comp = key_compare())
        : @\exposid{c}@(), @\exposid{compare}@(comp)
        { insert(first, last); }

    template<class InputIterator>
      constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last,
                              const key_compare& comp = key_compare())
        : @\exposid{c}@(first, last), @\exposid{compare}@(comp) { }

    template<@\exposconcept{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<@\exposconcept{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) { }

    // \ref{flat.multiset.cons.alloc}, constructors with allocators

    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<@\exposconcept{container-compatible-range}@<value_type> R, class Alloc>
      constexpr flat_multiset(from_range_t, R&& rg, const Alloc& a);
    template<@\exposconcept{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>);

    // iterators
    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;

    // capacity
    constexpr bool empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // \ref{flat.multiset.modifiers}, modifiers
    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<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(R&& rg);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      constexpr void insert_range(sorted_equivalent_t, 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) requires (!@\libconcept{same_as}@<iterator, const_iterator>);
    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(@\seebelow@);
    constexpr void clear() noexcept;

    // observers
    constexpr key_compare key_comp() const;
    constexpr value_compare value_comp() const;

    // set operations
    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 @\exposid{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(noexcept(x.swap(y)))
      { x.swap(y); }

  private:
    container_type @\exposidnc{c}@;           // \expos
    key_compare @\exposidnc{compare}@;        // \expos
  };

  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<@\placeholder{iter-value-type}@<InputIterator>>>
    flat_multiset(InputIterator, InputIterator, Compare = Compare())
      -> flat_multiset<@\placeholder{iter-value-type}@<InputIterator>, Compare>;

  template<class InputIterator, class Compare = less<@\placeholder{iter-value-type}@<InputIterator>>>
    flat_multiset(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare())
      -> flat_multiset<@\placeholder{iter-value-type}@<InputIterator>, Compare>;

  template<ranges::@\libconcept{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>,
                              @\exposid{alloc-rebind}@<Allocator, ranges::range_value_t<R>>>>;

  template<ranges::@\libconcept{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>,
                              @\exposid{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>> { };
}
\end{codeblock}

\rSec3[flat.multiset.cons]{Constructors}

\indexlibraryctor{flat_multiset}%
\begin{itemdecl}
constexpr explicit flat_multiset(container_type cont, const key_compare& comp = key_compare());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{c} with \tcode{std::move(cont)} and
\exposid{compare} with \tcode{comp}, and
sorts the range \range{begin()}{end()} with respect to \exposid{compare}.

\pnum
\complexity
Linear in $N$ if \tcode{cont} is already sorted with respect to \exposid{compare} and
otherwise $N \log N$, where $N$ is the value of \tcode{cont.size()} before this call.
\end{itemdescr}

\rSec3[flat.multiset.cons.alloc]{Constructors with allocators}

\pnum
The constructors in this subclause shall not participate in overload resolution
unless \tcode{uses_allocator_v<container_type, Alloc>} is \tcode{true}.

\indexlibraryctor{flat_multiset}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{flat_multiset(cont)} and
\tcode{flat_multiset(cont, comp)}, respectively,
except that \exposid{c} is constructed with
uses-allocator construction\iref{allocator.uses.construction}.

\pnum
\complexity
Same as \tcode{flat_multiset(cont)} and
\tcode{flat_multiset(cont, comp)}, respectively.
\end{itemdescr}

\indexlibraryctor{flat_multiset}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{flat_multiset(sorted_equivalent, cont)} and
\tcode{flat_multiset(sorted_equivalent, cont, comp)}, respectively,
except that \exposid{c} is constructed with
uses-allocator construction\iref{allocator.uses.construction}.

\pnum
\complexity
Linear.
\end{itemdescr}

\indexlibraryctor{flat_multiset}%
\begin{itemdecl}
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<@\exposconcept{container-compatible-range}@<value_type> R, class Alloc>
  constexpr flat_multiset(from_range_t, R&& rg, const Alloc& a);
template<@\exposconcept{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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to the corresponding non-allocator constructors
except that \exposid{c} is constructed with
uses-allocator construction\iref{allocator.uses.construction}.
\end{itemdescr}

\rSec3[flat.multiset.modifiers]{Modifiers}

\indexlibrarymember{emplace}{flat_multiset}%
\begin{itemdecl}
template<class... Args> constexpr iterator emplace(Args&&... args);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<value_type, Args...>} is \tcode{true}.

\pnum
\effects
First, initializes an object \tcode{t} of type \tcode{value_type}
with \tcode{std::forward<Args>(args)...},
then inserts \tcode{t} as if by:
\begin{codeblock}
auto it = ranges::upper_bound(@\exposid{c}@, t, @\exposid{compare}@);
@\exposid{c}@.insert(it, std::move(t));
\end{codeblock}

\pnum
\returns
An iterator that points to the inserted element.
\end{itemdescr}

\indexlibrarymember{insert}{flat_multiset}%
\begin{itemdecl}
template<class InputIterator>
  constexpr void insert(InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Adds elements to \exposid{c} as if by:
\begin{codeblock}
@\exposid{c}@.insert(@\exposid{c}@.end(), first, last);
\end{codeblock}
Then, sorts the range of newly inserted elements with respect to \exposid{compare},
and merges the resulting sorted range and
the sorted range of pre-existing elements into a single sorted range.

\pnum
\complexity
$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and $M$
is \tcode{distance(first, last)}.

\pnum
\remarks
Since this operation performs an in-place merge, it may allocate memory.
\end{itemdescr}

\indexlibrarymember{insert}{flat_multiset}%
\begin{itemdecl}
template<class InputIterator>
  constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{insert(first, last)}.

\pnum
\complexity
Linear in $N$, where $N$ is \tcode{size()} after the operation.
\end{itemdescr}

\indexlibrarymember{insert_range}{flat_multiset}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr void insert_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Adds elements to \exposid{c} as if by:
\begin{codeblock}
ranges::for_each(rg, [&](value_type e) {
  @\exposid{c}@.insert(@\exposid{c}@.end(), std::move(e));
});
\end{codeblock}
Then, sorts the range of newly inserted elements with respect to \exposid{compare},
and merges the resulting sorted range and
the sorted range of pre-existing elements into a single sorted range.

\pnum
\complexity
$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and $M$
is \tcode{ranges::distance(rg)}.

\pnum
\remarks
Since this operation performs an in-place merge,
it may allocate memory.
\end{itemdescr}

\indexlibrarymember{insert_range}{flat_multiset}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<value_type> R>
  constexpr void insert_range(sorted_equivalent_t, R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{insert_range(rg)}.

\pnum
\complexity
Linear in $N$, where $N$ is \tcode{size()} after the operation.
\end{itemdescr}

\indexlibrarymember{swap}{flat_multiset}%
\begin{itemdecl}
constexpr void swap(flat_multiset& y)
  noexcept(is_nothrow_swappable_v<container_type> &&
           is_nothrow_swappable_v<key_compare>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
ranges::swap(@\exposid{compare}@, y.@\exposid{compare}@);
ranges::swap(@\exposid{c}@, y.@\exposid{c}@);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{extract}{flat_multiset}%
\begin{itemdecl}
constexpr container_type extract() &&;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{*this} is emptied, even if the function exits via an exception.

\pnum
\returns
\tcode{std::move(\exposid{c})}.
\end{itemdescr}

\indexlibrarymember{replace}{flat_multiset}%
\begin{itemdecl}
constexpr void replace(container_type&& cont);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
The elements of \tcode{cont} are sorted with respect to \exposid{compare}.

\pnum
\effects
Equivalent to: \tcode{\exposid{c} = std::move(cont);}
\end{itemdescr}

\rSec3[flat.multiset.erasure]{Erasure}

\indexlibrarymember{erase_if}{flat_multiset}%
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{Key} meets the \oldconcept{MoveAssignable} requirements.

\pnum
\effects
Let $E$ be \tcode{bool(pred(as_const(e)))}.
Erases all elements \tcode{e} in \tcode{c} for which $E$ holds.

\pnum
\returns
The number of elements erased.

\pnum
\complexity
Exactly \tcode{c.size()} applications of the predicate.

\pnum
\remarks
Stable\iref{algorithm.stable}.
If an invocation of \tcode{erase_if} exits via an exception,
\tcode{c} is in a valid but unspecified state\iref{defns.valid}.
\begin{note}
\tcode{c} still meets its invariants, but can be empty.
\end{note}
\end{itemdescr}

\rSec2[container.adaptors.format]{Container adaptors formatting}

\pnum
For each of
\tcode{queue},
\tcode{priority_queue}, and
\tcode{stack},
the library provides the following constexpr-enabled formatter specialization
where \tcode{\placeholder{adaptor-type}} is the name of the template:

\indexlibraryglobal{formatter}%
\begin{codeblock}
namespace std {
  template<class charT, class T, @\libconcept{formattable}@<charT> Container, class... U>
  struct formatter<@\placeholder{adaptor-type}@<T, Container, U...>, charT> {
  private:
    using @\exposid{maybe-const-container}@ =                                             // \expos
      @\exposid{fmt-maybe-const}@<Container, charT>;
    using @\exposid{maybe-const-adaptor}@ =                                               // \expos
      @\exposid{maybe-const}@<is_const_v<@\exposid{maybe-const-container}@>,                          // see \ref{ranges.syn}
                  @\placeholder{adaptor-type}@<T, Container, U...>>;
    formatter<ranges::ref_view<@\exposid{maybe-const-container}@>, charT> @\exposid{underlying_}@;    // \expos

  public:
    template<class ParseContext>
      constexpr typename ParseContext::iterator
        parse(ParseContext& ctx);

    template<class FormatContext>
      constexpr typename FormatContext::iterator
        format(@\exposid{maybe-const-adaptor}@& r, FormatContext& ctx) const;
  };
}
\end{codeblock}

\indexlibrarymember{parse}{formatter}%
\begin{itemdecl}
template<class ParseContext>
  constexpr typename ParseContext::iterator
    parse(ParseContext& ctx);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);}
\end{itemdescr}

\indexlibrarymember{format}{formatter}%
\begin{itemdecl}
template<class FormatContext>
  constexpr typename FormatContext::iterator
    format(@\exposid{maybe-const-adaptor}@& r, FormatContext& ctx) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{underlying_}.format(r.c, ctx);}
\end{itemdescr}

\rSec1[views]{Views}

\rSec2[views.general]{General}

\pnum
The header \libheaderref{span} defines the view \tcode{span}.
The header \libheaderref{mdspan} defines the class template \tcode{mdspan} and
other facilities for interacting with these multidimensional views.

\pnum
In addition to being available via inclusion of the \libheaderref{span} header,
\tcode{dynamic_extent} is available when the header \libheaderref{mdspan} is included.

\rSec2[views.contiguous]{Contiguous access}

\rSec3[span.syn]{Header \tcode{<span>} synopsis}%

\indexheader{span}%
\begin{codeblock}
// mostly freestanding
namespace std {
  // constants
  inline constexpr size_t @\libglobal{dynamic_extent}@ = numeric_limits<size_t>::max();

  template<class T>
    concept @\defexposconcept{integral-constant-like}@ =                    // \expos
      is_integral_v<remove_cvref_t<decltype(T::value)>> &&
      !is_same_v<bool, remove_cvref_t<decltype(T::value)>> &&
      @\exposconcept{constexpr-wrapper-like}@<T>;

  template<class T>
    constexpr size_t @\defexposconcept{maybe-static-ext}@ = dynamic_extent; // \expos
  template<@\exposconcept{integral-constant-like}@ T>
    constexpr size_t @\exposconcept{maybe-static-ext}@<T> = {T::value};

  // \ref{views.span}, class template \tcode{span}
  template<class ElementType, size_t Extent = dynamic_extent>
    class span;                                                             // partially freestanding

  template<class ElementType, size_t Extent>
    constexpr bool ranges::@\libspec{enable_view}{span}@<span<ElementType, Extent>> = true;
  template<class ElementType, size_t Extent>
    constexpr bool ranges::@\libspec{enable_borrowed_range}{span}@<span<ElementType, Extent>> = true;

  // \ref{span.objectrep}, views of object representation
  template<class ElementType, size_t Extent>
    span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>
      as_bytes(span<ElementType, Extent> s) noexcept;

  template<class ElementType, size_t Extent>
    span<byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>
      as_writable_bytes(span<ElementType, Extent> s) noexcept;
}
\end{codeblock}

\rSec3[views.span]{Class template \tcode{span}}

\rSec4[span.overview]{Overview}

\pnum
\indexlibraryglobal{span}%
A \tcode{span} is a view over a contiguous sequence of objects,
the storage of which is owned by some other object.

\pnum
All member functions of \tcode{span} have constant time complexity.

\indexlibraryglobal{span}%
\begin{codeblock}
namespace std {
  template<class ElementType, size_t Extent = dynamic_extent>
  class span {
  public:
    // constants and types
    using element_type = ElementType;
    using value_type = remove_cv_t<ElementType>;
    using size_type = size_t;
    using difference_type = ptrdiff_t;
    using pointer = element_type*;
    using const_pointer = const element_type*;
    using reference = element_type&;
    using const_reference = const element_type&;
    using iterator = @\impdefx{type of \tcode{span::iterator}}@;        // see \ref{span.iterators}
    using const_iterator = std::const_iterator<iterator>;
    using reverse_iterator = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::const_iterator<reverse_iterator>;
    static constexpr size_type extent = Extent;

    // \ref{span.cons}, constructors, copy, and assignment
    constexpr span() noexcept;
    template<class It>
      constexpr explicit(extent != dynamic_extent) span(It first, size_type count);
    template<class It, class End>
      constexpr explicit(extent != dynamic_extent) span(It first, End last);
    template<size_t N>
      constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept;
    template<class T, size_t N>
      constexpr span(array<T, N>& arr) noexcept;
    template<class T, size_t N>
      constexpr span(const array<T, N>& arr) noexcept;
    template<class R>
      constexpr explicit(extent != dynamic_extent) span(R&& r);
    constexpr span(const span& other) noexcept = default;
    template<class OtherElementType, size_t OtherExtent>
      constexpr explicit(@\seebelow@) span(const span<OtherElementType, OtherExtent>& s) noexcept;

    constexpr span& operator=(const span& other) noexcept = default;

    // \ref{span.sub}, subviews
    template<size_t Count>
      constexpr span<element_type, Count> first() const;
    template<size_t Count>
      constexpr span<element_type, Count> last() const;
    template<size_t Offset, size_t Count = dynamic_extent>
      constexpr span<element_type, @\seebelow@> subspan() const;

    constexpr span<element_type, dynamic_extent> first(size_type count) const;
    constexpr span<element_type, dynamic_extent> last(size_type count) const;
    constexpr span<element_type, dynamic_extent> subspan(
      size_type offset, size_type count = dynamic_extent) const;

    // \ref{span.obs}, observers
    constexpr size_type size() const noexcept;
    constexpr size_type size_bytes() const noexcept;
    constexpr bool empty() const noexcept;

    // \ref{span.elem}, element access
    constexpr reference operator[](size_type idx) const;
    constexpr reference at(size_type idx) const;                            // freestanding-deleted
    constexpr reference front() const;
    constexpr reference back() const;
    constexpr pointer data() const noexcept;

    // \ref{span.iterators}, iterator support
    constexpr iterator begin() const noexcept;
    constexpr iterator end() const noexcept;
    constexpr const_iterator cbegin() const noexcept { return begin(); }
    constexpr const_iterator cend() const noexcept { return end(); }
    constexpr reverse_iterator rbegin() const noexcept;
    constexpr reverse_iterator rend() const noexcept;
    constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
    constexpr const_reverse_iterator crend() const noexcept { return rend(); }

  private:
    pointer @\exposid{data_}@;              // \expos
    size_type @\exposid{size_}@;            // \expos
  };

  template<class It, class EndOrSize>
    span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>,
                                @\exposconcept{maybe-static-ext}@<EndOrSize>>;
  template<class T, size_t N>
    span(T (&)[N]) -> span<T, N>;
  template<class T, size_t N>
    span(array<T, N>&) -> span<T, N>;
  template<class T, size_t N>
    span(const array<T, N>&) -> span<const T, N>;
  template<class R>
    span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>;
}
\end{codeblock}

\pnum
\tcode{span<ElementType, Extent>} is
a trivially copyable type\iref{term.trivially.copyable.type}.

\pnum
\tcode{ElementType} is required to be
a complete object type that is not an abstract class type.

\pnum
For a \tcode{span} \tcode{s},
any operation that invalidates a pointer in
the range \range{s.data()}{s.data() + s.size()}
invalidates pointers, iterators, and references to elements of \tcode{s}.

\rSec4[span.cons]{Constructors, copy, and assignment}

\indexlibraryctor{span}%
\begin{itemdecl}
constexpr span() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{Extent == dynamic_extent || Extent == 0} is \tcode{true}.

\pnum
\ensures
%FIXME: Should "is \tcode{true}" be appended here?
\tcode{size() == 0 \&\& data() == nullptr}.
\end{itemdescr}

\indexlibraryctor{span}%
\begin{itemdecl}
template<class It>
  constexpr explicit(extent != dynamic_extent) span(It first, size_type count);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
Let \tcode{U} be \tcode{remove_reference_t<iter_reference_t<It>>}.
\begin{itemize}
\item \tcode{It} satisfies \libconcept{contiguous_iterator}.
\item
\tcode{is_convertible_v<U(*)[], element_type(*)[]>} is \tcode{true}.
\begin{note}
The intent is to allow only qualification conversions
of the iterator reference type to \tcode{element_type}.
\end{note}
\end{itemize}

\pnum
\expects
\begin{itemize}
\item \range{first}{first + count} is a valid range.
\item \tcode{It} models \libconcept{contiguous_iterator}.
\end{itemize}

\pnum
\hardexpects
If \tcode{extent} is not equal to \tcode{dynamic_extent},
then \tcode{count == extent} is \tcode{true}.

\pnum
\effects
Initializes \exposid{data_} with \tcode{to_address(first)} and
\exposid{size_} with \tcode{count}.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibraryctor{span}%
\begin{itemdecl}
template<class It, class End>
  constexpr explicit(extent != dynamic_extent) span(It first, End last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
Let \tcode{U} be \tcode{remove_reference_t<iter_reference_t<It>>}.
\begin{itemize}
\item
\tcode{is_convertible_v<U(*)[], element_type(*)[]>} is \tcode{true}.
\begin{note}
The intent is to allow only qualification conversions
of the iterator reference type to \tcode{element_type}.
\end{note}
\item \tcode{It} satisfies \libconcept{contiguous_iterator}.
\item \tcode{End} satisfies \tcode{\libconcept{sized_sentinel_for}<It>}.
\item \tcode{is_convertible_v<End, size_t>} is \tcode{false}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item \range{first}{last} is a valid range.
\item \tcode{It} models \libconcept{contiguous_iterator}.
\item \tcode{End} models \tcode{\libconcept{sized_sentinel_for}<It>}.
\end{itemize}

\pnum
\hardexpects
If \tcode{extent} is not equal to \tcode{dynamic_extent},
then \tcode{(last - first) == extent} is \tcode{true}.

\pnum
\effects
Initializes \exposid{data_} with \tcode{to_address(first)} and
\exposid{size_} with \tcode{last - first}.

\pnum
\throws
When and what \tcode{last - first} throws.
\end{itemdescr}

\indexlibraryctor{span}%
\begin{itemdecl}
template<size_t N> constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept;
template<class T, size_t N> constexpr span(array<T, N>& arr) noexcept;
template<class T, size_t N> constexpr span(const array<T, N>& arr) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
Let \tcode{U} be \tcode{remove_pointer_t<decltype(std::data(arr))>}.
\begin{itemize}
\item \tcode{extent == dynamic_extent || N == extent} is \tcode{true}, and
\item \tcode{is_convertible_v<U(*)[], element_type(*)[]>} is \tcode{true}.
\begin{note}
The intent is to allow only qualification conversions
of the array element type to \tcode{element_type}.
\end{note}
\end{itemize}

\pnum
\effects
Constructs a \tcode{span} that is a view over the supplied array.
\begin{note}
\tcode{type_identity_t} affects class template argument deduction.
\end{note}

\pnum
\ensures
\tcode{size() == N \&\& data() == std::data(arr)} is \tcode{true}.
\end{itemdescr}

\indexlibraryctor{span}%
\begin{itemdecl}
template<class R> constexpr explicit(extent != dynamic_extent) span(R&& r);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
Let \tcode{U} be \tcode{remove_reference_t<ranges::range_reference_t<R>>}.
\begin{itemize}
\item \tcode{R} satisfies \tcode{ranges::\libconcept{contiguous_range}} and
  \tcode{ranges::\libconcept{sized_range}}.
\item Either \tcode{R} satisfies \tcode{ranges::\libconcept{borrowed_range}} or
\tcode{is_const_v<element_type>} is \tcode{true}.
\item \tcode{remove_cvref_t<R>} is not a specialization of \tcode{span}.
\item \tcode{remove_cvref_t<R>} is not a specialization of \tcode{array}.
\item \tcode{is_array_v<remove_cvref_t<R>>} is \tcode{false}.
\item
\tcode{is_convertible_v<U(*)[], element_type(*)[]>} is \tcode{true}.
\begin{note}
The intent is to allow only qualification conversions
of the range reference type to \tcode{element_type}.
\end{note}
\end{itemize}

\pnum
\expects
\begin{itemize}
\item \tcode{R} models \tcode{ranges::\libconcept{contiguous_range}} and
\tcode{ranges::\libconcept{sized_range}}.
\item If \tcode{is_const_v<element_type>} is \tcode{false},
\tcode{R} models \tcode{ranges::\libconcept{borrowed_range}}.
\end{itemize}

\pnum
\hardexpects
If \tcode{extent} is not equal to \tcode{dynamic_extent},
then \tcode{ranges::size(r) == extent} is \tcode{true}.

\pnum
\effects
Initializes \exposid{data_} with \tcode{ranges::data(r)} and
\exposid{size_} with \tcode{ranges::size(r)}.

\pnum
\throws
What and when \tcode{ranges::data(r)} and \tcode{ranges::size(r)} throw.
\end{itemdescr}

\indexlibraryctor{span}%
\begin{itemdecl}
constexpr span(const span& other) noexcept = default;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{other.size() == size() \&\& other.data() == data()}.
\end{itemdescr}

\indexlibraryctor{span}%
\begin{itemdecl}
template<class OtherElementType, size_t OtherExtent>
  constexpr explicit(@\seebelow@) span(const span<OtherElementType, OtherExtent>& s) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item \tcode{extent == dynamic_extent} \tcode{||} \tcode{OtherExtent == dynamic_extent} \tcode{||} \tcode{extent == OtherExtent} is \tcode{true}, and
\item \tcode{is_convertible_v<OtherElementType(*)[], element_type(*)[]>} is \tcode{true}.
\begin{note}
The intent is to allow only qualification conversions
of the \tcode{OtherElementType} to \tcode{element_type}.
\end{note}
\end{itemize}

\pnum
\hardexpects
If \tcode{extent} is not equal to \tcode{dynamic_extent},
then \tcode{s.size() == extent} is \tcode{true}.

\pnum
\effects
Constructs a \tcode{span} that is a view over the range
\range{s.data()}{s.data() + s.size()}.

\pnum
\ensures
\tcode{size() == s.size() \&\& data() == s.data()}.

\pnum
\remarks
The expression inside \keyword{explicit} is equivalent to:
\begin{codeblock}
extent != dynamic_extent && OtherExtent == dynamic_extent
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator=}{span}%
\begin{itemdecl}
constexpr span& operator=(const span& other) noexcept = default;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{size() == other.size() \&\& data() == other.data()}.
\end{itemdescr}

\rSec4[span.deduct]{Deduction guides}

\indexlibrary{\idxcode{span}!deduction guide}%
\begin{itemdecl}
template<class It, class EndOrSize>
  span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>,
                              @\exposconcept{maybe-static-ext}@<EndOrSize>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{It} satisfies \libconcept{contiguous_iterator}.
\end{itemdescr}

\indexlibrary{\idxcode{span}!deduction guide}%
\begin{itemdecl}
template<class R>
  span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{R} satisfies \tcode{ranges::\libconcept{contiguous_range}}.
\end{itemdescr}

\rSec4[span.sub]{Subviews}

\indexlibrarymember{span}{first}%
\begin{itemdecl}
template<size_t Count> constexpr span<element_type, Count> first() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{Count <= Extent} is \tcode{true}.

\pnum
\hardexpects
\tcode{Count <= size()} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return R(data(), Count);}
where \tcode{R} is the return type.
\end{itemdescr}

\indexlibrarymember{span}{last}%
\begin{itemdecl}
template<size_t Count> constexpr span<element_type, Count> last() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{Count <= Extent} is \tcode{true}.

\pnum
\hardexpects
\tcode{Count <= size()} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return R(data() + (size() - Count), Count);}
where \tcode{R} is the return type.
\end{itemdescr}

\indexlibrarymember{span}{subspan}%
\begin{itemdecl}
template<size_t Offset, size_t Count = dynamic_extent>
  constexpr span<element_type, @\seebelow@> subspan() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\begin{codeblock}
Offset <= Extent && (Count == dynamic_extent || Count <= Extent - Offset)
\end{codeblock}
is \tcode{true}.

\pnum
\hardexpects
\begin{codeblock}
Offset <= size() && (Count == dynamic_extent || Count <= size() - Offset)
\end{codeblock}
is \tcode{true}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
return span<ElementType, @\seebelow@>(
  data() + Offset, Count != dynamic_extent ? Count : size() - Offset);
\end{codeblock}

\pnum
\remarks
The second template argument of the returned \tcode{span} type is:
\begin{codeblock}
Count != dynamic_extent ? Count
                        : (Extent != dynamic_extent ? Extent - Offset
                                                    : dynamic_extent)
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{span}{first}%
\begin{itemdecl}
constexpr span<element_type, dynamic_extent> first(size_type count) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\hardexpects
\tcode{count <= size()} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return R(data(), count);}
where \tcode{R} is the return type.
\end{itemdescr}

\indexlibrarymember{span}{last}%
\begin{itemdecl}
constexpr span<element_type, dynamic_extent> last(size_type count) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\hardexpects
\tcode{count <= size()} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return R(data() + (size() - count), count);}
where \tcode{R} is the return type.
\end{itemdescr}

\indexlibrarymember{span}{subspan}%
\begin{itemdecl}
constexpr span<element_type, dynamic_extent> subspan(
  size_type offset, size_type count = dynamic_extent) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\hardexpects
\begin{codeblock}
offset <= size() && (count == dynamic_extent || count <= size() - offset)
\end{codeblock}
is \tcode{true}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
return R(data() + offset, count == dynamic_extent ? size() - offset : count);
\end{codeblock}
where \tcode{R} is the return type.
\end{itemdescr}

\rSec4[span.obs]{Observers}

\indexlibrarymember{span}{size}%
\begin{itemdecl}
constexpr size_type size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return \exposid{size_};}
\end{itemdescr}

\indexlibrarymember{span}{size_bytes}%
\begin{itemdecl}
constexpr size_type size_bytes() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return size() * sizeof(element_type);}
\end{itemdescr}

\indexlibrarymember{span}{empty}%
\begin{itemdecl}
constexpr bool empty() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return size() == 0;}
\end{itemdescr}

\rSec4[span.elem]{Element access}

\indexlibrary{\idxcode{operator[]}!\idxcode{span}}%
\begin{itemdecl}
constexpr reference operator[](size_type idx) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\hardexpects
\tcode{idx < size()} is \tcode{true}.

\pnum
\returns
\tcode{*(data() + idx)}.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{span}{at}%
\begin{itemdecl}
constexpr reference at(size_type idx) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{*(data() + idx)}.

\pnum
\throws
\tcode{out_of_range} if \tcode{idx >= size()} is \tcode{true}.
\end{itemdescr}

\indexlibrarymember{span}{front}%
\begin{itemdecl}
constexpr reference front() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\hardexpects
\tcode{empty()} is \tcode{false}.

\pnum
\returns
\tcode{*data()}.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{span}{back}%
\begin{itemdecl}
constexpr reference back() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\hardexpects
\tcode{empty()} is \tcode{false}.

\pnum
\returns
\tcode{*(data() + (size() - 1))}.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{span}{data}%
\begin{itemdecl}
constexpr pointer data() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{data_}.
\end{itemdescr}

\rSec4[span.iterators]{Iterator support}

\indexlibrarymember{iterator}{span}%
\begin{itemdecl}
using iterator = @\impdefx{type of \tcode{span::iterator}}@;
\end{itemdecl}

\begin{itemdescr}
\pnum
The type
models \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous},
meets the \oldconcept{RandomAccessIterator}
requirements\iref{random.access.iterators},
and
meets the requirements for
constexpr iterators\iref{iterator.requirements.general},
whose value type is \tcode{value_type} and
whose reference type is \tcode{reference}.

\pnum
All requirements on container iterators\iref{container.reqmts} apply to
\tcode{span::iterator} as well.
\end{itemdescr}

\indexlibrarymember{span}{begin}%
\begin{itemdecl}
constexpr iterator begin() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An iterator referring to the first element in the span.
If \tcode{empty()} is \tcode{true}, then it returns the
same value as \tcode{end()}.
\end{itemdescr}

\indexlibrarymember{span}{end}%
\begin{itemdecl}
constexpr iterator end() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An iterator which is the past-the-end value.
\end{itemdescr}

\indexlibrarymember{span}{rbegin}%
\begin{itemdecl}
constexpr reverse_iterator rbegin() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return reverse_iterator(end());}
\end{itemdescr}

\indexlibrarymember{span}{rend}%
\begin{itemdecl}
constexpr reverse_iterator rend() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return reverse_iterator(begin());}
\end{itemdescr}

\rSec3[span.objectrep]{Views of object representation}

\indexlibraryglobal{as_bytes}%
\begin{itemdecl}
template<class ElementType, size_t Extent>
  span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>
    as_bytes(span<ElementType, Extent> s) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_volatile_v<ElementType>} is \tcode{false}.

\pnum
\effects
Equivalent to: \tcode{return R\{reinterpret_cast<const byte*>(s.data()), s.size_bytes()\};}
where \tcode{R} is the return type.
\end{itemdescr}

\indexlibraryglobal{as_writable_bytes}%
\begin{itemdecl}
template<class ElementType, size_t Extent>
  span<byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>
    as_writable_bytes(span<ElementType, Extent> s) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_const_v<ElementType>} is \tcode{false} and
\tcode{is_volatile_v<ElementType>} is \tcode{false}.

\pnum
\effects
Equivalent to: \tcode{return R\{reinterpret_cast<byte*>(s.data()), s.size_bytes()\};}
where \tcode{R} is the return type.
\end{itemdescr}

\rSec2[views.multidim]{Multidimensional access}

\rSec3[mdspan.overview]{Overview}

\pnum
A \defnadj{multidimensional}{index space} is
a Cartesian product of integer intervals.
Each interval can be represented by a half-open range $[L_i, U_i)$,
where $L_i$ and $U_i$ are the lower and upper bounds of
the $i^\text{th}$ dimension.
The \defn{rank} of a multidimensional index space is
the number of intervals it represents.
The \defn{size of a multidimensional index space} is
the product of $U_i - L_i$ for each dimension $i$
if its rank is greater than 0, and 1 otherwise.

\pnum
An integer $r$ is a \defn{rank index} of an index space $S$
if $r$ is in the range $[0, \text{rank of $S$})$.

\pnum
A pack of integers \tcode{idx} is
a \defnadj{multidimensional}{index} in a multidimensional index space $S$
(or representation thereof) if both of the following are true:
\begin{itemize}
\item
\tcode{sizeof...(idx)} is equal to the rank of $S$, and
\item
for every rank index $i$ of $S$,
the $i^\text{th}$ value of \tcode{idx} is an integer
in the interval $[L_i, U_i)$ of $S$.
\end{itemize}

\rSec3[mdspan.syn]{Header \tcode{<mdspan>} synopsis}

\indexheader{mdspan}%
\begin{codeblock}
// mostly freestanding
namespace std {
  // \ref{mdspan.extents}, class template \tcode{extents}
  template<class IndexType, size_t... Extents>
    class extents;

  // \ref{mdspan.extents.dextents}, alias template \tcode{dextents}
  template<class IndexType, size_t Rank>
    using dextents = @\seebelow@;

  // \ref{mdspan.extents.dims}, alias template \tcode{dims}
  template<size_t Rank, class IndexType = size_t>
    using dims = @\seebelow@;

  // \ref{mdspan.layout}, layout mapping
  struct layout_left;
  struct layout_right;
  struct layout_stride;
  template<size_t PaddingValue = dynamic_extent>
    struct layout_left_padded;
  template<size_t PaddingValue = dynamic_extent>
    struct layout_right_padded;

  // \ref{mdspan.accessor.default}, class template \tcode{default_accessor}
  template<class ElementType>
    class default_accessor;

  // \ref{mdspan.accessor.aligned}, class template \tcode{aligned_accessor}
  template<class ElementType, size_t ByteAlignment>
    class aligned_accessor;

  // \ref{mdspan.mdspan}, class template \tcode{mdspan}
  template<class ElementType, class Extents, class LayoutPolicy = layout_right,
           class AccessorPolicy = default_accessor<ElementType>>
    class mdspan;                                                           // partially freestanding

  // \ref{mdspan.sub}, \tcode{submdspan} creation
  template<class OffsetType, class LengthType, class StrideType>
    struct extent_slice;
  template<class FirstType, class LastType, class StrideType = constant_wrapper<1zu>>
    struct range_slice;

  template<class LayoutMapping>
    struct submdspan_mapping_result;

  struct @\libglobal{full_extent_t}@ { explicit full_extent_t() = default; };
  inline constexpr full_extent_t @\libglobal{full_extent}@{};

  template<class IndexType, size_t... Extents, class... SliceSpecifiers>
    constexpr auto subextents(const extents<IndexType, Extents...>&, SliceSpecifiers...);

  // \ref{mdspan.sub.canonical}, \tcode{submdspan} slice canonicalization
  template<class IndexType, size_t... Extents, class... SliceSpecifiers>
    constexpr auto canonical_slices(const extents<IndexType, Extents...>& src,
                                    SliceSpecifiers... slices);

  // \ref{mdspan.sub.sub}, \tcode{submdspan} function template
  template<class ElementType, class Extents, class LayoutPolicy,
           class AccessorPolicy, class... SliceSpecifiers>
    constexpr auto submdspan(
      const mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& src,
      SliceSpecifiers... raw_slices) -> @\seebelow@;

  template<class T, class IndexType>
    concept @\defexposconcept{index-pair-like}@ =               // \expos
      @\exposconcept{pair-like}@<T> &&
      @\libconcept{convertible_to}@<tuple_element_t<0, T>, IndexType> &&
      @\libconcept{convertible_to}@<tuple_element_t<1, T>, IndexType>;
}
\end{codeblock}

\rSec3[mdspan.extents]{Class template \tcode{extents}}

\rSec4[mdspan.extents.overview]{Overview}

The class template \tcode{extents} represents
a multidimensional index space of rank equal to \tcode{sizeof...(Extents)}.
In~\ref{views},
\tcode{extents} is used synonymously with multidimensional index space.

\begin{codeblock}
namespace std {
  template<class IndexType, size_t... Extents>
  class @\libglobal{extents}@ {
  public:
    using @\libmember{index_type}{extents}@ = IndexType;
    using @\libmember{size_type}{extents}@ = make_unsigned_t<index_type>;
    using @\libmember{rank_type}{extents}@ = size_t;

    // \ref{mdspan.extents.obs}, observers of the multidimensional index space
    static constexpr rank_type @\libmember{rank}{extents}@() noexcept { return sizeof...(Extents); }
    static constexpr rank_type @\libmember{rank_dynamic}{extents}@() noexcept { return @\exposid{dynamic-index}@(rank()); }
    static constexpr size_t static_extent(rank_type) noexcept;
    constexpr index_type extent(rank_type) const noexcept;

    // \ref{mdspan.extents.cons}, constructors
    constexpr extents() noexcept = default;

    template<class OtherIndexType, size_t... OtherExtents>
      constexpr explicit(@\seebelow@)
        extents(const extents<OtherIndexType, OtherExtents...>&) noexcept;
    template<class... OtherIndexTypes>
      constexpr explicit extents(OtherIndexTypes...) noexcept;
    template<class OtherIndexType, size_t N>
      constexpr explicit(N != rank_dynamic())
        extents(span<OtherIndexType, N>) noexcept;
    template<class OtherIndexType, size_t N>
      constexpr explicit(N != rank_dynamic())
        extents(const array<OtherIndexType, N>&) noexcept;

    // \ref{mdspan.extents.cmp}, comparison operators
    template<class OtherIndexType, size_t... OtherExtents>
      friend constexpr bool operator==(const extents&,
                                       const extents<OtherIndexType, OtherExtents...>&) noexcept;

    // \ref{mdspan.extents.expo}, exposition-only helpers
    constexpr size_t @\exposid{fwd-prod-of-extents}@(rank_type) const noexcept;     // \expos
    constexpr size_t @\exposid{rev-prod-of-extents}@(rank_type) const noexcept;     // \expos
    template<class OtherIndexType>
      static constexpr auto @\exposid{index-cast}@(OtherIndexType&&) noexcept;      // \expos

  private:
    static constexpr rank_type @\exposid{dynamic-index}@(rank_type) noexcept;       // \expos
    static constexpr rank_type @\exposid{dynamic-index-inv}@(rank_type) noexcept;   // \expos
    array<index_type, rank_dynamic()> @\exposid{dynamic-extents}@{};                // \expos
  };

  template<class... Integrals>
    explicit extents(Integrals...)
      -> @\seebelow@;
}
\end{codeblock}

\pnum
\mandates
\begin{itemize}
\item
\tcode{IndexType} is a signed or unsigned integer type, and
\item
each element of \tcode{Extents} is either equal to \tcode{dynamic_extent}, or
is representable as a value of type \tcode{IndexType}.
\end{itemize}

\pnum
Each specialization of \tcode{extents} models \libconcept{regular} and
is trivially copyable.

\pnum
Let $E_r$ be the $r^\text{th}$ element of \tcode{Extents}.
$E_r$ is a \defnadj{dynamic}{extent} if it is equal to \tcode{dynamic_extent},
otherwise $E_r$ is a \defnadj{static}{extent}.
Let $D_r$ be the value of \tcode{\exposid{dynamic-extents}[\exposid{dynamic-index}($r$)]}
if $E_r$ is a dynamic extent,
otherwise $E_r$.

\pnum
The $r^\text{th}$ interval of the multidimensional index space
represented by an \tcode{extents} object is $[0, D_r)$.

\rSec4[mdspan.extents.expo]{Exposition-only helpers}

\begin{itemdecl}
static constexpr rank_type @\exposid{dynamic-index}@(rank_type i) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{i <= rank()} is \tcode{true}.

\pnum
\returns
The number of $E_r$ with $r < \tcode{i}$ for which $E_r$ is a dynamic extent.
\end{itemdescr}

\begin{itemdecl}
static constexpr rank_type @\exposid{dynamic-index-inv}@(rank_type i) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{i < rank_dynamic()} is \tcode{true}.

\pnum
\returns
The minimum value of $r$
such that \tcode{\exposid{dynamic-index}($r$ + 1) == i + 1} is \tcode{true}.
\end{itemdescr}

\begin{itemdecl}
constexpr size_t @\exposid{fwd-prod-of-extents}@(rank_type i) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{i <= rank()} is \tcode{true}.

\pnum
\returns
If \tcode{i > 0} is \tcode{true},
the product of \tcode{extent($k$)} for all $k$ in the range $[0, \tcode{i})$,
otherwise \tcode{1}.
\end{itemdescr}

\begin{itemdecl}
constexpr size_t @\exposid{rev-prod-of-extents}@(rank_type i) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{i < rank()} is \tcode{true}.

\pnum
\returns
If \tcode{i + 1 < rank()} is \tcode{true},
the product of \tcode{extent($k$)}
for all $k$ in the range $[\tcode{i + 1}, \tcode{rank()})$,
otherwise \tcode{1}.
\end{itemdescr}

\begin{itemdecl}
template<class OtherIndexType>
  static constexpr auto @\exposid{index-cast}@(OtherIndexType&& i) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\begin{itemize}
\item
If \tcode{remove_cvref_t<OtherIndexType>} is an integral type other than \tcode{bool},
then equivalent to \tcode{return i;},
\item
otherwise, equivalent to \tcode{return static_cast<index_type>(std::forward<OtherIndexType>(\brk{}i));}.
\end{itemize}
\begin{note}
This function will always return an integral type other than \tcode{bool}.
Since this function's call sites are constrained on
convertibility of \tcode{OtherIndexType} to \tcode{index_type},
integer-class types can use the \tcode{static_cast} branch
without loss of precision.
\end{note}
\end{itemdescr}

\rSec4[mdspan.extents.cons]{Constructors}

\indexlibraryctor{extents}%
\begin{itemdecl}
template<class OtherIndexType, size_t... OtherExtents>
  constexpr explicit(@\seebelow@)
    extents(const extents<OtherIndexType, OtherExtents...>& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{sizeof...(OtherExtents) == rank()} is \tcode{true}.
\item
\tcode{((OtherExtents == dynamic_extent || Extents == dynamic_extent || OtherExtents ==\newline Extents) \&\& ...)} is \tcode{true}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{other.extent($r$)} equals $E_r$
for each $r$ for which $E_r$ is a static extent, and
\item
either
\begin{itemize}
\item
\tcode{sizeof...(OtherExtents)} is zero, or
\item
\tcode{other.extent($r$)} is representable as
a value of type \tcode{index_type} for every rank index $r$ of \tcode{other}.
\end{itemize}
\end{itemize}

\pnum
\ensures
\tcode{*this == other} is \tcode{true}.

\pnum
\remarks
The expression inside \tcode{explicit} is equivalent to:
\begin{codeblock}
(((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ... ) ||
(numeric_limits<index_type>::max() < numeric_limits<OtherIndexType>::max())
\end{codeblock}
\end{itemdescr}

\indexlibraryctor{extents}%
\begin{itemdecl}
template<class... OtherIndexTypes>
  constexpr explicit extents(OtherIndexTypes... exts) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{N} be \tcode{sizeof...(OtherIndexTypes)},
and let \tcode{exts_arr} be
\tcode{array<index_type, N>\{static_cast<\\index_type>(std::move(exts))...\}}.

\pnum
\constraints
\begin{itemize}
\item
\tcode{(is_convertible_v<OtherIndexTypes, index_type> \&\& ...)} is \tcode{true},
\item
\tcode{(is_nothrow_constructible_v<index_type, OtherIndexTypes> \&\& ...)} is \tcode{true}, and
\item
\tcode{N == rank_dynamic() || N == rank()} is \tcode{true}.
\begin{note}
One can construct \tcode{extents} from just dynamic extents,
which are all the values getting stored, or
from all the extents with a precondition.
\end{note}
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
If \tcode{N != rank_dynamic()} is \tcode{true},
\tcode{exts_arr[$r$]} equals $E_r$
for each $r$ for which $E_r$ is a static extent, and
\item
either
\begin{itemize}
\item
\tcode{sizeof...(exts) == 0} is \tcode{true}, or
\item
each element of \tcode{exts} is representable
as a nonnegative value of type \tcode{index_type}.
\end{itemize}
\end{itemize}

\pnum
\ensures
\tcode{*this == extents(exts_arr)} is \tcode{true}.
\end{itemdescr}

\indexlibraryctor{extents}%
\begin{itemdecl}
template<class OtherIndexType, size_t N>
  constexpr explicit(N != rank_dynamic())
    extents(span<OtherIndexType, N> exts) noexcept;
template<class OtherIndexType, size_t N>
  constexpr explicit(N != rank_dynamic())
    extents(const array<OtherIndexType, N>& exts) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const OtherIndexType\&, index_type>} is \tcode{true},
\item
\tcode{is_nothrow_constructible_v<index_type, const OtherIndexType\&>} is \tcode{true}, and
\item
\tcode{N == rank_dynamic() || N == rank()} is \tcode{true}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
If \tcode{N != rank_dynamic()} is \tcode{true},
\tcode{exts[$r$]} equals $E_r$ for each $r$ for which $E_r$ is a static extent, and
\item
either
\begin{itemize}
\item
\tcode{N} is zero, or
\item
\tcode{exts[$r$]} is representable
as a nonnegative value of type \tcode{index_type} for every rank index $r$.
\end{itemize}
\end{itemize}

\pnum
\effects
\begin{itemize}
\item
If \tcode{N} equals \tcode{rank_dynamic()},
for all $d$ in the range $[0, \tcode{rank_dynamic()})$,
direct-non-list-initializes \tcode{\exposidnc{dynamic-extents}[$d$]}
with \tcode{as_const(exts[$d$])}.
\item
Otherwise, for all $d$ in the range $[0, \tcode{rank_dynamic()})$,
direct-non-list-initializes \exposidnc{dynamic-ex\-tents}\tcode{[$d$]}
with \tcode{as_const(exts[\exposidnc{dynamic-index-inv}($d$)])}.
\end{itemize}
\end{itemdescr}

\indexlibraryctor{extents}%
\begin{itemdecl}
template<class... Integrals>
  explicit extents(Integrals...) -> @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{(is_convertible_v<Integrals, size_t> \&\& ...)} is \tcode{true}.

\pnum
\remarks
The deduced type is \tcode{extents<size_t, \exposconcept{maybe-static-ext}<Integrals>...>}.
\end{itemdescr}

\rSec4[mdspan.extents.obs]{Observers of the multidimensional index space}

\indexlibrarymember{static_extent}{extents}%
\begin{itemdecl}
static constexpr size_t static_extent(rank_type i) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{i < rank()} is \tcode{true}.

\pnum
\returns
$E_\tcode{i}$.
\end{itemdescr}

\indexlibrarymember{extent}{extents}%
\begin{itemdecl}
constexpr index_type extent(rank_type i) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{i < rank()} is \tcode{true}.

\pnum
\returns
$D_\tcode{i}$.
\end{itemdescr}

\rSec4[mdspan.extents.cmp]{Comparison operators}

\indexlibrarymember{operator==}{extents}%
\begin{itemdecl}
template<class OtherIndexType, size_t... OtherExtents>
  friend constexpr bool operator==(const extents& lhs,
                                   const extents<OtherIndexType, OtherExtents...>& rhs) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if \tcode{lhs.rank()} equals \tcode{rhs.rank()} and
if \tcode{lhs.extent(r)} equals \tcode{rhs.extent(r)}
for every rank index \tcode{r} of \tcode{rhs},
otherwise \tcode{false}.
\end{itemdescr}

\rSec4[mdspan.extents.dextents]{Alias template \tcode{dextents}}

\indexlibraryglobal{dextents}%
\begin{itemdecl}
template<class IndexType, size_t Rank>
  using dextents = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A type \tcode{E} that is a specialization of \tcode{extents}
such that \tcode{E::rank() == Rank \&\& E::rank() == E::rank_dynamic()} is \tcode{true}, and
\tcode{E::index_type} denotes \tcode{IndexType}.
\end{itemdescr}

\rSec4[mdspan.extents.dims]{Alias template \tcode{dims}}

\indexlibraryglobal{dims}%
\begin{itemdecl}
template<size_t Rank, class IndexType = size_t>
  using dims = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A type \tcode{E} that is a specialization of \tcode{extents}
such that \tcode{E::rank() == Rank \&\& E::rank() == E::rank_dynamic()} is \tcode{true}, and
\tcode{E::index_type} denotes \tcode{IndexType}.
\end{itemdescr}

\rSec3[mdspan.layout]{Layout mapping}

\rSec4[mdspan.layout.general]{General}

\pnum
In \ref{mdspan.layout.reqmts} and \ref{mdspan.layout.policy.reqmts}:

\begin{itemize}
\item
\tcode{M} denotes a layout mapping class.

\item
\tcode{m} denotes a (possibly const) value of type \tcode{M}.

\item
\tcode{i} and \tcode{j} are packs of (possibly const) integers
that are multidimensional indices in \tcode{m.extents()}\iref{mdspan.overview}.
\begin{note}
The type of each element of the packs can be a different integer type.
\end{note}

\item
\tcode{r} is a (possibly const) rank index of \tcode{typename M::extents_type}.

\item
$\tcode{d}_r$ is a pack of (possibly const) integers
for which \tcode{sizeof...($\tcode{d}_r$) == M::extents_type::rank()} is \tcode{true},
the $r^\text{th}$ element is equal to 1, and
all other elements are equal to 0.
\end{itemize}

\pnum
In \ref{mdspan.layout.reqmts} through \ref{mdspan.layout.stride}:
\begin{itemize}
\item
Let \exposid{is-mapping-of} be the exposition-only variable template defined as follows:
\begin{codeblock}
template<class Layout, class Mapping>
constexpr bool @\exposid{is-mapping-of}@ =  // \expos
  is_same_v<typename Layout::template mapping<typename Mapping::extents_type>, Mapping>;
\end{codeblock}
\item
Let \exposid{is-layout-left-padded-mapping-of} be
the exposition-only variable template defined as follows:
\begin{codeblock}
template<class Mapping>
constexpr bool @\exposid{is-layout-left-padded-mapping-of}@ = @\seebelow@;   // \expos
\end{codeblock}
where \tcode{\exposid{is-layout-left-padded-mapping-of}<Mapping>} is \tcode{true}
if and only if \tcode{Mapping} denotes
a specialization of \tcode{layout_left_padded<S>::mapping}
for some value \tcode{S} of type \tcode{size_t}.
\item
Let \exposid{is-layout-right-padded-mapping-of} be
the exposition-only variable template defined as follows:
\begin{codeblock}
template<class Mapping>
constexpr bool @\exposid{is-layout-right-padded-mapping-of}@ = @\seebelow@;   // \expos
\end{codeblock}
where \tcode{\exposid{is-layout-right-padded-mapping-of}<Mapping>} is \tcode{true}
if and only if \tcode{Mapping} denotes
a specialization of \tcode{layout_right_padded<S>::mapping}
for some value \tcode{S} of type \tcode{size_t}.
\item
For nonnegative integers $x$ and $y$,
let $\exposid{LEAST-MULTIPLE-AT-LEAST}(x, y)$ denote
\begin{itemize}
\item
$y$ if $x$ is zero,
\item
otherwise, the least multiple of $x$ that is greater than or equal to $y$.
\end{itemize}
\end{itemize}

\rSec4[mdspan.layout.reqmts]{Requirements}

\pnum
A type \tcode{M} meets the \defn{layout mapping} requirements if

\begin{itemize}
\item
\tcode{M} models \libconcept{copyable} and \libconcept{equality_comparable},
\item
\tcode{is_nothrow_move_constructible_v<M>} is \tcode{true},
\item
\tcode{is_nothrow_move_assignable_v<M>} is \tcode{true},
\item
\tcode{is_nothrow_swappable_v<M>} is \tcode{true}, and
\item
the following types and expressions are well-formed and
have the specified semantics.
\end{itemize}

\begin{itemdecl}
typename M::extents_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A type that is a specialization of \tcode{extents}.
\end{itemdescr}

\begin{itemdecl}
typename M::index_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{typename M::extents_type::index_type}.
\end{itemdescr}

\begin{itemdecl}
typename M::rank_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{typename M::extents_type::rank_type}.
\end{itemdescr}

\begin{itemdecl}
typename M::layout_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A type \tcode{MP} that meets
the layout mapping policy requirements\iref{mdspan.layout.policy.reqmts} and
for which \tcode{\exposid{is-mapping-of}<MP, M>} is \tcode{true}.
\end{itemdescr}

\begin{itemdecl}
m.extents()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{const typename M::extents_type\&}
\end{itemdescr}

\begin{itemdecl}
m(i...)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{typename M::index_type}

\pnum
\returns
A nonnegative integer
less than \tcode{numeric_limits<typename M::index_type>::max()} and
less than or equal to \tcode{numeric_limits<size_t>::max()}.
\end{itemdescr}

\begin{itemdecl}
m(i...) == m(static_cast<typename M::index_type>(i)...)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{bool}

\pnum
\returns
\tcode{true}
\end{itemdescr}

\begin{itemdecl}
m.required_span_size()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{typename M::index_type}

\pnum
\returns
If the size of the multidimensional index space \tcode{m.extents()} is 0,
then \tcode{0},
else \tcode{1} plus the maximum value of \tcode{m(i...)} for all \tcode{i}.
\end{itemdescr}

\begin{itemdecl}
m.is_unique()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{bool}

\pnum
\returns
\tcode{true} only if
for every \tcode{i} and \tcode{j} where \tcode{(i != j || ...)} is \tcode{true},
\tcode{m(i...) != m(j...)} is \tcode{true}.
\begin{note}
A mapping can return \tcode{false} even if the condition is met.
For certain layouts, it is possibly not feasible to determine efficiently
whether the layout is unique.
\end{note}
\end{itemdescr}

\begin{itemdecl}
m.is_exhaustive()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{bool}

\pnum
\returns
\tcode{true} only if
for all $k$ in the range $[0, \tcode{m.required_span_size()})$
there exists an \tcode{i} such that \tcode{m(i...)} equals $k$.
\begin{note}
A mapping can return \tcode{false} even if the condition is met.
For certain layouts, it is possibly not feasible to determine efficiently
whether the layout is exhaustive.
\end{note}
\end{itemdescr}

\begin{itemdecl}
m.is_strided()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{bool}

\pnum
\returns
\tcode{true} only if
for every rank index $r$ of \tcode{m.extents()} there exists an integer $s_r$
such that,
for all \tcode{i} where $(\tcode{i}+d_r)$ is
a multidimensional index in \tcode{m.extents()}\iref{mdspan.overview},
\tcode{m((i + $d_r$)...) - m(i...)} equals $s_r$.
\begin{note}
This implies that for a strided layout
$m(i_0, \dotsc, i_k) = m(0, \dotsc, 0) + i_0 \times s_0 + \dotsb + i_k \times s_k$.
\end{note}
\begin{note}
A mapping can return \tcode{false} even if the condition is met.
For certain layouts, it is possibly not feasible to determine efficiently
whether the layout is strided.
\end{note}
\end{itemdescr}

\begin{itemdecl}
m.stride(r)
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{m.is_strided()} is \tcode{true}.

\pnum
\result
\tcode{typename M::index_type}

\pnum
\returns
$s_r$ as defined in \tcode{m.is_strided()} above.

\pnum
\begin{note}
It is not required for \tcode{m.stride(r)} to be well-formed
if \tcode{m.extents().rank()} is zero,
even if \tcode{m.is_always_strided()} is \tcode{true}.
\end{note}
\end{itemdescr}

\begin{itemdecl}
M::is_always_unique()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A constant expression\iref{expr.const.const} of type \tcode{bool}.

\pnum
\returns
\tcode{true} only if \tcode{m.is_unique()} is \tcode{true}
for all possible objects \tcode{m} of type \tcode{M}.
\begin{note}
A mapping can return \tcode{false} even if the above condition is met.
For certain layout mappings, it is possibly not feasible to determine
whether every instance is unique.
\end{note}
\end{itemdescr}

\begin{itemdecl}
M::is_always_exhaustive()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A constant expression\iref{expr.const.const} of type \tcode{bool}.

\pnum
\returns
\tcode{true} only if \tcode{m.is_exhaustive()} is \tcode{true}
for all possible objects \tcode{m} of type \tcode{M}.
\begin{note}
A mapping can return \tcode{false} even if the above condition is met.
For certain layout mappings, it is possibly not feasible to determine
whether every instance is exhaustive.
\end{note}
\end{itemdescr}

\begin{itemdecl}
M::is_always_strided()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A constant expression\iref{expr.const.const} of type \tcode{bool}.

\pnum
\returns
\tcode{true} only if \tcode{m.is_strided()} is \tcode{true}
for all possible objects \tcode{m} of type \tcode{M}.
\begin{note}
A mapping can return \tcode{false} even if the above condition is met.
For certain layout mappings, it is possibly not feasible to determine
whether every instance is strided.
\end{note}
\end{itemdescr}

\rSec4[mdspan.layout.policy.reqmts]{Layout mapping policy requirements}

\pnum
A type \tcode{MP} meets the \defn{layout mapping policy} requirements
if for a type \tcode{E} that is a specialization of \tcode{extents},
\tcode{MP::mapping<E>} is valid and denotes a type \tcode{X}
that meets the layout mapping requirements\iref{mdspan.layout.reqmts}, and
for which the \grammarterm{qualified-id} \tcode{X::layout_type} is valid and
denotes the type \tcode{MP} and
the \grammarterm{qualified-id} \tcode{X::extents_type} denotes \tcode{E}.

\rSec4[mdspan.layout.policy.overview]{Layout mapping policies}

\begin{codeblock}
namespace std {
  struct @\libglobal{layout_left}@ {
    template<class Extents>
      class mapping;
  };
  struct @\libglobal{layout_right}@ {
    template<class Extents>
      class mapping;
  };
  struct @\libglobal{layout_stride}@ {
    template<class Extents>
      class mapping;
  };

  template<size_t PaddingValue>
  struct @\libglobal{layout_left_padded}@ {
    template<class Extents> class mapping;
  };
  template<size_t PaddingValue>
  struct @\libglobal{layout_right_padded}@ {
    template<class Extents> class mapping;
  };
}
\end{codeblock}

\pnum
Each of \tcode{layout_left}, \tcode{layout_right}, and \tcode{layout_stride},
as well as each specialization of
\tcode{layout_left_padded} and \tcode{layout_right_padded},
meets the layout mapping policy requirements and is a trivially copyable type.
Furthermore,
\tcode{is_trivially_default_constructible_v<T>} is \tcode{true}
for any such type \tcode{T}.

\rSec4[mdspan.layout.left]{Class template \tcode{layout_left::mapping}}

\rSec5[mdspan.layout.left.overview]{Overview}

\pnum
\tcode{layout_left} provides a layout mapping
where the leftmost extent has stride 1, and
strides increase left-to-right as the product of extents.

\indexlibrarymember{mapping}{layout_left}%
\begin{codeblock}
namespace std {
  template<class Extents>
  class layout_left::mapping {
  public:
    using @\libmember{extents_type}{layout_left::mapping}@ = Extents;
    using @\libmember{index_type}{layout_left::mapping}@ = extents_type::index_type;
    using @\libmember{size_type}{layout_left::mapping}@ = extents_type::size_type;
    using @\libmember{rank_type}{layout_left::mapping}@ = extents_type::rank_type;
    using @\libmember{layout_type}{layout_left::mapping}@ = layout_left;

    // \ref{mdspan.layout.left.cons}, constructors
    constexpr mapping() noexcept = default;
    constexpr mapping(const mapping&) noexcept = default;
    constexpr mapping(const extents_type&) noexcept;
    template<class OtherExtents>
      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
        mapping(const mapping<OtherExtents>&) noexcept;
    template<class OtherExtents>
      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
        mapping(const layout_right::mapping<OtherExtents>&) noexcept;
    template<class LayoutLeftPaddedMapping>
      constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type,
                                           extents_type>)
        mapping(const LayoutLeftPaddedMapping&) noexcept;
    template<class OtherExtents>
      constexpr explicit(@\seebelow@)
        mapping(const layout_stride::mapping<OtherExtents>&);

    constexpr mapping& operator=(const mapping&) noexcept = default;

    // \ref{mdspan.layout.left.obs}, observers
    constexpr const extents_type& @\libmember{extents}{layout_left::mapping}@() const noexcept { return @\exposid{extents_}@; }

    constexpr index_type required_span_size() const noexcept;

    template<class... Indices>
      constexpr index_type operator()(Indices...) const noexcept;

    static constexpr bool @\libmember{is_always_unique}{layout_left::mapping}@() noexcept { return true; }
    static constexpr bool @\libmember{is_always_exhaustive}{layout_left::mapping}@() noexcept { return true; }
    static constexpr bool @\libmember{is_always_strided}{layout_left::mapping}@() noexcept { return true; }

    static constexpr bool @\libmember{is_unique}{layout_left::mapping}@() noexcept { return true; }
    static constexpr bool @\libmember{is_exhaustive}{layout_left::mapping}@() noexcept { return true; }
    static constexpr bool @\libmember{is_strided}{layout_left::mapping}@() noexcept { return true; }

    constexpr index_type stride(rank_type) const noexcept;

    template<class OtherExtents>
      friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;

  private:
    extents_type @\exposid{extents_}@{};                                               // \expos

    // \ref{mdspan.sub.map}, \tcode{submdspan} mapping specialization
    template<class... SliceSpecifiers>
      constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const     // \expos
        -> @\seebelow@;

    template<class... SliceSpecifiers>
      friend constexpr auto @\libmember{submdspan_mapping}{layout_left::mapping}@(
        const mapping& src, SliceSpecifiers... slices) {
          return src.@\exposid{submdspan-mapping-impl}@(slices...);
      }
  };
}
\end{codeblock}

\pnum
If \tcode{Extents} is not a specialization of \tcode{extents},
then the program is ill-formed.

\pnum
\tcode{layout_left::mapping<E>} is a trivially copyable type
that models \libconcept{regular} for each \tcode{E}.

\pnum
\mandates
If \tcode{Extents::rank_dynamic() == 0} is \tcode{true},
then the size of the multidimensional index space \tcode{Extents()}
is representable as a value of type \tcode{typename Extents::index_type}.

\rSec5[mdspan.layout.left.cons]{Constructors}

\indexlibraryctor{layout_left::mapping}%
\begin{itemdecl}
constexpr mapping(const extents_type& e) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
The size of the multidimensional index space \tcode{e}
is representable as a value of type \tcode{index_type}\iref{basic.fundamental}.

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{e}.
\end{itemdescr}

\indexlibraryctor{layout_left::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
    mapping(const mapping<OtherExtents>& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<extents_type, OtherExtents>} is \tcode{true}.

\pnum
\expects
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}\iref{basic.fundamental}.

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}.
\end{itemdescr}

\indexlibraryctor{layout_left::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
    mapping(const layout_right::mapping<OtherExtents>& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{extents_type::rank() <= 1} is \tcode{true}, and
\item
\tcode{is_constructible_v<extents_type, OtherExtents>} is \tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}\iref{basic.fundamental}.

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}.
\end{itemdescr}

\indexlibraryctor{layout_left::mapping}%
\begin{itemdecl}
template<class LayoutLeftPaddedMapping>
  constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type,
                                       extents_type>)
    mapping(const LayoutLeftPaddedMapping&) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{\exposid{is-layout-left-padded-mapping-of}<LayoutLeftPaddedMapping>} is \tcode{true}.
\item
\tcode{is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>}\newline is \tcode{true}.
\end{itemize}

\pnum
\mandates
If
\begin{itemize}
\item
\tcode{Extents::rank()} is greater than one,
\item
\tcode{Extents::static_extent(0)} does not equal \tcode{dynamic_extent}, and
\item
\tcode{LayoutLeftPaddedMapping::\exposid{static-padding-stride}}
does not equal \tcode{dynamic_extent},
\end{itemize}
then \tcode{Extents::static_extent(0)} equals
\tcode{LayoutLeftPaddedMapping::\exposid{static-padding-stride}}.

\pnum
\expects
\begin{itemize}
\item
If \tcode{extents_type::rank() > 1} is \tcode{true},
then \tcode{other.stride(1)} equals \tcode{other.extents().ex\-tent(0)}.
\item
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}.
\end{itemize}

\pnum
\effects
Direct-non-list-initializes \tcode{extents_} with \tcode{other.extents()}.
\end{itemdescr}

\indexlibraryctor{layout_left::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  constexpr explicit(@\seebelow@)
    mapping(const layout_stride::mapping<OtherExtents>& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<extents_type, OtherExtents>} is \tcode{true}.

\pnum
\expects
\begin{itemize}
\item
If \tcode{extents_type::rank() > 0} is \tcode{true},
then for all $r$ in the range $[0, \tcode{extents_type::rank()})$,
\tcode{other.stride($r$)} equals
\tcode{other.extents().\exposid{fwd-prod-of-extents}($r$)}, and
\item
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}\iref{basic.fundamental}.
\end{itemize}

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}.

\pnum
\remarks
The expression inside \tcode{explicit} is equivalent to:
\begin{codeblock}
!(extents_type::rank() == 0 && is_convertible_v<OtherExtents, extents_type>)
\end{codeblock}
\end{itemdescr}

\rSec5[mdspan.layout.left.obs]{Observers}

\indexlibrarymember{required_span_size}{layout_left::mapping}%
\begin{itemdecl}
constexpr index_type required_span_size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{extents().\exposid{fwd-prod-of-extents}(extents_type::rank())}.
\end{itemdescr}

\indexlibrarymember{operator()}{layout_left::mapping}%
\begin{itemdecl}
template<class... Indices>
  constexpr index_type operator()(Indices... i) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{sizeof...(Indices) == extents_type::rank()} is \tcode{true},
\item
\tcode{(is_convertible_v<Indices, index_type> \&\& ...)} is \tcode{true}, and
\item
\tcode{(is_nothrow_constructible_v<index_type, Indices> \&\& ...)} is \tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{extents_type::\exposid{index-cast}(i)} is
a multidimensional index in \exposid{extents_}\iref{mdspan.overview}.

\pnum
\effects
Let \tcode{P} be a parameter pack such that
\begin{codeblock}
is_same_v<index_sequence_for<Indices...>, index_sequence<P...>>
\end{codeblock}
is \tcode{true}.
Equivalent to:
\begin{codeblock}
return ((static_cast<index_type>(std::move(i)) * stride(P)) + ... + 0);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{stride}{layout_left::mapping}%
\begin{itemdecl}
constexpr index_type stride(rank_type i) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{extents_type::rank() > 0} is \tcode{true}.

\pnum
\expects
\tcode{i < extents_type::rank()} is \tcode{true}.

\pnum
\returns
\tcode{extents().\exposid{fwd-prod-of-extents}(i)}.
\end{itemdescr}

\indexlibrarymember{operator==}{layout_left::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{extents_type::rank() == OtherExtents::rank()} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return x.extents() == y.extents();}
\end{itemdescr}

\rSec4[mdspan.layout.right]{Class template \tcode{layout_right::mapping}}

\rSec5[mdspan.layout.right.overview]{Overview}

\pnum
\tcode{layout_right} provides a layout mapping
where the rightmost extent is stride 1, and
strides increase right-to-left as the product of extents.

\indexlibrarymember{mapping}{layout_right}%
\begin{codeblock}
namespace std {
  template<class Extents>
  class layout_right::mapping {
  public:
    using @\libmember{extents_type}{layout_right::mapping}@ = Extents;
    using @\libmember{index_type}{layout_right::mapping}@ = extents_type::index_type;
    using @\libmember{size_type}{layout_right::mapping}@ = extents_type::size_type;
    using @\libmember{rank_type}{layout_right::mapping}@ = extents_type::rank_type;
    using @\libmember{layout_type}{layout_right::mapping}@ = layout_right;

    // \ref{mdspan.layout.right.cons}, constructors
    constexpr mapping() noexcept = default;
    constexpr mapping(const mapping&) noexcept = default;
    constexpr mapping(const extents_type&) noexcept;
    template<class OtherExtents>
      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
        mapping(const mapping<OtherExtents>&) noexcept;
    template<class OtherExtents>
      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
        mapping(const layout_left::mapping<OtherExtents>&) noexcept;
    template<class LayoutRightPaddedMapping>
      constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type,
                                           extents_type>)
        mapping(const LayoutRightPaddedMapping&) noexcept;
    template<class OtherExtents>
      constexpr explicit(@\seebelow@)
        mapping(const layout_stride::mapping<OtherExtents>&) noexcept;

    constexpr mapping& operator=(const mapping&) noexcept = default;

    // \ref{mdspan.layout.right.obs}, observers
    constexpr const extents_type& @\libmember{extents}{layout_right::mapping}@() const noexcept { return @\exposid{extents_}@; }

    constexpr index_type required_span_size() const noexcept;

    template<class... Indices>
      constexpr index_type operator()(Indices...) const noexcept;

    static constexpr bool @\libmember{is_always_unique}{layout_right::mapping}@() noexcept { return true; }
    static constexpr bool @\libmember{is_always_exhaustive}{layout_right::mapping}@() noexcept { return true; }
    static constexpr bool @\libmember{is_always_strided}{layout_right::mapping}@() noexcept { return true; }

    static constexpr bool @\libmember{is_unique}{layout_right::mapping}@() noexcept { return true; }
    static constexpr bool @\libmember{is_exhaustive}{layout_right::mapping}@() noexcept { return true; }
    static constexpr bool @\libmember{is_strided}{layout_right::mapping}@() noexcept { return true; }

    constexpr index_type stride(rank_type) const noexcept;

    template<class OtherExtents>
      friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;

  private:
    extents_type @\exposid{extents_}@{};    // \expos

    // \ref{mdspan.sub.map}, \tcode{submdspan} mapping specialization
    template<class... SliceSpecifiers>
      constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const       // \expos
        -> @\seebelow@;

    template<class... SliceSpecifiers>
      friend constexpr auto @\libmember{submdspan_mapping}{layout_right::mapping}@(
        const mapping& src, SliceSpecifiers... slices) {
          return src.@\exposid{submdspan-mapping-impl}@(slices...);
      }
  };
}
\end{codeblock}

\pnum
If \tcode{Extents} is not a specialization of \tcode{extents},
then the program is ill-formed.

\pnum
\tcode{layout_right::mapping<E>} is a trivially copyable type
that models \libconcept{regular} for each \tcode{E}.

\pnum
\mandates
If \tcode{Extents::rank_dynamic() == 0} is \tcode{true},
then the size of the multidimensional index space \tcode{Extents()}
is representable as a value of type \tcode{typename Extents::index_type}.

\rSec5[mdspan.layout.right.cons]{Constructors}

\indexlibraryctor{layout_right::mapping}%
\begin{itemdecl}
constexpr mapping(const extents_type& e) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
The size of the multidimensional index space \tcode{e} is representable as
a value of type \tcode{index_type}\iref{basic.fundamental}.

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{e}.
\end{itemdescr}

\indexlibraryctor{layout_right::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
    mapping(const mapping<OtherExtents>& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<extents_type, OtherExtents>} is \tcode{true}.

\pnum
\expects
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}\iref{basic.fundamental}.

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}.
\end{itemdescr}

\indexlibraryctor{layout_right::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
    mapping(const layout_left::mapping<OtherExtents>& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{extents_type::rank() <= 1} is \tcode{true}, and
\item
\tcode{is_constructible_v<extents_type, OtherExtents>} is \tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}\iref{basic.fundamental}.

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}.
\end{itemdescr}

\indexlibraryctor{layout_right::mapping}%
\begin{itemdecl}
template<class LayoutRightPaddedMapping>
  constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type,
                                       extents_type>)
    mapping(const LayoutRightPaddedMapping&) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{\exposid{is-layout-right-padded-mapping-of}<LayoutRightPaddedMapping>}
is \tcode{true}.
\item
\tcode{is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_-\newline type>}
is \tcode{true}.
\end{itemize}

\pnum
\mandates
If
\begin{itemize}
\item
\tcode{Extents::rank()} is greater than one,
\item
\tcode{Extents::static_extent(Extents::rank() - 1)}
does not equal \tcode{dynamic_extent}, and
\item
\tcode{LayoutRightPaddedMapping::\exposid{static-padding-stride}}
does not equal \tcode{dynamic_extent},
\end{itemize}
then \tcode{Extents::static_extent(Extents::rank() - 1)} equals
\tcode{LayoutRightPaddedMapping::\exposid{sta\-tic-padding-stride}}.

\pnum
\expects
\begin{itemize}
\item
If \tcode{extents_type::rank() > 1} is \tcode{true},
then \tcode{other.stride(extents_type::rank() - 2)}\newline equals
\tcode{other.extents().extent(extents_type::rank() - 1)}.
\item
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}.
\end{itemize}

\pnum
\effects
Direct-non-list-initializes \tcode{extents_} with \tcode{other.extents()}.
\end{itemdescr}

\indexlibraryctor{layout_right::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  constexpr explicit(@\seebelow@)
    mapping(const layout_stride::mapping<OtherExtents>& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<extents_type, OtherExtents>} is \tcode{true}.

\pnum
\expects
\begin{itemize}
\item
If \tcode{extents_type::rank() > 0} is \tcode{true},
then for all $r$ in the range $[0, \tcode{extents_type::rank()})$,
\tcode{other.stride($r$)} equals
\tcode{other.extents().\exposid{rev-prod-of-extents}($r$)}.
\item
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}\iref{basic.fundamental}.
\end{itemize}

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}.

\pnum
\remarks
The expression inside \tcode{explicit} is equivalent to:
\begin{codeblock}
!(extents_type::rank() == 0 && is_convertible_v<OtherExtents, extents_type>)
\end{codeblock}
\end{itemdescr}

\rSec5[mdspan.layout.right.obs]{Observers}

\indexlibrarymember{required_span_size}{layout_right::mapping}%
\begin{itemdecl}
constexpr index_type required_span_size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{extents().\exposid{fwd-prod-of-extents}(extents_type::rank())}.
\end{itemdescr}

\indexlibrarymember{operator()}{layout_right::mapping}%
\begin{itemdecl}
template<class... Indices>
  constexpr index_type operator()(Indices... i) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{sizeof...(Indices) == extents_type::rank()} is \tcode{true},
\item
\tcode{(is_convertible_v<Indices, index_type> \&\& ...)} is \tcode{true}, and
\item
\tcode{(is_nothrow_constructible_v<index_type, Indices> \&\& ...)} is
\tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{extents_type::\exposid{index-cast}(i)} is
a multidimensional index in \exposid{extents_}\iref{mdspan.overview}.

\pnum
\effects
Let \tcode{P} be a parameter pack such that
\begin{codeblock}
is_same_v<index_sequence_for<Indices...>, index_sequence<P...>>
\end{codeblock}
is \tcode{true}. Equivalent to:
\begin{codeblock}
return ((static_cast<index_type>(std::move(i)) * stride(P)) + ... + 0);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{stride}{layout_right::mapping}%
\begin{itemdecl}
constexpr index_type stride(rank_type i) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{extents_type::rank() > 0} is \tcode{true}.

\pnum
\expects
\tcode{i < extents_type::rank()} is \tcode{true}.

\pnum
\returns
\tcode{extents().\exposid{rev-prod-of-extents}(i)}.
\end{itemdescr}

\indexlibrarymember{operator==}{layout_right::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{extents_type::rank() == OtherExtents::rank()} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return x.extents() == y.extents();}
\end{itemdescr}

\rSec4[mdspan.layout.stride]{Class template \tcode{layout_stride::mapping}}

\rSec5[mdspan.layout.stride.overview]{Overview}

\pnum
\tcode{layout_stride} provides a layout mapping
where the strides are user-defined.

\indexlibrarymember{mapping}{layout_stride}%
\begin{codeblock}
namespace std {
  template<class Extents>
  class layout_stride::mapping {
  public:
    using @\libmember{extents_type}{layout_stride::mapping}@ = Extents;
    using @\libmember{index_type}{layout_stride::mapping}@ = extents_type::index_type;
    using @\libmember{size_type}{layout_stride::mapping}@ = extents_type::size_type;
    using @\libmember{rank_type}{layout_stride::mapping}@ = extents_type::rank_type;
    using @\libmember{layout_type}{layout_stride::mapping}@ = layout_stride;

  private:
    static constexpr rank_type @\exposid{rank_}@ = extents_type::rank();    // \expos

  public:
    // \ref{mdspan.layout.stride.cons}, constructors
    constexpr mapping() noexcept;
    constexpr mapping(const mapping&) noexcept = default;
    template<class OtherIndexType>
      constexpr mapping(const extents_type&, span<OtherIndexType, @\exposid{rank_}@>) noexcept;
    template<class OtherIndexType>
      constexpr mapping(const extents_type&, const array<OtherIndexType, @\exposid{rank_}@>&) noexcept;

    template<class StridedLayoutMapping>
      constexpr explicit(@\seebelow@) mapping(const StridedLayoutMapping&) noexcept;

    constexpr mapping& operator=(const mapping&) noexcept = default;

    // \ref{mdspan.layout.stride.obs}, observers
    constexpr const extents_type& @\libmember{extents}{layout_stride::mapping}@() const noexcept { return @\exposid{extents_}@; }
    constexpr array<index_type, @\exposid{rank_}@> @\libmember{strides}{layout_stride::mapping}@() const noexcept { return @\exposid{strides_}@; }

    constexpr index_type required_span_size() const noexcept;

    template<class... Indices>
      constexpr index_type operator()(Indices...) const noexcept;

    static constexpr bool @\libmember{is_always_unique}{layout_stride::mapping}@() noexcept { return true; }
    static constexpr bool is_always_exhaustive() noexcept;
    static constexpr bool @\libmember{is_always_strided}{layout_stride::mapping}@() noexcept { return true; }

    static constexpr bool @\libmember{is_unique}{layout_stride::mapping}@() noexcept { return true; }
    constexpr bool is_exhaustive() const noexcept;
    static constexpr bool @\libmember{is_strided}{layout_stride::mapping}@() noexcept { return true; }

    constexpr index_type @\libmember{stride}{layout_stride::mapping}@(rank_type i) const noexcept { return @\exposid{strides_}@[i]; }

    template<class OtherMapping>
      friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept;

  private:
    extents_type @\exposid{extents_}@{};                    // \expos
    array<index_type, @\exposid{rank_}@> @\exposid{strides_}@{};        // \expos

    // \ref{mdspan.sub.map}, \tcode{submdspan} mapping specialization
    template<class... SliceSpecifiers>
      constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const       // \expos
        -> @\seebelow@;

    template<class... SliceSpecifiers>
      friend constexpr auto @\libmember{submdspan_mapping}{layout_stride::mapping}@(
        const mapping& src, SliceSpecifiers... slices) {
          return src.@\exposid{submdspan-mapping-impl}@(slices...);
      }
  };
}
\end{codeblock}

\pnum
If \tcode{Extents} is not a specialization of \tcode{extents},
then the program is ill-formed.

\pnum
\tcode{layout_stride::mapping<E>} is a trivially copyable type
that models \libconcept{regular} for each \tcode{E}.

\pnum
\mandates
If \tcode{Extents::rank_dynamic() == 0} is \tcode{true},
then the size of the multidimensional index space \tcode{Extents()}
is representable as a value of type \tcode{typename Extents::index_type}.

\rSec5[mdspan.layout.stride.expo]{Exposition-only helpers}

\pnum
Let \tcode{\exposid{REQUIRED-SPAN-SIZE}(e, strides)} be:
\begin{itemize}
\item
\tcode{1}, if \tcode{e.rank() == 0} is \tcode{true},
\item
otherwise \tcode{0}, if the size of the multidimensional index space \tcode{e} is 0,
\item
otherwise \tcode{1} plus the sum of products of
\tcode{(e.extent($r$) - 1)} and
\begin{codeblock}
extents_type::@\exposid{index-cast}@(strides[@$r$@])
\end{codeblock}
  for all $r$ in the range $[0, \tcode{e.rank()})$.
\end{itemize}

\pnum
Let \tcode{\exposid{OFFSET}(m)} be:
\begin{itemize}
\item
\tcode{m()}, if \tcode{e.rank() == 0} is \tcode{true},
\item
otherwise \tcode{0}, if the size of the multidimensional index space \tcode{e} is 0,
\item
otherwise \tcode{m(z...)} for a pack of integers \tcode{z}
that is a multidimensional index in \tcode{m.extents()} and
each element of \tcode{z} equals 0.
\end{itemize}

\pnum
Let \exposid{is-extents} be the exposition-only variable template
defined as follows:
\begin{codeblock}
template<class T>
  constexpr bool @\exposid{is-extents}@ = false;                              // \expos
template<class IndexType, size_t... Args>
  constexpr bool @\exposid{is-extents}@<extents<IndexType, Args...>> = true;  // \expos
\end{codeblock}

\pnum
Let \exposconcept{layout-mapping-alike} be the exposition-only concept
defined as follows:
\begin{codeblock}
template<class M>
concept @\defexposconcept{layout-mapping-alike}@ = requires {                         // \expos
  requires @\exposid{is-extents}@<typename M::extents_type>;
  { M::is_always_strided() } -> @\libconcept{same_as}@<bool>;
  { M::is_always_exhaustive() } -> @\libconcept{same_as}@<bool>;
  { M::is_always_unique() } -> @\libconcept{same_as}@<bool>;
  bool_constant<M::is_always_strided()>::value;
  bool_constant<M::is_always_exhaustive()>::value;
  bool_constant<M::is_always_unique()>::value;
};
\end{codeblock}
\begin{note}
This concept checks that the functions
\tcode{M::is_always_strided()},
\tcode{M::is_always_exhaustive()}, and
\tcode{M::is_always_unique()} exist,
are constant expressions, and
have a return type of \tcode{bool}.
\end{note}

\rSec5[mdspan.layout.stride.cons]{Constructors}

\indexlibraryctor{layout_stride::mapping}%
\begin{itemdecl}
constexpr mapping() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{layout_right::mapping<extents_type>().required_span_size()}
is representable as a value of type \tcode{index_type}\iref{basic.fundamental}.

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{extents_type()}, and
for all $d$ in the range \range{0}{\exposid{rank_}},
direct-non-list-initializes \tcode{\exposid{strides_}[$d$]} with
\tcode{layout_right::mapping<extents_type>().stride($d$)}.
\end{itemdescr}

\indexlibraryctor{layout_stride::mapping}%
\begin{itemdecl}
template<class OtherIndexType>
  constexpr mapping(const extents_type& e, span<OtherIndexType, @\exposid{rank_}@> s) noexcept;
template<class OtherIndexType>
  constexpr mapping(const extents_type& e, const array<OtherIndexType, @\exposid{rank_}@>& s) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const OtherIndexType\&, index_type>} is \tcode{true}, and
\item
\tcode{is_nothrow_constructible_v<index_type, const OtherIndexType\&>} is \tcode{true}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
The result of converting \tcode{s[$i$]} to \tcode{index_type}
is greater than \tcode{0}
for all $i$ in the range $[0, \exposid{rank_})$.
\item
\tcode{\exposid{REQUIRED-SPAN-SIZE}(e, s)} is representable
as a value of type \tcode{index_type}\iref{basic.fundamental}.
\item
If \exposid{rank_} is greater than 0,
then there exists a permutation $P$ of the integers
in the range $[0, \exposid{rank_})$,
such that \tcode{s[$p_i$] >= s[$p_{i-1}$] * e.extent(p$_{i-1}$)} is \tcode{true}
for all $i$ in the range $[1, \exposid{rank_})$,
where $p_i$ is the $i^\text{th}$ element of $P$.
\begin{note}
For \tcode{layout_stride},
this condition is necessary and sufficient
for \tcode{is_unique()} to be \tcode{true}.
\end{note}
\end{itemize}

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{e}, and
for all $d$ in the range $[0, \exposid{rank_})$,
direct-non-list-initializes \tcode{strides_[$d$]} with \tcode{as_const(s[$d$])}.
\end{itemdescr}

\indexlibraryctor{layout_stride::mapping}%
\begin{itemdecl}
template<class StridedLayoutMapping>
  constexpr explicit(@\seebelow@)
    mapping(const StridedLayoutMapping& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{\exposconcept{layout-mapping-alike}<StridedLayoutMapping>} is satisfied.
\item
\tcode{is_constructible_v<extents_type, typename StridedLayoutMapping::extents_type>} is\\\tcode{true}.
\item
\tcode{StridedLayoutMapping::is_always_unique()} is \tcode{true}.
\item
\tcode{StridedLayoutMapping::is_always_strided()} is \tcode{true}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{StridedLayoutMapping} meets the layout mapping requirements\iref{mdspan.layout.reqmts},
\item
\tcode{other.stride($r$) > 0} is \tcode{true}
for every rank index $r$ of \tcode{extents()},
\item
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}\iref{basic.fundamental}, and
\item
\tcode{\exposid{OFFSET}(other) == 0} is \tcode{true}.
\end{itemize}

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}, and
for all $d$ in the range $[0, \exposid{rank_})$,
direct-non-list-initializes \tcode{\exposid{strides_}[$d$]}
with \tcode{other.stride($d$)}.

\pnum
Remarks: The expression inside \tcode{explicit} is equivalent to:
\begin{codeblock}
!(is_convertible_v<typename StridedLayoutMapping::extents_type, extents_type> &&
  (@\exposid{is-mapping-of}@<layout_left, StridedLayoutMapping> ||
   @\exposid{is-mapping-of}@<layout_right, StridedLayoutMapping> ||
   @\exposid{is-layout-left-padded-mapping-of}@<StridedLayoutMapping> ||
   @\exposid{is-layout-right-padded-mapping-of}@<StridedLayoutMapping> ||
   @\exposid{is-mapping-of}@<layout_stride, StridedLayoutMapping>))
\end{codeblock}
\end{itemdescr}

\rSec5[mdspan.layout.stride.obs]{Observers}

\indexlibrarymember{required_span_size}{layout_stride::mapping}%
\begin{itemdecl}
constexpr index_type required_span_size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{REQUIRED-SPAN-SIZE}(extents(), \exposid{strides_})}.
\end{itemdescr}

\indexlibrarymember{operator()}{layout_stride::mapping}%
\begin{itemdecl}
template<class... Indices>
  constexpr index_type operator()(Indices... i) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{sizeof...(Indices) == \exposid{rank_}} is \tcode{true},
\item
\tcode{(is_convertible_v<Indices, index_type> \&\& ...)} is \tcode{true}, and
\item
\tcode{(is_nothrow_constructible_v<index_type, Indices> \&\& ...)} is \tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{extents_type::\exposid{index-cast}(i)} is
a multidimensional index in \exposid{extents_}\iref{mdspan.overview}.

\pnum
\effects
Let \tcode{P} be a parameter pack such that
\begin{codeblock}
is_same_v<index_sequence_for<Indices...>, index_sequence<P...>>
\end{codeblock}
is \tcode{true}.
Equivalent to:
\begin{codeblock}
return ((static_cast<index_type>(std::move(i)) * stride(P)) + ... + 0);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{is_always_exhaustive}{layout_stride::mapping}%
\begin{itemdecl}
static constexpr bool is_always_exhaustive() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if \exposid{rank_} is 0
or if there is a rank index \tcode{r} of \tcode{extents()}
such that \tcode{extents_type::sta\-tic_extent(r)} is 0,
otherwise \tcode{false}.
\end{itemdescr}

\indexlibrarymember{is_exhaustive}{layout_stride::mapping}%
\begin{itemdecl}
constexpr bool is_exhaustive() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{itemize}
\item
\tcode{true} if \exposid{rank_} or the size of the multidimensional index space
\tcode{m.extents()} is 0.
\item
Otherwise, \tcode{true} if there is
a permutation $P$ of the integers in the range $[0, \exposid{rank_})$
such that \tcode{stride($p_0$)} equals 1, and
\tcode{stride($p_i$)} equals \tcode{stride($ p_{i-1}$) * extents().extent($p_{i-1}$)}
for $i$ in the range $[1, \exposid{rank_})$,
where $p_i$ is the $i^\text{th}$ element of $P$.
\item
Otherwise, \tcode{false}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{operator==}{layout_stride::mapping}%
\begin{itemdecl}
template<class OtherMapping>
  friend constexpr bool operator==(const mapping& x, const OtherMapping& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{\exposconcept{layout-mapping-alike}<OtherMapping>} is satisfied.
\item
\tcode{\exposid{rank_} == OtherMapping::extents_type::rank()} is \tcode{true}.
\item
\tcode{OtherMapping::is_always_strided()} is \tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{OtherMapping} meets the layout mapping requirements\iref{mdspan.layout.policy.reqmts}.

\pnum
\returns
\tcode{true} if \tcode{x.extents() == y.extents()} is \tcode{true},
\tcode{\exposid{OFFSET}(y) == 0} is \tcode{true}, and
each of \tcode{x.stride($r$) == y.stride($r$)} is \tcode{true}
for $r$ in the range  $[0, \tcode{x.extents().rank()})$.
Otherwise, \tcode{false}.
\end{itemdescr}

\rSec4[mdspan.layout.leftpad]{Class template \tcode{layout_left_padded::mapping}}

\rSec5[mdspan.layout.leftpad.overview]{Overview}

\pnum
\tcode{layout_left_padded} provides a layout mapping
that behaves like \tcode{layout_left::mapping},
except that the padding stride \tcode{stride(1)}
can be greater than or equal to \tcode{extent(0)}.

\indexlibrarymember{mapping}{layout_left_padded}%
\begin{codeblock}
namespace std {
  template<size_t PaddingValue>
  template<class Extents>
  class layout_left_padded<PaddingValue>::mapping {
  public:
    static constexpr size_t @\libmember{padding_value}{layout_left_padded::mapping}@ = PaddingValue;

    using @\libmember{extents_type}{layout_left_padded::mapping}@ = Extents;
    using @\libmember{index_type}{layout_left_padded::mapping}@ = extents_type::index_type;
    using @\libmember{size_type}{layout_left_padded::mapping}@ = extents_type::size_type;
    using @\libmember{rank_type}{layout_left_padded::mapping}@ = extents_type::rank_type;
    using @\libmember{layout_type}{layout_left_padded::mapping}@ = layout_left_padded<PaddingValue>;

  private:
    static constexpr size_t @\exposid{rank_}@ = extents_type::rank();         // \expos
    static constexpr size_t @\exposid{first-static-extent}@ =                 // \expos
      extents_type::static_extent(0);

    // \ref{mdspan.layout.leftpad.expo}, exposition-only members
    static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@;  // \expos

  public:
    // \ref{mdspan.layout.leftpad.cons}, constructors
    constexpr mapping() noexcept : mapping(extents_type{}) {}
    constexpr mapping(const mapping&) noexcept = default;
    constexpr mapping(const extents_type&);
    template<class OtherIndexType>
      constexpr mapping(const extents_type&, OtherIndexType);
    template<class OtherExtents>
      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
        mapping(const layout_left::mapping<OtherExtents>&);
    template<class OtherExtents>
      constexpr explicit(@\seebelow@)
        mapping(const layout_stride::mapping<OtherExtents>&);
    template<class LayoutLeftPaddedMapping>
      constexpr explicit(@\seebelow@)
        mapping(const LayoutLeftPaddedMapping&);
    template<class LayoutRightPaddedMapping>
      constexpr explicit(@\seebelow@)
        mapping(const LayoutRightPaddedMapping&) noexcept;

    constexpr mapping& operator=(const mapping&) noexcept = default;

    // \ref{mdspan.layout.leftpad.obs}, observers
    constexpr const extents_type& @\libmember{extents}{layout_left_padded::mapping}@() const noexcept { return @\exposid{extents_}@; }
    constexpr array<index_type, @\exposid{rank_}@> strides() const noexcept;

    constexpr index_type required_span_size() const noexcept;
    template<class... Indices>
      constexpr index_type operator()(Indices...) const noexcept;

    static constexpr bool @\libmember{is_always_unique}{layout_left_padded::mapping}@() noexcept { return true; }
    static constexpr bool is_always_exhaustive() noexcept;
    static constexpr bool @\libmember{is_always_strided}{layout_left_padded::mapping}@() noexcept { return true; }

    static constexpr bool @\libmember{is_unique}{layout_left_padded::mapping}@() noexcept { return true; }
    constexpr bool is_exhaustive() const noexcept;
    static constexpr bool @\libmember{is_strided}{layout_left_padded::mapping}@() noexcept { return true; }

    constexpr index_type stride(rank_type) const noexcept;

    template<class LayoutLeftPaddedMapping>
      friend constexpr bool operator==(const mapping&, const LayoutLeftPaddedMapping&) noexcept;

  private:
    // \ref{mdspan.layout.leftpad.expo}, exposition-only members
    index_type @\exposid{stride-1}@ = @\exposid{static-padding-stride}@;                           // \expos
    extents_type @\exposid{extents_}@{};                                               // \expos
    // \ref{mdspan.sub.map}, \tcode{submdspan} mapping specialization
    template<class... SliceSpecifiers>
      constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const     // \expos
        -> @\seebelow@;

    template<class... SliceSpecifiers>
      friend constexpr auto @\libmember{submdspan_mapping}{layout_left_padded::mapping}@(const mapping& src, SliceSpecifiers... slices) {
      return src.@\exposid{submdspan-mapping-impl}@(slices...);
    }
  };
}
\end{codeblock}

\pnum
If \tcode{Extents} is not a specialization of \tcode{extents},
then the program is ill-formed.

\pnum
\tcode{layout_left_padded::mapping<E>} is a trivially copyable type
that models \libconcept{regular} for each \tcode{E}.

\pnum
Throughout \ref{mdspan.layout.leftpad},
let \tcode{P_rank} be the following
size \exposid{rank_} parameter pack of \tcode{size_}t values:
\begin{itemize}
\item
the empty parameter pack, if \exposid{rank_} equals zero;
\item
\tcode otherwise, \tcode{0zu}, if \exposid{rank_} equals one;
\item
otherwise, the parameter pack \tcode{0zu}, \tcode{1zu}, \ldots, \tcode{\exposid{rank_}- 1}.
\end{itemize}

\pnum
\mandates
\begin{itemize}
\item
If \tcode{rank_dynamic() == 0} is \tcode{true},
then the size of the multidimensional index space \tcode{Extents()}
is representable as a value of type \tcode{index_type}.
\item
If \tcode{padding_value} is not equal to \tcode{dynamic_extent}, then
\tcode{padding_value} is representable as a value of type \tcode{index_type}.
\item
If
\begin{itemize}
\item
\exposid{rank_} is greater than one,
\item
\tcode{padding_value} does not equal \tcode{dynamic_extent}, and
\item
\exposid{first-static-extent} does not equal \tcode{dynamic_extent},
\end{itemize}
then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, \exposid{first-static-extent})}
is representable as a val\-ue of type \tcode{size_t}, and
is representable as a value of type \tcode{index_type}.
\item
If
\begin{itemize}
\item
\exposid{rank_} is greater than one,
\item
\tcode{padding_value} does not equal \tcode{dynamic_extent}, and
\item
\tcode{extents_type::static_extent($k$)} does not equal \tcode{dynamic_extent}
for all $k$ in the range \range{0}{extents_type::rank()},
\end{itemize}
then the product of
\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.static_extent(0))} and
all values \tcode{ext.static_extent($k$)}
with $k$ in the range of \range{1}{\exposid{rank_}}
is representable as a value of type \tcode{size_t}, and
is representable as a value of type \tcode{index_type}.
\end{itemize}

\rSec5[mdspan.layout.leftpad.expo]{Exposition-only members}

\begin{itemdecl}
static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
The value is
\begin{itemize}
\item
\tcode{0}, if \exposid{rank_} equals zero or one;
\item
otherwise, \tcode{dynamic_extent},
if \tcode{padding_value} or \exposid{first-static-extent} equals
\tcode{dynamic_extent};
\item
otherwise, the \tcode{size_t} value which is
\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, \exposid{first-sta\-tic-extent})}.
\end{itemize}
\end{itemdescr}

\begin{itemdecl}
index_type @\exposid{stride-1}@ = @\exposid{static-padding-stride}@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\recommended
Implementations should not store this value
if \exposid{static-padding-stride} is not \tcode{dynamic_extent}.
\begin{note}
Using \tcode{extents<index_type, \exposid{static-padding-stride}>} instead of
\tcode{index_type} as the type of \exposid{stride-1} would achieve this.
\end{note}
\end{itemdescr}

\rSec5[mdspan.layout.leftpad.cons]{Constructors}

\indexlibraryctor{layout_left_padded::mapping}%
\begin{itemdecl}
constexpr mapping(const extents_type& ext);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\begin{itemize}
\item
The size of the multidimensional index space \tcode{ext} is representable as
a value of type \tcode{index_type}.
\item
If \exposid{rank_} is greater than one and
\tcode{padding_value} does not equal \tcode{dynamic_extent},
then \tcode{\exposid{LEAST-MUL\-TIPLE-AT-LEAST}(padding_value, ext.extent(0))}
is representable as a value of type \exposid{index_type}.
\item
If \exposid{rank_} is greater than one and
\tcode{padding_value} does not equal \tcode{dynamic_extent},
then the product of
\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(0))} and
all values \tcode{ext.extent($k$)}
with $k$ in the range of \range{1}{\exposid{rank_}}
is representable as a value of type \tcode{index_type}.
\end{itemize}

\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{extents_} with \tcode{ext}; and
\item
if \exposid{rank_} is greater than one,
direct-non-list-initializes \exposid{stride-1}
\begin{itemize}
\item
with \tcode{ext.extent(0)} if \tcode{padding_value} is \tcode{dynamic_extent},
\item
otherwise with
\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(0))}.
\end{itemize}
\end{itemize}
\end{itemdescr}

\indexlibraryctor{layout_left_padded::mapping}%
\begin{itemdecl}
template<class OtherIndexType>
constexpr mapping(const extents_type& ext, OtherIndexType padding);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{pad} be
\tcode{extents_type::\exposid{index-cast}(std::move(padding))}.

\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<OtherIndexType, index_type>} is \tcode{true}.
\item
\tcode{is_nothrow_constructible_v<index_type, OtherIndexType>} is \tcode{true}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{pad} is representable as a value of type \tcode{index_type}.
\item
\tcode{pad} is greater than zero.
\item
If \exposid{rank_} is greater than one,
then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(0))}
is representable as a value of type \tcode{index_type.}
\item
If \exposid{rank_} is greater than one,
then the product of
\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\linebreak 0))} and
all values \tcode{ext.extent($k$)}
with $k$ in the range of \range{1}{\exposid{rank_}}
is representable as a value of type \tcode{index_type}.
\item
If \tcode{padding_value} is not equal to \tcode{dynamic_extent},
\tcode{padding_value} equals \tcode{pad}.
\end{itemize}

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{ext}, and
if \exposid{rank_} is greater than one,
direct-non-list-initializes \exposid{stride-1} with
\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(0))}.
\end{itemdescr}

\indexlibraryctor{layout_left_padded::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
    mapping(const layout_left::mapping<OtherExtents>& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<extents_type, OtherExtents>} is \tcode{true}.

\pnum
\mandates
If \tcode{OtherExtents::rank()} is greater than \tcode{1}, then
\begin{codeblock}
(@\exposid{static-padding-stride}@ == dynamic_extent) ||
(OtherExtents::static_extent(0) == dynamic_extent) ||
(@\exposid{static-padding-stride}@ == OtherExtents::static_extent(0))
\end{codeblock}
is \tcode{true}.

\pnum
\expects
\begin{itemize}
\item
If \tcode{extents_type::rank() > 1} is \tcode{true} and
\tcode{padding_value} == \tcode{dynamic_extent} is \tcode{false},
then \tcode{other.stride(1)} equals
\begin{codeblock}
@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value,
                        extents_type::@\exposid{index-cast}@(other.extents().extent(0)))
\end{codeblock}
and
\item
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}.
\end{itemize}

\pnum
\effects
Equivalent to \tcode{mapping(other.extents())}.
\end{itemdescr}

\indexlibraryctor{layout_left_padded::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  constexpr explicit(@\seebelow@)
    mapping(const layout_stride::mapping<OtherExtents>& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<extents_type, OtherExtents>} is \tcode{true}.

\pnum
\expects
\begin{itemize}
\item
If \exposid{rank_} is greater than \tcode{1} and
\tcode{padding_value} does not equal \tcode{dynamic_extent},
then \tcode{other.\linebreak stride(1)} equals
\begin{codeblock}
@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value,
                        extents_type::@\exposid{index-cast}@(other.extents().extent(0)))
\end{codeblock}
\item
If \exposid{rank_} is greater than 0,
then \tcode{other.stride(0)} equals 1.
\item
If \exposid{rank_} is greater than 2,
then for all $r$ in the range \range{2}{\exposid{rank_}},
\tcode{other.stride(r)} equals
\begin{codeblock}
(other.extents().@\exposid{fwd-prod-of-extents}@(r) / other.extents().extent(0)) * other.stride(1)
\end{codeblock}
\item
\tcode{other.required_span_size()} is representable as
a value of type \exposid{index_type}.
\end{itemize}

\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()} and
\item
if \exposid{rank_} is greater than one,
direct-non-list-initializes \exposid{stride-1} with
\tcode{other.stride(1)}.
\end{itemize}

\pnum
\remarks
The expression inside \tcode{explicit} is equivalent to:
\begin{codeblock}
!(rank_ == 0 && is_convertible_v<OtherExtents, extents_type>)
\end{codeblock}
\end{itemdescr}

\indexlibraryctor{layout_left_padded::mapping}%
\begin{itemdecl}
template<class LayoutLeftPaddedMapping>
  constexpr explicit(@\seebelow@)
    mapping(const LayoutLeftPaddedMapping& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{\exposid{is-layout-left-padded-mapping-of}<LayoutLeftPaddedMapping>}
is \tcode{true}.
\item
\tcode{is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>}
\newline is \tcode{true}.
\end{itemize}

\pnum
\mandates
If \exposid{rank_} is greater than 1,
then
\begin{codeblock}
padding_value == dynamic_extent ||
LayoutLeftPaddedMapping::padding_value == dynamic_extent ||
padding_value == LayoutLeftPaddedMapping::padding_value
\end{codeblock}
is \tcode{true}.

\pnum
\expects
\begin{itemize}
\item
If \exposid{rank_} is greater than 1 and
\tcode{padding_value} does not equal \tcode{dynamic_extent},
then \tcode{other.\linebreak stride(1)} equals
\begin{codeblock}
@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value,
                        extents_type::@\exposid{index-cast}@(other.extent(0)))
\end{codeblock}
\item
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}.
\end{itemize}

\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()} and
\item
if \exposid{rank_} is greater than one,
direct-non-list-initializes \exposid{stride-1} with \tcode{other.stride(1)}.
\end{itemize}

\pnum
\remarks
The expression inside \tcode{explicit} is equivalent to:
\begin{codeblock}
!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type> ||
rank_> 1 &&
(padding_value != dynamic_extent ||
 LayoutLeftPaddedMapping::padding_value == dynamic_extent)
\end{codeblock}
\end{itemdescr}

\indexlibraryctor{layout_left_padded::mapping}%
\begin{itemdecl}
template<class LayoutRightPaddedMapping>
  constexpr explicit(@\seebelow@)
    mapping(const LayoutRightPaddedMapping& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{\exposid{is-layout-right-padded-mapping-of}<LayoutRightPaddedMapping>}
is \tcode{true} or\newline
\tcode{\exposid{is-mapping-of}<layout_right, LayoutRightPaddedMapping>}
is \tcode{true}.
\item
\exposid{rank_} equals zero or one.
\item
\tcode{is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_-\newline type>}
is \tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}.

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}.

\pnum
\remarks
The expression inside \tcode{explicit} is equivalent to:
\begin{codeblock}
!is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type>
\end{codeblock}

\begin{note}
Neither the input mapping nor the mapping to be constructed
uses the padding stride in the rank-0 or rank-1 case,
so the padding stride does not affect
either the constraints or the preconditions.
\end{note}
\end{itemdescr}

\rSec5[mdspan.layout.leftpad.obs]{Observers}

\indexlibrarymember{strides}{layout_left_padded::mapping}%
\begin{itemdecl}
constexpr array<index_type, @\exposid{rank_}@> strides() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{array<index_type, \exposid{rank_}>(\{stride(P_rank)...\})}.
\end{itemdescr}

\indexlibrarymember{required_span_size}{layout_left_padded::mapping}%
\begin{itemdecl}
constexpr index_type required_span_size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{itemize}
\item
\tcode{0} if the multidimensional index space \exposid{extents_} is empty,
\item
otherwise, \tcode{(*this)(\exposid{extents_}.extent(P_rank) - index_type(1)...) + 1}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{operator()}{layout_left_padded::mapping}%
\begin{itemdecl}
template<class... Indices>
constexpr index_type operator()(Indices... idxs) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{sizeof...(Indices) == \exposid{rank_}} is \tcode{true}.
\item
\tcode{(is_convertible_v<Indices, index_type> \&\& ...)} is \tcode{true}.
\item
\tcode{(is_nothrow_constructible_v<index_type, Indices> \&\& ...)} is \tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{extents_type::\exposid{index-cast}(idxs)} is
a multidimensional index in \tcode{extents()}\iref{mdspan.overview}.

\pnum
\returns
\tcode{((static_cast<index_type>(std::move(idxs)) * stride(P_rank)) + ... + 0)}.
\end{itemdescr}

\indexlibrarymember{is_always_exhaustive}{layout_left_padded::mapping}%
\begin{itemdecl}
static constexpr bool is_always_exhaustive() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{itemize}
\item
If \exposid{rank_} equals zero or one, then \tcode{true};
\item
otherwise, if
neither \exposid{static-padding-stride} nor \exposid{first-static-extent}
equal \tcode{dynamic_extent},
then \tcode{\exposid{static-padding-stride} == \exposid{first-static-extent}};
\item
otherwise, \tcode{false}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{is_exhaustive}{layout_left_padded::mapping}%
\begin{itemdecl}
constexpr bool is_exhaustive() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if \exposid{rank_} equals zero or one;
otherwise, \tcode{extents_.extent(0) == stride(1)}.
\end{itemdescr}

\indexlibrarymember{stride}{layout_left_padded::mapping}%
\begin{itemdecl}
constexpr index_type stride(rank_type r) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{r} is smaller than \exposid{rank_}.

\pnum
\returns
\begin{itemize}
\item
If \tcode{r} equals zero: 1;
\item
otherwise, if \tcode{r} equals one: \exposid{stride-1};
\item
otherwise, the product of \exposid{stride-1} and
all values \tcode{extents_.extent($k$)} with $k$ in the range \range{1}{r}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{operator==}{layout_left_padded::mapping}%
\begin{itemdecl}
template<class LayoutLeftPaddedMapping>
  friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{\exposid{is-layout-left-padded-mapping-of}<LayoutLeftPaddedMapping>}
is \tcode{true}.
\item
\tcode{LayoutLeftPaddedMapping::extents_type::rank() == rank_} is \tcode{true}.
\end{itemize}

\pnum
\returns
\tcode{true} if \tcode{x.extents() == y.extents()} is \tcode{true} and
\tcode{\exposid{rank_} < 2 || x.stride(1) == y.\newline stride(1)} is \tcode{true}.
Otherwise, \tcode{false}.
\end{itemdescr}

\rSec4[mdspan.layout.rightpad]{Class template \tcode{layout_right_padded::mapping}}

\rSec5[mdspan.layout.rightpad.overview]{Overview}

\pnum
\tcode{layout_right_padded} provides a layout mapping
that behaves like \tcode{layout_right::mapping},
except that the padding stride \tcode{stride(extents_type::rank() - 2)}
can be greater than or equal to
\tcode{extents_type::ex\-tent(extents_type::rank() - 1)}.

\indexlibrarymember{mapping}{layout_right_padded}%
\begin{codeblock}
namespace std {
  template<size_t PaddingValue>
  template<class Extents>
  class layout_right_padded<PaddingValue>::mapping {
  public:
    static constexpr size_t @\libmember{padding_value}{layout_right_padded::mapping}@ = PaddingValue;

    using @\libmember{extents_type}{layout_right_padded::mapping}@ = Extents;
    using @\libmember{index_type}{layout_right_padded::mapping}@ = extents_type::index_type;
    using @\libmember{size_type}{layout_right_padded::mapping}@ = extents_type::size_type;
    using @\libmember{rank_type}{layout_right_padded::mapping}@ = extents_type::rank_type;
    using @\libmember{layout_type}{layout_right_padded::mapping}@ = layout_right_padded<PaddingValue>;

  private:
    static constexpr size_t @\exposid{rank_}@ = extents_type::rank();    // \expos
    static constexpr size_t @\exposid{last-static-extent}@ =             // \expos
      extents_type::static_extent(@\exposid{rank_}@ - 1);

    // \ref{mdspan.layout.rightpad.expo}, exposition-only members
    static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@; // \expos

  public:
    // \ref{mdspan.layout.rightpad.cons}, constructors
    constexpr mapping() noexcept : mapping(extents_type{}) {}
    constexpr mapping(const mapping&) noexcept = default;
    constexpr mapping(const extents_type&);
    template<class OtherIndexType>
      constexpr mapping(const extents_type&, OtherIndexType);

    template<class OtherExtents>
      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
        mapping(const layout_right::mapping<OtherExtents>&);
    template<class OtherExtents>
      constexpr explicit(@\seebelow@)
        mapping(const layout_stride::mapping<OtherExtents>&);
    template<class LayoutRightPaddedMapping>
      constexpr explicit(@\seebelow@)
        mapping(const LayoutRightPaddedMapping&);
    template<class LayoutLeftPaddedMapping>
      constexpr explicit(@\seebelow@)
        mapping(const LayoutLeftPaddedMapping&) noexcept;

    constexpr mapping& operator=(const mapping&) noexcept = default;

    // \ref{mdspan.layout.rightpad.obs}, observers
    constexpr const extents_type& @\libmember{extents}{layout_right_padded::mapping}@() const noexcept { return @\exposid{extents_}@; }
    constexpr array<index_type, @\exposid{rank_}@> strides() const noexcept;

    constexpr index_type required_span_size() const noexcept;

    template<class... Indices>
      constexpr index_type operator()(Indices...) const noexcept;

    static constexpr bool @\libmember{is_always_unique}{layout_right_padded::mapping}@() noexcept { return true; }
    static constexpr bool is_always_exhaustive() noexcept;
    static constexpr bool @\libmember{is_always_strided}{layout_right_padded::mapping}@() noexcept { return true; }

    static constexpr bool @\libmember{is_unique}{layout_right_padded::mapping}@() noexcept { return true; }
    constexpr bool is_exhaustive() const noexcept;
    static constexpr bool @\libmember{is_strided}{layout_right_padded::mapping}@() noexcept { return true; }

    constexpr index_type stride(rank_type) const noexcept;

    template<class LayoutRightPaddedMapping>
      friend constexpr bool operator==(const mapping&, const LayoutRightPaddedMapping&) noexcept;

  private:
    // \ref{mdspan.layout.rightpad.expo}, exposition-only members
    index_type @\exposid{stride-rm2}@ = @\exposid{static-padding-stride}@;                         // \expos
    extents_type @\exposid{extents_}@{};                                               // \expos

    // \ref{mdspan.sub.map}, \tcode{submdspan} mapping specialization
    template<class... SliceSpecifiers>
      constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const     // \expos
        -> @\seebelow@;

    template<class... SliceSpecifiers>
      friend constexpr auto @\libmember{submdspan_mapping}{layout_right_padded::mapping}@(const mapping& src, SliceSpecifiers... slices) {
      return src.@\exposid{submdspan-mapping-impl}@(slices...);
    }
  };
}
\end{codeblock}

\pnum
If \tcode{Extents} is not a specialization of \tcode{extents},
then the program is ill-formed.

\pnum
\tcode{layout_right_padded::mapping<E>} is a trivially copyable type
that models \libconcept{regular} for each \tcode{E}.

\pnum
Throughout \ref{mdspan.layout.rightpad},
let \tcode{P_rank} be the following
size \exposid{rank_} parameter pack of \tcode{size_}t values:
\begin{itemize}
\item
the empty parameter pack, if \exposid{rank_} equals zero;
\item
\tcode otherwise, \tcode{0zu}, if \exposid{rank_} equals one;
\item
otherwise, the parameter pack \tcode{0zu}, \tcode{1zu}, \ldots, \tcode{\exposid{rank_}- 1}.
\end{itemize}

\pnum
\mandates
\begin{itemize}
\item
If \tcode{rank_dynamic() == 0} is \tcode{true},
then the size of the multidimensional index space \tcode{Extents()}
is representable as a value of type \tcode{index_type}.
\item
If \tcode{padding_value} is not equal to \tcode{dynamic_extent}, then
\tcode{padding_value} is representable as a value of type \tcode{index_type}.
\item
If
\begin{itemize}
\item
\exposid{rank_} is greater than one,
\item
\tcode{padding_value} does not equal \tcode{dynamic_extent}, and
\item
\exposid{last-static-extent} does not equal \tcode{dynamic_extent},
\end{itemize}
then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, \exposid{last-static-extent})}
is representable as a value of type \tcode{size_t}, and
is representable as a value of type \tcode{index_type}.
\item
If
\begin{itemize}
\item
\exposid{rank_} is greater than one,
\item
\tcode{padding_value} does not equal \tcode{dynamic_extent}, and
\item
\tcode{extents_type::static_extent($k$)} does not equal \tcode{dynamic_extent}
for all $k$ in the range \range{0}{\exposid{rank_}},
\end{itemize}
then the product of
\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.static_extent(\exposid{rank_} - 1))} and
all values \tcode{ext.static_extent($k$)}
with $k$ in the range of \range{0}{\exposid{rank_} - 1}
is representable as a value of type \tcode{size_t}, and
is representable as a value of type \tcode{index_type}.
\end{itemize}

\rSec5[mdspan.layout.rightpad.expo]{Exposition-only members}

\begin{itemdecl}
static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
The value is
\begin{itemize}
\item
\tcode{0}, if \exposid{rank_} equals zero or one;
\item
otherwise, \tcode{dynamic_extent},
if \tcode{padding_value} or \exposid{last-static-extent} equals
\tcode{dynamic_extent};
\item
otherwise, the \tcode{size_t} value which is
\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, \exposid{last-sta\-tic-extent})}.
\end{itemize}
\end{itemdescr}

\begin{itemdecl}
index_type @\exposid{stride-rm2}@ = @\exposid{static-padding-stride}@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\recommended
Implementations should not store this value
if \exposid{static-padding-stride} is not \tcode{dynamic_extent}.
\begin{note}
Using \tcode{extents<index_type, \exposid{static-padding-stride}>}
instead of \tcode{index_type} as the type of \exposid{stride-\linebreak rm2}
would achieve this.
\end{note}
\end{itemdescr}

\rSec5[mdspan.layout.rightpad.cons]{Constructors}

\indexlibraryctor{layout_right_padded::mapping}%
\begin{itemdecl}
constexpr mapping(const extents_type& ext);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\begin{itemize}
\item
The size of the multidimensional index space \tcode{ext}
is representable as a value of type \tcode{index_type}.
\item
If \exposid{rank_} is greater than one and
\tcode{padding_value} does not equal \tcode{dynamic_extent},
then \tcode{\exposid{LEAST-MUL\-TIPLE-AT-LEAST}(padding_value, ext.extent(\exposid{rank_} - 1))}
is representable as a value of type \exposid{index_type}.
\item
If \exposid{rank_} is greater than one and
\tcode{padding_value} does not equal \tcode{dynamic_extent},
then the product of
\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(\exposid{rank_} - 1))} and
all values \tcode{ext.extent($k$)}
with $k$ in the range of \range{0}{\exposid{rank_} - 1}
is representable as a value of type \tcode{index_type}.
\end{itemize}

\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{extents_} with \tcode{ext}; and
\item
if \exposid{rank_} is greater than one,
direct-non-list-initializes \exposid{stride-rm2}
\begin{itemize}
\item
with \tcode{ext.extent(\exposid{rank_} - 1)}
if \tcode{padding_value} is \tcode{dynamic_extent},
\item
otherwise with
\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(\exposid{rank_} - 1))}.
\end{itemize}
\end{itemize}
\end{itemdescr}

\indexlibraryctor{layout_right_padded::mapping}%
\begin{itemdecl}
template<class OtherIndexType>
constexpr mapping(const extents_type& ext, OtherIndexType padding);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{pad} be
\tcode{extents_type::\exposid{index-cast}(std::move(padding))}.

\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<OtherIndexType, index_type>} is \tcode{true}.
\item
\tcode{is_nothrow_constructible_v<index_type, OtherIndexType>} is \tcode{true}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{pad} is representable as a value of type \tcode{index_type}.
\item
\tcode{pad} is greater than zero.
\item
If \exposid{rank_} is greater than one,
then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\exposid{rank_} - 1))}
is representable as a value of type \tcode{index_type}.
\item
If \exposid{rank_} is greater than one,
then the product of
\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\exposid{\linebreak rank_} - 1))} and
all values \tcode{ext.extent($k$)}
with $k$ in the range of \range{0}{\exposid{rank_} - 1}
is representable as a value of type \tcode{index_type}.
\item
If \tcode{padding_value} is not equal to \tcode{dynamic_extent},
\tcode{padding_value} equals \tcode{pad}.
\end{itemize}

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{ext}, and
if \exposid{rank_} is greater than one,
direct-non-list-initializes \exposid{stride-rm2} with
\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\exposid{rank_} - 1))}.
\end{itemdescr}

\indexlibraryctor{layout_right_padded::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
    mapping(const layout_right::mapping<OtherExtents>& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<extents_type, OtherExtents>} is \tcode{true}.

\pnum
\mandates
If \tcode{OtherExtents::rank()} is greater than 1, then
\begin{codeblock}
(@\exposid{static-padding-stride}@ == dynamic_extent) ||
(OtherExtents::static_extent(@\exposid{rank_}@ - 1) == dynamic_extent) ||
(@\exposid{static-padding-stride}@ == OtherExtents::static_extent(@\exposid{rank_}@ - 1))
\end{codeblock}
is \tcode{true}.

\pnum
\expects
\begin{itemize}
\item
If \tcode{\exposid{rank_} > 1} is \tcode{true} and
\tcode{padding_value == dynamic_extent} is \tcode{false}, then
\tcode{other.stride(\newline \exposid{rank_} - 2)} equals
\begin{codeblock}
@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value,
                        extents_type::@\exposid{index-cast}@(other.extents().extent(rank_ - 1)))
\end{codeblock}
and
\item
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}.
\end{itemize}

\pnum
\effects
Equivalent to \tcode{mapping(other.extents())}.
\end{itemdescr}

\indexlibraryctor{layout_right_padded::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  constexpr explicit(@\seebelow@)
    mapping(const layout_stride::mapping<OtherExtents>& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<extents_type, OtherExtents>} is \tcode{true}.

\pnum
\expects
\begin{itemize}
\item
If \exposid{rank_} is greater than 1 and
\tcode{padding_value} does not equal \tcode{dynamic_extent},
then \tcode{other.\linebreak stride(\exposid{rank_} - 2)} equals
\begin{codeblock}
@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value,
                        extents_type::@\exposid{index-cast}@(other.extents().extent(@\exposid{rank_}@ - 1)))
\end{codeblock}
\item
If \exposid{rank_} is greater than 0,
then other.stride(\exposid{rank_} - 1) equals 1.
\item
If \exposid{rank_} is greater than 2,
then for all $r$ in the range \range{0}{\exposid{rank_} - 2},
\tcode{other.stride($r$)} equals
\begin{codeblock}
(other.extents().@\exposid{rev-prod-of-extents}@(r) / other.extents().extent(@\exposid{rank_}@ - 1)) *
  other.stride(@\exposid{rank_}@ - 2)
\end{codeblock}
\item
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}.
\end{itemize}

\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}; and
\item
if \exposid{rank_} is greater than one,
direct-non-list-initializes \exposid{stride-rm2}
with \tcode{other.stride(\exposid{rank_} - 2)}.
\end{itemize}

\pnum
\remarks
The expression inside \tcode{explicit} is equivalent to:
\begin{codeblock}
!(rank_ == 0 && is_convertible_v<OtherExtents, extents_type>)
\end{codeblock}
\end{itemdescr}

\indexlibraryctor{layout_right_padded::mapping}%
\begin{itemdecl}
template<class LayoutRightPaddedMapping>
  constexpr explicit(@\seebelow@)
    mapping(const LayoutRightPaddedMapping& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{\exposid{is-layout-right-padded-mapping-of}<LayoutRightPaddedMapping>}
is \tcode{true}.
\item
\tcode{is_constructible_v<extents_type, typename LayoutRightPaddedMapping::extents_-\newline type>}
is \tcode{true}.
\end{itemize}

\pnum
\mandates
If \exposid{rank_} is greater than 1, then
\begin{codeblock}
padding_value == dynamic_extent ||
LayoutRightPaddedMapping::padding_value == dynamic_extent ||
padding_value == LayoutRightPaddedMapping::padding_value
\end{codeblock}
is \tcode{true}.

\pnum
\expects
\begin{itemize}
\item
If \exposid{rank_} is greater than 1 and
\tcode{padding_value} does not equal \tcode{dynamic_extent},
then \tcode{other.\linebreak stride(\exposid{rank_} - 2)} equals
\begin{codeblock}
@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value,
                        extents_type::@\exposid{index-cast}@(other.extent(@\exposid{rank_}@ - 1)))
\end{codeblock}
\item
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}.
\end{itemize}

\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}; and
\item
if \exposid{rank_} is greater than one,
direct-non-list-initializes \exposid{stride-rm2}
with \tcode{other.stride(rank_ - 2)}.
\end{itemize}

\pnum
\remarks
The expression inside \tcode{explicit} is equivalent to:
\begin{codeblock}
!is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type> ||
@\exposid{rank_}@ > 1 &&
(padding_value != dynamic_extent ||
 LayoutRightPaddedMapping::padding_value == dynamic_extent)
\end{codeblock}
\end{itemdescr}

\indexlibraryctor{layout_right_padded::mapping}%
\begin{itemdecl}
template<class LayoutLeftPaddedMapping>
  constexpr explicit(@\seebelow@)
    mapping(const LayoutLeftPaddedMapping& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{\exposid{is-layout-left-padded-mapping-of}<LayoutLeftPaddedMapping>}
is \tcode{true} or\newline
\tcode{\exposid{is-mapping-of}<layout_left, LayoutLeftPaddedMapping>}
is \tcode{true}.
\item
\exposid{rank_} equals zero or one.
\item
\tcode{is_constructible_v<extents_type, typename LayoutLeftPaddedMapping::extents_type>}\newline
is \tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}.

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}.

\pnum
\remarks
The expression inside \tcode{explicit} is equivalent to:
\begin{codeblock}
!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type>
\end{codeblock}
\begin{note}
Neither the input mapping nor the mapping to be constructed
uses the padding stride in the rank-0 or rank-1 case,
so the padding stride affects neither the constraints nor the preconditions.
\end{note}
\end{itemdescr}

\rSec5[mdspan.layout.rightpad.obs]{Observers}

\indexlibrarymember{strides}{layout_right_padded::mapping}%
\begin{itemdecl}
constexpr array<index_type, @\exposid{rank_}@> strides() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{array<index_type, \exposid{rank_}>({stride(P_rank)...})}.
\end{itemdescr}

\indexlibrarymember{required_span_size}{layout_right_padded::mapping}%
\begin{itemdecl}
constexpr index_type required_span_size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{0} if the multidimensional index space \exposid{extents_} is empty,
otherwise \tcode{(*this)(\exposid{extents_}.extent(P_rank) - index_type(1)...) + 1}.
\end{itemdescr}

\indexlibrarymember{operator()}{layout_right_padded::mapping}%
\begin{itemdecl}
template<class... Indices>
constexpr index_type operator()(Indices... idxs) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{sizeof...(Indices) == \exposid{rank_}} is \tcode{true}.
\item
\tcode{(is_convertible_v<Indices, index_type> \&\& ...)} is \tcode{true}.
\item
\tcode{(is_nothrow_constructible_v<index_type, Indices> \&\& ...)} is \tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{extents_type::\exposid{index-cast}(idxs)} is
a multidimensional index in \tcode{extents()}\iref{mdspan.overview}.

\pnum
\returns
\tcode{((static_cast<index_type>(std::move(idxs)) * stride(P_rank)) + ... + 0)}.
\end{itemdescr}

\indexlibrarymember{is_always_exhaustive}{layout_right_padded::mapping}%
\begin{itemdecl}
static constexpr bool is_always_exhaustive() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{itemize}
\item
If \exposid{rank_} equals zero or one, then \tcode{true};
\item
otherwise,
if neither \exposid{static-padding-stride} nor \exposid{last-static-extent}
equal \tcode{dynamic_extent},
then \tcode{\exposid{static-padding-stride} == \exposid{last-static-extent}};
\item
otherwise, \tcode{false}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{is_exhaustive}{layout_right_padded::mapping}%
\begin{itemdecl}
constexpr bool is_exhaustive() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if \exposid{rank_} equals zero or one;
otherwise,
\begin{codeblock}
@\exposid{extents_}@.extent(@\exposid{rank_}@ - 1) == stride(@\exposid{rank_}@ - 2)
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{stride}{layout_right_padded::mapping}%
\begin{itemdecl}
constexpr index_type stride(rank_type r) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{r} is smaller than \exposid{rank_}.

\pnum
\returns
\begin{itemize}
\item
If \tcode{r} equals \tcode{\exposid{rank_} - 1}: \tcode{1};
\item
otherwise, if \tcode{r} equals \tcode{\exposid{rank_} - 2}: \exposid{stride-rm2};
\item
otherwise,
the product of \exposid{stride-rm2} and
all values \tcode{extents_.extent($k$)}
with $k$ in the range of \range{r + 1}{\exposid{rank_} - 1}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{operator==}{layout_right_padded::mapping}%
\begin{itemdecl}
template<class LayoutRightPaddedMapping>
  friend constexpr bool operator==(const mapping& x, const LayoutRightPaddedMapping& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{\exposid{is-layout-right-padded-mapping-of}<LayoutRightPaddedMapping>}
is \tcode{true}.
\item
\tcode{LayoutRightPaddedMapping::extents_type::rank() == \exposid{rank_}}
is \tcode{true}.
\end{itemize}

\pnum
\returns
\tcode{true} if \tcode{x.extents() == y.extents()} is \tcode{true} and
\tcode{\exposid{rank_} < 2 || x.stride(\exposid{rank_} - 2) == y.stride(\exposid{rank_} - 2)} is \tcode{true}.
Otherwise, \tcode{false}.
\end{itemdescr}

\rSec3[mdspan.accessor]{Accessor policy}

\rSec4[mdspan.accessor.general]{General}

\pnum
An \defn{accessor policy} defines types and operations by which
a reference to a single object is created
from an abstract data handle to a number of such objects and an index.

\pnum
A range of indices $[0, N)$ is an \defnadj{accessible}{range} of
a given data handle and an accessor
if, for each $i$ in the range,
the accessor policy's \tcode{access} function produces a valid reference to an object.

\pnum
In \ref{mdspan.accessor.reqmts},

\begin{itemize}
\item
\tcode{A} denotes an accessor policy.
\item
\tcode{a} denotes a value of type \tcode{A} or \tcode{const A}.
\item
\tcode{p} denotes a value of type \tcode{A::data_handle_type} or \tcode{const A::data_handle_type}.
\begin{note}
The type \tcode{A::data_handle_type} need not be dereferenceable.
\end{note}
\item
\tcode{n}, \tcode{i}, and \tcode{j} each denote values of type \tcode{size_t}.
\end{itemize}

\rSec4[mdspan.accessor.reqmts]{Requirements}

\pnum
A type \tcode{A} meets the accessor policy requirements if
\begin{itemize}
\item
\tcode{A} models \libconcept{copyable},
\item
\tcode{is_nothrow_move_constructible_v<A>} is \tcode{true},
\item
\tcode{is_nothrow_move_assignable_v<A>} is \tcode{true},
\item
\tcode{is_nothrow_swappable_v<A>} is \tcode{true}, and
\item
the following types and expressions
are well-formed and have the specified semantics.
\end{itemize}

\begin{itemdecl}
typename A::element_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A complete object type that is not an abstract class type.
\end{itemdescr}

\begin{itemdecl}
typename A::data_handle_type
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A type that models \libconcept{copyable}, and
for which \tcode{is_nothrow_move_constructible_v<A::data_handle_type>} is \tcode{true},
\tcode{is_nothrow_move_assignable_v<A::data_handle_type>} is \tcode{true}, and
\tcode{is_nothrow_swappable_v<A::data_handle_type>} is \tcode{true}.
\begin{note}
The type of \tcode{data_handle_type} need not be \tcode{element_type*}.
\end{note}
\end{itemdescr}

\begin{itemdecl}
typename A::reference
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A type that models
\tcode{\libconcept{common_reference_with}<A::reference\&\&, A::element_type\&>}.
\begin{note}
The type of \tcode{reference} need not be \tcode{element_type\&}.
\end{note}
\end{itemdescr}

\begin{itemdecl}
typename A::offset_policy
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A type \tcode{OP} such that:

\begin{itemize}
\item
\tcode{OP} meets the accessor policy requirements,
\item
\tcode{\libconcept{constructible_from}<OP, const A\&>} is modeled, and
\item
\tcode{is_same_v<typename OP::element_type, typename A::element_type>} is \tcode{true}.
\end{itemize}
\end{itemdescr}

\begin{itemdecl}
a.access(p, i)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{A::reference}

\pnum
\remarks
The expression is equality preserving.

\pnum
\begin{note}
Concrete accessor policies can impose preconditions for their \tcode{access} function.
However, they might not.
For example, an accessor where
\tcode{p} is \tcode{span<A::element_type, dynamic_extent>} and
\tcode{access(p, i)} returns \tcode{p[i \% p.size()]}
does not need to impose a precondition on \tcode{i}.
\end{note}
\end{itemdescr}

\begin{itemdecl}
a.offset(p, i)
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
\tcode{A::offset_policy::data_handle_type}

\pnum
\returns
\tcode{q} such that for \tcode{b} being \tcode{A::offset_policy(a)}, and
any integer \tcode{n} for which $[0, \tcode{n})$ is
an accessible range of \tcode{p} and \tcode{a}:
\begin{itemize}
\item
$[0, \tcode{n} - \tcode{i})$ is an accessible range of \tcode{q} and \tcode{b}; and
\item
\tcode{b.access(q, j)} provides access to
the same element as \tcode{a.access(p, i + j)},
for every \tcode{j} in the range $[0, \tcode{n} - \tcode{i})$.
\end{itemize}

\pnum
\remarks
The expression is equality-preserving.
\end{itemdescr}

\rSec4[mdspan.accessor.default]{Class template \tcode{default_accessor}}

\rSec5[mdspan.accessor.default.overview]{Overview}

\begin{codeblock}
namespace std {
  template<class ElementType>
  struct @\libglobal{default_accessor}@ {
    using @\libmember{offset_policy}{default_accessor}@ = default_accessor;
    using @\libmember{element_type}{default_accessor}@ = ElementType;
    using @\libmember{reference}{default_accessor}@ = ElementType&;
    using @\libmember{data_handle_type}{default_accessor}@ = ElementType*;

    constexpr default_accessor() noexcept = default;
    template<class OtherElementType>
      constexpr default_accessor(default_accessor<OtherElementType>) noexcept;
    constexpr reference access(data_handle_type p, size_t i) const noexcept;
    constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
  };
}
\end{codeblock}

\pnum
\tcode{default_accessor} meets the accessor policy requirements.

\pnum
\tcode{ElementType} is required to be a complete object type
that is neither an abstract class type nor an array type.

\pnum
Each specialization of \tcode{default_accessor} is
a trivially copyable type that models \libconcept{semiregular}.

\pnum
$[0, n)$ is an accessible range for
an object \tcode{p} of type \tcode{data_handle_type} and
an object of type \tcode{default_accessor}
if and only if \range{p}{p + $n$} is a valid range.

\rSec5[mdspan.accessor.default.members]{Members}

\indexlibraryctor{default_accessor}%
\begin{itemdecl}
template<class OtherElementType>
  constexpr default_accessor(default_accessor<OtherElementType>) noexcept {}
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_convertible_v<OtherElementType(*)[], element_type(*)[]>}
is \tcode{true}.
\end{itemdescr}

\indexlibrarymember{access}{default_accessor}%
\begin{itemdecl}
constexpr reference access(data_handle_type p, size_t i) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return p[i];}
\end{itemdescr}

\indexlibrarymember{offset}{default_accessor}%
\begin{itemdecl}
constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return p + i;}
\end{itemdescr}

\rSec4[mdspan.accessor.aligned]{Class template \tcode{aligned_accessor}}

\rSec5[mdspan.accessor.aligned.overview]{Overview}

\begin{codeblock}
namespace std {
  template<class ElementType, size_t ByteAlignment>
  struct @\libglobal{aligned_accessor}@ {
    using @\libmember{offset_policy}{aligned_accessor}@ = default_accessor<ElementType>;
    using @\libmember{element_type}{aligned_accessor}@ = ElementType;
    using @\libmember{reference}{aligned_accessor}@ = ElementType&;
    using @\libmember{data_handle_type}{aligned_accessor}@ = ElementType*;

    static constexpr size_t @\libmember{byte_alignment}{aligned_accessor}@ = ByteAlignment;

    constexpr aligned_accessor() noexcept = default;
    template<class OtherElementType, size_t OtherByteAlignment>
      constexpr aligned_accessor(
        aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;
    template<class OtherElementType>
      constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept;

    template<class OtherElementType>
      constexpr operator default_accessor<OtherElementType>() const noexcept;

    constexpr reference access(data_handle_type p, size_t i) const noexcept;

    constexpr typename offset_policy::data_handle_type offset(
      data_handle_type p, size_t i) const noexcept;
  };
}
\end{codeblock}

\pnum
\mandates
\begin{itemize}
\item \tcode{byte_alignment} is a power of two, and
\item \tcode{byte_alignment >= alignof(ElementType)} is \tcode{true}.
\end{itemize}

\pnum
\tcode{aligned_accessor} meets the accessor policy requirements.

\pnum
\tcode{ElementType} is required to be a complete object type
that is neither an abstract class type nor an array type.

\pnum
Each specialization of \tcode{aligned_accessor} is
a trivially copyable type that models \libconcept{semiregular}.

\pnum
\range{0}{$n$} is an accessible range
for an object \tcode{p} of type \tcode{data_handle_type} and
an object of type \tcode{aligned_accessor} if and only if
\begin{itemize}
\item
\range{p}{p + $n$} is a valid range, and,
\item
if $n$ is greater than zero,
then \tcode{is_sufficiently_aligned<byte_alignment>(p)} is \tcode{true}.
\end{itemize}

\pnum
\begin{example}
The following function \tcode{compute}
uses \tcode{is_sufficiently_aligned} to check
whether a given \tcode{mdspan} with \tcode{default_accessor} has
a data handle with sufficient alignment
to be used with \tcode{aligned_accessor<float, 4 * sizeof(float)>}.
If so, the function dispatches to
a function \tcode{compute_using_fourfold_overalignment}
that requires fourfold over-alignment of arrays,
but can therefore use hardware-specific instructions,
such as four-wide SIMD (Single Instruction Multiple Data) instructions.
Otherwise, \tcode{compute} dispatches to a
possibly less optimized function \tcode{compute_without_requiring_overalignment}
that has no over-alignment requirement.
\begin{codeblock}
void compute_using_fourfold_overalignment(
  mdspan<float, dims<1>, layout_right, aligned_accessor<float, 4 * alignof(float)>> x);

void compute_without_requiring_overalignment(
  mdspan<float, dims<1>, layout_right> x);

void compute(mdspan<float, dims<1>> x) {
  constexpr auto byte_alignment = 4 * sizeof(float);
  auto accessor = aligned_accessor<float, byte_alignment>{};
  auto x_handle = x.data_handle();

  if (is_sufficiently_aligned<byte_alignment>(x_handle)) {
    compute_using_fourfold_overalignment(mdspan{x_handle, x.mapping(), accessor});
  } else {
    compute_without_requiring_overalignment(x);
  }
}
\end{codeblock}
\end{example}

\rSec5[mdspan.accessor.aligned.members]{Members}

\indexlibraryctor{aligned_accessor}%
\begin{itemdecl}
template<class OtherElementType, size_t OtherByteAlignment>
  constexpr aligned_accessor(aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<OtherElementType(*)[], element_type(*)[]>}
is \tcode{true}.
\item
\tcode{OtherByteAlignment >= byte_alignment} is \tcode{true}.
\end{itemize}

\pnum
\effects
None.
\end{itemdescr}

\indexlibraryctor{aligned_accessor}%
\begin{itemdecl}
template<class OtherElementType>
  constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_convertible_v<OtherElementType(*)[], element_type(*)[]>}
is \tcode{true}.

\pnum
\effects
None.
\end{itemdescr}

\indexlibrarymember{access}{aligned_accessor}%
\begin{itemdecl}
constexpr reference access(data_handle_type p, size_t i) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\range{0}{i + 1} is an accessible range for \tcode{p} and \tcode{*this}.

\pnum
\effects
Equivalent to: \tcode{return assume_aligned<byte_alignment>(p)[i];}
\end{itemdescr}

\indexlibrarymember{operator default_accessor}{aligned_accessor}%
\begin{itemdecl}
template<class OtherElementType>
  constexpr operator default_accessor<OtherElementType>() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_convertible_v<element_type(*)[], OtherElementType(*)[]>}
is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return \{\};}
\end{itemdescr}

\indexlibrarymember{offset}{aligned_accessor}%
\begin{itemdecl}
constexpr typename offset_policy::data_handle_type
  offset(data_handle_type p, size_t i) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\range{0}{i + 1} is an accessible range for \tcode{p} and \tcode{*this}.

\pnum
\effects
Equivalent to: \tcode{return assume_aligned<byte_alignment>(p) + i;}
\end{itemdescr}

\rSec3[mdspan.mdspan]{Class template \tcode{mdspan}}

\rSec4[mdspan.mdspan.overview]{Overview}

\pnum
\tcode{mdspan} is a view of a multidimensional array of elements.

\begin{codeblock}
namespace std {
  template<class ElementType, class Extents, class LayoutPolicy = layout_right,
           class AccessorPolicy = default_accessor<ElementType>>
  class @\libglobal{mdspan}@ {
  public:
    using @\libmember{extents_type}{mdspan}@ = Extents;
    using @\libmember{layout_type}{mdspan}@ = LayoutPolicy;
    using @\libmember{accessor_type}{mdspan}@ = AccessorPolicy;
    using @\libmember{mapping_type}{mdspan}@ = layout_type::template mapping<extents_type>;
    using @\libmember{element_type}{mdspan}@ = ElementType;
    using @\libmember{value_type}{mdspan}@ = remove_cv_t<element_type>;
    using @\libmember{index_type}{mdspan}@ = extents_type::index_type;
    using @\libmember{size_type}{mdspan}@ = extents_type::size_type;
    using @\libmember{rank_type}{mdspan}@ = extents_type::rank_type;
    using @\libmember{data_handle_type}{mdspan}@ = accessor_type::data_handle_type;
    using @\libmember{reference}{mdspan}@ = accessor_type::reference;

    static constexpr rank_type @\libmember{rank}{mdspan}@() noexcept { return extents_type::rank(); }
    static constexpr rank_type @\libmember{rank_dynamic}{mdspan}@() noexcept { return extents_type::rank_dynamic(); }
    static constexpr size_t @\libmember{static_extent}{mdspan}@(rank_type r) noexcept
      { return extents_type::static_extent(r); }
    constexpr index_type @\libmember{extent}{mdspan}@(rank_type r) const noexcept { return extents().extent(r); }

    // \ref{mdspan.mdspan.cons}, constructors
    constexpr mdspan();
    constexpr mdspan(const mdspan& rhs) = default;
    constexpr mdspan(mdspan&& rhs) = default;

    template<class... OtherIndexTypes>
      constexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts);
    template<class OtherIndexType, size_t N>
      constexpr explicit(N != rank_dynamic())
        mdspan(data_handle_type p, span<OtherIndexType, N> exts);
    template<class OtherIndexType, size_t N>
      constexpr explicit(N != rank_dynamic())
        mdspan(data_handle_type p, const array<OtherIndexType, N>& exts);
    constexpr mdspan(data_handle_type p, const extents_type& ext);
    constexpr mdspan(data_handle_type p, const mapping_type& m);
    constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);

    template<class OtherElementType, class OtherExtents,
             class OtherLayoutPolicy, class OtherAccessorPolicy>
      constexpr explicit(@\seebelow@)
        mdspan(const mdspan<OtherElementType, OtherExtents,
                            OtherLayoutPolicy, OtherAccessorPolicy>& other);

    constexpr mdspan& operator=(const mdspan& rhs) = default;
    constexpr mdspan& operator=(mdspan&& rhs) = default;

    // \ref{mdspan.mdspan.members}, members
    template<class... OtherIndexTypes>
      constexpr reference operator[](OtherIndexTypes... indices) const;
    template<class OtherIndexType>
      constexpr reference operator[](span<OtherIndexType, rank()> indices) const;
    template<class OtherIndexType>
      constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;

    template<class... OtherIndexTypes>
      constexpr reference
        at(OtherIndexTypes... indices) const;                           // freestanding-deleted
    template<class OtherIndexType>
      constexpr reference
        at(span<OtherIndexType, rank()> indices) const;                 // freestanding-deleted
    template<class OtherIndexType>
      constexpr reference
        at(const array<OtherIndexType, rank()>& indices) const;         // freestanding-deleted

    constexpr size_type size() const noexcept;
    constexpr bool empty() const noexcept;

    friend constexpr void swap(mdspan& x, mdspan& y) noexcept;

    constexpr const extents_type& @\libmember{extents}{mdspan}@() const noexcept { return @\exposid{map_}@.extents(); }
    constexpr const data_handle_type& @\libmember{data_handle}{mdspan}@() const noexcept { return @\exposid{ptr_}@; }
    constexpr const mapping_type& @\libmember{mapping}{mdspan}@() const noexcept { return @\exposid{map_}@; }
    constexpr const accessor_type& @\libmember{accessor}{mdspan}@() const noexcept { return @\exposid{acc_}@; }

    static constexpr bool @\libmember{is_always_unique}{mdspan}@()
      { return mapping_type::is_always_unique(); }
    static constexpr bool @\libmember{is_always_exhaustive}{mdspan}@()
      { return mapping_type::is_always_exhaustive(); }
    static constexpr bool @\libmember{is_always_strided}{mdspan}@()
      { return mapping_type::is_always_strided(); }

    constexpr bool @\libmember{is_unique}{mdspan}@() const
      { return @\exposid{map_}@.is_unique(); }
    constexpr bool @\libmember{is_exhaustive}{mdspan}@() const
      { return @\exposid{map_}@.is_exhaustive(); }
    constexpr bool @\libmember{is_strided}{mdspan}@() const
      { return @\exposid{map_}@.is_strided(); }
    constexpr index_type @\libmember{stride}{mdspan}@(rank_type r) const
      { return @\exposid{map_}@.stride(r); }

  private:
    accessor_type @\exposid{acc_}@;         // \expos
    mapping_type @\exposid{map_}@;          // \expos
    data_handle_type @\exposid{ptr_}@;      // \expos
  };

  template<class CArray>
    requires (is_array_v<CArray> && rank_v<CArray> == 1)
    mdspan(CArray&)
      -> mdspan<remove_all_extents_t<CArray>, extents<size_t, extent_v<CArray, 0>>>;

  template<class Pointer>
    requires (is_pointer_v<remove_reference_t<Pointer>>)
    mdspan(Pointer&&)
      -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;

  template<class ElementType, class... Integrals>
    requires ((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
    explicit mdspan(ElementType*, Integrals...)
      -> mdspan<ElementType, extents<size_t, @\exposconcept{maybe-static-ext}@<Integrals>...>>;

  template<class ElementType, class OtherIndexType, size_t N>
    mdspan(ElementType*, span<OtherIndexType, N>)
      -> mdspan<ElementType, dextents<size_t, N>>;

  template<class ElementType, class OtherIndexType, size_t N>
    mdspan(ElementType*, const array<OtherIndexType, N>&)
      -> mdspan<ElementType, dextents<size_t, N>>;

  template<class ElementType, class IndexType, size_t... ExtentsPack>
    mdspan(ElementType*, const extents<IndexType, ExtentsPack...>&)
      -> mdspan<ElementType, extents<IndexType, ExtentsPack...>>;

  template<class ElementType, class MappingType>
    mdspan(ElementType*, const MappingType&)
      -> mdspan<ElementType, typename MappingType::extents_type,
                typename MappingType::layout_type>;

  template<class MappingType, class AccessorType>
    mdspan(typename AccessorType::data_handle_type, const MappingType&,
           const AccessorType&)
      -> mdspan<typename AccessorType::element_type, typename MappingType::extents_type,
                typename MappingType::layout_type, AccessorType>;
}
\end{codeblock}

\pnum
\mandates
\begin{itemize}
\item
\tcode{ElementType} is a complete object type
that is neither an abstract class type nor an array type,
\item
\tcode{Extents} is a specialization of \tcode{extents}, and
\item
\tcode{is_same_v<ElementType, typename AccessorPolicy::element_type>}
is \tcode{true}.
\end{itemize}

\pnum
\tcode{LayoutPolicy} shall meet
the layout mapping policy requirements\iref{mdspan.layout.policy.reqmts}, and
\tcode{AccessorPolicy} shall meet
the accessor policy requirements\iref{mdspan.accessor.reqmts}.

\pnum
Each specialization \tcode{MDS} of \tcode{mdspan} models \libconcept{copyable} and
\begin{itemize}
\item
\tcode{is_nothrow_move_constructible_v<MDS>} is \tcode{true},
\item
\tcode{is_nothrow_move_assignable_v<MDS>} is \tcode{true}, and
\item
\tcode{is_nothrow_swappable_v<MDS>} is \tcode{true}.
\end{itemize}

\pnum
A specialization of \tcode{mdspan} is a trivially copyable type if
its \tcode{accessor_type}, \tcode{mapping_type}, and \tcode{data_handle_type}
are trivially copyable types.

\rSec4[mdspan.mdspan.cons]{Constructors}

\indexlibraryctor{mdspan}%
\begin{itemdecl}
constexpr mdspan();
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{rank_dynamic() > 0} is \tcode{true}.
\item
\tcode{is_default_constructible_v<data_handle_type>} is \tcode{true}.
\item
\tcode{is_default_constructible_v<mapping_type>} is \tcode{true}.
\item
\tcode{is_default_constructible_v<accessor_type>} is \tcode{true}.
\end{itemize}

\pnum
\expects
$[0, \tcode{\exposid{map_}.required_span_size()})$ is
an accessible range of \exposid{ptr_} and \exposid{acc_}
for the values of \exposid{map_} and \exposid{acc_}
after the invocation of this constructor.

\pnum
\effects
Value-initializes \exposid{ptr_}, \exposid{map_}, and \exposid{acc_}.
\end{itemdescr}

\indexlibraryctor{mdspan}%
\begin{itemdecl}
template<class... OtherIndexTypes>
  constexpr explicit mdspan(data_handle_type p, OtherIndexTypes... exts);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{N} be \tcode{sizeof...(OtherIndexTypes)}.

\pnum
\constraints
\begin{itemize}
\item
\tcode{(is_convertible_v<OtherIndexTypes, index_type> \&\& ...)} is \tcode{true},
\item
\tcode{(is_nothrow_constructible_v<index_type, OtherIndexTypes> \&\& ...)} is \tcode{true},
\item
\tcode{N == rank() || N == rank_dynamic()} is \tcode{true},
\item
\tcode{is_constructible_v<mapping_type, extents_type>} is \tcode{true}, and
\item
\tcode{is_default_constructible_v<accessor_type>} is \tcode{true}.
\end{itemize}

\pnum
\expects
$[0, \tcode{\exposid{map_}.required_span_size()})$ is
an accessible range of \tcode{p} and \exposid{acc_}
for the values of \exposid{map_} and \exposid{acc_}
after the invocation of this constructor.

\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)},
\item
direct-non-list-initializes \exposid{map_} with
\tcode{extents_type(static_cast<index_type>(std::move(exts\brk{}))...)}, and
\item
value-initializes \exposid{acc_}.
\end{itemize}
\end{itemdescr}

\indexlibraryctor{mdspan}%
\begin{itemdecl}
template<class OtherIndexType, size_t N>
  constexpr explicit(N != rank_dynamic())
    mdspan(data_handle_type p, span<OtherIndexType, N> exts);
template<class OtherIndexType, size_t N>
  constexpr explicit(N != rank_dynamic())
    mdspan(data_handle_type p, const array<OtherIndexType, N>& exts);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const OtherIndexType\&, index_type>} is \tcode{true},
\item
\tcode{is_nothrow_constructible_v<index_type, const OtherIndexType\&>} is \tcode{true},
\item
\tcode{N == rank() || N == rank_dynamic()} is \tcode{true},
\item
\tcode{is_constructible_v<mapping_type, extents_type>} is \tcode{true}, and
\item
\tcode{is_default_constructible_v<accessor_type>} is \tcode{true}.
\end{itemize}

\pnum
\expects
$[0, \tcode{\exposid{map_}.required_span_size()})$ is
an accessible range of \tcode{p} and \exposid{acc_}
for the values of \exposid{map_} and \exposid{acc_}
after the invocation of this constructor.

\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)},
\item
direct-non-list-initializes \exposid{map_} with \tcode{extents_type(exts)}, and
\item
value-initializes \exposid{acc_}.
\end{itemize}
\end{itemdescr}

\indexlibraryctor{mdspan}%
\begin{itemdecl}
constexpr mdspan(data_handle_type p, const extents_type& ext);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_constructible_v<mapping_type, const extents_type\&>} is \tcode{true}, and
\item
\tcode{is_default_constructible_v<accessor_type>} is \tcode{true}.
\end{itemize}

\pnum
\expects
$[0, \tcode{\exposid{map_}.required_span_size()})$ is
an accessible range of \tcode{p} and \exposid{acc_}
for the values of \exposid{map_} and \exposid{acc_}
after the invocation of this constructor.

\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)},
\item
direct-non-list-initializes \exposid{map_} with \tcode{ext}, and
\item
value-initializes \exposid{acc_}.
\end{itemize}
\end{itemdescr}

\indexlibraryctor{mdspan}%
\begin{itemdecl}
constexpr mdspan(data_handle_type p, const mapping_type& m);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_default_constructible_v<accessor_type>} is \tcode{true}.

\pnum
\expects
$[0, \tcode{m.required_span_size()})$ is
an accessible range of \tcode{p} and \exposid{acc_}
for the value of \exposid{acc_} after the invocation of this constructor.

\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)},
\item
direct-non-list-initializes \exposid{map_} with \tcode{m}, and
\item
value-initializes \exposid{acc_}.
\end{itemize}
\end{itemdescr}

\indexlibraryctor{mdspan}%
\begin{itemdecl}
constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$[0, \tcode{m.required_span_size()})$ is
an accessible range of \tcode{p} and \tcode{a}.

\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{ptr_} with \tcode{std::move(p)},
\item
direct-non-list-initializes \exposid{map_} with \tcode{m}, and
\item
direct-non-list-initializes \exposid{acc_} with \tcode{a}.
\end{itemize}
\end{itemdescr}

\indexlibraryctor{mdspan}%
\begin{itemdecl}
template<class OtherElementType, class OtherExtents,
         class OtherLayoutPolicy, class OtherAccessor>
  constexpr explicit(@\seebelow@)
    mdspan(const mdspan<OtherElementType, OtherExtents,
                        OtherLayoutPolicy, OtherAccessor>& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_constructible_v<mapping_type, const OtherLayoutPolicy::template mapping<Oth-\newline erExtents>\&>}
is \tcode{true}, and
\item
\tcode{is_constructible_v<accessor_type, const OtherAccessor\&>} is \tcode{true}.
\end{itemize}

\pnum
\mandates
\begin{itemize}
\item
\tcode{is_constructible_v<data_handle_type, const OtherAccessor::data_handle_type\&>} is\newline \tcode{true}, and
\item
\tcode{is_constructible_v<extents_type, OtherExtents>} is \tcode{true}.
\end{itemize}

\pnum
\expects
$[0, \tcode{\exposid{map_}.required_span_size()})$ is
an accessible range of \exposid{ptr_} and \exposid{acc_}
for values of \exposid{ptr_}, \exposid{map_}, and \exposid{acc_}
after the invocation of this constructor.

\pnum
\hardexpects
For each rank index \tcode{r} of \tcode{extents_type},
\tcode{static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r)}
is \tcode{true}.

\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{ptr_} with \tcode{other.\exposid{ptr_}},
\item
direct-non-list-initializes \exposid{map_} with \tcode{other.\exposid{map_}}, and
\item
direct-non-list-initializes \exposid{acc_} with \tcode{other.\exposid{acc_}}.
\end{itemize}

\pnum
\remarks
The expression inside \tcode{explicit} is equivalent to:
\begin{codeblock}
!is_convertible_v<const OtherLayoutPolicy::template mapping<OtherExtents>&, mapping_type>
|| !is_convertible_v<const OtherAccessor&, accessor_type>
\end{codeblock}
\end{itemdescr}

\rSec4[mdspan.mdspan.members]{Members}

\indexlibrarymember{operator[]}{mdspan}%
\begin{itemdecl}
template<class... OtherIndexTypes>
  constexpr reference operator[](OtherIndexTypes... indices) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{(is_convertible_v<OtherIndexTypes, index_type> \&\& ...)} is \tcode{true},
\item
\tcode{(is_nothrow_constructible_v<index_type, OtherIndexTypes> \&\& ...)} is \tcode{true}, and
\item
\tcode{sizeof...(OtherIndexTypes) == rank()} is \tcode{true}.
\end{itemize}

\pnum
Let \tcode{I} be \tcode{extents_type::\exposid{index-cast}(std::move(indices))}.

\pnum
\hardexpects
\tcode{I} is a multidimensional index in \tcode{extents()}.
\begin{note}
This implies that
\tcode{\exposid{map_}(I) < \exposid{map_}.required_span_size()}
is \tcode{true}.
\end{note}

\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{acc_}@.access(@\exposid{ptr_}@, @\exposid{map_}@(static_cast<index_type>(std::move(indices))...));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator[]}{mdspan}%
\begin{itemdecl}
template<class OtherIndexType>
  constexpr reference operator[](span<OtherIndexType, rank()> indices) const;
template<class OtherIndexType>
  constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const OtherIndexType\&, index_type>} is \tcode{true}, and
\item
\tcode{is_nothrow_constructible_v<index_type, const OtherIndexType\&>} is \tcode{true}.
\end{itemize}

\pnum
\effects
Let \tcode{P} be a parameter pack such that
\begin{codeblock}
is_same_v<make_index_sequence<rank()>, index_sequence<P...>>
\end{codeblock}
is \tcode{true}.
Equivalent to:
\begin{codeblock}
return operator[](extents_type::@\exposid{index-cast}@(as_const(indices[P]))...);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{at}{mdspan}%
\begin{itemdecl}
template<class... OtherIndexTypes>
  constexpr reference at(OtherIndexTypes... indices) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{(is_convertible_v<OtherIndexTypes, index_type> \&\& ...)} is \tcode{true},
\item
\tcode{(is_nothrow_constructible_v<index_type, OtherIndexTypes> \&\& ...)} is \tcode{true}, and
\item
\tcode{sizeof...(OtherIndexTypes) == rank()}  is \tcode{true}.
\end{itemize}

\pnum
Let \tcode{I} be \tcode{extents_type::\exposid{index-cast}(std::move(indices))}.

\pnum
\returns
\tcode{(*this)[I...]}.

\pnum
\throws
\tcode{out_of_range} if \tcode{I} is not a multidimensional index in \tcode{extents()}.
\end{itemdescr}

\indexlibrarymember{at}{mdspan}%
\begin{itemdecl}
template<class OtherIndexType>
  constexpr reference at(span<OtherIndexType, rank()> indices) const;
template<class OtherIndexType>
  constexpr reference at(const array<OtherIndexType, rank()>& indices) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const OtherIndexType\&, index_type>} is \tcode{true}, and
\item
\tcode{is_nothrow_constructible_v<index_type, const OtherIndexType\&>} is \tcode{true}.
\end{itemize}

\pnum
\effects
Let \tcode{P} be a parameter pack such that
\begin{codeblock}
is_same_v<make_index_sequence<rank()>, index_sequence<P...>>
\end{codeblock}
is \tcode{true}.
Equivalent to:
\begin{codeblock}
return at(extents_type::@\exposid{index-cast}@(as_const(indices[P]))...);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{size}{mdspan}%
\begin{itemdecl}
constexpr size_type size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
The size of the multidimensional index space \tcode{extents()}
is representable as a value of type \tcode{size_type}\iref{basic.fundamental}.

\pnum
\returns
\tcode{extents().\exposid{fwd-prod-of-extents}(rank())}.
\end{itemdescr}

\indexlibrarymember{empty}{mdspan}%
\begin{itemdecl}
constexpr bool empty() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true}
if the size of the multidimensional index space \tcode{extents()} is 0,
otherwise \tcode{false}.
\end{itemdescr}

\indexlibrarymember{swap}{mdspan}%
\begin{itemdecl}
friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
swap(x.@\exposid{ptr_}@, y.@\exposid{ptr_}@);
swap(x.@\exposid{map_}@, y.@\exposid{map_}@);
swap(x.@\exposid{acc_}@, y.@\exposid{acc_}@);
\end{codeblock}
\end{itemdescr}

\rSec3[mdspan.sub]{\tcode{submdspan}}

\rSec4[mdspan.sub.overview]{Overview}

\pnum
The \tcode{submdspan} facilities create a new \tcode{mdspan}
viewing a subset of elements of an existing input \tcode{mdspan}.
The subset viewed by the created \tcode{mdspan} is determined by
the \tcode{SliceSpecifier} arguments.

\pnum
Given a signed or unsigned integer type \tcode{IndexType},
a type $S$ is a
\defnx{\tcode{submdspan} slice type for \tcode{IndexType}}{\tcode{submdspan}!slice type for \tcode{IndexType}}
if at least one of the following holds:
\begin{itemize}
\item
  \tcode{is_convertible_v<$S$, full_extent_t>} is \tcode{true};
\item
  \tcode{is_convertible_v<$S$, IndexType>} is \tcode{true};
\item
  $S$ is a specialization of \tcode{extent_slice} and
  \tcode{is_convertible_v<$X$, IndexType>} is \tcode{true} for $X$ denoting
  \tcode{$S$::offset_type},
  \tcode{$S$::extent_type}, and
  \tcode{$S$::stride_type};
\item
  $S$ is a specialization of \tcode{range_slice} and
  \tcode{is_convertible_v<$X$, IndexType>} is \tcode{true} for $X$ denoting type of
  \tcode{$S$::first},
  \tcode{$S$::last}, and
  \tcode{$S$::stride} members; or
\item
  all of the following hold:
  \begin{itemize}
  \item
    the declaration \tcode{auto [...ls] = std::move(s);} is well-formed
    for some object \tcode{s} of type $S$,
  \item
    \tcode{sizeof...(ls)} is equal to 2, and
  \item
    \tcode{(is_convertible_v<decltype(std::move(ls)), IndexType> \&\& ...)} is \tcode{true}.
  \end{itemize}
\end{itemize}

\pnum
Given a signed or unsigned integer type \tcode{IndexType},
a type $S$ is a
\defnx{canonical \tcode{submdspan} index type for \tcode{IndexType}}{\tcode{submdspan}!canonical index type for \tcode{IndexType}}
if $S$ is either \tcode{IndexType} or \tcode{constant_wrapper<v>}
for some value \tcode{v} of type \tcode{IndexType},
such that \tcode{v} is greater than or equal to zero.

\pnum
Given a signed or unsigned integer type \tcode{IndexType},
a type $S$ is a
\defnx{canonical \tcode{submdspan} slice type for \tcode{IndexType}}{\tcode{submdspan}!canonical slice type for \tcode{IndexType}}
if exactly one of the following is \tcode{true}:
\begin{itemize}
\item
  $S$ is \tcode{full_extent_t};
\item
  $S$ is a canonical \tcode{submdspan} index type for \tcode{IndexType}; or
\item
  $S$ is a specialization of \tcode{extent_slice}
  where all of the following hold:
  \begin{itemize}
  \item
    \tcode{S::offset_type}, \tcode{S::extent_type}, and \tcode{S::stride_type}
    are all canonical \tcode{submdspan} index types for \tcode{IndexType}; and
  \item
    if \tcode{$S$::stride_type} and \tcode{$S$::extent_type}
    are both specializations of \tcode{constant_wrapper},
    then \tcode{$S$::stride_type::value} is greater than zero.
  \end{itemize}
\end{itemize}

\pnum
A type \tcode{S} is a \defnadj{collapsing}{slice type} if
it is neither \tcode{full_extent_t} nor
a specialization of \tcode{extent_slice}.
\begin{note}
Each collapsing slice type in \tcode{submdspan_mapping}'s parameter pack
of slice specifier types
reduces the rank of the result of \tcode{submdspan_mapping} by one.
\end{note}

\pnum
A type \tcode{S} is a \defnadj{unit-stride}{slice type} if
\begin{itemize}
\item
  \tcode{S} is a specialization of \tcode{extent_slice}
  where \tcode{S::stride_type} is a specialization of \tcode{constant_wrapper} and
  \tcode{S::stride_type::value} is equal to 1, or
\item
  \tcode{S} denotes \tcode{full_extent_t}.
\end{itemize}

\pnum
Given an object \tcode{e} of type \tcode{E} that is a specialization of \tcode{extents}, and
an object \tcode{s} of type \tcode{S}
that is a canonical \tcode{submdspan} slice type for \tcode{E::index_type},
the \defnx{\tcode{submdspan} slice range of \tcode{s} for the $k^\text{th}$ extent of \tcode{e}}{\tcode{submdspan}!slice range of \tcode{s} for the $k^\text{th}$ extent of \tcode{e}}
is:
\begin{itemize}
\item
  \range{$0$}{e.extent($k$)},
  if \tcode{S} is \tcode{full_extent_t};
\item
  \range{E::index_type(s.offset)}{E::index_type(s.offset)},
  if \tcode{S} is a specialization of \tcode{extent_slice} and
  \tcode{E::index_type(s.extent)} is zero; otherwise
\item
  \range{E::index_type(s.offset)}{E::index_type(s.offset + 1 + (s.extent - 1) * s.stride)},
  if \tcode{S} is a specialization of \tcode{extent_slice}; otherwise
\item
  \range{\tcode{E::index_type(s)}}{$\tcode{E::index_type(s)} + 1$}
\end{itemize}

\pnum
Given a type \tcode{E} that is a specialization of \tcode{extents},
a type \tcode{S} is a
\defnx{valid \tcode{submdspan} slice type for the $k^\text{th}$ extent of \tcode{E}}{\tcode{submdspan}!valid slice type for the $k^\text{th}$ extent of \tcode{E}}
if \tcode{S} is a canonical slice type for \tcode{E::index_type}, and
for $x$ equal to \tcode{E::static_extent($k$)},
either $x$ is equal to \tcode{dynamic_extent}; or
\begin{itemize}
\item
  if \tcode{S} is a specialization of \tcode{extent_slice}, then
  \begin{itemize}
  \item
    $o$ is less than or equal to $x$;
  \item
    $e$ is less than or equal to $x$;
  \item
    if $e$ is greater than one,
    then $t$ is greater than zero,
  \item
    if $e$ is greater than zero,
    then $o + 1 + (e - 1) * t$ is less than or equal to $x$,
  \end{itemize}
  where
  \begin{itemize}
  \item
    $o$ is the value of \tcode{S::offset_type::value}
    if \tcode{S::offset_type} is a specialization of \tcode{constant_wrapper} and
    \tcode{0} otherwise,
  \item
    $e$ is the value of \tcode{S::extent_type::value}
    if \tcode{S::extend_type} is a specialization of \tcode{constant_wrapper} and
    \tcode{0} otherwise,
  \item
    $t$ is the value of \tcode{S::stride_type::value}
    if \tcode{S::stride_type} is a specialization of \tcode{constant_wrapper} and
    \tcode{1} otherwise; and
  \end{itemize}
\item
  if $S$ is a specialization of \tcode{constant_wrapper},
  then \tcode{S::value} is less than \tcode{x}.
\end{itemize}

\pnum
Given an object \tcode{e} of type \tcode{E}
that is a specialization of \tcode{extents} and
an object \tcode{s} of type \tcode{S},
\tcode{s} is a
\defnx{valid \tcode{submdspan} slice for the $k^\text{th}$ extent of \tcode{e}}{\tcode{submdspan}!valid slice for the $k^\text{th}$ extent of \tcode{e}}
if
\begin{itemize}
\item
  \tcode{S} is a valid \tcode{submdspan} slice type for the $k^\text{th}$ extent of \tcode{E};
\item
  the $k^\text{th}$ interval of \tcode{e}
  contains the \tcode{submdspan} slice range of \tcode{s}
  for the $k^\text{th}$ extent of \tcode{e}; and
\item
  if \tcode{S} is a specialization of \tcode{extent_slice}, then
  \begin{itemize}
  \item \tcode{s.extent} is greater than or equal to zero, and
  \item either \tcode{s.extent} is less than two or \tcode{s.stride} is greater than zero.
  \end{itemize}
\end{itemize}

\rSec4[mdspan.sub.range.slices]{Range slices}

\pnum
\tcode{extent_slice} and \tcode{range_slice} represent a set of
\tcode{extent} regularly spaced integer indices.
The indices start at \tcode{offset} and \tcode{first}, respectively, and
increase by increments of \tcode{stride}.

\indexlibraryglobal{extent_slice}%
\indexlibraryglobal{range_slice}%
\begin{codeblock}
namespace std {
  template<class OffsetType, class ExtentType, class StrideType>
  struct extent_slice {
    using @\libmember{offset_type}{extent_slice}@ = OffsetType;
    using @\libmember{extent_type}{extent_slice}@ = ExtentType;
    using @\libmember{stride_type}{extent_slice}@ = StrideType;

    [[no_unique_address]] offset_type @\libmember{offset}{extent_slice}@{};
    [[no_unique_address]] extent_type @\libmember{extent}{extent_slice}@{};
    [[no_unique_address]] stride_type @\libmember{stride}{extent_slice}@{};
  };

  template<class FirstType, class LastType, class StrideType = constant_wrapper<1zu>>
  struct range_slice {
    [[no_unique_address]] FirstType @\libmember{first}{range_slice}@{};
    [[no_unique_address]] LastType @\libmember{last}{range_slice}@{};
    [[no_unique_address]] StrideType @\libmember{stride}{range_slice}@{};
  };
}
\end{codeblock}

\pnum
\tcode{extent_slice} and \tcode{range_slice}
have the data members and special members specified above.
They have no base classes or members other than those specified.

\pnum
\mandates
\tcode{OffsetType}, \tcode{ExtentType},
\tcode{FirstType}, \tcode{LastType}, and \tcode{StrideType}
are signed or unsigned integer types, or
model \exposconcept{integral-constant-like}.
\begin{note}
Both \tcode{extent_slice\{.offset = 1, .extent = 4, .stride = 3\}} and
\tcode{range_slice\{.first = 1, .last = 11, .stride = 3\}}
indicate the indices \tcode{1}, \tcode{4}, \tcode{7}, and \tcode{10}.
Indices are selected from the half-open interval \range{1}{1 + 10}.
\end{note}

\rSec4[mdspan.sub.map.result]{\tcode{submdspan_mapping_result}}

\pnum
Specializations of \tcode{submdspan_mapping_result}
are returned by overloads of \tcode{submdspan_mapping}.

\indexlibraryglobal{submdspan_mapping_result}%
\begin{codeblock}
namespace std {
  template<class LayoutMapping>
  struct submdspan_mapping_result {
    [[no_unique_address]] LayoutMapping @\libmember{mapping}{submdspan_mapping_result}@ = LayoutMapping();
    size_t @\libmember{offset}{submdspan_mapping_result}@{};
  };
}
\end{codeblock}

\pnum
\tcode{submdspan_mapping_result} has
the data members and special members specified above.
It has no base classes or members other than those specified.

\pnum
\tcode{LayoutMapping} shall meet
the layout mapping requirements\iref{mdspan.layout.policy.reqmts}.

\rSec4[mdspan.sub.helpers]{Exposition-only helpers}

\pnum
\indexlibraryglobal{\tcode{\placeholder{MAP_RANK}}}%
For a pack \tcode{p} and an integer $i$,
let \tcode{\placeholder{MAP_RANK}(p, $i$)} be the number of elements \tcode{p...[$j$]}
for $0 \le j < i$ whose types are not collapsing slice types.

\begin{itemdecl}
template<class T>
  concept @\defexposconcept{is-extent-slice}@ = @\seebelow;@
\end{itemdecl}

\begin{itemdescr}
\pnum
The concept \tcode{\exposconcept{is-extent-slice}<T>}
is satisfied and modeled if and only
if \tcode{T} is a specialization of \tcode{extent_slice}.
\end{itemdescr}

\begin{itemdecl}
template<class T>
  concept @\defexposconcept{is-range-slice}@ = @\seebelow;@
\end{itemdecl}

\begin{itemdescr}
\pnum
The concept \tcode{\exposconcept{is-range-slice}<T>}
is satisfied and modeled if and only
if \tcode{T} is a specialization of \tcode{range_slice}.
\end{itemdescr}

\indexlibraryglobal{\exposid{canonical-index}}%
\begin{itemdecl}
template<class IndexType, class S>
  constexpr auto @\exposid{canonical-index}@(S s);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
If \tcode{S} models \exposconcept{integral-constant-like},
then \tcode{extents<IndexType>::\exposid{index-cast}(S::val\-ue)}
is representable as a value of type \tcode{IndexType}.

\pnum
\expects
\tcode{extents<IndexType>::\exposid{index-cast}(std::move(s))}
is representable as a value of type \tcode{IndexType}.

\pnum
\effects
Equivalent to:
\begin{itemize}
\item
\tcode{return cw<IndexType(S::value)>;}
if \tcode{S} models \exposconcept{integral-constant-like};
\item
\tcode{return IndexType(std::move(s));} otherwise.
\end{itemize}
\end{itemdescr}

\begin{itemdecl}
template<class IndexType, class OffsetType, class SpanType, class... StrideTypes>
  constexpr auto @\exposid{canonical-range-slice}@(OffsetType offset, SpanType span, StrideTypes... strides);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let
\begin{itemize}
\item
  \tcode{StrideType} denote
  \tcode{constant_wrapper<IndexType(1)>}
  if \tcode{StrideTypes} is an empty pack or
  \tcode{SpanType} denotes \tcode{constant_wrapper<IndexType(0)>}, otherwise
  \tcode{StrideTypes...[0]};
\item
  \tcode{stride} be
  \tcode{StrideType()} if \tcode{StrideType}
  is a specialization of \tcode{constant_wrapper}, otherwise
  \tcode{IndexType(1)} if \tcode{span == 0} is \tcode{true}, otherwise
  \tcode{strides...[0]};
\item
  \exposid{extent-value} be \tcode{1 + (span - 1) / stride}
  if \tcode{span != 0} is \tcode{true}, and
  \tcode{0} otherwise; and
\item
  let \tcode{extent} be \tcode{cw<IndexType(\exposid{extent-value})>}
  if both \tcode{SpanType} and \tcode{StrideType}
  are specializations of \tcode{constant_wrapper}, and
  \tcode{IndexType(\exposid{extent-value})} otherwise.
\end{itemize}

\pnum
\mandates
\tcode{sizeof...(StrideTypes) <= 1} is \tcode{true}, and
if \tcode{StrideType} is a specialization of \tcode{con\-stant_wrapper},
then \tcode{StrideType::value > 0} is \tcode{true}.

\pnum
\expects
\tcode{stride > 0} is \tcode{true}.

\pnum
\returns
\tcode{extent_slice\{.offset = offset, .extent = extent, .stride = stride\}}.
\end{itemdescr}

\indexlibraryglobal{\exposid{canonical-slice}}
\begin{itemdecl}
template<class IndexType, class S>
  constexpr auto @\exposid{canonical-slice}@(S s);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{S} is a \tcode{submdspan} slice type for \tcode{IndexType}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
if constexpr (is_convertible_v<S, full_extent_t>) {
  return static_cast<full_extent_t>(std::move(s));
} else if constexpr (is_convertible_v<S, IndexType>) {
  return @\exposid{canonical-index}@<IndexType>(std::move(s));
} else if constexpr (@\exposconcept{is-extent-slice}@<S>) {
  return extent_slice{
    .offset = @\exposid{canonical-index}@<IndexType>(std::move(s.extent)),
    .extent = @\exposid{canonical-index}@<IndexType>(std::move(s.offset)),
    .stride = @\exposid{canonical-index}@<IndexType>(std::move(s.stride))
  };
} else if constexpr (@\exposconcept{is-range-slice}@<S>) {
  auto c_first = @\exposid{canonical-index}@<IndexType>(std::move(s.first));
  auto c_last  = @\exposid{canonical-index}@<IndexType>(std::move(s.last));
  return @\exposid{canonical-slice-range}@<IndexType>(
    c_first,
    @\exposid{canonical-index}@<IndexType>(c_last - c_first),
    @\exposid{canonical-index}@<IndexType>(std::move(s.stride)));
} else {
  auto [s_first, s_last] = std::move(s);
  auto c_first = @\exposid{canonical-index}@<IndexType>(std::move(s_first));
  auto c_last  = @\exposid{canonical-index}@<IndexType>(std::move(s_last));
  return @\exposid{canonical-slice-range}@<IndexType>(
    c_first,
    @\exposid{canonical-index}@<IndexType>(c_last - c_first));
}
\end{codeblock}
\end{itemdescr}

\rSec4[mdspan.sub.canonical]{\tcode{submdspan} slice canonicalization}

\indexlibraryglobal{canonical_slices}%
\begin{itemdecl}
template<class IndexType, size_t... Extents, class... SliceSpecifiers>
  constexpr auto canonical_slices(const extents<IndexType, Extents...>& src,
                                  SliceSpecifiers... slices);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{sizeof...(SliceSpecifiers)} equals \tcode{sizeof...(Extents)}.

\pnum
\mandates
For each rank index $k$ of \tcode{src}:
\begin{itemize}
\item
  \tcode{SliceSpecifiers...[k]}
  is a \tcode{submdspan} slice type for \tcode{IndexType}, and
\item
  \tcode{decltype(\exposid{canonical-slice}<IndexType>(slices...[k]))}
  is a valid \tcode{submdspan} slice type for the $k^\text{th}$ extent of
  \tcode{extents<IndexType, Extents...>}.
\end{itemize}

\pnum
\expects
For each rank index $k$ of \tcode{src},
\tcode{\exposid{canonical-slice}<IndexType>(slices...[k])}
is a valid \tcode{submdspan} slice for the $k^\text{th}$ extent of \tcode{src}.

\pnum
\returns
\tcode{make_tuple(\exposid{canonical-slice}<IndexType>(slices)...)}.
\end{itemdescr}

\rSec4[mdspan.sub.extents]{\tcode{subextents} function}

\indexlibraryglobal{subextents}%
\begin{itemdecl}
template<class IndexType, size_t... Extents, class... SliceSpecifiers>
  constexpr auto subextents(const extents<IndexType, Extents...>& src,
                            SliceSpecifiers... raw_slices);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{slices} be the pack introduced by the following declaration:
\begin{codeblock}
auto [...slices] = canonical_slices(src, raw_slices...);
\end{codeblock}

\pnum
\constraints
\tcode{sizeof...(SliceSpecifiers)} equals \tcode{sizeof...(Extents)}.

\pnum
\mandates
For each rank index $k$ of \tcode{src}:
\begin{itemize}
\item
  \tcode{SliceSpecifiers...[$k$]}
  is a \tcode{submdspan} slice type for \tcode{IndexType}, and
\item
  \tcode{decltype(slices...[$k$])} is a valid \tcode{submdspan} slice type
  for the $k^\text{th}$ extent of \tcode{extents<\brk{}Index\-Type, Extents...>}.
\end{itemize}

\pnum
\expects
For each rank index $k$ of \tcode{src},
\tcode{slices...[$k$]} is a valid \tcode{submdspan} slice
for the $k^\text{th}$ extent of \tcode{src}.

\pnum
Let \tcode{SubExtents} be a specialization of \tcode{extents} such that:

\begin{itemize}
\item
\tcode{SubExtents::rank()} equals
\tcode{\placeholder{MAP_RANK}(slices, Extents::rank())}; and

\item
for each rank index $k$ of \tcode{extents<IndexType, Extents...>} such that
the type of \tcode{slices...[$k$]} is not a collapsing slice type,
\tcode{SubExt\-ents::static_extent(\placeholder{MAP_RANK}(slices, $k$))}
equals the following, where $\Sigma_k$
denotes the type of \tcode{slices...[$k$]}:

  \begin{itemize}
  \item
  \tcode{Extents::static_extent($k$)}
  if $\Sigma_k$ denotes \tcode{full_extent_t};
  otherwise

  \item
  \tcode{$\Sigma_k$::extent_type::value}
  if $\Sigma_k$ is a specialization of \tcode{extent_slice} whose
  \tcode{extent_type} denotes a specialization of \tcode{constant_wrapper};

  \item
  otherwise,
  \tcode{dynamic_extent}.
  \end{itemize}
\end{itemize}

\pnum
\returns
A value \tcode{ext} of type \tcode{SubExtents} such that
for each rank index $k$ of \tcode{extents<IndexType, Extents...>},
where the type of \tcode{slices...[$k$]} is not a collapsing slice type,
\tcode{ext.extent(\placeholder{MAP_RANK}(slices, $k$))}
equals the following,
where $\sigma_k$ denotes \tcode{slices...[$k$]}:
\begin{itemize}
\item
  \tcode{$\sigma_k$.extent}
  if the type of $\sigma_k$ is a specialization of \tcode{extent_slice},
\item
  otherwise,
  $U - L$, where \range{$L$}{$U$} is the \tcode{submdspan} slice range
  of $\sigma_k$ for the $k^\text{th}$ extent of \tcode{src}.
\end{itemize}
\end{itemdescr}

\rSec4[mdspan.sub.map]{Specializations of \tcode{submdspan_mapping}}

\rSec5[mdspan.sub.map.sliceable]{Sliceable layout mapping requirements}

\pnum
Let:
\begin{itemize}
\item
  \tcode{M} denote a layout mapping class;
\item
  \tcode{IT} denote \tcode{M::extents_type::index_type};
\item
  \tcode{m} denote a value of type (possibly const) \tcode{M};
\item
  \tcode{M_rank} be equal to \tcode{M::extents_type::rank()};
\item
  \tcode{valid_slices} denote a pack of (possibly const) objects
  for which \tcode{sizeof...(valid_slices) == M_rank} is \tcode{true} and,
  for each rank index $i$ of \tcode{m.extents()},
  \tcode{valid_slices...[$i$]} is a valid \tcode{submdspan} slice
  for the $i^\text{th}$ extent of \tcode{m.extents()};
\item
  \tcode{invalid_slices} denote a pack of objects
  for which \tcode{sizeof...(invalid_slices) == M_rank} is \tcode{true} and
  there exists an integer $k$ such that the cv-unqualified type
  of \tcode{invalid_slices...[$k$]} is none of the following:
  \begin{itemize}
  \item \tcode{IT},
  \item \tcode{full_extent_t},
  \item a specialization of \tcode{constant_wrapper}, or
  \item a specialization of \tcode{extent_slice}.
  \end{itemize}
\end{itemize}

\pnum
\indexlibraryglobal{submdspan_mapping}%
For the purpose of this section,
the meaning of \tcode{submdspan_mapping} is established
as if by performing argument-dependent lookup only\iref{basic.lookup.argdep}.

\pnum
A type \tcode{M} meets the \defn{sliceable layout mapping requirements} if
\begin{itemize}
\item
\tcode{M} meets the layout mapping requirements\iref{mdspan.layout.policy.reqmts},
\item
the expression \tcode{submdspan_mapping(m, invalid_slices...)} is ill-formed, and
\item
the following expression is well-formed and has the specified semantics:
\begin{codeblock}
submdspan_mapping(m, valid_slices...)
\end{codeblock}
\end{itemize}

\begin{itemdescr}
\pnum
\result
A type \tcode{SMR} that is a specialization of type \tcode{submdspan_mapping_result<SM>} for some type \tcode{SM} such that
\begin{itemize}
\item \tcode{SM} meets the layout mapping requirements\iref{mdspan.layout.policy.reqmts},
\item \tcode{SM::extents_type} is a specialization of \tcode{extents},
\item \tcode{SM::extents_type::rank()} equals
\tcode{\placeholder{MAP_RANK}(valid_slices, M_rank)}, and
\item \tcode{SM::extents_type::index_type} denotes \tcode{IT}.
\end{itemize}

\pnum
\returns
An object \tcode{smr} of type \tcode{SMR} such that
\begin{itemize}
\item
  \tcode{smr.mapping.extents() == subextents(m.extents(), valid_slices...)}
  is \tcode{true};\newline and
\item
  for each integer pack \tcode{i}
  which is a multidimensional index in \tcode{smr.mapping.extents()},\newline
  \tcode{smr.mapping(i...) + smr.offset == m(j)} is \tcode{true},
  where \tcode{j} is an integer pack such that
  \begin{itemize}
  \item
    \tcode{sizeof...(j)} is equal to \tcode{M_rank}; and
  \item
    for each rank index $\rho$ of \tcode{m.extents()},
    \tcode{j...[$\rho$]} is equal to the sum of
    \begin{itemize}
    \item
      the lower bound of the \tcode{submdspan} slice range of \tcode{valid_slices...[$\rho$]}
      for extent $\rho$ of \tcode{m.extents()}, and
    \item
      zero if the type of \tcode{valid_slices...[$\rho$]} is a collapsing slice type,
      \tcode{i...[MAP_RANK(valid_slices,$\rho$)]} otherwise.
    \end{itemize}
  \end{itemize}
\end{itemize}
\end{itemdescr}

\begin{itemdecl}
template<class LayoutMapping>
  concept @\defexposconcept{sliceable-mapping}@ = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{lm} be an object of type \tcode{LayoutMapping}
and let \tcode{fe} denote a pack of objects of type \tcode{full_extent_t}
for which \tcode{sizeof...(fe) == LayoutMapping::extents_type::rank()} is \tcode{true}.
A type \tcode{LayoutMapping} satisfies \exposconcept{sliceable-mapping} if
\begin{itemize}
\item
  the expression \tcode{submdspan_mapping(lm, fe...)} is well-formed
  when treated as an unevaluated operand, and
\item
  the type of that expression is a specialization of
  \tcode{submdspan_mapping_result}.
\end{itemize}

\pnum
A type \tcode{LayoutMapping} models \exposconcept{sliceable-mapping}
if \tcode{LayoutMapping} meets the sliceable layout mapping requirements.
\end{itemdescr}

\rSec5[mdspan.sub.map.common]{Common}

\pnum
The following elements apply to all functions in \ref{mdspan.sub.map}.

\pnum
\constraints
\tcode{sizeof...(SliceSpecifiers)} equals \tcode{extents_type::rank()}.

\pnum
\mandates
For each rank index $k$ of \tcode{extents()},
\tcode{SliceSpecifiers...[$k$]} is a valid \tcode{submdspan} slice type
for the $k^\text{th}$ extent of \tcode{Extents}.

\pnum
\expects
For each rank index $k$ of \tcode{extents()},
\tcode{slices...[$k$]} is a valid slice
for the $k^\text{th}$ extent of \tcode{extents()}.

\pnum
Let \tcode{sub_ext} be
the result of \tcode{subextents(extents(), slices...)} and
let \tcode{SubExtents} be \tcode{decl\-type(sub_ext)}.

\pnum
Let \tcode{sub_strides} be
an \tcode{array<SubExtents::index_type, SubExtents::rank()>}
such that for each rank index $k$ of \tcode{extents()}
for which the type of \tcode{slices...[$k$]} is not a collapsing slice type,
\tcode{sub_strides[\placeholder{MAP_RANK}(slices,$k$)]} equals:
\begin{itemize}
\item
\tcode{stride(k) * s.stride}
if the type of \tcode{s} is a specialization of \tcode{extent_slice} and
\tcode{s.extent > 1} is \tcode{true},
where \tcode{s} is \tcode{slices...[$k$]};
\item
otherwise, \tcode{stride($k$)}.
\end{itemize}

\pnum
Let \tcode{ls} be a pack of values of \tcode{index_type},
where the $\rho^\text{th}$ element equals the lower bound
of the \tcode{submdspan} slice range of \tcode{slices...[$\rho$]}
for extent $\rho$ of \tcode{extents()}.

\pnum
If \tcode{ls...[$k$]}
equals \tcode{extents().extent($k$)}
for any rank index $k$ of \tcode{extents()}, then
let \tcode{offset} be a value of type \tcode{size_t} equal to
\tcode{required_span_size()}.
Otherwise,
let \tcode{offset} be a value of type \tcode{size_t} equal to
\tcode{operator()(ls...)}.

\rSec5[mdspan.sub.map.left]{\tcode{layout_left} specialization of \tcode{submdspan_mapping}}

\indexlibrarymemberexpos{layout_left::mapping}{submdspan-mapping-impl}%
\begin{itemdecl}
template<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_left::mapping<Extents>::@\exposid{submdspan-mapping-impl}@(
      SliceSpecifiers... slices) const -> @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{itemize}
\item
\tcode{submdspan_mapping_result\{*this, 0\}},
if \tcode{Extents::rank() == 0} is \tcode{true};
\item
otherwise,
\tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}},\newline
if \tcode{SubEx\-tents::rank() == 0} is \tcode{true};
\item
otherwise,
\tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}},
if
  \begin{itemize}
  \item
  for each $k$ in the range \range{0}{SubExtents::rank() - 1},
  \tcode{SliceSpecifiers...[$k$]} denotes \tcode{full_extent_t}; and
  \item
  for $k$ equal to \tcode{SubExtents::rank() - 1},
  \tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type;
  \end{itemize}
\begin{note}
If the above conditions are true,
all \tcode{SliceSpecifiers...[$k$]} with $k$ larger than \tcode{SubExtents\brk{}::rank\brk{}() - 1}
are convertible to \tcode{index_type}.
\end{note}
\item
otherwise,
\begin{codeblock}
submdspan_mapping_result{layout_left_padded<S_static>::mapping(sub_ext, stride(@$u$@ + 1)),
                         offset}
\end{codeblock}
if for a value $u$ for which $u+1$ is
the smallest value $p$ larger than zero
for which \tcode{SliceSpecifiers...\brk{}[\brk{}$p$]} is a unit-stride slice type,
the following conditions are met:
\begin{itemize}
\item
\tcode{SliceSpecifiers...[0]} is a unit-stride slice type; and
\item
for each $k$ in the range \range{$u$ + 1}{$u$ + SubExtents::rank() - 1},
\tcode{SliceSpecifiers...[$k$]} denotes \tcode{full_extent_t}; and
\item
for $k$ equal to \tcode{$u$ + SubExtents::rank() - 1},
\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type;
\end{itemize}
and where \tcode{S_static} is:
\begin{itemize}
\item
\tcode{dynamic_extent},
if \tcode{static_extent($k$)} is \tcode{dynamic_extent}
for any $k$ in the range \range{0}{$u$ + 1},
\item
otherwise, the product of all values
\tcode{static_extent($k$)} for $k$ in the range \range{0}{$u$ + 1};
\end{itemize}
\item
otherwise,
\begin{codeblock}
submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
\end{codeblock}
\end{itemize}
\end{itemdescr}

\rSec5[mdspan.sub.map.right]{\tcode{layout_right} specialization of \tcode{submdspan_mapping}}

\indexlibrarymemberexpos{layout_right::mapping}{submdspan-mapping-impl}%
\begin{itemdecl}
template<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_right::mapping<Extents>::@\exposid{submdspan-mapping-impl}@(
      SliceSpecifiers... slices) const -> @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{itemize}
\item
\tcode{submdspan_mapping_result\{*this, 0\}},
if \tcode{Extents::rank() == 0} is \tcode{true};
\item
otherwise,
\tcode{submdspan_mapping_result\{layout_right::mapping(sub_ext), offset\}},\newline
if \tcode{Sub\-Extents::rank() == 0} is \tcode{true};
\item
otherwise,
\tcode{submdspan_mapping_result\{layout_right::mapping(sub_ext), offset\}},
if
  \begin{itemize}
  \item
  for each $k$ in the range \range{\exposid{rank_} - SubExtents::rank() + 1}{\exposid{rank_}},\newline
  \tcode{SliceSpecifiers...[$k$]} denotes \tcode{full_extent_t}; and
  \item
  for $k$ equal to \exposid{rank_} - \tcode{SubExtents::rank()},
  \tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type;
  \end{itemize}
\begin{note}
If the above conditions are true,
all \tcode{SliceSpecifiers...[$k$]} with\newline
$k < \tcode{\exposid{rank_} - SubExtents::rank()}$
are convertible to \tcode{index_type}.
\end{note}
\item
otherwise,
\begin{codeblock}
submdspan_mapping_result{layout_right_padded<S_static>::mapping(sub_ext,
                             stride(@\exposid{rank_}@ - @$u$@ - 2)), offset}
\end{codeblock}
if for a value $u$ for which $\exposid{rank_} - u - 2$ is
the largest value $p$ smaller than \tcode{\exposid{rank_} - 1}
for which \tcode{SliceSpecifiers...[$p$]} is a unit-stride slice type,
the following conditions are met:
\begin{itemize}
\item
for $k$ equal to \tcode{\exposid{rank_} - 1},
\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type; and
\item
for each $k$ in the range
\range{\exposid{rank_} - SubExtents::rank() - $u$ + 1}{\exposid{rank_} - $u$ - 1},\newline
\tcode{SliceSpecifiers...[$p$]} denotes \tcode{full_extent_t}; and
\item
for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$},
\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type;
\end{itemize}
and where \tcode{S_static} is:
\begin{itemize}
\item
\tcode{dynamic_extent},
if \tcode{static_extent($k$)} is \tcode{dynamic_extent}
for any $k$ in the range \range{\exposid{rank_} - $u$ - 1}{\exposid{rank_}},
\item
otherwise, the product of all values
\tcode{static_extent($k$)}
for $k$ in the range \range{\exposid{rank_} - $u$ - 1}{\exposid{rank_}};
\end{itemize}
\item
otherwise,
\begin{codeblock}
submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
\end{codeblock}
\end{itemize}
\end{itemdescr}

\rSec5[mdspan.sub.map.stride]{\tcode{layout_stride} specialization of \tcode{submdspan_mapping}}

\indexlibrarymemberexpos{layout_stride::mapping}{submdspan-mapping-impl}%
\begin{itemdecl}
template<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_stride::mapping<Extents>::@\exposid{submdspan-mapping-impl}@(
      SliceSpecifiers... slices) const -> @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{itemize}
\item
\tcode{submdspan_mapping_result\{*this, 0\}},
if \tcode{Extents::rank() == 0} is \tcode{true};
\item
otherwise,
\begin{codeblock}
submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
\end{codeblock}
\end{itemize}
\end{itemdescr}

\rSec5[mdspan.sub.map.leftpad]{\tcode{layout_left_padded} specialization of \tcode{submdspan_mapping}}

\indexlibrarymemberexpos{layout_left_padded::mapping}{submdspan-mapping-impl}%
\begin{itemdecl}
template<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_left_padded::mapping<Extents>::@\exposid{submdspan-mapping-impl}@(
    SliceSpecifiers... slices) const -> @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{itemize}
\item
\tcode{submdspan_mapping_result\{*this, 0\}},
if \tcode{Extents::rank() == 0} is \tcode{true};
\item
otherwise,
\tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}},
if \tcode{\exposid{rank_} == 1} is \tcode{true} or
\tcode{SubExtents::rank() == 0} is \tcode{true};
\item
otherwise,
\tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}},
if
\begin{itemize}
\item
\tcode{SubExtents::rank() == 1} is \tcode{true} and
\item
\tcode{SliceSpecifiers...[0]} is a unit-stride slice type;
\end{itemize}
\item
otherwise,
\begin{codeblock}
submdspan_mapping_result{layout_left_padded<S_static>::mapping(sub_ext, stride(@$u$@ + 1)),
                         offset}
\end{codeblock}
if for a value $u$
for which \tcode{$u$ + 1} is the smallest value $p$ larger than zero
for which \tcode{Slice\-Speci\-fiers\brk{}...[\brk{}$p$]} is a unit-stride slice type,
the following conditions are met:
\begin{itemize}
\item
\tcode{SliceSpecifiers...[0]} is a unit-stride slice type; and
\item
for each $k$ in the range \range{$u$ + 1}{$u$ + SubExtents::rank() - 1},
\tcode{SliceSpecifiers...[$k$]} denotes \tcode{full_extent_t}; and
\item
for $k$ equal to \tcode{$u$ + SubExtents::rank() - 1},
\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type;
\end{itemize}
where \tcode{S_static} is:
\begin{itemize}
\item
\tcode{dynamic_extent},
if \exposid{static-padding-stride} is \tcode{dynamic_extent} or
\tcode{static_extent($k$)} is \tcode{dynamic_extent}
for any $k$ in the range \range{1}{$u$ + 1},
\item
otherwise, the product of \exposid{static-padding-stride} and
all values \tcode{static_extent($k$)} for $k$ in the range \range{1}{$u$ + 1};
\end{itemize}
\item
otherwise,
\begin{codeblock}
submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
\end{codeblock}
\end{itemize}
\end{itemdescr}

\rSec5[mdspan.sub.map.rightpad]{\tcode{layout_right_padded} specialization of \tcode{submdspan_mapping}}

\indexlibrarymemberexpos{layout_right_padded::mapping}{submdspan-mapping-impl}%
\begin{itemdecl}
template<class Extents>
template<class... SliceSpecifiers>
constexpr auto layout_right_padded::mapping<Extents>::@\exposid{submdspan-mapping-impl}@(
    SliceSpecifiers... slices) const -> @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{itemize}
\item
\tcode{submdspan_mapping_result\{*this, 0\}},
if \tcode{\exposid{rank_} == 0} is \tcode{true};
\item
otherwise,
\tcode{submdspan_mapping_result\{layout_right::mapping(sub_ext), offset\}},\newline
if \tcode{\exposid{rank_} == 1} is \tcode{true} or
\tcode{SubExtents::rank() == 0} is \tcode{true};
\item
otherwise,
\tcode{submdspan_mapping_result\{layout_right::mapping(sub_ext), offset\}},
if
\begin{itemize}
\item
\tcode{SubExtents::rank() == 1} is \tcode{true} and
\item
for $k$ equal to \tcode{\exposid{rank_} - 1},
\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type;
\end{itemize}
\item
otherwise,
\begin{codeblock}
submdspan_mapping_result{layout_right_padded<S_static>::mapping(sub_ext,
                             stride(@\exposid{rank_}@ - @$u$@ - 2)), offset}
\end{codeblock}
if for a value $u$
for which \tcode{\exposid{rank_} - $u$ - 2}
is the largest value $p$ smaller than \tcode{\exposid{rank_} - 1}
for which \tcode{SliceSpecifiers...[$p$]} is a unit-stride slice type,
the following conditions are met:
\begin{itemize}
\item
for $k$ equal to \tcode{\exposid{rank_} - 1},
\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type; and
\item
for each $k$ in the range
\range{\exposid{rank_} - SubExtents::rank() - $u$ + 1}{\exposid{rank_} - $u$ - 1},\newline
\tcode{SliceSpecifiers...[$k$]} denotes \tcode{full_extent_t}; and
\item
for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$},
\tcode{SliceSpecifiers...[$k$]} is a unit-stride slice type;
\end{itemize}
and where \tcode{S_static} is:
\begin{itemize}
\item
\tcode{dynamic_extent}
if \exposid{static-padding-stride} is \tcode{dynamic_extent} or
for any $k$ in the range \range{\exposid{rank_} - $u$ - 1}{\exposid{rank_} - 1}
\tcode{static_extent($k$)} is \tcode{dynamic_extent},
\item
otherwise, the product of \exposid{static-padding-stride} and
all values \tcode{static_extent($k$)}
with $k$ in the range \range{\exposid{rank_} - $u$ - 1}{\exposid{rank_} - 1};
\end{itemize}
\item
otherwise,
\begin{codeblock}
submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
\end{codeblock}
\end{itemize}
\end{itemdescr}

\rSec4[mdspan.sub.sub]{\tcode{submdspan} function template}

\indexlibraryglobal{submdspan}%
\begin{itemdecl}
template<class ElementType, class Extents, class LayoutPolicy,
         class AccessorPolicy, class... SliceSpecifiers>
  constexpr auto submdspan(
    const mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& src,
    SliceSpecifiers... raw_slices) -> @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{index_type} be \tcode{typename Extents::index_type}.

\pnum
Let \tcode{slices} be the pack introduced by the following declaration:
\begin{codeblock}
auto [...slices] = canonical_slices(src.extents(), raw_slices...);
\end{codeblock}

\pnum
Let \tcode{sub_map_offset} be the result of
\tcode{submdspan_mapping(src.mapping(), slices...)}.
\begin{note}
This invocation of \tcode{submdspan_mapping}
selects a function call via overload resolution
on a candidate set that includes the lookup set
found by argument-dependent lookup\iref{basic.lookup.argdep}.
\end{note}

\pnum
\constraints
\begin{itemize}
\item
\tcode{sizeof...(slices)} equals \tcode{Extents::rank()}, and
\item
\tcode{LayoutPolicy::mapping<Extents>} models \exposconcept{sliceable-mapping}.
\end{itemize}

\pnum
\mandates
For each rank index $k$ of \tcode{src}:
\begin{itemize}
\item
  \tcode{SliceSpecifiers...[$k$]} is a \tcode{submdspan} slice type
  for \tcode{index_type}, and
\item
  \tcode{decltype(slices...[$k$])} is a valid \tcode{submdspan} slice type
  for the $k^\text{th}$ extent of \tcode{Extents}.
\end{itemize}

\pnum
\expects
For each rank index $k$ of \tcode{src.extents()},
\tcode{slices...[$k$]} is a valid \tcode{submdspan} slice
for the $k^\text{th}$ extent of \tcode{src.extents()}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
auto sub_map_result = submdspan_mapping(src.mapping(), slices...);
return mdspan(src.accessor().offset(src.data_handle(), sub_map_result.offset),
              sub_map_result.mapping,
              typename AccessorPolicy::offset_policy(src.accessor()));
\end{codeblock}
\end{itemdescr}

\pnum
\begin{example}
Given a rank-3 \tcode{mdspan grid3d} representing a three-dimensional grid
of regularly spaced points in a rectangular prism,
the function \tcode{zero_surface} sets all elements on
the surface of the 3-dimensional shape to zero.
It does so by reusing a function \tcode{zero_2d}
that takes a rank-2 \tcode{mdspan}.

\begin{codeblock}
// zero out all elements in an \tcode{mdspan}
template<class T, class E, class L, class A>
void zero_2d(mdspan<T, E, L, A> a) {
  static_assert(a.rank() == 2);
  for (int i = 0; i < a.extent(0); i++)
    for (int j = 0; j < a.extent(1); j++)
      a[i, j] = 0;
}

// zero out just the surface
template<class T, class E, class L, class A>
void zero_surface(mdspan<T, E, L, A> grid3d) {
  static_assert(grid3d.rank() == 3);
  zero_2d(submdspan(grid3d, 0, full_extent, full_extent));
  zero_2d(submdspan(grid3d, full_extent, 0, full_extent));
  zero_2d(submdspan(grid3d, full_extent, full_extent, 0));
  zero_2d(submdspan(grid3d, grid3d.extent(0) - 1, full_extent, full_extent));
  zero_2d(submdspan(grid3d, full_extent, grid3d.extent(1) - 1, full_extent));
  zero_2d(submdspan(grid3d, full_extent, full_extent, grid3d.extent(2) - 1));
}
\end{codeblock}
\end{example}
