%!TEX root = std.tex
\rSec0[diagnostics]{Diagnostics library}

\rSec1[diagnostics.general]{General}

\pnum
This Clause describes components that \Cpp{} programs may use to detect and
report error conditions.

\pnum
The following subclauses describe components for
reporting several kinds of exceptional conditions,
documenting program assertions,
obtaining stacktraces, and
a global variable for error number codes,
as summarized in \tref{diagnostics.summary}.

\begin{libsumtab}{Diagnostics library summary}{diagnostics.summary}
\ref{std.exceptions}  & Exception classes     &   \tcode{<stdexcept>}     \\ \rowsep
\ref{assertions}      & Assertions            &   \tcode{<cassert>}       \\ \rowsep
\ref{errno}           & Error numbers         &   \tcode{<cerrno>}        \\ \rowsep
\ref{syserr}          & System error support  &   \tcode{<system_error>}  \\ \rowsep
\ref{stacktrace}      & Stacktrace            &   \tcode{<stacktrace>}    \\ \rowsep
\ref{debugging}       & Debugging             & \tcode{<debugging>}       \\
\end{libsumtab}

\rSec1[std.exceptions]{Exception classes}

\rSec2[std.exceptions.general]{General}

\pnum
The \Cpp{} standard library provides classes to be used to report certain errors\iref{res.on.exception.handling} in
\Cpp{} programs.
In the error model reflected in these classes, errors are divided into two
broad categories:
\term{logic}
errors and
\term{runtime}
errors.

\pnum
The distinguishing characteristic of logic errors is that they are due to errors
in the internal logic of the program.
In theory, they are preventable.

\pnum
By contrast, runtime errors are due to events beyond the scope of the program.
They cannot be easily predicted in advance.
The header \libheaderdef{stdexcept}
defines several types of predefined exceptions for reporting errors in a \Cpp{} program.
These exceptions are related by inheritance.

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

\indexlibraryglobal{logic_error}%
\indexlibraryglobal{domain_error}%
\indexlibraryglobal{invalid_argument}%
\indexlibraryglobal{length_error}%
\indexlibraryglobal{out_of_range}%
\indexlibraryglobal{runtime_error}%
\indexlibraryglobal{range_error}%
\indexlibraryglobal{overflow_error}%
\indexlibraryglobal{underflow_error}%
\begin{codeblock}
namespace std {
  class logic_error;
    class domain_error;
    class invalid_argument;
    class length_error;
    class out_of_range;
  class runtime_error;
    class range_error;
    class overflow_error;
    class underflow_error;
}
\end{codeblock}

\rSec2[logic.error]{Class \tcode{logic_error}}

\indexlibraryglobal{logic_error}%
\begin{codeblock}
namespace std {
  class logic_error : public exception {
  public:
    constexpr explicit logic_error(const string& what_arg);
    constexpr explicit logic_error(const char* what_arg);
  };
}
\end{codeblock}

\pnum
The class
\tcode{logic_error}
defines the type of objects thrown as
exceptions to report errors presumably detectable before
the program executes, such as violations of logical preconditions or class
invariants.

\indexlibraryctor{logic_error}%
\begin{itemdecl}
constexpr logic_error(const string& what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg.c_str()) == 0}.
\end{itemdescr}

\indexlibraryctor{logic_error}%
\begin{itemdecl}
constexpr logic_error(const char* what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg) == 0}.
\end{itemdescr}

\rSec2[domain.error]{Class \tcode{domain_error}}

\indexlibraryglobal{domain_error}%
\begin{codeblock}
namespace std {
  class domain_error : public logic_error {
  public:
    constexpr explicit domain_error(const string& what_arg);
    constexpr explicit domain_error(const char* what_arg);
  };
}
\end{codeblock}

\pnum
The class
\tcode{domain_error}
defines the type of objects thrown as
exceptions by the implementation to report domain errors.

\indexlibraryctor{domain_error}%
\begin{itemdecl}
constexpr domain_error(const string& what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg.c_str()) == 0}.
\end{itemdescr}

\indexlibraryctor{domain_error}%
\begin{itemdecl}
constexpr domain_error(const char* what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg) == 0}.
\end{itemdescr}

\rSec2[invalid.argument]{Class \tcode{invalid_argument}}

\indexlibraryglobal{invalid_argument}%
\begin{codeblock}
namespace std {
  class invalid_argument : public logic_error {
  public:
    constexpr explicit invalid_argument(const string& what_arg);
    constexpr explicit invalid_argument(const char* what_arg);
  };
}
\end{codeblock}

\pnum
The class
\tcode{invalid_argument}
defines the type of objects thrown as exceptions to report an invalid argument.

\indexlibraryctor{invalid_argument}%
\begin{itemdecl}
constexpr invalid_argument(const string& what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg.c_str()) == 0}.
\end{itemdescr}

\indexlibraryctor{invalid_argument}%
\begin{itemdecl}
constexpr invalid_argument(const char* what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg) == 0}.
\end{itemdescr}

\rSec2[length.error]{Class \tcode{length_error}}

\indexlibraryglobal{length_error}%
\begin{codeblock}
namespace std {
  class length_error : public logic_error {
  public:
    constexpr explicit length_error(const string& what_arg);
    constexpr explicit length_error(const char* what_arg);
  };
}
\end{codeblock}

\pnum
The class
\tcode{length_error}
defines the type of objects thrown as exceptions
to report an attempt to produce
an object whose length exceeds its maximum allowable size.

\indexlibraryctor{length_error}%
\begin{itemdecl}
constexpr length_error(const string& what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg.c_str()) == 0}.
\end{itemdescr}

\indexlibraryctor{length_error}%
\begin{itemdecl}
constexpr length_error(const char* what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg) == 0}.
\end{itemdescr}

\rSec2[out.of.range]{Class \tcode{out_of_range}}

\indexlibraryglobal{out_of_range}%
\begin{codeblock}
namespace std {
  class out_of_range : public logic_error {
  public:
    constexpr explicit out_of_range(const string& what_arg);
    constexpr explicit out_of_range(const char* what_arg);
  };
}
\end{codeblock}

\pnum
The class
\tcode{out_of_range}
defines the type of objects thrown as exceptions to report an
argument value not in its expected range.
\indextext{argument}

\indexlibraryctor{out_of_range}%
\begin{itemdecl}
constexpr out_of_range(const string& what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg.c_str()) == 0}.
\end{itemdescr}

\indexlibraryctor{out_of_range}%
\begin{itemdecl}
constexpr out_of_range(const char* what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg) == 0}.
\end{itemdescr}

\rSec2[runtime.error]{Class \tcode{runtime_error}}

\indexlibraryglobal{runtime_error}%
\begin{codeblock}
namespace std {
  class runtime_error : public exception {
  public:
    constexpr explicit runtime_error(const string& what_arg);
    constexpr explicit runtime_error(const char* what_arg);
  };
}
\end{codeblock}

\pnum
The class
\tcode{runtime_error}
defines the type of objects thrown as exceptions to report errors presumably detectable only
when the program executes.

\indexlibraryctor{runtime_error}%
\begin{itemdecl}
constexpr runtime_error(const string& what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg.c_str()) == 0}.
\end{itemdescr}

\indexlibraryctor{runtime_error}%
\begin{itemdecl}
constexpr runtime_error(const char* what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg) == 0}.
\end{itemdescr}

\rSec2[range.error]{Class \tcode{range_error}}

\indexlibraryglobal{range_error}%
\begin{codeblock}
namespace std {
  class range_error : public runtime_error {
  public:
    constexpr explicit range_error(const string& what_arg);
    constexpr explicit range_error(const char* what_arg);
  };
}
\end{codeblock}

\pnum
The class
\tcode{range_error}
defines the type of objects thrown as exceptions to report range errors
in internal computations.

\indexlibraryctor{range_error}%
\begin{itemdecl}
constexpr range_error(const string& what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg.c_str()) == 0}.
\end{itemdescr}

\indexlibraryctor{range_error}%
\begin{itemdecl}
constexpr range_error(const char* what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg) == 0}.
\end{itemdescr}

\rSec2[overflow.error]{Class \tcode{overflow_error}}

\indexlibraryglobal{overflow_error}%
\begin{codeblock}
namespace std {
  class overflow_error : public runtime_error {
  public:
    constexpr explicit overflow_error(const string& what_arg);
    constexpr explicit overflow_error(const char* what_arg);
  };
}
\end{codeblock}

\pnum
The class
\tcode{overflow_error}
defines the type of objects thrown as exceptions to report an arithmetic overflow error.

\indexlibraryctor{overflow_error}%
\begin{itemdecl}
constexpr overflow_error(const string& what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg.c_str()) == 0}.
\end{itemdescr}

\indexlibraryctor{overflow_error}%
\begin{itemdecl}
constexpr overflow_error(const char* what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg) == 0}.
\end{itemdescr}

\rSec2[underflow.error]{Class \tcode{underflow_error}}

\indexlibraryglobal{underflow_error}%
\begin{codeblock}
namespace std {
  class underflow_error : public runtime_error {
  public:
    constexpr explicit underflow_error(const string& what_arg);
    constexpr explicit underflow_error(const char* what_arg);
  };
}
\end{codeblock}

\pnum
The class
\tcode{underflow_error}
defines the type of objects thrown as exceptions to report an arithmetic underflow error.

\indexlibraryctor{underflow_error}%
\begin{itemdecl}
constexpr underflow_error(const string& what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg.c_str()) == 0}.
\end{itemdescr}

\indexlibraryctor{underflow_error}%
\begin{itemdecl}
constexpr underflow_error(const char* what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{strcmp(what(), what_arg) == 0}.
\end{itemdescr}

\rSec1[assertions]{Assertions}

\rSec2[assertions.general]{General}

\pnum
The header \libheaderdef{cassert}
provides a macro for documenting \Cpp{} program assertions and a mechanism
for disabling the assertion checks through defining the macro \tcode{NDEBUG}.

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

\begin{codeblock}
#define @\libmacro{assert}@(...) @\seebelow@
\end{codeblock}

\rSec2[assertions.assert]{The \tcode{assert} macro}

\pnum
If \tcode{NDEBUG} is defined as a macro name
at the point in the source file where \tcode{<cassert>} is included,
the \tcode{assert} macro is defined as
\begin{codeblock}
#define @\libmacro{assert}@(...) ((void)0)
\end{codeblock}

\pnum
Otherwise, the \libmacro{assert} macro puts a diagnostic test into programs;
it expands to an expression of type \keyword{void} which
has the following effects:

\begin{itemize}
\item
\mname{VA_ARGS} is evaluated and contextually converted to \tcode{bool}.
\item
If the evaluation yields \tcode{true} there are no further effects.
\item
Otherwise, the \tcode{assert} macro's expression
creates a diagnostic on the standard error stream (\IsoC{}, 7.23.3) in an
\impldef{format of diagnostic created by \tcode{assert} macro's expression}
format and calls \tcode{abort()}.
The diagnostic contains \tcode{\#}\mname{VA_ARGS} and
information on
the name of the source file,
the source line number, and
the name of the enclosing function
(such as provided by \tcode{source_location::current()}).
\end{itemize}

\pnum
If \mname{VA_ARGS} does not expand to
a  well-formed \grammarterm{assignment-expression},
the program is ill-formed.
If such an \grammarterm{assignment-expression} is ill-formed when
treated as an unevaluated operand\iref{expr.await, expr.yield},
the program is ill-formed, no diagnostic required.

\pnum
The macro \tcode{assert} is redefined according to
the current state of \tcode{NDEBUG} each time that
\tcode{<cassert>} is included.

\pnum
An expression \tcode{assert(E)}
is a constant subexpression\iref{defns.const.subexpr}, if
\begin{itemize}
\item
\tcode{NDEBUG} is defined at the point where \tcode{assert}
is last defined or redefined, or
\item
\tcode{E} contextually converted to \tcode{bool}\iref{conv}
is a constant subexpression that evaluates to the value \tcode{true}.
\end{itemize}

\rSec1[errno]{Error numbers}

\rSec2[errno.general]{General}

\pnum
The contents of the header \libheaderdef{cerrno} are the same as the POSIX header
\libheader{errno.h}, except that \libmacro{errno} shall be defined as a macro.
\begin{note}
The intent is to remain in close alignment with the POSIX standard.
\end{note}
A separate \tcode{errno} value is provided for each thread.

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

\begin{codeblock}
#define @\libmacro{errno}@ @\seebelow@

#define @\libmacro{E2BIG}@ @\seebelow@                                                // freestanding
#define @\libmacro{EACCES}@ @\seebelow@                                               // freestanding
#define @\libmacro{EADDRINUSE}@ @\seebelow@                                           // freestanding
#define @\libmacro{EADDRNOTAVAIL}@ @\seebelow@                                        // freestanding
#define @\libmacro{EAFNOSUPPORT}@ @\seebelow@                                         // freestanding
#define @\libmacro{EAGAIN}@ @\seebelow@                                               // freestanding
#define @\libmacro{EALREADY}@ @\seebelow@                                             // freestanding
#define @\libmacro{EBADF}@ @\seebelow@                                                // freestanding
#define @\libmacro{EBADMSG}@ @\seebelow@                                              // freestanding
#define @\libmacro{EBUSY}@ @\seebelow@                                                // freestanding
#define @\libmacro{ECANCELED}@ @\seebelow@                                            // freestanding
#define @\libmacro{ECHILD}@ @\seebelow@                                               // freestanding
#define @\libmacro{ECONNABORTED}@ @\seebelow@                                         // freestanding
#define @\libmacro{ECONNREFUSED}@ @\seebelow@                                         // freestanding
#define @\libmacro{ECONNRESET}@ @\seebelow@                                           // freestanding
#define @\libmacro{EDEADLK}@ @\seebelow@                                              // freestanding
#define @\libmacro{EDESTADDRREQ}@ @\seebelow@                                         // freestanding
#define @\libmacro{EDOM}@ @\seebelow@                                                 // freestanding
#define @\libmacro{EEXIST}@ @\seebelow@                                               // freestanding
#define @\libmacro{EFAULT}@ @\seebelow@                                               // freestanding
#define @\libmacro{EFBIG}@ @\seebelow@                                                // freestanding
#define @\libmacro{EHOSTUNREACH}@ @\seebelow@                                         // freestanding
#define @\libmacro{EIDRM}@ @\seebelow@                                                // freestanding
#define @\libmacro{EILSEQ}@ @\seebelow@                                               // freestanding
#define @\libmacro{EINPROGRESS}@ @\seebelow@                                          // freestanding
#define @\libmacro{EINTR}@ @\seebelow@                                                // freestanding
#define @\libmacro{EINVAL}@ @\seebelow@                                               // freestanding
#define @\libmacro{EIO}@ @\seebelow@                                                  // freestanding
#define @\libmacro{EISCONN}@ @\seebelow@                                              // freestanding
#define @\libmacro{EISDIR}@ @\seebelow@                                               // freestanding
#define @\libmacro{ELOOP}@ @\seebelow@                                                // freestanding
#define @\libmacro{EMFILE}@ @\seebelow@                                               // freestanding
#define @\libmacro{EMLINK}@ @\seebelow@                                               // freestanding
#define @\libmacro{EMSGSIZE}@ @\seebelow@                                             // freestanding
#define @\libmacro{ENAMETOOLONG}@ @\seebelow@                                         // freestanding
#define @\libmacro{ENETDOWN}@ @\seebelow@                                             // freestanding
#define @\libmacro{ENETRESET}@ @\seebelow@                                            // freestanding
#define @\libmacro{ENETUNREACH}@ @\seebelow@                                          // freestanding
#define @\libmacro{ENFILE}@ @\seebelow@                                               // freestanding
#define @\libmacro{ENOBUFS}@ @\seebelow@                                              // freestanding
#define @\libmacro{ENODEV}@ @\seebelow@                                               // freestanding
#define @\libmacro{ENOENT}@ @\seebelow@                                               // freestanding
#define @\libmacro{ENOEXEC}@ @\seebelow@                                              // freestanding
#define @\libmacro{ENOLCK}@ @\seebelow@                                               // freestanding
#define @\libmacro{ENOLINK}@ @\seebelow@                                              // freestanding
#define @\libmacro{ENOMEM}@ @\seebelow@                                               // freestanding
#define @\libmacro{ENOMSG}@ @\seebelow@                                               // freestanding
#define @\libmacro{ENOPROTOOPT}@ @\seebelow@                                          // freestanding
#define @\libmacro{ENOSPC}@ @\seebelow@                                               // freestanding
#define @\libmacro{ENOSYS}@ @\seebelow@                                               // freestanding
#define @\libmacro{ENOTCONN}@ @\seebelow@                                             // freestanding
#define @\libmacro{ENOTDIR}@ @\seebelow@                                              // freestanding
#define @\libmacro{ENOTEMPTY}@ @\seebelow@                                            // freestanding
#define @\libmacro{ENOTRECOVERABLE}@ @\seebelow@                                      // freestanding
#define @\libmacro{ENOTSOCK}@ @\seebelow@                                             // freestanding
#define @\libmacro{ENOTSUP}@ @\seebelow@                                              // freestanding
#define @\libmacro{ENOTTY}@ @\seebelow@                                               // freestanding
#define @\libmacro{ENXIO}@ @\seebelow@                                                // freestanding
#define @\libmacro{EOPNOTSUPP}@ @\seebelow@                                           // freestanding
#define @\libmacro{EOVERFLOW}@ @\seebelow@                                            // freestanding
#define @\libmacro{EOWNERDEAD}@ @\seebelow@                                           // freestanding
#define @\libmacro{EPERM}@ @\seebelow@                                                // freestanding
#define @\libmacro{EPIPE}@ @\seebelow@                                                // freestanding
#define @\libmacro{EPROTO}@ @\seebelow@                                               // freestanding
#define @\libmacro{EPROTONOSUPPORT}@ @\seebelow@                                      // freestanding
#define @\libmacro{EPROTOTYPE}@ @\seebelow@                                           // freestanding
#define @\libmacro{ERANGE}@ @\seebelow@                                               // freestanding
#define @\libmacro{EROFS}@ @\seebelow@                                                // freestanding
#define @\libmacro{ESPIPE}@ @\seebelow@                                               // freestanding
#define @\libmacro{ESRCH}@ @\seebelow@                                                // freestanding
#define @\libmacro{ETIMEDOUT}@ @\seebelow@                                            // freestanding
#define @\libmacro{ETXTBSY}@ @\seebelow@                                              // freestanding
#define @\libmacro{EWOULDBLOCK}@ @\seebelow@                                          // freestanding
#define @\libmacro{EXDEV}@ @\seebelow@                                                // freestanding
\end{codeblock}

\pnum
The meaning of the macros in this header is defined by the POSIX standard.

\xrefc{7.5}

\rSec1[syserr]{System error support}

\rSec2[syserr.general]{General}

\pnum
Subclause \ref{syserr} describes components that the standard library and
\Cpp{} programs may use to report error conditions originating from
the operating system or other low-level application program interfaces.

\pnum
Components described in \ref{syserr} do not change the value of
\tcode{errno}\iref{errno}.

\recommended
Implementations should leave the error states provided by other
libraries unchanged.

\rSec2[system.error.syn]{Header \tcode{<system_error>} synopsis}

\indexheader{system_error}%
\indexlibraryglobal{error_category}%
\indexlibraryglobal{error_code}%
\indexlibraryglobal{error_condition}%
\indexlibraryglobal{system_error}%
\begin{codeblock}
#include <compare>              // see \ref{compare.syn}

namespace std {
  class error_category;
  const error_category& generic_category() noexcept;
  const error_category& system_category() noexcept;

  class error_code;
  class error_condition;
  class system_error;

  template<class T>
    struct @\libglobal{is_error_code_enum}@ : public false_type {};

  template<class T>
    struct @\libglobal{is_error_condition_enum}@ : public false_type {};

  enum class @\libglobal{errc}@ {                                                     // freestanding
    @\libmember{address_family_not_supported}{errc}@,       // \tcode{EAFNOSUPPORT}
    @\libmember{address_in_use}{errc}@,                     // \tcode{EADDRINUSE}
    @\libmember{address_not_available}{errc}@,              // \tcode{EADDRNOTAVAIL}
    @\libmember{already_connected}{errc}@,                  // \tcode{EISCONN}
    @\libmember{argument_list_too_long}{errc}@,             // \tcode{E2BIG}
    @\libmember{argument_out_of_domain}{errc}@,             // \tcode{EDOM}
    @\libmember{bad_address}{errc}@,                        // \tcode{EFAULT}
    @\libmember{bad_file_descriptor}{errc}@,                // \tcode{EBADF}
    @\libmember{bad_message}{errc}@,                        // \tcode{EBADMSG}
    @\libmember{broken_pipe}{errc}@,                        // \tcode{EPIPE}
    @\libmember{connection_aborted}{errc}@,                 // \tcode{ECONNABORTED}
    @\libmember{connection_already_in_progress}{errc}@,     // \tcode{EALREADY}
    @\libmember{connection_refused}{errc}@,                 // \tcode{ECONNREFUSED}
    @\libmember{connection_reset}{errc}@,                   // \tcode{ECONNRESET}
    @\libmember{cross_device_link}{errc}@,                  // \tcode{EXDEV}
    @\libmember{destination_address_required}{errc}@,       // \tcode{EDESTADDRREQ}
    @\libmember{device_or_resource_busy}{errc}@,            // \tcode{EBUSY}
    @\libmember{directory_not_empty}{errc}@,                // \tcode{ENOTEMPTY}
    @\libmember{executable_format_error}{errc}@,            // \tcode{ENOEXEC}
    @\libmember{file_exists}{errc}@,                        // \tcode{EEXIST}
    @\libmember{file_too_large}{errc}@,                     // \tcode{EFBIG}
    @\libmember{filename_too_long}{errc}@,                  // \tcode{ENAMETOOLONG}
    @\libmember{function_not_supported}{errc}@,             // \tcode{ENOSYS}
    @\libmember{host_unreachable}{errc}@,                   // \tcode{EHOSTUNREACH}
    @\libmember{identifier_removed}{errc}@,                 // \tcode{EIDRM}
    @\libmember{illegal_byte_sequence}{errc}@,              // \tcode{EILSEQ}
    @\libmember{inappropriate_io_control_operation}{errc}@, // \tcode{ENOTTY}
    @\libmember{interrupted}{errc}@,                        // \tcode{EINTR}
    @\libmember{invalid_argument}{errc}@,                   // \tcode{EINVAL}
    @\libmember{invalid_seek}{errc}@,                       // \tcode{ESPIPE}
    @\libmember{io_error}{errc}@,                           // \tcode{EIO}
    @\libmember{is_a_directory}{errc}@,                     // \tcode{EISDIR}
    @\libmember{message_size}{errc}@,                       // \tcode{EMSGSIZE}
    @\libmember{network_down}{errc}@,                       // \tcode{ENETDOWN}
    @\libmember{network_reset}{errc}@,                      // \tcode{ENETRESET}
    @\libmember{network_unreachable}{errc}@,                // \tcode{ENETUNREACH}
    @\libmember{no_buffer_space}{errc}@,                    // \tcode{ENOBUFS}
    @\libmember{no_child_process}{errc}@,                   // \tcode{ECHILD}
    @\libmember{no_link}{errc}@,                            // \tcode{ENOLINK}
    @\libmember{no_lock_available}{errc}@,                  // \tcode{ENOLCK}
    @\libmember{no_message}{errc}@,                         // \tcode{ENOMSG}
    @\libmember{no_protocol_option}{errc}@,                 // \tcode{ENOPROTOOPT}
    @\libmember{no_space_on_device}{errc}@,                 // \tcode{ENOSPC}
    @\libmember{no_such_device_or_address}{errc}@,          // \tcode{ENXIO}
    @\libmember{no_such_device}{errc}@,                     // \tcode{ENODEV}
    @\libmember{no_such_file_or_directory}{errc}@,          // \tcode{ENOENT}
    @\libmember{no_such_process}{errc}@,                    // \tcode{ESRCH}
    @\libmember{not_a_directory}{errc}@,                    // \tcode{ENOTDIR}
    @\libmember{not_a_socket}{errc}@,                       // \tcode{ENOTSOCK}
    @\libmember{not_connected}{errc}@,                      // \tcode{ENOTCONN}
    @\libmember{not_enough_memory}{errc}@,                  // \tcode{ENOMEM}
    @\libmember{not_supported}{errc}@,                      // \tcode{ENOTSUP}
    @\libmember{operation_canceled}{errc}@,                 // \tcode{ECANCELED}
    @\libmember{operation_in_progress}{errc}@,              // \tcode{EINPROGRESS}
    @\libmember{operation_not_permitted}{errc}@,            // \tcode{EPERM}
    @\libmember{operation_not_supported}{errc}@,            // \tcode{EOPNOTSUPP}
    @\libmember{operation_would_block}{errc}@,              // \tcode{EWOULDBLOCK}
    @\libmember{owner_dead}{errc}@,                         // \tcode{EOWNERDEAD}
    @\libmember{permission_denied}{errc}@,                  // \tcode{EACCES}
    @\libmember{protocol_error}{errc}@,                     // \tcode{EPROTO}
    @\libmember{protocol_not_supported}{errc}@,             // \tcode{EPROTONOSUPPORT}
    @\libmember{read_only_file_system}{errc}@,              // \tcode{EROFS}
    @\libmember{resource_deadlock_would_occur}{errc}@,      // \tcode{EDEADLK}
    @\libmember{resource_unavailable_try_again}{errc}@,     // \tcode{EAGAIN}
    @\libmember{result_out_of_range}{errc}@,                // \tcode{ERANGE}
    @\libmember{state_not_recoverable}{errc}@,              // \tcode{ENOTRECOVERABLE}
    @\libmember{text_file_busy}{errc}@,                     // \tcode{ETXTBSY}
    @\libmember{timed_out}{errc}@,                          // \tcode{ETIMEDOUT}
    @\libmember{too_many_files_open_in_system}{errc}@,      // \tcode{ENFILE}
    @\libmember{too_many_files_open}{errc}@,                // \tcode{EMFILE}
    @\libmember{too_many_links}{errc}@,                     // \tcode{EMLINK}
    @\libmember{too_many_symbolic_link_levels}{errc}@,      // \tcode{ELOOP}
    @\libmember{value_too_large}{errc}@,                    // \tcode{EOVERFLOW}
    @\libmember{wrong_protocol_type}{errc}@,                // \tcode{EPROTOTYPE}
  };

  template<> struct is_error_condition_enum<errc> : true_type {};

  // \ref{syserr.errcode.nonmembers}, non-member functions
  error_code make_error_code(errc e) noexcept;

  template<class charT, class traits>
    basic_ostream<charT, traits>&
      operator<<(basic_ostream<charT, traits>& os, const error_code& ec);

  // \ref{syserr.errcondition.nonmembers}, non-member functions
  error_condition make_error_condition(errc e) noexcept;

  // \ref{syserr.compare}, comparison operator functions
  bool operator==(const error_code& lhs, const error_code& rhs) noexcept;
  bool operator==(const error_code& lhs, const error_condition& rhs) noexcept;
  bool operator==(const error_condition& lhs, const error_condition& rhs) noexcept;
  strong_ordering operator<=>(const error_code& lhs, const error_code& rhs) noexcept;
  strong_ordering operator<=>(const error_condition& lhs, const error_condition& rhs) noexcept;

  // \ref{syserr.hash}, hash support
  template<class T> struct hash;
  template<> struct hash<error_code>;
  template<> struct hash<error_condition>;

  // \ref{syserr}, system error support
  template<class T>
    constexpr bool @\libglobal{is_error_code_enum_v}@ = is_error_code_enum<T>::value;
  template<class T>
    constexpr bool @\libglobal{is_error_condition_enum_v}@ = is_error_condition_enum<T>::value;
}
\end{codeblock}

\pnum
The value of each \tcode{enum errc} enumerator is the same as
the value of the \libheader{cerrno} macro shown in the above synopsis.
Whether or not the \libheader{system_error} implementation
exposes the \libheader{cerrno} macros is unspecified.

\pnum
The \tcode{is_error_code_enum} and \tcode{is_error_condition_enum} templates may be
specialized for program-defined types to indicate that such types are eligible
for \tcode{class error_code} and \tcode{class error_condition} implicit
conversions, respectively.

\rSec2[syserr.errcat]{Class \tcode{error_category}}

\rSec3[syserr.errcat.overview]{Overview}

\pnum
The class \tcode{error_category} serves as a base class for types used
to identify the source and encoding of a particular category of error code.
Classes may be derived from \tcode{error_category} to support
categories of errors in addition to those defined in this document.
Such classes shall behave as specified in subclause~\ref{syserr.errcat}.
\begin{note}
\tcode{error_category} objects are
passed by reference, and two such objects
are equal if they have the same address.
If there is more than a single object of a custom \tcode{error_category} type,
such equality comparisons can evaluate to \tcode{false}
even for objects holding the same value.
\end{note}

\indexlibraryglobal{error_category}%
\indexlibraryctor{error_category}%
\indexlibrarydtor{error_category}%
\indexlibraryglobal{generic_category}%
\indexlibraryglobal{system_category}%
\begin{codeblock}
namespace std {
  class error_category {
  public:
    constexpr error_category() noexcept;
    virtual ~error_category();
    error_category(const error_category&) = delete;
    error_category& operator=(const error_category&) = delete;
    virtual const char* name() const noexcept = 0;
    virtual error_condition default_error_condition(int ev) const noexcept;
    virtual bool equivalent(int code, const error_condition& condition) const noexcept;
    virtual bool equivalent(const error_code& code, int condition) const noexcept;
    virtual string message(int ev) const = 0;

    bool operator==(const error_category& rhs) const noexcept;
    strong_ordering operator<=>(const error_category& rhs) const noexcept;
  };

  const error_category& generic_category() noexcept;
  const error_category& system_category() noexcept;
}
\end{codeblock}

\rSec3[syserr.errcat.virtuals]{Virtual members}

\indexlibrarymember{name}{error_category}%
\begin{itemdecl}
virtual const char* name() const noexcept = 0;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A string naming the error category.
\end{itemdescr}

\indexlibrarymember{default_error_condition}{error_category}%
\begin{itemdecl}
virtual error_condition default_error_condition(int ev) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{error_condition(ev, *this)}.
\end{itemdescr}

\indexlibrarymember{equivalent}{error_category}%
\begin{itemdecl}
virtual bool equivalent(int code, const error_condition& condition) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{default_error_condition(code) == condition}.
\end{itemdescr}

\indexlibrarymember{equivalent}{error_category}%
\begin{itemdecl}
virtual bool equivalent(const error_code& code, int condition) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{*this == code.category() \&\& code.value() == condition}.
\end{itemdescr}

\indexlibrarymember{message}{error_category}%
\begin{itemdecl}
virtual string message(int ev) const = 0;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A string that describes the error condition denoted by \tcode{ev}.
\end{itemdescr}

\rSec3[syserr.errcat.nonvirtuals]{Non-virtual members}

\indexlibrarymember{operator==}{error_category}%
\begin{itemdecl}
bool operator==(const error_category& rhs) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{this == \&rhs}.
\end{itemdescr}

\indexlibrarymember{operator<=>}{error_category}%
\begin{itemdecl}
strong_ordering operator<=>(const error_category& rhs) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{compare_three_way()(this, \&rhs)}.

\begin{note}
\tcode{compare_three_way}\iref{comparisons.three.way} provides a total ordering for pointers.
\end{note}
\end{itemdescr}

\rSec3[syserr.errcat.derived]{Program-defined classes derived from \tcode{error_category}}

\indexlibrarymember{name}{error_category}%
\begin{itemdecl}
virtual const char* name() const noexcept = 0;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A string naming the error category.
\end{itemdescr}

\indexlibrarymember{default_error_condition}{error_category}%
\begin{itemdecl}
virtual error_condition default_error_condition(int ev) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An object of type \tcode{error_condition} that corresponds to \tcode{ev}.
\end{itemdescr}

\indexlibrarymember{equivalent}{error_category}%
\begin{itemdecl}
virtual bool equivalent(int code, const error_condition& condition) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if, for the category of error represented by \tcode{*this}, \tcode{code} is considered equivalent to \tcode{condition}; otherwise, \tcode{false}.
\end{itemdescr}

\indexlibrarymember{equivalent}{error_category}%
\begin{itemdecl}
virtual bool equivalent(const error_code& code, int condition) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if, for the category of error represented by \tcode{*this}, \tcode{code} is considered equivalent to \tcode{condition}; otherwise, \tcode{false}.
\end{itemdescr}

\rSec3[syserr.errcat.objects]{Error category objects}

\indexlibraryglobal{generic_category}%
\begin{itemdecl}
const error_category& generic_category() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A reference to an object of a type derived from class \tcode{error_category}.
All calls to this function shall return references to the same object.

\pnum
\remarks
The object's \tcode{default_error_condition} and \tcode{equivalent} virtual functions shall behave as specified for the class \tcode{error_category}. The object's \tcode{name} virtual function shall return a pointer to the string \tcode{"generic"}.
\end{itemdescr}

\indexlibraryglobal{system_category}%
\begin{itemdecl}
const error_category& system_category() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A reference to an object of a type derived from class \tcode{error_category}.
All calls to this function shall return references to the same object.

\pnum
\remarks
The object's \tcode{equivalent} virtual functions shall behave as specified for
class \tcode{error_category}. The object's \tcode{name} virtual function shall return a
pointer to the string \tcode{"system"}. The object's \tcode{default_error_condition}
virtual function shall behave as follows:

If the argument \tcode{ev} is equal to 0,
the function returns \tcode{error_condition(0, generic_category())}.
Otherwise,
if \tcode{ev} corresponds to a POSIX \tcode{errno} value \tcode{pxv},
the function returns \tcode{error_condition(pxv, generic_category())}.
Otherwise, the function returns \tcode{error_condition(ev, system_category())}.
What constitutes correspondence for any given operating system is unspecified.
\begin{note}
The number of potential system error codes is large
and unbounded, and some might not correspond to any POSIX \tcode{errno} value. Thus
implementations are given latitude in determining correspondence.
\end{note}
\end{itemdescr}

\rSec2[syserr.errcode]{Class \tcode{error_code}}

\rSec3[syserr.errcode.overview]{Overview}

\pnum
The class \tcode{error_code} describes an object used to hold error code
values, such as those originating from the operating system or other low-level
application program interfaces.
\begin{note}
Class \tcode{error_code} is an
adjunct to error reporting by exception.
\end{note}

\indexlibraryglobal{error_code}%
\begin{codeblock}
namespace std {
  class error_code {
  public:
    // \ref{syserr.errcode.constructors}, constructors
    error_code() noexcept;
    error_code(int val, const error_category& cat) noexcept;
    template<class ErrorCodeEnum>
      error_code(ErrorCodeEnum e) noexcept;

    // \ref{syserr.errcode.modifiers}, modifiers
    void assign(int val, const error_category& cat) noexcept;
    template<class ErrorCodeEnum>
      error_code& operator=(ErrorCodeEnum e) noexcept;
    void clear() noexcept;

    // \ref{syserr.errcode.observers}, observers
    int value() const noexcept;
    const error_category& category() const noexcept;
    error_condition default_error_condition() const noexcept;
    string message() const;
    explicit operator bool() const noexcept;

  private:
    int @\exposid{val_}@;                   // \expos
    const error_category* @\exposid{cat_}@; // \expos
  };

  // \ref{syserr.errcode.nonmembers}, non-member functions
  error_code make_error_code(errc e) noexcept;

  template<class charT, class traits>
    basic_ostream<charT, traits>&
      operator<<(basic_ostream<charT, traits>& os, const error_code& ec);
}
\end{codeblock}

\rSec3[syserr.errcode.constructors]{Constructors}

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

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{val_} with \tcode{0}
and \exposid{cat_} with \tcode{\&system_category()}.
\end{itemdescr}

\indexlibraryctor{error_code}%
\begin{itemdecl}
error_code(int val, const error_category& cat) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{val_} with \tcode{val}
and \exposid{cat_} with \tcode{\&cat}.
\end{itemdescr}

\indexlibraryctor{error_code}%
\begin{itemdecl}
template<class ErrorCodeEnum>
  error_code(ErrorCodeEnum e) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_error_code_enum_v<ErrorCodeEnum>} is \tcode{true}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
error_code ec = make_error_code(e);
assign(ec.value(), ec.category());
\end{codeblock}
\end{itemdescr}

\rSec3[syserr.errcode.modifiers]{Modifiers}

\indexlibrarymember{assign}{error_code}%
\begin{itemdecl}
void assign(int val, const error_category& cat) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{\exposid{val_} == val} and \tcode{\exposid{cat_} == \&cat}.
\end{itemdescr}

\indexlibrarymember{operator=}{error_code}%
\begin{itemdecl}
template<class ErrorCodeEnum>
  error_code& operator=(ErrorCodeEnum e) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_error_code_enum_v<ErrorCodeEnum>} is \tcode{true}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
error_code ec = make_error_code(e);
assign(ec.value(), ec.category());
\end{codeblock}

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

\indexlibrarymember{clear}{error_code}%
\begin{itemdecl}
void clear() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{value() == 0} and \tcode{category() == system_category()}.
\end{itemdescr}


\rSec3[syserr.errcode.observers]{Observers}

\indexlibrarymember{value}{error_code}%
\begin{itemdecl}
int value() const noexcept;
\end{itemdecl}

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

\indexlibrarymember{category}{error_code}%
\begin{itemdecl}
const error_category& category() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{*\exposid{cat_}}.
\end{itemdescr}

\indexlibrarymember{default_error_condition}{error_code}%
\begin{itemdecl}
error_condition default_error_condition() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{category().default_error_condition(value())}.
\end{itemdescr}

\indexlibrarymember{message}{error_code}%
\begin{itemdecl}
string message() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{category().message(value())}.
\end{itemdescr}

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

\begin{itemdescr}
\pnum
\returns
\tcode{value() != 0}.
\end{itemdescr}

\rSec3[syserr.errcode.nonmembers]{Non-member functions}

\indexlibrarymember{make_error_code}{errc}%
\begin{itemdecl}
error_code make_error_code(errc e) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{error_code(static_cast<int>(e), generic_category())}.
\end{itemdescr}

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

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return os << ec.category().name() << ':' << ec.value();}
\end{itemdescr}


\rSec2[syserr.errcondition]{Class \tcode{error_condition}}

\rSec3[syserr.errcondition.overview]{Overview}

\pnum
The class \tcode{error_condition} describes an object used to hold values identifying
error conditions.
\begin{note}
\tcode{error_condition} values are portable abstractions,
while \tcode{error_code} values\iref{syserr.errcode} are implementation specific.
\end{note}

\indexlibraryglobal{error_condition}%
\begin{codeblock}
namespace std {
  class error_condition {
  public:
    // \ref{syserr.errcondition.constructors}, constructors
    error_condition() noexcept;
    error_condition(int val, const error_category& cat) noexcept;
    template<class ErrorConditionEnum>
      error_condition(ErrorConditionEnum e) noexcept;

    // \ref{syserr.errcondition.modifiers}, modifiers
    void assign(int val, const error_category& cat) noexcept;
    template<class ErrorConditionEnum>
      error_condition& operator=(ErrorConditionEnum e) noexcept;
    void clear() noexcept;

    // \ref{syserr.errcondition.observers}, observers
    int value() const noexcept;
    const error_category& category() const noexcept;
    string message() const;
    explicit operator bool() const noexcept;

  private:
    int @\exposid{val_}@;                   // \expos
    const error_category* @\exposid{cat_}@; // \expos
  };
}
\end{codeblock}

\rSec3[syserr.errcondition.constructors]{Constructors}

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

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{val_} with \tcode{0}
and \exposid{cat_} with \tcode{\&generic_category()}.
\end{itemdescr}

\indexlibraryctor{error_condition}%
\begin{itemdecl}
error_condition(int val, const error_category& cat) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{val_} with \tcode{val}
and \exposid{cat_} with \tcode{\&cat}.
\end{itemdescr}

\indexlibraryctor{error_condition}%
\begin{itemdecl}
template<class ErrorConditionEnum>
  error_condition(ErrorConditionEnum e) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_error_condition_enum_v<ErrorConditionEnum>} is \tcode{true}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
error_condition ec = make_error_condition(e);
assign(ec.value(), ec.category());
\end{codeblock}
\end{itemdescr}


\rSec3[syserr.errcondition.modifiers]{Modifiers}

\indexlibrarymember{assign}{error_condition}%
\begin{itemdecl}
void assign(int val, const error_category& cat) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{\exposid{val_} == val} and \tcode{\exposid{cat_} == \&cat}.
\end{itemdescr}

\indexlibrarymember{operator=}{error_condition}%
\begin{itemdecl}
template<class ErrorConditionEnum>
  error_condition& operator=(ErrorConditionEnum e) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_error_condition_enum_v<ErrorConditionEnum>} is \tcode{true}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
error_condition ec = make_error_condition(e);
assign(ec.value(), ec.category());
\end{codeblock}

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

\indexlibrarymember{clear}{error_condition}%
\begin{itemdecl}
void clear() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{value() == 0} and \tcode{category() == generic_category()}.
\end{itemdescr}

\rSec3[syserr.errcondition.observers]{Observers}

\indexlibrarymember{value}{error_condition}%
\begin{itemdecl}
int value() const noexcept;
\end{itemdecl}

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

\indexlibrarymember{category}{error_condition}%
\begin{itemdecl}
const error_category& category() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{*\exposid{cat_}}.
\end{itemdescr}

\indexlibrarymember{message}{error_condition}%
\begin{itemdecl}
string message() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{category().message(value())}.
\end{itemdescr}

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

\begin{itemdescr}
\pnum
\returns
\tcode{value() != 0}.
\end{itemdescr}

\rSec3[syserr.errcondition.nonmembers]{Non-member functions}

\indexlibrarymember{make_error_condition}{errc}%
\begin{itemdecl}
error_condition make_error_condition(errc e) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{error_condition(static_cast<int>(e), generic_category())}.
\end{itemdescr}

\rSec2[syserr.compare]{Comparison operator functions}

\indexlibrarymember{operator==}{error_code}%
\begin{itemdecl}
bool operator==(const error_code& lhs, const error_code& rhs) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{codeblock}
lhs.category() == rhs.category() && lhs.value() == rhs.value()
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{error_condition}%
\indexlibrarymember{operator==}{error_code}%
\begin{itemdecl}
bool operator==(const error_code& lhs, const error_condition& rhs) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{codeblock}
lhs.category().equivalent(lhs.value(), rhs) || rhs.category().equivalent(lhs, rhs.value())
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator==}{error_condition}%
\begin{itemdecl}
bool operator==(const error_condition& lhs, const error_condition& rhs) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{codeblock}
lhs.category() == rhs.category() && lhs.value() == rhs.value()
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator<=>}{error_code}%
\begin{itemdecl}
strong_ordering operator<=>(const error_code& lhs, const error_code& rhs) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
if (auto c = lhs.category() <=> rhs.category(); c != 0) return c;
return lhs.value() <=> rhs.value();
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{operator<=>}{error_condition}%
\begin{itemdecl}
strong_ordering operator<=>(const error_condition& lhs, const error_condition& rhs) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{codeblock}
if (auto c = lhs.category() <=> rhs.category(); c != 0) return c;
return lhs.value() <=> rhs.value();
\end{codeblock}
\end{itemdescr}

\rSec2[syserr.hash]{System error hash support}

\indexlibrarymember{hash}{error_code}%
\begin{itemdecl}
template<> struct hash<error_code>;
template<> struct hash<error_condition>;
\end{itemdecl}

\begin{itemdescr}
\pnum
The specializations are enabled\iref{unord.hash}.
\end{itemdescr}

\rSec2[syserr.syserr]{Class \tcode{system_error}}

\rSec3[syserr.syserr.overview]{Overview}

\pnum
The class \tcode{system_error} describes an exception object used to
report error conditions that have an associated error code. Such error
conditions typically originate from the operating system or other low-level
application program interfaces.

\pnum
\begin{note}
If an error represents an out-of-memory condition, implementations are
encouraged to throw an exception object of type \tcode{bad_alloc}\iref{bad.alloc} rather
than \tcode{system_error}.
\end{note}
\indexlibraryglobal{system_error}%
\begin{codeblock}
namespace std {
  class system_error : public runtime_error {
  public:
    system_error(error_code ec, const string& what_arg);
    system_error(error_code ec, const char* what_arg);
    system_error(error_code ec);
    system_error(int ev, const error_category& ecat, const string& what_arg);
    system_error(int ev, const error_category& ecat, const char* what_arg);
    system_error(int ev, const error_category& ecat);
    const error_code& code() const noexcept;
    const char* what() const noexcept override;
  };
}
\end{codeblock}

\rSec3[syserr.syserr.members]{Members}

\indexlibraryctor{system_error}%
\begin{itemdecl}
system_error(error_code ec, const string& what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{code() == ec} and\newline
\tcode{string_view(what()).find(what_arg.c_str()) != string_view::npos}.
\end{itemdescr}

\indexlibraryctor{system_error}%
\begin{itemdecl}
system_error(error_code ec, const char* what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{code() == ec} and
\tcode{string_view(what()).find(what_arg) != string_view::npos}.
\end{itemdescr}

\indexlibraryctor{system_error}%
\begin{itemdecl}
system_error(error_code ec);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{code() == ec}.
\end{itemdescr}

\indexlibraryctor{system_error}%
\begin{itemdecl}
system_error(int ev, const error_category& ecat, const string& what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\raggedright \tcode{code() == error_code(ev, ecat)} and\linebreak
\tcode{string_view(what()).find(what_arg.c_str()) != string_view::npos}.
\end{itemdescr}

\indexlibraryctor{system_error}%
\begin{itemdecl}
system_error(int ev, const error_category& ecat, const char* what_arg);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\raggedright \tcode{code() == error_code(ev, ecat)} and\linebreak
\tcode{string_view(what()).find(what_arg) != string_view::npos}.
\end{itemdescr}

\indexlibraryctor{system_error}%
\begin{itemdecl}
system_error(int ev, const error_category& ecat);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{code() == error_code(ev, ecat)}.
\end{itemdescr}

\indexlibrarymember{code}{system_error}%
\begin{itemdecl}
const error_code& code() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{ec} or \tcode{error_code(ev, ecat)}, from the constructor,
as appropriate.
\end{itemdescr}

\indexlibrarymember{what}{system_error}%
\begin{itemdecl}
const char* what() const noexcept override;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An \ntbs{} incorporating the arguments supplied in the constructor.

\begin{note}
The returned \ntbs{} might be the contents of \tcode{what_arg + ": " +
code.message()}.
\end{note}
\end{itemdescr}

\rSec1[stacktrace]{Stacktrace}

\rSec2[stacktrace.general]{General}

\pnum
Subclause \ref{stacktrace} describes components
that \Cpp{} programs may use to store
the stacktrace of the current thread of execution and
query information about the stored stacktrace at runtime.

\pnum
The \defn{invocation sequence} of the current evaluation $x_0$
in the current thread of execution
is a sequence $(x_0, \ldots, x_n)$ of evaluations such that, for $i \geq 0$,
$x_i$ is within the function invocation $x_{i+1}$\iref{intro.execution}.

\pnum
A \defn{stacktrace} is an approximate representation of
an invocation sequence and consists of stacktrace entries.
A \defn{stacktrace entry} represents an evaluation in a stacktrace.

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

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

namespace std {
  // \ref{stacktrace.entry}, class \tcode{stacktrace_entry}
  class stacktrace_entry;

  // \ref{stacktrace.basic}, class template \tcode{basic_stacktrace}
  template<class Allocator>
    class basic_stacktrace;

  // \tcode{basic_stacktrace} \grammarterm{typedef-name}s
  using stacktrace = basic_stacktrace<allocator<stacktrace_entry>>;

  // \ref{stacktrace.basic.nonmem}, non-member functions
  template<class Allocator>
    void swap(basic_stacktrace<Allocator>& a, basic_stacktrace<Allocator>& b)
      noexcept(noexcept(a.swap(b)));

  string to_string(const stacktrace_entry& f);

  template<class Allocator>
    string to_string(const basic_stacktrace<Allocator>& st);

  ostream& operator<<(ostream& os, const stacktrace_entry& f);
  template<class Allocator>
    ostream& operator<<(ostream& os, const basic_stacktrace<Allocator>& st);

  // \ref{stacktrace.format}, formatting support
  template<> struct formatter<stacktrace_entry>;
  template<class Allocator> struct formatter<basic_stacktrace<Allocator>>;

  namespace pmr {
    using stacktrace = basic_stacktrace<polymorphic_allocator<stacktrace_entry>>;
  }

  // \ref{stacktrace.basic.hash}, hash support
  template<class T> struct hash;
  template<> struct hash<stacktrace_entry>;
  template<class Allocator> struct hash<basic_stacktrace<Allocator>>;
}
\end{codeblock}

\rSec2[stacktrace.entry]{Class \tcode{stacktrace_entry}}

\rSec3[stacktrace.entry.overview]{Overview}

\begin{codeblock}
namespace std {
  class @\libglobal{stacktrace_entry}@ {
  public:
    using native_handle_type = @\impdefx{\tcode{stacktrace_entry::native_handle_type}}@;

    // \ref{stacktrace.entry.cons}, constructors
    constexpr stacktrace_entry() noexcept;
    constexpr stacktrace_entry(const stacktrace_entry& other) noexcept;
    constexpr stacktrace_entry& operator=(const stacktrace_entry& other) noexcept;

    ~stacktrace_entry();

    // \ref{stacktrace.entry.obs}, observers
    constexpr native_handle_type native_handle() const noexcept;
    constexpr explicit operator bool() const noexcept;

    // \ref{stacktrace.entry.query}, query
    string description() const;
    string source_file() const;
    uint_least32_t source_line() const;

    // \ref{stacktrace.entry.cmp}, comparison
    friend constexpr bool operator==(const stacktrace_entry& x,
                                     const stacktrace_entry& y) noexcept;
    friend constexpr strong_ordering operator<=>(const stacktrace_entry& x,
                                                 const stacktrace_entry& y) noexcept;
  };
}
\end{codeblock}

\pnum
An object of type \tcode{stacktrace_entry} is either empty,
or represents a stacktrace entry and
provides operations for querying information about it.
The class \tcode{stacktrace_entry} models
\libconcept{regular}\iref{concepts.object} and
\tcode{\libconcept{three_way_comparable}<strong_ordering>}\iref{cmp.concept}.

\rSec3[stacktrace.entry.cons]{Constructors}

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

\begin{itemdescr}
\pnum
\ensures
\tcode{*this} is empty.
\end{itemdescr}

\rSec3[stacktrace.entry.obs]{Observers}

\indexlibrarymember{native_handle}{stacktrace_entry}%
\begin{itemdecl}
constexpr native_handle_type native_handle() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
The semantics of this function are
\impldef{semantics of \tcode{stacktrace_entry::native_handle}}.

\pnum
\remarks
Successive invocations of the \tcode{native_handle} function
for an unchanged \tcode{stacktrace_entry} object return identical values.
\end{itemdescr}

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

\begin{itemdescr}
\pnum
\returns
\tcode{false} if and only if \tcode{*this} is empty.
\end{itemdescr}

\rSec3[stacktrace.entry.query]{Query}

\pnum
\begin{note}
All the \tcode{stacktrace_entry} query functions treat
errors other than memory allocation errors
as ``no information available'' and do not throw in that case.
\end{note}

\indexlibrarymember{description}{stacktrace_entry}%
\begin{itemdecl}
string description() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A description of the evaluation represented by \tcode{*this},
or an empty string.

\pnum
\throws
\tcode{bad_alloc} if memory for
the internal data structures or the resulting string cannot be allocated.
\end{itemdescr}

\indexlibrarymember{source_file}{stacktrace_entry}%
\begin{itemdecl}
string source_file() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The presumed or actual name of the source file\iref{cpp.predefined}
that lexically contains the expression or statement
whose evaluation is represented by \tcode{*this}, or an empty string.

\pnum
\throws
\tcode{bad_alloc} if memory for
the internal data structures or the resulting string cannot be allocated.
\end{itemdescr}

\indexlibrarymember{source_line}{stacktrace_entry}%
\begin{itemdecl}
uint_least32_t source_line() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{0}, or a 1-based line number that lexically relates to the evaluation
represented by \tcode{*this}.
If \tcode{source_file} returns the presumed name of the source file,
returns the presumed line number;
if \tcode{source_file} returns the actual name of the source file,
returns the actual line number.

\pnum
\throws
\tcode{bad_alloc} if memory for
the internal data structures cannot be allocated.
\end{itemdescr}

\rSec3[stacktrace.entry.cmp]{Comparison}

\indexlibrarymember{operator==}{stacktrace_entry}%
\begin{itemdecl}
friend constexpr bool operator==(const stacktrace_entry& x, const stacktrace_entry& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if and only if \tcode{x} and \tcode{y} represent
the same stacktrace entry or both \tcode{x} and \tcode{y} are empty.
\end{itemdescr}

\rSec2[stacktrace.basic]{Class template \tcode{basic_stacktrace}}

\rSec3[stacktrace.basic.overview]{Overview}

\begin{codeblock}
namespace std {
  template<class Allocator>
  class @\libglobal{basic_stacktrace}@ {
  public:
    using value_type = stacktrace_entry;
    using const_reference = const value_type&;
    using reference = value_type&;
    using const_iterator = @\impdefx{type of \tcode{basic_stacktrace::const_iterator}}@;  // see \ref{stacktrace.basic.obs}
    using iterator = const_iterator;
    using reverse_iterator = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using difference_type = @\impdefx{type of \tcode{basic_stacktrace::difference_type}}@;
    using size_type = @\impdefx{type of \tcode{basic_stacktrace::size_type}}@;
    using allocator_type = Allocator;

    // \ref{stacktrace.basic.cons}, creation and assignment
    static basic_stacktrace current(const allocator_type& alloc = allocator_type()) noexcept;
    static basic_stacktrace current(size_type skip,
                                    const allocator_type& alloc = allocator_type()) noexcept;
    static basic_stacktrace current(size_type skip, size_type max_depth,
                                    const allocator_type& alloc = allocator_type()) noexcept;

    basic_stacktrace() noexcept(is_nothrow_default_constructible_v<allocator_type>);
    explicit basic_stacktrace(const allocator_type& alloc) noexcept;

    basic_stacktrace(const basic_stacktrace& other);
    basic_stacktrace(basic_stacktrace&& other) noexcept;
    basic_stacktrace(const basic_stacktrace& other, const allocator_type& alloc);
    basic_stacktrace(basic_stacktrace&& other, const allocator_type& alloc);
    basic_stacktrace& operator=(const basic_stacktrace& other);
    basic_stacktrace& operator=(basic_stacktrace&& other)
      noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
        allocator_traits<Allocator>::is_always_equal::value);

    ~basic_stacktrace();

    // \ref{stacktrace.basic.obs}, observers
    allocator_type get_allocator() const noexcept;

    const_iterator begin() const noexcept;
    const_iterator end() const noexcept;
    const_reverse_iterator rbegin() const noexcept;
    const_reverse_iterator rend() const noexcept;

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

    bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    const_reference operator[](size_type) const;
    const_reference at(size_type) const;

    // \ref{stacktrace.basic.cmp}, comparisons
    template<class Allocator2>
    friend bool operator==(const basic_stacktrace& x,
                           const basic_stacktrace<Allocator2>& y) noexcept;
    template<class Allocator2>
    friend strong_ordering operator<=>(const basic_stacktrace& x,
                                       const basic_stacktrace<Allocator2>& y) noexcept;

    // \ref{stacktrace.basic.mod}, modifiers
    void swap(basic_stacktrace& other)
      noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
        allocator_traits<Allocator>::is_always_equal::value);

  private:
    vector<value_type, allocator_type> @\exposid{frames_}@;         // \expos
  };
}
\end{codeblock}

\pnum
The class template \tcode{basic_stacktrace} satisfies
the requirements
of a reversible container\iref{container.rev.reqmts},
of an allocator-aware container\iref{container.alloc.reqmts}, and
of a sequence container\iref{sequence.reqmts},
except that
\begin{itemize}
\item
only move, assignment, swap, and
operations defined for const-qualified sequence containers are supported and,
\item
the semantics of comparison functions
are different from those required for a container.
\end{itemize}

\rSec3[stacktrace.basic.cons]{Creation and assignment}

\indexlibrarymember{current}{basic_stacktrace}%
\begin{itemdecl}
static basic_stacktrace current(const allocator_type& alloc = allocator_type()) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{basic_stacktrace} object
with \exposid{frames_} storing
the stacktrace of the current evaluation in the current thread of execution, or
an empty \tcode{basic_stacktrace} object
if the initialization of \exposid{frames_} failed.
\tcode{alloc} is passed to the constructor of the \exposid{frames_} object.

\begin{note}
If the stacktrace was successfully obtained,
then \tcode{\exposid{frames_}.front()} is the \tcode{stacktrace_entry}
representing approximately the current evaluation, and
\tcode{\exposid{frames_}.back()} is the \tcode{stacktrace_entry}
representing approximately the initial function of
the current thread of execution.
\end{note}
\end{itemdescr}

\indexlibrarymember{current}{basic_stacktrace}%
\begin{itemdecl}
static basic_stacktrace current(size_type skip,
                                const allocator_type& alloc = allocator_type()) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{t} be a stacktrace
as-if obtained via \tcode{basic_stacktrace::current(alloc)}.
Let \tcode{n} be \tcode{t.size()}.

\pnum
\returns
A \tcode{basic_stacktrace} object
where \exposid{frames_} is direct-non-list-initialized from arguments
\tcode{t.begin() + min(n, skip)}, \tcode{t.end()}, and \tcode{alloc},
or an empty \tcode{basic_stacktrace} object
if the initialization of \exposid{frames_} failed.
\end{itemdescr}

\indexlibrarymember{current}{basic_stacktrace}%
\begin{itemdecl}
static basic_stacktrace current(size_type skip, size_type max_depth,
                                const allocator_type& alloc = allocator_type()) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{t} be a stacktrace
as-if obtained via \tcode{basic_stacktrace::current(alloc)}.
Let \tcode{n} be \tcode{t.size()}.

\pnum
\hardexpects
\tcode{skip <= skip + max_depth} is \tcode{true}.

\pnum
\returns
A \tcode{basic_stacktrace} object
where \exposid{frames_} is direct-non-list-initialized from arguments
\tcode{t.begin() + min(n, skip)}, \tcode{t.begin() + min(n, skip + max_depth)},
and \tcode{alloc},
or an empty \tcode{basic_stacktrace} object
if the initialization of \exposid{frames_} failed.
\end{itemdescr}

\indexlibraryctor{basic_stacktrace}%
\begin{itemdecl}
basic_stacktrace() noexcept(is_nothrow_default_constructible_v<allocator_type>);
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{empty()} is \tcode{true}.
\end{itemdescr}

\indexlibraryctor{basic_stacktrace}%
\begin{itemdecl}
explicit basic_stacktrace(const allocator_type& alloc) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\tcode{alloc} is passed to the \exposid{frames_} constructor.

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

\indexlibraryctor{basic_stacktrace}%
\indexlibrarymember{operator=}{basic_stacktrace}%
\begin{itemdecl}
basic_stacktrace(const basic_stacktrace& other);
basic_stacktrace(const basic_stacktrace& other, const allocator_type& alloc);
basic_stacktrace(basic_stacktrace&& other, const allocator_type& alloc);
basic_stacktrace& operator=(const basic_stacktrace& other);
basic_stacktrace& operator=(basic_stacktrace&& other)
  noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
    allocator_traits<Allocator>::is_always_equal::value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\remarks
Implementations may strengthen the exception specification
for these functions\iref{res.on.exception.handling}
by ensuring that \tcode{empty()} is \tcode{true} on failed allocation.
\end{itemdescr}

\rSec3[stacktrace.basic.obs]{Observers}

\indexlibrarymember{const_iterator}{basic_stacktrace}%
\begin{itemdecl}
using const_iterator = @\impdef@;
\end{itemdecl}

\begin{itemdescr}
\pnum
The type models
\libconcept{random_access_iterator}\iref{iterator.concept.random.access} and
meets the
\oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators}.
\end{itemdescr}

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

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{frames_}.get_allocator()}.
\end{itemdescr}

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

\begin{itemdescr}
\pnum
\returns
An iterator referring to the first element in \exposid{frames_}.
If \tcode{empty()} is \tcode{true},
then it returns the same value as \tcode{end()}.
\end{itemdescr}

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

\begin{itemdescr}
\pnum
\returns
The end iterator.
\end{itemdescr}

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

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

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

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

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

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{frames_}.empty()}.
\end{itemdescr}

\indexlibrarymember{size}{basic_stacktrace}%
\begin{itemdecl}
size_type size() const noexcept;
\end{itemdecl}

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

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

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{frames_}.max_size()}.
\end{itemdescr}

\indexlibrarymember{operator[]}{basic_stacktrace}%
\begin{itemdecl}
const_reference operator[](size_type frame_no) const;
\end{itemdecl}

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

\pnum
\returns
\tcode{\exposid{frames_}[frame_no]}.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{at}{basic_stacktrace}%
\begin{itemdecl}
const_reference at(size_type frame_no) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{frames_}[frame_no]}.

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

\rSec3[stacktrace.basic.cmp]{Comparisons}

\indexlibrarymember{operator==}{basic_stacktrace}%
\begin{itemdecl}
template<class Allocator2>
friend bool operator==(const basic_stacktrace& x, const basic_stacktrace<Allocator2>& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{equal(x.begin(), x.end(), y.begin(), y.end())}.
\end{itemdescr}

\indexlibrarymember{operator<=>}{basic_stacktrace}%
\begin{itemdecl}
template<class Allocator2>
friend strong_ordering
  operator<=>(const basic_stacktrace& x, const basic_stacktrace<Allocator2>& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.size() <=> y.size()} if \tcode{x.size() != y.size()};
\tcode{lexicographical_compare_three_way(x.begin(), x.end(), y.begin(), y.end())}
otherwise.
\end{itemdescr}

\rSec3[stacktrace.basic.mod]{Modifiers}

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

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

\rSec3[stacktrace.basic.nonmem]{Non-member functions}

\indexlibrarymember{swap}{basic_stacktrace}%
\begin{itemdecl}
template<class Allocator>
  void swap(basic_stacktrace<Allocator>& a, basic_stacktrace<Allocator>& b)
    noexcept(noexcept(a.swap(b)));
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{a.swap(b)}.
\end{itemdescr}

\indexlibrarymember{to_string}{basic_stacktrace}%
\begin{itemdecl}
string to_string(const stacktrace_entry& f);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A string with a description of \tcode{f}.

\pnum
\recommended
The description should provide information about the contained evaluation,
including information from
\tcode{f.source_file()} and \tcode{f.source_line()}.
\end{itemdescr}

\indexlibrarymember{to_string}{basic_stacktrace}%
\begin{itemdecl}
template<class Allocator>
  string to_string(const basic_stacktrace<Allocator>& st);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A string with a description of \tcode{st}.
\begin{note}
The number of lines is not guaranteed to be equal to \tcode{st.size()}.
\end{note}
\end{itemdescr}

\indexlibrarymember{operator<<}{stacktrace_entry}%
\begin{itemdecl}
ostream& operator<<(ostream& os, const stacktrace_entry& f);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return os << to_string(f);}
\end{itemdescr}

\indexlibrarymember{operator<<}{basic_stacktrace}%
\begin{itemdecl}
template<class Allocator>
  ostream& operator<<(ostream& os, const basic_stacktrace<Allocator>& st);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return os << to_string(st);}
\end{itemdescr}

\rSec2[stacktrace.format]{Formatting support}

\begin{itemdecl}
template<> struct formatter<stacktrace_entry>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\tcode{formatter<stacktrace_entry>} interprets \fmtgrammarterm{format-spec}
as a \fmtgrammarterm{stacktrace-entry-format-spec}.
The syntax of format specifications is as follows:

\begin{ncbnf}
\fmtnontermdef{stacktrace-entry-format-spec}\br
    \opt{fill-and-align} \opt{width}
\end{ncbnf}

\begin{note}
The productions \fmtgrammarterm{fill-and-align} and \fmtgrammarterm{width}
are described in \ref{format.string.std}.
\end{note}

\pnum
A \tcode{stacktrace_entry} object \tcode{se} is formatted as if by
copying \tcode{to_string(se)} through the output iterator of the context
with additional padding and adjustments as specified by the format specifiers.
\end{itemdescr}

\begin{itemdecl}
template<class Allocator> struct formatter<basic_stacktrace<Allocator>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
For \tcode{formatter<basic_stacktrace<Allocator>>},
\fmtgrammarterm{format-spec} is empty.

\pnum
A \tcode{basic_stacktrace<Allocator>} object \tcode{s} is formatted as if by
copying \tcode{to_string(s)} through the output iterator of the context.
\end{itemdescr}

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

\begin{itemdecl}
template<> struct hash<stacktrace_entry>;
template<class Allocator> struct hash<basic_stacktrace<Allocator>>;
\end{itemdecl}

\begin{itemdescr}
\pnum
The specializations are enabled\iref{unord.hash}.
\end{itemdescr}

\rSec1[debugging]{Debugging}

\rSec2[debugging.general]{General}

\pnum
Subclause \ref{debugging} describes functionality to introspect and
interact with the execution of the program.

\begin{note}
The facilities provided by the debugging functionality interact with a program
that could be tracing the execution of a \Cpp{} program, such as a debugger.
\end{note}

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

\indexheader{debugging}%
\begin{codeblock}
// all freestanding
namespace std {
  // \ref{debugging.utility}, utility
  void breakpoint() noexcept;
  void breakpoint_if_debugging() noexcept;
  bool is_debugger_present() noexcept;
}
\end{codeblock}

\rSec2[debugging.utility]{Utility}

\indexlibraryglobal{breakpoint}%
\begin{itemdecl}
void breakpoint() noexcept;
\end{itemdecl}

\begin{itemdescr}

\pnum
The semantics of this function are \impldef{semantics of \tcode{breakpoint}}.

\begin{note}
It is intended that, when invoked with a debugger present, the execution of the
program temporarily halts and execution is handed to the debugger until the
program is either terminated by the debugger or the debugger resumes execution
of the program as if the function was not invoked. In particular, there is no
intent for a call to this function to accomodate resumption of the program in a
different manner. If there is no debugger present, execution of the program can
end abnormally.
\end{note}

\end{itemdescr}

\indexlibraryglobal{breakpoint_if_debugging}%
\begin{itemdecl}
void breakpoint_if_debugging() noexcept;
\end{itemdecl}

\begin{itemdescr}

\pnum
\effects
Equivalent to:
\begin{codeblock}
if (is_debugger_present()) breakpoint();
\end{codeblock}

\end{itemdescr}

\indexlibraryglobal{is_debugger_present}%
\begin{itemdecl}
bool is_debugger_present() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\required
This function has no preconditions.

\pnum
\default
\impldef{default semantics of \tcode{is_debugger_present}}.

\begin{note}
It is intended that, using an immediate (uncached) query to determine if the
program is being traced by a debugger, an implementation returns \tcode{true}
only when tracing the execution of the program with a debugger. On Windows or
equivalent systems, this can be achieved by calling the
\tcode{::IsDebuggerPresent()} Win32 function. For systems compatible with
ISO/IEC 23360:2021, this can be achieved by checking for a tracing process, with
a best-effort determination that such a tracing process is a debugger.
\end{note}

\pnum
\remarks
This function is replaceable\iref{term.replaceable.function}.

\end{itemdescr}
