%!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{<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 subclause \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{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}%
}

\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 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{iterator};
\tcode{const_iterator} for constant \tcode{b}.

\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{iterator};
\tcode{const_iterator} for constant \tcode{b}.

\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}

\indexcont{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}

\indexcont{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 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 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}, 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}, 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{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}%
}

\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{reverse_iterator};
\tcode{const_reverse_iterator} for constant \tcode{a}.

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

\pnum
\complexity
Constant.
\end{itemdescr}

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

\begin{itemdescr}
\pnum
\result
\tcode{reverse_iterator};
\tcode{const_reverse_iterator} for constant \tcode{a}.

\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}, 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{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 four basic kinds of sequence containers:
\tcode{vector}, \tcode{forward_list}, \tcode{list}, and \tcode{deque}. In addition,
\tcode{array} is provided as a sequence container which provides limited sequence operations
because it has a fixed number of elements. 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
\tcode{[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
\tcode{[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}%
}

\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 \tcode{[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
neither \tcode{ranges::\libconcept{sized_range}} nor \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
\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} 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 constructed from \tcode{args} into \tcode{a}.
\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} 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} 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} and \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.
Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}.

\pnum
\effects
Inserts copies of elements in \tcode{[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} and \tcode{deque},
\tcode{T} is also
\oldconcept{MoveInsertable} into \tcode{X},
and \tcode{T} meets the
\oldconcept{MoveConstructible},
\oldconcept{Move\-Assignable}, 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} 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} and \tcode{deque}, \tcode{T} is \oldconcept{MoveAssignable}.

\pnum
\effects
Erases the elements in the range \tcode{[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 \tcode{[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.

\pnum
\expects
\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X}
from \tcode{*ranges::begin(rg)}.
For \tcode{vector},
if \tcode{R} models
neither \tcode{ranges::\libconcept{sized_range}} nor \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.
\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{reference; const_reference} for constant \tcode{a}.

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

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

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

\begin{itemdescr}
\pnum
\result
\tcode{reference; const_reference} for constant \tcode{a}.

\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{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{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{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{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{list}, and
\tcode{vector}.
\end{itemdescr}

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

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

\pnum
\expects
\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
\expects
\tcode{a.empty()} is \tcode{false}.

\pnum
\effects
Destroys the last element.

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

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

\begin{itemdescr}
\pnum
\result
\tcode{reference; const_reference} for constant \tcode{a}

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

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

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

\begin{itemdescr}
\pnum
\result
\tcode{reference; const_reference} for constant \tcode{a}

\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}, 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 container_node_type = @\unspecnc@;                  // \expos
  using ator_traits = allocator_traits<allocator_type>;     // \expos

  typename ator_traits::template
    rebind_traits<container_node_type>::pointer ptr_;       // \expos
  optional<allocator_type> alloc_;                          // \expos

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

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

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

  allocator_type get_allocator() const;
  explicit operator bool() const noexcept;
  [[nodiscard]] bool empty() const noexcept;

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

  friend 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}
@\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&& nh) noexcept;
\end{itemdecl}

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

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

\begin{itemdescr}
\pnum
\expects
Either \tcode{!alloc_}, or
\tcode{ator_traits::propagate_on_container_move_assignment::\-value}
is \tcode{true}, or \tcode{alloc_ ==  nh.alloc_}.

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

\pnum
\returns
\tcode{*this}.

\pnum
\throws
Nothing.
\end{itemdescr}

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

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

\begin{itemdescr}
\pnum
\effects
If \tcode{ptr_ != nullptr}, destroys the \tcode{value_type} subobject
in the \tcode{container_node_type} object pointed to by \tcode{ptr_} by calling
\tcode{ator_traits::destroy}, then deallocates \tcode{ptr_} by calling
\tcode{ator_traits::template rebind_traits<container_node_type>::deallocate}.
\end{itemdescr}

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

\begin{itemdecl}
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
\tcode{container_node_type} object pointed to by \tcode{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 \tcode{contain\-er_node_type} object
pointed to by \tcode{ptr_}.

\pnum
\throws
Nothing.

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

\begin{itemdecl}
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 \tcode{container_node_type} object
pointed to by \tcode{ptr_}.

\pnum
\throws
Nothing.
\end{itemdescr}


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

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

\pnum
\returns
\tcode{*alloc_}.

\pnum
\throws
Nothing.
\end{itemdescr}

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

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

\begin{itemdecl}
[[nodiscard]] bool empty() const noexcept;
\end{itemdecl}

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

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

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

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

\pnum
\effects
Calls \tcode{swap(ptr_, nh.ptr_)}. If \tcode{!alloc_}, or
\tcode{!nh.alloc_}, or \tcode{ator_traits::propagate_on_container_swap::value}
is \tcode{true} calls \tcode{swap(alloc_, nh.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 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 or 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 multiple 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
\tcode{[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.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.alloc.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}}%
}

\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
An iterator pointing to the element
with the key equivalent to the newly inserted element.

\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()}.

\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}.
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{iterator}; \tcode{const_iterator} for constant \tcode{b}.

\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{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}.

\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{iterator}; \tcode{const_iterator} for constant \tcode{b}.

\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{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}.

\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{iterator}; \tcode{const_iterator} for constant \tcode{b}.

\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{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}.

\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<iterator, iterator>};
\tcode{pair<const_iterator, const_iterator>} for constant \tcode{b}.

\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<iterator, iterator>};
\tcode{pair<const_iterator, const_iterator>} for constant \tcode{a_tran}.

\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
\tcode{[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
\tcode{[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.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.alloc.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
\expects
\tcode{value_type} is
\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.

\pnum
\effects
Equivalent to \tcode{a.emplace(std::forward<Args>(args)...)}.

\pnum
\returns
An iterator pointing to the element
with the key equivalent to the newly inserted element.
The \tcode{const_iterator} \tcode{p} is a hint
pointing to where the search should start.
Implementations are permitted to ignore the hint.

\pnum
\complexity
Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}.
\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 \tcode{[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 \tcode{[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{iterator}; \tcode{const_iterator} for constant \tcode{b}.

\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{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}.

\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<iterator, iterator>};
\tcode{pair<const_iterator, const_iterator>} for constant \tcode{b}.

\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<iterator, iterator>};
\tcode{pair<const_iterator, const_iterator>} for constant \tcode{a_tran}.

\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 \tcode{[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 \tcode{[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 \tcode{[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{local_iterator}; \tcode{const_local_iterator} for constant \tcode{b}.

\pnum
\expects
\tcode{n} is in the range \tcode{[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{local_iterator}; \tcode{const_local_iterator} for constant \tcode{b}.

\pnum
\expects
\tcode{n} is in the range \tcode{[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 \tcode{[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 \tcode{[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]{In general}

\pnum
The headers
\libheaderref{array},
\libheaderref{deque},
\libheaderrefx{forward_list}{forward.list.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}@ = typename 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 @\placeholder{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[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>
    bool operator==(const deque<T, Allocator>& x, const deque<T, Allocator>& y);
  template<class T, class Allocator>
    @\placeholder{synth-three-way-result}@<T> operator<=>(const deque<T, Allocator>& x,
    @\itcorr@                                      const deque<T, Allocator>& y);

  template<class T, class Allocator>
    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>
    typename deque<T, Allocator>::size_type
      erase(deque<T, Allocator>& c, const U& value);
  template<class T, class Allocator, class Predicate>
    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[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>
    bool operator==(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template<class T, class Allocator>
    @\placeholder{synth-three-way-result}@<T> operator<=>(const forward_list<T, Allocator>& x,
    @\itcorr@                                      const forward_list<T, Allocator>& y);

  template<class T, class Allocator>
    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>
    typename forward_list<T, Allocator>::size_type
      erase(forward_list<T, Allocator>& c, const U& value);
  template<class T, class Allocator, class Predicate>
    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[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>
    bool operator==(const list<T, Allocator>& x, const list<T, Allocator>& y);
  template<class T, class Allocator>
    @\placeholder{synth-three-way-result}@<T> operator<=>(const list<T, Allocator>& x,
    @\itcorr@                                      const list<T, Allocator>& y);

  template<class T, class Allocator>
    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>
    typename list<T, Allocator>::size_type
      erase(list<T, Allocator>& c, const U& value);
  template<class T, class Allocator, class Predicate>
    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[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 @\placeholder{synth-three-way-result}@<T> operator<=>(const vector<T, Allocator>& x,
              @\itcorr@                                      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[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
    [[nodiscard]] 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}%
The conditions for an aggregate\iref{dcl.init.aggr} shall be
met. Class \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 implicit 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
The effect of calling \tcode{front()} or \tcode{back()} for a zero-sized array is
undefined.

\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<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_move_constructible_v<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]{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.

\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                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\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
    deque() : deque(Allocator()) { }
    explicit deque(const Allocator&);
    explicit deque(size_type n, const Allocator& = Allocator());
    deque(size_type n, const T& value, const Allocator& = Allocator());
    template<class InputIterator>
      deque(InputIterator first, InputIterator last, const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<T> R>
      deque(from_range_t, R&& rg, const Allocator& = Allocator());
    deque(const deque& x);
    deque(deque&&);
    deque(const deque&, const type_identity_t<Allocator>&);
    deque(deque&&, const type_identity_t<Allocator>&);
    deque(initializer_list<T>, const Allocator& = Allocator());

    ~deque();
    deque& operator=(const deque& x);
    deque& operator=(deque&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    deque& 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{deque.capacity}, capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;
    void      resize(size_type sz);
    void      resize(size_type sz, const T& c);
    void      shrink_to_fit();

    // element access
    reference       operator[](size_type n);
    const_reference operator[](size_type n) const;
    reference       at(size_type n);
    const_reference at(size_type n) const;
    reference       front();
    const_reference front() const;
    reference       back();
    const_reference back() const;

    // \ref{deque.modifiers}, modifiers
    template<class... Args> reference emplace_front(Args&&... args);
    template<class... Args> reference emplace_back(Args&&... args);
    template<class... Args> iterator emplace(const_iterator position, Args&&... args);

    void push_front(const T& x);
    void push_front(T&& x);
    template<@\exposconcept{container-compatible-range}@<T> R>
      void prepend_range(R&& rg);
    void push_back(const T& x);
    void push_back(T&& x);
    template<@\exposconcept{container-compatible-range}@<T> R>
      void append_range(R&& rg);

    iterator insert(const_iterator position, const T& x);
    iterator insert(const_iterator position, T&& x);
    iterator insert(const_iterator position, size_type n, const T& x);
    template<class InputIterator>
      iterator insert(const_iterator position, InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<T> R>
      iterator insert_range(const_iterator position, R&& rg);
    iterator insert(const_iterator position, initializer_list<T>);

    void pop_front();
    void pop_back();

    iterator erase(const_iterator position);
    iterator erase(const_iterator first, const_iterator last);
    void     swap(deque&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    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}
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}
explicit deque(size_type n, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{*this}.

\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}
deque(size_type n, const T& value, const Allocator& = Allocator());
\end{itemdecl}

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

\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>
  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>
  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}
void resize(size_type sz);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{MoveInsertable} and \oldconcept{DefaultInsertable} into \tcode{*this}.

\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}
void resize(size_type sz, const T& c);
\end{itemdecl}

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

\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}
void shrink_to_fit();
\end{itemdecl}

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

\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}
iterator insert(const_iterator position, const T& x);
iterator insert(const_iterator position, T&& x);
iterator insert(const_iterator position, size_type n, const T& x);
template<class InputIterator>
  iterator insert(const_iterator position,
                  InputIterator first, InputIterator last);
template<@\exposconcept{container-compatible-range}@<T> R>
  iterator insert_range(const_iterator position, R&& rg);
iterator insert(const_iterator position, initializer_list<T>);

template<class... Args> reference emplace_front(Args&&... args);
template<class... Args> reference emplace_back(Args&&... args);
template<class... Args> iterator emplace(const_iterator position, Args&&... args);
void push_front(const T& x);
void push_front(T&& x);
template<@\exposconcept{container-compatible-range}@<T> R>
  void prepend_range(R&& rg);
void push_back(const T& x);
void push_back(T&& x);
template<@\exposconcept{container-compatible-range}@<T> R>
  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}
iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);
void pop_front();
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>
  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>
  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]{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}

\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         = typename allocator_traits<Allocator>::pointer;
    using const_pointer   = typename allocator_traits<Allocator>::const_pointer;
    using reference       = value_type&;
    using const_reference = const value_type&;
    using size_type       = @\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
    forward_list() : forward_list(Allocator()) { }
    explicit forward_list(const Allocator&);
    explicit forward_list(size_type n, const Allocator& = Allocator());
    forward_list(size_type n, const T& value, const Allocator& = Allocator());
    template<class InputIterator>
      forward_list(InputIterator first, InputIterator last, const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<T> R>
      forward_list(from_range_t, R&& rg, const Allocator& = Allocator());
    forward_list(const forward_list& x);
    forward_list(forward_list&& x);
    forward_list(const forward_list& x, const type_identity_t<Allocator>&);
    forward_list(forward_list&& x, const type_identity_t<Allocator>&);
    forward_list(initializer_list<T>, const Allocator& = Allocator());
    ~forward_list();
    forward_list& operator=(const forward_list& x);
    forward_list& operator=(forward_list&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    forward_list& 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;

    // \ref{forward.list.iter}, iterators
    iterator before_begin() noexcept;
    const_iterator before_begin() const noexcept;
    iterator begin() noexcept;
    const_iterator begin() const noexcept;
    iterator end() noexcept;
    const_iterator end() const noexcept;

    const_iterator cbegin() const noexcept;
    const_iterator cbefore_begin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type max_size() const noexcept;

    // \ref{forward.list.access}, element access
    reference front();
    const_reference front() const;

    // \ref{forward.list.modifiers}, modifiers
    template<class... Args> reference emplace_front(Args&&... args);
    void push_front(const T& x);
    void push_front(T&& x);
    template<@\exposconcept{container-compatible-range}@<T> R>
      void prepend_range(R&& rg);
    void pop_front();

    template<class... Args> iterator emplace_after(const_iterator position, Args&&... args);
    iterator insert_after(const_iterator position, const T& x);
    iterator insert_after(const_iterator position, T&& x);

    iterator insert_after(const_iterator position, size_type n, const T& x);
    template<class InputIterator>
      iterator insert_after(const_iterator position, InputIterator first, InputIterator last);
    iterator insert_after(const_iterator position, initializer_list<T> il);
    template<@\exposconcept{container-compatible-range}@<T> R>
      iterator insert_range_after(const_iterator position, R&& rg);

    iterator erase_after(const_iterator position);
    iterator erase_after(const_iterator position, const_iterator last);
    void swap(forward_list&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);

    void resize(size_type sz);
    void resize(size_type sz, const value_type& c);
    void clear() noexcept;

    // \ref{forward.list.ops}, \tcode{forward_list} operations
    void splice_after(const_iterator position, forward_list& x);
    void splice_after(const_iterator position, forward_list&& x);
    void splice_after(const_iterator position, forward_list& x, const_iterator i);
    void splice_after(const_iterator position, forward_list&& x, const_iterator i);
    void splice_after(const_iterator position, forward_list& x,
                      const_iterator first, const_iterator last);
    void splice_after(const_iterator position, forward_list&& x,
                      const_iterator first, const_iterator last);

    size_type remove(const T& value);
    template<class Predicate> size_type remove_if(Predicate pred);

    size_type unique();
    template<class BinaryPredicate> size_type unique(BinaryPredicate binary_pred);

    void merge(forward_list& x);
    void merge(forward_list&& x);
    template<class Compare> void merge(forward_list& x, Compare comp);
    template<class Compare> void merge(forward_list&& x, Compare comp);

    void sort();
    template<class Compare> void sort(Compare comp);

    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}
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}
explicit forward_list(size_type n, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{*this}.

\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}
forward_list(size_type n, const T& value, const Allocator& = Allocator());
\end{itemdecl}

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

\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>
  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>
  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}
iterator before_begin() noexcept;
const_iterator before_begin() const noexcept;
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}
reference front();
const_reference front() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{*begin()}
\end{itemdescr}

\rSec3[forward.list.modifiers]{Modifiers}

\pnum
None of the overloads of \tcode{insert_after} shall affect the validity of iterators and
references, and \tcode{erase_after} shall invalidate only iterators and references to
the erased elements. If an exception is thrown during \tcode{insert_after} there shall
be no effect. 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> 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}
void push_front(const T& x);
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>
  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}
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}
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}
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}
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>
  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>
  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}
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>
  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}
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}
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}
void resize(size_type sz);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{*this}.

\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}
void resize(size_type sz, const value_type& c);
\end{itemdecl}

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

\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}
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}
void splice_after(const_iterator position, forward_list& x);
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}
void splice_after(const_iterator position, forward_list& x, const_iterator i);
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}
void splice_after(const_iterator position, forward_list& x,
                  const_iterator first, const_iterator last);
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}
size_type remove(const T& value);
template<class Predicate> 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}
size_type unique();
template<class BinaryPredicate> 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}
void merge(forward_list& x);
void merge(forward_list&& x);
template<class Compare> void merge(forward_list& x, Compare comp);
template<class Compare> 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}
void sort();
template<class Compare> 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}
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>
  typename forward_list<T, Allocator>::size_type
    erase(forward_list<T, Allocator>& c, const U& value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return erase_if(c, [\&](auto\& elem) \{ return elem == value; \});}
\end{itemdescr}

\indexlibrarymember{erase_if}{forward_list}%
\begin{itemdecl}
template<class T, class Allocator, class Predicate>
  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[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.

\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                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\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
    list() : list(Allocator()) { }
    explicit list(const Allocator&);
    explicit list(size_type n, const Allocator& = Allocator());
    list(size_type n, const T& value, const Allocator& = Allocator());
    template<class InputIterator>
      list(InputIterator first, InputIterator last, const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<T> R>
      list(from_range_t, R&& rg, const Allocator& = Allocator());
    list(const list& x);
    list(list&& x);
    list(const list&, const type_identity_t<Allocator>&);
    list(list&&, const type_identity_t<Allocator>&);
    list(initializer_list<T>, const Allocator& = Allocator());
    ~list();
    list& operator=(const list& x);
    list& operator=(list&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    list& 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{list.capacity}, capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;
    void      resize(size_type sz);
    void      resize(size_type sz, const T& c);

    // element access
    reference       front();
    const_reference front() const;
    reference       back();
    const_reference back() const;

    // \ref{list.modifiers}, modifiers
    template<class... Args> reference emplace_front(Args&&... args);
    template<class... Args> reference emplace_back(Args&&... args);
    void push_front(const T& x);
    void push_front(T&& x);
    template<@\exposconcept{container-compatible-range}@<T> R>
      void prepend_range(R&& rg);
    void pop_front();
    void push_back(const T& x);
    void push_back(T&& x);
    template<@\exposconcept{container-compatible-range}@<T> R>
      void append_range(R&& rg);
    void pop_back();

    template<class... Args> iterator emplace(const_iterator position, Args&&... args);
    iterator insert(const_iterator position, const T& x);
    iterator insert(const_iterator position, T&& x);
    iterator insert(const_iterator position, size_type n, const T& x);
    template<class InputIterator>
      iterator insert(const_iterator position, InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<T> R>
      iterator insert_range(const_iterator position, R&& rg);
    iterator insert(const_iterator position, initializer_list<T> il);

    iterator erase(const_iterator position);
    iterator erase(const_iterator position, const_iterator last);
    void     swap(list&) noexcept(allocator_traits<Allocator>::is_always_equal::value);
    void     clear() noexcept;

    // \ref{list.ops}, list operations
    void splice(const_iterator position, list& x);
    void splice(const_iterator position, list&& x);
    void splice(const_iterator position, list& x, const_iterator i);
    void splice(const_iterator position, list&& x, const_iterator i);
    void splice(const_iterator position, list& x, const_iterator first, const_iterator last);
    void splice(const_iterator position, list&& x, const_iterator first, const_iterator last);

    size_type remove(const T& value);
    template<class Predicate> size_type remove_if(Predicate pred);

    size_type unique();
    template<class BinaryPredicate>
      size_type unique(BinaryPredicate binary_pred);

    void merge(list& x);
    void merge(list&& x);
    template<class Compare> void merge(list& x, Compare comp);
    template<class Compare> void merge(list&& x, Compare comp);

    void sort();
    template<class Compare> void sort(Compare comp);

    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}
explicit list(const Allocator&);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an empty list, using the specified allocator.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{list}%
\begin{itemdecl}
explicit list(size_type n, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{*this}.

\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}
list(size_type n, const T& value, const Allocator& = Allocator());
\end{itemdecl}

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

\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>
  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>
  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}
void resize(size_type sz);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{*this}.

\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}
void resize(size_type sz, const T& c);
\end{itemdecl}

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

\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}
iterator insert(const_iterator position, const T& x);
iterator insert(const_iterator position, T&& x);
iterator insert(const_iterator position, size_type n, const T& x);
template<class InputIterator>
  iterator insert(const_iterator position, InputIterator first,
                  InputIterator last);
template<@\exposconcept{container-compatible-range}@<T> R>
  iterator insert_range(const_iterator position, R&& rg);
iterator insert(const_iterator position, initializer_list<T>);

template<class... Args> reference emplace_front(Args&&... args);
template<class... Args> reference emplace_back(Args&&... args);
template<class... Args> iterator emplace(const_iterator position, Args&&... args);
void push_front(const T& x);
void push_front(T&& x);
template<@\exposconcept{container-compatible-range}@<T> R>
  void prepend_range(R&& rg);
void push_back(const T& x);
void push_back(T&& x);
template<@\exposconcept{container-compatible-range}@<T> R>
  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}
iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);

void pop_front();
void pop_back();
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}
void splice(const_iterator position, list& x);
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}
void splice(const_iterator position, list& x, const_iterator i);
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}
void splice(const_iterator position, list& x, const_iterator first,
            const_iterator last);
void splice(const_iterator position, list&& x, const_iterator first,
            const_iterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{[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}
size_type remove(const T& value);
template<class Predicate> 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}
size_type unique();
template<class BinaryPredicate> 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}
void merge(list& x);
void merge(list&& x);
template<class Compare> void merge(list& x, Compare comp);
template<class Compare> 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}
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
\tcode{N == 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
    erase(list<T, Allocator>& c, const U& value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return erase_if(c, [\&](auto\& elem) \{ return elem == value; \});}
\end{itemdescr}

\indexlibrarymember{erase_if}{list}%
\begin{itemdecl}
template<class T, class Allocator, class Predicate>
  typename list<T, Allocator>::size_type
    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]{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                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\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
    [[nodiscard]] 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 const_reference at(size_type n) const;
    constexpr reference       at(size_type n);
    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{*this}.

\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{*this}.

\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 iterators \tcode{first} and \tcode{last} are of forward, bidirectional, or random access categories.
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)}.
Performs no reallocations if \tcode{R} models
\tcode{ranges::\libconcept{forward_range}} or \tcode{ranges::\libconcept{sized_range}};
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{*this}.

\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
It does not change the size of the sequence and takes at most linear
time 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}
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{*this}.

\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{*this}.

\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{*this}.

\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.
\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>}@ {
      friend class vector;
      constexpr reference() noexcept;

    public:
      constexpr reference(const reference&) = default;
      constexpr ~reference();
      constexpr operator bool() const noexcept;
      constexpr reference& operator=(bool x) noexcept;
      constexpr reference& operator=(const reference& x) noexcept;
      constexpr const reference& operator=(bool x) const noexcept;
      constexpr void flip() noexcept;   // flips the bit
    };

    // 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
    [[nodiscard]] 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 const_reference at(size_type n) const;
    constexpr reference       at(size_type n);
    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);
    static constexpr void swap(reference x, reference y) noexcept;
    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 primary \tcode{vector} 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 the behavior of references of a single bit in
\tcode{vector<bool>}. The conversion function returns \tcode{true}
when the bit is set, and \tcode{false} otherwise. The assignment operators
set the bit when the argument is (convertible to) \tcode{true} and
clear it otherwise. \tcode{flip} reverses the state of the bit.

\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}

\indexlibrarymember{swap}{vector<bool>}%
\begin{itemdecl}
static constexpr void swap(reference x, reference y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Exchanges the contents of \tcode{x} and \tcode{y} as if by:

\begin{codeblock}
bool b = x;
x = y;
y = b;
\end{codeblock}

\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>
      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>
  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}

\rSec1[associative]{Associative containers}

\rSec2[associative.general]{In general}

\pnum
The header \libheader{map} defines the class templates \tcode{map} and
\tcode{multimap}; the header \libheader{set} 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}@ =
    typename iterator_traits<InputIterator>::value_type;                // \expos
template<class InputIterator>
  using @\placeholder{iter-key-type}@ = remove_const_t<
    tuple_element_t<0, @\exposid{iter-value-type}@<InputIterator>>>;                // \expos
template<class InputIterator>
  using @\placeholder{iter-mapped-type}@ =
    tuple_element_t<1, @\exposid{iter-value-type}@<InputIterator>>;                 // \expos
template<class InputIterator>
  using @\placeholder{iter-to-alloc-type}@ = pair<
    add_const_t<tuple_element_t<0, @\exposid{iter-value-type}@<InputIterator>>>,
    tuple_element_t<1, @\exposid{iter-value-type}@<InputIterator>>>;                // \expos
template<ranges::@\libconcept{input_range}@ Range>
  using @\exposid{range-key-type}@ =
    remove_const_t<typename ranges::range_value_t<Range>::first_type>;  // \expos
template<ranges::@\libconcept{input_range}@ Range>
  using @\exposid{range-mapped-type}@ = typename ranges::range_value_t<Range>::second_type; // \expos
template<ranges::@\libconcept{input_range}@ Range>
  using @\exposid{range-to-alloc-type}@ =
    pair<add_const_t<typename ranges::range_value_t<Range>::first_type>,
         typename ranges::range_value_t<Range>::second_type>;           // \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>
    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>
    @\placeholder{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>
    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>
    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>
    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>
    @\placeholder{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>
    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>
    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[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>
    bool operator==(const set<Key, Compare, Allocator>& x,
                    const set<Key, Compare, Allocator>& y);
  template<class Key, class Compare, class Allocator>
    @\placeholder{synth-three-way-result}@<Key> operator<=>(const set<Key, Compare, Allocator>& x,
    @\itcorr@                                        const set<Key, Compare, Allocator>& y);

  template<class Key, class Compare, class Allocator>
    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>
    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>
    bool operator==(const multiset<Key, Compare, Allocator>& x,
                    const multiset<Key, Compare, Allocator>& y);
  template<class Key, class Compare, class Allocator>
    @\placeholder{synth-three-way-result}@<Key> operator<=>(const multiset<Key, Compare, Allocator>& x,
    @\itcorr@                                        const multiset<Key, Compare, Allocator>& y);

  template<class Key, class Compare, class Allocator>
    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>
    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[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.

\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                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\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 {
      friend class map;
    protected:
      Compare comp;
      value_compare(Compare c) : comp(c) {}

    public:
      bool operator()(const value_type& x, const value_type& y) const {
        return comp(x.first, y.first);
      }
    };

    // \ref{map.cons}, construct/copy/destroy
    map() : map(Compare()) { }
    explicit map(const Compare& comp, const Allocator& = Allocator());
    template<class InputIterator>
      map(InputIterator first, InputIterator last,
          const Compare& comp = Compare(), const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator());
    map(const map& x);
    map(map&& x);
    explicit map(const Allocator&);
    map(const map&, const type_identity_t<Allocator>&);
    map(map&&, const type_identity_t<Allocator>&);
    map(initializer_list<value_type>,
      const Compare& = Compare(),
      const Allocator& = Allocator());
    template<class InputIterator>
      map(InputIterator first, InputIterator last, const Allocator& a)
        : map(first, last, Compare(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      map(from_range_t, R&& rg, const Allocator& a))
        : map(from_range, std::forward<R>(rg), Compare(), a) { }
    map(initializer_list<value_type> il, const Allocator& a)
      : map(il, Compare(), a) { }
    ~map();
    map& operator=(const map& x);
    map& operator=(map&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Compare>);
    map& operator=(initializer_list<value_type>);
    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;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // \ref{map.access}, element access
    mapped_type& operator[](const key_type& x);
    mapped_type& operator[](key_type&& x);
    template<class K> mapped_type& operator[](K&& x);
    mapped_type&       at(const key_type& x);
    const mapped_type& at(const key_type& x) const;
    template<class K> mapped_type&       at(const K& x);
    template<class K> const mapped_type& at(const K& x) const;

    // \ref{map.modifiers}, modifiers
    template<class... Args> pair<iterator, bool> emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    pair<iterator, bool> insert(const value_type& x);
    pair<iterator, bool> insert(value_type&& x);
    template<class P> pair<iterator, bool> insert(P&& x);
    iterator insert(const_iterator position, const value_type& x);
    iterator insert(const_iterator position, value_type&& x);
    template<class P>
      iterator insert(const_iterator position, P&&);
    template<class InputIterator>
      void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      void insert_range(R&& rg);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    template<class K> node_type extract(K&& x);
    insert_return_type insert(node_type&& nh);
    iterator           insert(const_iterator hint, node_type&& nh);

    template<class... Args>
      pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
    template<class... Args>
      pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
    template<class K, class... Args>
      pair<iterator, bool> try_emplace(K&& k, Args&&... args);
    template<class... Args>
      iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
    template<class... Args>
      iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
    template<class K, class... Args>
      iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
    template<class M>
      pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
    template<class M>
      pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
    template<class K, class M>
      pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
    template<class M>
      iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
    template<class M>
      iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
    template<class K, class M>
      iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& x);
    template<class K> size_type erase(K&& x);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(map&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Compare>);
    void      clear() noexcept;

    template<class C2>
      void merge(map<Key, T, C2, Allocator>& source);
    template<class C2>
      void merge(map<Key, T, C2, Allocator>&& source);
    template<class C2>
      void merge(multimap<Key, T, C2, Allocator>& source);
    template<class C2>
      void merge(multimap<Key, T, C2, Allocator>&& source);

    // observers
    key_compare key_comp() const;
    value_compare value_comp() const;

    // map operations
    iterator       find(const key_type& x);
    const_iterator find(const key_type& x) const;
    template<class K> iterator       find(const K& x);
    template<class K> const_iterator find(const K& x) const;

    size_type      count(const key_type& x) const;
    template<class K> size_type count(const K& x) const;

    bool           contains(const key_type& x) const;
    template<class K> bool contains(const K& x) const;

    iterator       lower_bound(const key_type& x);
    const_iterator lower_bound(const key_type& x) const;
    template<class K> iterator       lower_bound(const K& x);
    template<class K> const_iterator lower_bound(const K& x) const;

    iterator       upper_bound(const key_type& x);
    const_iterator upper_bound(const key_type& x) const;
    template<class K> iterator       upper_bound(const K& x);
    template<class K> const_iterator upper_bound(const K& x) const;

    pair<iterator, iterator>               equal_range(const key_type& x);
    pair<const_iterator, const_iterator>   equal_range(const key_type& x) const;
    template<class K>
      pair<iterator, iterator>             equal_range(const K& x);
    template<class K>
      pair<const_iterator, const_iterator> equal_range(const K& x) const;
  };

  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}
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>
  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>
  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}
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}
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> 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}
mapped_type&       at(const key_type& x);
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> mapped_type&       at(const K& x);
template<class K> 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>
  pair<iterator, bool> insert(P&& x);
template<class P>
  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>
  pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
template<class... Args>
  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>
  pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
template<class... Args>
  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>
  pair<iterator, bool> try_emplace(K&& k, Args&&... args);
template<class K, class... Args>
  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>
  pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
template<class M>
  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>
  pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
template<class M>
  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>
  pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
template<class K, class M>
  iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);
\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
    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.

\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                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\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 {
      friend class multimap;
    protected:
      Compare comp;
      value_compare(Compare c) : comp(c) { }

    public:
      bool operator()(const value_type& x, const value_type& y) const {
        return comp(x.first, y.first);
      }
    };

    // \ref{multimap.cons}, construct/copy/destroy
    multimap() : multimap(Compare()) { }
    explicit multimap(const Compare& comp, const Allocator& = Allocator());
    template<class InputIterator>
      multimap(InputIterator first, InputIterator last,
               const Compare& comp = Compare(),
               const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      multimap(from_range_t, R&& rg,
               const Compare& comp = Compare(), const Allocator& = Allocator());
    multimap(const multimap& x);
    multimap(multimap&& x);
    explicit multimap(const Allocator&);
    multimap(const multimap&, const type_identity_t<Allocator>&);
    multimap(multimap&&, const type_identity_t<Allocator>&);
    multimap(initializer_list<value_type>,
      const Compare& = Compare(),
      const Allocator& = Allocator());
    template<class InputIterator>
      multimap(InputIterator first, InputIterator last, const Allocator& a)
        : multimap(first, last, Compare(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      multimap(from_range_t, R&& rg, const Allocator& a))
        : multimap(from_range, std::forward<R>(rg), Compare(), a) { }
    multimap(initializer_list<value_type> il, const Allocator& a)
      : multimap(il, Compare(), a) { }
    ~multimap();
    multimap& operator=(const multimap& x);
    multimap& operator=(multimap&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Compare>);
    multimap& operator=(initializer_list<value_type>);
    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;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // \ref{multimap.modifiers}, modifiers
    template<class... Args> iterator emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    iterator insert(const value_type& x);
    iterator insert(value_type&& x);
    template<class P> iterator insert(P&& x);
    iterator insert(const_iterator position, const value_type& x);
    iterator insert(const_iterator position, value_type&& x);
    template<class P> iterator insert(const_iterator position, P&& x);
    template<class InputIterator>
      void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      void insert_range(R&& rg);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    template<class K> node_type extract(K&& x);
    iterator insert(node_type&& nh);
    iterator insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& x);
    template<class K> size_type erase(K&& x);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(multimap&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Compare>);
    void      clear() noexcept;

    template<class C2>
      void merge(multimap<Key, T, C2, Allocator>& source);
    template<class C2>
      void merge(multimap<Key, T, C2, Allocator>&& source);
    template<class C2>
      void merge(map<Key, T, C2, Allocator>& source);
    template<class C2>
      void merge(map<Key, T, C2, Allocator>&& source);

    // observers
    key_compare key_comp() const;
    value_compare value_comp() const;

    // map operations
    iterator       find(const key_type& x);
    const_iterator find(const key_type& x) const;
    template<class K> iterator       find(const K& x);
    template<class K> const_iterator find(const K& x) const;

    size_type      count(const key_type& x) const;
    template<class K> size_type count(const K& x) const;

    bool           contains(const key_type& x) const;
    template<class K> bool contains(const K& x) const;

    iterator       lower_bound(const key_type& x);
    const_iterator lower_bound(const key_type& x) const;
    template<class K> iterator       lower_bound(const K& x);
    template<class K> const_iterator lower_bound(const K& x) const;

    iterator       upper_bound(const key_type& x);
    const_iterator upper_bound(const key_type& x) const;
    template<class K> iterator       upper_bound(const K& x);
    template<class K> const_iterator upper_bound(const K& x) const;

    pair<iterator, iterator>               equal_range(const key_type& x);
    pair<const_iterator, const_iterator>   equal_range(const key_type& x) const;
    template<class K>
      pair<iterator, iterator>             equal_range(const K& x);
    template<class K>
      pair<const_iterator, const_iterator> equal_range(const K& x) const;
  };

  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}
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>
  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>
  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> iterator insert(P&& x);
template<class P> 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
    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[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.

\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                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\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
    set() : set(Compare()) { }
    explicit set(const Compare& comp, const Allocator& = Allocator());
    template<class InputIterator>
      set(InputIterator first, InputIterator last,
          const Compare& comp = Compare(), const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator());
    set(const set& x);
    set(set&& x);
    explicit set(const Allocator&);
    set(const set&, const type_identity_t<Allocator>&);
    set(set&&, const type_identity_t<Allocator>&);
    set(initializer_list<value_type>, const Compare& = Compare(),
        const Allocator& = Allocator());
    template<class InputIterator>
      set(InputIterator first, InputIterator last, const Allocator& a)
        : set(first, last, Compare(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      set(from_range_t, R&& rg, const Allocator& a))
        : set(from_range, std::forward<R>(rg), Compare(), a) { }
    set(initializer_list<value_type> il, const Allocator& a)
      : set(il, Compare(), a) { }
    ~set();
    set& operator=(const set& x);
    set& operator=(set&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Compare>);
    set& operator=(initializer_list<value_type>);
    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;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // \ref{set.modifiers}, modifiers
    template<class... Args> pair<iterator, bool> emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    pair<iterator,bool> insert(const value_type& x);
    pair<iterator,bool> insert(value_type&& x);
    template<class K> pair<iterator, bool> insert(K&& x);
    iterator insert(const_iterator position, const value_type& x);
    iterator insert(const_iterator position, value_type&& x);
    template<class K> iterator insert(const_iterator position, K&& x);
    template<class InputIterator>
      void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      void insert_range(R&& rg);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    template<class K> node_type extract(K&& x);
    insert_return_type insert(node_type&& nh);
    iterator           insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position)
      requires (!@\libconcept{same_as}@<iterator, const_iterator>);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& x);
    template<class K> size_type erase(K&& x);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(set&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Compare>);
    void      clear() noexcept;

    template<class C2>
      void merge(set<Key, C2, Allocator>& source);
    template<class C2>
      void merge(set<Key, C2, Allocator>&& source);
    template<class C2>
      void merge(multiset<Key, C2, Allocator>& source);
    template<class C2>
      void merge(multiset<Key, C2, Allocator>&& source);

    // observers
    key_compare key_comp() const;
    value_compare value_comp() const;

    // set operations
    iterator       find(const key_type& x);
    const_iterator find(const key_type& x) const;
    template<class K> iterator       find(const K& x);
    template<class K> const_iterator find(const K& x) const;

    size_type      count(const key_type& x) const;
    template<class K> size_type count(const K& x) const;

    bool           contains(const key_type& x) const;
    template<class K> bool contains(const K& x) const;

    iterator       lower_bound(const key_type& x);
    const_iterator lower_bound(const key_type& x) const;
    template<class K> iterator       lower_bound(const K& x);
    template<class K> const_iterator lower_bound(const K& x) const;

    iterator       upper_bound(const key_type& x);
    const_iterator upper_bound(const key_type& x) const;
    template<class K> iterator       upper_bound(const K& x);
    template<class K> const_iterator upper_bound(const K& x) const;

    pair<iterator, iterator>               equal_range(const key_type& x);
    pair<const_iterator, const_iterator>   equal_range(const key_type& x) const;
    template<class K>
      pair<iterator, iterator>             equal_range(const K& x);
    template<class K>
      pair<const_iterator, const_iterator> equal_range(const K& x) const;
  };

  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}
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>
  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>
  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>
  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> pair<iterator, bool> insert(K&& x);
template<class K> 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 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},
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.

\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                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = @\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
    multiset() : multiset(Compare()) { }
    explicit multiset(const Compare& comp, const Allocator& = Allocator());
    template<class InputIterator>
      multiset(InputIterator first, InputIterator last,
               const Compare& comp = Compare(), const Allocator& = Allocator());
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      multiset(from_range_t, R&& rg,
               const Compare& comp = Compare(), const Allocator& = Allocator());
    multiset(const multiset& x);
    multiset(multiset&& x);
    explicit multiset(const Allocator&);
    multiset(const multiset&, const type_identity_t<Allocator>&);
    multiset(multiset&&, const type_identity_t<Allocator>&);
    multiset(initializer_list<value_type>, const Compare& = Compare(),
             const Allocator& = Allocator());
    template<class InputIterator>
      multiset(InputIterator first, InputIterator last, const Allocator& a)
        : multiset(first, last, Compare(), a) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      multiset(from_range_t, R&& rg, const Allocator& a))
        : multiset(from_range, std::forward<R>(rg), Compare(), a) { }
    multiset(initializer_list<value_type> il, const Allocator& a)
      : multiset(il, Compare(), a) { }
    ~multiset();
    multiset& operator=(const multiset& x);
    multiset& operator=(multiset&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Compare>);
    multiset& operator=(initializer_list<value_type>);
    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;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> iterator emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    iterator insert(const value_type& x);
    iterator insert(value_type&& x);
    iterator insert(const_iterator position, const value_type& x);
    iterator insert(const_iterator position, value_type&& x);
    template<class InputIterator>
      void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      void insert_range(R&& rg);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    template<class K> node_type extract(K&& x);
    iterator insert(node_type&& nh);
    iterator insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position)
      requires (!@\libconcept{same_as}@<iterator, const_iterator>);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& x);
    template<class K> size_type erase(K&& x);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(multiset&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Compare>);
    void      clear() noexcept;

    template<class C2>
      void merge(multiset<Key, C2, Allocator>& source);
    template<class C2>
      void merge(multiset<Key, C2, Allocator>&& source);
    template<class C2>
      void merge(set<Key, C2, Allocator>& source);
    template<class C2>
      void merge(set<Key, C2, Allocator>&& source);

    // observers
    key_compare key_comp() const;
    value_compare value_comp() const;

    // set operations
    iterator       find(const key_type& x);
    const_iterator find(const key_type& x) const;
    template<class K> iterator       find(const K& x);
    template<class K> const_iterator find(const K& x) const;

    size_type      count(const key_type& x) const;
    template<class K> size_type count(const K& x) const;

    bool           contains(const key_type& x) const;
    template<class K> bool contains(const K& x) const;

    iterator       lower_bound(const key_type& x);
    const_iterator lower_bound(const key_type& x) const;
    template<class K> iterator       lower_bound(const K& x);
    template<class K> const_iterator lower_bound(const K& x) const;

    iterator       upper_bound(const key_type& x);
    const_iterator upper_bound(const key_type& x) const;
    template<class K> iterator       upper_bound(const K& x);
    template<class K> const_iterator upper_bound(const K& x) const;

    pair<iterator, iterator>               equal_range(const key_type& x);
    pair<const_iterator, const_iterator>   equal_range(const key_type& x) const;
    template<class K>
      pair<iterator, iterator>             equal_range(const K& x);
    template<class K>
      pair<const_iterator, const_iterator> equal_range(const K& x) const;
  };

  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}
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>
  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>
  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>
  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]{In general}

\pnum
The header \libheader{unordered_map} defines the class templates
\tcode{unordered_map} and
\tcode{unordered_multimap}; the header \libheader{unordered_set} 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>
    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>
    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>
    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>
    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>
    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>
    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.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>
    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>
    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>
    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>
    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>
    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>
    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.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.

\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              = typename allocator_traits<Allocator>::pointer;
    using const_pointer        = typename allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = @\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
    unordered_map();
    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>
      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>
      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());
    unordered_map(const unordered_map&);
    unordered_map(unordered_map&&);
    explicit unordered_map(const Allocator&);
    unordered_map(const unordered_map&, const type_identity_t<Allocator>&);
    unordered_map(unordered_map&&, const type_identity_t<Allocator>&);
    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());
    unordered_map(size_type n, const allocator_type& a)
      : unordered_map(n, hasher(), key_equal(), a) { }
    unordered_map(size_type n, const hasher& hf, const allocator_type& a)
      : unordered_map(n, hf, key_equal(), a) { }
    template<class InputIterator>
      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>
      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>
      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>
      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) { }
    unordered_map(initializer_list<value_type> il, size_type n, const allocator_type& a)
      : unordered_map(il, n, hasher(), key_equal(), a) { }
    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) { }
    ~unordered_map();
    unordered_map& operator=(const unordered_map&);
    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>);
    unordered_map& operator=(initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // \ref{unord.map.modifiers}, modifiers
    template<class... Args> pair<iterator, bool> emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    pair<iterator, bool> insert(const value_type& obj);
    pair<iterator, bool> insert(value_type&& obj);
    template<class P> pair<iterator, bool> insert(P&& obj);
    iterator       insert(const_iterator hint, const value_type& obj);
    iterator       insert(const_iterator hint, value_type&& obj);
    template<class P> iterator insert(const_iterator hint, P&& obj);
    template<class InputIterator> void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      void insert_range(R&& rg);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    template<class K> node_type extract(K&& x);
    insert_return_type insert(node_type&& nh);
    iterator           insert(const_iterator hint, node_type&& nh);

    template<class... Args>
      pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
    template<class... Args>
      pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
    template<class K, class... Args>
      pair<iterator, bool> try_emplace(K&& k, Args&&... args);
    template<class... Args>
      iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
    template<class... Args>
      iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
    template<class K, class... Args>
      iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
    template<class M>
      pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
    template<class M>
      pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
    template<class K, class M>
      pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
    template<class M>
      iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
    template<class M>
      iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
    template<class K, class M>
      iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& k);
    template<class K> size_type erase(K&& x);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(unordered_map&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Hash> &&
               is_nothrow_swappable_v<Pred>);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_map<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_map<Key, T, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // map operations
    iterator         find(const key_type& k);
    const_iterator   find(const key_type& k) const;
    template<class K>
      iterator       find(const K& k);
    template<class K>
      const_iterator find(const K& k) const;
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;
    pair<iterator, iterator>               equal_range(const key_type& k);
    pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // \ref{unord.map.elem}, element access
    mapped_type& operator[](const key_type& k);
    mapped_type& operator[](key_type&& k);
    template<class K> mapped_type& operator[](K&& k);
    mapped_type& at(const key_type& k);
    const mapped_type& at(const key_type& k) const;
    template<class K> mapped_type& at(const K& k);
    template<class K> const mapped_type& at(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;
    size_type max_bucket_count() const noexcept;
    size_type bucket_size(size_type n) const;
    size_type bucket(const key_type& k) const;
    template<class K> size_type bucket(const K& k) const;
    local_iterator begin(size_type n);
    const_local_iterator begin(size_type n) const;
    local_iterator end(size_type n);
    const_local_iterator end(size_type n) const;
    const_local_iterator cbegin(size_type n) const;
    const_local_iterator cend(size_type n) const;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    void rehash(size_type n);
    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}
unordered_map() : unordered_map(size_type(@\seebelow@)) { }
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>
  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>
  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());
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}
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}
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> 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}
mapped_type& at(const key_type& k);
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> mapped_type&       at(const K& k);
template<class K> 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>
  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>
  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>
  pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
template<class... Args>
  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>
  pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
template<class... Args>
  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>
  pair<iterator, bool> try_emplace(K&& k, Args&&... args);
template<class K, class... Args>
  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>
  pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
template<class M>
  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>
  pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
template<class M>
  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>
  pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
template<class K, class M>
  iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);
\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>
  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.

\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              = typename allocator_traits<Allocator>::pointer;
    using const_pointer        = typename allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = @\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
    unordered_multimap();
    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>
      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>
      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());
    unordered_multimap(const unordered_multimap&);
    unordered_multimap(unordered_multimap&&);
    explicit unordered_multimap(const Allocator&);
    unordered_multimap(const unordered_multimap&, const type_identity_t<Allocator>&);
    unordered_multimap(unordered_multimap&&, const type_identity_t<Allocator>&);
    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());
    unordered_multimap(size_type n, const allocator_type& a)
      : unordered_multimap(n, hasher(), key_equal(), a) { }
    unordered_multimap(size_type n, const hasher& hf, const allocator_type& a)
      : unordered_multimap(n, hf, key_equal(), a) { }
    template<class InputIterator>
      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>
      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>
    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>
    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) { }
    unordered_multimap(initializer_list<value_type> il, size_type n, const allocator_type& a)
      : unordered_multimap(il, n, hasher(), key_equal(), a) { }
    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) { }
    ~unordered_multimap();
    unordered_multimap& operator=(const unordered_multimap&);
    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>);
    unordered_multimap& operator=(initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // \ref{unord.multimap.modifiers}, modifiers
    template<class... Args> iterator emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    iterator insert(const value_type& obj);
    iterator insert(value_type&& obj);
    template<class P> iterator insert(P&& obj);
    iterator insert(const_iterator hint, const value_type& obj);
    iterator insert(const_iterator hint, value_type&& obj);
    template<class P> iterator insert(const_iterator hint, P&& obj);
    template<class InputIterator> void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      void insert_range(R&& rg);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    template<class K> node_type extract(K&& x);
    iterator insert(node_type&& nh);
    iterator insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& k);
    template<class K> size_type erase(K&& x);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(unordered_multimap&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Hash> &&
               is_nothrow_swappable_v<Pred>);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      void merge(unordered_map<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_map<Key, T, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // map operations
    iterator         find(const key_type& k);
    const_iterator   find(const key_type& k) const;
    template<class K>
      iterator       find(const K& k);
    template<class K>
      const_iterator find(const K& k) const;
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;
    pair<iterator, iterator>               equal_range(const key_type& k);
    pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;
    size_type max_bucket_count() const noexcept;
    size_type bucket_size(size_type n) const;
    size_type bucket(const key_type& k) const;
    template<class K> size_type bucket(const K& k) const;
    local_iterator begin(size_type n);
    const_local_iterator begin(size_type n) const;
    local_iterator end(size_type n);
    const_local_iterator end(size_type n) const;
    const_local_iterator cbegin(size_type n) const;
    const_local_iterator cend(size_type n) const;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    void rehash(size_type n);
    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}
unordered_multimap() : unordered_multimap(size_type(@\seebelow@)) { }
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>
  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>
  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());
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>
  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>
  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>
  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]{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},
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.

\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              = typename allocator_traits<Allocator>::pointer;
    using const_pointer        = typename allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = @\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
    unordered_set();
    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>
      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>
      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());
    unordered_set(const unordered_set&);
    unordered_set(unordered_set&&);
    explicit unordered_set(const Allocator&);
    unordered_set(const unordered_set&, const type_identity_t<Allocator>&);
    unordered_set(unordered_set&&, const type_identity_t<Allocator>&);
    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());
    unordered_set(size_type n, const allocator_type& a)
      : unordered_set(n, hasher(), key_equal(), a) { }
    unordered_set(size_type n, const hasher& hf, const allocator_type& a)
      : unordered_set(n, hf, key_equal(), a) { }
    template<class InputIterator>
      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>
      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) { }
    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>
      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>
      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) { }
    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) { }
    ~unordered_set();
    unordered_set& operator=(const unordered_set&);
    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>);
    unordered_set& operator=(initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // \ref{unord.set.modifiers}, modifiers
    template<class... Args> pair<iterator, bool> emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    pair<iterator, bool> insert(const value_type& obj);
    pair<iterator, bool> insert(value_type&& obj);
    template<class K> pair<iterator, bool> insert(K&& obj);
    iterator insert(const_iterator hint, const value_type& obj);
    iterator insert(const_iterator hint, value_type&& obj);
    template<class K> iterator insert(const_iterator hint, K&& obj);
    template<class InputIterator> void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      void insert_range(R&& rg);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    template<class K> node_type extract(K&& x);
    insert_return_type insert(node_type&& nh);
    iterator           insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position)
      requires (!@\libconcept{same_as}@<iterator, const_iterator>);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& k);
    template<class K> size_type erase(K&& x);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(unordered_set&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Hash> &&
               is_nothrow_swappable_v<Pred>);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_set<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_set<Key, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      void merge(unordered_multiset<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_multiset<Key, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // set operations
    iterator         find(const key_type& k);
    const_iterator   find(const key_type& k) const;
    template<class K>
      iterator       find(const K& k);
    template<class K>
      const_iterator find(const K& k) const;
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;
    pair<iterator, iterator>               equal_range(const key_type& k);
    pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;
    size_type max_bucket_count() const noexcept;
    size_type bucket_size(size_type n) const;
    size_type bucket(const key_type& k) const;
    template<class K> size_type bucket(const K& k) const;
    local_iterator begin(size_type n);
    const_local_iterator begin(size_type n) const;
    local_iterator end(size_type n);
    const_local_iterator end(size_type n) const;
    const_local_iterator cbegin(size_type n) const;
    const_local_iterator cend(size_type n) const;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    void rehash(size_type n);
    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}
unordered_set() : unordered_set(size_type(@\seebelow@)) { }
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>
  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>
  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());
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>
  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> pair<iterator, bool> insert(K&& obj);
template<class K> 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.

\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              = typename allocator_traits<Allocator>::pointer;
    using const_pointer        = typename allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = @\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
    unordered_multiset();
    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>
      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>
      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());
    unordered_multiset(const unordered_multiset&);
    unordered_multiset(unordered_multiset&&);
    explicit unordered_multiset(const Allocator&);
    unordered_multiset(const unordered_multiset&, const type_identity_t<Allocator>&);
    unordered_multiset(unordered_multiset&&, const type_identity_t<Allocator>&);
    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());
    unordered_multiset(size_type n, const allocator_type& a)
      : unordered_multiset(n, hasher(), key_equal(), a) { }
    unordered_multiset(size_type n, const hasher& hf, const allocator_type& a)
      : unordered_multiset(n, hf, key_equal(), a) { }
    template<class InputIterator>
      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>
      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>
      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>
      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) { }
    unordered_multiset(initializer_list<value_type> il, size_type n, const allocator_type& a)
      : unordered_multiset(il, n, hasher(), key_equal(), a) { }
    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) { }
    ~unordered_multiset();
    unordered_multiset& operator=(const unordered_multiset&);
    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>);
    unordered_multiset& operator=(initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> iterator emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    iterator insert(const value_type& obj);
    iterator insert(value_type&& obj);
    iterator insert(const_iterator hint, const value_type& obj);
    iterator insert(const_iterator hint, value_type&& obj);
    template<class InputIterator> void insert(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      void insert_range(R&& rg);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    template<class K> node_type extract(K&& x);
    iterator insert(node_type&& nh);
    iterator insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position)
      requires (!@\libconcept{same_as}@<iterator, const_iterator>);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& k);
    template<class K> size_type erase(K&& x);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(unordered_multiset&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Hash> &&
               is_nothrow_swappable_v<Pred>);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_multiset<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_multiset<Key, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      void merge(unordered_set<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_set<Key, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // set operations
    iterator         find(const key_type& k);
    const_iterator   find(const key_type& k) const;
    template<class K>
      iterator       find(const K& k);
    template<class K>
      const_iterator find(const K& k) const;
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;
    pair<iterator, iterator>               equal_range(const key_type& k);
    pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;
    size_type max_bucket_count() const noexcept;
    size_type bucket_size(size_type n) const;
    size_type bucket(const key_type& k) const;
    template<class K> size_type bucket(const K& k) const;
    local_iterator begin(size_type n);
    const_local_iterator begin(size_type n) const;
    local_iterator end(size_type n);
    const_local_iterator end(size_type n) const;
    const_local_iterator cbegin(size_type n) const;
    const_local_iterator cend(size_type n) const;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    void rehash(size_type n);
    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, @\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}
unordered_multiset() : unordered_multiset(size_type(@\seebelow@)) { }
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>
  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>
  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());
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>
  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]{In general}

\pnum
The headers
\libheader{queue},
\libheader{stack},
\libheader{flat_map},
and \libheader{flat_set}
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}@ =                      // \expos
    typename allocator_traits<Allocator>::template rebind_alloc<T>;
\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>
    bool operator==(const queue<T, Container>& x, const queue<T, Container>& y);
  template<class T, class Container>
    bool operator!=(const queue<T, Container>& x, const queue<T, Container>& y);
  template<class T, class Container>
    bool operator< (const queue<T, Container>& x, const queue<T, Container>& y);
  template<class T, class Container>
    bool operator> (const queue<T, Container>& x, const queue<T, Container>& y);
  template<class T, class Container>
    bool operator<=(const queue<T, Container>& x, const queue<T, Container>& y);
  template<class T, class Container>
    bool operator>=(const queue<T, Container>& x, const queue<T, Container>& y);
  template<class T, @\libconcept{three_way_comparable}@ Container>
    compare_three_way_result_t<Container>
      operator<=>(const queue<T, Container>& x, const queue<T, Container>& y);

  template<class T, class Container>
    void swap(queue<T, Container>& x, queue<T, Container>& y) noexcept(noexcept(x.swap(y)));
  template<class T, class Container, class Alloc>
    struct uses_allocator<queue<T, Container>, Alloc>;

  // \ref{container.adaptors.format}, formatter specialization for \tcode{queue}
  template<class charT, class T, @\libconcept{formattable}@<charT> Container>
    struct formatter<queue<T, Container>, charT>;

  // \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>
    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>;
}
\end{codeblock}

\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>
    bool operator==(const stack<T, Container>& x, const stack<T, Container>& y);
  template<class T, class Container>
    bool operator!=(const stack<T, Container>& x, const stack<T, Container>& y);
  template<class T, class Container>
    bool operator< (const stack<T, Container>& x, const stack<T, Container>& y);
  template<class T, class Container>
    bool operator> (const stack<T, Container>& x, const stack<T, Container>& y);
  template<class T, class Container>
    bool operator<=(const stack<T, Container>& x, const stack<T, Container>& y);
  template<class T, class Container>
    bool operator>=(const stack<T, Container>& x, const stack<T, Container>& y);
  template<class T, @\libconcept{three_way_comparable}@ Container>
    compare_three_way_result_t<Container>
      operator<=>(const stack<T, Container>& x, const stack<T, Container>& y);

  template<class T, class Container>
    void swap(stack<T, Container>& x, stack<T, Container>& y) noexcept(noexcept(x.swap(y)));
  template<class T, class Container, class Alloc>
    struct uses_allocator<stack<T, Container>, Alloc>;

  // \ref{container.adaptors.format}, formatter specialization for \tcode{stack}
  template<class charT, class T, @\libconcept{formattable}@<charT> Container>
    struct formatter<stack<T, Container>, charT>;
}
\end{codeblock}

\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>
    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>
    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.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>
    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>
    typename flat_multiset<Key, Compare, KeyContainer>::size_type
      erase_if(flat_multiset<Key, Compare, KeyContainer>& c, Predicate pred);
}
\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      = typename Container::value_type;
    using reference       = typename Container::reference;
    using const_reference = typename Container::const_reference;
    using size_type       = typename Container::size_type;
    using container_type  =          Container;

  protected:
    Container c;

  public:
    queue() : queue(Container()) {}
    explicit queue(const Container&);
    explicit queue(Container&&);
    template<class InputIterator> queue(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<T> R> queue(from_range_t, R&& rg);
    template<class Alloc> explicit queue(const Alloc&);
    template<class Alloc> queue(const Container&, const Alloc&);
    template<class Alloc> queue(Container&&, const Alloc&);
    template<class Alloc> queue(const queue&, const Alloc&);
    template<class Alloc> queue(queue&&, const Alloc&);
    template<class InputIterator, class Alloc>
      queue(InputIterator first, InputIterator last, const Alloc&);
    template<@\exposconcept{container-compatible-range}@<T> R, class Alloc>
      queue(from_range_t, R&& rg, const Alloc&);

    [[nodiscard]] bool empty() const    { return c.empty(); }
    size_type         size()  const     { return c.size(); }
    reference         front()           { return c.front(); }
    const_reference   front() const     { return c.front(); }
    reference         back()            { return c.back(); }
    const_reference   back() const      { return c.back(); }
    void push(const value_type& x)      { c.push_back(x); }
    void push(value_type&& x)           { c.push_back(std::move(x)); }
    template<@\exposconcept{container-compatible-range}@<T> R> void push_range(R&& rg);
    template<class... Args>
      decltype(auto) emplace(Args&&... args)
        { return c.emplace_back(std::forward<Args>(args)...); }
    void pop()                          { c.pop_front(); }
    void swap(queue& q) noexcept(is_nothrow_swappable_v<Container>)
      { using std::swap; swap(c, q.c); }
  };

  template<class Container>
    queue(Container) -> queue<typename Container::value_type, Container>;

  template<class InputIterator>
    queue(InputIterator, InputIterator) -> queue<@\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}
explicit queue(const Container& cont);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{cont}.
\end{itemdescr}

\indexlibraryctor{queue}%
\begin{itemdecl}
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>
  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>
  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> 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> 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> 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> 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> 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>
  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>
  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>
  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>
  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>
  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>
  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>
  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>
  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>
    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>
  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>
  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      = typename Container::value_type;
    using reference       = typename Container::reference;
    using const_reference = typename Container::const_reference;
    using size_type       = typename Container::size_type;
    using container_type  = Container;
    using value_compare   = Compare;

  protected:
    Container c;
    Compare comp;

  public:
    priority_queue() : priority_queue(Compare()) {}
    explicit priority_queue(const Compare& x) : priority_queue(x, Container()) {}
    priority_queue(const Compare& x, const Container&);
    priority_queue(const Compare& x, Container&&);
    template<class InputIterator>
      priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare());
    template<class InputIterator>
      priority_queue(InputIterator first, InputIterator last, const Compare& x,
                     const Container&);
    template<class InputIterator>
      priority_queue(InputIterator first, InputIterator last, const Compare& x,
                     Container&&);
    template<@\exposconcept{container-compatible-range}@<T> R>
      priority_queue(from_range_t, R&& rg, const Compare& x = Compare());
    template<class Alloc> explicit priority_queue(const Alloc&);
    template<class Alloc> priority_queue(const Compare&, const Alloc&);
    template<class Alloc> priority_queue(const Compare&, const Container&, const Alloc&);
    template<class Alloc> priority_queue(const Compare&, Container&&, const Alloc&);
    template<class Alloc> priority_queue(const priority_queue&, const Alloc&);
    template<class Alloc> priority_queue(priority_queue&&, const Alloc&);
    template<class InputIterator, class Alloc>
      priority_queue(InputIterator, InputIterator, const Alloc&);
    template<class InputIterator, class Alloc>
      priority_queue(InputIterator, InputIterator, const Compare&, const Alloc&);
    template<class InputIterator, class Alloc>
      priority_queue(InputIterator, InputIterator, const Compare&, const Container&,
                     const Alloc&);
    template<class InputIterator, class Alloc>
      priority_queue(InputIterator, InputIterator, const Compare&, Container&&, const Alloc&);
    template<@\exposconcept{container-compatible-range}@<T> R, class Alloc>
      priority_queue(from_range_t, R&& rg, const Compare&, const Alloc&);
    template<@\exposconcept{container-compatible-range}@<T> R, class Alloc>
      priority_queue(from_range_t, R&& rg, const Alloc&);

    [[nodiscard]] bool empty() const { return c.empty(); }
    size_type size()  const          { return c.size(); }
    const_reference   top() const    { return c.front(); }
    void push(const value_type& x);
    void push(value_type&& x);
    template<@\exposconcept{container-compatible-range}@<T> R>
      void push_range(R&& rg);
    template<class... Args> void emplace(Args&&... args);
    void pop();
    void swap(priority_queue& q) noexcept(is_nothrow_swappable_v<Container> &&
                                          is_nothrow_swappable_v<Compare>)
      { using std::swap; swap(c, q.c); swap(comp, q.comp); }
  };

  template<class Compare, class Container>
    priority_queue(Compare, Container)
      -> priority_queue<typename Container::value_type, Container, Compare>;

  template<class InputIterator,
           class Compare = less<@\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}
priority_queue(const Compare& x, const Container& y);
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>
  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>
  priority_queue(InputIterator first, InputIterator last, const Compare& x, const Container& y);
template<class InputIterator>
  priority_queue(InputIterator first, InputIterator last, const Compare& x, Container&& y);
\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>
  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> 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> 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>
  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>
  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> 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> 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>
  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>
  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>
  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>
  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>
  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>
  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)};
calls \tcode{make_heap(c.\linebreak begin(), c.end(), comp)}.
\end{itemdescr}

\rSec3[priqueue.members]{Members}

\indexlibrarymember{push}{priority_queue}%
\begin{itemdecl}
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}
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>
  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> 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}
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>
  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]{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      = typename Container::value_type;
    using reference       = typename Container::reference;
    using const_reference = typename Container::const_reference;
    using size_type       = typename Container::size_type;
    using container_type  = Container;

  protected:
    Container c;

  public:
    stack() : stack(Container()) {}
    explicit stack(const Container&);
    explicit stack(Container&&);
    template<class InputIterator> stack(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<T> R> stack(from_range_t, R&& rg);
    template<class Alloc> explicit stack(const Alloc&);
    template<class Alloc> stack(const Container&, const Alloc&);
    template<class Alloc> stack(Container&&, const Alloc&);
    template<class Alloc> stack(const stack&, const Alloc&);
    template<class Alloc> stack(stack&&, const Alloc&);
    template<class InputIterator, class Alloc>
      stack(InputIterator first, InputIterator last, const Alloc&);
    template<@\exposconcept{container-compatible-range}@<T> R, class Alloc>
      stack(from_range_t, R&& rg, const Alloc&);

    [[nodiscard]] bool empty() const    { return c.empty(); }
    size_type size()  const             { return c.size(); }
    reference         top()             { return c.back(); }
    const_reference   top() const       { return c.back(); }
    void push(const value_type& x)      { c.push_back(x); }
    void push(value_type&& x)           { c.push_back(std::move(x)); }
    template<@\exposconcept{container-compatible-range}@<T> R>
      void push_range(R&& rg);
    template<class... Args>
      decltype(auto) emplace(Args&&... args)
        { return c.emplace_back(std::forward<Args>(args)...); }
    void pop()                          { c.pop_back(); }
    void swap(stack& s) noexcept(is_nothrow_swappable_v<Container>)
      { using std::swap; swap(c, s.c); }
  };

  template<class Container>
    stack(Container) -> stack<typename Container::value_type, Container>;

  template<class InputIterator>
    stack(InputIterator, InputIterator) -> stack<@\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}
explicit stack(const Container& cont);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \tcode{c} with \tcode{cont}.
\end{itemdescr}

\indexlibraryctor{stack}%
\begin{itemdecl}
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>
  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>
  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> 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> 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> 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> 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> 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>
  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>
  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>
  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>
  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>
  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>
  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>
  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>
  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>
  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>
  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>
  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]{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 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 constructor or 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.

\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 comp;                                 // \expos
      value_compare(key_compare c) : comp(c) { }        // \expos

    public:
      bool operator()(const_reference x, const_reference y) const {
        return comp(x.first, y.first);
      }
    };

    struct containers {
      key_container_type keys;
      mapped_container_type values;
    };

    // \ref{flat.map.cons}, construct/copy/destroy
    flat_map() : flat_map(key_compare()) { }

    template<class Allocator>
      flat_map(const flat_map&, const Allocator& a);
    template<class Allocator>
      flat_map(flat_map&&, const Allocator& a);

    flat_map(key_container_type key_cont, mapped_container_type mapped_cont,
             const key_compare& comp = key_compare());
    template<class Allocator>
      flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont,
               const Allocator& a);
    template<class Allocator>
      flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont,
               const key_compare& comp, const Allocator& a);

    flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont,
             const key_compare& comp = key_compare());
    template<class Allocator>
      flat_map(sorted_unique_t, const key_container_type& key_cont,
               const mapped_container_type& mapped_cont, const Allocator& a);
    template<class Allocator>
      flat_map(sorted_unique_t, const key_container_type& key_cont,
               const mapped_container_type& mapped_cont,
               const key_compare& comp, const Allocator& a);

    explicit flat_map(const key_compare& comp)
      : c(), compare(comp) { }
    template<class Allocator>
      flat_map(const key_compare& comp, const Allocator& a);
    template<class Allocator>
      explicit flat_map(const Allocator& a);

    template<class InputIterator>
      flat_map(InputIterator first, InputIterator last, const key_compare& comp = key_compare())
        : c(), compare(comp) { insert(first, last); }
    template<class InputIterator, class Allocator>
      flat_map(InputIterator first, InputIterator last,
               const key_compare& comp, const Allocator& a);
    template<class InputIterator, class Allocator>
      flat_map(InputIterator first, InputIterator last, const Allocator& a);

    template<@\exposconcept{container-compatible-range}@<value_type> R>
      flat_map(from_range_t fr, R&& rg)
        : flat_map(fr, std::forward<R>(rg), key_compare()) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
      flat_map(from_range_t, R&& rg, const Allocator& a);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      flat_map(from_range_t, R&& rg, const key_compare& comp)
        : flat_map(comp) { insert_range(std::forward<R>(rg)); }
    template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
      flat_map(from_range_t, R&& rg, const key_compare& comp, const Allocator& a);

    template<class InputIterator>
      flat_map(sorted_unique_t s, InputIterator first, InputIterator last,
               const key_compare& comp = key_compare())
        : c(), compare(comp) { insert(s, first, last); }
    template<class InputIterator, class Allocator>
      flat_map(sorted_unique_t, InputIterator first, InputIterator last,
               const key_compare& comp, const Allocator& a);
    template<class InputIterator, class Allocator>
      flat_map(sorted_unique_t, InputIterator first, InputIterator last, const Allocator& a);

    flat_map(initializer_list<value_type> il, const key_compare& comp = key_compare())
        : flat_map(il.begin(), il.end(), comp) { }
    template<class Allocator>
      flat_map(initializer_list<value_type> il, const key_compare& comp, const Allocator& a);
    template<class Allocator>
      flat_map(initializer_list<value_type> il, const Allocator& a);

    flat_map(sorted_unique_t s, initializer_list<value_type> il,
             const key_compare& comp = key_compare())
        : flat_map(s, il.begin(), il.end(), comp) { }
    template<class Allocator>
      flat_map(sorted_unique_t, initializer_list<value_type> il,
               const key_compare& comp, const Allocator& a);
    template<class Allocator>
      flat_map(sorted_unique_t, initializer_list<value_type> il, const Allocator& a);

    flat_map& operator=(initializer_list<value_type> il);

    // iterators
    iterator               begin() noexcept;
    const_iterator         begin() const noexcept;
    iterator               end() noexcept;
    const_iterator         end() const noexcept;

    reverse_iterator       rbegin() noexcept;
    const_reverse_iterator rbegin() const noexcept;
    reverse_iterator       rend() noexcept;
    const_reverse_iterator rend() const noexcept;

    const_iterator         cbegin() const noexcept;
    const_iterator         cend() const noexcept;
    const_reverse_iterator crbegin() const noexcept;
    const_reverse_iterator crend() const noexcept;

    // \ref{flat.map.capacity}, capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // \ref{flat.map.access}, element access
    mapped_type& operator[](const key_type& x);
    mapped_type& operator[](key_type&& x);
    template<class K> mapped_type& operator[](K&& x);
    mapped_type& at(const key_type& x);
    const mapped_type& at(const key_type& x) const;
    template<class K> mapped_type& at(const K& x);
    template<class K> const mapped_type& at(const K& x) const;

    // \ref{flat.map.modifiers}, modifiers
    template<class... Args> pair<iterator, bool> emplace(Args&&... args);
    template<class... Args>
      iterator emplace_hint(const_iterator position, Args&&... args);

    pair<iterator, bool> insert(const value_type& x)
      { return emplace(x); }
    pair<iterator, bool> insert(value_type&& x)
      { return emplace(std::move(x)); }
    iterator insert(const_iterator position, const value_type& x)
      { return emplace_hint(position, x); }
    iterator insert(const_iterator position, value_type&& x)
      { return emplace_hint(position, std::move(x)); }

    template<class P> pair<iterator, bool> insert(P&& x);
    template<class P>
      iterator insert(const_iterator position, P&&);
    template<class InputIterator>
      void insert(InputIterator first, InputIterator last);
    template<class InputIterator>
      void insert(sorted_unique_t, InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      void insert_range(R&& rg);

    void insert(initializer_list<value_type> il)
      { insert(il.begin(), il.end()); }
    void insert(sorted_unique_t s, initializer_list<value_type> il)
      { insert(s, il.begin(), il.end()); }

    containers extract() &&;
    void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont);

    template<class... Args>
      pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
    template<class... Args>
      pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
    template<class K, class... Args>
      pair<iterator, bool> try_emplace(K&& k, Args&&... args);
    template<class... Args>
      iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
    template<class... Args>
      iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
    template<class K, class... Args>
      iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
    template<class M>
      pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
    template<class M>
      pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
    template<class K, class M>
      pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
    template<class M>
      iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
    template<class M>
      iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
    template<class K, class M>
      iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);

    iterator erase(iterator position);
    iterator erase(const_iterator position);
    size_type erase(const key_type& x);
    template<class K> size_type erase(K&& x);
    iterator erase(const_iterator first, const_iterator last);

    void swap(flat_map& y) noexcept;
    void clear() noexcept;

    // observers
    key_compare key_comp() const;
    value_compare value_comp() const;

    const key_container_type& keys() const noexcept      { return c.keys; }
    const mapped_container_type& values() const noexcept { return c.values; }

    // map operations
    iterator find(const key_type& x);
    const_iterator find(const key_type& x) const;
    template<class K> iterator find(const K& x);
    template<class K> const_iterator find(const K& x) const;

    size_type count(const key_type& x) const;
    template<class K> size_type count(const K& x) const;

    bool contains(const key_type& x) const;
    template<class K> bool contains(const K& x) const;

    iterator lower_bound(const key_type& x);
    const_iterator lower_bound(const key_type& x) const;
    template<class K> iterator lower_bound(const K& x);
    template<class K> const_iterator lower_bound(const K& x) const;

    iterator upper_bound(const key_type& x);
    const_iterator upper_bound(const key_type& x) const;
    template<class K> iterator upper_bound(const K& x);
    template<class K> const_iterator upper_bound(const K& x) const;

    pair<iterator, iterator> equal_range(const key_type& x);
    pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
    template<class K> pair<iterator, iterator> equal_range(const K& x);
    template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const;

    friend bool operator==(const flat_map& x, const flat_map& y);

    friend @\exposid{synth-three-way-result}@<value_type>
      operator<=>(const flat_map& x, const flat_map& y);

    friend void swap(flat_map& x, flat_map& y) noexcept
      { x.swap(y); }

  private:
    containers c;               // \expos
    key_compare compare;        // \expos

    struct key_equiv {  // \expos
      key_equiv(key_compare c) : comp(c) { }
      bool operator()(const_reference x, const_reference y) const {
        return !comp(x.first, y.first) && !comp(y.first, x.first);
      }
      key_compare comp;
    };
  };

  template<class KeyContainer, class MappedContainer,
           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}
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{c.keys} with \tcode{std::move(key_cont)},
\tcode{c.values} with \tcode{std::move(mapped_cont)}, and
\tcode{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(c.keys, c.values);
auto it = ranges::unique(zv, key_equiv(compare)).begin();
auto dist = distance(zv.begin(), it);
c.keys.erase(c.keys.begin() + dist, c.keys.end());
c.values.erase(c.values.begin() + dist, c.values.end());
\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}
template<class Allocator>
  flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont,
           const Allocator& a);
template<class Allocator>
  flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont,
           const key_compare& comp, const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{uses_allocator_v<key_container_type, Allocator>} is \tcode{true} and
\tcode{uses_allocator_v<mapped_container_type, Allocator>} is \tcode{true}.

\pnum
\effects
Equivalent to \tcode{flat_map(key_cont, mapped_cont)} and
\tcode{flat_map(key_cont, mapped_cont, comp)}, respectively,
except that \tcode{c.keys} and \tcode{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}
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{c.keys} with \tcode{std::move(key_cont)},
\tcode{c.values} with \tcode{std::move(mapped_cont)}, and
\tcode{compare} with \tcode{comp}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{flat_map}%
\begin{itemdecl}
template<class Allocator>
  flat_map(sorted_unique_t s, const key_container_type& key_cont,
           const mapped_container_type& mapped_cont, const Allocator& a);
template<class Allocator>
  flat_map(sorted_unique_t s, const key_container_type& key_cont,
           const mapped_container_type& mapped_cont, const key_compare& comp,
           const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{uses_allocator_v<key_container_type, Allocator>} is \tcode{true} and
\tcode{uses_allocator_v<mapped_container_type, Allocator>} is \tcode{true}.

\pnum
\effects
Equivalent to \tcode{flat_map(s, key_cont, mapped_cont)} and
\tcode{flat_map(s, key_cont, \linebreak{}mapped_cont, comp)}, respectively,
except that \tcode{c.keys} and \tcode{c.values} are constructed
with uses-allocator construction\iref{allocator.uses.construction}.

\pnum
\complexity
Linear.
\end{itemdescr}

\indexlibraryctor{flat_map}%
\begin{itemdecl}
template<class Allocator>
  flat_map(const flat_map&, const Allocator& a);
template<class Allocator>
  flat_map(flat_map&&, const Allocator& a);
template<class Allocator>
  flat_map(const key_compare& comp, const Allocator& a);
template<class Allocator>
  explicit flat_map(const Allocator& a);
template<class InputIterator, class Allocator>
  flat_map(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a);
template<class InputIterator, class Allocator>
  flat_map(InputIterator first, InputIterator last, const Allocator& a);
template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
  flat_map(from_range_t, R&& rg, const Allocator& a);
template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
  flat_map(from_range_t, R&& rg, const key_compare& comp, const Allocator& a);
template<class InputIterator, class Allocator>
  flat_map(sorted_unique_t, InputIterator first, InputIterator last,
           const key_compare& comp, const Allocator& a);
template<class InputIterator, class Allocator>
  flat_map(sorted_unique_t, InputIterator first, InputIterator last, const Allocator& a);
template<class Allocator>
  flat_map(initializer_list<value_type> il, const key_compare& comp, const Allocator& a);
template<class Allocator>
  flat_map(initializer_list<value_type> il, const Allocator& a);
template<class Allocator>
  flat_map(sorted_unique_t, initializer_list<value_type> il,
           const key_compare& comp, const Allocator& a);
template<class Allocator>
  flat_map(sorted_unique_t, initializer_list<value_type> il, const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{uses_allocator_v<key_container_type, Allocator>} is \tcode{true} and
\tcode{uses_allocator_v<mapped_container_type, Allocator>} is \tcode{true}.

\pnum
\effects
Equivalent to the corresponding non-allocator constructors
except that \tcode{c.keys} and \tcode{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}
size_type size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{c.keys.size()}.
\end{itemdescr}

\indexlibrarymember{max_size}{flat_map}%
\begin{itemdecl}
size_type max_size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{min<size_type>(c.keys.max_size(), c.values.max_size())}.
\end{itemdescr}

\rSec3[flat.map.access]{Access}

\indexlibrarymember{operator[]}{flat_map}%
\begin{itemdecl}
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}
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> 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}
mapped_type&       at(const key_type& x);
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> mapped_type&       at(const K& x);
template<class K> 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> 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(c.keys, t.first, compare);
auto value_it = c.values.begin() + distance(c.keys.begin(), key_it);
c.keys.insert(key_it, std::move(t.first));
c.values.insert(value_it, std::move(t.second));
\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> pair<iterator, bool> insert(P&& x);
template<class P> 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>
  void insert(InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Adds elements to \tcode{c} as if by:
\begin{codeblock}
for (; first != last; ++first) {
  value_type value = *first;
  c.keys.insert(c.keys.end(), std::move(value.first));
  c.values.insert(c.values.end(), std::move(value.second));
}
\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(c.keys, c.values);
auto it = ranges::unique(zv, key_equiv(compare)).begin();
auto dist = distance(zv.begin(), it);
c.keys.erase(c.keys.begin() + dist, c.keys.end());
c.values.erase(c.values.begin() + dist, c.values.end());
\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>
  void insert(sorted_unique_t, InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Adds elements to \tcode{c} as if by:
\begin{codeblock}
for (; first != last; ++first) {
  value_type value = *first;
  c.keys.insert(c.keys.end(), std::move(value.first));
  c.values.insert(c.values.end(), std::move(value.second));
}
\end{codeblock}
Then, merges the sorted range of newly added elements and
the sorted range of pre-existing elements into a single sorted range; and
finally erases the duplicate elements as if by:
\begin{codeblock}
auto zv = views::zip(c.keys, c.values);
auto it = ranges::unique(zv, key_equiv(compare)).begin();
auto dist = distance(zv.begin(), it);
c.keys.erase(c.keys.begin() + dist, c.keys.end());
c.values.erase(c.values.begin() + dist, c.values.end());
\end{codeblock}

\pnum
\complexity
Linear in $N$, where $N$ is \tcode{size()} after the operation.

\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>
  void insert_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Adds elements to \tcode{c} as if by:
\begin{codeblock}
for (const auto& e : rg) {
  c.keys.insert(c.keys.end(), e.first);
  c.values.insert(c.values.end(), 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(c.keys, c.values);
auto it = ranges::unique(zv, key_equiv(compare)).begin();
auto dist = distance(zv.begin(), it);
c.keys.erase(c.keys.begin() + dist, c.keys.end());
c.values.erase(c.values.begin() + dist, c.values.end());
\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{try_emplace}{flat_map}%
\begin{itemdecl}
template<class... Args>
  pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
template<class... Args>
  pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
template<class... Args>
  iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
template<class... Args>
  iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
\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(c.keys, k, compare);
auto value_it = c.values.begin() + distance(c.keys.begin(), key_it);
c.keys.insert(key_it, std::forward<decltype(k)>(k));
c.values.emplace(value_it, std::forward<Args>(args)...);
\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>
  pair<iterator, bool> try_emplace(K&& k, Args&&... args);
template<class K, class... Args>
  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 = ranges::upper_bound(c.keys, k, compare);
auto value_it = c.values.begin() + distance(c.keys.begin(), key_it);
c.keys.emplace(key_it, std::forward<K>(k));
c.values.emplace(value_it, std::forward<Args>(args)...);
\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>
  pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
template<class M>
  pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
template<class M>
  iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
template<class M>
  iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
\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>
  pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
template<class K, class M>
  iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);
\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}
void swap(flat_map& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
ranges::swap(compare, y.compare);
ranges::swap(c.keys, y.c.keys);
ranges::swap(c.values, y.c.values);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{extract}{flat_map}%
\begin{itemdecl}
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(c)}.
\end{itemdescr}

\indexlibrarymember{replace}{flat_map}%
\begin{itemdecl}
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 \tcode{compare}, and
\tcode{key_cont} contains no equal elements.

\pnum
\effects
Equivalent to:
\begin{codeblock}
c.keys = std::move(key_cont);
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>
  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 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 constructor or 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.

\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 comp;                                 // \expos
      value_compare(key_compare c) : comp(c) { }        // \expos

    public:
      bool operator()(const_reference x, const_reference y) const {
        return comp(x.first, y.first);
      }
    };

    struct containers {
      key_container_type keys;
      mapped_container_type values;
    };

    // \ref{flat.multimap.cons}, construct/copy/destroy
    flat_multimap() : flat_multimap(key_compare()) { }

    template<class Allocator>
      flat_multimap(const flat_multimap&, const Allocator& a);
    template<class Allocator>
      flat_multimap(flat_multimap&&, const Allocator& a);

    flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont,
                  const key_compare& comp = key_compare());
    template<class Allocator>
      flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont,
                    const Allocator& a);
    template<class Allocator>
      flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont,
                    const key_compare& comp, const Allocator& a);

    flat_multimap(sorted_equivalent_t,
                  key_container_type key_cont, mapped_container_type mapped_cont,
                  const key_compare& comp = key_compare());
    template<class Allocator>
      flat_multimap(sorted_equivalent_t, const key_container_type& key_cont,
                    const mapped_container_type& mapped_cont, const Allocator& a);
    template<class Allocator>
      flat_multimap(sorted_equivalent_t, const key_container_type& key_cont,
                    const mapped_container_type& mapped_cont,
                    const key_compare& comp, const Allocator& a);

    explicit flat_multimap(const key_compare& comp)
      : c(), compare(comp) { }
    template<class Allocator>
      flat_multimap(const key_compare& comp, const Allocator& a);
    template<class Allocator>
      explicit flat_multimap(const Allocator& a);

    template<class InputIterator>
      flat_multimap(InputIterator first, InputIterator last,
                    const key_compare& comp = key_compare())
        : c(), compare(comp)
        { insert(first, last); }
    template<class InputIterator, class Allocator>
      flat_multimap(InputIterator first, InputIterator last,
                    const key_compare& comp, const Allocator& a);
    template<class InputIterator, class Allocator>
      flat_multimap(InputIterator first, InputIterator last, const Allocator& a);

    template<@\exposconcept{container-compatible-range}@<value_type> R>
      flat_multimap(from_range_t fr, R&& rg)
        : flat_multimap(fr, std::forward<R>(rg), key_compare()) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
      flat_multimap(from_range_t, R&& rg, const Allocator& a);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      flat_multimap(from_range_t, R&& rg, const key_compare& comp)
        : flat_multimap(comp) { insert_range(std::forward<R>(rg)); }
    template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
      flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Allocator& a);

    template<class InputIterator>
      flat_multimap(sorted_equivalent_t s, InputIterator first, InputIterator last,
                    const key_compare& comp = key_compare())
        : c(), compare(comp) { insert(s, first, last); }
    template<class InputIterator, class Allocator>
      flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last,
                    const key_compare& comp, const Allocator& a);
    template<class InputIterator, class Allocator>
      flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last,
                    const Allocator& a);

    flat_multimap(initializer_list<value_type> il, const key_compare& comp = key_compare())
        : flat_multimap(il.begin(), il.end(), comp) { }
    template<class Allocator>
      flat_multimap(initializer_list<value_type> il, const key_compare& comp,
                    const Allocator& a);
    template<class Allocator>
      flat_multimap(initializer_list<value_type> il, const Allocator& a);

    flat_multimap(sorted_equivalent_t s, initializer_list<value_type> il,
                  const key_compare& comp = key_compare())
        : flat_multimap(s, il.begin(), il.end(), comp) { }
    template<class Allocator>
      flat_multimap(sorted_equivalent_t, initializer_list<value_type> il,
                    const key_compare& comp, const Allocator& a);
    template<class Allocator>
      flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const Allocator& a);

    flat_multimap& operator=(initializer_list<value_type> il);

    // iterators
    iterator               begin() noexcept;
    const_iterator         begin() const noexcept;
    iterator               end() noexcept;
    const_iterator         end() const noexcept;

    reverse_iterator       rbegin() noexcept;
    const_reverse_iterator rbegin() const noexcept;
    reverse_iterator       rend() noexcept;
    const_reverse_iterator rend() const noexcept;

    const_iterator         cbegin() const noexcept;
    const_iterator         cend() const noexcept;
    const_reverse_iterator crbegin() const noexcept;
    const_reverse_iterator crend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> iterator emplace(Args&&... args);
    template<class... Args>
      iterator emplace_hint(const_iterator position, Args&&... args);

    iterator insert(const value_type& x)
      { return emplace(x); }
    iterator insert(value_type&& x)
      { return emplace(std::move(x)); }
    iterator insert(const_iterator position, const value_type& x)
      { return emplace_hint(position, x); }
    iterator insert(const_iterator position, value_type&& x)
      { return emplace_hint(position, std::move(x)); }

    template<class P> iterator insert(P&& x);
    template<class P>
      iterator insert(const_iterator position, P&&);
    template<class InputIterator>
      void insert(InputIterator first, InputIterator last);
    template<class InputIterator>
      void insert(sorted_equivalent_t, InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      void insert_range(R&& rg);

    void insert(initializer_list<value_type> il)
      { insert(il.begin(), il.end()); }
    void insert(sorted_equivalent_t s, initializer_list<value_type> il)
      { insert(s, il.begin(), il.end()); }

    containers extract() &&;
    void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont);

    iterator erase(iterator position);
    iterator erase(const_iterator position);
    size_type erase(const key_type& x);
    template<class K> size_type erase(K&& x);
    iterator erase(const_iterator first, const_iterator last);

    void swap(flat_multimap&) noexcept;
    void clear() noexcept;

    // observers
    key_compare key_comp() const;
    value_compare value_comp() const;

    const key_container_type& keys() const noexcept { return c.keys; }
    const mapped_container_type& values() const noexcept { return c.values; }

    // map operations
    iterator find(const key_type& x);
    const_iterator find(const key_type& x) const;
    template<class K> iterator find(const K& x);
    template<class K> const_iterator find(const K& x) const;

    size_type count(const key_type& x) const;
    template<class K> size_type count(const K& x) const;

    bool contains(const key_type& x) const;
    template<class K> bool contains(const K& x) const;

    iterator lower_bound(const key_type& x);
    const_iterator lower_bound(const key_type& x) const;
    template<class K> iterator lower_bound(const K& x);
    template<class K> const_iterator lower_bound(const K& x) const;

    iterator upper_bound(const key_type& x);
    const_iterator upper_bound(const key_type& x) const;
    template<class K> iterator upper_bound(const K& x);
    template<class K> const_iterator upper_bound(const K& x) const;

    pair<iterator, iterator> equal_range(const key_type& x);
    pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
    template<class K>
      pair<iterator, iterator> equal_range(const K& x);
    template<class K>
      pair<const_iterator, const_iterator> equal_range(const K& x) const;

    friend bool operator==(const flat_multimap& x, const flat_multimap& y);

    friend @\exposid{synth-three-way-result}@<value_type>
      operator<=>(const flat_multimap& x, const flat_multimap& y);

    friend void swap(flat_multimap& x, flat_multimap& y) noexcept
      { x.swap(y); }

  private:
    containers c;               // \expos
    key_compare 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}
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{c.keys} with \tcode{std::move(key_cont)},
\tcode{c.values} with \tcode{std::move(mapped_cont)}, and
\tcode{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}
template<class Allocator>
  flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont,
                const Allocator& a);
template<class Allocator>
  flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont,
                const key_compare& comp, const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{uses_allocator_v<key_container_type, Allocator>} is \tcode{true} and
\tcode{uses_allocator_v<mapped_container_type, Allocator>} is \tcode{true}.

\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{c.keys} and \tcode{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}
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{c.keys} with \tcode{std::move(key_cont)},
\tcode{c.values} with \tcode{std::move(mapped_cont)}, and
\tcode{compare} with \tcode{comp}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{flat_multimap}%
\begin{itemdecl}
template<class Allocator>
  flat_multimap(sorted_equivalent_t s, const key_container_type& key_cont,
                const mapped_container_type& mapped_cont, const Allocator& a);
template<class Allocator>
  flat_multimap(sorted_equivalent_t s, const key_container_type& key_cont,
                const mapped_container_type& mapped_cont, const key_compare& comp,
                const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{uses_allocator_v<key_container_type, Allocator>} is \tcode{true} and
\tcode{uses_allocator_v<mapped_container_type, Allocator>} is \tcode{true}.

\pnum
\effects
Equivalent to \tcode{flat_multimap(s, key_cont, mapped_cont)} and
\tcode{flat_multimap(s, key_cont, mapped_cont, comp)}, respectively,
except that \tcode{c.keys} and \tcode{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 Allocator>
  flat_multimap(const flat_multimap&, const Allocator& a);
template<class Allocator>
  flat_multimap(flat_multimap&&, const Allocator& a);
template<class Allocator>
  flat_multimap(const key_compare& comp, const Allocator& a);
template<class Allocator>
  explicit flat_multimap(const Allocator& a);
template<class InputIterator, class Allocator>
  flat_multimap(InputIterator first, InputIterator last, const key_compare& comp,
                const Allocator& a);
template<class InputIterator, class Allocator>
  flat_multimap(InputIterator first, InputIterator last, const Allocator& a);
template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
  flat_multimap(from_range_t, R&& rg, const Allocator& a);
template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
  flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Allocator& a);
template<class InputIterator, class Allocator>
  flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last,
                const key_compare& comp, const Allocator& a);
template<class InputIterator, class Allocator>
  flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last,
                const Allocator& a);
template<class Allocator>
  flat_multimap(initializer_list<value_type> il, const key_compare& comp, const Allocator& a);
template<class Allocator>
  flat_multimap(initializer_list<value_type> il, const Allocator& a);
template<class Allocator>
  flat_multimap(sorted_equivalent_t, initializer_list<value_type> il,
                const key_compare& comp, const Allocator& a);
template<class Allocator>
  flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{uses_allocator_v<key_container_type, Allocator>} is \tcode{true} and
\tcode{uses_allocator_v<mapped_container_type, Allocator>} is \tcode{true}.

\pnum
\effects
Equivalent to the corresponding non-allocator constructors
except that \tcode{c.keys} and \tcode{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>
  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]{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 is 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 constructor or 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.

\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                 = typename KeyContainer::size_type;
    using difference_type           = typename 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
    flat_set() : flat_set(key_compare()) { }

    template<class Allocator>
      flat_set(const flat_set&, const Allocator& a);
    template<class Allocator>
      flat_set(flat_set&&, const Allocator& a);

    explicit flat_set(container_type cont, const key_compare& comp = key_compare());
    template<class Allocator>
      flat_set(const container_type& cont, const Allocator& a);
    template<class Allocator>
      flat_set(const container_type& cont, const key_compare& comp, const Allocator& a);

    flat_set(sorted_unique_t, container_type cont, const key_compare& comp = key_compare())
      : @\exposid{c}@(std::move(cont)), @\exposid{compare}@(comp) { }
    template<class Allocator>
      flat_set(sorted_unique_t, const container_type& cont, const Allocator& a);
    template<class Allocator>
      flat_set(sorted_unique_t, const container_type& cont,
               const key_compare& comp, const Allocator& a);

    explicit flat_set(const key_compare& comp)
      : @\exposid{c}@(), @\exposid{compare}@(comp) { }
    template<class Allocator>
      flat_set(const key_compare& comp, const Allocator& a);
    template<class Allocator>
      explicit flat_set(const Allocator& a);

    template<class InputIterator>
      flat_set(InputIterator first, InputIterator last, const key_compare& comp = key_compare())
        : @\exposid{c}@(), @\exposid{compare}@(comp)
        { insert(first, last); }
    template<class InputIterator, class Allocator>
      flat_set(InputIterator first, InputIterator last,
               const key_compare& comp, const Allocator& a);
    template<class InputIterator, class Allocator>
      flat_set(InputIterator first, InputIterator last, const Allocator& a);

    template<@\exposconcept{container-compatible-range}@<value_type> R>
      flat_set(from_range_t fr, R&& rg)
        : flat_set(fr, std::forward<R>(rg), key_compare()) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
      flat_set(from_range_t, R&& rg, const Allocator& a);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      flat_set(from_range_t, R&& rg, const key_compare& comp)
        : flat_set(comp)
        { insert_range(std::forward<R>(rg)); }
    template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
       flat_set(from_range_t, R&& rg, const key_compare& comp, const Allocator& a);

    template<class InputIterator>
      flat_set(sorted_unique_t, InputIterator first, InputIterator last,
               const key_compare& comp = key_compare())
        : @\exposid{c}@(first, last), @\exposid{compare}@(comp) { }
    template<class InputIterator, class Allocator>
      flat_set(sorted_unique_t, InputIterator first, InputIterator last,
               const key_compare& comp, const Allocator& a);
    template<class InputIterator, class Allocator>
      flat_set(sorted_unique_t, InputIterator first, InputIterator last, const Allocator& a);

    flat_set(initializer_list<value_type> il, const key_compare& comp = key_compare())
        : flat_set(il.begin(), il.end(), comp) { }
    template<class Allocator>
      flat_set(initializer_list<value_type> il, const key_compare& comp, const Allocator& a);
    template<class Allocator>
      flat_set(initializer_list<value_type> il, const Allocator& a);

    flat_set(sorted_unique_t s, initializer_list<value_type> il,
             const key_compare& comp = key_compare())
        : flat_set(s, il.begin(), il.end(), comp) { }
    template<class Allocator>
      flat_set(sorted_unique_t, initializer_list<value_type> il,
               const key_compare& comp, const Allocator& a);
    template<class Allocator>
      flat_set(sorted_unique_t, initializer_list<value_type> il, const Allocator& a);

    flat_set& operator=(initializer_list<value_type>);

    // iterators
    iterator               begin() noexcept;
    const_iterator         begin() const noexcept;
    iterator               end() noexcept;
    const_iterator         end() const noexcept;

    reverse_iterator       rbegin() noexcept;
    const_reverse_iterator rbegin() const noexcept;
    reverse_iterator       rend() noexcept;
    const_reverse_iterator rend() const noexcept;

    const_iterator         cbegin() const noexcept;
    const_iterator         cend() const noexcept;
    const_reverse_iterator crbegin() const noexcept;
    const_reverse_iterator crend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // \ref{flat.set.modifiers}, modifiers
    template<class... Args> pair<iterator, bool> emplace(Args&&... args);
    template<class... Args>
      iterator emplace_hint(const_iterator position, Args&&... args);

    pair<iterator, bool> insert(const value_type& x)
      { return emplace(x); }
    pair<iterator, bool> insert(value_type&& x)
      { return emplace(std::move(x)); }
    template<class K> pair<iterator, bool> insert(K&& x);
    iterator insert(const_iterator position, const value_type& x)
      { return emplace_hint(position, x); }
    iterator insert(const_iterator position, value_type&& x)
      { return emplace_hint(position, std::move(x)); }
    template<class K> iterator insert(const_iterator hint, K&& x);

    template<class InputIterator>
      void insert(InputIterator first, InputIterator last);
    template<class InputIterator>
      void insert(sorted_unique_t, InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      void insert_range(R&& rg);

    void insert(initializer_list<value_type> il)
      { insert(il.begin(), il.end()); }
    void insert(sorted_unique_t s, initializer_list<value_type> il)
      { insert(s, il.begin(), il.end()); }

    container_type extract() &&;
    void replace(container_type&&);

    iterator erase(iterator position);
    iterator erase(const_iterator position);
    size_type erase(const key_type& x);
    template<class K> size_type erase(K&& x);
    iterator erase(const_iterator first, const_iterator last);

    void swap(flat_set& y) noexcept;
    void clear() noexcept;

    // observers
    key_compare key_comp() const;
    value_compare value_comp() const;

    // set operations
    iterator find(const key_type& x);
    const_iterator find(const key_type& x) const;
    template<class K> iterator find(const K& x);
    template<class K> const_iterator find(const K& x) const;

    size_type count(const key_type& x) const;
    template<class K> size_type count(const K& x) const;

    bool contains(const key_type& x) const;
    template<class K> bool contains(const K& x) const;

    iterator lower_bound(const key_type& x);
    const_iterator lower_bound(const key_type& x) const;
    template<class K> iterator lower_bound(const K& x);
    template<class K> const_iterator lower_bound(const K& x) const;

    iterator upper_bound(const key_type& x);
    const_iterator upper_bound(const key_type& x) const;
    template<class K> iterator upper_bound(const K& x);
    template<class K> const_iterator upper_bound(const K& x) const;

    pair<iterator, iterator> equal_range(const key_type& x);
    pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
    template<class K>
      pair<iterator, iterator> equal_range(const K& x);
    template<class K>
      pair<const_iterator, const_iterator> equal_range(const K& x) const;

    friend bool operator==(const flat_set& x, const flat_set& y);

    friend @\placeholder{synth-three-way-result}@<value_type>
      operator<=>(const flat_set& x, const flat_set& y);

    friend void swap(flat_set& x, flat_set& y) noexcept { x.swap(y); }

  private:
    container_type @\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}
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 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}

\indexlibraryctor{flat_set}%
\begin{itemdecl}
template<class Allocator>
  flat_set(const container_type& cont, const Allocator& a);
template<class Allocator>
  flat_set(const container_type& cont, const key_compare& comp, const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{uses_allocator_v<container_type, Allocator>} is \tcode{true}.

\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 Allocator>
  flat_set(sorted_unique_t s, const container_type& cont, const Allocator& a);
template<class Allocator>
  flat_set(sorted_unique_t s, const container_type& cont,
           const key_compare& comp, const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{uses_allocator_v<container_type, Allocator>} is \tcode{true}.

\pnum
\effects
Equivalent to
\tcode{flat_set(s, cont)} and \tcode{flat_set(s, cont, 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 Allocator>
  flat_set(const flat_set&, const Allocator& a);
template<class Allocator>
  flat_set(flat_set&&, const Allocator& a);
template<class Allocator>
  flat_set(const key_compare& comp, const Allocator& a);
template<class Allocator>
  explicit flat_set(const Allocator& a);
template<class InputIterator, class Allocator>
  flat_set(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a);
template<class InputIterator, class Allocator>
  flat_set(InputIterator first, InputIterator last, const Allocator& a);
template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
  flat_set(from_range_t, R&& rg, const Allocator& a);
template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
  flat_set(from_range_t, R&& rg, const key_compare& comp, const Allocator& a);
template<class InputIterator, class Allocator>
  flat_set(sorted_unique_t, InputIterator first, InputIterator last,
           const key_compare& comp, const Allocator& a);
template<class InputIterator, class Allocator>
  flat_set(sorted_unique_t, InputIterator first, InputIterator last, const Allocator& a);
template<class Allocator>
  flat_set(initializer_list<value_type> il, const key_compare& comp, const Allocator& a);
template<class Allocator>
  flat_set(initializer_list<value_type> il, const Allocator& a);
template<class Allocator>
  flat_set(sorted_unique_t, initializer_list<value_type> il,
           const key_compare& comp, const Allocator& a);
template<class Allocator>
  flat_set(sorted_unique_t, initializer_list<value_type> il, const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{uses_allocator_v<container_type, Allocator>} is \tcode{true}.

\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> pair<iterator, bool> insert(K&& x);
template<class K> 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 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}{flatset}%
\begin{itemdecl}
template<class InputIterator>
  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>
  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>
  void insert_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Adds elements to \exposid{c} as if by:
\begin{codeblock}
for (const auto& e : rg) {
  @\exposid{c}@.insert(@\exposid{c}@.end(), 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{swap}{flat_set}%
\begin{itemdecl}
void swap(flat_set& y) noexcept;
\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}{flatset}%
\begin{itemdecl}
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}
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>
  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 is 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 constructor or 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.

\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                 = typename KeyContainer::size_type;
    using difference_type           = typename 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
    flat_multiset() : flat_multiset(key_compare()) { }

    template<class Allocator>
      flat_multiset(const flat_multiset&, const Allocator& a);
    template<class Allocator>
      flat_multiset(flat_multiset&&, const Allocator& a);

    explicit flat_multiset(container_type cont, const key_compare& comp = key_compare());
    template<class Allocator>
      flat_multiset(const container_type& cont, const Allocator& a);
    template<class Allocator>
      flat_multiset(const container_type& cont, const key_compare& comp, const Allocator& a);

    flat_multiset(sorted_equivalent_t, container_type cont,
                  const key_compare& comp = key_compare())
      : @\exposid{c}@(std::move(cont)), @\exposid{compare}@(comp) { }
    template<class Allocator>
      flat_multiset(sorted_equivalent_t, const container_type& cont, const Allocator& a);
    template<class Allocator>
      flat_multiset(sorted_equivalent_t, const container_type& cont,
                    const key_compare& comp, const Allocator& a);

    explicit flat_multiset(const key_compare& comp)
      : @\exposid{c}@(), @\exposid{compare}@(comp) { }
    template<class Allocator>
      flat_multiset(const key_compare& comp, const Allocator& a);
    template<class Allocator>
      explicit flat_multiset(const Allocator& a);

    template<class InputIterator>
      flat_multiset(InputIterator first, InputIterator last,
                    const key_compare& comp = key_compare())
        : @\exposid{c}@(), @\exposid{compare}@(comp)
        { insert(first, last); }
    template<class InputIterator, class Allocator>
      flat_multiset(InputIterator first, InputIterator last,
                    const key_compare& comp, const Allocator& a);
    template<class InputIterator, class Allocator>
      flat_multiset(InputIterator first, InputIterator last, const Allocator& a);

    template<@\exposconcept{container-compatible-range}@<value_type> R>
      flat_multiset(from_range_t fr, R&& rg)
        : flat_multiset(fr, std::forward<R>(rg), key_compare()) { }
    template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
      flat_multiset(from_range_t, R&& rg, const Allocator& a);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      flat_multiset(from_range_t, R&& rg, const key_compare& comp)
        : flat_multiset(comp)
        { insert_range(std::forward<R>(rg)); }
    template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
      flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Allocator& a);

    template<class InputIterator>
      flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last,
                    const key_compare& comp = key_compare())
        : @\exposid{c}@(first, last), @\exposid{compare}@(comp) { }
    template<class InputIterator, class Allocator>
      flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last,
                    const key_compare& comp, const Allocator& a);
    template<class InputIterator, class Allocator>
      flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last,
                    const Allocator& a);

    flat_multiset(initializer_list<value_type> il, const key_compare& comp = key_compare())
      : flat_multiset(il.begin(), il.end(), comp) { }
    template<class Allocator>
      flat_multiset(initializer_list<value_type> il, const key_compare& comp,
                    const Allocator& a);
    template<class Allocator>
      flat_multiset(initializer_list<value_type> il, const Allocator& a);

    flat_multiset(sorted_equivalent_t s, initializer_list<value_type> il,
                  const key_compare& comp = key_compare())
        : flat_multiset(s, il.begin(), il.end(), comp) { }
    template<class Allocator>
      flat_multiset(sorted_equivalent_t, initializer_list<value_type> il,
                    const key_compare& comp, const Allocator& a);
    template<class Allocator>
      flat_multiset(sorted_equivalent_t, initializer_list<value_type> il, const Allocator& a);

    flat_multiset& operator=(initializer_list<value_type>);

    // iterators
    iterator               begin() noexcept;
    const_iterator         begin() const noexcept;
    iterator               end() noexcept;
    const_iterator         end() const noexcept;

    reverse_iterator       rbegin() noexcept;
    const_reverse_iterator rbegin() const noexcept;
    reverse_iterator       rend() noexcept;
    const_reverse_iterator rend() const noexcept;

    const_iterator         cbegin() const noexcept;
    const_iterator         cend() const noexcept;
    const_reverse_iterator crbegin() const noexcept;
    const_reverse_iterator crend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // \ref{flat.multiset.modifiers}, modifiers
    template<class... Args> iterator emplace(Args&&... args);
    template<class... Args>
      iterator emplace_hint(const_iterator position, Args&&... args);

    iterator insert(const value_type& x)
      { return emplace(x); }
    iterator insert(value_type&& x)
      { return emplace(std::move(x)); }
    iterator insert(const_iterator position, const value_type& x)
      { return emplace_hint(position, x); }
    iterator insert(const_iterator position, value_type&& x)
      { return emplace_hint(position, std::move(x)); }

    template<class InputIterator>
      void insert(InputIterator first, InputIterator last);
    template<class InputIterator>
      void insert(sorted_equivalent_t, InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<value_type> R>
      void insert_range(R&& rg);

    void insert(initializer_list<value_type> il)
      { insert(il.begin(), il.end()); }
    void insert(sorted_equivalent_t s, initializer_list<value_type> il)
      { insert(s, il.begin(), il.end()); }

    container_type extract() &&;
    void replace(container_type&&);

    iterator erase(iterator position);
    iterator erase(const_iterator position);
    size_type erase(const key_type& x);
    template<class K> size_type erase(K&& x);
    iterator erase(const_iterator first, const_iterator last);

    void swap(flat_multiset& y) noexcept;
    void clear() noexcept;

    // observers
    key_compare key_comp() const;
    value_compare value_comp() const;

    // set operations
    iterator find(const key_type& x);
    const_iterator find(const key_type& x) const;
    template<class K> iterator find(const K& x);
    template<class K> const_iterator find(const K& x) const;

    size_type count(const key_type& x) const;
    template<class K> size_type count(const K& x) const;

    bool contains(const key_type& x) const;
    template<class K> bool contains(const K& x) const;

    iterator lower_bound(const key_type& x);
    const_iterator lower_bound(const key_type& x) const;
    template<class K> iterator lower_bound(const K& x);
    template<class K> const_iterator lower_bound(const K& x) const;

    iterator upper_bound(const key_type& x);
    const_iterator upper_bound(const key_type& x) const;
    template<class K> iterator upper_bound(const K& x);
    template<class K> const_iterator upper_bound(const K& x) const;

    pair<iterator, iterator> equal_range(const key_type& x);
    pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
    template<class K>
      pair<iterator, iterator> equal_range(const K& x);
    template<class K>
      pair<const_iterator, const_iterator> equal_range(const K& x) const;

    friend bool operator==(const flat_multiset& x, const flat_multiset& y);

    friend @\placeholder{synth-three-way-result}@<value_type>
      operator<=>(const flat_multiset& x, const flat_multiset& y);

    friend void swap(flat_multiset& x, flat_multiset& y) noexcept
      { x.swap(y); }

  private:
    container_type @\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}
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 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}

\indexlibraryctor{flat_multiset}%
\begin{itemdecl}
template<class Allocator>
  flat_multiset(const container_type& cont, const Allocator& a);
template<class Allocator>
  flat_multiset(const container_type& cont, const key_compare& comp, const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{uses_allocator_v<container_type, Allocator>} is \tcode{true}.

\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 Allocator>
  flat_multiset(sorted_equivalent_t s, const container_type& cont, const Allocator& a);
template<class Allocator>
  flat_multiset(sorted_equivalent_t s, const container_type& cont,
                const key_compare& comp, const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{uses_allocator_v<container_type, Allocator>} is \tcode{true}.

\pnum
\effects
Equivalent to \tcode{flat_multiset(s, cont)} and
\tcode{flat_multiset(s, 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 Allocator>
  flat_multiset(const flat_multiset&, const Allocator& a);
template<class Allocator>
  flat_multiset(flat_multiset&&, const Allocator& a);
template<class Allocator>
  flat_multiset(const key_compare& comp, const Allocator& a);
template<class Allocator>
  explicit flat_multiset(const Allocator& a);
template<class InputIterator, class Allocator>
  flat_multiset(InputIterator first, InputIterator last,
                const key_compare& comp, const Allocator& a);
template<class InputIterator, class Allocator>
  flat_multiset(InputIterator first, InputIterator last, const Allocator& a);
template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
  flat_multiset(from_range_t, R&& rg, const Allocator& a);
template<@\exposconcept{container-compatible-range}@<value_type> R, class Allocator>
  flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Allocator& a);
template<class InputIterator, class Allocator>
  flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last,
                const key_compare& comp, const Allocator& a);
template<class InputIterator, class Allocator>
  flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const Allocator& a);
template<class Allocator>
  flat_multiset(initializer_list<value_type> il, const key_compare& comp, const Allocator& a);
template<class Allocator>
  flat_multiset(initializer_list<value_type> il, const Allocator& a);
template<class Allocator>
  flat_multiset(sorted_equivalent_t, initializer_list<value_type> il,
                const key_compare& comp, const Allocator& a);
template<class Allocator>
  flat_multiset(sorted_equivalent_t, initializer_list<value_type> il, const Allocator& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{uses_allocator_v<container_type, Allocator>} is \tcode{true}.

\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> 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(c, t, compare);
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>
  void insert(InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Adds elements to \exposid{c} as if by:
\begin{codeblock}
c.insert(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>
  void insert(sorted_equivalent_t, InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{insert(first, last)}.

\pnum
\complexity
Linear.
\end{itemdescr}

\indexlibrarymember{swap}{flat_multiset}%
\begin{itemdecl}
void swap(flat_multiset& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
ranges::swap(compare, y.compare);
ranges::swap(c, y.c);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{extract}{flat_multiset}%
\begin{itemdecl}
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(c)}.
\end{itemdescr}

\indexlibrarymember{replace}{flat_multiset}%
\begin{itemdecl}
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{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>
  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 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>
      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>
  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 \libheader{span} defines the view \tcode{span}.
The header \libheader{mdspan} defines the class template \tcode{mdspan} and
other facilities for interacting with these multidimensional views.

\rSec2[views.contiguous]{Contiguous access}

\rSec3[span.syn]{Header \tcode{<span>} synopsis}%

\indexheader{span}%
\begin{codeblock}
#include <initializer_list>     // see \ref{initializer.list.syn}

// 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<decltype(T::value)> &&
      !is_same_v<bool, remove_const_t<decltype(T::value)>> &&
      @\libconcept{convertible_to}@<T, decltype(T::value)> &&
      @\libconcept{equality_comparable_with}@<T, decltype(T::value)> &&
      bool_constant<T() == T::value>::value &&
      bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value;

  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 explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il);
    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;
    [[nodiscard]] 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
\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}.
\item
If \tcode{extent} is not equal to \tcode{dynamic_extent},
then \tcode{count} is equal to \tcode{extent}.
\end{itemize}

\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
If \tcode{extent} is not equal to \tcode{dynamic_extent},
then \tcode{last - first} is equal to \tcode{extent}.
\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
\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 If \tcode{extent} is not equal to \tcode{dynamic_extent},
then \tcode{ranges::size(r)} is equal to \tcode{extent}.
\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
\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 explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_const_v<element_type>} is \tcode{true}.

\pnum
\expects
If \tcode{extent} is not equal to \tcode{dynamic_extent}, then
\tcode{il.size()} is equal to \tcode{extent}.

\pnum
\effects
Initializes \exposid{data_} with \tcode{il.begin()} and
\exposid{size_} with \tcode{il.size()}.
\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
\expects
If \tcode{extent} is not equal to \tcode{dynamic_extent},
then \tcode{s.size()} is equal to \tcode{extent}.

\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
\expects
\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
\expects
\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
\expects
\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
\expects
\tcode{count <= size()} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return \{data(), count\};}
\end{itemdescr}

\indexlibrarymember{span}{last}%
\begin{itemdecl}
constexpr span<element_type, dynamic_extent> last(size_type count) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{count <= size()} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return \{data() + (size() - count), count\};}
\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
\expects
\begin{codeblock}
offset <= size() && (count == dynamic_extent || count <= size() - offset)
\end{codeblock}
is \tcode{true}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
return {data() + offset, count == dynamic_extent ? size() - offset : count};
\end{codeblock}
\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}
[[nodiscard]] 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
\expects
\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
\expects
\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
\expects
\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
\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}.

\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}
// all 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.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.mdspan}, class template \tcode{mdspan}
  template<class ElementType, class Extents, class LayoutPolicy = layout_right,
           class AccessorPolicy = default_accessor<ElementType>>
    class mdspan;

  // \ref{mdspan.sub}, \tcode{submdspan} creation
  template<class OffsetType, class LengthType, class StrideType>
    struct strided_slice;

  template<class LayoutMapping>
    struct submdspan_mapping_result;

  struct full_extent_t { explicit full_extent_t() = default; };
  inline constexpr full_extent_t full_extent{};

  template<class IndexType, class... Extents, class... SliceSpecifiers>
    constexpr auto submdspan_extents(const extents<IndexType, Extents...>&, SliceSpecifiers...);

  // \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... 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 subclause \iref{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 index_type = IndexType;
    using size_type = make_unsigned_t<index_type>;
    using rank_type = size_t;

    // \ref{mdspan.extents.obs}, observers of the multidimensional index space
    static constexpr rank_type rank() noexcept { return sizeof...(Extents); }
    static constexpr rank_type rank_dynamic() 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{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>(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{dynamic_rank()},
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}

\rSec3[mdspan.layout]{Layout mapping}

\rSec4[mdspan.layout.general]{General}

\pnum
In subclauses \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 subclauses \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.
\end{itemdescr}

\begin{itemdecl}
M::is_always_unique()
\end{itemdecl}

\begin{itemdescr}
\pnum
\result
A constant expression\iref{expr.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} 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} 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 layout_left {
    template<class Extents>
      class mapping;
  };
  struct layout_right {
    template<class Extents>
      class mapping;
  };
  struct layout_stride {
    template<class Extents>
      class mapping;
  };

  template<size_t PaddingValue>
  struct layout_left_padded {
    template<class Extents> class mapping;
  };
  template<size_t PaddingValue>
  struct layout_right_padded {
    template<class Extents> class mapping;
  };
}
\end{codeblock}

\pnum
Each of \tcode{layout_left}, \tcode{layout_right}, and \tcode{layout_stride}
meets the layout mapping policy requirements and is a trivial type.

\pnum
Each specialization of
\tcode{layout_left_padded} and \tcode{layout_right_padded}
meets the layout mapping policy requirements and is a trivial type.

\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.

\begin{codeblock}
namespace std {
  template<class Extents>
  class layout_left::mapping {
  public:
    using extents_type = Extents;
    using index_type = typename extents_type::index_type;
    using size_type = typename extents_type::size_type;
    using rank_type = typename extents_type::rank_type;
    using layout_type = 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(extents_type::rank() > 0)
        mapping(const layout_stride::mapping<OtherExtents>&);

    constexpr mapping& operator=(const mapping&) noexcept = default;

    // \ref{mdspan.layout.left.obs}, observers
    constexpr const extents_type& extents() 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 is_always_unique() noexcept { return true; }
    static constexpr bool is_always_exhaustive() noexcept { return true; }
    static constexpr bool is_always_strided() noexcept { return true; }

    static constexpr bool is_unique() noexcept { return true; }
    static constexpr bool is_exhaustive() noexcept { return true; }
    static constexpr bool is_strided() 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 submdspan_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 OtherExents>
  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(0)}.
\item
\tcode{other.required_span_size()} is representable as
a value of type \tcode{index_type}.
\end{itemize}

\pnum
\effects
Effects: Direct-non-list-initializes
\tcode{extents_} with \tcode{other.extents()}.
\end{itemdescr}

\indexlibraryctor{layout_left::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  constexpr explicit(extents_type::rank() > 0)
    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()}.
\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>(i) * stride(P)) + ... + 0);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{stride}{layout_left::mapping}%
\begin{itemdecl}
constexpr index_type stride(rank_type i) const;
\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.

\begin{codeblock}
namespace std {
  template<class Extents>
  class layout_right::mapping {
  public:
    using extents_type = Extents;
    using index_type = typename extents_type::index_type;
    using size_type = typename extents_type::size_type;
    using rank_type = typename extents_type::rank_type;
    using layout_type = 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(extents_type::rank() > 0)
        mapping(const layout_stride::mapping<OtherExtents>&) noexcept;

    constexpr mapping& operator=(const mapping&) noexcept = default;

    // \ref{mdspan.layout.right.obs}, observers
    constexpr const extents_type& extents() 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 is_always_unique() noexcept { return true; }
    static constexpr bool is_always_exhaustive() noexcept { return true; }
    static constexpr bool is_always_strided() noexcept { return true; }

    static constexpr bool is_unique() noexcept { return true; }
    static constexpr bool is_exhaustive() noexcept { return true; }
    static constexpr bool is_strided() 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 submdspan_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(extents_type::rank() > 0)
    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()}.
\end{itemdescr}

\rSec5[mdspan.layout.right.obs]{Observers}

\indexlibrarymember{required_span_size}{layout_right::mapping}%
\begin{itemdecl}
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>(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.

\begin{codeblock}
namespace std {
  template<class Extents>
  class layout_stride::mapping {
  public:
    using extents_type = Extents;
    using index_type = typename extents_type::index_type;
    using size_type = typename extents_type::size_type;
    using rank_type = typename extents_type::rank_type;
    using layout_type = 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& extents() const noexcept { return @\exposid{extents_}@; }
    constexpr array<index_type, @\exposid{rank_}@> strides() 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 is_always_unique() noexcept { return true; }
    static constexpr bool is_always_exhaustive() noexcept { return false; }
    static constexpr bool is_always_strided() noexcept { return true; }

    static constexpr bool is_unique() noexcept { return true; }
    constexpr bool is_exhaustive() const noexcept;
    static constexpr bool is_strided() noexcept { return true; }

    constexpr index_type stride(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 submdspan_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>(i) * stride(P)) + ... + 0);
\end{codeblock}
\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_} 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)}.

\begin{codeblock}
namespace std {
  template<size_t PaddingValue>
  template<class Extents>
  class layout_left_padded<PaddingValue>::mapping {
  public:
    static constexpr size_t padding_value = PaddingValue;

    using extents_type = Extents;
    using index_type = typename extents_type::index_type;
    using size_type = typename extents_type::size_type;
    using rank_type = typename extents_type::rank_type;
    using layout_type = 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(extents_type::rank() > 0)
        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& extents() const noexcept { return @\exposid{extents_}@; }
    constexpr array<index_type, 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 is_always_unique() noexcept { return true; }
    static constexpr bool is_always_exhaustive() noexcept;
    static constexpr bool is_always_strided() noexcept { return true; }

    static constexpr bool is_unique() noexcept { return true; }
    constexpr bool is_exhaustive() const noexcept;
    static constexpr bool is_strided() 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}, submdspan mapping specialization
    template<class... SliceSpecifiers>
      constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const     // \expos
        -> @\seebelow@;

    template<class... SliceSpecifiers>
      friend constexpr auto submdspan_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, {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
\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 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 pad);
\end{itemdecl}

\begin{itemdescr}
\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{extents_type::index-cast(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{extents_type::\exposid{in\-dex-cast}(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}
(static-padding-stride== dynamic_extent) ||
(OtherExtents::static_extent(0) == dynamic_extent) ||
(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(rank_ > 0)
    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}
\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 true.

\pnum
\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}
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}

\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}

\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_}(P_rank) - index_type(1))...)) + 1}.
\end{itemize}
\end{itemdescr}

\begin{itemdecl}
template<class... Indices>
constexpr size_t 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
\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>(idxs) * stride(P_rank)) + ... + 0)}.
\end{itemdescr}

\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}

\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}

\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}

\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)}.

\begin{codeblock}
namespace std {
  template<size_t PaddingValue>
  template<class Extents>
  class layout_right_padded<PaddingValue>::mapping {
  public:
    static constexpr size_t padding_value = PaddingValue;

    using extents_type = Extents;
    using index_type = typename extents_type::index_type;
    using size_type = typename extents_type::size_type;
    using rank_type = typename extents_type::rank_type;
    using layout_type = 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(rank_ > 0)
        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& extents() const noexcept { return extents_; }
    constexpr array<index_type, 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 is_always_unique() noexcept { return true; }
    static constexpr bool is_always_exhaustive() noexcept;
    static constexpr bool is_always_strided() noexcept { return true; }

    static constexpr bool is_unique() noexcept { return true; }
    constexpr bool is_exhaustive() const noexcept;
    static constexpr bool is_strided() 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}, submdspan mapping specialization
    template<class... SliceSpecifiers>
      constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const     // \expos
        -> @\seebelow@;

    template<class... SliceSpecifiers>
      friend constexpr auto submdspan_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
\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{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 pad);
\end{itemdecl}

\begin{itemdescr}
\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{extents_type::\exposid{index-cast}(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{extents_type::\linebreak \exposid{index-cast}(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(rank_ > 0)
    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}
\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}
@\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{layout_right_padded::mapping}{strides}%
\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{layout_right_padded::mapping}{required_span_size}%
\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_}(P_rank) - index_type(1))...)) + 1}.
\end{itemdescr}

\indexlibrarymember{layout_right_padded::mapping}{operator()}%
\begin{itemdecl}
template<class... Indices>
constexpr size_t 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>(idxs) * stride(P_rank)) + ... + 0)}.
\end{itemdescr}

\indexlibrarymember{layout_right_padded::mapping}{is_always_exhaustive}%
\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{layout_right_padded::mapping}{is_exhaustive}%
\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}

\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{layout_right_padded::mapping}{operator==}%
\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 subclause \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 default_accessor {
    using offset_policy = default_accessor;
    using element_type = ElementType;
    using reference = ElementType&;
    using data_handle_type = 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}

\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 mdspan {
  public:
    using extents_type = Extents;
    using layout_type = LayoutPolicy;
    using accessor_type = AccessorPolicy;
    using mapping_type = typename layout_type::template mapping<extents_type>;
    using element_type = ElementType;
    using value_type = remove_cv_t<element_type>;
    using index_type = typename extents_type::index_type;
    using size_type = typename extents_type::size_type;
    using rank_type = typename extents_type::rank_type;
    using data_handle_type = typename accessor_type::data_handle_type;
    using reference = typename accessor_type::reference;

    static constexpr rank_type rank() noexcept { return extents_type::rank(); }
    static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
    static constexpr size_t static_extent(rank_type r) noexcept
      { return extents_type::static_extent(r); }
    constexpr index_type extent(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;

    constexpr size_type size() const noexcept;
    [[nodiscard]] constexpr bool empty() const noexcept;

    friend constexpr void swap(mdspan& x, mdspan& y) noexcept;

    constexpr const extents_type& extents() const noexcept { return @\exposid{map_}@.extents(); }
    constexpr const data_handle_type& data_handle() const noexcept { return @\exposid{ptr_}@; }
    constexpr const mapping_type& mapping() const noexcept { return @\exposid{map_}@; }
    constexpr const accessor_type& accessor() const noexcept { return @\exposid{acc_}@; }

    static constexpr bool is_always_unique()
      { return mapping_type::is_always_unique(); }
    static constexpr bool is_always_exhaustive()
      { return mapping_type::is_always_exhaustive(); }
    static constexpr bool is_always_strided()
      { return mapping_type::is_always_strided(); }

    constexpr bool is_unique() const
      { return @\exposid{map_}@.is_unique(); }
    constexpr bool is_exhaustive() const
      { return @\exposid{map_}@.is_exhaustive(); }
    constexpr bool is_strided() const
      { return @\exposid{map_.}@is_strided(); }
    constexpr index_type stride(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(const 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<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
\begin{itemize}
\item
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}.
\item
$[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.
\end{itemize}

\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
\expects
\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{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}
[[nodiscard]] 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
For each function defined in subclause \ref{mdspan.sub} that
takes a parameter pack named \tcode{slices} as an argument:

\begin{itemize}
\item let \tcode{index_type} be
  \begin{itemize}
  \item
  \tcode{M::index_type}
  if the function is a member of a class \tcode{M},
  \item
  otherwise,
  \tcode{remove_reference_t<decltype(src)>::index_type}
  if the function has a parameter named \tcode{src},
  \item
  otherwise,
  the same type as the function's template argument \tcode{IndexType};
  \end{itemize}
\item let \tcode{rank} be the number of elements in \tcode{slices};
\item let $s_k$ be the $k^\text{th}$ element of \tcode{slices};
\item let $S_k$ be the type of $s_k$; and
\item let \tcode{\placeholder{map-rank}} be an \tcode{array<size_t, rank>} such that
for each $k$ in the range \range{0}{rank},
\tcode{\placeholder{map-rank}[$k$]} equals:
  \begin{itemize}
  \item
  \tcode{dynamic_extent}
  if $S_k$ models \tcode{\libconcept{convertible_to}<index_type>},
  \item
  otherwise,
  the number of types $S_j$ with $j < k$ that
  do not model \tcode{\libconcept{convertible_to}<index_type>}.
  \end{itemize}
\end{itemize}

\rSec4[mdspan.sub.strided.slice]{\tcode{strided_slice}}

\pnum
\tcode{strided_slice} represents a set of
\tcode{extent} regularly spaced integer indices.
The indices start at \tcode{offset}, and
increase by increments of \tcode{stride}.

\indexlibraryglobal{strided_slice}%
\begin{codeblock}
namespace std {
  template<class OffsetType, class ExtentType, class StrideType>
  struct strided_slice {
    using offset_type = OffsetType;
    using extent_type = ExtentType;
    using stride_type = StrideType;

    [[no_unique_address]] offset_type offset{};
    [[no_unique_address]] extent_type extent{};
    [[no_unique_address]] stride_type stride{};
  };
}
\end{codeblock}

\pnum
\tcode{strided_slice} has the data members and special members specified above.
It has no base classes or members other than those specified.

\pnum
\mandates
\tcode{OffsetType}, \tcode{ExtentType}, and \tcode{StrideType}
are signed or unsigned integer types, or
model \exposconcept{integral-constant-like}.
\begin{note}
\tcode{strided_slice\{.offset = 1, .extent = 10, .stride = 3\}}
indicates 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 mapping = LayoutMapping();
    size_t offset{};
  };
}
\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}

\indexlibraryglobal{\exposid{de-ice}}%
\indexlibraryglobal{\exposid{first_}}%
\begin{itemdecl}
template<class T>
  constexpr T @\exposid{de-ice}@(T val) { return val; }
template<@\exposconcept{integral-constant-like}@ T>
  constexpr auto @\exposid{de-ice}@(T) { return T::value; }

template<class IndexType, size_t k, class... SliceSpecifiers>
  constexpr IndexType @\exposid{first_}@(SliceSpecifiers... slices);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{IndexType} is a signed or unsigned integer type.

%FIXME: What is $k$ in this itemdescr? Did we mean the \tcode{k} passed to first_? If so, what do we do for de-ice?
\pnum
Let $\phi{}_k$ denote the following value:
\begin{itemize}
\item
$s_k$ if $S_k$ models \tcode{\libconcept{convertible_to}<IndexType>};
\item
otherwise,
\tcode{get<0>($s_k$)}
if $S_k$ models \tcode{\exposconcept{index-pair-like}<IndexType>};
\item
otherwise,
\tcode{\exposid{de-ice}($s_k$.offset)}
if $S_k$ is a specialization of \tcode{strided_slice};
\item
otherwise,
\tcode{0}.
\end{itemize}

\pnum
\expects
$\phi{}_k$ is representable as a value of type \tcode{IndexType}.

\pnum
\returns
\tcode{extents<IndexType>::\exposid{index-cast}($\phi{}_k$)}.
\end{itemdescr}

\indexlibraryglobal{\exposid{last_}}%
\begin{itemdecl}
template<size_t k, class Extents, class... SliceSpecifiers>
  constexpr auto @\exposid{last_}@(const Extents& src, SliceSpecifiers... slices);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{Extents} is a specialization of \tcode{extents}.

\pnum
Let \tcode{index_type} be \tcode{typename Extents::index_type}.

%FIXME: What is $k$ in this itemdescr? Don't we want \tcode{k} and not $k$?
\pnum
Let $\lambda{}_k$ denote the following value:
\begin{itemize}
\item
\tcode{\exposid{de-ice}($s_k$) + 1}
if $S_k$ models \tcode{\libconcept{convertible_to}<index_type>}; otherwise
\item
\tcode{get<1>($s_k$)}
if $S_k$ models \tcode{\exposconcept{index-pair-like}<index_type>}; otherwise
\item
\tcode{\exposid{de-ice}($s_k$.offset)} \tcode{+}
\tcode{\exposid{de-ice}($s_k$.extent)}
if $S_k$ is a specialization of \tcode{strided_slice}; otherwise
\item
%FIXME: Note that the paper uses \tcode{k} here.
\tcode{src.extent(k)}.
\end{itemize}

\pnum
\expects
$\lambda{}_k$ is representable as a value of type \tcode{index_type}.

\pnum
\returns
\tcode{Extents::\exposid{index-cast}($\lambda{}_k$)}.
\end{itemdescr}

\indexlibraryglobal{\exposid{src-indices}}%
\begin{itemdecl}
template<class IndexType, size_t N, class... SliceSpecifiers>
  constexpr array<IndexType, sizeof...(SliceSpecifiers)>
    @\exposid{src-indices}@(const array<IndexType, N>& indices, SliceSpecifiers... slices);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{IndexType} is a signed or unsigned integer type.

\pnum
\returns
An \tcode{array<IndexType, sizeof...(SliceSpecifiers)> src_idx} such that
for each $k$ in the range \range{0}{sizeof...(SliceSpecifiers)},
\tcode{src_idx[$k$]} equals

\begin{itemize}
\item
%FIXME: We're redefining what $k$ is here.
%FIXME: Also, calling first_ on each $k$ below gives us a set of indeces - how do we assign a set to the src_idx[$k$] above?
\tcode{\exposid{first_}<IndexType, $k$>(slices...)} for each $k$
where \tcode{\placeholder{map-rank}[$k$]} equals
\tcode{dynamic_extent},

\item
%FIXME: How do we fail the previous \item to get here? There's no "if" test to fail.
otherwise,
\tcode{\exposid{first_}<IndexType, $k$>(slices...)} \tcode{+}
\tcode{indices[\placeholder{map-rank}[$k$]]}.
\end{itemize}
\end{itemdescr}

\rSec4[mdspan.sub.extents]{\tcode{submdspan_extents} function}

\indexlibraryglobal{submdspan_extents}%
\begin{itemdecl}
template<class IndexType, class... Extents, class... SliceSpecifiers>
  constexpr auto submdspan_extents(const extents<IndexType, Extents...>& src,
                                   SliceSpecifiers... slices);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{sizeof...(slices)} equals \tcode{Extents::rank()}.

\pnum
\mandates
For each rank index $k$ of \tcode{src.extents()},
exactly one of the following is true:
\begin{itemize}
\item $S_k$ models \tcode{\libconcept{convertible_to}<IndexType>},
\item $S_k$ models \tcode{\exposconcept{index-pair-like}<IndexType>},
\item \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}, or
\item $S_k$ is a specialization of \tcode{strided_slice}.
\end{itemize}

\pnum
\expects
For each rank index $k$ of \tcode{src.extents()},
all of the following are \tcode{true}:
\begin{itemize}
\item
if $S_k$ is a specialization of \tcode{strided_slice}
  \begin{itemize}
  \item $\tcode{$s_k$.extent} = 0$, or
  \item $\tcode{$s_k$.stride} > 0$
  \end{itemize}
\item
$0 \le \tcode{\exposid{first_}<IndexType, $k$>(slices...)}$
$\le \tcode{\exposid{last_}<$k$>(src, slices...)}$
$\le \tcode{src.extent($k$)}$
\end{itemize}

\pnum
Let \tcode{SubExtents} be a specialization of \tcode{extents} such that:

\begin{itemize}
\item
%FIXME: I think we want the count here, "number" is ambiguous.
\tcode{SubExtents::rank()} equals the number of $k$ such that
$S_k$ does not model \tcode{\libconcept{convertible_to}<IndexType>}; and

\item
for each rank index $k$ of \tcode{Extents} such that
\tcode{\placeholder{map-rank}[$k$] != dynamic_extent} is \tcode{true},
\tcode{SubExt\-ents::static_extent(\placeholder{map-rank}[$k$])} equals:

  \begin{itemize}
  \item
  \tcode{Extents::static_extent($k$)}
  if \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true};
  otherwise

  \item
  \tcode{\exposid{de-ice}(tuple_element_t<1, $S_k$>()) -}
  \tcode{\exposid{de-ice}(tuple_element_t<0, $S_k$>())}
  if $S_k$ models \tcode{\exposconcept{index-pair-like}<IndexType>}, and
  both \tcode{tuple_element_t<0, $S_k$>} and
  \tcode{tuple_elem\-ent_t<1, $S_k$>}
  model \exposconcept{integral-constant-like}; otherwise

  \item
  \tcode{0},
  if $S_k$ is a specialization of \tcode{strided_slice}, whose
  \tcode{extent_type} models \exposconceptx{integral-cons\-tant-like}{integral-constant-like},
  for which \tcode{extent_type()} equals zero; otherwise

  \item
  \tcode{1 + (\exposid{de-ice}($S_k$::extent_type()) - 1) /}
  \tcode{\exposid{de-ice}($S_k$::stride_type())},
  if $S_k$ is a specialization of \tcode{strided_slice} whose
  \tcode{extent_type} and \tcode{stride_type}
  model \exposconceptx{integral-cons\-tant-like}{integral-constant-like};

  \item
  otherwise,
  \tcode{dynamic_extent}.
  \end{itemize}
\end{itemize}

\pnum
\returns
A value \tcode{ext} of type \tcode{SubExtents} such that
for each $k$
for which \tcode{\placeholder{map-rank}[$k$] != dynamic_extent} is \tcode{true},
\tcode{ext.extent(\placeholder{map-rank}[$k$])} equals:

\begin{itemize}
\item
\tcode{$s_k$.extent == 0 ? 0 : 1 + (\exposid{de-ice}($s_k$.extent) - 1) / \exposid{de-ice}($s_k$.stride)}
if $S_k$ is a specialization of \tcode{strided_slice},

\item
otherwise,
\tcode{\exposid{last_}<$k$>(src, slices...) - \exposid{first_}<IndexType, $k$>(slices...)}.
\end{itemize}
\end{itemdescr}

\rSec4[mdspan.sub.map]{Specializations of \tcode{submdspan_mapping}}

\rSec5[mdspan.sub.map.common]{Common}

\pnum
The following elements apply to all functions in \ref{mdspan.sub.map}.

\pnum
\constraints
\tcode{sizeof...(slices)} equals \tcode{extents_type::rank()}.

\pnum
\mandates
For each rank index $k$ of \tcode{extents()},
exactly one of the following is true:
\begin{itemize}
\item
$S_k$ models \tcode{\libconcept{convertible_to}<index_type>},
\item
$S_k$ models \tcode{\exposconcept{index-pair-like}<index_type>},
\item
\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}, or
\item
$S_k$ is a specialization of \tcode{strided_slice}.
\end{itemize}

\pnum
\expects
For each rank index $k$ of \tcode{extents()},
all of the following are \tcode{true}:
\begin{itemize}
\item
if $S_k$ is a specialization of \tcode{strided_slice},
\tcode{$s_k$.extent} is equal to zero or
\tcode{$s_k$.stride} is greater than zero; and
\item
$0            \leq \tcode{\exposid{first_}<index_type, $k$>(slices...)} \\
\hphantom{0 } \leq \tcode{\exposid{last_}<$k$>(extents(), slices...)} \\
\hphantom{0 } \leq \tcode{extents().extent($k$)}$
\end{itemize}

\pnum
Let \tcode{sub_ext} be
the result of \tcode{submdspan_extents(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 \tcode{\exposid{map-rank}[$k$]} is not \tcode{dynamic_extent},
\tcode{sub_strides[\exposid{map-rank}[$k$]]} equals:
\begin{itemize}
\item
\tcode{stride(k) * \exposid{de-ice}($s_k$.stride)}
if $S_k$ is a specialization of \tcode{strided_slice} and
\tcode{$s_k$.stride < $s_k$.\linebreak extent} is \tcode{true};
\item
otherwise, \tcode{stride($k$)}.
\end{itemize}

\pnum
Let \tcode{P} be a parameter pack
such that \tcode{is_same_v<make_index_sequence<rank()>, index_sequence<P...>>}
is \tcode{true}.

\pnum
Let \tcode{offset} be a value of type \tcode{size_t} equal to
\tcode{(*this)(\exposid{first_}<index_type, P>(slices...)...)}.

\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\}},
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{is_convertible_v<$S_k$, full_ext\-ent_t>} is \tcode{true}; and
  \item
  for $k$ equal to \tcode{SubExtents::rank() - 1},
  $S_k$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
  \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true};
  \end{itemize}
\begin{note}
If the above conditions are true,
all $S_k$ with $k$ larger than \tcode{SubExtents::rank() - 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 $S_p$ models
\tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<$S_p$, full_extent_t>} is \tcode{true},
the following conditions are met:
\begin{itemize}
\item
$S_0$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<$S_0$, full_extent_t>} is \tcode{true}; and
\item
for each $k$ in the range \range{$u$ + 1}{$u$ + SubExtents::rank() - 1},
\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and
\item
for $k$ equal to \tcode{$u$ + SubExtents::rank() - 1},
$S_k$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true};
\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\}},
if \tcode{Sub\-Extents::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{\exposid{rank_} - SubExtents::rank() + 1}{\exposid{rank_}},
  \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and
  \item
  for $k$ equal to \exposid{_rank} - \tcode{SubExtents::rank()},
  $S_k$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
  \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true};
  \end{itemize}
\begin{note}
If the above conditions are true,
all $S_k$ with $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 $S_p$ models
\tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<$S_p$, full_extent_t>} is \tcode{true},
the following conditions are met:
\begin{itemize}
\item
for $k$ equal to \tcode{\exposid{rank_} - 1},
$S_k$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<$S_k$, full_extent_t> }is \tcode{true}; and
\item
for each $k$ in the range
\range{\exposid{rank_} - SubExtents::rank() - $u$ + 1}{\exposid{rank_} - $u$ - 1},
\tcode{is_con\-vertible_v<$S_k$, full_extent_t>} is \tcode{true}; and
\item
for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$},
$S_k$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true};
\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
$S_0$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<$S_0$ , full_extent_t>} is \tcode{true};
\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 $S_p$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<$S_p$, full_extent_t>} is \tcode{true},
the following conditions are met:
\begin{itemize}
\item
$S_0$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<$S_0$, full_extent_t>} is \tcode{true}; and
\item
for each $k$ in the range \range{$u$ + 1}{$u$ + SubExtents::rank() - 1},
\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and
\item
for $k$ equal to \tcode{$u$ + SubExtents::rank() - 1},
$S_k$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<Sk, full_extent_t>} is \tcode{true};
\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>::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},
$S_k$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<$S_k$ , full_extent_t>} is \tcode{true};
\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 $S_p$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<$S_p$, full_extent_t>} is \tcode{true},
the following conditions are met:
\begin{itemize}
\item
for $k$ equal to \tcode{\exposid{rank_} - 1},
$S_k$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and
\item
for each $k$ in the range
\range{\exposid{rank_} - SubExtents::rank() - $u$ + 1}{\exposid{rank_} - $u$ - 1)},
\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and
\item
for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$},
$S_k$ models \tcode{\exposconcept{index-pair-like}<index_type>} or
\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true};
\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... slices) -> @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{index_type} be \tcode{typename Extents::index_type}.

\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
the expression \tcode{submdspan_mapping(src.mapping(), slices...)}
is well-formed when treated as an unevaluated operand.
\end{itemize}

\pnum
\mandates
\begin{itemize}
\item
\tcode{decltype(submdspan_mapping(src.mapping(), slices...))}
is a specialization of \tcode{submd-\linebreak{}span_mapping_result}.

\item
\tcode{is_same_v<remove_cvref_t<decltype(sub_map_offset.mapping.extents())>,}
\tcode{decltype(\linebreak{}submdspan_extents(src.mapping(), slices...))>}
is \tcode{true}.

\item
For each rank index $k$ of \tcode{src.extents()},
exactly one of the following is true:
  \begin{itemize}
  \item $S_k$ models \tcode{\libconcept{convertible_to}<index_type>},
  \item $S_k$ models \tcode{\exposconcept{index-pair-like}<index_type>},
  \item \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}, or
  \item $S_k$ is a specialization of \tcode{strided_slice}.
  \end{itemize}
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
For each rank index $k$ of \tcode{src.extents()},
all of the following are \tcode{true}:
  \begin{itemize}
  \item
  if $S_k$ is a specialization of \tcode{strided_slice}
    \begin{itemize}
    \item $\tcode{$s_k$.extent} = 0$, or
    \item $\tcode{$s_k$.stride} > 0$
    \end{itemize}
  \item
  $0 \le \tcode{\exposid{first_}<index_type, $k$>(slices...)}$
  $\le \tcode{\exposid{last_}<$k$>(src.extents(), slices...)}$
  $\le \tcode{\linebreak{}src.extent($k$)}$
  \end{itemize}

\item
\tcode{sub_map_offset.mapping.extents() == submdspan_extents(src.mapping(), slices...)}\linebreak
is \tcode{true}; and

\item
for each integer pack \tcode{I} which is a multidimensional index
in \tcode{sub_map_offset.mapping.extents()},
\begin{codeblock}
sub_map_offset.mapping(I...) + sub_map_offset.offset ==
  src.mapping()(@\exposid{src-indices}@(array{I...}, slices...))
\end{codeblock}
is \tcode{true}.
\end{itemize}

\begin{note}
These conditions ensure that the mapping returned by \tcode{submdspan_mapping}
matches the algorithmically expected index-mapping given the slice specifiers.
\end{note}

\pnum
\effects
Equivalent to:
\begin{codeblock}
auto sub_map_offset = submdspan_mapping(src.mapping(), slices...);
return mdspan(src.accessor().offset(src.data(), sub_map_offset.offset),
              sub_map_offset.mapping,
              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}
