%!TEX root = std.tex
\rSec0[strings]{Strings library}

\rSec1[strings.general]{General}

\pnum
This Clause describes components for manipulating sequences of
any non-array trivially copyable standard-layout\iref{term.standard.layout.type} type \tcode{T}
where \tcode{is_trivially_default_constructible_v<T>} is \tcode{true}.
Such types are called \defnx{char-like types}{char-like type},
and objects of
char-like types are called \defnx{char-like objects}{char-like object} or
simply \term{characters}.

\pnum
The following subclauses describe a
character traits class, string classes, and
null-terminated sequence utilities,
as summarized in \tref{strings.summary}.

\begin{libsumtab}[x{2.1in}]{Strings library summary}{strings.summary}
\ref{char.traits}     & Character traits                    & \tcode{<string>}  \\
\ref{string.view}     & String view classes                 & \tcode{<string_view>} \\ \rowsep
\ref{string.classes}  & String classes                      & \tcode{<string>}  \\ \rowsep
\ref{c.strings}       & Null-terminated sequence utilities  & \tcode{<cstring>} \\
\end{libsumtab}

\rSec1[char.traits]{Character traits}

\rSec2[char.traits.general]{General}

\pnum
Subclause \ref{char.traits} defines requirements on classes representing
\term{character traits},
and defines a class template
\tcode{char_traits<charT>},
along with five specializations,
\tcode{char_traits<char>},
\tcode{char_traits<char8_t>},
\tcode{char_traits<char16_t>},
\tcode{char_traits<char32_t>},
and
\tcode{char_traits<wchar_t>},
that meet those requirements.

\pnum
Most classes specified in \ref{string.classes}, \ref{string.view},
and \ref{input.output} need a set of related types and functions to complete
the definition of their semantics.  These types and functions are provided as a
set of member \grammarterm{typedef-name}{s} and functions in the template
parameter \tcode{traits} used by each such template.
Subclause \ref{char.traits} defines the semantics of these members.

\pnum
To specialize those templates to generate a string, string view, or
iostream class to handle a particular character container type\iref{defns.character.container}
\tcode{C},
that and its related character traits class
\tcode{X}
are passed as a pair of parameters to the string, string view, or iostream template as
parameters
\tcode{charT}
and
\tcode{traits}.
If
\tcode{X::char_type}
is not the same type as
\tcode{C}, the program is ill-formed.

\rSec2[char.traits.require]{Character traits requirements}

\pnum
In \tref{char.traits.req},
\tcode{X}
denotes a traits class defining types and functions for the
character container type
\tcode{C};
\tcode{c}
and
\tcode{d}
denote values of type
\tcode{C};
\tcode{p}
and
\tcode{q}
denote values of type
\tcode{const C*};
\tcode{s}
denotes a value of type
\tcode{C*};
\tcode{n},
\tcode{i}
and
\tcode{j}
denote values of type
\tcode{size_t};
\tcode{e}
and
\tcode{f}
denote values of type
\tcode{X::int_type};
\tcode{pos}
denotes a value of type
\tcode{X::pos_type};
and
\tcode{r}
denotes an lvalue of type
\tcode{C}.
No expression which is part of the character traits requirements
specified in \ref{char.traits.require}
shall exit via an exception.

\begin{libreqtab4d}
{Character traits requirements}
{char.traits.req}
\\ \topline
\lhdr{Expression}       &   \chdr{Return type}  &   \chdr{Assertion/note}   &   \rhdr{Complexity}\\
                        &                       &   \chdr{pre-/post-condition}   &               \\ \capsep
\endfirsthead
\continuedcaption\\
\topline
\lhdr{Expression}       &   \chdr{Return type}  &   \chdr{Assertion/note}   &   \rhdr{Complexity}\\
                        &                       &   \chdr{pre-/post-condition}   &               \\ \capsep
\endhead
\tcode{X::char_type}    &   \tcode{C}       &
   &    \\ \rowsep
\tcode{X::int_type} &                       &
(described in~\ref{char.traits.typedefs})   &    \\ \rowsep
\tcode{X::off_type} &                       &
(described in~\ref{iostreams.limits.pos} and \ref{iostream.forward})   &    \\ \rowsep
\tcode{X::pos_type} &                       &
(described in~\ref{iostreams.limits.pos} and \ref{iostream.forward})   &    \\ \rowsep
\tcode{X::state_type}   &                       &
(described in~\ref{char.traits.typedefs})   &    \\ \rowsep
\tcode{X::eq(c,d)}      &   \tcode{bool}        &
 \returns
whether \tcode{c} is to be treated as equal to \tcode{d}.   &   constant    \\ \rowsep
\tcode{X::lt(c,d)}      &   \tcode{bool}        &
 \returns
whether \tcode{c} is to be treated as less than \tcode{d}.  &   constant    \\ \rowsep
\tcode{X::compare(p,q,n)}   &   \tcode{int}     &
 \returns
\tcode{0} if for each \tcode{i} in \range{0}{n}, \tcode{X::eq(p[i],q[i])}
is \tcode{true}; else, a negative value if, for some \tcode{j} in \range{0}{n},
\tcode{X::lt(p[j],q[j])} is \tcode{true} and for each \tcode{i} in \range{0}{j}
\tcode{X::eq(p[i],q[i])} is \tcode{true}; else a positive value.            &   linear      \\ \rowsep
\tcode{X::length(p)}    &   \tcode{size_t}     &
 \returns
the smallest \tcode{i} such that \tcode{X::eq(p[i],charT())} is \tcode{true}.  &   linear  \\ \rowsep
\tcode{X::find(p,n,c)}  &   \tcode{const X::char_type*} &
 \returns
the smallest \tcode{q} in \range{p}{p+n} such that
\tcode{X::eq(*q,c)} is \tcode{true}, \tcode{nullptr} otherwise.                &   linear      \\ \rowsep
\tcode{X::move(s,p,n)}  &   \tcode{X::char_type*}   &
for each \tcode{i} in \range{0}{n}, performs \tcode{X::assign(s[i],p[i])}.
Copies correctly even where the ranges \range{p}{p+n} and \range{s}{s+n} overlap.\br \returns \tcode{s}.    &   linear  \\ \rowsep
\tcode{X::copy(s,p,n)}  &   \tcode{X::char_type*}   &
 \expects
The ranges \range{p}{p+n} and \range{s}{s+n} do not overlap.\par
 \returns
\tcode{s}.\br
for each \tcode{i} in
\range{0}{n}, performs \tcode{X::assign(s[i],p[i])}.               &   linear      \\ \rowsep
\tcode{X::assign(r,d)}  &   (not used)          &
assigns \tcode{r=d}.                            &   constant        \\ \rowsep
\tcode{X::assign\-(s,n,c)}  &   \tcode{X::char_type*}   &
for each \tcode{i} in \range{0}{n}, performs
\tcode{X::assign(s[i],c)}.\br
 \returns
\tcode{s}.                       &   linear      \\ \rowsep
\tcode{X::not_eof(e)}   &   \tcode{int_type}        &
 \returns
\tcode{e} if \tcode{X::eq_int_type(e,X::eof())} is \tcode{false},
otherwise a value \tcode{f} such that
\tcode{X::eq_int_type(f,X::eof())} is \tcode{false}.                       &   constant    \\ \rowsep
\tcode{X::to_char_type\-(e)}    &   \tcode{X::char_type}    &
 \returns
if for some \tcode{c}, \tcode{X::eq_int_type(e,X::to_int_type(c))}
is \tcode{true}, \tcode{c}; else some unspecified value.                    &   constant    \\ \rowsep
\tcode{X::to_int_type\-(c)} &   \tcode{X::int_type} &
 \returns
some value \tcode{e}, constrained by the definitions of
\tcode{to_char_type} and \tcode{eq_int_type}.                  &   constant    \\ \rowsep
\tcode{X::eq_int_type\-(e,f)}   &   \tcode{bool}            &
 \returns
for all \tcode{c} and \tcode{d}, \tcode{X::eq(c,d)} is equal to
\tcode{X::eq_int_type(X::to_int_type(c), X::to_int_type(d))}; otherwise, yields \tcode{true}
if \tcode{e} and \tcode{f} are both copies of \tcode{X::eof()}; otherwise, yields \tcode{false} if
one of \tcode{e} and \tcode{f} is a copy of \tcode{X::eof()} and the other is not; otherwise
the value is unspecified.                                           &   constant    \\ \rowsep
\tcode{X::eof()}                &   \tcode{X::int_type} &
 \returns
a value \tcode{e} such that \tcode{X::eq_int_type(e,X::to_int_type(c))}
is \tcode{false} for all values \tcode{c}.                                  &   constant    \\
\end{libreqtab4d}

\pnum
The class template
\indexlibraryglobal{char_traits}%
\begin{codeblock}
template<class charT> struct char_traits;
\end{codeblock}
is provided in the header \libheaderref{string}
as a basis for explicit specializations.

\rSec2[char.traits.typedefs]{Traits typedefs}

\indexlibrarymember{char_type}{char_traits}%
\indexlibrarymember{int_type}{char_traits}%
\begin{itemdecl}
using int_type = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{int_type}
shall be able to represent all of the
valid characters converted from the corresponding
\tcode{char_type}
values, as well as an end-of-file value,
\tcode{eof()}.
\begin{footnote}
If
\tcode{eof()}
can be held in
\tcode{char_type}
then some iostreams operations can give surprising results.
\end{footnote}
\end{itemdescr}

\indexlibrarymember{state_type}{char_traits}%
\begin{itemdecl}
using state_type = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{state_type} meets the
\oldconcept{Destructible} (\tref{cpp17.destructible}),
\oldconcept{CopyAssignable} (\tref{cpp17.copyassignable}),
\oldconcept{CopyConstructible} (\tref{cpp17.copyconstructible}), and
\oldconcept{DefaultConstructible} (\tref{cpp17.defaultconstructible}) requirements.
\end{itemdescr}

\rSec2[char.traits.specializations]{\tcode{char_traits} specializations}

\rSec3[char.traits.specializations.general]{General}

\indexlibraryglobal{char_traits}%
\begin{codeblock}
namespace std {
  template<> struct char_traits<char>;
  template<> struct char_traits<char8_t>;
  template<> struct char_traits<char16_t>;
  template<> struct char_traits<char32_t>;
  template<> struct char_traits<wchar_t>;
}
\end{codeblock}

\pnum
The header \libheader{string}
defines five specializations of the class template
\tcode{char_traits}:
\tcode{char_traits<\brk{}char>},
\tcode{char_traits<char8_t>},
\tcode{char_traits<char16_t>},
\tcode{char_traits<char32_t>},
and
\tcode{char_traits<wchar_t>}.


\rSec3[char.traits.specializations.char]{\tcode{struct char_traits<char>}}

\indexlibraryglobal{char_traits}%
\begin{codeblock}
namespace std {
  template<> struct char_traits<char> {
    using char_type  = char;
    using int_type   = int;
    using off_type   = streamoff;
    using pos_type   = streampos;
    using state_type = mbstate_t;
    using comparison_category = strong_ordering;

    static constexpr void assign(char_type& c1, const char_type& c2) noexcept;
    static constexpr bool eq(char_type c1, char_type c2) noexcept;
    static constexpr bool lt(char_type c1, char_type c2) noexcept;

    static constexpr int compare(const char_type* s1, const char_type* s2, size_t n);
    static constexpr size_t length(const char_type* s);
    static constexpr const char_type* find(const char_type* s, size_t n,
                                           const char_type& a);
    static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n);
    static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n);
    static constexpr char_type* assign(char_type* s, size_t n, char_type a);

    static constexpr int_type not_eof(int_type c) noexcept;
    static constexpr char_type to_char_type(int_type c) noexcept;
    static constexpr int_type to_int_type(char_type c) noexcept;
    static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept;
    static constexpr int_type eof() noexcept;
  };
}
\end{codeblock}

\pnum
The type \tcode{mbstate_t} is defined in \libheaderref{cwchar}
and can represent any of the conversion states that can occur in an
\impldef{supported multibyte character encoding rules} set of supported multibyte
character encoding rules.

\pnum
The two-argument member \tcode{assign} is defined identically to the
built-in operator \tcode{=}. The two-argument members \tcode{eq}
and \tcode{lt} are defined identically to the built-in operators
\tcode{==} and \tcode{<} for type \tcode{unsigned char}.

\pnum
The member
\tcode{eof()}
returns
\tcode{EOF}.

\rSec3[char.traits.specializations.char8.t]{\tcode{struct char_traits<char8_t>}}

\indexlibraryglobal{char_traits}%
\begin{codeblock}
namespace std {
  template<> struct char_traits<char8_t> {
    using char_type  = char8_t;
    using int_type   = unsigned int;
    using off_type   = streamoff;
    using pos_type   = u8streampos;
    using state_type = mbstate_t;
    using comparison_category = strong_ordering;

    static constexpr void assign(char_type& c1, const char_type& c2) noexcept;
    static constexpr bool eq(char_type c1, char_type c2) noexcept;
    static constexpr bool lt(char_type c1, char_type c2) noexcept;

    static constexpr int compare(const char_type* s1, const char_type* s2, size_t n);
    static constexpr size_t length(const char_type* s);
    static constexpr const char_type* find(const char_type* s, size_t n,
                                           const char_type& a);
    static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n);
    static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n);
    static constexpr char_type* assign(char_type* s, size_t n, char_type a);
    static constexpr int_type not_eof(int_type c) noexcept;
    static constexpr char_type to_char_type(int_type c) noexcept;
    static constexpr int_type to_int_type(char_type c) noexcept;
    static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept;
    static constexpr int_type eof() noexcept;
  };
}
\end{codeblock}

\pnum
The two-argument members \tcode{assign}, \tcode{eq}, and \tcode{lt}
are defined identically to
the built-in operators \tcode{=}, \tcode{==}, and \tcode{<} respectively.

\pnum
\indextext{UTF-8}%
The member \tcode{eof()} returns an
\impldef{return value of \tcode{char_traits<char8_t>::eof}} constant
that cannot appear as a valid UTF-8 code unit.

\rSec3[char.traits.specializations.char16.t]{\tcode{struct char_traits<char16_t>}}

\indexlibraryglobal{char_traits}%
\begin{codeblock}
namespace std {
  template<> struct char_traits<char16_t> {
    using char_type  = char16_t;
    using int_type   = uint_least16_t;
    using off_type   = streamoff;
    using pos_type   = u16streampos;
    using state_type = mbstate_t;
    using comparison_category = strong_ordering;

    static constexpr void assign(char_type& c1, const char_type& c2) noexcept;
    static constexpr bool eq(char_type c1, char_type c2) noexcept;
    static constexpr bool lt(char_type c1, char_type c2) noexcept;

    static constexpr int compare(const char_type* s1, const char_type* s2, size_t n);
    static constexpr size_t length(const char_type* s);
    static constexpr const char_type* find(const char_type* s, size_t n,
                                           const char_type& a);
    static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n);
    static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n);
    static constexpr char_type* assign(char_type* s, size_t n, char_type a);

    static constexpr int_type not_eof(int_type c) noexcept;
    static constexpr char_type to_char_type(int_type c) noexcept;
    static constexpr int_type to_int_type(char_type c) noexcept;
    static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept;
    static constexpr int_type eof() noexcept;
  };
}
\end{codeblock}


\pnum
The two-argument members \tcode{assign},
\tcode{eq}, and \tcode{lt} are defined identically to
the built-in operators \tcode{=}, \tcode{==}, and
\tcode{<}, respectively.

\pnum
The member \tcode{eof()} returns an
\impldef{return value of \tcode{char_traits<char16_t>::eof}} constant that cannot appear
as a valid UTF-16 code unit.

\rSec3[char.traits.specializations.char32.t]{\tcode{struct char_traits<char32_t>}}

\indexlibraryglobal{char_traits}%
\begin{codeblock}
namespace std {
  template<> struct char_traits<char32_t> {
    using char_type  = char32_t;
    using int_type   = uint_least32_t;
    using off_type   = streamoff;
    using pos_type   = u32streampos;
    using state_type = mbstate_t;
    using comparison_category = strong_ordering;

    static constexpr void assign(char_type& c1, const char_type& c2) noexcept;
    static constexpr bool eq(char_type c1, char_type c2) noexcept;
    static constexpr bool lt(char_type c1, char_type c2) noexcept;

    static constexpr int compare(const char_type* s1, const char_type* s2, size_t n);
    static constexpr size_t length(const char_type* s);
    static constexpr const char_type* find(const char_type* s, size_t n,
                                           const char_type& a);
    static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n);
    static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n);
    static constexpr char_type* assign(char_type* s, size_t n, char_type a);

    static constexpr int_type not_eof(int_type c) noexcept;
    static constexpr char_type to_char_type(int_type c) noexcept;
    static constexpr int_type to_int_type(char_type c) noexcept;
    static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept;
    static constexpr int_type eof() noexcept;
  };
}
\end{codeblock}


\pnum
The two-argument members \tcode{assign},
\tcode{eq}, and \tcode{lt} are defined identically to
the built-in operators \tcode{=}, \tcode{==}, and
\tcode{<}, respectively.

\pnum
The member \tcode{eof()} returns an
\impldef{return value of \tcode{char_traits<char32_t>::eof}} constant that cannot appear as a Unicode
code point.

\rSec3[char.traits.specializations.wchar.t]{\tcode{struct char_traits<wchar_t>}}

\indexlibraryglobal{char_traits}%
\begin{codeblock}
namespace std {
  template<> struct char_traits<wchar_t> {
    using char_type  = wchar_t;
    using int_type   = wint_t;
    using off_type   = streamoff;
    using pos_type   = wstreampos;
    using state_type = mbstate_t;
    using comparison_category = strong_ordering;

    static constexpr void assign(char_type& c1, const char_type& c2) noexcept;
    static constexpr bool eq(char_type c1, char_type c2) noexcept;
    static constexpr bool lt(char_type c1, char_type c2) noexcept;

    static constexpr int compare(const char_type* s1, const char_type* s2, size_t n);
    static constexpr size_t length(const char_type* s);
    static constexpr const char_type* find(const char_type* s, size_t n,
                                           const char_type& a);
    static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n);
    static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n);
    static constexpr char_type* assign(char_type* s, size_t n, char_type a);

    static constexpr int_type not_eof(int_type c) noexcept;
    static constexpr char_type to_char_type(int_type c) noexcept;
    static constexpr int_type to_int_type(char_type c) noexcept;
    static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept;
    static constexpr int_type eof() noexcept;
  };
}
\end{codeblock}


\pnum
The two-argument members
\tcode{assign},
\tcode{eq},
and
\tcode{lt}
are defined identically
to the built-in operators
\tcode{=},
\tcode{==},
and
\tcode{<},
respectively.

\pnum
The member
\tcode{eof()}
returns
\tcode{WEOF}.

\rSec1[string.view]{String view classes}

\rSec2[string.view.general]{General}

\pnum
The class template \tcode{basic_string_view} describes an object
that can refer to a constant contiguous sequence of char-like\iref{strings.general} objects
with the first element of the sequence at position zero.
In the rest of \ref{string.view}, the type of the char-like objects
held in a \tcode{basic_string_view} object is designated by \tcode{charT}.

\pnum
\begin{note}
The library provides implicit conversions from \tcode{const charT*}
and \tcode{std::basic_string<charT, ...>} to \tcode{std::basic_string_view<charT, ...>}
so that user code can accept just \tcode{std::basic_string_view<charT>}
as a non-templated parameter wherever a sequence of characters is expected.
User-defined types can define their own implicit conversions
to \tcode{std::basic_string_view<charT>} in order to interoperate with these functions.
\end{note}

\rSec2[string.view.synop]{Header \tcode{<string_view>} synopsis}

\indexheader{string_view}%
\begin{codeblock}
// mostly freestanding
#include <compare>              // see \ref{compare.syn}

namespace std {
  // \ref{string.view.template}, class template \tcode{basic_string_view}
  template<class charT, class traits = char_traits<charT>>
  class basic_string_view;                                              // partially freestanding

  template<class charT, class traits>
    constexpr bool ranges::@\libspec{enable_view}{basic_string_view}@<basic_string_view<charT, traits>> = true;
  template<class charT, class traits>
    constexpr bool ranges::@\libspec{enable_borrowed_range}{basic_string_view}@<basic_string_view<charT, traits>> = true;

  // \ref{string.view.comparison}, non-member comparison functions
  template<class charT, class traits>
    constexpr bool operator==(basic_string_view<charT, traits> x,
                              type_identity_t<basic_string_view<charT, traits>> y) noexcept;
  template<class charT, class traits>
    constexpr @\seebelow@ operator<=>(basic_string_view<charT, traits> x,
              @\itcorr@                      type_identity_t<basic_string_view<charT,
              @\itcorr@                                      traits>> y) noexcept;

  // \ref{string.view.io}, inserters and extractors
  template<class charT, class traits>
    basic_ostream<charT, traits>&
      operator<<(basic_ostream<charT, traits>& os,
                 basic_string_view<charT, traits> str);                 // hosted

  // \tcode{basic_string_view} \grammarterm{typedef-name}s
  using @\libglobal{string_view}@    = basic_string_view<char>;
  using @\libglobal{u8string_view}@  = basic_string_view<char8_t>;
  using @\libglobal{u16string_view}@ = basic_string_view<char16_t>;
  using @\libglobal{u32string_view}@ = basic_string_view<char32_t>;
  using @\libglobal{wstring_view}@   = basic_string_view<wchar_t>;

  // \ref{string.view.hash}, hash support
  template<class T> struct hash;
  template<> struct hash<string_view>;
  template<> struct hash<u8string_view>;
  template<> struct hash<u16string_view>;
  template<> struct hash<u32string_view>;
  template<> struct hash<wstring_view>;

  inline namespace literals {
    inline namespace string_view_literals {
      // \ref{string.view.literals}, suffix for \tcode{basic_string_view} literals
      constexpr string_view    operator""sv(const char* str, size_t len) noexcept;
      constexpr u8string_view  operator""sv(const char8_t* str, size_t len) noexcept;
      constexpr u16string_view operator""sv(const char16_t* str, size_t len) noexcept;
      constexpr u32string_view operator""sv(const char32_t* str, size_t len) noexcept;
      constexpr wstring_view   operator""sv(const wchar_t* str, size_t len) noexcept;
    }
  }
}
\end{codeblock}

\pnum
The function templates defined in \ref{utility.swap} and \ref{iterator.range}
are available when \tcode{<string_view>} is included.

\rSec2[string.view.template]{Class template \tcode{basic_string_view}}

\rSec3[string.view.template.general]{General}

\indexlibraryglobal{basic_string_view}%
\indexlibrarymember{traits_type}{basic_string_view}%
\indexlibrarymember{value_type}{basic_string_view}%
\indexlibrarymember{pointer}{basic_string_view}%
\indexlibrarymember{const_pointer}{basic_string_view}%
\indexlibrarymember{reference}{basic_string_view}%
\indexlibrarymember{const_reference}{basic_string_view}%
\indexlibrarymember{const_iterator}{basic_string_view}%
\indexlibrarymember{iterator}{basic_string_view}%
\indexlibrarymember{const_reverse_iterator}{basic_string_view}%
\indexlibrarymember{reverse_iterator}{basic_string_view}%
\indexlibrarymember{size_type}{basic_string_view}%
\indexlibrarymember{difference_type}{basic_string_view}%
\begin{codeblock}
namespace std {
  template<class charT, class traits = char_traits<charT>>
  class basic_string_view {
  public:
    // types
    using traits_type            = traits;
    using value_type             = charT;
    using pointer                = value_type*;
    using const_pointer          = const value_type*;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using const_iterator         = @\impdefx{type of \tcode{basic_string_view::const_iterator}}@; // see \ref{string.view.iterators}
    using iterator               = const_iterator;@
\begin{footnote}
Because \tcode{basic_string_view} refers to a constant sequence, \tcode{iterator} and \tcode{const_iterator} are the same type.
\end{footnote}@
    using const_reverse_iterator = reverse_iterator<const_iterator>;
    using reverse_iterator       = const_reverse_iterator;
    using size_type              = size_t;
    using difference_type        = ptrdiff_t;
    static constexpr size_type npos = size_type(-1);

    // \ref{string.view.cons}, construction and assignment
    constexpr basic_string_view() noexcept;
    constexpr basic_string_view(const basic_string_view&) noexcept = default;
    constexpr basic_string_view& operator=(const basic_string_view&) noexcept = default;
    constexpr basic_string_view(const charT* str);
    basic_string_view(nullptr_t) = delete;
    constexpr basic_string_view(const charT* str, size_type len);
    template<class It, class End>
      constexpr basic_string_view(It begin, End end);
    template<class R>
      constexpr explicit basic_string_view(R&& r);

    // \ref{string.view.iterators}, iterator support
    constexpr const_iterator begin() const noexcept;
    constexpr const_iterator end() const noexcept;
    constexpr const_iterator cbegin() const noexcept;
    constexpr const_iterator cend() const noexcept;
    constexpr const_reverse_iterator rbegin() const noexcept;
    constexpr const_reverse_iterator rend() const noexcept;
    constexpr const_reverse_iterator crbegin() const noexcept;
    constexpr const_reverse_iterator crend() const noexcept;

    // \ref{string.view.capacity}, capacity
    constexpr size_type size() const noexcept;
    constexpr size_type length() const noexcept;
    constexpr size_type max_size() const noexcept;
    constexpr bool empty() const noexcept;

    // \ref{string.view.access}, element access
    constexpr const_reference operator[](size_type pos) const;
    constexpr const_reference at(size_type pos) const;                  // freestanding-deleted
    constexpr const_reference front() const;
    constexpr const_reference back() const;
    constexpr const charT* data() const noexcept;

    // \ref{string.view.modifiers}, modifiers
    constexpr void remove_prefix(size_type n);
    constexpr void remove_suffix(size_type n);
    constexpr void swap(basic_string_view& s) noexcept;

    // \ref{string.view.ops}, string operations
    constexpr size_type copy(charT* s, size_type n,
                             size_type pos = 0) const;                  // freestanding-deleted

    constexpr basic_string_view substr(size_type pos = 0,
                                       size_type n = npos) const;       // freestanding-deleted
    constexpr basic_string_view subview(size_type pos = 0,
                                        size_type n = npos) const;      // freestanding-deleted

    constexpr int compare(basic_string_view s) const noexcept;
    constexpr int compare(size_type pos1, size_type n1,
                          basic_string_view s) const;                   // freestanding-deleted
    constexpr int compare(size_type pos1, size_type n1, basic_string_view s,
                          size_type pos2, size_type n2) const;          // freestanding-deleted
    constexpr int compare(const charT* s) const;
    constexpr int compare(size_type pos1, size_type n1,
                          const charT* s) const;                        // freestanding-deleted
    constexpr int compare(size_type pos1, size_type n1, const charT* s,
                          size_type n2) const;                          // freestanding-deleted

    constexpr bool starts_with(basic_string_view x) const noexcept;
    constexpr bool starts_with(charT x) const noexcept;
    constexpr bool starts_with(const charT* x) const;
    constexpr bool ends_with(basic_string_view x) const noexcept;
    constexpr bool ends_with(charT x) const noexcept;
    constexpr bool ends_with(const charT* x) const;

    constexpr bool contains(basic_string_view x) const noexcept;
    constexpr bool contains(charT x) const noexcept;
    constexpr bool contains(const charT* x) const;

    // \ref{string.view.find}, searching
    constexpr size_type find(basic_string_view s, size_type pos = 0) const noexcept;
    constexpr size_type find(charT c, size_type pos = 0) const noexcept;
    constexpr size_type find(const charT* s, size_type pos, size_type n) const;
    constexpr size_type find(const charT* s, size_type pos = 0) const;
    constexpr size_type rfind(basic_string_view s, size_type pos = npos) const noexcept;
    constexpr size_type rfind(charT c, size_type pos = npos) const noexcept;
    constexpr size_type rfind(const charT* s, size_type pos, size_type n) const;
    constexpr size_type rfind(const charT* s, size_type pos = npos) const;

    constexpr size_type find_first_of(basic_string_view s, size_type pos = 0) const noexcept;
    constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept;
    constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const;
    constexpr size_type find_first_of(const charT* s, size_type pos = 0) const;
    constexpr size_type find_last_of(basic_string_view s, size_type pos = npos) const noexcept;
    constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept;
    constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const;
    constexpr size_type find_last_of(const charT* s, size_type pos = npos) const;
    constexpr size_type find_first_not_of(basic_string_view s, size_type pos = 0) const noexcept;
    constexpr size_type find_first_not_of(charT c, size_type pos = 0) const noexcept;
    constexpr size_type find_first_not_of(const charT* s, size_type pos,
                                          size_type n) const;
    constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const;
    constexpr size_type find_last_not_of(basic_string_view s,
                                         size_type pos = npos) const noexcept;
    constexpr size_type find_last_not_of(charT c, size_type pos = npos) const noexcept;
    constexpr size_type find_last_not_of(const charT* s, size_type pos,
                                         size_type n) const;
    constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const;

  private:
    const charT* @\exposid{data_}@;         // \expos
    size_type @\exposid{size_}@;            // \expos
  };

  // \ref{string.view.deduct}, deduction guides
  template<class It, class End>
    basic_string_view(It, End) -> basic_string_view<iter_value_t<It>>;
  template<class R>
    basic_string_view(R&&) -> basic_string_view<ranges::range_value_t<R>>;
}
\end{codeblock}

\pnum
In every specialization \tcode{basic_string_view<charT, traits>}, the type \tcode{traits} shall meet the character traits requirements\iref{char.traits}.
\begin{note}
The program is ill-formed if \tcode{traits::char_type} is not the same type as \tcode{charT}.
\end{note}

\pnum
For a \tcode{basic_string_view str},
any operation that invalidates a pointer
in the range
\begin{codeblock}
@\range{str.data()}{str.data() + str.size()}@
\end{codeblock}
invalidates pointers, iterators, and references
to elements of \tcode{str}.

\pnum
The complexity of \tcode{basic_string_view} member functions is \bigoh{1}
unless otherwise specified.

\pnum
\tcode{basic_string_view<charT, traits>} is
a trivially copyable type\iref{term.trivially.copyable.type}.

\rSec3[string.view.cons]{Construction and assignment}

\indexlibraryctor{basic_string_view}%
\begin{itemdecl}
constexpr basic_string_view() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{\exposid{size_} == 0} and \tcode{\exposid{data_} == nullptr}.
\end{itemdescr}

\indexlibraryctor{basic_string_view}%
\begin{itemdecl}
constexpr basic_string_view(const charT* str);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\range{str}{str + traits::length(str)} is a valid range.

\pnum
\effects
Constructs a \tcode{basic_string_view}, initializing \exposid{data_} with \tcode{str}
and initializing \exposid{size_} with \tcode{traits::length(str)}.

\pnum
\complexity
\bigoh{\tcode{traits::length(str)}}.
\end{itemdescr}

\indexlibraryctor{basic_string_view}%
\begin{itemdecl}
constexpr basic_string_view(const charT* str, size_type len);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\range{str}{str + len} is a valid range.

\pnum
\effects
Constructs a \tcode{basic_string_view}, initializing \exposid{data_} with \tcode{str}
and initializing \exposid{size_} with \tcode{len}.
\end{itemdescr}

\indexlibraryctor{basic_string_view}%
\begin{itemdecl}
template<class It, class End>
  constexpr basic_string_view(It begin, End end);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item \tcode{It} satisfies \libconcept{contiguous_iterator}.
\item \tcode{End} satisfies \tcode{\libconcept{sized_sentinel_for}<It>}.
\item \tcode{is_same_v<iter_value_t<It>, charT>} is \tcode{true}.
\item \tcode{is_convertible_v<End, size_type>} is \tcode{false}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item \range{begin}{end} 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(begin)} and
initializes \exposid{size_} with \tcode{end - begin}.

\pnum
\throws
When and what \tcode{end - begin} throws.
\end{itemdescr}

\indexlibraryctor{basic_string_view}%
\begin{itemdecl}
template<class R>
  constexpr explicit basic_string_view(R&& r);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{d} be an lvalue of type \tcode{remove_cvref_t<R>}.

\pnum
\constraints
\begin{itemize}
\item
\tcode{remove_cvref_t<R>} is not the same type as \tcode{basic_string_view},
\item
\tcode{R} models
\tcode{ranges::\libconcept{contiguous_range}} and \tcode{ranges::\libconcept{sized_range}},
\item
\tcode{is_same_v<ranges::range_value_t<R>, charT>} is \tcode{true},
\item
\tcode{is_convertible_v<R, const charT*>} is \tcode{false}, and
\item
\tcode{d.operator ::std::basic_string_view<charT, traits>()}
is not a valid expression.
\end{itemize}

\pnum
\effects
Initializes \exposid{data_} with \tcode{ranges::data(r)} and
\exposid{size_} with \tcode{ranges::size(r)}.

\pnum
\throws
Any exception thrown by \tcode{ranges::data(r)} and \tcode{ranges::size(r)}.
\end{itemdescr}

\rSec3[string.view.deduct]{Deduction guides}

\begin{itemdecl}
template<class It, class End>
  basic_string_view(It, End) -> basic_string_view<iter_value_t<It>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item \tcode{It} satisfies \libconcept{contiguous_iterator}.
\item \tcode{End} satisfies \tcode{\libconcept{sized_sentinel_for}<It>}.
\end{itemize}
\end{itemdescr}

\begin{itemdecl}
template<class R>
  basic_string_view(R&&) -> basic_string_view<ranges::range_value_t<R>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{R} satisfies \tcode{ranges::\libconcept{contiguous_range}}.
\end{itemdescr}

\rSec3[string.view.iterators]{Iterator support}

\indexlibrarymember{const_iterator}{basic_string_view}%
\begin{itemdecl}
using const_iterator = @\impdefx{type of \tcode{basic_string_view::const_iterator}}@;
\end{itemdecl}

\begin{itemdescr}
\pnum
A type that meets the requirements
of a constant
\oldconcept{RandomAccessIterator}\iref{random.access.iterators},
models \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}, and
meets the constexpr iterator requirements\iref{iterator.requirements.general},
whose \tcode{value_type} is the template parameter \tcode{charT}.

\pnum
All requirements on container iterators\iref{container.requirements}
apply to \tcode{basic_string_view::const_iterator} as well.
\end{itemdescr}

\indexlibrarymember{begin}{basic_string_view}%
\indexlibrarymember{cbegin}{basic_string_view}%
\begin{itemdecl}
constexpr const_iterator begin() const noexcept;
constexpr const_iterator cbegin() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An iterator such that
\begin{itemize}
\item if \tcode{!empty()}, \tcode{addressof(*begin()) == \exposid{data_}},
\item otherwise, an unspecified value such that \range{begin()}{end()} is a valid range.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{end}{basic_string_view}%
\indexlibrarymember{cend}{basic_string_view}%
\begin{itemdecl}
constexpr const_iterator end() const noexcept;
constexpr const_iterator cend() const noexcept;
\end{itemdecl}

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

\indexlibrarymember{rbegin}{basic_string_view}%
\indexlibrarymember{crbegin}{basic_string_view}%
\begin{itemdecl}
constexpr const_reverse_iterator rbegin() const noexcept;
constexpr const_reverse_iterator crbegin() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{const_reverse_iterator(end())}.
\end{itemdescr}

\indexlibrarymember{rend}{basic_string_view}%
\indexlibrarymember{crend}{basic_string_view}%
\begin{itemdecl}
constexpr const_reverse_iterator rend() const noexcept;
constexpr const_reverse_iterator crend() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{const_reverse_iterator(begin())}.
\end{itemdescr}

\rSec3[string.view.capacity]{Capacity}

\indexlibrarymember{size}{basic_string_view}%
\indexlibrarymember{length}{basic_string_view}%
\begin{itemdecl}
constexpr size_type size() const noexcept;
constexpr size_type length() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{size_}.
\end{itemdescr}


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

\begin{itemdescr}
\pnum
\returns
The largest possible number of char-like objects
that can be referred to by a \tcode{basic_string_view}.
\end{itemdescr}

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

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{size_} == 0}.
\end{itemdescr}

\rSec3[string.view.access]{Element access}

\indexlibrarymember{operator[]}{basic_string_view}%
\begin{itemdecl}
constexpr const_reference operator[](size_type pos) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\hardexpects
\tcode{pos < size()} is \tcode{true}.
\begin{note}
This precondition is stronger than the one on \tcode{basic_string::operator[]}.
\end{note}

\pnum
\returns
\tcode{\exposid{data_}[pos]}.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{at}{basic_string_view}%
\begin{itemdecl}
constexpr const_reference at(size_type pos) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{data_}[pos]}.

\pnum
\throws
\tcode{out_of_range} if \tcode{pos >= size()}.
\end{itemdescr}

\indexlibrarymember{front}{basic_string_view}%
\begin{itemdecl}
constexpr const_reference front() const;
\end{itemdecl}

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

\pnum
\returns
\tcode{\exposid{data_}[0]}.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{back}{basic_string_view}%
\begin{itemdecl}
constexpr const_reference back() const;
\end{itemdecl}

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

\pnum
\returns
\tcode{\exposid{data_}[size() - 1]}.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{data}{basic_string_view}%
\begin{itemdecl}
constexpr const charT* data() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\exposid{data_}.

\pnum
\begin{note}
Unlike \tcode{basic_string::data()} and \grammarterm{string-literal}s,
\tcode{data()} can return a pointer to a buffer that is not null-terminated.
Therefore it is typically a mistake to pass \tcode{data()} to a function
that takes just a \tcode{const charT*} and expects a null-terminated string.
\end{note}
\end{itemdescr}

\rSec3[string.view.modifiers]{Modifiers}

\indexlibrarymember{remove_prefix}{basic_string_view}%
\begin{itemdecl}
constexpr void remove_prefix(size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\hardexpects
\tcode{n <= size()} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{\exposid{data_} += n; \exposid{size_} -= n;}
\end{itemdescr}

\indexlibrarymember{remove_suffix}{basic_string_view}%
\begin{itemdecl}
constexpr void remove_suffix(size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\hardexpects
\tcode{n <= size()} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{\exposid{size_} -= n;}
\end{itemdescr}

\indexlibrarymember{swap}{basic_string_view}%
\begin{itemdecl}
constexpr void swap(basic_string_view& s) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Exchanges the values of \tcode{*this} and \tcode{s}.
\end{itemdescr}

\rSec3[string.view.ops]{String operations}

\indexlibrarymember{copy}{basic_string_view}%
\begin{itemdecl}
constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{rlen} be the smaller of \tcode{n} and \tcode{size() - pos}.

\pnum
\expects
\range{s}{s + rlen} is a valid range.

\pnum
\effects
Equivalent to \tcode{traits::copy(s, data() + pos, rlen)}.

\pnum
\returns
\tcode{rlen}.

\pnum
\throws
\tcode{out_of_range} if \tcode{pos > size()}.

\pnum
\complexity
\bigoh{\tcode{rlen}}.
\end{itemdescr}

\indexlibrarymember{substr}{basic_string_view}%
\indexlibrarymember{subview}{basic_string_view}%
\begin{itemdecl}
constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
constexpr basic_string_view subview(size_type pos = 0, size_type n = npos) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{rlen} be the smaller of \tcode{n} and \tcode{size() - pos}.

\pnum
\effects
Determines \tcode{rlen}, the effective length of the string to reference.

\pnum
\returns
\tcode{basic_string_view(data() + pos, rlen)}.

\pnum
\throws
\tcode{out_of_range} if \tcode{pos > size()}.
\end{itemdescr}

\indexlibrarymember{compare}{basic_string_view}%
\begin{itemdecl}
constexpr int compare(basic_string_view str) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{rlen} be the smaller of \tcode{size()} and \tcode{str.size()}.

\pnum
\effects
Determines \tcode{rlen}, the effective length of the strings to compare.
The function then compares the two strings by calling \tcode{traits::compare(data(), str.data(), rlen)}.

\pnum
\returns
The nonzero result if the result of the comparison is nonzero.
Otherwise, returns a value as indicated in \tref{string.view.compare}.
\begin{libtab2}{\tcode{compare()} results}{string.view.compare}{cc}{Condition}{Return Value}
\tcode{size() < str.size()}  & \tcode{< 0}\\
\tcode{size() == str.size()} & \tcode{ \ 0}\\
\tcode{size() >  str.size()} & \tcode{> 0}\\
\end{libtab2}

\pnum
\complexity
\bigoh{\tcode{rlen}}.
\end{itemdescr}

\indexlibrarymember{compare}{basic_string_view}%
\begin{itemdecl}
constexpr int compare(size_type pos1, size_type n1, basic_string_view str) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return substr(pos1, n1).compare(str);}
\end{itemdescr}

\indexlibrarymember{compare}{basic_string_view}%
\begin{itemdecl}
constexpr int compare(size_type pos1, size_type n1, basic_string_view str,
                      size_type pos2, size_type n2) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return substr(pos1, n1).compare(str.substr(pos2, n2));}
\end{itemdescr}

\indexlibrarymember{compare}{basic_string_view}%
\begin{itemdecl}
constexpr int compare(const charT* s) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return compare(basic_string_view(s));}
\end{itemdescr}

\indexlibrarymember{compare}{basic_string_view}%
\begin{itemdecl}
constexpr int compare(size_type pos1, size_type n1, const charT* s) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return substr(pos1, n1).compare(basic_string_view(s));}
\end{itemdescr}

\indexlibrarymember{compare}{basic_string_view}%
\begin{itemdecl}
constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return substr(pos1, n1).compare(basic_string_view(s, n2));}
\end{itemdescr}

\indexlibrarymember{starts_with}{basic_string_view}%
\begin{itemdecl}
constexpr bool starts_with(basic_string_view x) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{rlen} be the smaller of \tcode{size()} and \tcode{x.size()}.

\pnum
\effects
Equivalent to: \tcode{return basic_string_view(data(), rlen) == x;}
\end{itemdescr}

\indexlibrarymember{starts_with}{basic_string_view}%
\begin{itemdecl}
constexpr bool starts_with(charT x) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !empty() \&\& traits::eq(front(), x);}
\end{itemdescr}

\indexlibrarymember{starts_with}{basic_string_view}%
\begin{itemdecl}
constexpr bool starts_with(const charT* x) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return starts_with(basic_string_view(x));}
\end{itemdescr}

\indexlibrarymember{ends_with}{basic_string_view}%
\begin{itemdecl}
constexpr bool ends_with(basic_string_view x) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{rlen} be the smaller of \tcode{size()} and \tcode{x.size()}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
return basic_string_view(data() + (size() - rlen), rlen) == x;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{ends_with}{basic_string_view}%
\begin{itemdecl}
constexpr bool ends_with(charT x) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return !empty() \&\& traits::eq(back(), x);}
\end{itemdescr}

\indexlibrarymember{ends_with}{basic_string_view}%
\begin{itemdecl}
constexpr bool ends_with(const charT* x) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return ends_with(basic_string_view(x));}
\end{itemdescr}

\indexlibrarymember{contains}{basic_string_view}%
\begin{itemdecl}
constexpr bool contains(basic_string_view x) const noexcept;
constexpr bool contains(charT x) const noexcept;
constexpr bool contains(const charT* x) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return find(x) != npos;}
\end{itemdescr}

\rSec3[string.view.find]{Searching}

\pnum
Member functions in this subclause have complexity \bigoh{\tcode{size() * str.size()}} at worst,
although implementations should do better.

\pnum
Let \placeholder{F} be one of
\tcode{find},
\tcode{rfind},
\tcode{find_first_of},
\tcode{find_last_of},
\tcode{find_first_not_of},
and
\tcode{find_last_not_of}.
\begin{itemize}
\item
Each member function of the form
\begin{codeblock}
constexpr @\placeholder{return-type}@ @\placeholder{F}@(const charT* s, size_type pos) const;
\end{codeblock}
has effects equivalent to: \tcode{return \placeholder{F}(basic_string_view(s), pos);}

\item
Each member function of the form
\begin{codeblock}
constexpr @\placeholder{return-type}@ @\placeholder{F}@(const charT* s, size_type pos, size_type n) const;
\end{codeblock}
has effects equivalent to: \tcode{return \placeholder{F}(basic_string_view(s, n), pos);}

\item
Each member function of the form
\begin{codeblock}
constexpr @\placeholder{return-type}@ @\placeholder{F}@(charT c, size_type pos) const noexcept;
\end{codeblock}
has effects equivalent to: \tcode{return \placeholder{F}(basic_string_view(addressof(c), 1), pos);}
\end{itemize}

\indexlibrarymember{find}{basic_string_view}%
\begin{itemdecl}
constexpr size_type find(basic_string_view str, size_type pos = 0) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{xpos} be the lowest position, if possible, such that the following conditions hold:
\begin{itemize}
\item
\tcode{pos <= xpos}
\item
\tcode{xpos + str.size() <= size()}
\item
\tcode{traits::eq(\exposid{data_}[xpos + I], str[I])} for all elements \tcode{I} of the string referenced by \tcode{str}.
\end{itemize}

\pnum
\effects
Determines \tcode{xpos}.

\pnum
\returns
\tcode{xpos} if the function can determine such a value for \tcode{xpos}.
Otherwise, returns \tcode{npos}.
\end{itemdescr}

\indexlibrarymember{rfind}{basic_string_view}%
\begin{itemdecl}
constexpr size_type rfind(basic_string_view str, size_type pos = npos) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{xpos} be the highest position, if possible, such that the following conditions hold:
\begin{itemize}
\item
\tcode{xpos <= pos}
\item
\tcode{xpos + str.size() <= size()}
\item
\tcode{traits::eq(\exposid{data_}[xpos + I], str[I])} for all elements \tcode{I} of the string referenced by \tcode{str}.
\end{itemize}

\pnum
\effects
Determines \tcode{xpos}.

\pnum
\returns
\tcode{xpos} if the function can determine such a value for \tcode{xpos}.
Otherwise, returns \tcode{npos}.
\end{itemdescr}

\indexlibrarymember{find_first_of}{basic_string_view}%
\begin{itemdecl}
constexpr size_type find_first_of(basic_string_view str, size_type pos = 0) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{xpos} be the lowest position, if possible, such that the following conditions hold:
\begin{itemize}
\item
\tcode{pos <= xpos}
\item
\tcode{xpos < size()}
\item
\tcode{traits::eq(\exposid{data_}[xpos], str[I])} for some element \tcode{I} of the string referenced by \tcode{str}.
\end{itemize}

\pnum
\effects
Determines \tcode{xpos}.

\pnum
\returns
\tcode{xpos} if the function can determine such a value for \tcode{xpos}.
Otherwise, returns \tcode{npos}.
\end{itemdescr}

\indexlibrarymember{find_last_of}{basic_string_view}%
\begin{itemdecl}
constexpr size_type find_last_of(basic_string_view str, size_type pos = npos) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{xpos} be the highest position, if possible, such that the following conditions hold:
\begin{itemize}
\item
\tcode{xpos <= pos}
\item
\tcode{xpos < size()}
\item
\tcode{traits::eq(\exposid{data_}[xpos], str[I])} for some element \tcode{I} of the string referenced by \tcode{str}.
\end{itemize}

\pnum
\effects
Determines \tcode{xpos}.

\pnum
\returns
\tcode{xpos} if the function can determine such a value for \tcode{xpos}.
Otherwise, returns \tcode{npos}.
\end{itemdescr}

\indexlibrarymember{find_first_not_of}{basic_string_view}%
\begin{itemdecl}
constexpr size_type find_first_not_of(basic_string_view str, size_type pos = 0) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{xpos} be the lowest position, if possible, such that the following conditions hold:
\begin{itemize}
\item
\tcode{pos <= xpos}
\item
\tcode{xpos < size()}
\item
\tcode{traits::eq(\exposid{data_}[xpos], str[I])} for no element \tcode{I} of the string referenced by \tcode{str}.
\end{itemize}

\pnum
\effects
Determines \tcode{xpos}.

\pnum
\returns
\tcode{xpos} if the function can determine such a value for \tcode{xpos}. Otherwise, returns \tcode{npos}.
\end{itemdescr}

\indexlibrarymember{find_last_not_of}{basic_string_view}%
\begin{itemdecl}
constexpr size_type find_last_not_of(basic_string_view str, size_type pos = npos) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{xpos} be the highest position, if possible, such that the following conditions hold:
\begin{itemize}
\item
\tcode{xpos <= pos}
\item
\tcode{xpos < size()}
\item
\tcode{traits::eq(\exposid{data_}[xpos], str[I])} for no element \tcode{I} of the string referenced by \tcode{str}.
\end{itemize}

\pnum
\effects
Determines \tcode{xpos}.

\pnum
\returns
\tcode{xpos} if the function can determine such a value for \tcode{xpos}.
Otherwise, returns \tcode{npos}.
\end{itemdescr}

\rSec2[string.view.comparison]{Non-member comparison functions}

\indexlibrarymember{operator==}{basic_string_view}%
\begin{itemdecl}
template<class charT, class traits>
  constexpr bool operator==(basic_string_view<charT, traits> lhs,
                            type_identity_t<basic_string_view<charT, traits>> rhs) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{lhs.compare(rhs) == 0}.
\end{itemdescr}

\indexlibrarymember{operator<=>}{basic_string_view}%
\begin{itemdecl}
template<class charT, class traits>
  constexpr @\seebelow@ operator<=>(basic_string_view<charT, traits> lhs,
            @\itcorr@                      type_identity_t<basic_string_view<charT, traits>> rhs) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{R} denote the type \tcode{traits::comparison_category} if
that \grammarterm{qualified-id} is valid and denotes a type\iref{temp.deduct},
otherwise \tcode{R} is \tcode{weak_ordering}.

\pnum
\mandates
\tcode{R} denotes a comparison category type\iref{cmp.categories}.

\pnum
\returns
\tcode{static_cast<R>(lhs.compare(rhs) <=> 0)}.

\pnum
\begin{note}
The usage of \tcode{type_identity_t} as parameter
ensures that an object of type \tcode{basic_string_view<charT, traits>}
can always be compared with an object of a type \tcode{T} with
an implicit conversion to \tcode{basic_string_view<charT, traits>}, and
vice versa, as per \ref{over.match.oper}.
\end{note}
\end{itemdescr}

\rSec2[string.view.io]{Inserters and extractors}

\indexlibrarymember{operator<<}{basic_string_view}%
\begin{itemdecl}
template<class charT, class traits>
  basic_ostream<charT, traits>&
    operator<<(basic_ostream<charT, traits>& os, basic_string_view<charT, traits> str);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Behaves as a formatted output
function\iref{ostream.formatted.reqmts} of \tcode{os}. Forms a character sequence
\tcode{seq}, initially consisting of the elements defined by the range
\range{str.begin()}{str.end()}. Determines padding for \tcode{seq}
as described in~\ref{ostream.formatted.reqmts}.
Then inserts \tcode{seq} as if by calling
\tcode{os.rdbuf()->sputn(\brk{}seq, n)}, where \tcode{n} is the larger
of \tcode{os.width()} and \tcode{str.size()};
then calls \tcode{os.\brk{}width(0)}.

\pnum
\returns
\tcode{os}.
\end{itemdescr}

\rSec2[string.view.hash]{Hash support}

\indexlibrarymember{hash}{string_view}%
\indexlibrarymember{hash}{u8string_view}%
\indexlibrarymember{hash}{u16string_view}%
\indexlibrarymember{hash}{u32string_view}%
\indexlibrarymember{hash}{wstring_view}%
\begin{itemdecl}
template<> struct hash<string_view>;
template<> struct hash<u8string_view>;
template<> struct hash<u16string_view>;
template<> struct hash<u32string_view>;
template<> struct hash<wstring_view>;
\end{itemdecl}

\begin{itemdescr}
\pnum
The specialization is enabled\iref{unord.hash}.
\begin{note}
The hash value of a string view object is equal to the hash value of
the corresponding string object\iref{basic.string.hash}.
\end{note}
\end{itemdescr}

\rSec2[string.view.literals]{Suffix for \tcode{basic_string_view} literals}

\indexlibrarymember{operator""""sv}{string_view}%
\begin{itemdecl}
constexpr string_view operator""sv(const char* str, size_t len) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{string_view\{str, len\}}.
\end{itemdescr}

\indexlibrarymember{operator""""sv}{u8string_view}%
\begin{itemdecl}
constexpr u8string_view operator""sv(const char8_t* str, size_t len) noexcept;
\end{itemdecl}
\begin{itemdescr}
\pnum
\returns
\tcode{u8string_view\{str, len\}}.
\end{itemdescr}

\indexlibrarymember{operator""""sv}{u16string_view}%
\begin{itemdecl}
constexpr u16string_view operator""sv(const char16_t* str, size_t len) noexcept;
\end{itemdecl}
\begin{itemdescr}
\pnum
\returns
\tcode{u16string_view\{str, len\}}.
\end{itemdescr}

\indexlibrarymember{operator""""sv}{u32string_view}%
\begin{itemdecl}
constexpr u32string_view operator""sv(const char32_t* str, size_t len) noexcept;
\end{itemdecl}
\begin{itemdescr}
\pnum
\returns
\tcode{u32string_view\{str, len\}}.
\end{itemdescr}

\indexlibrarymember{operator""""sv}{wstring_view}%
\begin{itemdecl}
constexpr wstring_view operator""sv(const wchar_t* str, size_t len) noexcept;
\end{itemdecl}
\begin{itemdescr}
\pnum
\returns
\tcode{wstring_view\{str, len\}}.
\end{itemdescr}

\rSec1[string.classes]{String classes}

\rSec2[string.classes.general]{General}

\pnum
The header \tcode{<string>} defines the
\tcode{basic_string} class template for manipulating
varying-length sequences of char-like objects and five
\grammarterm{typedef-name}{s}, \tcode{string},
\tcode{u8string},
\tcode{u16string},
\tcode{u32string},
and \tcode{wstring}, that name
the specializations
\tcode{basic_string<char>},
\tcode{basic_string<char8_t>},
\tcode{basic_string<char16_t>},
\tcode{basic_string<char32_t>},
and
\tcode{basic_string<\brk{}wchar_t>}, respectively.

\rSec2[string.syn]{Header \tcode{<string>} synopsis}
\indexheader{string}%

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

namespace std {
  // \ref{char.traits}, character traits
  template<class charT> struct char_traits;                             // freestanding
  template<> struct char_traits<char>;                                  // freestanding
  template<> struct char_traits<char8_t>;                               // freestanding
  template<> struct char_traits<char16_t>;                              // freestanding
  template<> struct char_traits<char32_t>;                              // freestanding
  template<> struct char_traits<wchar_t>;                               // freestanding

  // \ref{basic.string}, \tcode{basic_string}
  template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
    class basic_string;

  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(const basic_string<charT, traits, Allocator>& lhs,
                const basic_string<charT, traits, Allocator>& rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(basic_string<charT, traits, Allocator>&& lhs,
                const basic_string<charT, traits, Allocator>& rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(const basic_string<charT, traits, Allocator>& lhs,
                basic_string<charT, traits, Allocator>&& rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(basic_string<charT, traits, Allocator>&& lhs,
                basic_string<charT, traits, Allocator>&& rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(const charT* lhs,
                const basic_string<charT, traits, Allocator>& rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(const charT* lhs,
                basic_string<charT, traits, Allocator>&& rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(charT lhs,
                const basic_string<charT, traits, Allocator>& rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(charT lhs,
                basic_string<charT, traits, Allocator>&& rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(const basic_string<charT, traits, Allocator>& lhs,
                const charT* rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(basic_string<charT, traits, Allocator>&& lhs,
                const charT* rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(const basic_string<charT, traits, Allocator>& lhs,
                charT rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(basic_string<charT, traits, Allocator>&& lhs,
                charT rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(const basic_string<charT, traits, Allocator>& lhs,
                type_identity_t<basic_string_view<charT, traits>> rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(basic_string<charT, traits, Allocator>&& lhs,
                type_identity_t<basic_string_view<charT, traits>> rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(type_identity_t<basic_string_view<charT, traits>> lhs,
                const basic_string<charT, traits, Allocator>& rhs);
  template<class charT, class traits, class Allocator>
    constexpr basic_string<charT, traits, Allocator>
      operator+(type_identity_t<basic_string_view<charT, traits>> lhs,
                basic_string<charT, traits, Allocator>&& rhs);

  template<class charT, class traits, class Allocator>
    constexpr bool
      operator==(const basic_string<charT, traits, Allocator>& lhs,
                 const basic_string<charT, traits, Allocator>& rhs) noexcept;
  template<class charT, class traits, class Allocator>
    constexpr bool operator==(const basic_string<charT, traits, Allocator>& lhs,
                              const charT* rhs);

  template<class charT, class traits, class Allocator>
    constexpr @\seebelow@ operator<=>(const basic_string<charT, traits, Allocator>& lhs,
              @\itcorr@                      const basic_string<charT, traits, Allocator>& rhs) noexcept;
  template<class charT, class traits, class Allocator>
    constexpr @\seebelow@ operator<=>(const basic_string<charT, traits, Allocator>& lhs,
              @\itcorr@                      const charT* rhs);

  // \ref{string.special}, swap
  template<class charT, class traits, class Allocator>
    constexpr void
      swap(basic_string<charT, traits, Allocator>& lhs,
           basic_string<charT, traits, Allocator>& rhs)
        noexcept(noexcept(lhs.swap(rhs)));

  // \ref{string.io}, inserters and extractors
  template<class charT, class traits, class Allocator>
    basic_istream<charT, traits>&
      operator>>(basic_istream<charT, traits>& is,
                 basic_string<charT, traits, Allocator>& str);
  template<class charT, class traits, class Allocator>
    basic_ostream<charT, traits>&
      operator<<(basic_ostream<charT, traits>& os,
                 const basic_string<charT, traits, Allocator>& str);
  template<class charT, class traits, class Allocator>
    basic_istream<charT, traits>&
      getline(basic_istream<charT, traits>& is,
              basic_string<charT, traits, Allocator>& str,
              charT delim);
  template<class charT, class traits, class Allocator>
    basic_istream<charT, traits>&
      getline(basic_istream<charT, traits>&& is,
              basic_string<charT, traits, Allocator>& str,
              charT delim);
  template<class charT, class traits, class Allocator>
    basic_istream<charT, traits>&
      getline(basic_istream<charT, traits>& is,
              basic_string<charT, traits, Allocator>& str);
  template<class charT, class traits, class Allocator>
    basic_istream<charT, traits>&
      getline(basic_istream<charT, traits>&& is,
              basic_string<charT, traits, Allocator>& str);

  // \ref{string.erasure}, erasure
  template<class charT, class traits, class Allocator, class U = charT>
    constexpr typename basic_string<charT, traits, Allocator>::size_type
      erase(basic_string<charT, traits, Allocator>& c, const U& value);
  template<class charT, class traits, class Allocator, class Predicate>
    constexpr typename basic_string<charT, traits, Allocator>::size_type
      erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred);

  // \tcode{basic_string} \grammarterm{typedef-name}s
  using @\libglobal{string}@    = basic_string<char>;
  using @\libglobal{u8string}@  = basic_string<char8_t>;
  using @\libglobal{u16string}@ = basic_string<char16_t>;
  using @\libglobal{u32string}@ = basic_string<char32_t>;
  using @\libglobal{wstring}@   = basic_string<wchar_t>;

  // \ref{string.conversions}, numeric conversions
  int stoi(const string& str, size_t* idx = nullptr, int base = 10);
  long stol(const string& str, size_t* idx = nullptr, int base = 10);
  unsigned long stoul(const string& str, size_t* idx = nullptr, int base = 10);
  long long stoll(const string& str, size_t* idx = nullptr, int base = 10);
  unsigned long long stoull(const string& str, size_t* idx = nullptr, int base = 10);
  float stof(const string& str, size_t* idx = nullptr);
  double stod(const string& str, size_t* idx = nullptr);
  long double stold(const string& str, size_t* idx = nullptr);
  constexpr string to_string(int val);
  constexpr string to_string(unsigned val);
  constexpr string to_string(long val);
  constexpr string to_string(unsigned long val);
  constexpr string to_string(long long val);
  constexpr string to_string(unsigned long long val);
  string to_string(float val);
  string to_string(double val);
  string to_string(long double val);

  int stoi(const wstring& str, size_t* idx = nullptr, int base = 10);
  long stol(const wstring& str, size_t* idx = nullptr, int base = 10);
  unsigned long stoul(const wstring& str, size_t* idx = nullptr, int base = 10);
  long long stoll(const wstring& str, size_t* idx = nullptr, int base = 10);
  unsigned long long stoull(const wstring& str, size_t* idx = nullptr, int base = 10);
  float stof(const wstring& str, size_t* idx = nullptr);
  double stod(const wstring& str, size_t* idx = nullptr);
  long double stold(const wstring& str, size_t* idx = nullptr);
  constexpr wstring to_wstring(int val);
  constexpr wstring to_wstring(unsigned val);
  constexpr wstring to_wstring(long val);
  constexpr wstring to_wstring(unsigned long val);
  constexpr wstring to_wstring(long long val);
  constexpr wstring to_wstring(unsigned long long val);
  wstring to_wstring(float val);
  wstring to_wstring(double val);
  wstring to_wstring(long double val);

  namespace pmr {
    template<class charT, class traits = char_traits<charT>>
      using basic_string = std::basic_string<charT, traits, polymorphic_allocator<charT>>;

    using string    = basic_string<char>;
    using u8string  = basic_string<char8_t>;
    using u16string = basic_string<char16_t>;
    using u32string = basic_string<char32_t>;
    using wstring   = basic_string<wchar_t>;
  }

  // \ref{basic.string.hash}, hash support
  template<class T> struct hash;
  template<class A> struct hash<basic_string<char, char_traits<char>, A>>;
  template<class A> struct hash<basic_string<char8_t, char_traits<char8_t>, A>>;
  template<class A> struct hash<basic_string<char16_t, char_traits<char16_t>, A>>;
  template<class A> struct hash<basic_string<char32_t, char_traits<char32_t>, A>>;
  template<class A> struct hash<basic_string<wchar_t, char_traits<wchar_t>, A>>;

  inline namespace literals {
    inline namespace string_literals {
      // \ref{basic.string.literals}, suffix for \tcode{basic_string} literals
      constexpr string    operator""s(const char* str, size_t len);
      constexpr u8string  operator""s(const char8_t* str, size_t len);
      constexpr u16string operator""s(const char16_t* str, size_t len);
      constexpr u32string operator""s(const char32_t* str, size_t len);
      constexpr wstring   operator""s(const wchar_t* str, size_t len);
    }
  }
}
\end{codeblock}

\rSec2[basic.string]{Class template \tcode{basic_string}}

\rSec3[basic.string.general]{General}

\pnum
\indexlibraryglobal{basic_string}%
The
class template
\tcode{basic_string}
describes objects that can store a sequence consisting of a varying number of
arbitrary char-like objects with the first element of the sequence at position zero.
Such a sequence is also called a ``string'' if the type of the
char-like objects that it holds
is clear from context.
In the rest of \ref{basic.string},
the type of the char-like objects held in a \tcode{basic_string} object
is designated by \tcode{charT}.

\pnum
A specialization of \tcode{basic_string} is a contiguous container\iref{container.reqmts}.

\pnum
In all cases,
\crange{data()}{data() + size()} is a valid range,
\tcode{data() + size()} points at an object with value \tcode{charT()}
(a ``null terminator''\indextext{string!null terminator}),
and \tcode{size() <= capacity()} is \tcode{true}.
The program has undefined behavior if
the null terminator is modified to any value other than \tcode{charT()}.


\indexlibraryglobal{basic_string}%
\indexlibrarymember{traits_type}{basic_string}%
\indexlibrarymember{value_type}{basic_string}%
\indexlibrarymember{allocator_type}{basic_string}%
\indexlibrarymember{size_type}{basic_string}%
\indexlibrarymember{difference_type}{basic_string}%
\indexlibrarymember{pointer}{basic_string}%
\indexlibrarymember{const_pointer}{basic_string}%
\indexlibrarymember{reference}{basic_string}%
\indexlibrarymember{const_reference}{basic_string}%
\indexlibrarymember{iterator}{basic_string}%
\indexlibrarymember{const_iterator}{basic_string}%
\indexlibrarymember{reverse_iterator}{basic_string}%
\indexlibrarymember{const_reverse_iterator}{basic_string}%
\begin{codeblock}
namespace std {
  template<class charT, class traits = char_traits<charT>,
           class Allocator = allocator<charT>>
  class basic_string {
  public:
    // types
    using traits_type            = traits;
    using value_type             = charT;
    using allocator_type         = Allocator;
    using size_type              = allocator_traits<Allocator>::size_type;
    using difference_type        = allocator_traits<Allocator>::difference_type;
    using pointer                = allocator_traits<Allocator>::pointer;
    using const_pointer          = allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;

    using iterator               = @\impdefx{type of \tcode{basic_string::iterator}}@; // see \ref{container.requirements}
    using const_iterator         = @\impdefx{type of \tcode{basic_string::const_iterator}}@; // see \ref{container.requirements}
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    static constexpr size_type npos = size_type(-1);

    // \ref{string.cons}, construct/copy/destroy
    constexpr basic_string() noexcept(noexcept(Allocator())) : basic_string(Allocator()) { }
    constexpr explicit basic_string(const Allocator& a) noexcept;
    constexpr basic_string(const basic_string& str);
    constexpr basic_string(basic_string&& str) noexcept;
    constexpr basic_string(const basic_string& str, size_type pos,
                           const Allocator& a = Allocator());
    constexpr basic_string(const basic_string& str, size_type pos, size_type n,
                           const Allocator& a = Allocator());
    constexpr basic_string(basic_string&& str, size_type pos,
                           const Allocator& a = Allocator());
    constexpr basic_string(basic_string&& str, size_type pos, size_type n,
                           const Allocator& a = Allocator());
    template<class T>
      constexpr basic_string(const T& t, size_type pos, size_type n,
                             const Allocator& a = Allocator());
    template<class T>
      constexpr explicit basic_string(const T& t, const Allocator& a = Allocator());
    constexpr basic_string(const charT* s, size_type n, const Allocator& a = Allocator());
    constexpr basic_string(const charT* s, const Allocator& a = Allocator());
    basic_string(nullptr_t) = delete;
    constexpr basic_string(size_type n, charT c, const Allocator& a = Allocator());
    template<class InputIterator>
      constexpr basic_string(InputIterator begin, InputIterator end,
                             const Allocator& a = Allocator());
    template<@\exposconcept{container-compatible-range}@<charT> R>
      constexpr basic_string(from_range_t, R&& rg, const Allocator& a = Allocator());
    constexpr basic_string(initializer_list<charT>, const Allocator& = Allocator());
    constexpr basic_string(const basic_string&, const Allocator&);
    constexpr basic_string(basic_string&&, const Allocator&);
    constexpr ~basic_string();

    constexpr basic_string& operator=(const basic_string& str);
    constexpr basic_string& operator=(basic_string&& str)
      noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
               allocator_traits<Allocator>::is_always_equal::value);
    template<class T>
      constexpr basic_string& operator=(const T& t);
    constexpr basic_string& operator=(const charT* s);
    basic_string& operator=(nullptr_t) = delete;
    constexpr basic_string& operator=(charT c);
    constexpr basic_string& operator=(initializer_list<charT>);

    // \ref{string.iterators}, 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{string.capacity}, capacity
    constexpr size_type size() const noexcept;
    constexpr size_type length() const noexcept;
    constexpr size_type max_size() const noexcept;
    constexpr void resize(size_type n, charT c);
    constexpr void resize(size_type n);
    template<class Operation> constexpr void resize_and_overwrite(size_type n, Operation op);
    constexpr size_type capacity() const noexcept;
    constexpr void reserve(size_type res_arg);
    constexpr void shrink_to_fit();
    constexpr void clear() noexcept;
    constexpr bool empty() const noexcept;

    // \ref{string.access}, element access
    constexpr const_reference operator[](size_type pos) const;
    constexpr reference       operator[](size_type pos);
    constexpr const_reference at(size_type n) const;
    constexpr reference       at(size_type n);

    constexpr const_reference front() const;
    constexpr reference       front();
    constexpr const_reference back() const;
    constexpr reference       back();

    // \ref{string.modifiers}, modifiers
    constexpr basic_string& operator+=(const basic_string& str);
    template<class T>
      constexpr basic_string& operator+=(const T& t);
    constexpr basic_string& operator+=(const charT* s);
    constexpr basic_string& operator+=(charT c);
    constexpr basic_string& operator+=(initializer_list<charT>);
    constexpr basic_string& append(const basic_string& str);
    constexpr basic_string& append(const basic_string& str, size_type pos, size_type n = npos);
    template<class T>
      constexpr basic_string& append(const T& t);
    template<class T>
      constexpr basic_string& append(const T& t, size_type pos, size_type n = npos);
    constexpr basic_string& append(const charT* s, size_type n);
    constexpr basic_string& append(const charT* s);
    constexpr basic_string& append(const charT* s, size_type pos, size_type n);
    constexpr basic_string& append(size_type n, charT c);
    template<class InputIterator>
      constexpr basic_string& append(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<charT> R>
      constexpr basic_string& append_range(R&& rg);
    constexpr basic_string& append(initializer_list<charT>);

    constexpr void push_back(charT c);

    constexpr basic_string& assign(const basic_string& str);
    constexpr basic_string& assign(basic_string&& str)
      noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
               allocator_traits<Allocator>::is_always_equal::value);
    constexpr basic_string& assign(const basic_string& str, size_type pos, size_type n = npos);
    template<class T>
      constexpr basic_string& assign(const T& t);
    template<class T>
      constexpr basic_string& assign(const T& t, size_type pos, size_type n = npos);
    constexpr basic_string& assign(const charT* s, size_type n);
    constexpr basic_string& assign(const charT* s);
    constexpr basic_string& assign(const charT* s, size_type pos, size_type n);
    constexpr basic_string& assign(size_type n, charT c);
    template<class InputIterator>
      constexpr basic_string& assign(InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<charT> R>
      constexpr basic_string& assign_range(R&& rg);
    constexpr basic_string& assign(initializer_list<charT>);

    constexpr basic_string& insert(size_type pos, const basic_string& str);
    constexpr basic_string& insert(size_type pos1, const basic_string& str,
                                   size_type pos2, size_type n = npos);
    template<class T>
      constexpr basic_string& insert(size_type pos, const T& t);
    template<class T>
      constexpr basic_string& insert(size_type pos1, const T& t,
                                     size_type pos2, size_type n = npos);
    constexpr basic_string& insert(size_type pos, const charT* s, size_type n);
    constexpr basic_string& insert(size_type pos, const charT* s);
    constexpr basic_string& insert(size_type pos, size_type n, charT c);
    constexpr iterator insert(const_iterator p, charT c);
    constexpr iterator insert(const_iterator p, size_type n, charT c);
    template<class InputIterator>
      constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last);
    template<@\exposconcept{container-compatible-range}@<charT> R>
      constexpr iterator insert_range(const_iterator p, R&& rg);
    constexpr iterator insert(const_iterator p, initializer_list<charT>);

    constexpr basic_string& erase(size_type pos = 0, size_type n = npos);
    constexpr iterator erase(const_iterator p);
    constexpr iterator erase(const_iterator first, const_iterator last);

    constexpr void pop_back();

    constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str);
    constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str,
                                    size_type pos2, size_type n2 = npos);
    template<class T>
      constexpr basic_string& replace(size_type pos1, size_type n1, const T& t);
    template<class T>
      constexpr basic_string& replace(size_type pos1, size_type n1, const T& t,
                                      size_type pos2, size_type n2 = npos);
    constexpr basic_string& replace(size_type pos, size_type n1, const charT* s, size_type n2);
    constexpr basic_string& replace(size_type pos, size_type n1, const charT* s);
    constexpr basic_string& replace(size_type pos, size_type n1, size_type n2, charT c);
    constexpr basic_string& replace(const_iterator i1, const_iterator i2,
                                    const basic_string& str);
    template<class T>
      constexpr basic_string& replace(const_iterator i1, const_iterator i2, const T& t);
    constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s,
                                    size_type n);
    constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s);
    constexpr basic_string& replace(const_iterator i1, const_iterator i2, size_type n, charT c);
    template<class InputIterator>
      constexpr basic_string& replace(const_iterator i1, const_iterator i2,
                                      InputIterator j1, InputIterator j2);
    template<@\exposconcept{container-compatible-range}@<charT> R>
      constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg);
    constexpr basic_string& replace(const_iterator, const_iterator, initializer_list<charT>);

    constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const;

    constexpr void swap(basic_string& str)
      noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
               allocator_traits<Allocator>::is_always_equal::value);

    // \ref{string.ops}, string operations
    constexpr const charT* c_str() const noexcept;
    constexpr const charT* data() const noexcept;
    constexpr       charT* data() noexcept;
    constexpr operator basic_string_view<charT, traits>() const noexcept;
    constexpr allocator_type get_allocator() const noexcept;

    template<class T>
      constexpr size_type find(const T& t, size_type pos = 0) const noexcept(@\seebelow@);
    constexpr size_type find(const basic_string& str, size_type pos = 0) const noexcept;
    constexpr size_type find(const charT* s, size_type pos, size_type n) const;
    constexpr size_type find(const charT* s, size_type pos = 0) const;
    constexpr size_type find(charT c, size_type pos = 0) const noexcept;
    template<class T>
      constexpr size_type rfind(const T& t, size_type pos = npos) const noexcept(@\seebelow@);
    constexpr size_type rfind(const basic_string& str, size_type pos = npos) const noexcept;
    constexpr size_type rfind(const charT* s, size_type pos, size_type n) const;
    constexpr size_type rfind(const charT* s, size_type pos = npos) const;
    constexpr size_type rfind(charT c, size_type pos = npos) const noexcept;

    template<class T>
      constexpr size_type find_first_of(const T& t, size_type pos = 0) const noexcept(@\seebelow@);
    constexpr size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept;
    constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const;
    constexpr size_type find_first_of(const charT* s, size_type pos = 0) const;
    constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept;
    template<class T>
      constexpr size_type find_last_of(const T& t,
                                       size_type pos = npos) const noexcept(@\seebelow@);
    constexpr size_type find_last_of(const basic_string& str,
                                     size_type pos = npos) const noexcept;
    constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const;
    constexpr size_type find_last_of(const charT* s, size_type pos = npos) const;
    constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept;

    template<class T>
      constexpr size_type find_first_not_of(const T& t,
                                            size_type pos = 0) const noexcept(@\seebelow@);
    constexpr size_type find_first_not_of(const basic_string& str,
                                          size_type pos = 0) const noexcept;
    constexpr size_type find_first_not_of(const charT* s, size_type pos, size_type n) const;
    constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const;
    constexpr size_type find_first_not_of(charT c, size_type pos = 0) const noexcept;
    template<class T>
      constexpr size_type find_last_not_of(const T& t,
                                           size_type pos = npos) const noexcept(@\seebelow@);
    constexpr size_type find_last_not_of(const basic_string& str,
                                         size_type pos = npos) const noexcept;
    constexpr size_type find_last_not_of(const charT* s, size_type pos, size_type n) const;
    constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const;
    constexpr size_type find_last_not_of(charT c, size_type pos = npos) const noexcept;

    constexpr basic_string substr(size_type pos = 0, size_type n = npos) const &;
    constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&;
    constexpr basic_string_view<charT, traits> subview(size_type pos = 0,
                                                       size_type n = npos) const;

    template<class T>
      constexpr int compare(const T& t) const noexcept(@\seebelow@);
    template<class T>
      constexpr int compare(size_type pos1, size_type n1, const T& t) const;
    template<class T>
      constexpr int compare(size_type pos1, size_type n1, const T& t,
                            size_type pos2, size_type n2 = npos) const;
    constexpr int compare(const basic_string& str) const noexcept;
    constexpr int compare(size_type pos1, size_type n1, const basic_string& str) const;
    constexpr int compare(size_type pos1, size_type n1, const basic_string& str,
                          size_type pos2, size_type n2 = npos) const;
    constexpr int compare(const charT* s) const;
    constexpr int compare(size_type pos1, size_type n1, const charT* s) const;
    constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const;

    constexpr bool starts_with(basic_string_view<charT, traits> x) const noexcept;
    constexpr bool starts_with(charT x) const noexcept;
    constexpr bool starts_with(const charT* x) const;
    constexpr bool ends_with(basic_string_view<charT, traits> x) const noexcept;
    constexpr bool ends_with(charT x) const noexcept;
    constexpr bool ends_with(const charT* x) const;

    constexpr bool contains(basic_string_view<charT, traits> x) const noexcept;
    constexpr bool contains(charT x) const noexcept;
    constexpr bool contains(const charT* x) const;
  };

  template<class InputIterator,
           class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
    basic_string(InputIterator, InputIterator, Allocator = Allocator())
      -> basic_string<typename iterator_traits<InputIterator>::value_type,
                      char_traits<typename iterator_traits<InputIterator>::value_type>,
                      Allocator>;

  template<ranges::@\libconcept{input_range}@ R,
           class Allocator = allocator<ranges::range_value_t<R>>>
    basic_string(from_range_t, R&&, Allocator = Allocator())
      -> basic_string<ranges::range_value_t<R>, char_traits<ranges::range_value_t<R>>,
                      Allocator>;

  template<class charT,
           class traits,
           class Allocator = allocator<charT>>
    explicit basic_string(basic_string_view<charT, traits>, const Allocator& = Allocator())
      -> basic_string<charT, traits, Allocator>;

  template<class charT,
           class traits,
           class Allocator = allocator<charT>>
    basic_string(basic_string_view<charT, traits>,
                 typename @\seebelow@::size_type, typename @\seebelow@::size_type,
                 const Allocator& = Allocator())
      -> basic_string<charT, traits, Allocator>;
}
\end{codeblock}

\pnum
A \tcode{size_type} parameter type in
a \tcode{basic_string} deduction guide
refers to the \tcode{size_type} member type of
the type deduced by the deduction guide.

\pnum
The types \tcode{iterator} and \tcode{const_iterator} meet
the constexpr iterator requirements\iref{iterator.requirements.general}.

\rSec3[string.require]{General requirements}

\pnum
If any operation would cause \tcode{size()} to
exceed \tcode{max_size()}, that operation throws an
exception object of type \tcode{length_error}.

\pnum
If any member function or operator of \tcode{basic_string} throws an exception, that
function or operator has no other effect on the \tcode{basic_string} object.

\pnum
Every object of type
\tcode{basic_string<charT, traits, Allocator>} uses an object of type
\tcode{Allocator} to allocate and free storage for the contained \tcode{charT}
objects as needed. The \tcode{Allocator} object used is
obtained as described in \ref{container.reqmts}.
In every specialization \tcode{basic_string<charT, traits, Allocator>},
the type \tcode{traits} shall meet
the character traits requirements\iref{char.traits}.
\begin{note}
Every specialization \tcode{basic_string<charT, traits, Allocator>} is
an allocator-aware container\iref{container.alloc.reqmts},
but does not use the allocator's \tcode{construct} and \tcode{destroy}
member functions\iref{container.requirements.pre}.
The program is ill-formed if
\tcode{Allocator::value_type} is not the same type as \tcode{charT}.
\end{note}
\begin{note}
The program is ill-formed if \tcode{traits::char_type}
is not the same type as \tcode{charT}.
\end{note}

\pnum
References, pointers, and iterators referring to the elements of a
\tcode{basic_string} sequence may be
invalidated by the following uses of that \tcode{basic_string} object:

\begin{itemize}
\item Passing as an argument to any standard library function taking a reference to non-const
\tcode{basic_string} as an argument.
\begin{footnote}
For example, as an argument to non-member
functions \tcode{swap()}\iref{string.special},
\tcode{operator>{}>()}\iref{string.io}, and \tcode{getline()}\iref{string.io}, or as
an argument to \tcode{basic_string::swap()}.
\end{footnote}

\item Calling non-const member functions, except
\tcode{operator[]},
\tcode{at},
\tcode{data},
\tcode{front},
\tcode{back},
\tcode{begin},
\tcode{rbegin},
\tcode{end},
and
\tcode{rend}.
\end{itemize}

\rSec3[string.cons]{Constructors and assignment operators}

\indexlibraryctor{basic_string}%
\begin{itemdecl}
constexpr explicit basic_string(const Allocator& a) noexcept;
\end{itemdecl}

\begin{itemdescr}

\pnum
\ensures
\tcode{size()} is equal to \tcode{0}.
\end{itemdescr}

\indexlibraryctor{basic_string}%
\begin{itemdecl}
constexpr basic_string(const basic_string& str);
constexpr basic_string(basic_string&& str) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an object whose
value is that of \tcode{str} prior to this call.

\pnum
\remarks
In the second form, \tcode{str} is left in a valid but unspecified state.
\end{itemdescr}

\indexlibraryctor{basic_string}%
\begin{itemdecl}
constexpr basic_string(const basic_string& str, size_type pos,
                       const Allocator& a = Allocator());
constexpr basic_string(const basic_string& str, size_type pos, size_type n,
                       const Allocator& a = Allocator());
constexpr basic_string(basic_string&& str, size_type pos,
                       const Allocator& a = Allocator());
constexpr basic_string(basic_string&& str, size_type pos, size_type n,
                       const Allocator& a = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
Let
\begin{itemize}
\item
\tcode{s} be the value of \tcode{str} prior to this call and
\item
\tcode{rlen} be \tcode{pos + min(n, s.size() - pos)}
for the overloads with parameter \tcode{n}, and
\tcode{s.size()} otherwise.
\end{itemize}

\pnum
\effects
Constructs an object
whose initial value is the range \range{s.data() + pos}{s.data() + rlen}.

\pnum
\throws
\tcode{out_of_range} if \tcode{pos > s.size()}.

\pnum
\remarks
For the overloads with a \tcode{basic_string\&\&} parameter,
\tcode{str} is left in a valid but unspecified state.

\pnum
\recommended
For the overloads with a \tcode{basic_string\&\&} parameter,
implementations should avoid allocation
if \tcode{s.get_allocator() == a} is \tcode{true}.
\end{itemdescr}

\indexlibraryctor{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>}
is \tcode{true}.

\pnum
\effects
Creates a variable, \tcode{sv},
as if by \tcode{basic_string_view<charT, traits> sv = t;}
and then behaves the same as:
\begin{codeblock}
basic_string(sv.substr(pos, n), a);
\end{codeblock}
\end{itemdescr}

\indexlibraryctor{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr explicit basic_string(const T& t, const Allocator& a = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Creates a variable, \tcode{sv}, as if by
\tcode{basic_string_view<charT, traits> sv = t;} and
then behaves the same as \tcode{basic_string(sv.data(), sv.size(), a)}.
\end{itemdescr}

\indexlibraryctor{basic_string}%
\begin{itemdecl}
constexpr basic_string(const charT* s, size_type n, const Allocator& a = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\range{s}{s + n} is a valid range.

\pnum
\effects
Constructs an object whose initial value is the range \range{s}{s + n}.

\pnum
\ensures
\tcode{size()} is equal to \tcode{n}, and
\tcode{traits::compare(data(), s, n)} is equal to \tcode{0}.
\end{itemdescr}

\indexlibraryctor{basic_string}%
\begin{itemdecl}
constexpr basic_string(const charT* s, const Allocator& a = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{Allocator} is a type
that qualifies as an allocator\iref{container.reqmts}.
\begin{note}
This affects class template argument deduction.
\end{note}

\pnum
\effects
Equivalent to: \tcode{basic_string(s, traits::length(s), a)}.
\end{itemdescr}

\indexlibraryctor{basic_string}%
\begin{itemdecl}
constexpr basic_string(size_type n, charT c, const Allocator& a = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{Allocator} is a type
that qualifies as an allocator\iref{container.reqmts}.
\begin{note}
This affects class template argument deduction.
\end{note}

\pnum
\effects
Constructs an object whose value consists of \tcode{n} copies of \tcode{c}.
\end{itemdescr}

\indexlibraryctor{basic_string}%
\begin{itemdecl}
template<class InputIterator>
  constexpr basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{InputIterator} is a type that qualifies as an input
iterator\iref{container.reqmts}.

\pnum
\effects
Constructs a string from the values in the range \range{begin}{end},
as specified in \ref{sequence.reqmts}.
\end{itemdescr}

\indexlibraryctor{basic_string}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<charT> R>
  constexpr basic_string(from_range_t, R&& rg, const Allocator& = Allocator());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a string from the values in the range \tcode{rg},
as specified in \ref{sequence.reqmts}.
\end{itemdescr}

\indexlibraryctor{basic_string}%
\begin{itemdecl}
constexpr basic_string(initializer_list<charT> il, const Allocator& a = Allocator());
\end{itemdecl}

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

\indexlibraryctor{basic_string}%
\begin{itemdecl}
constexpr basic_string(const basic_string& str, const Allocator& alloc);
constexpr basic_string(basic_string&& str, const Allocator& alloc);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs an object whose value is
that of \tcode{str} prior to this call.
The stored allocator is constructed from \tcode{alloc}.
In the second form, \tcode{str} is left in a valid but unspecified state.

\pnum
\throws
The second form throws nothing if \tcode{alloc == str.get_allocator()}.
\end{itemdescr}

\begin{itemdecl}
template<class InputIterator,
         class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
  basic_string(InputIterator, InputIterator, Allocator = Allocator())
    -> basic_string<typename iterator_traits<InputIterator>::value_type,
                    char_traits<typename iterator_traits<InputIterator>::value_type>,
                    Allocator>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{InputIterator} is a type that qualifies as an input iterator,
and \tcode{Allocator} is a type that qualifies as an allocator\iref{container.reqmts}.
\end{itemdescr}

\begin{itemdecl}
template<class charT,
         class traits,
         class Allocator = allocator<charT>>
  explicit basic_string(basic_string_view<charT, traits>, const Allocator& = Allocator())
    -> basic_string<charT, traits, Allocator>;

template<class charT,
         class traits,
         class Allocator = allocator<charT>>
  basic_string(basic_string_view<charT, traits>,
               typename @\seebelow@::size_type, typename @\seebelow@::size_type,
               const Allocator& = Allocator())
    -> basic_string<charT, traits, Allocator>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{Allocator} is a type that qualifies as
an allocator\iref{container.reqmts}.
\end{itemdescr}

\indexlibrarymember{operator=}{basic_string}%
\begin{itemdecl}
constexpr basic_string& operator=(const basic_string& str);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
If \tcode{*this} and \tcode{str} are the same object, has no effect.
Otherwise, replaces the value of \tcode{*this} with a copy of \tcode{str}.

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

\indexlibrarymember{operator=}{basic_string}%
\begin{itemdecl}
constexpr basic_string& operator=(basic_string&& str)
  noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
           allocator_traits<Allocator>::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Move assigns as a sequence container\iref{sequence.reqmts},
except that iterators, pointers and references may be invalidated.

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

\indexlibrarymember{operator=}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr basic_string& operator=(const T& t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item \tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>}
is \tcode{true} and
\item \tcode{is_convertible_v<const T\&, const charT*>}
is \tcode{false}.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string_view<charT, traits> sv = t;
return assign(sv);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator=}{basic_string}%
\begin{itemdecl}
constexpr basic_string& operator=(const charT* s);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return *this = basic_string_view<charT, traits>(s);}
\end{itemdescr}

\indexlibrarymember{operator=}{basic_string}%
\begin{itemdecl}
constexpr basic_string& operator=(charT c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return *this = basic_string_view<charT, traits>(addressof(c), 1);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator=}{basic_string}%
\begin{itemdecl}
constexpr basic_string& operator=(initializer_list<charT> il);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return *this = basic_string_view<charT, traits>(il.data(), il.size());
\end{codeblock}
\end{itemdescr}

\rSec3[string.iterators]{Iterator support}

\indexlibrarymember{begin}{basic_string}%
\indexlibrarymember{cbegin}{basic_string}%
\begin{itemdecl}
constexpr iterator       begin() noexcept;
constexpr const_iterator begin() const noexcept;
constexpr const_iterator cbegin() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An iterator referring to the first character in the string.
\end{itemdescr}

\indexlibrarymember{end}{basic_string}%
\indexlibrarymember{cend}{basic_string}%
\begin{itemdecl}
constexpr iterator       end() noexcept;
constexpr const_iterator end() const noexcept;
constexpr const_iterator cend() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An iterator which is the past-the-end value.
\end{itemdescr}

\indexlibrarymember{rbegin}{basic_string}%
\indexlibrarymember{crbegin}{basic_string}%
\begin{itemdecl}
constexpr reverse_iterator       rbegin() noexcept;
constexpr const_reverse_iterator rbegin() const noexcept;
constexpr const_reverse_iterator crbegin() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An iterator which is semantically equivalent to
\tcode{reverse_iterator(end())}.
\end{itemdescr}

\indexlibrarymember{rend}{basic_string}%
\indexlibrarymember{crend}{basic_string}%
\begin{itemdecl}
constexpr reverse_iterator       rend() noexcept;
constexpr const_reverse_iterator rend() const noexcept;
constexpr const_reverse_iterator crend() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An iterator which is semantically equivalent to
\tcode{reverse_iterator(begin())}.
\end{itemdescr}

\rSec3[string.capacity]{Capacity}

\indexlibrarymember{size}{basic_string}%
\indexlibrarymember{length}{basic_string}%
\begin{itemdecl}
constexpr size_type size() const noexcept;
constexpr size_type length() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A count of the number of char-like objects currently in the string.

\pnum
\complexity
Constant time.
\end{itemdescr}

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

\begin{itemdescr}
\pnum
\returns
The largest possible number of char-like objects that can be stored in a
\tcode{basic_string}.

\pnum
\complexity
Constant time.
\end{itemdescr}

\indexlibrarymember{resize}{basic_string}%
\begin{itemdecl}
constexpr void resize(size_type n, charT c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Alters the value of
\tcode{*this}
as follows:
\begin{itemize}
\item
If
\tcode{n <= size()},
erases the last \tcode{size() - n} elements.
\item
If
\tcode{n > size()},
appends \tcode{n - size()} copies of \tcode{c}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{resize}{basic_string}%
\begin{itemdecl}
constexpr void resize(size_type n);
\end{itemdecl}

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

\indexlibrarymember{resize_and_overwrite}{basic_string}%
\begin{itemdecl}
template<class Operation> constexpr void resize_and_overwrite(size_type n, Operation op);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let
\begin{itemize}
\item
\tcode{o = size()} before the call to \tcode{resize_and_overwrite}.
\item
\tcode{k} be \tcode{min(o, n)}.
\item
\tcode{p} be a value of type \tcode{charT*} or \tcode{charT* const},
such that the range \crange{p}{p + n} is valid and
\tcode{this->compare(0, k, p, k) == 0} is \tcode{true} before the call.
The values in the range \crange{p + k}{p + n} may be indeterminate\iref{basic.indet}.
\item
\tcode{m} be a value of type \tcode{size_type} or \tcode{const size_type}
equal to \tcode{n}.
\item
\tcode{\placeholder{OP}} be the expression \tcode{std::move(op)(p, m)}.
\item
\tcode{r} = \tcode{\placeholder{OP}}.
\end{itemize}

\pnum
\mandates
\tcode{\placeholder{OP}} has an integer-like type\iref{iterator.concept.winc}.

\pnum
\expects
\begin{itemize}
\item
\tcode{\placeholder{OP}} does not throw an exception or modify \tcode{p} or \tcode{m}.
\item
$\tcode{r} \geq 0$.
\item
$\tcode{r} \leq \tcode{m}$.
\item
After evaluating \tcode{\placeholder{OP}}
there are no indeterminate values in the range \range{p}{p + r}.
\end{itemize}

\pnum
\effects
Evaluates \tcode{\placeholder{OP}},
replaces the contents of \tcode{*this} with \range{p}{p + r}, and
invalidates all pointers and references to the range \crange{p}{p + n}.

\pnum
\recommended
Implementations should avoid unnecessary copies and allocations
by, for example, making \tcode{p} a pointer into internal storage and
by restoring \tcode{*(p + r)} to \tcode{charT()} after evaluating \tcode{\placeholder{OP}}.
\end{itemdescr}

\indexlibrarymember{capacity}{basic_string}%
\begin{itemdecl}
constexpr size_type capacity() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The size of the allocated storage in the string.

\pnum
\complexity
Constant time.
\end{itemdescr}

\indexlibrarymember{reserve}{basic_string}%
\begin{itemdecl}
constexpr void reserve(size_type res_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
A directive that informs a \tcode{basic_string} of a planned change in size,
so that the storage allocation can be managed accordingly.
Following a call to
\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}.

\pnum
\throws
\tcode{length_error}
if
\tcode{res_arg > max_size()} or any exceptions thrown by
\tcode{allocator_traits} \tcode{<Allocator>::allocate}.
\end{itemdescr}

\indexlibrarymember{shrink_to_fit}{basic_string}%
\begin{itemdecl}
constexpr void shrink_to_fit();
\end{itemdecl}

\begin{itemdescr}
\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.

\pnum
\complexity
If the size is not equal to the old capacity,
linear in the size of the sequence;
otherwise constant.

\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{clear}{basic_string}%
\begin{itemdecl}
constexpr void clear() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{erase(begin(), end());}
\end{itemdescr}

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

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return size() == 0;}
\end{itemdescr}

\rSec3[string.access]{Element access}

\indexlibrarymember{operator[]}{basic_string}%
\begin{itemdecl}
constexpr const_reference operator[](size_type pos) const;
constexpr reference       operator[](size_type pos);
\end{itemdecl}

\begin{itemdescr}
\pnum
\hardexpects
\tcode{pos <= size()} is \tcode{true}.

\pnum
\returns
\tcode{data()[pos]}.

\pnum
\throws
Nothing.

\pnum
\complexity
Constant time.
\end{itemdescr}

\indexlibrarymember{at}{basic_string}%
\begin{itemdecl}
constexpr const_reference at(size_type pos) const;
constexpr reference       at(size_type pos);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{operator[](pos)}.

\pnum
\throws
\tcode{out_of_range}
if
\tcode{pos >= size()}.
\end{itemdescr}

\indexlibrarymember{front}{basic_string}%
\begin{itemdecl}
constexpr const_reference front() const;
constexpr reference front();
\end{itemdecl}

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

\pnum
\effects
Equivalent to: \tcode{return operator[](0);}
\end{itemdescr}

\indexlibrarymember{back}{basic_string}%
\begin{itemdecl}
constexpr const_reference back() const;
constexpr reference back();
\end{itemdecl}

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

\pnum
\effects
Equivalent to: \tcode{return operator[](size() - 1);}
\end{itemdescr}

\rSec3[string.modifiers]{Modifiers}

\rSec4[string.op.append]{\tcode{basic_string::operator+=}}

\indexlibrarymember{operator+=}{basic_string}%
\begin{itemdecl}
constexpr basic_string& operator+=(const basic_string& str);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return append(str);}


\end{itemdescr}

\indexlibrarymember{operator+=}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr basic_string& operator+=(const T& t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string_view<charT, traits> sv = t;
return append(sv);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+=}{basic_string}%
\begin{itemdecl}
constexpr basic_string& operator+=(const charT* s);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return append(s);}
\end{itemdescr}

\indexlibrarymember{operator+=}{basic_string}%
\begin{itemdecl}
constexpr basic_string& operator+=(charT c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return append(size_type\{1\}, c);}
\end{itemdescr}

\indexlibrarymember{operator+=}{basic_string}%
\begin{itemdecl}
constexpr basic_string& operator+=(initializer_list<charT> il);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return append(il);}
\end{itemdescr}


\rSec4[string.append]{\tcode{basic_string::append}}

\indexlibrarymember{append}{basic_string}%
\begin{itemdecl}
constexpr basic_string& append(const basic_string& str);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return append(str.data(), str.size());}
\end{itemdescr}

\indexlibrarymember{append}{basic_string}%
\begin{itemdecl}
constexpr basic_string& append(const basic_string& str, size_type pos, size_type n = npos);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return append(basic_string_view<charT, traits>(str).substr(pos, n));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{append}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr basic_string& append(const T& t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string_view<charT, traits> sv = t;
return append(sv.data(), sv.size());
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{append}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr basic_string& append(const T& t, size_type pos, size_type n = npos);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string_view<charT, traits> sv = t;
return append(sv.substr(pos, n));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{append}{basic_string}%
\begin{itemdecl}
constexpr basic_string& append(const charT* s, size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\range{s}{s + n} is a valid range.

\pnum
\effects
Appends a copy of the range \range{s}{s + n} to the string.

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

\indexlibrarymember{append}{basic_string}%
\begin{itemdecl}
constexpr basic_string& append(const charT* s);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return append(s, traits::length(s));}
\end{itemdescr}

\indexlibrarymember{append}{basic_string}%
\begin{itemdecl}
constexpr basic_string& append(const charT* s, size_type pos, size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return append(basic_string_view<charT, traits>(s).substr(pos, n));}
\end{itemdescr}

\indexlibrarymember{append}{basic_string}%
\begin{itemdecl}
constexpr basic_string& append(size_type n, charT c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Appends \tcode{n} copies of \tcode{c} to the string.

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

\indexlibrarymember{append}{basic_string}%
\begin{itemdecl}
template<class InputIterator>
  constexpr basic_string& append(InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{InputIterator} is a type that qualifies as an input
iterator\iref{container.reqmts}.

\pnum
\effects
Equivalent to: \tcode{return append(basic_string(first, last, get_allocator()));}
\end{itemdescr}

\indexlibrarymember{append_range}{basic_string}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<charT> R>
  constexpr basic_string& append_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return append(basic_string(from_range, std::forward<R>(rg), get_allocator()));}
\end{itemdescr}

\indexlibrarymember{append}{basic_string}%
\begin{itemdecl}
constexpr basic_string& append(initializer_list<charT> il);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return append(il.data(), il.size());}
\end{itemdescr}

\indexlibrarymember{push_back}{basic_string}%
\begin{itemdecl}
constexpr void push_back(charT c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to
\tcode{append(size_type\{1\}, c)}.
\end{itemdescr}

\rSec4[string.assign]{\tcode{basic_string::assign}}

\indexlibrarymember{assign}{basic_string}%
\begin{itemdecl}
constexpr basic_string& assign(const basic_string& str);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *this = str;}
\end{itemdescr}

\indexlibrarymember{assign}{basic_string}%
\begin{itemdecl}
constexpr basic_string& assign(basic_string&& str)
  noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
           allocator_traits<Allocator>::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *this = std::move(str);}
\end{itemdescr}


\indexlibrarymember{assign}{basic_string}%
\begin{itemdecl}
constexpr basic_string& assign(const basic_string& str, size_type pos, size_type n = npos);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return assign(basic_string_view<charT, traits>(str).substr(pos, n));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{assign}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr basic_string& assign(const T& t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string_view<charT, traits> sv = t;
return assign(sv.data(), sv.size());
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{assign}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr basic_string& assign(const T& t, size_type pos, size_type n = npos);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string_view<charT, traits> sv = t;
return assign(sv.substr(pos, n));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{assign}{basic_string}%
\begin{itemdecl}
constexpr basic_string& assign(const charT* s, size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\range{s}{s + n} is a valid range.

\pnum
\effects
Replaces the string controlled by \tcode{*this} with
a copy of the range \range{s}{s + n}.

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

\indexlibrarymember{assign}{basic_string}%
\begin{itemdecl}
constexpr basic_string& assign(const charT* s);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return assign(s, traits::length(s));}
\end{itemdescr}

\indexlibrarymember{assign}{basic_string}%
\begin{itemdecl}
constexpr basic_string& assign(const charT* s, size_type pos, size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return assign(basic_string_view<charT, traits>(s).substr(pos, n));}
\end{itemdescr}

\indexlibrarymember{assign}{basic_string}%
\begin{itemdecl}
constexpr basic_string& assign(initializer_list<charT> il);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return assign(il.data(), il.size());}
\end{itemdescr}

\indexlibrarymember{assign}{basic_string}%
\begin{itemdecl}
constexpr basic_string& assign(size_type n, charT c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
clear();
resize(n, c);
return *this;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{assign}{basic_string}%
\begin{itemdecl}
template<class InputIterator>
  constexpr basic_string& assign(InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{InputIterator} is a type that qualifies as an input
iterator\iref{container.reqmts}.

\pnum
\effects
Equivalent to: \tcode{return assign(basic_string(first, last, get_allocator()));}
\end{itemdescr}

\indexlibrarymember{assign_range}{basic_string}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<charT> R>
  constexpr basic_string& assign_range(R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return assign(basic_string(from_range, std::forward<R>(rg), get_allocator()));}
\end{itemdescr}

\rSec4[string.insert]{\tcode{basic_string::insert}}

\indexlibrarymember{insert}{basic_string}%
\begin{itemdecl}
constexpr basic_string& insert(size_type pos, const basic_string& str);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return insert(pos, str.data(), str.size());}
\end{itemdescr}

\indexlibrarymember{insert}{basic_string}%
\begin{itemdecl}
constexpr basic_string& insert(size_type pos1, const basic_string& str,
                               size_type pos2, size_type n = npos);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return insert(pos1, basic_string_view<charT, traits>(str), pos2, n);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{insert}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr basic_string& insert(size_type pos, const T& t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string_view<charT, traits> sv = t;
return insert(pos, sv.data(), sv.size());
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{insert}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr basic_string& insert(size_type pos1, const T& t,
                                 size_type pos2, size_type n = npos);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string_view<charT, traits> sv = t;
return insert(pos1, sv.substr(pos2, n));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{insert}{basic_string}%
\begin{itemdecl}
constexpr basic_string& insert(size_type pos, const charT* s, size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\range{s}{s + n} is a valid range.

\pnum
\effects
Inserts a copy of the range \range{s}{s + n}
immediately before the character at position \tcode{pos} if \tcode{pos < size()},
or otherwise at the end of the string.

\pnum
\returns
\tcode{*this}.

\pnum
\throws
\begin{itemize}
\item \tcode{out_of_range} if \tcode{pos > size()},
\item \tcode{length_error} if \tcode{n > max_size() - size()}, or
\item any exceptions thrown by \tcode{allocator_traits<Allocator>::allocate}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{insert}{basic_string}%
\begin{itemdecl}
constexpr basic_string& insert(size_type pos, const charT* s);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return insert(pos, s, traits::length(s));}
\end{itemdescr}

\indexlibrarymember{insert}{basic_string}%
\begin{itemdecl}
constexpr basic_string& insert(size_type pos, size_type n, charT c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Inserts \tcode{n} copies of \tcode{c} before the character at position \tcode{pos}
if \tcode{pos < size()},
or otherwise at the end of the string.

\pnum
\returns
\tcode{*this}.

\pnum
\throws
\begin{itemize}
\item \tcode{out_of_range} if \tcode{pos > size()},
\item \tcode{length_error} if \tcode{n > max_size() - size()}, or
\item any exceptions thrown by \tcode{allocator_traits<Allocator>::allocate}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{insert}{basic_string}%
\begin{itemdecl}
constexpr iterator insert(const_iterator p, charT c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{p} is a valid iterator on
\tcode{*this}.

\pnum
\effects
Inserts a copy of \tcode{c} at the position \tcode{p}.

\pnum
\returns
An iterator which refers to the inserted character.
\end{itemdescr}

\indexlibrarymember{insert}{basic_string}%
\begin{itemdecl}
constexpr iterator insert(const_iterator p, size_type n, charT c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{p} is a valid iterator on
\tcode{*this}.

\pnum
\effects
Inserts \tcode{n} copies of \tcode{c} at the position \tcode{p}.

\pnum
\returns
An iterator which refers to  the first inserted character, or
\tcode{p} if \tcode{n == 0}.
\end{itemdescr}

\indexlibrarymember{insert}{basic_string}%
\begin{itemdecl}
template<class InputIterator>
  constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{InputIterator} is a type that qualifies as an input
iterator\iref{container.reqmts}.

\pnum
\expects
\tcode{p} is a valid iterator on
\tcode{*this}.

\pnum
\effects
Equivalent to
\tcode{insert(p - begin(), basic_string(first, last, get_allocator()))}.

\pnum
\returns
An iterator which refers to the first inserted character, or
\tcode{p} if \tcode{first == last}.
\end{itemdescr}

\indexlibrarymember{insert_range}{basic_string}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<charT> R>
  constexpr iterator insert_range(const_iterator p, R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{p} is a valid iterator on \tcode{*this}.

\pnum
\effects
Equivalent to
\tcode{insert(p - begin(), basic_string(from_range, std::forward<R>(rg), get_allocator()))}.

\pnum
\returns
An iterator which refers to the first inserted character, or
\tcode{p} if \tcode{rg} is empty.
\end{itemdescr}

\indexlibrarymember{insert}{basic_string}%
\begin{itemdecl}
constexpr iterator insert(const_iterator p, initializer_list<charT> il);
\end{itemdecl}

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

\rSec4[string.erase]{\tcode{basic_string::erase}}

\indexlibrarymember{erase}{basic_string}%
\begin{itemdecl}
constexpr basic_string& erase(size_type pos = 0, size_type n = npos);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Determines the effective length \tcode{xlen}
of the string to be removed as the smaller of \tcode{n} and
\tcode{size() - pos}.
Removes the characters in the range \range{begin() + pos}{begin() + pos + xlen}.

\pnum
\returns
\tcode{*this}.

\pnum
\throws
\tcode{out_of_range}
if \tcode{pos}
\tcode{> size()}.
\end{itemdescr}

\indexlibrarymember{erase}{basic_string}%
\begin{itemdecl}
constexpr iterator erase(const_iterator p);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{p} is a valid dereferenceable iterator on \tcode{*this}.

\pnum
\effects
Removes the character referred to by \tcode{p}.

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

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{erase}{basic_string}%
\begin{itemdecl}
constexpr iterator erase(const_iterator first, const_iterator last);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{first} and \tcode{last} are valid iterators on
\tcode{*this}. \range{first}{last} is a valid range.

\pnum
\effects
Removes the characters in the range
\range{first}{last}.

\pnum
\returns
An iterator which points to the element pointed to by \tcode{last} prior to
the other elements being erased.
If no such element exists,
\tcode{end()}
is returned.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{pop_back}{basic_string}%
\begin{itemdecl}
constexpr void pop_back();
\end{itemdecl}

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

\pnum
\effects
Equivalent to \tcode{erase(end() - 1)}.

\pnum
\throws
Nothing.
\end{itemdescr}

\rSec4[string.replace]{\tcode{basic_string::replace}}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return replace(pos1, n1, str.data(), str.size());}
\end{itemdescr}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str,
                                size_type pos2, size_type n2 = npos);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return replace(pos1, n1, basic_string_view<charT, traits>(str).substr(pos2, n2));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr basic_string& replace(size_type pos1, size_type n1, const T& t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string_view<charT, traits> sv = t;
return replace(pos1, n1, sv.data(), sv.size());
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr basic_string& replace(size_type pos1, size_type n1, const T& t,
                                  size_type pos2, size_type n2 = npos);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string_view<charT, traits> sv = t;
return replace(pos1, n1, sv.substr(pos2, n2));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
constexpr basic_string& replace(size_type pos1, size_type n1, const charT* s, size_type n2);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\range{s}{s + n2} is a valid range.

\pnum
\effects
Determines the effective length \tcode{xlen} of the string to be
removed as the smaller of \tcode{n1} and \tcode{size() - pos1}. If
\tcode{size() - xlen >= max_size() - n2} throws \tcode{length_error}. Otherwise,
the function replaces the characters in the range
\range{begin() + pos1}{begin() + pos1 + xlen}
with a copy of the range \range{s}{s + n2}.

\pnum
\returns
\tcode{*this}.

\pnum
\throws
\begin{itemize}
\item \tcode{out_of_range} if \tcode{pos1 > size()},
\item \tcode{length_error} if the length of the resulting string
would exceed \tcode{max_size()}, or
\item any exceptions thrown by \tcode{allocator_traits<Allocator>::allocate}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
constexpr basic_string& replace(size_type pos, size_type n, const charT* s);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return replace(pos, n, s, traits::length(s));}
\end{itemdescr}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
constexpr basic_string& replace(size_type pos1, size_type n1, size_type n2, charT c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Determines the effective length \tcode{xlen} of the string to be
removed as the smaller of \tcode{n1} and \tcode{size() - pos1}. If
\tcode{size() - xlen >=} \tcode{max_size() - n2} throws \tcode{length_error}. Otherwise,
the function replaces the characters in the range
\range{begin() + pos1}{begin() + pos1 + xlen}
with \tcode{n2} copies of \tcode{c}.

\pnum
\returns
\tcode{*this}.

\pnum
\throws
\begin{itemize}
\item \tcode{out_of_range} if \tcode{pos1 > size()},
\item \tcode{length_error} if the length of the resulting string
would exceed \tcode{max_size()}, or
\item any exceptions thrown by \tcode{allocator_traits<Allocator>::allocate.}
\end{itemize}
\end{itemdescr}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
constexpr basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return replace(i1, i2, basic_string_view<charT, traits>(str));}
\end{itemdescr}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr basic_string& replace(const_iterator i1, const_iterator i2, const T& t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\expects
\range{begin()}{i1} and \range{i1}{i2} are valid ranges.

\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string_view<charT, traits> sv = t;
return replace(i1 - begin(), i2 - i1, sv.data(), sv.size());
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s, size_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return replace(i1, i2, basic_string_view<charT, traits>(s, n));}
\end{itemdescr}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return replace(i1, i2, basic_string_view<charT, traits>(s));}
\end{itemdescr}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
constexpr basic_string& replace(const_iterator i1, const_iterator i2, size_type n, charT c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\range{begin()}{i1} and \range{i1}{i2} are valid ranges.

\pnum
\effects
Equivalent to: \tcode{return replace(i1 - begin(), i2 - i1, n, c);}
\end{itemdescr}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
template<class InputIterator>
  constexpr basic_string& replace(const_iterator i1, const_iterator i2,
                                  InputIterator j1, InputIterator j2);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{InputIterator} is a type that qualifies as an input
iterator\iref{container.reqmts}.

\pnum
\effects
Equivalent to: \tcode{return replace(i1, i2, basic_string(j1, j2, get_allocator()));}
\end{itemdescr}

\indexlibrarymember{replace_with_range}{basic_string}%
\begin{itemdecl}
template<@\exposconcept{container-compatible-range}@<charT> R>
  constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return replace(i1, i2, basic_string(from_range, std::forward<R>(rg), get_allocator()));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{replace}{basic_string}%
\begin{itemdecl}
constexpr basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<charT> il);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return replace(i1, i2, il.data(), il.size());}
\end{itemdescr}

\rSec4[string.copy]{\tcode{basic_string::copy}}

\indexlibrarymember{copy}{basic_string}%
\begin{itemdecl}
constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return basic_string_view<charT, traits>(*this).copy(s, n, pos);}
\begin{note}
This does not terminate \tcode{s} with a null object.
\end{note}
\end{itemdescr}

\rSec4[string.swap]{\tcode{basic_string::swap}}

\indexlibrarymember{swap}{basic_string}%
\begin{itemdecl}
constexpr void swap(basic_string& s)
  noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
           allocator_traits<Allocator>::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{allocator_traits<Allocator>::propagate_on_container_swap::value} is \tcode{true}
or
\tcode{get_allocator() == s.get_allocator()}.

\pnum
\ensures
\tcode{*this}
contains the same sequence of characters that was in \tcode{s},
\tcode{s} contains the same sequence of characters that was in
\tcode{*this}.

\pnum
\throws
Nothing.

\pnum
\complexity
Constant time.
\end{itemdescr}

\rSec3[string.ops]{String operations}

\rSec4[string.accessors]{Accessors}

\indexlibrarymember{c_str}{basic_string}%
\indexlibrarymember{data}{basic_string}%
\begin{itemdecl}
constexpr const charT* c_str() const noexcept;
constexpr const charT* data() const noexcept;
constexpr charT* data() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{to_address(begin())}.

\pnum
\complexity
Constant time.
\end{itemdescr}

\indexlibrarymember{operator basic_string_view}{basic_string}%
\begin{itemdecl}
constexpr operator basic_string_view<charT, traits>() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return basic_string_view<charT, traits>(data(), size());}
\end{itemdescr}

\indexlibrarymember{get_allocator}{basic_string}%
\begin{itemdecl}
constexpr allocator_type get_allocator() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A copy of the
\tcode{Allocator}
object used to construct the string or, if that allocator has been replaced, a
copy of the most recent replacement.
\end{itemdescr}

\rSec4[string.find]{Searching}

\pnum
\indexlibrarymember{find}{basic_string}%
\indexlibrarymember{rfind}{basic_string}%
\indexlibrarymember{find_first_of}{basic_string}%
\indexlibrarymember{find_last_of}{basic_string}%
\indexlibrarymember{find_first_not_of}{basic_string}%
\indexlibrarymember{find_last_not_of}{basic_string}%
Let \placeholder{F} be one of
\tcode{find}, \tcode{rfind}, \tcode{find_first_of}, \tcode{find_last_of},
\tcode{find_first_not_of}, and \tcode{find_last_not_of}.

\begin{itemize}
\item
Each member function of the form
\begin{codeblock}
constexpr size_type @\placeholder{F}@(const basic_string& str, size_type pos) const noexcept;
\end{codeblock}
has effects equivalent to:
\tcode{return \placeholder{F}(basic_string_view<charT, traits>(str), pos);}

\item
Each member function of the form
\begin{codeblock}
constexpr size_type @\placeholder{F}@(const charT* s, size_type pos) const;
\end{codeblock}
has effects equivalent to:
\tcode{return \placeholder{F}(basic_string_view<charT, traits>(s), pos);}

\item
Each member function of the form
\begin{codeblock}
constexpr size_type @\placeholder{F}@(const charT* s, size_type pos, size_type n) const;
\end{codeblock}
has effects equivalent to:
\tcode{return \placeholder{F}(basic_string_view<charT, traits>(s, n), pos);}

\item
Each member function of the form
\begin{codeblock}
constexpr size_type @\placeholder{F}@(charT c, size_type pos) const noexcept;
\end{codeblock}
has effects equivalent to:
\begin{codeblock}
return @\placeholder{F}@(basic_string_view<charT, traits>(addressof(c), 1), pos);
\end{codeblock}
\end{itemize}

\indexlibrarymember{find}{basic_string}%
\indexlibrarymember{rfind}{basic_string}%
\indexlibrarymember{find_first_of}{basic_string}%
\indexlibrarymember{find_last_of}{basic_string}%
\indexlibrarymember{find_first_not_of}{basic_string}%
\indexlibrarymember{find_last_not_of}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr size_type find(const T& t, size_type pos = 0) const noexcept(@\seebelow@);
template<class T>
  constexpr size_type rfind(const T& t, size_type pos = npos) const noexcept(@\seebelow@);
template<class T>
  constexpr size_type find_first_of(const T& t, size_type pos = 0) const noexcept(@\seebelow@);
template<class T>
  constexpr size_type find_last_of(const T& t, size_type pos = npos) const noexcept(@\seebelow@);
template<class T>
  constexpr size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept(@\seebelow@);
template<class T>
  constexpr size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept(@\seebelow@);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Let \placeholder{G} be the name of the function.
Equivalent to:
\begin{codeblock}
basic_string_view<charT, traits> s = *this, sv = t;
if (auto result = s.@\placeholder{G}@(sv, pos); result == s.npos) {
  return npos;
} else {
  return result;
}
\end{codeblock}

\pnum
\remarks
The exception specification is equivalent to
\tcode{is_nothrow_convertible_v<const T\&, basic_string_view<charT, traits>>}.
\end{itemdescr}

\rSec4[string.substr]{\tcode{basic_string::substr}}

\indexlibrarymember{substr}{basic_string}%
\begin{itemdecl}
constexpr basic_string substr(size_type pos = 0, size_type n = npos) const &;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return basic_string(*this, pos, n);}
\end{itemdescr}

\indexlibrarymember{substr}{basic_string}%
\begin{itemdecl}
constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return basic_string(std::move(*this), pos, n);}
\end{itemdescr}

\indexlibrarymember{subview}{basic_string}%
\begin{itemdecl}
constexpr basic_string_view<charT, traits> subview(size_type pos = 0, size_type n = npos) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return basic_string_view<charT, traits>(*this).subview(pos, n);}
\end{itemdescr}

\rSec4[string.compare]{\tcode{basic_string::compare}}

\indexlibrarymember{compare}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr int compare(const T& t) const noexcept(@\seebelow@);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Equivalent to: \tcode{return basic_string_view<charT, traits>(*this).compare(t);}

\pnum
\remarks
The exception specification is equivalent to
\tcode{is_nothrow_convertible_v<const T\&, basic_string_view<charT, traits>>}.
\end{itemdescr}

\indexlibrarymember{compare}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr int compare(size_type pos1, size_type n1, const T& t) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
return basic_string_view<charT, traits>(*this).substr(pos1, n1).compare(t);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{compare}{basic_string}%
\begin{itemdecl}
template<class T>
  constexpr int compare(size_type pos1, size_type n1, const T& t,
                        size_type pos2, size_type n2 = npos) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<const T\&, basic_string_view<charT, traits>>} is
\tcode{true} and
\item
\tcode{is_convertible_v<const T\&, const charT*>} is
\tcode{false}.
\end{itemize}

\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string_view<charT, traits> s = *this, sv = t;
return s.substr(pos1, n1).compare(sv.substr(pos2, n2));
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{compare}{basic_string}%
\begin{itemdecl}
constexpr int compare(const basic_string& str) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return compare(basic_string_view<charT, traits>(str));}
\end{itemdescr}

\indexlibrarymember{compare}{basic_string}%
\begin{itemdecl}
constexpr int compare(size_type pos1, size_type n1, const basic_string& str) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return compare(pos1, n1, basic_string_view<charT, traits>(str));}
\end{itemdescr}

\indexlibrarymember{compare}{basic_string}%
\begin{itemdecl}
constexpr int compare(size_type pos1, size_type n1, const basic_string& str,
                      size_type pos2, size_type n2 = npos) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return compare(pos1, n1, basic_string_view<charT, traits>(str), pos2, n2);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{compare}{basic_string}%
\begin{itemdecl}
constexpr int compare(const charT* s) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\tcode{return compare(basic_string_view<charT, traits>(s));}
\end{itemdescr}

\indexlibrarymember{compare}{basic_string}%
\begin{itemdecl}
constexpr int compare(size_type pos, size_type n1, const charT* s) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return compare(pos, n1, basic_string_view<charT, traits>(s));}
\end{itemdescr}

\indexlibrarymember{compare}{basic_string}%
\begin{itemdecl}
constexpr int compare(size_type pos, size_type n1, const charT* s, size_type n2) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return compare(pos, n1, basic_string_view<charT, traits>(s, n2));}
\end{itemdescr}

\rSec4[string.starts.with]{\tcode{basic_string::starts_with}}

\indexlibrarymember{starts_with}{basic_string}%
\begin{itemdecl}
constexpr bool starts_with(basic_string_view<charT, traits> x) const noexcept;
constexpr bool starts_with(charT x) const noexcept;
constexpr bool starts_with(const charT* x) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return basic_string_view<charT, traits>(data(), size()).starts_with(x);
\end{codeblock}
\end{itemdescr}

\rSec4[string.ends.with]{\tcode{basic_string::ends_with}}

\indexlibrarymember{ends_with}{basic_string}%
\begin{itemdecl}
constexpr bool ends_with(basic_string_view<charT, traits> x) const noexcept;
constexpr bool ends_with(charT x) const noexcept;
constexpr bool ends_with(const charT* x) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return basic_string_view<charT, traits>(data(), size()).ends_with(x);
\end{codeblock}
\end{itemdescr}

\rSec4[string.contains]{\tcode{basic_string::contains}}

\indexlibrarymember{contains}{basic_string}%
\begin{itemdecl}
constexpr bool contains(basic_string_view<charT, traits> x) const noexcept;
constexpr bool contains(charT x) const noexcept;
constexpr bool contains(const charT* x) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return basic_string_view<charT, traits>(data(), size()).contains(x);
\end{codeblock}
\end{itemdescr}

\rSec2[string.nonmembers]{Non-member functions}

\indexlibraryglobal{basic_string}

\rSec3[string.op.plus]{\tcode{operator+}}

\indexlibrarymember{operator+}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const basic_string<charT, traits, Allocator>& lhs,
              const basic_string<charT, traits, Allocator>& rhs);
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string<charT, traits, Allocator> r = lhs;
r.append(rhs);
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(basic_string<charT, traits, Allocator>&& lhs,
              const basic_string<charT, traits, Allocator>& rhs);
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(basic_string<charT, traits, Allocator>&& lhs, const charT* rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
lhs.append(rhs);
return std::move(lhs);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(basic_string<charT, traits, Allocator>&& lhs,
              basic_string<charT, traits, Allocator>&& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
lhs.append(rhs);
return std::move(lhs);
\end{codeblock}
except that both \tcode{lhs} and \tcode{rhs}
are left in valid but unspecified states.
\begin{note}
If \tcode{lhs} and \tcode{rhs} have equal allocators,
the implementation can move from either.
\end{note}
\end{itemdescr}

\indexlibrarymember{operator+}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const basic_string<charT, traits, Allocator>& lhs,
              basic_string<charT, traits, Allocator>&& rhs);
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const charT* lhs, basic_string<charT, traits, Allocator>&& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
rhs.insert(0, lhs);
return std::move(rhs);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string<charT, traits, Allocator> r = rhs;
r.insert(0, lhs);
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(charT lhs, const basic_string<charT, traits, Allocator>& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string<charT, traits, Allocator> r = rhs;
r.insert(r.begin(), lhs);
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(charT lhs, basic_string<charT, traits, Allocator>&& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
rhs.insert(rhs.begin(), lhs);
return std::move(rhs);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const basic_string<charT, traits, Allocator>& lhs, charT rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
basic_string<charT, traits, Allocator> r = lhs;
r.push_back(rhs);
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(basic_string<charT, traits, Allocator>&& lhs, charT rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
lhs.push_back(rhs);
return std::move(lhs);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const basic_string<charT, traits, Allocator>& lhs,
              type_identity_t<basic_string_view<charT, traits>> rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
Equivalent to:
\begin{codeblock}
basic_string<charT, traits, Allocator> r = lhs;
r.append(rhs);
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(basic_string<charT, traits, Allocator>&& lhs,
              type_identity_t<basic_string_view<charT, traits>> rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
Equivalent to:
\begin{codeblock}
lhs.append(rhs);
return std::move(lhs);
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(type_identity_t<basic_string_view<charT, traits>> lhs,
              const basic_string<charT, traits, Allocator>& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
Equivalent to:
\begin{codeblock}
basic_string<charT, traits, Allocator> r = rhs;
r.insert(0, lhs);
return r;
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator+}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(type_identity_t<basic_string_view<charT, traits>> lhs,
              basic_string<charT, traits, Allocator>&& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
Equivalent to:
\begin{codeblock}
rhs.insert(0, lhs);
return std::move(rhs);
\end{codeblock}
\end{itemdescr}

\pnum
\begin{note}
Using a specialization of \tcode{type_identity_t} as a parameter type ensures
that an object of type \tcode{basic_string<charT, traits, Allocator>}
can be concatenated with an object of a type \tcode{T}
having an implicit conversion to
\tcode{basic_string_view<charT, traits>}\iref{over.match.oper}.
\end{note}

\rSec3[string.cmp]{Non-member comparison operator functions}
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr bool
    operator==(const basic_string<charT, traits, Allocator>& lhs,
               const basic_string<charT, traits, Allocator>& rhs) noexcept;
template<class charT, class traits, class Allocator>
  constexpr bool operator==(const basic_string<charT, traits, Allocator>& lhs,
                            const charT* rhs);

template<class charT, class traits, class Allocator>
  constexpr @\seebelow@ operator<=>(const basic_string<charT, traits, Allocator>& lhs,
            @\itcorr@                      const basic_string<charT, traits, Allocator>& rhs) noexcept;
template<class charT, class traits, class Allocator>
  constexpr @\seebelow@ operator<=>(const basic_string<charT, traits, Allocator>& lhs,
            @\itcorr@                      const charT* rhs);
\end{itemdecl}
\begin{itemdescr}
\pnum
\effects
Let \tcode{\placeholder{op}} be the operator.
Equivalent to:
\begin{codeblock}
return basic_string_view<charT, traits>(lhs) @\placeholder{op}@ basic_string_view<charT, traits>(rhs);
\end{codeblock}
\end{itemdescr}

\rSec3[string.special]{\tcode{swap}}

\indexlibrarymember{swap}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  constexpr void
    swap(basic_string<charT, traits, Allocator>& lhs,
         basic_string<charT, traits, Allocator>& rhs)
      noexcept(noexcept(lhs.swap(rhs)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{lhs.swap(rhs)}.
\end{itemdescr}

\rSec3[string.io]{Inserters and extractors}

\indexlibrarymember{operator>>}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  basic_istream<charT, traits>&
    operator>>(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Behaves as a formatted input function\iref{istream.formatted.reqmts}.
After constructing a \tcode{sentry} object,
if the \tcode{sentry} object returns \tcode{true}
when converted to a value of type \tcode{bool},
calls \tcode{str.erase()}
and then extracts characters from \tcode{is} and appends them
to \tcode{str} as if by calling
\tcode{str.append(1, c)}.
If
\tcode{is.width()}
is greater than zero, the maximum
number \tcode{n} of characters appended is
\tcode{is.width()};
otherwise \tcode{n} is
\tcode{str.max_size()}.
Characters are extracted and appended until any of the following
occurs:
\begin{itemize}
\item
\textit{n}
characters are stored;
\item
end-of-file occurs on the input sequence;
\item
\tcode{isspace(c, is.getloc())}
is \tcode{true} for the next available input character
\textit{c}.
\end{itemize}

\pnum
After the last character (if any) is extracted,
\tcode{is.width(0)}
is called and the
\tcode{sentry}
object is destroyed.

\pnum
If the function extracts no characters,
\tcode{ios_base::failbit} is set in the input function's local error state
before \tcode{setstate} is called.

\pnum
\returns
\tcode{is}.
\end{itemdescr}

\indexlibrarymember{operator<<}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  basic_ostream<charT, traits>&
    operator<<(basic_ostream<charT, traits>& os,
               const basic_string<charT, traits, Allocator>& str);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return os << basic_string_view<charT, traits>(str);}
\end{itemdescr}

\indexlibrarymember{getline}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  basic_istream<charT, traits>&
    getline(basic_istream<charT, traits>& is,
            basic_string<charT, traits, Allocator>& str,
            charT delim);
template<class charT, class traits, class Allocator>
  basic_istream<charT, traits>&
    getline(basic_istream<charT, traits>&& is,
            basic_string<charT, traits, Allocator>& str,
            charT delim);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Behaves as an unformatted input function\iref{istream.unformatted},
except that it does not affect the value returned by subsequent calls to
\tcode{basic_istream<>::gcount()}.
After constructing a \tcode{sentry} object,
if the \tcode{sentry} object returns \tcode{true}
when converted to a value of type \tcode{bool},
calls \tcode{str.erase()}
and then extracts characters from \tcode{is} and appends them
to \tcode{str} as if by calling
\tcode{str.append(1, c)}
until any of the following occurs:
\begin{itemize}
\item
end-of-file occurs on the input sequence;
\item
\tcode{traits::eq(c, delim)}
for the next available input character
\textit{c}
(in which case,
\textit{c}
is extracted but not appended);
\item
\tcode{str.max_size()}
characters are stored
(in which case,
\tcode{ios_base::failbit} is set in the input function's local error state).
\end{itemize}

\pnum
The conditions are tested in the order shown.
In any case,
after the last character is extracted, the
\tcode{sentry}
object is destroyed.

\pnum
If the function extracts no characters,
\tcode{ios_base::failbit} is set in the input function's local error state
before \tcode{setstate} is called.

\pnum
\returns
\tcode{is}.
\end{itemdescr}

\indexlibrarymember{getline}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator>
  basic_istream<charT, traits>&
    getline(basic_istream<charT, traits>& is,
            basic_string<charT, traits, Allocator>& str);
template<class charT, class traits, class Allocator>
  basic_istream<charT, traits>&
    getline(basic_istream<charT, traits>&& is,
            basic_string<charT, traits, Allocator>& str);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{getline(is, str, is.widen('\textbackslash n'))}.
\end{itemdescr}

\rSec3[string.erasure]{Erasure}

\indexlibrarymember{erase}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator, class U = charT>
  constexpr typename basic_string<charT, traits, Allocator>::size_type
    erase(basic_string<charT, traits, 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}{basic_string}%
\begin{itemdecl}
template<class charT, class traits, class Allocator, class Predicate>
  constexpr typename basic_string<charT, traits, Allocator>::size_type
    erase_if(basic_string<charT, traits, 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[string.conversions]{Numeric conversions}

\indexlibraryglobal{stoi}%
\indexlibraryglobal{stol}%
\indexlibraryglobal{stoul}%
\indexlibraryglobal{stoll}%
\indexlibraryglobal{stoull}%
\begin{itemdecl}
int stoi(const string& str, size_t* idx = nullptr, int base = 10);
long stol(const string& str, size_t* idx = nullptr, int base = 10);
unsigned long stoul(const string& str, size_t* idx = nullptr, int base = 10);
long long stoll(const string& str, size_t* idx = nullptr, int base = 10);
unsigned long long stoull(const string& str, size_t* idx = nullptr, int base = 10);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
The first two functions call \tcode{strtol(str.c_str(), ptr, base)},
and the last three functions call \tcode{strtoul(str.c_str(), ptr, base)},
\tcode{strtoll(str.c_str(), ptr, base)}, and \tcode{strtoull(\brk{}str.c_str(), ptr,
base)}, respectively. Each function returns the converted result, if any. The
argument \tcode{ptr} designates a pointer to an object internal to the function
that is used to determine what to store at \tcode{*idx}. If the function does
not throw an exception and \tcode{idx != nullptr}, the function stores in \tcode{*idx}
the index of the first unconverted element of \tcode{str}.

\pnum
\returns
The converted result.

\pnum
\throws
\tcode{invalid_argument} if \tcode{strtol}, \tcode{strtoul},
\tcode{strtoll}, or \tcode{strtoull} reports that no conversion can be
performed. Throws \tcode{out_of_range} if \tcode{strtol}, \tcode{strtoul},
\tcode{strtoll} or \tcode{strtoull} sets \tcode{errno} to \tcode{ERANGE},
or if the converted value is outside the range of representable values
for the return type.
\end{itemdescr}

\indexlibraryglobal{stof}%
\indexlibraryglobal{stod}%
\indexlibraryglobal{stold}%
\begin{itemdecl}
float stof(const string& str, size_t* idx = nullptr);
double stod(const string& str, size_t* idx = nullptr);
long double stold(const string& str, size_t* idx = nullptr);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions call
\tcode{strtof(str.c_str(), ptr)}, \tcode{strtod(str.c_str(), ptr)}, and
\tcode{strtold(\brk{}str.c_str(), ptr)}, respectively. Each function returns
the converted result, if any. The argument \tcode{ptr} designates a pointer to
an object internal to the function that is used to determine what to store at
\tcode{*idx}. If the function does not throw an exception and \tcode{idx != nullptr},
the function stores in \tcode{*idx} the index of the first unconverted element
of \tcode{str}.

\pnum
\returns
The converted result.

\pnum
\throws
\tcode{invalid_argument} if \tcode{strtof}, \tcode{strtod}, or
\tcode{strtold} reports that no conversion can be performed. Throws
\tcode{out_of_range} if \tcode{strtof}, \tcode{strtod}, or
\tcode{strtold} sets \tcode{errno} to \tcode{ERANGE}
or if the converted value is outside the range of representable
values for the return type.
\end{itemdescr}

\indexlibraryglobal{to_string}%
\begin{itemdecl}
constexpr string to_string(int val);
constexpr string to_string(unsigned val);
constexpr string to_string(long val);
constexpr string to_string(unsigned long val);
constexpr string to_string(long long val);
constexpr string to_string(unsigned long long val);
string to_string(float val);
string to_string(double val);
string to_string(long double val);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{format("\{\}", val)}.
\end{itemdescr}

\indexlibraryglobal{stoi}%
\indexlibraryglobal{stol}%
\indexlibraryglobal{stoul}%
\indexlibraryglobal{stoll}%
\indexlibraryglobal{stoull}%
\begin{itemdecl}
int stoi(const wstring& str, size_t* idx = nullptr, int base = 10);
long stol(const wstring& str, size_t* idx = nullptr, int base = 10);
unsigned long stoul(const wstring& str, size_t* idx = nullptr, int base = 10);
long long stoll(const wstring& str, size_t* idx = nullptr, int base = 10);
unsigned long long stoull(const wstring& str, size_t* idx = nullptr, int base = 10);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
The first two functions call \tcode{wcstol(str.c_str(), ptr, base)},
and the last three functions call \tcode{wcstoul(str.c_str(), ptr, base)},
\tcode{wcstoll(str.c_str(), ptr, base)}, and \tcode{wcstoull(\brk{}str.c_str(), ptr,
base)}, respectively. Each function returns the converted result, if any. The
argument \tcode{ptr} designates a pointer to an object internal to the function
that is used to determine what to store at \tcode{*idx}. If the function does
not throw an exception and \tcode{idx != nullptr}, the function stores in \tcode{*idx}
the index of the first unconverted element of \tcode{str}.

\pnum
\returns
The converted result.

\pnum
\throws
\tcode{invalid_argument} if \tcode{wcstol}, \tcode{wcstoul}, \tcode{wcstoll}, or
\tcode{wcstoull} reports that no conversion can be performed. Throws
\tcode{out_of_range} if the converted value is outside the range of representable values
for the return type.
\end{itemdescr}

\indexlibraryglobal{stof}%
\indexlibraryglobal{stod}%
\indexlibraryglobal{stold}%
\begin{itemdecl}
float stof(const wstring& str, size_t* idx = nullptr);
double stod(const wstring& str, size_t* idx = nullptr);
long double stold(const wstring& str, size_t* idx = nullptr);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions call \tcode{wcstof(str.c_str(), ptr)},
\tcode{wcstod(str.c_str(), ptr)}, and \tcode{wcstold(\brk{}str.c_str(), ptr)},
respectively. Each function returns the converted
result, if any. The argument \tcode{ptr} designates a pointer to an object internal to
the function that is used to determine what to store at \tcode{*idx}. If the function
does not throw an exception and \tcode{idx != nullptr}, the function stores in \tcode{*idx}
the index of the first unconverted element of \tcode{str}.

\pnum
\returns
The converted result.

\pnum
\throws
\tcode{invalid_argument} if \tcode{wcstof}, \tcode{wcstod}, or \tcode{wcstold} reports that no
conversion can be performed. Throws \tcode{out_of_range} if \tcode{wcstof}, \tcode{wcstod}, or
\tcode{wcstold} sets \tcode{errno} to \tcode{ERANGE}.
\end{itemdescr}

\indexlibraryglobal{to_wstring}%
\begin{itemdecl}
constexpr wstring to_wstring(int val);
constexpr wstring to_wstring(unsigned val);
constexpr wstring to_wstring(long val);
constexpr wstring to_wstring(unsigned long val);
constexpr wstring to_wstring(long long val);
constexpr wstring to_wstring(unsigned long long val);
wstring to_wstring(float val);
wstring to_wstring(double val);
wstring to_wstring(long double val);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{format(L"\{\}", val)}.
\end{itemdescr}

\rSec2[basic.string.hash]{Hash support}

\indexlibrarymember{hash}{basic_string}%
\indexlibrarymember{hash}{string}%
\indexlibrarymember{hash}{u8string}%
\indexlibrarymember{hash}{u16string}%
\indexlibrarymember{hash}{u32string}%
\indexlibrarymember{hash}{wstring}%
\begin{itemdecl}
template<class A> struct hash<basic_string<char, char_traits<char>, A>>;
template<class A> struct hash<basic_string<char8_t, char_traits<char8_t>, A>>;
template<class A> struct hash<basic_string<char16_t, char_traits<char16_t>, A>>;
template<class A> struct hash<basic_string<char32_t, char_traits<char32_t>, A>>;
template<class A> struct hash<basic_string<wchar_t, char_traits<wchar_t>, A>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
If \tcode{S} is one of these string types,
\tcode{SV} is the corresponding string view type, and
\tcode{s} is an object of type \tcode{S},
then \tcode{hash<S>()(s) == hash<SV>()(SV(s))}.
\end{itemdescr}

\rSec2[basic.string.literals]{Suffix for \tcode{basic_string} literals}

\indexlibrarymember{operator""""s}{string}%
\begin{itemdecl}
constexpr string operator""s(const char* str, size_t len);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{string\{str, len\}}.
\end{itemdescr}

\indexlibrarymember{operator""""s}{u8string}%
\begin{itemdecl}
constexpr u8string operator""s(const char8_t* str, size_t len);
\end{itemdecl}
\begin{itemdescr}
\pnum
\returns
\tcode{u8string\{str, len\}}.
\end{itemdescr}

\indexlibrarymember{operator""""s}{u16string}%
\begin{itemdecl}
constexpr u16string operator""s(const char16_t* str, size_t len);
\end{itemdecl}
\begin{itemdescr}
\pnum
\returns
\tcode{u16string\{str, len\}}.
\end{itemdescr}

\indexlibrarymember{operator""""s}{u32string}%
\begin{itemdecl}
constexpr u32string operator""s(const char32_t* str, size_t len);
\end{itemdecl}
\begin{itemdescr}
\pnum
\returns
\tcode{u32string\{str, len\}}.
\end{itemdescr}

\indexlibrarymember{operator""""s}{wstring}%
\begin{itemdecl}
constexpr wstring operator""s(const wchar_t* str, size_t len);
\end{itemdecl}
\begin{itemdescr}
\pnum
\returns
\tcode{wstring\{str, len\}}.
\end{itemdescr}

\pnum
\begin{note}
The same suffix \tcode{s} is used for \tcode{chrono::duration} literals denoting seconds but there is no conflict, since duration suffixes apply to numbers and string literal suffixes apply to character array literals.
\end{note}

\rSec1[c.strings]{Null-terminated sequence utilities}

\rSec2[cstring.syn]{Header \tcode{<cstring>} synopsis}

\indexlibraryglobal{memchr}%
\indexlibraryglobal{memcmp}%
\indexlibraryglobal{memcpy}%
\indexlibraryglobal{memmove}%
\indexlibraryglobal{memset}%
\indexlibraryglobal{size_t}%
\indexlibraryglobal{strcat}%
\indexlibraryglobal{strchr}%
\indexlibraryglobal{strcmp}%
\indexlibraryglobal{strcoll}%
\indexlibraryglobal{strcpy}%
\indexlibraryglobal{strcspn}%
\indexlibraryglobal{strerror}%
\indexlibraryglobal{strlen}%
\indexlibraryglobal{strncat}%
\indexlibraryglobal{strncmp}%
\indexlibraryglobal{strncpy}%
\indexlibraryglobal{strpbrk}%
\indexlibraryglobal{strrchr}%
\indexlibraryglobal{strspn}%
\indexlibraryglobal{strstr}%
\indexlibraryglobal{strtok}%
\indexlibraryglobal{strxfrm}%
\begin{codeblock}
#define __STDC_VERSION_STRING_H__ 202311L

namespace std {
  using size_t = @\textit{see \ref{support.types.layout}}@;                                            // freestanding

  void* memcpy(void* s1, const void* s2, size_t n);                     // freestanding
  void* memccpy(void* s1, const void* s2, int c, size_t n);             // freestanding
  void* memmove(void* s1, const void* s2, size_t n);                    // freestanding
  char* strcpy(char* s1, const char* s2);                               // freestanding
  char* strncpy(char* s1, const char* s2, size_t n);                    // freestanding
  char* strdup(const char* s);
  char* strndup(const char* s, size_t size);
  char* strcat(char* s1, const char* s2);                               // freestanding
  char* strncat(char* s1, const char* s2, size_t n);                    // freestanding
  int memcmp(const void* s1, const void* s2, size_t n);                 // freestanding
  int strcmp(const char* s1, const char* s2);                           // freestanding
  int strcoll(const char* s1, const char* s2);
  int strncmp(const char* s1, const char* s2, size_t n);                // freestanding
  size_t strxfrm(char* s1, const char* s2, size_t n);
  const void* memchr(const void* s, int c, size_t n);                   // freestanding; see \ref{library.c}
  void* memchr(void* s, int c, size_t n);                               // freestanding; see \ref{library.c}
  const char* strchr(const char* s, int c);                             // freestanding; see \ref{library.c}
  char* strchr(char* s, int c);                                         // freestanding; see \ref{library.c}
  size_t strcspn(const char* s1, const char* s2);                       // freestanding
  const char* strpbrk(const char* s1, const char* s2);                  // freestanding; see \ref{library.c}
  char* strpbrk(char* s1, const char* s2);                              // freestanding; see \ref{library.c}
  const char* strrchr(const char* s, int c);                            // freestanding; see \ref{library.c}
  char* strrchr(char* s, int c);                                        // freestanding; see \ref{library.c}
  size_t strspn(const char* s1, const char* s2);                        // freestanding
  const char* strstr(const char* s1, const char* s2);                   // freestanding; see \ref{library.c}
  char* strstr(char* s1, const char* s2);                               // freestanding; see \ref{library.c}
  char* strtok(char* s1, const char* s2);
  void* memset(void* s, int c, size_t n);                               // freestanding
  void* memset_explicit(void* s, int c, size_t n);                      // freestanding
  char* strerror(int errnum);
  size_t strlen(const char* s);                                         // freestanding
}

#define NULL @\textit{see \ref{support.types.nullptr}}@                                                // freestanding
\end{codeblock}

\pnum
The contents and meaning of the header \libheaderdef{cstring}
are the same as the C standard library header \libheader{string.h}.

\pnum
The functions \tcode{strerror} and \tcode{strtok} are not required to avoid data
races\iref{res.on.data.races}.

\pnum
\indextext{signal-safe!\idxcode{memcpy}}%
\indextext{signal-safe!\idxcode{memmove}}%
The functions \tcode{memcpy} and \tcode{memmove} are signal-safe\iref{support.signal}.
Each of these functions implicitly creates objects\iref{intro.object}
in the destination region of storage
immediately prior to copying the sequence of characters to the destination.
Each of these functions returns a pointer to a suitable created object, if any,
otherwise the value of the first parameter.

\pnum
\begin{note}
The functions
\tcode{strchr}, \tcode{strpbrk}, \tcode{strrchr}, \tcode{strstr}, and \tcode{memchr},
have different signatures in this document,
but they have the same behavior as in the C standard library\iref{library.c}.
\end{note}

\xrefc{7.26}
