From 024b157b7008065ca135161ccd4574e8d9d2b0e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Thu, 21 Oct 2021 17:01:29 +0100 Subject: [PATCH 001/182] Update configuration for building working drafts after N4901. --- source/config.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/config.tex b/source/config.tex index cd2cfe4c57..556faf904a 100644 --- a/source/config.tex +++ b/source/config.tex @@ -1,8 +1,8 @@ %!TEX root = std.tex %%-------------------------------------------------- %% Version numbers -\newcommand{\docno}{N4901} -\newcommand{\prevdocno}{N4892} +\newcommand{\docno}{Dxxxx} +\newcommand{\prevdocno}{N4901} \newcommand{\cppver}{202002L} %% Release date From 04e0ea7074c9b0d0ca939821ce0f575c589df6b7 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 21 Oct 2021 23:52:55 +0200 Subject: [PATCH 002/182] [pairs.pair] Use T1/T2, not first_type/second_type --- source/utilities.tex | 81 ++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 41 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index 1b3144ba34..928c196e3a 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -765,8 +765,8 @@ \pnum \constraints \begin{itemize} -\item \tcode{is_default_constructible_v} is \tcode{true} and -\item \tcode{is_default_constructible_v} is \tcode{true}. +\item \tcode{is_default_constructible_v} is \tcode{true} and +\item \tcode{is_default_constructible_v} is \tcode{true}. \end{itemize} \pnum @@ -776,11 +776,11 @@ \pnum \remarks The expression inside \keyword{explicit} evaluates to \tcode{true} -if and only if either \tcode{first_type} or -\tcode{second_type} is not implicitly default-constructible. +if and only if either \tcode{T1} or +\tcode{T2} is not implicitly default-constructible. \begin{note} This behavior can be implemented with a trait that checks -whether a \tcode{const first_type\&} or a \tcode{const second_type\&} +whether a \tcode{const T1\&} or a \tcode{const T2\&} can be initialized with \tcode{\{\}}. \end{note} \end{itemdescr} @@ -794,8 +794,8 @@ \pnum \constraints \begin{itemize} -\item \tcode{is_copy_constructible_v} is \tcode{true} and -\item \tcode{is_copy_constructible_v} is \tcode{true}. +\item \tcode{is_copy_constructible_v} is \tcode{true} and +\item \tcode{is_copy_constructible_v} is \tcode{true}. \end{itemize} \pnum @@ -806,8 +806,7 @@ \remarks The expression inside \keyword{explicit} is equivalent to: \begin{codeblock} -!is_convertible_v || - !is_convertible_v +!is_convertible_v || !is_convertible_v \end{codeblock} \end{itemdescr} @@ -820,8 +819,8 @@ \pnum \constraints \begin{itemize} -\item \tcode{is_constructible_v} is \tcode{true} and -\item \tcode{is_constructible_v} is \tcode{true}. +\item \tcode{is_constructible_v} is \tcode{true} and +\item \tcode{is_constructible_v} is \tcode{true}. \end{itemize} \pnum @@ -834,7 +833,7 @@ \remarks The expression inside \keyword{explicit} is equivalent to: \begin{codeblock} -!is_convertible_v || !is_convertible_v +!is_convertible_v || !is_convertible_v \end{codeblock} \end{itemdescr} @@ -854,10 +853,10 @@ \constraints \begin{itemize} \item -\tcode{is_constructible_v(\exposid{FWD}(p)))>} +\tcode{is_constructible_v(\exposid{FWD}(p)))>} is \tcode{true} and \item -\tcode{is_constructible_v(\exposid{FWD}(p)))>} +\tcode{is_constructible_v(\exposid{FWD}(p)))>} is \tcode{true}. \end{itemize} @@ -870,8 +869,8 @@ \remarks The expression inside \keyword{explicit} is equivalent to: \begin{codeblock} -!is_convertible_v(@\exposid{FWD}@(p))), first_type> || -!is_convertible_v(@\exposid{FWD}@(p))), second_type> +!is_convertible_v(@\exposid{FWD}@(p))), T1> || +!is_convertible_v(@\exposid{FWD}@(p))), T2> \end{codeblock} \end{itemdescr} @@ -886,8 +885,8 @@ \pnum \mandates \begin{itemize} -\item \tcode{is_constructible_v} is \tcode{true} and -\item \tcode{is_constructible_v} is \tcode{true}. +\item \tcode{is_constructible_v} is \tcode{true} and +\item \tcode{is_constructible_v} is \tcode{true}. \end{itemize} \pnum @@ -919,8 +918,8 @@ \pnum \remarks This operator is defined as deleted unless -\tcode{is_copy_assignable_v} is \tcode{true} and -\tcode{is_copy_assignable_v} is \tcode{true}. +\tcode{is_copy_assignable_v} is \tcode{true} and +\tcode{is_copy_assignable_v} is \tcode{true}. \end{itemdescr} \indexlibrarymember{operator=}{pair}% @@ -933,9 +932,9 @@ \constraints \begin{itemize} \item -\tcode{is_copy_assignable} is \tcode{true} and +\tcode{is_copy_assignable} is \tcode{true} and \item -\tcode{is_copy_assignable} is \tcode{true}. +\tcode{is_copy_assignable} is \tcode{true}. \end{itemize} \pnum @@ -956,8 +955,8 @@ \pnum \constraints \begin{itemize} -\item \tcode{is_assignable_v} is \tcode{true} and -\item \tcode{is_assignable_v} is \tcode{true}. +\item \tcode{is_assignable_v} is \tcode{true} and +\item \tcode{is_assignable_v} is \tcode{true}. \end{itemize} \pnum @@ -979,9 +978,9 @@ \constraints \begin{itemize} \item -\tcode{is_assignable_v} is \tcode{true}, and +\tcode{is_assignable_v} is \tcode{true}, and \item -\tcode{is_assignable_v} is \tcode{true}. +\tcode{is_assignable_v} is \tcode{true}. \end{itemize} \pnum @@ -1002,14 +1001,14 @@ \pnum \constraints \begin{itemize} -\item \tcode{is_move_assignable_v} is \tcode{true} and -\item \tcode{is_move_assignable_v} is \tcode{true}. +\item \tcode{is_move_assignable_v} is \tcode{true} and +\item \tcode{is_move_assignable_v} is \tcode{true}. \end{itemize} \pnum \effects -Assigns to \tcode{first} with \tcode{std::forward(p.first)} -and to \tcode{second} with\\ \tcode{std::forward(p.second)}. +Assigns to \tcode{first} with \tcode{std::forward(p.first)} +and to \tcode{second} with \tcode{std::forward(\brk{}p.second)}. \pnum \returns @@ -1033,15 +1032,15 @@ \constraints \begin{itemize} \item -\tcode{is_assignable} is \tcode{true} and +\tcode{is_assignable} is \tcode{true} and \item -\tcode{is_assignable} is \tcode{true}. +\tcode{is_assignable} is \tcode{true}. \end{itemize} \pnum \effects -Assigns \tcode{std::forward(p.first)} to \tcode{first} and -\tcode{std::forward(\brk{}p.second)} to \tcode{second}. +Assigns \tcode{std::forward(p.first)} to \tcode{first} and +\tcode{std::forward(p.second)} to \tcode{second}. \pnum \returns @@ -1057,8 +1056,8 @@ \pnum \constraints \begin{itemize} -\item \tcode{is_assignable_v} is \tcode{true} and -\item \tcode{is_assignable_v} is \tcode{true}. +\item \tcode{is_assignable_v} is \tcode{true} and +\item \tcode{is_assignable_v} is \tcode{true}. \end{itemize} \pnum @@ -1081,9 +1080,9 @@ \constraints \begin{itemize} \item -\tcode{is_assignable_v} is \tcode{true}, and +\tcode{is_assignable_v} is \tcode{true}, and \item -\tcode{is_assignable_v} is \tcode{true}. +\tcode{is_assignable_v} is \tcode{true}. \end{itemize} \effects @@ -1131,10 +1130,10 @@ The exception specification is equivalent to: \begin{itemize} \item -\tcode{is_nothrow_swappable_v \&\& is_nothrow_swappable_v} -for the\newline first overload, and +\tcode{is_nothrow_swappable_v \&\& is_nothrow_swappable_v} +for the first overload, and \item -\tcode{is_nothrow_swappable_v \&\& is_nothrow_swappable_v} +\tcode{is_nothrow_swappable_v \&\& is_nothrow_swappable_v} for the second overload. \end{itemize} \end{itemdescr} From ed6e1b5da5d13449cf27c878c60e90892289f98a Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 23 Oct 2021 01:20:31 +0200 Subject: [PATCH 003/182] [index] Fix dangling 'see' references Also update the automatic check script to prevent further occurrences. --- source/lex.tex | 2 ++ source/numerics.tex | 2 +- source/overloading.tex | 2 ++ tools/check-output.sh | 16 ++++++++++++++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/source/lex.tex b/source/lex.tex index 19b93a0a18..7cae838222 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -357,6 +357,8 @@ the value of such a code unit can be the same as that of a code unit for an element of the basic literal character set. \end{note} +\indextext{character!null}% +\indextext{wide-character!null}% The U+0000 NULL character is encoded as the value \tcode{0}. No other element of the translation character set is encoded with a code unit of value \tcode{0}. diff --git a/source/numerics.tex b/source/numerics.tex index 3dbad178de..e685c29edc 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -10183,7 +10183,7 @@ \indexlibraryglobal{beta}% \indexlibraryglobal{betaf}% \indexlibraryglobal{betal}% -\indextext{Eulerian integral of the first kind|see{\tcode{beta}}}% +\indextext{Eulerian integral of the first kind|see{beta functions $\mathsf{B}$}}% \indextext{beta functions $\mathsf{B}$}% \begin{itemdecl} double beta(double x, double y); diff --git a/source/overloading.tex b/source/overloading.tex index 9628d1d6aa..e1b21b02fd 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -3352,6 +3352,7 @@ \indextext{postfix ++ and -{-} overloading@postfix \tcode{++} and \tcode{--}!overloading}% \pnum +\indextext{overloading!increment operator}% An \defnadj{increment}{operator function} is a function named \tcode{\keyword{operator}++}. If this function is a non-static member function with no non-object parameters, or a non-member @@ -3408,6 +3409,7 @@ \end{example} \pnum +\indextext{overloading!decrement operator}% A \defnadj{decrement}{operator function} is a function named \tcode{\keyword{operator}--} and is handled analogously to an increment operator function. diff --git a/tools/check-output.sh b/tools/check-output.sh index e6b8acab41..3ea883bb94 100755 --- a/tools/check-output.sh +++ b/tools/check-output.sh @@ -17,6 +17,22 @@ sed -n '/\.tex/{s/^.*\/\([-a-z0-9]\+\.tex\).*$/\1/;h}; /Overfull [\\][hv]box\|LaTeX Warning..Reference/{x;p;x;p}' std.log | sed '/^.\+\.tex$/{N;s/\n/:/}' | fail || failed=1 +# Check for dangling "see" in general index (does not work with formatting) +grep item < std-generalindex.ind | sed 's/,.*$//;s/\\[sub]*item //' | + awk '/^ [^ ]/ { item=$0; print $0 } /^ [^ ]/ { subitem=$0; print item ", " $0 } /^ [^ ]/ { print item ", " subitem ", " $0 }' | + sed 's/^ *//;s/ */ /g' | sort > tmp.txt + +grep -o '\\see{[^}]*}' < std-generalindex.ind | + sed 's/^\\see{//;s/}$//;s/\\-//' | + grep -v "leavevmode\|texttt\|textsc\|kern" | + while read see; do + if grep -q "$see" tmp.txt; then + : + else + grep -n "see{$see}" *.tex | sed 's/$/ is dangling/' + fi + done | fail || failed=1 +rm -f tmp.txt # Cross references since the previous standard. function indexentries() { sed 's,\\glossaryentry{\(.*\)@.*,\1,' "$1" | LANG=C sort; } From 3d1424716844aef59891d770709e19d83b5bea35 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 24 Oct 2021 22:05:40 +0200 Subject: [PATCH 004/182] [ranges] Remove \expos markers for nested types (#4829) An \expos marker should appear only on the first declaration of a name. --- source/ranges.tex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/ranges.tex b/source/ranges.tex index 4e6a0286c5..91d74512d2 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -3016,7 +3016,7 @@ template<@\libconcept{movable}@ Val, class CharT, class Traits> requires @\libconcept{default_initializable}@ && @\exposconcept{stream-extractable}@ - class basic_istream_view::@\exposid{iterator}@ { // \expos + class basic_istream_view::@\exposid{iterator}@ { public: using iterator_concept = input_iterator_tag; using difference_type = ptrdiff_t; @@ -4969,7 +4969,7 @@ requires @\libconcept{input_range}@ && is_object_v && @\libconcept{indirect_unary_predicate}@> template - class take_while_view::@\exposidnc{sentinel}@ { // \expos + class take_while_view::@\exposidnc{sentinel}@ { using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos sentinel_t<@\exposidnc{Base}@> @\exposid{end_}@ = sentinel_t<@\exposidnc{Base}@>(); // \expos @@ -7124,7 +7124,7 @@ @\exposconcept{has-tuple-element}@>, N> && @\exposconcept{returnable-element}@, N> template - class elements_view::@\exposid{iterator}@ { // \expos + class elements_view::@\exposid{iterator}@ { using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos @@ -7523,7 +7523,7 @@ @\placeholder{has-tuple-element}@>, N> && @\exposconcept{returnable-element}@, N> template - class elements_view::@\exposid{sentinel}@ { // \expos + class elements_view::@\exposid{sentinel}@ { private: using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos From 741c20794fdc7aec28afcd9e6c52d6d184d2845c Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 26 Oct 2021 16:36:39 +0200 Subject: [PATCH 005/182] [class.copy.assign] Fix phrasing in note to avoid 'could'. (#4418) --- source/classes.tex | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index 62a8de403a..1a20b4aa5a 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -1870,11 +1870,13 @@ a base class copy/move assignment operator is always hidden by the corresponding assignment operator of a derived class\iref{over.ass}. \begin{note} -A \grammarterm{using-declaration} that names an assignment operator -with a parameter type that could be that of a -copy/move assignment operator for a -derived class does not suppress the implicit declaration of the derived class -operator\iref{namespace.udecl}. +A \grammarterm{using-declaration} in a derived class \tcode{C} +that names an assignment operator from a base class +never suppresses the implicit declaration of +an assignment operator of \tcode{C}, +even if the base class assignment operator would be +a copy or move assignment operator +if declared as a member of \tcode{C}. \end{note} \pnum From 352e4b125072cfd827e6bc9a99a4e7f5d0b54c64 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 26 Oct 2021 21:58:47 +0200 Subject: [PATCH 006/182] [intro.object,lex.ccon] Use \Cpp{} macros and augment the automatic checks to flag literal 'C++'. --- source/basic.tex | 2 +- source/lex.tex | 2 +- tools/check-source.sh | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 89184d41a6..51503ca73d 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -3323,7 +3323,7 @@ implicitly creates objects in the returned region of storage and returns a pointer to a suitable created object. \begin{note} -Some functions in the C++ standard library implicitly create objects +Some functions in the \Cpp{} standard library implicitly create objects (\ref{allocator.traits.members}, \ref{c.malloc}, \ref{cstring.syn}, \ref{bit.cast}). \end{note} \indextext{object model|)} diff --git a/source/lex.tex b/source/lex.tex index 7cae838222..ab1c771c71 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -1485,7 +1485,7 @@ is specified in \tref{lex.ccon.esc}. \begin{note} Using an escape sequence for a question mark -is supported for compatibility with ISO C++ 2014 and ISO C. +is supported for compatibility with ISO \CppXIV{} and ISO C. \end{note} \begin{floattable}{Simple escape sequences}{lex.ccon.esc} diff --git a/tools/check-source.sh b/tools/check-source.sh index 37bd96f9e4..635f103351 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -67,6 +67,10 @@ grep -n 'opt{}' *.tex | grep -n "// not defined" $texfiles | fail "use \\notdef instead" || failed=1 +# Use \Cpp{} instead of C++ +grep -n '^[^%]*[^{"]C++[^"}]' $texfiles | + fail 'use \Cpp{} instead' || failed=1 + # Library element introducer followed by stuff. grep -ne '^\\\(constraints\|mandates\|expects\|effects\|sync\|ensures\|returns\|throws\|complexity\|remarks\|errors\).\+$' $texlibdesc | fail 'stuff after library element' || failed=1 From c8d22d409ccf96b496ee435182998f181996f80f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Wed, 27 Oct 2021 21:57:16 +0100 Subject: [PATCH 007/182] [expr.prim.lambda.capture] Add missing \keyword This fixes a misapplication of CWG1249, which requested "mutable" to be code, not text. --- source/expressions.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/expressions.tex b/source/expressions.tex index 75a4f5bde0..dd24afa83e 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -2515,7 +2515,7 @@ \item If \tcode{m1} captures the entity by copy, \tcode{m2} captures the corresponding non-static data member of \tcode{m1}'s closure type; -if \tcode{m1} is not mutable, the non-static data member is considered to be const-qualified. +if \tcode{m1} is not \keyword{mutable}, the non-static data member is considered to be const-qualified. \item If \tcode{m1} captures the entity by reference, \tcode{m2} captures the same entity captured by \tcode{m1}. From f3ab334c789ac89d2f6baf501d60716278cb8fa3 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 4 Jul 2021 23:30:42 +0200 Subject: [PATCH 008/182] [contents] Add special lookup treatment for swap --- source/lib-intro.tex | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 87bf68e065..5a7d9dcae5 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -927,7 +927,7 @@ \end{footnote} \pnum -Whenever an unqualified name is used +Whenever an unqualified name other than \tcode{swap} is used in the specification of a declaration \tcode{D} in \ref{\firstlibchapter} through \ref{\lastlibchapter} or \ref{depr}, its meaning is established @@ -946,6 +946,9 @@ Operators in expressions\iref{over.match.oper} are not so constrained; see \ref{global.functions}. \end{note} +The meaning of the unqualified name \tcode{swap} is established +in an overload resolution context +for swappable values\iref{swappable.requirements}. \rSec3[headers]{Headers} From 6a0a1aa981620cc56afc452f5587207c66641719 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 5 Nov 2021 22:39:07 +0100 Subject: [PATCH 009/182] [check] Cosmetics --- .github/workflows/check.yml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 45b4a1b4fc..2c1415675c 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -2,12 +2,11 @@ name: check -on: - pull_request: - push: +on: [pull_request, push] defaults: run: + shell: bash working-directory: source jobs: @@ -16,18 +15,25 @@ jobs: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 - - name: check-source + - name: checkout + uses: actions/checkout@v2 + + - name: check-source.sh run: ../tools/check-source.sh + - name: update-apt-cache run: sudo apt-get update + - name: install run: sudo apt-get install latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended lmodern + - name: make run: make quiet - - name: check-output + + - name: check-output.sh run: ../tools/check-output.sh - - name: upload pdf + + - name: upload PDF uses: actions/upload-artifact@v2 with: name: draft-snapshot From 280684c7824b6b7f62c003b909ccf3703d82681b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Mon, 8 Nov 2021 07:19:14 -0400 Subject: [PATCH 010/182] [defs] Update introduction to match ISO Directives (#5096) Reference: https://www.iso.org/sites/directives/current/part2/index.xhtml#_idTextAnchor218 --- source/intro.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/intro.tex b/source/intro.tex index 97433869f5..6f4bcbd7af 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -118,12 +118,12 @@ and the following apply. \pnum -ISO and IEC maintain terminological databases +ISO and IEC maintain terminology databases for use in standardization at the following addresses: \begin{itemize} \item ISO Online browsing platform: available at \url{https://www.iso.org/obp} -\item IEC Electropedia: available at \url{http://www.electropedia.org/} +\item IEC Electropedia: available at \url{http://www.electropedia.org} \end{itemize} \pnum From 1567c481e3ca3c52f80e4a33db0f913ce1392c4d Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 9 Nov 2021 09:31:08 +0000 Subject: [PATCH 011/182] [intro.refs] Update dated reference to previous POSIX standard Fixes #5098 --- source/intro.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/intro.tex b/source/intro.tex index 6f4bcbd7af..bc3202190f 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -92,7 +92,7 @@ \end{footnote} \pnum -The operating system interface described in ISO/IEC 9945:2003 is +The operating system interface described in ISO/IEC 9945:2009 is hereinafter called \defn{POSIX}. \pnum From e31cb7ca1a0ab6aa23793bac14aeb28a5fae3b96 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 27 Oct 2021 10:01:25 +0200 Subject: [PATCH 012/182] [lex] Introduce \unicode macro for Unicode character names and format them using \textsc --- source/lex.tex | 144 ++++++++++++++++++++++--------------------- source/macros.tex | 3 + source/strings.tex | 4 +- source/uax31.tex | 4 +- source/utilities.tex | 28 ++++----- 5 files changed, 95 insertions(+), 88 deletions(-) diff --git a/source/lex.tex b/source/lex.tex index ab1c771c71..210a116c69 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -243,45 +243,45 @@ \begin{floattable}{Basic character set}{lex.charset.basic}{lll} \topline \lhdrx{2}{character} & \rhdr{glyph} \\ \capsep -U+0009 & CHARACTER TABULATION & \\ -U+000B & LINE TABULATION & \\ -U+000C & FORM FEED (FF) & \\ -U+0020 & SPACE & \\ -U+000A & LINE FEED (LF) & new-line \\ -U+0021 & EXCLAMATION MARK & \tcode{!} \\ -U+0022 & QUOTATION MARK & \tcode{"} \\ -U+0023 & NUMBER SIGN & \tcode{\#} \\ -U+0025 & PERCENT SIGN & \tcode{\%} \\ -U+0026 & AMPERSAND & \tcode{\&} \\ -U+0027 & APOSTROPHE & \tcode{'} \\ -U+0028 & LEFT PARENTHESIS & \tcode{(} \\ -U+0029 & RIGHT PARENTHESIS & \tcode{)} \\ -U+002A & ASTERISK & \tcode{*} \\ -U+002B & PLUS SIGN & \tcode{+} \\ -U+002C & COMMA & \tcode{,} \\ -U+002D & HYPHEN-MINUS & \tcode{-} \\ -U+002E & FULL STOP & \tcode{.} \\ -U+002F & SOLIDUS & \tcode{/} \\ -U+0030 .. U+0039 & DIGIT ZERO .. NINE & \tcode{0 1 2 3 4 5 6 7 8 9} \\ -U+003A & COLON & \tcode{:} \\ -U+003B & SEMICOLON & \tcode{;} \\ -U+003C & LESS-THAN SIGN & \tcode{<} \\ -U+003D & EQUALS SIGN & \tcode{=} \\ -U+003E & GREATER-THAN SIGN & \tcode{>} \\ -U+003F & QUESTION MARK & \tcode{?} \\ -U+0041 .. U+005A & LATIN CAPITAL LETTER A .. Z & \tcode{A B C D E F G H I J K L M} \\ -& & \tcode{N O P Q R S T U V W X Y Z} \\ -U+005B & LEFT SQUARE BRACKET & \tcode{[} \\ -U+005C & REVERSE SOLIDUS & \tcode{\textbackslash} \\ -U+005D & RIGHT SQUARE BRACKET & \tcode{]} \\ -U+005E & CIRCUMFLEX ACCENT & \tcode{\caret} \\ -U+005F & LOW LINE & \tcode{_} \\ -U+0061 .. U+007A & LATIN SMALL LETTER A .. Z & \tcode{a b c d e f g h i j k l m} \\ +\ucode{0009} & \uname{character tabulation} & \\ +\ucode{000b} & \uname{line tabulation} & \\ +\ucode{000c} & \uname{form feed (ff)} & \\ +\ucode{0020} & \uname{space} & \\ +\ucode{000a} & \uname{line feed (lf)} & new-line \\ +\ucode{0021} & \uname{exclamation mark} & \tcode{!} \\ +\ucode{0022} & \uname{quotation mark} & \tcode{"} \\ +\ucode{0023} & \uname{number sign} & \tcode{\#} \\ +\ucode{0025} & \uname{percent sign} & \tcode{\%} \\ +\ucode{0026} & \uname{ampersand} & \tcode{\&} \\ +\ucode{0027} & \uname{apostrophe} & \tcode{'} \\ +\ucode{0028} & \uname{left parenthesis} & \tcode{(} \\ +\ucode{0029} & \uname{right parenthesis} & \tcode{)} \\ +\ucode{002a} & \uname{asterisk} & \tcode{*} \\ +\ucode{002b} & \uname{plus sign} & \tcode{+} \\ +\ucode{002c} & \uname{comma} & \tcode{,} \\ +\ucode{002d} & \uname{hyphen-minus} & \tcode{-} \\ +\ucode{002e} & \uname{full stop} & \tcode{.} \\ +\ucode{002f} & \uname{solidus} & \tcode{/} \\ +\ucode{0030} .. \ucode{0039} & \uname{digit zero .. nine} & \tcode{0 1 2 3 4 5 6 7 8 9} \\ +\ucode{003a} & \uname{colon} & \tcode{:} \\ +\ucode{003b} & \uname{semicolon} & \tcode{;} \\ +\ucode{003c} & \uname{less-than sign} & \tcode{<} \\ +\ucode{003d} & \uname{equals sign} & \tcode{=} \\ +\ucode{003e} & \uname{greater-than sign} & \tcode{>} \\ +\ucode{003f} & \uname{question mark} & \tcode{?} \\ +\ucode{0041} .. \ucode{005a} & \uname{latin capital letter a .. z} & \tcode{A B C D E F G H I J K L M} \\ + & & \tcode{N O P Q R S T U V W X Y Z} \\ +\ucode{005b} & \uname{left square bracket} & \tcode{[} \\ +\ucode{005c} & \uname{reverse solidus} & \tcode{\textbackslash} \\ +\ucode{005d} & \uname{right square bracket} & \tcode{]} \\ +\ucode{005e} & \uname{circumflex accent} & \tcode{\caret} \\ +\ucode{005f} & \uname{low line} & \tcode{_} \\ +\ucode{0061} .. \ucode{007a} & \uname{latin small letter a .. z} & \tcode{a b c d e f g h i j k l m} \\ & & \tcode{n o p q r s t u v w x y z} \\ -U+007B & LEFT CURLY BRACKET & \tcode{\{} \\ -U+007C & VERTICAL LINE & \tcode{|} \\ -U+007D & RIGHT CURLY BRACKET & \tcode{\}} \\ -U+007E & TILDE & \tcode{\textasciitilde} \\ +\ucode{007b} & \uname{left curly bracket} & \tcode{\{} \\ +\ucode{007c} & \uname{vertical line} & \tcode{|} \\ +\ucode{007d} & \uname{right curly bracket} & \tcode{\}} \\ +\ucode{007e} & \uname{tilde} & \tcode{\textasciitilde} \\ \end{floattable} \pnum @@ -325,10 +325,10 @@ \begin{floattable}{Additional control characters in the basic literal character set}{lex.charset.literal}{ll} \topline \ohdrx{2}{character} \\ \capsep -U+0000 & NULL \\ -U+0007 & BELL \\ -U+0008 & BACKSPACE \\ -U+000D & CARRIAGE RETURN (CR) \\ +\ucode{0000} & \uname{null} \\ +\ucode{0007} & \uname{bell} \\ +\ucode{0008} & \uname{backspace} \\ +\ucode{000d} & \uname{carriage return (cr)} \\ \end{floattable} \pnum @@ -359,10 +359,10 @@ \end{note} \indextext{character!null}% \indextext{wide-character!null}% -The U+0000 NULL character is encoded as the value \tcode{0}. +The \unicode{0000}{null} character is encoded as the value \tcode{0}. No other element of the translation character set is encoded with a code unit of value \tcode{0}. -The code unit value of each decimal digit character after the digit \tcode{0} (U+0030) +The code unit value of each decimal digit character after the digit \tcode{0} (\ucode{0030}) shall be one greater than the value of the previous. The ordinary and wide literal encodings are otherwise \impldef{ordinary and wide literal encodings}. @@ -412,7 +412,7 @@ literals), string literals (including user-defined string literals), preprocessing operators and punctuators, and single non-whitespace characters that do not lexically match the other preprocessing token categories. -If a U+0027 APOSTROPHE or a U+0022 QUOTATION MARK character +If a \unicode{0027}{apostrophe} or a \unicode{0022}{quotation mark} character matches the last category, the behavior is undefined. If any character not in the basic character set matches the last category, the program is ill-formed. @@ -420,8 +420,13 @@ \indextext{whitespace}% whitespace; \indextext{comment}% -this consists of comments\iref{lex.comment}, or whitespace -characters (U+0020 SPACE, U+0009 CHARACTER TABULATION, new-line, U+000B LINE TABULATION, and U+000C FORM FEED), or both. As described in \ref{cpp}, in certain +this consists of comments\iref{lex.comment}, or whitespace characters +(\unicode{0020}{space}, +\unicode{0009}{character tabulation}, +new-line, +\unicode{000b}{line tabulation}, and +\unicode{000c}{form feed}), or both. +As described in \ref{cpp}, in certain circumstances during translation phase 4, whitespace (or the absence thereof) serves as more than preprocessing token separation. Whitespace can appear within a preprocessing token only as part of a header name or @@ -625,7 +630,7 @@ \begin{bnf} \nontermdef{h-char}\br - \textnormal{any member of the translation character set except new-line and \terminal{U+003E GREATER-THAN SIGN}} + \textnormal{any member of the translation character set except new-line and \unicode{003e}{greater-than sign}} \end{bnf} \begin{bnf} @@ -636,7 +641,7 @@ \begin{bnf} \nontermdef{q-char}\br - \textnormal{any member of the translation character set except new-line and \terminal{U+0022 QUOTATION MARK}} + \textnormal{any member of the translation character set except new-line and \unicode{0022}{quotation mark}} \end{bnf} \pnum @@ -1273,8 +1278,8 @@ \begin{bnf} \nontermdef{basic-c-char}\br - \textnormal{any member of the translation character set except the U+0027 APOSTROPHE,}\br - \bnfindent\textnormal{U+005C REVERSE SOLIDUS, or new-line character} + \textnormal{any member of the translation character set except the \unicode{0027}{apostrophe},}\br + \bnfindent\textnormal{\unicode{005c}{reverse solidus}, or new-line character} \end{bnf} \begin{bnf} @@ -1492,17 +1497,17 @@ {lll} \topline \lhdrx{2}{character} & \rhdr{\grammarterm{simple-escape-sequence}} \\ \capsep -U+000A & LINE FEED (LF) & \tcode{\textbackslash n} \\ -U+0009 & CHARACTER TABULATION & \tcode{\textbackslash t} \\ -U+000B & LINE TABULATION & \tcode{\textbackslash v} \\ -U+0008 & BACKSPACE & \tcode{\textbackslash b} \\ -U+000D & CARRIAGE RETURN (CR) & \tcode{\textbackslash r} \\ -U+000C & FORM FEED (FF) & \tcode{\textbackslash f} \\ -U+0007 & BELL & \tcode{\textbackslash a} \\ -U+005C & REVERSE SOLIDUS & \tcode{\textbackslash\textbackslash} \\ -U+003F & QUESTION MARK & \tcode{\textbackslash ?} \\ -U+0027 & APOSTROPHE & \tcode{\textbackslash '} \\ -U+0022 & QUOTATION MARK & \tcode{\textbackslash "} \\ +\ucode{000a} & \uname{line feed} & \tcode{\textbackslash n} \\ +\ucode{0009} & \uname{character tabulation} & \tcode{\textbackslash t} \\ +\ucode{000b} & \uname{line tabulation} & \tcode{\textbackslash v} \\ +\ucode{0008} & \uname{backspace} & \tcode{\textbackslash b} \\ +\ucode{000d} & \uname{carriage return} & \tcode{\textbackslash r} \\ +\ucode{000c} & \uname{form feed} & \tcode{\textbackslash f} \\ +\ucode{0007} & \uname{bell} & \tcode{\textbackslash a} \\ +\ucode{005c} & \uname{reverse solidus} & \tcode{\textbackslash\textbackslash} \\ +\ucode{003f} & \uname{question mark} & \tcode{\textbackslash ?} \\ +\ucode{0027} & \uname{apostrohpe} & \tcode{\textbackslash '} \\ +\ucode{0022} & \uname{quotation mark} & \tcode{\textbackslash "} \\ \end{floattable} \rSec2[lex.fcon]{Floating-point literals} @@ -1654,8 +1659,8 @@ \begin{bnf} \nontermdef{basic-s-char}\br - \textnormal{any member of the translation character set except the U+0022 QUOTATION MARK,}\br - \bnfindent\textnormal{U+005C REVERSE SOLIDUS, or new-line character} + \textnormal{any member of the translation character set except the \unicode{0022}{quotation mark},}\br + \bnfindent\textnormal{\unicode{005c}{reverse solidus}, or new-line character} \end{bnf} \begin{bnf} @@ -1671,8 +1676,8 @@ \begin{bnf} \nontermdef{r-char}\br - \textnormal{any member of the translation character set, except a U+0029 RIGHT PARENTHESIS followed by}\br - \bnfindent\textnormal{the initial \grammarterm{d-char-sequence} (which may be empty) followed by a U+0022 QUOTATION MARK} + \textnormal{any member of the translation character set, except a \unicode{0029}{right parenthesis} followed by}\br + \bnfindent\textnormal{the initial \grammarterm{d-char-sequence} (which may be empty) followed by a \unicode{0022}{quotation mark}} \end{bnf} \begin{bnf} @@ -1684,9 +1689,8 @@ \begin{bnf} \nontermdef{d-char}\br \textnormal{any member of the basic character set except:}\br - \bnfindent\textnormal{U+0020 SPACE, U+0028 LEFT PARENTHESIS, U+0029 RIGHT PARENTHESIS,}\br - \bnfindent\textnormal{U+005C REVERSE SOLIDUS, U+0009 CHARACTER TABULATION,}\br - \bnfindent\textnormal{U+000B LINE TABULATION, U+000C FORM FEED (FF), and new-line} + \bnfindent\textnormal{\unicode{0020}{space}, \unicode{0028}{left parenthesis}, \unicode{0029}{right parenthesis}, \unicode{005c}{reverse solidus},}\br + \bnfindent\textnormal{\unicode{0009}{character tabulation}, \unicode{000b}{line tabulation}, \unicode{000c}{form feed}, and new-line} \end{bnf} \pnum @@ -1882,7 +1886,7 @@ corresponding to the \grammarterm{string-literal}'s sequence of \grammarterm{s-char}s (originally from non-raw string literals) and \grammarterm{r-char}s (originally from raw string literals), -plus a terminating U+0000 NULL character, +plus a terminating \unicode{0000}{null} character, in order as follows: \begin{itemize} \item diff --git a/source/macros.tex b/source/macros.tex index b012059397..604edb598a 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -358,6 +358,9 @@ \renewcommand{\fref}[1]{\hyperref[fig:#1]{\figurerefname \nolinebreak[3] \ref*{fig:#1}}} %% NTBS, etc. +\newcommand{\ucode}[1]{\textsc{u}\textsmaller[1]{\kern-0.05em\protect\raisebox{.25ex}{\textsmaller[1]{+}}\uppercase{#1}}} +\newcommand{\uname}[1]{\textsc{#1}} +\newcommand{\unicode}[2]{\ucode{#1} \uname{#2}} \newcommand{\NTS}[1]{\textsc{#1}} \newcommand{\ntbs}{\NTS{ntbs}} \newcommand{\ntmbs}{\NTS{ntmbs}} diff --git a/source/strings.tex b/source/strings.tex index b65235b7c3..c8e1f55b34 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -5772,7 +5772,7 @@ Subsequent calls will store successive UTF-8 code units without consuming any additional input until all the code units have been stored. -If the corresponding Unicode character is U+0000, +If the corresponding Unicode character is \unicode{0000}{null}, the resulting state described is the initial conversion state. \pnum @@ -5781,7 +5781,7 @@ \begin{itemize} \item \tcode{0}, if the next \tcode{n} or fewer bytes complete the multibyte character -that corresponds to the U+0000 Unicode character +that corresponds to the \unicode{0000}{null} Unicode character (which is the value stored). \item between \tcode{1} and \tcode{n} (inclusive), if the next n or fewer bytes complete a valid multibyte character diff --git a/source/uax31.tex b/source/uax31.tex index 392e74ec96..64f4b873b7 100644 --- a/source/uax31.tex +++ b/source/uax31.tex @@ -29,14 +29,14 @@ where \tcode{} has the XID_Start property, \tcode{} has the XID_Continue property, and \tcode{} is a list of characters permitted between continue characters. -For \Cpp{} we add the character U+005F, LOW LINE, or \tcode{_}, +For \Cpp{} we add the character \unicode{005f}{low line}, or \tcode{_}, to the set of permitted \tcode{} characters, the \tcode{} set is empty, and the \tcode{} characters are unmodified. In the grammar used in UAX \#31, this is \begin{codeblock} := * - := XID_Start + U+005F + := XID_Start + @\textrm{\ucode{005f}}@ := + XID_Continue \end{codeblock} diff --git a/source/utilities.tex b/source/utilities.tex index 928c196e3a..a81d5265f5 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -21046,20 +21046,20 @@ The extended grapheme clusters of a string are defined by UAX \#29. The estimated width of the following code points is 2: \begin{itemize} -\item \tcode{U+1100-U+115F} -\item \tcode{U+2329-U+232A} -\item \tcode{U+2E80-U+303E} -\item \tcode{U+3040-U+A4CF} -\item \tcode{U+AC00-U+D7A3} -\item \tcode{U+F900-U+FAFF} -\item \tcode{U+FE10-U+FE19} -\item \tcode{U+FE30-U+FE6F} -\item \tcode{U+FF00-U+FF60} -\item \tcode{U+FFE0-U+FFE6} -\item \tcode{U+1F300-U+1F64F} -\item \tcode{U+1F900-U+1F9FF} -\item \tcode{U+20000-U+2FFFD} -\item \tcode{U+30000-U+3FFFD} +\item \ucode{1100} -- \ucode{115f} +\item \ucode{2329} -- \ucode{232a} +\item \ucode{2e80} -- \ucode{303e} +\item \ucode{3040} -- \ucode{a4cf} +\item \ucode{ac00} -- \ucode{d7a3} +\item \ucode{f900} -- \ucode{faff} +\item \ucode{fe10} -- \ucode{fe19} +\item \ucode{fe30} -- \ucode{fe6f} +\item \ucode{ff00} -- \ucode{ff60} +\item \ucode{ffe0} -- \ucode{ffe6} +\item \ucode{1f300} -- \ucode{1f64f} +\item \ucode{1f900} -- \ucode{1f9ff} +\item \ucode{20000} -- \ucode{2fffd} +\item \ucode{30000} -- \ucode{3fffd} \end{itemize} The estimated width of other code points is 1. From 02f9bb582cadedc590f9eddf7252bf6c327089df Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 7 Nov 2021 20:42:05 +0100 Subject: [PATCH 013/182] [check] Add check for verbatim U+nnnn Also check for uppercase hex digits inside \ucode and \unicode, which do not work well with \textsc. --- tools/check-source.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/check-source.sh b/tools/check-source.sh index 635f103351..e45e7cae92 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -71,6 +71,16 @@ grep -n "// not defined" $texfiles | grep -n '^[^%]*[^{"]C++[^"}]' $texfiles | fail 'use \Cpp{} instead' || failed=1 +# Use \unicode instead of U+nnnn +grep -n 'U+' $texfiles | + fail 'use \\unicode or \\ucode or \\uname instead' || failed=1 + +# Hex digits inside \ucode and \unicode must be lowercase so that \textsc works +grep -n 'ucode{[^}]*[^0-9a-f}][^}]*}' $texfiles | + fail 'use lowercase hex digits inside \\ucode' || failed=1 +grep -n 'unicode{[^}]*[^0-9a-f}][^}]*}' $texfiles | + fail 'use lowercase hex digits inside \\unicode' || failed=1 + # Library element introducer followed by stuff. grep -ne '^\\\(constraints\|mandates\|expects\|effects\|sync\|ensures\|returns\|throws\|complexity\|remarks\|errors\).\+$' $texlibdesc | fail 'stuff after library element' || failed=1 From ae314810325bc109cb2c7e401cf833b20a77d0a0 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 22 Nov 2021 19:43:51 +0100 Subject: [PATCH 014/182] [alg.c.library,c.math.fpclass,cmath.syn] Use \xrefc macro (#5076) and augment the automatic checks to flag literal 'ISO C'. --- source/algorithms.tex | 3 +-- source/numerics.tex | 6 ++---- tools/check-source.sh | 4 ++++ 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/source/algorithms.tex b/source/algorithms.tex index c35079a748..a6e7f7810b 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -10968,5 +10968,4 @@ Any exception thrown by \tcode{compar}\iref{res.on.exception.handling}. \end{itemdescr} -\xref -ISO C 7.22.5. +\xrefc{7.22.5} diff --git a/source/numerics.tex b/source/numerics.tex index e685c29edc..322ec98e0e 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -9949,8 +9949,7 @@ \tcode{abs} is exempted from these rules in order to stay compatible with C. \end{note} -\xref -ISO C 7.12 +\xrefc{7.12} \rSec2[c.math.abs]{Absolute values} @@ -10047,8 +10046,7 @@ corresponding names defined in the C standard library. Each function is overloaded for the three floating-point types. -\xref -ISO C 7.12.3, 7.12.4 +\xrefc{7.12.3, 7.12.4} \rSec2[sf.cmath]{Mathematical special functions}% diff --git a/tools/check-source.sh b/tools/check-source.sh index e45e7cae92..ddcf064298 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -81,6 +81,10 @@ grep -n 'ucode{[^}]*[^0-9a-f}][^}]*}' $texfiles | grep -n 'unicode{[^}]*[^0-9a-f}][^}]*}' $texfiles | fail 'use lowercase hex digits inside \\unicode' || failed=1 +# Use \xrefc instead of "ISO C x.y.z" +grep -n "^ISO C [0-9]*\." $texfiles | + fail 'use \\xrefc instead' || failed=1 + # Library element introducer followed by stuff. grep -ne '^\\\(constraints\|mandates\|expects\|effects\|sync\|ensures\|returns\|throws\|complexity\|remarks\|errors\).\+$' $texlibdesc | fail 'stuff after library element' || failed=1 From c8ec4ab45f58e3a16d8dcb12bd660dd2cf6e936a Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 23 Nov 2021 17:22:38 +0100 Subject: [PATCH 015/182] [refwrap.general] Add cross-references to the class synopsis (#5122) Also rename [refwrap.const], because it does not specify any destructors. --- source/utilities.tex | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index a81d5265f5..9bae004aa8 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -14372,19 +14372,19 @@ // types using type = T; - // construct/copy/destroy + // \ref{refwrap.const}, constructors template constexpr reference_wrapper(U&&) noexcept(@\seebelow@); constexpr reference_wrapper(const reference_wrapper& x) noexcept; - // assignment + // \ref{refwrap.assign}, assignment constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept; - // access + // \ref{refwrap.access}, access constexpr operator T& () const noexcept; constexpr T& get() const noexcept; - // invocation + // \ref{refwrap.invoke}, invocation template constexpr invoke_result_t operator()(ArgTypes&&...) const; }; @@ -14405,7 +14405,7 @@ The template parameter \tcode{T} of \tcode{reference_wrapper} may be an incomplete type. -\rSec3[refwrap.const]{Constructors and destructor} +\rSec3[refwrap.const]{Constructors} \indexlibraryctor{reference_wrapper}% \begin{itemdecl} From b4bf594c81865f892bae81342ffb67c8ca8adb74 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 23 Nov 2021 17:24:35 +0100 Subject: [PATCH 016/182] [smartptr] Rework subclause nesting (#5119) --- source/utilities.tex | 62 +++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index 9bae004aa8..72b0cc9c10 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -8924,7 +8924,7 @@ \rSec1[smartptr]{Smart pointers} -\rSec2[unique.ptr]{Class template \tcode{unique_ptr}} +\rSec2[unique.ptr]{Unique-ownership pointers} \rSec3[unique.ptr.general]{General} @@ -10161,7 +10161,9 @@ \tcode{os}. \end{itemdescr} -\rSec2[util.smartptr.weak.bad]{Class \tcode{bad_weak_ptr}}% +\rSec2[util.sharedptr]{Shared-ownership pointers} + +\rSec3[util.smartptr.weak.bad]{Class \tcode{bad_weak_ptr}}% \indextext{smart pointers|(}% \indexlibraryglobal{bad_weak_ptr}% @@ -10190,9 +10192,9 @@ An \impldef{return value of \tcode{bad_weak_ptr::what}} \ntbs{}. \end{itemdescr} -\rSec2[util.smartptr.shared]{Class template \tcode{shared_ptr}} +\rSec3[util.smartptr.shared]{Class template \tcode{shared_ptr}} -\rSec3[util.smartptr.shared.general]{General} +\rSec4[util.smartptr.shared.general]{General} \pnum \indexlibraryglobal{shared_ptr}% @@ -10317,7 +10319,7 @@ \tcode{Y*} is convertible to \tcode{T*} or \tcode{Y} is \tcode{U[N]} and \tcode{T} is \cv{}~\tcode{U[]}. -\rSec3[util.smartptr.shared.const]{Constructors} +\rSec4[util.smartptr.shared.const]{Constructors} \pnum In the constructor definitions below, @@ -10573,7 +10575,7 @@ If an exception is thrown, the constructor has no effect. \end{itemdescr} -\rSec3[util.smartptr.shared.dest]{Destructor} +\rSec4[util.smartptr.shared.dest]{Destructor} \indexlibrarydtor{shared_ptr}% \begin{itemdecl} @@ -10607,7 +10609,7 @@ than its previous value. \end{note} -\rSec3[util.smartptr.shared.assign]{Assignment} +\rSec4[util.smartptr.shared.assign]{Assignment} \indexlibrarymember{operator=}{shared_ptr}% \begin{itemdecl} @@ -10672,7 +10674,7 @@ \tcode{*this}. \end{itemdescr} -\rSec3[util.smartptr.shared.mod]{Modifiers} +\rSec4[util.smartptr.shared.mod]{Modifiers} \indexlibrarymember{swap}{shared_ptr}% \begin{itemdecl} @@ -10730,7 +10732,7 @@ Equivalent to \tcode{shared_ptr(p, d, a).swap(*this)}. \end{itemdescr} -\rSec3[util.smartptr.shared.obs]{Observers} +\rSec4[util.smartptr.shared.obs]{Observers} \indexlibrarymember{get}{shared_ptr}% \begin{itemdecl} element_type* get() const noexcept; @@ -10886,7 +10888,7 @@ \end{itemdescr} -\rSec3[util.smartptr.shared.create]{Creation} +\rSec4[util.smartptr.shared.create]{Creation} \pnum The common requirements that apply to all @@ -11259,7 +11261,7 @@ \end{example} \end{itemdescr} -\rSec3[util.smartptr.shared.cmp]{Comparison} +\rSec4[util.smartptr.shared.cmp]{Comparison} \indexlibrarymember{operator==}{shared_ptr}% \begin{itemdecl} @@ -11317,7 +11319,7 @@ \end{codeblock} \end{itemdescr} -\rSec3[util.smartptr.shared.spec]{Specialized algorithms} +\rSec4[util.smartptr.shared.spec]{Specialized algorithms} \indexlibrarymember{swap}{shared_ptr}% \begin{itemdecl} @@ -11331,7 +11333,7 @@ Equivalent to \tcode{a.swap(b)}. \end{itemdescr} -\rSec3[util.smartptr.shared.cast]{Casts} +\rSec4[util.smartptr.shared.cast]{Casts} \indexlibrarymember{static_pointer_cast}{shared_ptr}% \begin{itemdecl} @@ -11458,7 +11460,7 @@ \end{note} \end{itemdescr} -\rSec3[util.smartptr.getdeleter]{\tcode{get_deleter}} +\rSec4[util.smartptr.getdeleter]{\tcode{get_deleter}} \indexlibrarymember{get_deleter}{shared_ptr}% \begin{itemdecl} @@ -11482,7 +11484,7 @@ \end{note} \end{itemdescr} -\rSec3[util.smartptr.shared.io]{I/O} +\rSec4[util.smartptr.shared.io]{I/O} \indexlibrarymember{operator<<}{shared_ptr}% \begin{itemdecl} @@ -11500,9 +11502,9 @@ \tcode{os}. \end{itemdescr} -\rSec2[util.smartptr.weak]{Class template \tcode{weak_ptr}} +\rSec3[util.smartptr.weak]{Class template \tcode{weak_ptr}} -\rSec3[util.smartptr.weak.general]{General} +\rSec4[util.smartptr.weak.general]{General} \pnum \indexlibraryglobal{weak_ptr}% @@ -11566,7 +11568,7 @@ containers. The template parameter \tcode{T} of \tcode{weak_ptr} may be an incomplete type. -\rSec3[util.smartptr.weak.const]{Constructors} +\rSec4[util.smartptr.weak.const]{Constructors} \indexlibraryctor{weak_ptr}% \begin{itemdecl} @@ -11629,7 +11631,7 @@ \tcode{r} is empty, stores a null pointer value, and \tcode{r.use_count() == 0}. \end{itemdescr} -\rSec3[util.smartptr.weak.dest]{Destructor} +\rSec4[util.smartptr.weak.dest]{Destructor} \indexlibrarydtor{weak_ptr}% \begin{itemdecl} @@ -11643,7 +11645,7 @@ effect on the object its stored pointer points to. \end{itemdescr} -\rSec3[util.smartptr.weak.assign]{Assignment} +\rSec4[util.smartptr.weak.assign]{Assignment} \indexlibrarymember{operator=}{weak_ptr}% \begin{itemdecl} @@ -11683,7 +11685,7 @@ \tcode{*this}. \end{itemdescr} -\rSec3[util.smartptr.weak.mod]{Modifiers} +\rSec4[util.smartptr.weak.mod]{Modifiers} \indexlibrarymember{swap}{weak_ptr}% \begin{itemdecl} void swap(weak_ptr& r) noexcept; @@ -11706,7 +11708,7 @@ Equivalent to \tcode{weak_ptr().swap(*this)}. \end{itemdescr} -\rSec3[util.smartptr.weak.obs]{Observers} +\rSec4[util.smartptr.weak.obs]{Observers} \indexlibrarymember{use_count}{weak_ptr}% \begin{itemdecl} long use_count() const noexcept; @@ -11763,7 +11765,7 @@ \end{itemdescr} -\rSec3[util.smartptr.weak.spec]{Specialized algorithms} +\rSec4[util.smartptr.weak.spec]{Specialized algorithms} \indexlibrarymember{swap}{weak_ptr}% \begin{itemdecl} @@ -11777,7 +11779,7 @@ Equivalent to \tcode{a.swap(b)}. \end{itemdescr} -\rSec2[util.smartptr.ownerless]{Class template \tcode{owner_less}} +\rSec3[util.smartptr.ownerless]{Class template \tcode{owner_less}} \pnum The class template \tcode{owner_less} allows ownership-based mixed comparisons of shared @@ -11831,7 +11833,7 @@ \end{itemize} \end{note} -\rSec2[util.smartptr.enab]{Class template \tcode{enable_shared_from_this}} +\rSec3[util.smartptr.enab]{Class template \tcode{enable_shared_from_this}} \pnum \indexlibraryglobal{enable_shared_from_this}% @@ -11963,7 +11965,9 @@ \end{itemdescr}% \indextext{smart pointers|)} -\rSec2[out.ptr.t]{Class template \tcode{out_ptr_t}} +\rSec2[smartptr.adapt]{Smart pointer adaptors} + +\rSec3[out.ptr.t]{Class template \tcode{out_ptr_t}} \pnum \tcode{out_ptr_t} is a class template used to adapt types @@ -12163,7 +12167,7 @@ \end{note} \end{itemdescr} -\rSec2[out.ptr]{Function template \tcode{out_ptr}} +\rSec3[out.ptr]{Function template \tcode{out_ptr}} \indexlibraryglobal{out_ptr}% \begin{itemdecl} @@ -12182,7 +12186,7 @@ \tcode{out_ptr_t(s, std::forward(args)...)} \end{itemdescr} -\rSec2[inout.ptr.t]{Class template \tcode{inout_ptr_t}} +\rSec3[inout.ptr.t]{Class template \tcode{inout_ptr_t}} \pnum \tcode{inout_ptr_t} is a class template used to adapt types @@ -12401,7 +12405,7 @@ \end{note} \end{itemdescr} -\rSec2[inout.ptr]{Function template \tcode{inout_ptr}} +\rSec3[inout.ptr]{Function template \tcode{inout_ptr}} \indexlibraryglobal{inout_ptr}% \begin{itemdecl} From d0cb462d511e5c9bf1ae7403c275f7c1ccf2543d Mon Sep 17 00:00:00 2001 From: Hewill Kang <67143766+hewillk@users.noreply.github.com> Date: Sat, 20 Nov 2021 02:16:40 +0800 Subject: [PATCH 017/182] [range.adjacent.overview] Fix multi-character in example --- source/ranges.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/ranges.tex b/source/ranges.tex index 91d74512d2..7fc5643bdd 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -8926,7 +8926,7 @@ vector v = {1, 2, 3, 4}; for (auto i : v | views::adjacent<2>) { - cout << '(' << i.first << ', ' << i.second << ") "; // prints: (1, 2) (2, 3) (3, 4) + cout << "(" << i.first << ", " << i.second << ") "; // prints: (1, 2) (2, 3) (3, 4) } \end{codeblock} \end{example} From 26f6a1f7573ea54ed93b4e90d0e487fe39d44b87 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 13 Nov 2021 10:01:36 +0100 Subject: [PATCH 018/182] [dcl.typedef] Add explanation for lookup failure in example --- source/declarations.tex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/declarations.tex b/source/declarations.tex index 8c86e2ee99..b3c2f9b3e7 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -621,7 +621,8 @@ using handler_t = void (*)(int); extern handler_t ignore; extern void (*ignore)(int); // redeclare \tcode{ignore} -using cell = pair; // error +template struct P { }; +using cell = P; // error: \tcode{cell} not found\iref{basic.scope.pdecl} \end{codeblock} \end{example} The \grammarterm{defining-type-specifier-seq} From c63e5e836e8dbe0ae6c7ebc1b2a1b1534d37a220 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 10 Nov 2021 23:40:48 +0100 Subject: [PATCH 019/182] [input.output] Fix headings of 'assign and swap' subclauses --- source/iostreams.tex | 64 ++++++++++++++++++++++++-------------------- source/xrefdelta.tex | 7 +++++ 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/source/iostreams.tex b/source/iostreams.tex index 2ea745316f..9c1c8d94a6 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -4291,7 +4291,7 @@ basic_istream(const basic_istream&) = delete; basic_istream(basic_istream&& rhs); - // \ref{istream.assign}, assign and swap + // \ref{istream.assign}, assignment and swap basic_istream& operator=(const basic_istream&) = delete; basic_istream& operator=(basic_istream&& rhs); void swap(basic_istream& rhs); @@ -5714,7 +5714,7 @@ basic_iostream(const basic_iostream&) = delete; basic_iostream(basic_iostream&& rhs); - // \ref{iostream.assign}, assign and swap + // \ref{iostream.assign}, assignment and swap basic_iostream& operator=(const basic_iostream&) = delete; basic_iostream& operator=(basic_iostream&& rhs); void swap(basic_iostream& rhs); @@ -5874,7 +5874,7 @@ basic_ostream(const basic_ostream&) = delete; basic_ostream(basic_ostream&& rhs); - // \ref{ostream.assign}, assign and swap + // \ref{ostream.assign}, assignment and swap basic_ostream& operator=(const basic_ostream&) = delete; basic_ostream& operator=(basic_ostream&& rhs); void swap(basic_ostream& rhs); @@ -7587,7 +7587,7 @@ basic_stringbuf(basic_stringbuf&& rhs); basic_stringbuf(basic_stringbuf&& rhs, const Allocator& a); - // \ref{stringbuf.assign}, assign and swap + // \ref{stringbuf.assign}, assignment and swap basic_stringbuf& operator=(const basic_stringbuf&) = delete; basic_stringbuf& operator=(basic_stringbuf&& rhs); void swap(basic_stringbuf& rhs) noexcept(@\seebelow@); @@ -8383,9 +8383,10 @@ basic_istringstream(const basic_istringstream&) = delete; basic_istringstream(basic_istringstream&& rhs); - // \ref{istringstream.assign}, assign and swap basic_istringstream& operator=(const basic_istringstream&) = delete; basic_istringstream& operator=(basic_istringstream&& rhs); + + // \ref{istringstream.swap}, swap void swap(basic_istringstream& rhs); // \ref{istringstream.members}, members @@ -8532,7 +8533,7 @@ to install the contained \tcode{basic_stringbuf}. \end{itemdescr} -\rSec3[istringstream.assign]{Assignment and swap} +\rSec3[istringstream.swap]{Swap} \indexlibrarymember{swap}{basic_istringstream}% \begin{itemdecl} @@ -8697,9 +8698,10 @@ basic_ostringstream(const basic_ostringstream&) = delete; basic_ostringstream(basic_ostringstream&& rhs); - // \ref{ostringstream.assign}, assign and swap basic_ostringstream& operator=(const basic_ostringstream&) = delete; basic_ostringstream& operator=(basic_ostringstream&& rhs); + + // \ref{ostringstream.swap}, swap void swap(basic_ostringstream& rhs); // \ref{ostringstream.members}, members @@ -8851,7 +8853,7 @@ to install the contained \tcode{basic_stringbuf}. \end{itemdescr} -\rSec3[ostringstream.assign]{Assignment and swap} +\rSec3[ostringstream.swap]{Swap} \indexlibrarymember{swap}{basic_ostringstream}% \begin{itemdecl} @@ -9016,9 +9018,10 @@ basic_stringstream(const basic_stringstream&) = delete; basic_stringstream(basic_stringstream&& rhs); - // \ref{stringstream.assign}, assign and swap basic_stringstream& operator=(const basic_stringstream&) = delete; basic_stringstream& operator=(basic_stringstream&& rhs); + + // \ref{stringstream.swap}, swap void swap(basic_stringstream& rhs); // \ref{stringstream.members}, members @@ -9175,7 +9178,7 @@ to install the contained \tcode{basic_stringbuf}. \end{itemdescr} -\rSec3[stringstream.assign]{Assignment and swap} +\rSec3[stringstream.swap]{Swap} \indexlibrarymember{swap}{basic_stringstream}% \begin{itemdecl} @@ -9707,9 +9710,10 @@ basic_ispanstream(basic_ispanstream&& rhs); template explicit basic_ispanstream(ROS&& s); - // \ref{ispanstream.assign}, assignment and swap basic_ispanstream& operator=(const basic_ispanstream&) = delete; basic_ispanstream& operator=(basic_ispanstream&& rhs); + + // \ref{ispanstream.swap}, swap void swap(basic_ispanstream& rhs); // \ref{ispanstream.members}, member functions @@ -9786,7 +9790,7 @@ \end{codeblock} \end{itemdescr} -\rSec3[ispanstream.assign]{Assignment and swap} +\rSec3[ispanstream.swap]{Swap} \indexlibrarymember{swap}{basic_ispanstream}% \begin{itemdecl} @@ -9896,9 +9900,10 @@ basic_ospanstream(const basic_ospanstream&) = delete; basic_ospanstream(basic_ospanstream&& rhs); - // \ref{ospanstream.assign}, assignment and swap basic_ospanstream& operator=(const basic_ospanstream&) = delete; basic_ospanstream& operator=(basic_ospanstream&& rhs); + + // \ref{ospanstream.swap}, swap void swap(basic_ospanstream& rhs); // \ref{ospanstream.members}, member functions @@ -9946,7 +9951,7 @@ is called to install the contained \tcode{basic_spanbuf}. \end{itemdescr} -\rSec3[ospanstream.assign]{Assignment and swap} +\rSec3[ospanstream.swap]{Swap} \indexlibrarymember{swap}{basic_ospanstream}% \begin{itemdecl} @@ -10036,9 +10041,10 @@ basic_spanstream(const basic_spanstream&) = delete; basic_spanstream(basic_spanstream&& rhs); - // \ref{spanstream.assign}, assignment and swap basic_spanstream& operator=(const basic_spanstream&) = delete; basic_spanstream& operator=(basic_spanstream&& rhs); + + // \ref{spanstream.swap}, swap void swap(basic_spanstream& rhs); // \ref{spanstream.members}, members @@ -10086,7 +10092,7 @@ is called to install the contained \tcode{basic_spanbuf}. \end{itemdescr} -\rSec3[spanstream.assign]{Assignment and swap} +\rSec3[spanstream.swap]{Swap} \indexlibrarymember{swap}{basic_spanstream}% \begin{itemdecl} @@ -10257,7 +10263,7 @@ basic_filebuf(basic_filebuf&& rhs); virtual ~basic_filebuf(); - // \ref{filebuf.assign}, assign and swap + // \ref{filebuf.assign}, assignment and swap basic_filebuf& operator=(const basic_filebuf&) = delete; basic_filebuf& operator=(basic_filebuf&& rhs); void swap(basic_filebuf& rhs); @@ -10447,8 +10453,7 @@ \indexlibrarymember{swap}{basic_filebuf}% \begin{itemdecl} template - void swap(basic_filebuf& x, - basic_filebuf& y); + void swap(basic_filebuf& x, basic_filebuf& y); \end{itemdecl} \begin{itemdescr} @@ -11031,9 +11036,10 @@ basic_ifstream(const basic_ifstream&) = delete; basic_ifstream(basic_ifstream&& rhs); - // \ref{ifstream.assign}, assign and swap basic_ifstream& operator=(const basic_ifstream&) = delete; basic_ifstream& operator=(basic_ifstream&& rhs); + + // \ref{ifstream.swap}, swap void swap(basic_ifstream& rhs); // \ref{ifstream.members}, members @@ -11144,7 +11150,7 @@ to install the contained \tcode{basic_filebuf}. \end{itemdescr} -\rSec3[ifstream.assign]{Assignment and swap} +\rSec3[ifstream.swap]{Swap} \indexlibrarymember{swap}{basic_ifstream}% \begin{itemdecl} @@ -11163,8 +11169,7 @@ \indexlibrarymember{swap}{basic_ifstream}% \begin{itemdecl} template - void swap(basic_ifstream& x, - basic_ifstream& y); + void swap(basic_ifstream& x, basic_ifstream& y); \end{itemdecl} \begin{itemdescr} @@ -11276,9 +11281,10 @@ basic_ofstream(const basic_ofstream&) = delete; basic_ofstream(basic_ofstream&& rhs); - // \ref{ofstream.assign}, assign and swap basic_ofstream& operator=(const basic_ofstream&) = delete; basic_ofstream& operator=(basic_ofstream&& rhs); + + // \ref{ofstream.swap}, swap void swap(basic_ofstream& rhs); // \ref{ofstream.members}, members @@ -11389,7 +11395,7 @@ to install the contained \tcode{basic_filebuf}. \end{itemdescr} -\rSec3[ofstream.assign]{Assignment and swap} +\rSec3[ofstream.swap]{Swap} \indexlibrarymember{swap}{basic_ofstream}% \begin{itemdecl} @@ -11408,8 +11414,7 @@ \indexlibrarymember{swap}{basic_ofstream}% \begin{itemdecl} template - void swap(basic_ofstream& x, - basic_ofstream& y); + void swap(basic_ofstream& x, basic_ofstream& y); \end{itemdecl} \begin{itemdescr} @@ -11522,9 +11527,10 @@ basic_fstream(const basic_fstream&) = delete; basic_fstream(basic_fstream&& rhs); - // \ref{fstream.assign}, assign and swap basic_fstream& operator=(const basic_fstream&) = delete; basic_fstream& operator=(basic_fstream&& rhs); + + // \ref{fstream.swap}, swap void swap(basic_fstream& rhs); // \ref{fstream.members}, members @@ -11645,7 +11651,7 @@ to install the contained \tcode{basic_filebuf}. \end{itemdescr} -\rSec3[fstream.assign]{Assignment and swap} +\rSec3[fstream.swap]{Swap} \indexlibrarymember{swap}{basic_fstream}% \begin{itemdecl} diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index aa5fc326ea..fbd137a397 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -82,5 +82,12 @@ \movedxref{depr.stdbool.h.syn}{stdbool.h.syn} \movedxref{depr.tgmath.h.syn}{tgmath.h.syn} +\movedxref{istringstream.assign}{istringstream.swap} +\movedxref{ostringstream.assign}{ostringstream.swap} +\movedxref{stringstream.assign}{stringstream.swap} +\movedxref{ifstream.assign}{ifstream.swap} +\movedxref{ofstream.assign}{ofstream.swap} +\movedxref{fstream.assign}{fstream.swap} + % Deprecated features. %\deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) From d2699e5de0c10085df309074d2dfbc57d5bc86bb Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 27 Oct 2021 21:20:02 +0200 Subject: [PATCH 020/182] [std] Replace 'OK:' in code comments with 'OK,' In contrast to errors, which use a colon, an OK comment is not followed by any unique reason why the code is well-formed, but by a subjective highlighting of a fact. --- source/basic.tex | 84 ++++++++++++++-------------- source/classes.tex | 98 ++++++++++++++++----------------- source/compatibility.tex | 4 +- source/declarations.tex | 116 +++++++++++++++++++-------------------- source/expressions.tex | 52 +++++++++--------- source/lex.tex | 2 +- source/lib-intro.tex | 6 +- source/overloading.tex | 30 +++++----- source/templates.tex | 100 ++++++++++++++++----------------- 9 files changed, 246 insertions(+), 246 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 51503ca73d..f8ed8b751d 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -950,7 +950,7 @@ enum E : int { a }; void f(int); // \#1 void f(Int) {} // defines \#1 -void f(E) {} // OK: another overload +void f(E) {} // OK, another overload struct X { static void f(); @@ -960,7 +960,7 @@ void g() &; // error: redeclaration void h(this X&, int); - void h(int) &&; // OK: another overload + void h(int) &&; // OK, another overload void j(this const X&); void j() const&; // error: redeclaration void k(); @@ -993,9 +993,9 @@ enum { f }; // error: different entity for \tcode{::f} namespace A {} namespace B = A; -namespace B = A; // OK: no effect -namespace B = B; // OK: no effect -namespace A = B; // OK: no effect +namespace B = A; // OK, no effect +namespace B = B; // OK, no effect +namespace A = B; // OK, no effect namespace B {} // error: different entity for \tcode{B} \end{codeblock} \end{example} @@ -1452,7 +1452,7 @@ \begin{codeblocktu}{Translation unit \#3} import R; -int main() { return sq(9); } // OK: \tcode{sq} from module \tcode{Q} +int main() { return sq(9); } // OK, \tcode{sq} from module \tcode{Q} \end{codeblocktu} \end{example} \end{note} @@ -1616,9 +1616,9 @@ struct D : B, C { }; void f(D* pd) { - pd->v++; // OK: only one \tcode{v} (virtual) - pd->s++; // OK: only one \tcode{s} (static) - int i = pd->e; // OK: only one \tcode{e} (enumerator) + pd->v++; // OK, only one \tcode{v} (virtual) + pd->s++; // OK, only one \tcode{s} (static) + int i = pd->e; // OK, only one \tcode{e} (enumerator) pd->a++; // error: ambiguous: two \tcode{a}{s} in \tcode{D} } \end{codeblock} @@ -1658,8 +1658,8 @@ right-hand instance of \tcode{W} are not hidden at all. \begin{codeblock} void D::glorp() { - x++; // OK: \tcode{B::x} hides \tcode{V::x} - f(); // OK: \tcode{B::f()} hides \tcode{V::f()} + x++; // OK, \tcode{B::x} hides \tcode{V::x} + f(); // OK, \tcode{B::f()} hides \tcode{V::f()} y++; // error: \tcode{B::y} and \tcode{C}'s \tcode{W::y} g(); // error: \tcode{B::g()} and \tcode{C}'s \tcode{W::g()} } @@ -1685,7 +1685,7 @@ D d; B* pb = &d; A* pa = &d; // error: ambiguous: \tcode{C}'s \tcode{A} or \tcode{B}'s \tcode{A}? - V* pv = &d; // OK: only one \tcode{V} subobject + V* pv = &d; // OK, only one \tcode{V} subobject } \end{codeblock} \end{example} @@ -1886,7 +1886,7 @@ void g() { N::S s; - f(s); // OK: calls \tcode{N::f} + f(s); // OK, calls \tcode{N::f} (f)(s); // error: \tcode{N::f} not considered; parentheses prevent argument-dependent lookup } \end{codeblock} @@ -1913,8 +1913,8 @@ template int h(T); } -int x = f(N::A()); // OK: lookup of \tcode{f} finds nothing, \tcode{f} treated as template name -int y = g(N::A()); // OK: lookup of \tcode{g} finds a function, \tcode{g} treated as template name +int x = f(N::A()); // OK, lookup of \tcode{f} finds nothing, \tcode{f} treated as template name +int y = g(N::A()); // OK, lookup of \tcode{g} finds a function, \tcode{g} treated as template name int z = h(N::A()); // error: \tcode{h<} does not begin a \grammarterm{template-id} \end{codeblock} @@ -2086,9 +2086,9 @@ NS::T parm; void g(NS::T, float); int main() { - f(parm); // OK: calls \tcode{NS::f} + f(parm); // OK, calls \tcode{NS::f} extern void g(NS::T, float); - g(parm, 1); // OK: calls \tcode{g(NS::T, float)} + g(parm, 1); // OK, calls \tcode{g(NS::T, float)} } \end{codeblock} \end{example} @@ -2215,8 +2215,8 @@ template void g(T *p) { // as instantiated for \tcode{g}: p->X<0>::f(); // error: \tcode{A::X} not found in \tcode{((p->X) < 0) > ::f()} - p->template X<0>::f(); // OK: \tcode{::X} found in definition context - p->B::f(); // OK: non-type \tcode{A::B} ignored + p->template X<0>::f(); // OK, \tcode{::X} found in definition context + p->B::f(); // OK, non-type \tcode{A::B} ignored p->template C<0>::f(); // error: \tcode{A::C} is not a template p->template D<0>::f(); // error: \tcode{A::D<0>} is not a class type p->T::f(); // error: \tcode{A::T} is not a class type @@ -2405,7 +2405,7 @@ void f() { - BC::a++; // OK: \tcode{S} is $\{ \tcode{A::a}, \tcode{A::a} \}$ + BC::a++; // OK, \tcode{S} is $\{ \tcode{A::a}, \tcode{A::a} \}$ } namespace D { @@ -2419,7 +2419,7 @@ void g() { - BD::a++; // OK: \tcode{S} is $\{ \tcode{A::a}, \tcode{A::a} \}$ + BD::a++; // OK, \tcode{S} is $\{ \tcode{A::a}, \tcode{A::a} \}$ } \end{codeblock} \end{example} @@ -2445,10 +2445,10 @@ void f() { - A::a++; // OK: \tcode{a} declared directly in \tcode{A}, \tcode{S} is $\{ \tcode{A::a} \}$ - B::a++; // OK: both \tcode{A} and \tcode{B} searched (once), \tcode{S} is $\{ \tcode{A::a} \}$ - A::b++; // OK: both \tcode{A} and \tcode{B} searched (once), \tcode{S} is $\{ \tcode{B::b} \}$ - B::b++; // OK: \tcode{b} declared directly in \tcode{B}, \tcode{S} is $\{ \tcode{B::b} \}$ + A::a++; // OK, \tcode{a} declared directly in \tcode{A}, \tcode{S} is $\{ \tcode{A::a} \}$ + B::a++; // OK, both \tcode{A} and \tcode{B} searched (once), \tcode{S} is $\{ \tcode{A::a} \}$ + A::b++; // OK, both \tcode{A} and \tcode{B} searched (once), \tcode{S} is $\{ \tcode{B::b} \}$ + B::b++; // OK, \tcode{b} declared directly in \tcode{B}, \tcode{S} is $\{ \tcode{B::b} \}$ } \end{codeblock} \end{example} @@ -2509,31 +2509,31 @@ \begin{example} \begin{codeblock} struct Node { - struct Node* Next; // OK: Refers to injected-class-name \tcode{Node} - struct Data* Data; // OK: Declares type \tcode{Data} at global scope and member \tcode{Data} + struct Node* Next; // OK, refers to injected-class-name \tcode{Node} + struct Data* Data; // OK, declares type \tcode{Data} at global scope and member \tcode{Data} }; struct Data { - struct Node* Node; // OK: Refers to \tcode{Node} at global scope + struct Node* Node; // OK, refers to \tcode{Node} at global scope friend struct ::Glob; // error: \tcode{Glob} is not declared, cannot introduce a qualified type\iref{dcl.type.elab} - friend struct Glob; // OK: Refers to (as yet) undeclared \tcode{Glob} at global scope. + friend struct Glob; // OK, refers to (as yet) undeclared \tcode{Glob} at global scope. @\commentellip@ }; struct Base { - struct Data; // OK: Declares nested \tcode{Data} - struct ::Data* thatData; // OK: Refers to \tcode{::Data} - struct Base::Data* thisData; // OK: Refers to nested \tcode{Data} - friend class ::Data; // OK: global \tcode{Data} is a friend - friend class Data; // OK: nested \tcode{Data} is a friend + struct Data; // OK, declares nested \tcode{Data} + struct ::Data* thatData; // OK, refers to \tcode{::Data} + struct Base::Data* thisData; // OK, refers to nested \tcode{Data} + friend class ::Data; // OK, global \tcode{Data} is a friend + friend class Data; // OK, nested \tcode{Data} is a friend struct Data { @\commentellip@ }; // Defines nested \tcode{Data} }; -struct Data; // OK: Redeclares \tcode{Data} at global scope +struct Data; // OK, redeclares \tcode{Data} at global scope struct ::Data; // error: cannot introduce a qualified type\iref{dcl.type.elab} struct Base::Data; // error: cannot introduce a qualified type\iref{dcl.type.elab} struct Base::Datum; // error: \tcode{Datum} undefined -struct Base::Data* pBase; // OK: refers to nested \tcode{Data} +struct Base::Data* pBase; // OK, refers to nested \tcode{Data} \end{codeblock} \end{example} \indextext{lookup!elaborated type specifier|)}% @@ -2739,7 +2739,7 @@ module; #include "decls.h" export module M; -export using ::f; // OK: does not declare an entity, exports \#1 +export using ::f; // OK, does not declare an entity, exports \#1 int g(); // error: matches \#2, but attached to \tcode{M} export int h(); // \#3 export int k(); // \#4 @@ -2799,7 +2799,7 @@ \begin{codeblock} int f(int x, int x); // error: different entities for \tcode{x} void g(); // \#1 -void g(int); // OK: different entity from \#1 +void g(int); // OK, different entity from \#1 int g(); // error: same entity as \#1 with different type void h(); // \#2 namespace h {} // error: same entity as \#2, but not a function @@ -3458,8 +3458,8 @@ void* p = std::malloc(sizeof(D1) + sizeof(D2)); B* pb = new (p) D1; pb->mutate(); - *pb; // OK: \tcode{pb} points to valid memory - void* q = pb; // OK: \tcode{pb} points to valid memory + *pb; // OK, \tcode{pb} points to valid memory + void* q = pb; // OK, \tcode{pb} points to valid memory pb->f(); // undefined behavior: lifetime of \tcode{*pb} has ended } \end{codeblock} @@ -4651,7 +4651,7 @@ void foo() { xp++; // error: \tcode{X} is incomplete arrp++; // error: incomplete type - arrpp++; // OK: sizeof \tcode{UNKA*} is known + arrpp++; // OK, sizeof \tcode{UNKA*} is known } struct X { int i; }; // now \tcode{X} is a complete type @@ -4661,7 +4661,7 @@ void bar() { xp = &x; // OK; type is ``pointer to \tcode{X}'' arrp = &arr; // OK; qualification conversion\iref{conv.qual} - xp++; // OK: \tcode{X} is complete + xp++; // OK, \tcode{X} is complete arrp++; // error: \tcode{UNKA} can't be completed } \end{codeblock} diff --git a/source/classes.tex b/source/classes.tex index 1a20b4aa5a..8f8da3465f 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -128,12 +128,12 @@ \begin{example} \begin{codeblock} struct A; -struct A final {}; // OK: definition of \tcode{struct A}, +struct A final {}; // OK, definition of \tcode{struct A}, // not value-initialization of variable \tcode{final} struct X { struct C { constexpr operator int() { return 5; } }; - struct B final : C{}; // OK: definition of nested class \tcode{B}, + struct B final : C{}; // OK, definition of nested class \tcode{B}, // not declaration of a bit-field member \tcode{final} }; \end{codeblock} @@ -619,8 +619,8 @@ \begin{codeblock} struct S { using T = void(); - T * p = 0; // OK: \grammarterm{brace-or-equal-initializer} - virtual T f = 0; // OK: \grammarterm{pure-specifier} + T * p = 0; // OK, \grammarterm{brace-or-equal-initializer} + virtual T f = 0; // OK, \grammarterm{pure-specifier} }; \end{codeblock} \end{example} @@ -2396,7 +2396,7 @@ Y a; int b = a; // error: no viable conversion (\tcode{a.operator X().operator int()} not considered) -int c = X(a); // OK: \tcode{a.operator X().operator int()} +int c = X(a); // OK, \tcode{a.operator X().operator int()} \end{codeblock} \end{example} @@ -2446,15 +2446,15 @@ explicit Z(int, int); }; -Z a; // OK: default-initialization performed -Z b{}; // OK: direct initialization syntax used +Z a; // OK, default-initialization performed +Z b{}; // OK, direct initialization syntax used Z c = {}; // error: copy-list-initialization Z a1 = 1; // error: no implicit conversion -Z a3 = Z(1); // OK: direct initialization syntax used -Z a2(1); // OK: direct initialization syntax used -Z* p = new Z(1); // OK: direct initialization syntax used -Z a4 = (Z)1; // OK: explicit cast used -Z a5 = static_cast(1); // OK: explicit cast used +Z a3 = Z(1); // OK, direct initialization syntax used +Z a2(1); // OK, direct initialization syntax used +Z* p = new Z(1); // OK, direct initialization syntax used +Z a4 = (Z)1; // OK, explicit cast used +Z a5 = static_cast(1); // OK, explicit cast used Z a6 = { 3, 4 }; // error: no implicit conversion \end{codeblock} \end{example} @@ -2539,9 +2539,9 @@ }; void h(Z z) { - Y y1(z); // OK: direct-initialization + Y y1(z); // OK, direct-initialization Y y2 = z; // error: no conversion function candidate for copy-initialization - Y y3 = (Y)z; // OK: cast notation + Y y3 = (Y)z; // OK, cast notation } void g(X a, X b) { @@ -2648,7 +2648,7 @@ process& g(); void f() { - process::reschedule(); // OK: no object necessary + process::reschedule(); // OK, no object necessary g().reschedule(); // \tcode{g()} is called } \end{codeblock} @@ -2887,14 +2887,14 @@ struct inner { void f(int i) { - int a = sizeof(x); // OK: operand of sizeof is an unevaluated operand + int a = sizeof(x); // OK, operand of sizeof is an unevaluated operand x = i; // error: assign to \tcode{enclose::x} - s = i; // OK: assign to \tcode{enclose::s} - ::x = i; // OK: assign to global \tcode{x} - y = i; // OK: assign to global \tcode{y} + s = i; // OK, assign to \tcode{enclose::s} + ::x = i; // OK, assign to global \tcode{x} + y = i; // OK, assign to global \tcode{y} } void g(enclose* p, int i) { - p->x = i; // OK: assign to \tcode{enclose::x} + p->x = i; // OK, assign to \tcode{enclose::x} } }; }; @@ -3069,9 +3069,9 @@ union C { B b; int k; }; int f() { C c; // does not start lifetime of any union member - c.b.a.y[3] = 4; // OK: $S($\tcode{c.b.a.y[3]}$)$ contains \tcode{c.b} and \tcode{c.b.a.y}; + c.b.a.y[3] = 4; // OK, $S($\tcode{c.b.a.y[3]}$)$ contains \tcode{c.b} and \tcode{c.b.a.y}; // creates objects to hold union members \tcode{c.b} and \tcode{c.b.a.y} - return c.b.a.y[3]; // OK: \tcode{c.b.a.y} refers to newly created object (see \ref{basic.life}) + return c.b.a.y[3]; // OK, \tcode{c.b.a.y} refers to newly created object (see \ref{basic.life}) } struct X { const int a; int b; }; @@ -3079,7 +3079,7 @@ void g() { Y y = { { 1, 2 } }; // OK, \tcode{y.x} is active union member\iref{class.mem} int n = y.x.a; - y.k = 4; // OK: ends lifetime of \tcode{y.x}, \tcode{y.k} is active member of union + y.k = 4; // OK, ends lifetime of \tcode{y.x}, \tcode{y.k} is active member of union y.x.b = n; // undefined behavior: \tcode{y.x.b} modified outside its lifetime, // $S($\tcode{y.x.b}$)$ is empty because \tcode{X}'s default constructor is deleted, // so union member \tcode{y.x}'s lifetime does not implicitly start @@ -3228,7 +3228,7 @@ int h() { return s; } // OK int k() { return ::x; } // OK int l() { return q(); } // OK - int m() { return N; } // OK: not an odr-use + int m() { return N; } // OK, not an odr-use int* n() { return &N; } // error: odr-use of non-odr-usable variable \tcode{N} int p() { return y; } // error: odr-use of non-odr-usable structured binding \tcode{y} }; @@ -3656,7 +3656,7 @@ struct A { virtual void f(); }; struct B : A { }; struct C : A { void f(); }; -struct D : B, C { }; // OK: \tcode{A::f} and \tcode{C::f} are the final overriders +struct D : B, C { }; // OK, \tcode{A::f} and \tcode{C::f} are the final overriders // for the \tcode{B} and \tcode{C} subobjects, respectively \end{codeblock} \end{example} @@ -3787,7 +3787,7 @@ void vf1(); // virtual and overrides \tcode{Base::vf1()} void vf2(int); // not virtual, hides \tcode{Base::vf2()} char vf3(); // error: invalid difference in return type only - D* vf4(); // OK: returns pointer to derived class + D* vf4(); // OK, returns pointer to derived class A* vf5(); // error: returns pointer to incomplete class void f(); }; @@ -4459,7 +4459,7 @@ ::B::si = 3; // OK ::B* bp1 = this; // error: \tcode{B} is a private base class ::B* bp2 = (::B*)this; // OK with cast - bp2->mi = 3; // OK: access through a pointer to \tcode{B}. + bp2->mi = 3; // OK, access through a pointer to \tcode{B}. } \end{codeblock} \end{note} @@ -4632,7 +4632,7 @@ }; class B : public A { }; void f(B* p) { - p->i = 1; // OK: \tcode{B*} can be implicitly converted to \tcode{A*}, and \tcode{f} has access to \tcode{i} in \tcode{A} + p->i = 1; // OK, \tcode{B*} can be implicitly converted to \tcode{A*}, and \tcode{f} has access to \tcode{i} in \tcode{A} } \end{codeblock} \end{example} @@ -4699,10 +4699,10 @@ friend class X; }; -struct X : A::B { // OK: \tcode{A::B} accessible to friend - A::B mx; // OK: \tcode{A::B} accessible to member of friend +struct X : A::B { // OK, \tcode{A::B} accessible to friend + A::B mx; // OK, \tcode{A::B} accessible to member of friend class Y { - A::B my; // OK: \tcode{A::B} accessible to nested member of friend + A::B my; // OK, \tcode{A::B} accessible to nested member of friend }; }; \end{codeblock} @@ -4749,13 +4749,13 @@ typedef C Ct; class X1 { - friend C; // OK: \tcode{class C} is a friend + friend C; // OK, \tcode{class C} is a friend }; class X2 { - friend Ct; // OK: \tcode{class C} is a friend + friend Ct; // OK, \tcode{class C} is a friend friend D; // error: \tcode{D} not found - friend class D; // OK: elaborated-type-specifier declares new class + friend class D; // OK, elaborated-type-specifier declares new class }; template class R { @@ -4763,7 +4763,7 @@ }; R rc; // \tcode{class C} is a friend of \tcode{R} -R Ri; // OK: \tcode{"friend int;"} is ignored +R Ri; // OK, \tcode{"friend int;"} is ignored \end{codeblock} \end{example} @@ -5008,7 +5008,7 @@ B* pb = &d; D* pd = &d; - pb->f(); // OK: \tcode{B::f()} is public, \tcode{D::f()} is invoked + pb->f(); // OK, \tcode{B::f()} is public, \tcode{D::f()} is invoked pd->f(); // error: \tcode{D::f()} is private } \end{codeblock} @@ -5063,10 +5063,10 @@ class B { }; class I { - B b; // OK: \tcode{E::I} can access \tcode{E::B} + B b; // OK, \tcode{E::I} can access \tcode{E::B} int y; void f(E* p, int i) { - p->x = i; // OK: \tcode{E::I} can access \tcode{E::x} + p->x = i; // OK, \tcode{E::I} can access \tcode{E::x} } }; @@ -5459,10 +5459,10 @@ struct C { C() { } // initializes members as follows: - A a; // OK: calls \tcode{A::A()} + A a; // OK, calls \tcode{A::A()} const B b; // error: \tcode{B} has no default constructor - int i; // OK: \tcode{i} has indeterminate value - int j = 5; // OK: \tcode{j} has the value \tcode{5} + int i; // OK, \tcode{i} has indeterminate value + int j = 5; // OK, \tcode{j} has the value \tcode{5} }; \end{codeblock} \end{example} @@ -5732,7 +5732,7 @@ }; void test() { - D1 d(2, 3, 4); // OK: \tcode{B1} is initialized by calling \tcode{B1(2, 3, 4)}, + D1 d(2, 3, 4); // OK, \tcode{B1} is initialized by calling \tcode{B1(2, 3, 4)}, // then \tcode{d.x} is default-initialized (no initialization is performed), // then \tcode{d.y} is initialized by calling \tcode{get()} D1 e; // error: \tcode{D1} has a deleted default constructor @@ -5749,7 +5749,7 @@ struct X : virtual W { using W::W; X() = delete; }; struct Y : X { using X::X; }; struct Z : Y, virtual W { using Y::Y; }; -Z z(0); // OK: initialization of \tcode{Y} does not invoke default constructor of \tcode{X} +Z z(0); // OK, initialization of \tcode{Y} does not invoke default constructor of \tcode{X} template struct Log : T { using T::T; // inherits all constructors from class \tcode{T} @@ -5786,14 +5786,14 @@ }; D1 d1(0); // error: ambiguous -D2 d2(0); // OK: initializes virtual \tcode{B} base class, which initializes the \tcode{A} base class +D2 d2(0); // OK, initializes virtual \tcode{B} base class, which initializes the \tcode{A} base class // then initializes the \tcode{V1} and \tcode{V2} base classes as if by a defaulted default constructor struct M { M(); M(int); }; struct N : M { using M::M; }; struct O : M {}; struct P : N, O { using N::N; using O::O; }; -P p(0); // OK: use \tcode{M(0)} to initialize \tcode{N}{'s} base class, +P p(0); // OK, use \tcode{M(0)} to initialize \tcode{N}{'s} base class, // use \tcode{M()} to initialize \tcode{O}{'s} base class \end{codeblock} \end{example} @@ -6240,11 +6240,11 @@ Thing f(bool b) { Thing t; if (b) - throw t; // OK: \tcode{Thing(Thing\&\&)} used (or elided) to throw \tcode{t} - return t; // OK: \tcode{Thing(Thing\&\&)} used (or elided) to return \tcode{t} + throw t; // OK, \tcode{Thing(Thing\&\&)} used (or elided) to throw \tcode{t} + return t; // OK, \tcode{Thing(Thing\&\&)} used (or elided) to return \tcode{t} } -Thing t2 = f(false); // OK: no extra copy/move performed, \tcode{t2} constructed by call to \tcode{f} +Thing t2 = f(false); // OK, no extra copy/move performed, \tcode{t2} constructed by call to \tcode{f} struct Weird { Weird(); @@ -6253,7 +6253,7 @@ Weird g() { Weird w; - return w; // OK: first overload resolution fails, second overload resolution selects \tcode{Weird(Weird\&)} + return w; // OK, first overload resolution fails, second overload resolution selects \tcode{Weird(Weird\&)} } \end{codeblock} \end{example} diff --git a/source/compatibility.tex b/source/compatibility.tex index 595f0b9e29..c4b75839dd 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -1990,9 +1990,9 @@ \begin{codeblock} char* p = "abc"; // valid in C, invalid in \Cpp{} void f(char*) { - char* p = (char*)"abc"; // OK: cast added + char* p = (char*)"abc"; // OK, cast added f(p); - f((char*)"def"); // OK: cast added + f((char*)"def"); // OK, cast added } \end{codeblock} diff --git a/source/declarations.tex b/source/declarations.tex index b3c2f9b3e7..406cecc0fe 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -730,23 +730,23 @@ \end{note} \begin{example} \begin{codeblock} -constexpr void square(int &x); // OK: declaration -constexpr int bufsz = 1024; // OK: definition +constexpr void square(int &x); // OK, declaration +constexpr int bufsz = 1024; // OK, definition constexpr struct pixel { // error: \tcode{pixel} is a type int x; int y; - constexpr pixel(int); // OK: declaration + constexpr pixel(int); // OK, declaration }; constexpr pixel::pixel(int a) - : x(a), y(x) // OK: definition + : x(a), y(x) // OK, definition { square(x); } constexpr pixel small(2); // error: \tcode{square} not defined, so \tcode{small(2)} // not constant\iref{expr.const} so \keyword{constexpr} not satisfied -constexpr void square(int &x) { // OK: definition +constexpr void square(int &x) { // OK, definition x *= x; } -constexpr pixel large(4); // OK: \tcode{square} defined +constexpr pixel large(4); // OK, \tcode{square} defined int next(constexpr int x) { // error: not for parameters return x + 1; } @@ -1209,7 +1209,7 @@ int i = 2; // not cv-qualified const int* cip; // pointer to \tcode{const int} -cip = &i; // OK: cv-qualified access path to unqualified +cip = &i; // OK, cv-qualified access path to unqualified *cip = 4; // error: attempt to modify through ptr to \keyword{const} int* ip; @@ -1635,7 +1635,7 @@ template auto f(T) // \#2 -> void; auto g() -> void { - f(42); // OK: calls \#2. (\#1 is not a viable candidate: type deduction + f(42); // OK, calls \#2. (\#1 is not a viable candidate: type deduction // fails\iref{temp.deduct} because \tcode{A::\~{}A()} is implicitly used in its // \grammarterm{decltype-specifier}) } @@ -1715,13 +1715,13 @@ \grammarterm{initializer}. \begin{example} \begin{codeblock} -auto x = 5; // OK: \tcode{x} has type \tcode{int} -const auto *v = &x, u = 6; // OK: \tcode{v} has type \tcode{const int*}, \tcode{u} has type \tcode{const int} -static auto y = 0.0; // OK: \tcode{y} has type \tcode{double} +auto x = 5; // OK, \tcode{x} has type \tcode{int} +const auto *v = &x, u = 6; // OK, \tcode{v} has type \tcode{const int*}, \tcode{u} has type \tcode{const int} +static auto y = 0.0; // OK, \tcode{y} has type \tcode{double} auto int r; // error: \keyword{auto} is not a \grammarterm{storage-class-specifier} -auto f() -> int; // OK: \tcode{f} returns \tcode{int} -auto g() { return 0.0; } // OK: \tcode{g} returns \tcode{double} -auto h(); // OK: \tcode{h}'s return type will be deduced when it is defined +auto f() -> int; // OK, \tcode{f} returns \tcode{int} +auto g() { return 0.0; } // OK, \tcode{g} returns \tcode{double} +auto h(); // OK, \tcode{h}'s return type will be deduced when it is defined \end{codeblock} \end{example} The \keyword{auto} \grammarterm{type-specifier} @@ -1755,7 +1755,7 @@ \begin{example} \begin{codeblock} -auto x = 5, *y = &x; // OK: \keyword{auto} is \tcode{int} +auto x = 5, *y = &x; // OK, \keyword{auto} is \tcode{int} auto a = 5, b = { 1, 2 }; // error: different types for \keyword{auto} \end{codeblock} \end{example} @@ -2194,8 +2194,8 @@ \end{codeblock} as opposed to \begin{codeblock} -auto i = 1; // OK: \tcode{i} deduced to have type \tcode{int} -auto j = 2.0; // OK: \tcode{j} deduced to have type \tcode{double} +auto i = 1; // OK, \tcode{i} deduced to have type \tcode{int} +auto j = 2.0; // OK, \tcode{j} deduced to have type \tcode{double} \end{codeblock} \end{note} @@ -2586,7 +2586,7 @@ } using P::f,P::g; } -template<> void N::f(int*) {} // OK: \#2 is not nominable +template<> void N::f(int*) {} // OK, \#2 is not nominable template void N::g(int); // error: lookup is ambiguous \end{codeblock} \end{example} @@ -3255,8 +3255,8 @@ static int y[10]; }; -int x[]; // OK: bound is 10 -int S::y[]; // OK: bound is 10 +int x[]; // OK, bound is 10 +int S::y[]; // OK, bound is 10 void f() { extern int x[]; @@ -3550,12 +3550,12 @@ \begin{codeblock} void f(char*); // \#1 void f(char[]) {} // defines \#1 -void f(const char*) {} // OK: another overload +void f(const char*) {} // OK, another overload void f(char *const) {} // error: redefines \#1 void g(char(*)[2]); // \#2 void g(char[3][2]) {} // defines \#2 -void g(char[3][3]) {} // OK: another overload +void g(char[3][3]) {} // OK, another overload void h(int x(const int)); // \#3 void h(int (*)(int)) {} // defines \#3 @@ -3666,7 +3666,7 @@ \begin{codeblock} typedef void F(); struct S { - const F f; // OK: equivalent to: \tcode{void f();} + const F f; // OK, equivalent to: \tcode{void f();} }; \end{codeblock} \end{example} @@ -3723,9 +3723,9 @@ \begin{example} \begin{codeblock} typedef void F(); -F fv; // OK: equivalent to \tcode{void fv();} +F fv; // OK, equivalent to \tcode{void fv();} F fv { } // error -void fv() { } // OK: definition of \tcode{fv} +void fv() { } // OK, definition of \tcode{fv} \end{codeblock} \end{example} @@ -5770,7 +5770,7 @@ }; S2 s21 = { 1, 2, 3.0 }; // OK S2 s22 { 1.0, 2, 3 }; // error: narrowing -S2 s23 { }; // OK: default to 0,0,0 +S2 s23 { }; // OK, default to 0,0,0 \end{codeblock} \end{example} @@ -5817,9 +5817,9 @@ S(); // \#2 // ... }; -S s1 = { 1, 2, 3.0 }; // OK: invoke \#1 +S s1 = { 1, 2, 3.0 }; // OK, invoke \#1 S s2 { 1.0, 2, 3 }; // error: narrowing -S s3 { }; // OK: invoke \#2 +S s3 { }; // OK, invoke \#2 \end{codeblock} \end{example} @@ -5887,12 +5887,12 @@ S(const std::string&); // \#2 // ... }; -const S& r1 = { 1, 2, 3.0 }; // OK: invoke \#1 -const S& r2 { "Spinach" }; // OK: invoke \#2 +const S& r1 = { 1, 2, 3.0 }; // OK, invoke \#1 +const S& r2 { "Spinach" }; // OK, invoke \#2 S& r3 = { 1, 2, 3 }; // error: initializer is not an lvalue const int& i1 = { 1 }; // OK const int& i2 = { 1.1 }; // error: narrowing -const int (&iar)[2] = { 1, 2 }; // OK: \tcode{iar} is bound to temporary array +const int (&iar)[2] = { 1, 2 }; // OK, \tcode{iar} is bound to temporary array struct A { } a; struct B { explicit B(const A&); }; @@ -6050,18 +6050,18 @@ char c1 = x; // OK, though it potentially narrows (in this case, it does narrow) char c2{x}; // error: potentially narrows char c3{y}; // error: narrows (assuming \tcode{char} is 8 bits) -char c4{z}; // OK: no narrowing needed -unsigned char uc1 = {5}; // OK: no narrowing needed +char c4{z}; // OK, no narrowing needed +unsigned char uc1 = {5}; // OK, no narrowing needed unsigned char uc2 = {-1}; // error: narrows unsigned int ui1 = {-1}; // error: narrows signed int si1 = { (unsigned int)-1 }; // error: narrows int ii = {2.0}; // error: narrows float f1 { x }; // error: potentially narrows -float f2 { 7 }; // OK: 7 can be exactly represented as a \tcode{float} +float f2 { 7 }; // OK, 7 can be exactly represented as a \tcode{float} bool b = {"meow"}; // error: narrows int f(int); -int a[] = { 2, f(2), f(2.0) }; // OK: the \tcode{double}-to-\tcode{int} conversion is not at the top level +int a[] = { 2, f(2), f(2.0) }; // OK, the \tcode{double}-to-\tcode{int} conversion is not at the top level \end{codeblock} \end{example} \indextext{initialization!list-initialization|)}% @@ -6257,9 +6257,9 @@ ~S() noexcept(false) = default; // OK, despite mismatched exception specification private: int i; - S(S&); // OK: private copy constructor + S(S&); // OK, private copy constructor }; -S::S(S&) = default; // OK: defines copy constructor +S::S(S&) = default; // OK, defines copy constructor struct T { T(); @@ -7098,7 +7098,7 @@ values of type \tcode{color}. \begin{codeblock} color c = 1; // error: type mismatch, no conversion from \tcode{int} to \tcode{color} -int i = yellow; // OK: \tcode{yellow} converted to integral value \tcode{1}, integral promotion +int i = yellow; // OK, \tcode{yellow} converted to integral value \tcode{1}, integral promotion \end{codeblock} Note that this implicit \keyword{enum} to \tcode{int} conversion is not provided for a scoped enumeration: @@ -7604,8 +7604,8 @@ void f() { X(1); // error: name \tcode{X} found in two namespaces - g(); // OK: name \tcode{g} refers to the same entity - h(); // OK: overload resolution selects \tcode{A::h} + g(); // OK, name \tcode{g} refers to the same entity + h(); // OK, overload resolution selects \tcode{A::h} } \end{codeblock} \end{note} @@ -7636,7 +7636,7 @@ } using namespace D; -int d1; // OK: no conflict with \tcode{D::d1} +int d1; // OK, no conflict with \tcode{D::d1} namespace E { int e; @@ -7653,10 +7653,10 @@ d1++; // error: ambiguous \tcode{::d1} or \tcode{D::d1}? ::d1++; // OK D::d1++; // OK - d2++; // OK: \tcode{D::d2} - e++; // OK: \tcode{E::e} + d2++; // OK, \tcode{D::d2} + e++; // OK, \tcode{E::e} f(1); // error: ambiguous: \tcode{D::f(int)} or \tcode{E::f(int)}? - f('a'); // OK: \tcode{D::f(char)} + f('a'); // OK, \tcode{D::f(char)} } \end{codeblock} \end{example} @@ -7763,9 +7763,9 @@ }; struct D : B { - using B::f; // OK: \tcode{B} is a base of \tcode{D} - using B::e; // OK: \tcode{e} is an enumerator of base \tcode{B} - using B::x; // OK: \tcode{x} is a union member of base \tcode{B} + using B::f; // OK, \tcode{B} is a base of \tcode{D} + using B::e; // OK, \tcode{e} is an enumerator of base \tcode{B} + using B::x; // OK, \tcode{x} is a union member of base \tcode{B} using C::f; // error: \tcode{C} isn't a base of \tcode{D} void f(int) { f('c'); } // calls \tcode{B::f(char)} void g(int) { g('c'); } // recursively calls \tcode{D::g(int)} @@ -7774,7 +7774,7 @@ struct X : bases... { using bases::f...; }; -X x; // OK: \tcode{B::f} and \tcode{C::f} named +X x; // OK, \tcode{B::f} and \tcode{C::f} named \end{codeblock} \end{example} @@ -7895,17 +7895,17 @@ struct x { }; void f(int); void f(double); - void g(char); // OK: hides \tcode{struct g} + void g(char); // OK, hides \tcode{struct g} } void func() { int i; using B::i; // error: conflicts void f(char); - using B::f; // OK: each \tcode{f} is a function + using B::f; // OK, each \tcode{f} is a function using A::f; // OK, but interferes with \tcode{B::f(int)} f(1); // error: ambiguous - static_cast(f)(1); // OK: calls \tcode{A::f} + static_cast(f)(1); // OK, calls \tcode{A::f} f(3.5); // calls \tcode{B::f(double)} using B::g; g('a'); // calls \tcode{B::g(char)} @@ -7914,7 +7914,7 @@ void h(); using A::h; // error: conflicts using B::x; - using A::x; // OK: hides \tcode{struct B::x} + using A::x; // OK, hides \tcode{struct B::x} x = 99; // assigns to \tcode{A::x} struct x x1; // \tcode{x1} has class type \tcode{B::x} } @@ -7939,13 +7939,13 @@ struct D : B { using B::f; - void f(int); // OK: \tcode{D::f(int)} overrides \tcode{B::f(int)}; + void f(int); // OK, \tcode{D::f(int)} overrides \tcode{B::f(int)}; using B::g; void g(char); // OK using B::h; - void h(int); // OK: \tcode{D::h(int)} hides \tcode{B::h(int)} + void h(int); // OK, \tcode{D::h(int)} hides \tcode{B::h(int)} }; void k(D* p) @@ -7973,7 +7973,7 @@ struct D2 : B1, B2 { using B1::B1; using B2::B2; - D2(int); // OK: \tcode{D2::D2(int)} hides \tcode{B1::B1(int)} and \tcode{B2::B2(int)} + D2(int); // OK, \tcode{D2::D2(int)} hides \tcode{B1::B1(int)} and \tcode{B2::B2(int)} }; D2 d2(0); // calls \tcode{D2::D2(int)} \end{codeblock} @@ -8192,15 +8192,15 @@ } extern "C" void f5() { - extern void f4(); // OK: Name linkage (internal) and function type linkage (C language linkage) + extern void f4(); // OK, name linkage (internal) and function type linkage (C language linkage) // obtained from previous declaration. } -extern void f4(); // OK: Name linkage (internal) and function type linkage (C language linkage) +extern void f4(); // OK, name linkage (internal) and function type linkage (C language linkage) // obtained from previous declaration. void f6() { - extern void f4(); // OK: Name linkage (internal) and function type linkage (C language linkage) + extern void f4(); // OK, name linkage (internal) and function type linkage (C language linkage) // obtained from previous declaration. } \end{codeblock} diff --git a/source/expressions.tex b/source/expressions.tex index dd24afa83e..3d7bd74216 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -1254,7 +1254,7 @@ \begin{codeblock} class Outer { int a[sizeof(*this)]; // error: not inside a member function - unsigned int sz = sizeof(*this); // OK: in default member initializer + unsigned int sz = sizeof(*this); // OK, in default member initializer void f() { int b[sizeof(*this)]; // OK @@ -1734,10 +1734,10 @@ \tcode{return} statements as described in~\ref{dcl.spec.auto}. \begin{example} \begin{codeblock} -auto x1 = [](int i) { return i; }; // OK: return type is \tcode{int} +auto x1 = [](int i) { return i; }; // OK, return type is \tcode{int} auto x2 = []{ return { 1, 2 }; }; // error: deducing return type from \grammarterm{braced-init-list} int j; -auto x3 = []()->auto&& { return j; }; // OK: return type is \tcode{int\&} +auto x3 = []()->auto&& { return j; }; // OK, return type is \tcode{int\&} \end{codeblock} \end{example} @@ -1748,8 +1748,8 @@ if the lambda has a \grammarterm{template-parameter-list}. \begin{example} \begin{codeblock} -int i = [](int i, auto a) { return i; }(3, 4); // OK: a generic lambda -int j = [](T t, int i) { return i; }(3, 4); // OK: a generic lambda +int i = [](int i, auto a) { return i; }(3, 4); // OK, a generic lambda +int j = [](T t, int i) { return i; }(3, 4); // OK, a generic lambda \end{codeblock} \end{example} @@ -1812,7 +1812,7 @@ bool b = glambda(3, 3.14); // OK auto vglambda = [](auto printer) { - return [=](auto&& ... ts) { // OK: \tcode{ts} is a function parameter pack + return [=](auto&& ... ts) { // OK, \tcode{ts} is a function parameter pack printer(std::forward(ts)...); return [=]() { @@ -1822,13 +1822,13 @@ }; auto p = vglambda( [](auto v1, auto v2, auto v3) { std::cout << v1 << v2 << v3; } ); -auto q = p(1, 'a', 3.14); // OK: outputs \tcode{1a3.14} -q(); // OK: outputs \tcode{1a3.14} +auto q = p(1, 'a', 3.14); // OK, outputs \tcode{1a3.14} +q(); // OK, outputs \tcode{1a3.14} -auto fact = [](this auto self, int n) -> int { // OK: explicit object parameter +auto fact = [](this auto self, int n) -> int { // OK, explicit object parameter return (n <= 1) ? 1 : n * self(n-1); }; -std::cout << fact(5); // OK: outputs 120 +std::cout << fact(5); // OK, outputs 120 \end{codeblock} \end{example} @@ -2020,7 +2020,7 @@ f1(glambda); // OK f2(glambda); // error: ID is not convertible g(glambda); // error: ambiguous -h(glambda); // OK: calls \#3 since it is convertible from ID +h(glambda); // OK, calls \#3 since it is convertible from ID int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK \end{codeblock} \end{example} @@ -2042,8 +2042,8 @@ \begin{example} \begin{codeblock} auto GL = [](auto a) { std::cout << a; return a; }; -int (*GL_int)(int) = GL; // OK: through conversion function template -GL_int(3); // OK: same as \tcode{GL(3)} +int (*GL_int)(int) = GL; // OK, through conversion function template +GL_int(3); // OK, same as \tcode{GL(3)} \end{codeblock} \end{example} @@ -2297,16 +2297,16 @@ void test() { const int x = 17; auto g = [](auto a) { - f(x); // OK: calls \#1, does not capture \tcode{x} + f(x); // OK, calls \#1, does not capture \tcode{x} }; auto g1 = [=](auto a) { - f(x); // OK: calls \#1, captures \tcode{x} + f(x); // OK, calls \#1, captures \tcode{x} }; auto g2 = [=](auto a) { int selector[sizeof(a) == 1 ? 1 : 2]{}; - f(x, selector); // OK: captures \tcode{x}, can call \#1 or \#2 + f(x, selector); // OK, captures \tcode{x}, can call \#1 or \#2 }; auto g3 = [=](auto a) { @@ -2353,8 +2353,8 @@ auto m1 = [=]{ int const M = 30; auto m2 = [i]{ - int x[N][M]; // OK: \tcode{N} and \tcode{M} are not odr-used - x[0][0] = i; // OK: \tcode{i} is explicitly captured by \tcode{m2} and implicitly captured by \tcode{m1} + int x[N][M]; // OK, \tcode{N} and \tcode{M} are not odr-used + x[0][0] = i; // OK, \tcode{i} is explicitly captured by \tcode{m2} and implicitly captured by \tcode{m1} }; }; struct s1 { @@ -2365,10 +2365,10 @@ auto m3 = [this,m] { auto m4 = [&,j] { // error: \tcode{j} not odr-usable due to intervening lambda \tcode{m3} int x = n; // error: \tcode{n} is odr-used but not odr-usable due to intervening lambda \tcode{m3} - x += m; // OK: \tcode{m} implicitly captured by \tcode{m4} and explicitly captured by \tcode{m3} + x += m; // OK, \tcode{m} implicitly captured by \tcode{m4} and explicitly captured by \tcode{m3} x += i; // error: \tcode{i} is odr-used but not odr-usable // due to intervening function and class scopes - x += f; // OK: \keyword{this} captured implicitly by \tcode{m4} and explicitly by \tcode{m3} + x += f; // OK, \keyword{this} captured implicitly by \tcode{m4} and explicitly by \tcode{m3} }; }; } @@ -2461,8 +2461,8 @@ void g() { const int N = 10; [=] { - int arr[N]; // OK: not an odr-use, refers to automatic variable - f(&N); // OK: causes \tcode{N} to be captured; \tcode{\&N} points to + int arr[N]; // OK, not an odr-use, refers to automatic variable + f(&N); // OK, causes \tcode{N} to be captured; \tcode{\&N} points to // the corresponding member of the closure type }; } @@ -7379,7 +7379,7 @@ constexpr A(bool b) : m(b?42:x) { } int m; }; -constexpr int v = A(true).m; // OK: constructor call initializes \tcode{m} with the value \tcode{42} +constexpr int v = A(true).m; // OK, constructor call initializes \tcode{m} with the value \tcode{42} constexpr int w = A(false).m; // error: initializer for \tcode{m} is \tcode{x}, which is non-constant @@ -7389,7 +7389,7 @@ return x; } constexpr int f2(int k) { - int x = k; // OK: not required to be a constant expression + int x = k; // OK, not required to be a constant expression // because \tcode{x} is not \keyword{constexpr} return x; } @@ -7403,10 +7403,10 @@ return x; } constexpr int h(int k) { - int x = incr(k); // OK: \tcode{incr(k)} is not required to be a core constant expression + int x = incr(k); // OK, \tcode{incr(k)} is not required to be a core constant expression return x; } -constexpr int y = h(1); // OK: initializes \tcode{y} with the value \tcode{2} +constexpr int y = h(1); // OK, initializes \tcode{y} with the value \tcode{2} // \tcode{h(1)} is a core constant expression because // the lifetime of \tcode{k} begins inside \tcode{h(1)} \end{codeblock} diff --git a/source/lex.tex b/source/lex.tex index 210a116c69..133208bd4b 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -2156,7 +2156,7 @@ \begin{example} \begin{codeblock} int main() { - L"A" "B" "C"_x; // OK: same as \tcode{L"ABC"_x} + L"A" "B" "C"_x; // OK, same as \tcode{L"ABC"_x} "P"_x "Q" "R"_y; // error: two different \grammarterm{ud-suffix}{es} } \end{codeblock} diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 5a7d9dcae5..7cf1ca4e43 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -1628,7 +1628,7 @@ template void value_swap(T&& t, U&& u) { using std::swap; - swap(std::forward(t), std::forward(u)); // OK: uses ``swappable with'' conditions + swap(std::forward(t), std::forward(u)); // OK, uses ``swappable with'' conditions // for rvalues and lvalues } @@ -1636,7 +1636,7 @@ template void lv_swap(T& t1, T& t2) { using std::swap; - swap(t1, t2); // OK: uses swappable conditions for lvalues of type \tcode{T} + swap(t1, t2); // OK, uses swappable conditions for lvalues of type \tcode{T} } namespace N { @@ -1645,7 +1645,7 @@ Proxy proxy(A& a) { return Proxy{ &a }; } void swap(A& x, Proxy p) { - std::swap(x.m, p.a->m); // OK: uses context equivalent to swappable + std::swap(x.m, p.a->m); // OK, uses context equivalent to swappable // conditions for fundamental types } void swap(Proxy p, A& x) { swap(x, p); } // satisfy symmetry constraint diff --git a/source/overloading.tex b/source/overloading.tex index e1b21b02fd..9872bb1991 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -936,7 +936,7 @@ void B::f() { operator+ (a,a); // error: global operator hidden by member - a + a; // OK: calls global \tcode{\keyword{operator}+} + a + a; // OK, calls global \tcode{\keyword{operator}+} } \end{codeblock} \end{note} @@ -2274,9 +2274,9 @@ \begin{example} \begin{codeblock} void f(std::initializer_list); -f( {} ); // OK: \tcode{f(initializer_list)} identity conversion -f( {1,2,3} ); // OK: \tcode{f(initializer_list)} identity conversion -f( {'a','b'} ); // OK: \tcode{f(initializer_list)} integral promotion +f( {} ); // OK, \tcode{f(initializer_list)} identity conversion +f( {1,2,3} ); // OK, \tcode{f(initializer_list)} identity conversion +f( {'a','b'} ); // OK, \tcode{f(initializer_list)} integral promotion f( {1.0} ); // error: narrowing struct A { @@ -2291,7 +2291,7 @@ typedef int IA[3]; void h(const IA&); -h({ 1, 2, 3 }); // OK: identity conversion +h({ 1, 2, 3 }); // OK, identity conversion \end{codeblock} \end{example} @@ -2333,13 +2333,13 @@ A(std::initializer_list); }; void f(A); -f( {'a', 'b'} ); // OK: \tcode{f(A(std::initializer_list))} user-defined conversion +f( {'a', 'b'} ); // OK, \tcode{f(A(std::initializer_list))} user-defined conversion struct B { B(int, double); }; void g(B); -g( {'a', 'b'} ); // OK: \tcode{g(B(int, double))} user-defined conversion +g( {'a', 'b'} ); // OK, \tcode{g(B(int, double))} user-defined conversion g( {1.0, 1.0} ); // error: narrowing void f(B); @@ -2349,13 +2349,13 @@ C(std::string); }; void h(C); -h({"foo"}); // OK: \tcode{h(C(std::string("foo")))} +h({"foo"}); // OK, \tcode{h(C(std::string("foo")))} struct D { D(A, C); }; void i(D); -i({ {1,2}, {"bar"} }); // OK: \tcode{i(D(A(std::initializer_list\{1,2\}), C(std::string("bar"))))} +i({ {1,2}, {"bar"} }); // OK, \tcode{i(D(A(std::initializer_list\{1,2\}), C(std::string("bar"))))} \end{codeblock} \end{example} @@ -2373,7 +2373,7 @@ }; void f(A); -f( {'a', 'b'} ); // OK: \tcode{f(A(int,double))} user-defined conversion +f( {'a', 'b'} ); // OK, \tcode{f(A(int,double))} user-defined conversion f( {1.0} ); // error: narrowing \end{codeblock} \end{example} @@ -2392,7 +2392,7 @@ }; void f(const A&); -f( {'a', 'b'} ); // OK: \tcode{f(A(int,double))} user-defined conversion +f( {'a', 'b'} ); // OK, \tcode{f(A(int,double))} user-defined conversion f( {1.0} ); // error: narrowing void g(const double &); @@ -2409,7 +2409,7 @@ \begin{example} \begin{codeblock} void f(int); -f( {'a'} ); // OK: same conversion as \tcode{char} to \tcode{int} +f( {'a'} ); // OK, same conversion as \tcode{char} to \tcode{int} f( {1.0} ); // error: narrowing \end{codeblock} \end{example} @@ -2419,7 +2419,7 @@ \begin{example} \begin{codeblock} void f(int); -f( { } ); // OK: identity conversion +f( { } ); // OK, identity conversion \end{codeblock} \end{example} \end{itemize} @@ -3846,11 +3846,11 @@ \begin{codeblock} void operator "" _km(long double); // OK string operator "" _i18n(const char*, std::size_t); // OK -template double operator "" _\u03C0(); // OK: UCN for lowercase pi +template double operator "" _\u03C0(); // OK, UCN for lowercase pi float operator ""_e(const char*); // OK float operator ""E(const char*); // ill-formed, no diagnostic required: // reserved literal suffix~(\ref{usrlit.suffix}, \ref{lex.ext}) -double operator""_Bq(long double); // OK: does not use the reserved \grammarterm{identifier} \tcode{_Bq}\iref{lex.name} +double operator""_Bq(long double); // OK, does not use the reserved \grammarterm{identifier} \tcode{_Bq}\iref{lex.name} double operator"" _Bq(long double); // ill-formed, no diagnostic required: // uses the reserved \grammarterm{identifier} \tcode{_Bq}\iref{lex.name} float operator " " B(const char*); // error: non-empty \grammarterm{string-literal} diff --git a/source/templates.tex b/source/templates.tex index c34d77a66a..b68b7311c1 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -428,8 +428,8 @@ &i; // error: address of non-reference template-parameter &a; // OK int& ri = i; // error: attempt to bind non-const reference to temporary - const int& cri = i; // OK: const reference binds to temporary - const A& ra = a; // OK: const reference binds to a template parameter object + const int& cri = i; // OK, const reference binds to temporary + const A& ra = a; // OK, const reference binds to a template parameter object } \end{codeblock} \end{example} @@ -733,9 +733,9 @@ }; template void f(T* p) { T* p1 = p->alloc<200>(); // error: \tcode{<} means less than - T* p2 = p->template alloc<200>(); // OK: \tcode{<} starts template argument list + T* p2 = p->template alloc<200>(); // OK, \tcode{<} starts template argument list T::adjust<100>(); // error: \tcode{<} means less than - T::template adjust<100>(); // OK: \tcode{<} starts template argument list + T::template adjust<100>(); // OK, \tcode{<} starts template argument list } \end{codeblock} \end{example} @@ -812,7 +812,7 @@ template void f(T t) { A a; - a.template f<>(t); // OK: calls template + a.template f<>(t); // OK, calls template a.template f(t); // error: not a \grammarterm{template-id} } @@ -1031,9 +1031,9 @@ class Y { private: struct S { @\commentellip@ }; - X x; // OK: \tcode{S} is accessible + X x; // OK, \tcode{S} is accessible // \tcode{X} has a static member of type \tcode{Y::S} - // OK: even though \tcode{Y::S} is private + // OK, even though \tcode{Y::S} is private }; X y; // error: \tcode{S} not accessible @@ -1072,10 +1072,10 @@ \begin{example} \begin{codeblock} template class String; -String<>* p; // OK: \tcode{String} +String<>* p; // OK, \tcode{String} String* q; // syntax error template class Tuple; -Tuple<>* t; // OK: \tcode{Elements} is empty +Tuple<>* t; // OK, \tcode{Elements} is empty Tuple* u; // syntax error \end{codeblock} \end{example} @@ -1090,8 +1090,8 @@ ~A(); }; void f(A* p, A* q) { - p->A::~A(); // OK: destructor call - q->A::~A(); // OK: destructor call + p->A::~A(); // OK, destructor call + q->A::~A(); // OK, destructor call } \end{codeblock} \end{example} @@ -1387,8 +1387,8 @@ template struct D; template struct E; -eval> eA; // OK: matches partial specialization of \tcode{eval} -eval> eB; // OK: matches partial specialization of \tcode{eval} +eval> eA; // OK, matches partial specialization of \tcode{eval} +eval> eB; // OK, matches partial specialization of \tcode{eval} eval> eC; // error: \tcode{C} does not match \tcode{TT} in partial specialization eval> eD; // error: \tcode{D} does not match \tcode{TT} in partial specialization eval> eE; // error: \tcode{E} does not match \tcode{TT} in partial specialization @@ -1539,7 +1539,7 @@ void f(int); -f('a'); // OK: calls \tcode{f(int)} +f('a'); // OK, calls \tcode{f(int)} \end{codeblock} In the satisfaction of the associated constraints\iref{temp.constr.decl} of \tcode{f}, the constraint \tcode{sizeof(char) > 1} is not satisfied; @@ -2285,7 +2285,7 @@ template struct Inner; }; -template void S::f() { } // OK: \grammarterm{template-head}{s} match +template void S::f() { } // OK, \grammarterm{template-head}{s} match template void S::g() { } // error: no matching declaration for \tcode{S} template requires C // ill-formed, no diagnostic required: \grammarterm{template-head}{s} are @@ -2444,9 +2444,9 @@ template struct A { class B; }; -A::B* b1; // OK: requires \tcode{A} to be defined but not \tcode{A::B} +A::B* b1; // OK, requires \tcode{A} to be defined but not \tcode{A::B} template class A::B { }; -A::B b2; // OK: requires \tcode{A::B} to be defined +A::B b2; // OK, requires \tcode{A::B} to be defined \end{codeblock} \end{note} @@ -2483,7 +2483,7 @@ static int i[]; }; template int A::i[4]; // 4 elements -template <> int A::i[] = { 1 }; // OK: 1 element +template <> int A::i[] = { 1 }; // OK, 1 element \end{codeblock} \end{example} @@ -2789,11 +2789,11 @@ // error: different number of arguments specified for \tcode{Args1} and \tcode{Args2} template - void g(Args ... args) { // OK: \tcode{Args} is expanded by the function parameter pack \tcode{args} - f(const_cast(&args)...); // OK: ``\tcode{Args}'' and ``\tcode{args}'' are expanded + void g(Args ... args) { // OK, \tcode{Args} is expanded by the function parameter pack \tcode{args} + f(const_cast(&args)...); // OK, ``\tcode{Args}'' and ``\tcode{args}'' are expanded f(5 ...); // error: pattern does not contain any packs f(args); // error: pack ``\tcode{args}'' is not expanded - f(h(args ...) + args ...); // OK: first ``\tcode{args}'' expanded within \tcode{h}, + f(h(args ...) + args ...); // OK, first ``\tcode{args}'' expanded within \tcode{h}, // second ``\tcode{args}'' expanded within \tcode{f} } \end{codeblock} @@ -2925,7 +2925,7 @@ X x(values...); } -template void f<>(); // OK: \tcode{X<>} has no base classes +template void f<>(); // OK, \tcode{X<>} has no base classes // \tcode{x} is a variable of type \tcode{X<>} that is value-initialized \end{codeblock} \end{example} @@ -3609,7 +3609,7 @@ \begin{codeblock} template void f(); -template void f(); // OK: overloads the first template +template void f(); // OK, overloads the first template // distinguishable with an explicit template argument list \end{codeblock} \end{note} @@ -3959,8 +3959,8 @@ template void g(T); // \#4 void h(int i) { - f(&i); // OK: calls \#2 - g(&i); // OK: calls \#3 + f(&i); // OK, calls \#2 + g(&i); // OK, calls \#3 } \end{codeblock} \end{example} @@ -4030,7 +4030,7 @@ template void f(Q &, C auto &); void g(struct A *ap, struct B *bp) { - f(*ap, *bp); // OK: Can use different methods to produce template parameters + f(*ap, *bp); // OK, can use different methods to produce template parameters } template struct X {}; @@ -4039,7 +4039,7 @@ template bool operator==(T, X); void h() { - X{} == 0; // OK: Correspondence of [\tcode{T}, \tcode{U}, \tcode{V}] and [\tcode{U}, \tcode{V}, \tcode{T}] + X{} == 0; // OK, correspondence of [\tcode{T}, \tcode{U}, \tcode{V}] and [\tcode{U}, \tcode{V}, \tcode{T}] } \end{codeblock} \end{example} @@ -4083,7 +4083,7 @@ template class TT> void g(TT>); -g(v); // OK: \tcode{TT} = \tcode{vector} +g(v); // OK, \tcode{TT} = \tcode{vector} \end{codeblock} \end{example} @@ -4221,7 +4221,7 @@ struct D : B { T get() { return operator T(); } // \grammarterm{conversion-function-id} is dependent }; -int f(D d) { return d.get(); } // OK: lookup finds A::operator int +int f(D d) { return d.get(); } // OK, lookup finds A::operator int \end{codeblock} \end{example} \begin{example} @@ -4313,7 +4313,7 @@ void foo() { A a; B b; - f(b); // OK: \tcode{T::X} refers to \tcode{B::X} + f(b); // OK, \tcode{T::X} refers to \tcode{B::X} f(a); // error: \tcode{T::X} refers to the data member \tcode{A::X} not the struct \tcode{A::X} } \end{codeblock} @@ -4578,7 +4578,7 @@ }; template class U = T::Base> struct Third { }; -Third > t; // OK: default argument uses injected-class-name as a template +Third > t; // OK, default argument uses injected-class-name as a template \end{codeblock} \end{example} @@ -4631,7 +4631,7 @@ void f() { char T; // error: \grammarterm{template-parameter} hidden } - friend void T(); // OK: no name bound + friend void T(); // OK, no name bound }; template class X; // error: hidden by \grammarterm{template-parameter} @@ -4974,7 +4974,7 @@ }; template int C::f(); // error: finds both \tcode{A::m} and \tcode{B::m} -template int C::g(); // OK: transformation to class member access syntax +template int C::g(); // OK, transformation to class member access syntax // does not occur in the template definition context; see~\ref{class.mfct.non-static} \end{codeblock} \end{example} @@ -5451,7 +5451,7 @@ export module M; import F; void g(X x) { - f(x); // OK: instantiates \tcode{f} from \tcode{F}, + f(x); // OK, instantiates \tcode{f} from \tcode{F}, // \tcode{operator+} is visible in instantiation context } \end{codeblocktu} @@ -5795,7 +5795,7 @@ struct Outer { template struct Inner; template struct Inner; // \#1a - template struct Inner { }; // \#1b; OK: valid redeclaration of \#1a + template struct Inner { }; // \#1b; OK, valid redeclaration of \#1a template struct Inner { }; // \#2 }; @@ -6383,7 +6383,7 @@ template class X; -template<> class X { @\commentellip@ }; // OK: \tcode{X} is a template +template<> class X { @\commentellip@ }; // OK, \tcode{X} is a template \end{codeblock} \end{example} @@ -6488,7 +6488,7 @@ } template<> void sort(Array& v); // error: specialization after use of primary template -template<> void sort<>(Array& v); // OK: \tcode{sort} not yet used +template<> void sort<>(Array& v); // OK, \tcode{sort} not yet used template struct A { enum E : T; enum class S : T; @@ -6538,7 +6538,7 @@ template class X; // \tcode{X} is a class template template<> class X; -X* p; // OK: pointer to declared class \tcode{X} +X* p; // OK, pointer to declared class \tcode{X} X x; // error: object of incomplete class \tcode{X} \end{codeblock} \end{example} @@ -6587,8 +6587,8 @@ template void f(T) { @\commentellip@ } template inline T g(T) { @\commentellip@ } -template<> inline void f<>(int) { @\commentellip@ } // OK: inline -template<> int g<>(int) { @\commentellip@ } // OK: not inline +template<> inline void f<>(int) { @\commentellip@ } // OK, inline +template<> int g<>(int) { @\commentellip@ } // OK, not inline \end{codeblock} \end{example} @@ -8150,8 +8150,8 @@ void g(A a, B b) { f(a,b); // error: \tcode{T} deduced as both \tcode{A} and \tcode{B} f(b,a); // error: \tcode{T} deduced as both \tcode{A} and \tcode{B} - f(a,a); // OK: \tcode{T} is \tcode{A} - f(b,b); // OK: \tcode{T} is \tcode{B} + f(a,a); // OK, \tcode{T} is \tcode{A} + f(b,b); // OK, \tcode{T} is \tcode{B} } \end{codeblock} @@ -8168,7 +8168,7 @@ int g3( int, char, float); void r() { - f(g1); // OK: \tcode{T} is \tcode{int} and \tcode{U} is \tcode{float} + f(g1); // OK, \tcode{T} is \tcode{int} and \tcode{U} is \tcode{float} f(g2); // error: \tcode{T} deduced as both \tcode{char} and \tcode{int} f(g3); // error: \tcode{U} deduced as both \tcode{char} and \tcode{float} } @@ -8430,7 +8430,7 @@ template void f(int (&a)[i]); int v[10]; void g() { - f(v); // OK: \tcode{T} is \tcode{std::size_t} + f(v); // OK, \tcode{T} is \tcode{std::size_t} } \end{codeblock} \end{example} @@ -8446,11 +8446,11 @@ void g() { int v[10][20]; - f1(v); // OK: \tcode{i} deduced as \tcode{20} + f1(v); // OK, \tcode{i} deduced as \tcode{20} f1<20>(v); // OK f2(v); // error: cannot deduce template-argument \tcode{i} f2<10>(v); // OK - f3(v); // OK: \tcode{i} deduced as \tcode{10} + f3(v); // OK, \tcode{i} deduced as \tcode{10} } \end{codeblock} \end{note} @@ -8530,7 +8530,7 @@ template void g(B); void k2() { B<1> b; - g(b); // OK: cv-qualifiers are ignored on template parameter types + g(b); // OK, cv-qualifiers are ignored on template parameter types } \end{codeblock} \end{example} @@ -8552,7 +8552,7 @@ void h(char,int); int m() { f(&g); // error: ambiguous - f(&h); // OK: void \tcode{h(char,int)} is a unique match + f(&h); // OK, void \tcode{h(char,int)} is a unique match f(&foo); // error: type deduction fails because \tcode{foo} is a template } \end{codeblock} @@ -8566,9 +8566,9 @@ \begin{codeblock} template void f(T = 5, T = 7); void g() { - f(1); // OK: call \tcode{f(1,7)} + f(1); // OK, calls \tcode{f(1,7)} f(); // error: cannot deduce \tcode{T} - f(); // OK: call \tcode{f(5,7)} + f(); // OK, calls \tcode{f(5,7)} } \end{codeblock} \end{example} From 5e3f1ad0ceb89feb2977a0531422bcbe9ab8fba7 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 26 Oct 2021 21:49:15 +0200 Subject: [PATCH 021/182] [stdatomic.h.syn] Fix missing \expos and augment the autmatic checks accordingly. --- source/atomics.tex | 2 +- tools/check-source.sh | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/source/atomics.tex b/source/atomics.tex index 77967cd1ba..2c314ce8ad 100644 --- a/source/atomics.tex +++ b/source/atomics.tex @@ -3712,7 +3712,7 @@ \begin{codeblock} template - using @\exposid{std-atomic}@ = std::atomic; // exposition only + using @\exposid{std-atomic}@ = std::atomic; // \expos #define _Atomic(T) @\exposid{std-atomic}@ diff --git a/tools/check-source.sh b/tools/check-source.sh index ddcf064298..7637904661 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -63,6 +63,10 @@ grep -n '\\opt[^{]' $texfiles | grep -n 'opt{}' *.tex | fail '\\opt used incorrectly' || failed=1 +# Use \expos insted of "exposition only" +grep -n "// exposition only" $texfiles | + fail 'use \\expos instead' || failed=1 + # Use \notdef instead of "not defined". grep -n "// not defined" $texfiles | fail "use \\notdef instead" || failed=1 From 16e60c63ad14f3f3fc9132a8443421a15ebec8fc Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 9 Nov 2021 13:09:27 +0100 Subject: [PATCH 022/182] [locale.time.get] Replace 'ISO/IEC 9945' with 'POSIX' We introduce POSIX as an alias for ISO/IEC 9945, and we use 'POSIX' everywhere else. --- source/locales.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/locales.tex b/source/locales.tex index 328ed5c7ed..088a795501 100644 --- a/source/locales.tex +++ b/source/locales.tex @@ -3345,7 +3345,7 @@ optionally followed by a modifier character, followed by a conversion specifier character, \tcode{format}, together forming a conversion specification -valid for the ISO/IEC 9945 function \tcode{strptime}. +valid for the POSIX function \tcode{strptime}. If the number of elements in the range \range{fmt}{fmtend} is not sufficient to unambiguously determine whether the conversion specification is complete and valid, @@ -3535,7 +3535,7 @@ until it has extracted and assigned those \tcode{tm} members, and any remaining format characters, corresponding to a conversion directive appropriate for -the ISO/IEC 9945 function \tcode{strptime}, +the POSIX function \tcode{strptime}, formed by concatenating \tcode{'\%'}, the \tcode{modifier} character, when non-NUL, and the \tcode{format} character. From 31c32e035770797eedc69f150c3a3484bbe828a5 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 9 Nov 2021 17:54:18 +0100 Subject: [PATCH 023/182] [locale.time.get.virtuals] Use 'conversion specification' POSIX does not define the term 'conversion directive'. --- source/locales.tex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/locales.tex b/source/locales.tex index 088a795501..7c51ca862b 100644 --- a/source/locales.tex +++ b/source/locales.tex @@ -3534,7 +3534,7 @@ It then reads characters starting at \tcode{s} until it encounters an error, or until it has extracted and assigned those \tcode{tm} members, and any remaining format characters, -corresponding to a conversion directive appropriate for +corresponding to a conversion specification appropriate for the POSIX function \tcode{strptime}, formed by concatenating \tcode{'\%'}, the \tcode{modifier} character, when non-NUL, and @@ -3546,9 +3546,9 @@ the function evaluates \tcode{err |= ios_base::eofbit}. \pnum -For complex conversion directives +For complex conversion specifications such as \tcode{\%c}, \tcode{\%x}, or \tcode{\%X}, or -directives that involve the optional modifiers \tcode{E} or \tcode{O}, +conversion specifications that involve the optional modifiers \tcode{E} or \tcode{O}, when the function is unable to unambiguously determine some or all \tcode{tm} members from the input sequence \range{s}{end}, it evaluates \tcode{err |= ios_base::eofbit}. From fbab3f13719c34affdb7b712aed7f6d2313570d7 Mon Sep 17 00:00:00 2001 From: languagelawyer <38548419+languagelawyer@users.noreply.github.com> Date: Tue, 23 Nov 2021 20:03:13 +0300 Subject: [PATCH 024/182] [defns.access, basic.lval] Clarify what can be accessed and how (#4777) --- source/expressions.tex | 4 +++- source/intro.tex | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/source/expressions.tex b/source/expressions.tex index 3d7bd74216..d63db2546f 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -319,7 +319,9 @@ that does not denote an object of type \cv{}~\keyword{U} within its lifetime, the behavior is undefined. \begin{note} -Unlike in C, \Cpp{} has no accesses of class type. +In C, an entire object of structure type can be accessed, e.g. using assignment. +By contrast, \Cpp{} has no notion of accessing an object of class type +through an lvalue of class type. \end{note} \rSec2[expr.type]{Type} diff --git a/source/intro.tex b/source/intro.tex index bc3202190f..cbee223c7b 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -137,9 +137,9 @@ read or modify the value of an object \begin{defnote} -Only objects of scalar type can be accessed. +Only glvalues of scalar type can be used to access objects. Reads of scalar objects are described in \ref{conv.lval} and -modifications of scalar objects are describred in +modifications of scalar objects are described in \ref{expr.ass}, \ref{expr.post.incr}, and \ref{expr.pre.incr}. Attempts to read or modify an object of class type typically invoke a constructor\iref{class.ctor} From 5475bdab828b3585a21172945303ccebbcefb516 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 21 Oct 2021 22:11:07 +0200 Subject: [PATCH 025/182] [c.mb.wcs] mbrtoc8 stores code units, not characters --- source/strings.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/strings.tex b/source/strings.tex index c8e1f55b34..ee30bed8c1 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -5785,9 +5785,9 @@ (which is the value stored). \item between \tcode{1} and \tcode{n} (inclusive), if the next n or fewer bytes complete a valid multibyte character -(which is the value stored); +(whose first (or only) code unit is stored); the value returned is the number of bytes that complete the multibyte character. -\item \tcode{(size_t)(-3)}, if the next character +\item \tcode{(size_t)(-3)}, if the next code unit resulting from a previous call has been stored (no bytes from the input have been consumed by this call). \item \tcode{(size_t)(-2)}, if the next \tcode{n} bytes From ba4bb3ee56b94b63d0d1e5914a136a04b1620052 Mon Sep 17 00:00:00 2001 From: mordante Date: Tue, 23 Nov 2021 18:13:22 +0100 Subject: [PATCH 026/182] [format.functions] Add "std::move" around "out" (#5069) This fixes a misapplication of the resolution of LWG 3539. --- source/utilities.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index 72b0cc9c10..0016e78053 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -21506,7 +21506,7 @@ \effects Equivalent to: \begin{codeblock} -return vformat_to(out, fmt.@\exposid{str}@, make_format_args(args...)); +return vformat_to(std::move(out), fmt.@\exposid{str}@, make_format_args(args...)); \end{codeblock} \end{itemdescr} @@ -21536,7 +21536,7 @@ \effects Equivalent to: \begin{codeblock} -return vformat_to(out, loc, fmt.@\exposid{str}@, make_format_args(args...)); +return vformat_to(std::move(out), loc, fmt.@\exposid{str}@, make_format_args(args...)); \end{codeblock} \end{itemdescr} From 0d0ec1a1393b3baae564234007c94b80da9bab48 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 23 Nov 2021 18:15:55 +0100 Subject: [PATCH 027/182] [func.wrap.{func.general, move.class}] Remove 'first-class object' (#5067) The term is undefined and does not improve the specification. --- source/utilities.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index 0016e78053..a680c2cd23 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -16113,7 +16113,7 @@ The \tcode{function} class template provides polymorphic wrappers that generalize the notion of a function pointer. Wrappers can store, copy, and call arbitrary callable objects\iref{func.def}, given a call -signature\iref{func.def}, allowing functions to be first-class objects. +signature\iref{func.def}. \pnum \indextext{callable type}% @@ -16571,7 +16571,7 @@ The \tcode{move_only_function} class template provides polymorphic wrappers that generalize the notion of a callable object\iref{func.def}. These wrappers can store, move, and call arbitrary callable objects, -given a call signature, allowing functions to be first-class objects. +given a call signature. \pnum \recommended From d27c3b388befadc4c35aac1d12f0ba8581f14a5f Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 12 Nov 2021 14:29:00 +0000 Subject: [PATCH 028/182] [spanstream.ctor] Fix base class name in effects --- source/iostreams.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/iostreams.tex b/source/iostreams.tex index 9c1c8d94a6..3554d361ca 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -10073,7 +10073,7 @@ \pnum \effects Initializes the base class with -\tcode{basic_ostream(addressof(sb))} +\tcode{basic_iostream(addressof(sb))} and \tcode{sb} with \tcode{basic_spanbuf(s, which)}\iref{spanbuf.ctor}. \end{itemdescr} From c1935504da840995b1bb60eba536cb12bca5ae71 Mon Sep 17 00:00:00 2001 From: timsong-cpp Date: Tue, 23 Nov 2021 11:51:37 -0600 Subject: [PATCH 029/182] [basic.start.main] Remove redundant phrase (#5083) --- source/basic.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/basic.tex b/source/basic.tex index f8ed8b751d..2d21697791 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -6386,7 +6386,7 @@ without leaving the current block (e.g., by calling the function \tcode{std::exit(int)}\iref{support.start.term}) does not destroy any objects with automatic storage duration\iref{class.dtor}. If -\tcode{std::exit} is called to end a program during the destruction of +\tcode{std::exit} is invoked during the destruction of an object with static or thread storage duration, the program has undefined behavior. From 70eb0406596b4f4e3d97ed50b3fd6d93b3032d18 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 25 Oct 2021 23:57:58 +0200 Subject: [PATCH 030/182] [basic.start.main] Avoid implementation guidance in a note --- source/basic.tex | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 2d21697791..dfde634451 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -6346,11 +6346,9 @@ the initial character of a \ntmbs{} that represents the name used to invoke the program or \tcode{""}. The value of \tcode{argc} shall be non-negative. The value of \tcode{argv[argc]} shall be 0. -\begin{note} -It -is recommended that any further (optional) parameters be added after -\tcode{argv}. -\end{note} + +\recommended +Any further (optional) parameters should be added after \tcode{argv}. \pnum The function \tcode{main} shall not be used within From ac8d6611a739c64eda4a7062f2cb83f770cd8a53 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 25 Oct 2021 23:58:08 +0200 Subject: [PATCH 031/182] [dcl.link] Avoid implementation guidance in a note --- source/declarations.tex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/declarations.tex b/source/declarations.tex index 406cecc0fe..254bc1d818 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -8129,12 +8129,12 @@ Therefore, a linkage-specification with a \grammarterm{string-literal} that is unknown to the implementation requires a diagnostic. \end{note} -\begin{note} -It is recommended that the spelling of the \grammarterm{string-literal} be + +\recommended +The spelling of the \grammarterm{string-literal} should be taken from the document defining that language. For example, \tcode{Ada} (not \tcode{ADA}) and \tcode{Fortran} or \tcode{FORTRAN}, depending on the vintage. -\end{note} \pnum \indextext{specification!linkage!implementation-defined}% From 2ad67aefe350017c4e9403ba2015af683813787f Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 6 Nov 2021 22:08:47 +0100 Subject: [PATCH 032/182] [lex] Remove Unicode character name abbreviations They are not part of the character name or alias. The presentation in ISO 10646 is misleading, though. --- source/lex.tex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/lex.tex b/source/lex.tex index 133208bd4b..0727a29608 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -245,9 +245,9 @@ \lhdrx{2}{character} & \rhdr{glyph} \\ \capsep \ucode{0009} & \uname{character tabulation} & \\ \ucode{000b} & \uname{line tabulation} & \\ -\ucode{000c} & \uname{form feed (ff)} & \\ +\ucode{000c} & \uname{form feed} & \\ \ucode{0020} & \uname{space} & \\ -\ucode{000a} & \uname{line feed (lf)} & new-line \\ +\ucode{000a} & \uname{line feed} & new-line \\ \ucode{0021} & \uname{exclamation mark} & \tcode{!} \\ \ucode{0022} & \uname{quotation mark} & \tcode{"} \\ \ucode{0023} & \uname{number sign} & \tcode{\#} \\ @@ -328,7 +328,7 @@ \ucode{0000} & \uname{null} \\ \ucode{0007} & \uname{bell} \\ \ucode{0008} & \uname{backspace} \\ -\ucode{000d} & \uname{carriage return (cr)} \\ +\ucode{000d} & \uname{carriage return} \\ \end{floattable} \pnum From 29c89b16e92cd03a76eb2a19866e683a7bb7ac80 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 6 Nov 2021 22:15:05 +0100 Subject: [PATCH 033/182] [lex] Rename U+0007 BELL to ALERT The former is ambiguous with U+1F514 BELL. The ALERT alias is defined in UCD NameAliases.txt. --- source/lex.tex | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/lex.tex b/source/lex.tex index 0727a29608..3576c7406e 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -322,11 +322,16 @@ The \defnadj{basic literal}{character set} consists of all characters of the basic character set, plus the control characters specified in \tref{lex.charset.literal}. +\begin{note} +The alias \uname{bell} for \ucode{0007} shown in ISO 10646 +is ambiguous with \unicode{1f514}{bell}. +\end{note} + \begin{floattable}{Additional control characters in the basic literal character set}{lex.charset.literal}{ll} \topline \ohdrx{2}{character} \\ \capsep \ucode{0000} & \uname{null} \\ -\ucode{0007} & \uname{bell} \\ +\ucode{0007} & \uname{alert} \\ \ucode{0008} & \uname{backspace} \\ \ucode{000d} & \uname{carriage return} \\ \end{floattable} @@ -1503,7 +1508,7 @@ \ucode{0008} & \uname{backspace} & \tcode{\textbackslash b} \\ \ucode{000d} & \uname{carriage return} & \tcode{\textbackslash r} \\ \ucode{000c} & \uname{form feed} & \tcode{\textbackslash f} \\ -\ucode{0007} & \uname{bell} & \tcode{\textbackslash a} \\ +\ucode{0007} & \uname{alert} & \tcode{\textbackslash a} \\ \ucode{005c} & \uname{reverse solidus} & \tcode{\textbackslash\textbackslash} \\ \ucode{003f} & \uname{question mark} & \tcode{\textbackslash ?} \\ \ucode{0027} & \uname{apostrohpe} & \tcode{\textbackslash '} \\ From 408623b7d8f0efd77403d1d0142d9bd59d1cfe55 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 4 Dec 2021 11:19:54 +0100 Subject: [PATCH 034/182] [associative.reqmts.general] Fix typo: 'kx', not 'rx' (#5136) --- source/containers.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/containers.tex b/source/containers.tex index 2393a6a8d7..532888a1d8 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -1723,7 +1723,7 @@ \tcode{kx} is a value such that \begin{itemize} \item -\tcode{a} is partitioned with respect to \tcode{c(r, rx)} and \tcode{!c(kx, r)}, +\tcode{a} is partitioned with respect to \tcode{c(r, kx)} and \tcode{!c(kx, r)}, with \tcode{c(r, kx)} implying \tcode{!c(kx, r)}, and \item \tcode{kx} is not convertible to From f03473cd1e32691c105260e65dd534960cf9db21 Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Sun, 5 Dec 2021 21:19:00 +0100 Subject: [PATCH 035/182] [over.sub] Fix typo: change oeprator to operator (#5140) --- source/overloading.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/overloading.tex b/source/overloading.tex index 9872bb1991..2b65b63002 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -3315,7 +3315,7 @@ \begin{codeblock} struct X { Z operator[](std::initializer_list); - Z oeprator[](auto...); + Z operator[](auto...); }; X x; x[{1,2,3}] = 7; // OK, meaning \tcode{x.\keyword{operator}[](\{1,2,3\})} From c69a35501174f5ab5d3f13f12186cc9b1fcd40dd Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 14 Dec 2021 11:24:04 +0100 Subject: [PATCH 036/182] [range.access] Fix cross-references for 'array' (#5147) Also introduce a label 'term.array.type' in [dcl.array]. --- source/declarations.tex | 1 + source/ranges.tex | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/source/declarations.tex b/source/declarations.tex index 254bc1d818..dade96d3b3 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -3175,6 +3175,7 @@ \pnum \indextext{declaration!array}% +\label{term.array.type}% A type of the form ``array of \tcode{N} \tcode{U}'' or ``array of unknown bound of \tcode{U}'' is an \defn{array type}. The optional \grammarterm{attribute-specifier-seq} diff --git a/source/ranges.tex b/source/ranges.tex index 7fc5643bdd..7616368c5f 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -465,7 +465,7 @@ \tcode{ranges::begin(E)} is ill-formed. \item - Otherwise, if \tcode{T} is an array type\iref{basic.compound} and + Otherwise, if \tcode{T} is an array type\iref{term.array.type} and \tcode{remove_all_extents_t} is an incomplete type, \tcode{ranges::begin(E)} is ill-formed with no diagnostic required. @@ -531,7 +531,7 @@ \tcode{ranges::end(E)} is ill-formed. \item - Otherwise, if \tcode{T} is an array type\iref{basic.compound} and + Otherwise, if \tcode{T} is an array type\iref{term.array.type} and \tcode{remove_all_extents_t} is an incomplete type, \tcode{ranges::end(E)} is ill-formed with no diagnostic required. @@ -644,7 +644,7 @@ \tcode{ranges::rbegin(E)} is ill-formed. \item - Otherwise, if \tcode{T} is an array type\iref{basic.compound} and + Otherwise, if \tcode{T} is an array type\iref{term.array.type} and \tcode{remove_all_extents_t} is an incomplete type, \tcode{ranges::rbegin(E)} is ill-formed with no diagnostic required. @@ -713,7 +713,7 @@ \tcode{ranges::rend(E)} is ill-formed. \item - Otherwise, if \tcode{T} is an array type\iref{basic.compound} and + Otherwise, if \tcode{T} is an array type\iref{term.array.type} and \tcode{remove_all_extents_t} is an incomplete type, \tcode{ranges::rend(E)} is ill-formed with no diagnostic required. @@ -821,7 +821,7 @@ \begin{itemize} \item - If \tcode{T} is an array of unknown bound\iref{dcl.array}, + If \tcode{T} is an array of unknown bound\iref{term.array.type}, \tcode{ranges::size(E)} is ill-formed. \item @@ -912,7 +912,7 @@ \begin{itemize} \item - If \tcode{T} is an array of unknown bound\iref{basic.compound}, + If \tcode{T} is an array of unknown bound\iref{term.array.type}, \tcode{ranges::empty(E)} is ill-formed. \item @@ -968,7 +968,7 @@ \tcode{ranges::data(E)} is ill-formed. \item - Otherwise, if \tcode{T} is an array type\iref{basic.compound} and + Otherwise, if \tcode{T} is an array type\iref{term.array.type} and \tcode{remove_all_extents_t} is an incomplete type, \tcode{ranges::data(E)} is ill-formed with no diagnostic required. From 2501feefb62bc26dcf2a39278b3b5a10da7945c5 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 19 Nov 2021 22:45:33 +0100 Subject: [PATCH 037/182] [index] Index keywords as ', keyword' for differentiation --- source/macros.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/macros.tex b/source/macros.tex index 604edb598a..50a06d8fca 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -224,7 +224,7 @@ \newcommand{\term}[1]{\textit{#1}} \newcommand{\gterm}[1]{\GrammarStylex{#1}} \newcommand{\fakegrammarterm}[1]{\gterm{#1}} -\newcommand{\keyword}[1]{\tcode{#1}\indextext{\idxcode{#1}}} % macro length: 8 +\newcommand{\keyword}[1]{\tcode{#1}\indextext{\idxcode{#1}!keyword}} % macro length: 8 \newcommand{\grammarterm}[1]{\indexgram{\idxgram{#1}}\gterm{#1}} \newcommand{\grammartermnc}[1]{\indexgram{\idxgram{#1}}\gterm{#1\nocorr}} \newcommand{\regrammarterm}[1]{\textit{#1}} @@ -597,7 +597,7 @@ { \newcommand{\nontermdef}[1]{{\BnfNontermshape##1\itcorr}\indexgrammar{\idxgram{##1}}\textnormal{:}} \newcommand{\terminal}[1]{{\BnfTermshape ##1}} - \renewcommand{\keyword}[1]{\terminal{##1}\indextext{\idxcode{##1}}} + \renewcommand{\keyword}[1]{\terminal{##1}\indextext{\idxcode{##1}!keyword}} \renewcommand{\exposid}[1]{\terminal{\textit{##1}}} \renewcommand{\placeholder}[1]{\textrm{\textit{##1}}} \newcommand{\descr}[1]{\textnormal{##1}} From 7a09dddd036359a10cf10b8e7d80c8edd8c76817 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 16 Dec 2021 19:39:18 +0100 Subject: [PATCH 038/182] [basic.fundamental] Excise normative requirements on std::numeric_limits (#5105) --- source/basic.tex | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index dfde634451..90685d5eea 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4985,13 +4985,18 @@ This document imposes no requirements on the accuracy of floating-point operations; see also~\ref{support.limits}. \end{note} + +\pnum Integral and floating-point types are collectively termed \defnx{arithmetic types}{type!arithmetic}. -\indextext{\idxcode{numeric_limits}!specializations for arithmetic types}% -Specializations of the standard library template -\tcode{std::numeric_limits}\iref{support.limits} shall specify the -maximum and minimum values of each arithmetic type for an -implementation. +\begin{note} +Properties of the arithmetic types, +such as their minimum and maximum representable value, +can be queried using the facilities in the standard library headers +\libheaderref{limits}, +\libheaderref{climits}, and +\libheaderref{cfloat}. +\end{note} \pnum \indextext{type!\idxcode{void}}% From c2617432eac3313abd2134a26e2d8a1d925dfd15 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Thu, 16 Dec 2021 23:53:17 -0800 Subject: [PATCH 039/182] [depr.default.allocator] Index allocator::is_always_equal here (#5152) LWG3170 deprecated `allocator::is_always_equal`. We moved it to Annex D, but left the index entry behind. --- source/future.tex | 1 + source/utilities.tex | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/source/future.tex b/source/future.tex index ee0a3f2443..44b4b31aa1 100644 --- a/source/future.tex +++ b/source/future.tex @@ -1319,6 +1319,7 @@ The following member is defined in addition to those specified in \ref{default.allocator}: +\indexlibrarymember{is_always_equal}{allocator}% \begin{codeblock} namespace std { template class allocator { diff --git a/source/utilities.tex b/source/utilities.tex index a680c2cd23..3405366739 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -8700,7 +8700,6 @@ \indexlibrarymember{size_type}{allocator}% \indexlibrarymember{difference_type}{allocator}% \indexlibrarymember{propagate_on_container_move_assignment}{allocator}% -\indexlibrarymember{is_always_equal}{allocator}% \indexlibrarymember{operator=}{allocator}% \begin{codeblock} namespace std { From 28effaea15ef697f5a64fba47b9c095c9fbfe82a Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 19 Dec 2021 22:16:18 +0100 Subject: [PATCH 040/182] [ptr.align,re.regiter.incr] Replace 'compiler' with 'implementation' --- source/regex.tex | 2 +- source/utilities.tex | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/regex.tex b/source/regex.tex index d69c440ed5..f326424900 100644 --- a/source/regex.tex +++ b/source/regex.tex @@ -3235,7 +3235,7 @@ \pnum \begin{note} -This means that a compiler can call an +This means that an implementation can call an implementation-specific search function, in which case a program-defined specialization of \tcode{regex_search} will not be called. diff --git a/source/utilities.tex b/source/utilities.tex index 3405366739..44cf73ad5c 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -8074,7 +8074,7 @@ expressed by a call to \tcode{assume_aligned} might result in generation of more efficient code. It is up to the program to ensure that the assumption actually holds. -The call does not cause the compiler to verify or enforce this. +The call does not cause the implementation to verify or enforce this. An implementation might only make the assumption for those operations on \tcode{X} that access \tcode{X} through the pointer returned by \tcode{assume_aligned}. From 575b9a99062de34cc44bc45aeb459f32aa12b98f Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 19 Dec 2021 22:19:19 +0100 Subject: [PATCH 041/182] [smartptr.adapt] Emphasize that casting might not always be viable --- source/utilities.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index 44cf73ad5c..ca4e740f22 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -12162,7 +12162,7 @@ \pnum \begin{note} \tcode{reinterpret_cast(static_cast(*this))} -can be a viable implementation strategy. +can be a viable implementation strategy for some implementations. \end{note} \end{itemdescr} @@ -12400,7 +12400,7 @@ \pnum \begin{note} \tcode{reinterpret_cast(static_cast(*this))} -can be a viable implementation strategy. +can be a viable implementation strategy for some implementations. \end{note} \end{itemdescr} From b34b337b26cd42e994e7189b1be68b6100ad6060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Tue, 21 Dec 2021 22:54:41 +0000 Subject: [PATCH 042/182] [macros] Make U+NNNN "fake small-cap-height" numbers a bit smaller. Previously, the scaled-down numbers and letters were a little bit taller than the small-caps height. Now they should look more or less equally tall. --- source/macros.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/macros.tex b/source/macros.tex index 50a06d8fca..40286c0842 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -358,7 +358,7 @@ \renewcommand{\fref}[1]{\hyperref[fig:#1]{\figurerefname \nolinebreak[3] \ref*{fig:#1}}} %% NTBS, etc. -\newcommand{\ucode}[1]{\textsc{u}\textsmaller[1]{\kern-0.05em\protect\raisebox{.25ex}{\textsmaller[1]{+}}\uppercase{#1}}} +\newcommand{\ucode}[1]{\textsc{u}\textsmaller[1.5]{\kern-0.05em\protect\raisebox{.25ex}{\textsmaller[1]{+}}\uppercase{#1}}} \newcommand{\uname}[1]{\textsc{#1}} \newcommand{\unicode}[2]{\ucode{#1} \uname{#2}} \newcommand{\NTS}[1]{\textsc{#1}} From 5da69c95b3e83cde83aff7c05952fd7b96715b5a Mon Sep 17 00:00:00 2001 From: timsong-cpp Date: Mon, 10 Jan 2022 13:42:12 -0600 Subject: [PATCH 043/182] [algorithm.syn,alg.min.max] Fix indexing of indirectly_copyable_storable (#5195) --- source/algorithms.tex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/algorithms.tex b/source/algorithms.tex index a6e7f7810b..c6f00f2971 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -2651,7 +2651,7 @@ constexpr T min(initializer_list r, Comp comp = {}, Proj proj = {}); template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> - requires @\libconcept{indirectly_copyable}@_storable, range_value_t*> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr range_value_t min(R&& r, Comp comp = {}, Proj proj = {}); } @@ -2673,7 +2673,7 @@ constexpr T max(initializer_list r, Comp comp = {}, Proj proj = {}); template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> - requires @\libconcept{indirectly_copyable}@_storable, range_value_t*> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr range_value_t max(R&& r, Comp comp = {}, Proj proj = {}); } @@ -2700,7 +2700,7 @@ minmax(initializer_list r, Comp comp = {}, Proj proj = {}); template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> - requires @\libconcept{indirectly_copyable}@_storable, range_value_t*> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr minmax_result> minmax(R&& r, Comp comp = {}, Proj proj = {}); } @@ -8264,7 +8264,7 @@ constexpr T ranges::min(initializer_list r, Comp comp = {}, Proj proj = {}); template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> - requires @\libconcept{indirectly_copyable}@_storable, range_value_t*> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr range_value_t ranges::min(R&& r, Comp comp = {}, Proj proj = {}); \end{itemdecl} From 9ba8e0329a0f5db15544c31c514ff44e0003f08f Mon Sep 17 00:00:00 2001 From: frederick-vs-ja Date: Tue, 11 Jan 2022 23:29:26 +0800 Subject: [PATCH 044/182] [pairs.pair] Add missing _v for type traits (#5196) --- source/utilities.tex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index ca4e740f22..edf6a7a6b3 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -932,9 +932,9 @@ \constraints \begin{itemize} \item -\tcode{is_copy_assignable} is \tcode{true} and +\tcode{is_copy_assignable_v} is \tcode{true} and \item -\tcode{is_copy_assignable} is \tcode{true}. +\tcode{is_copy_assignable_v} is \tcode{true}. \end{itemize} \pnum @@ -1032,9 +1032,9 @@ \constraints \begin{itemize} \item -\tcode{is_assignable} is \tcode{true} and +\tcode{is_assignable_v} is \tcode{true} and \item -\tcode{is_assignable} is \tcode{true}. +\tcode{is_assignable_v} is \tcode{true}. \end{itemize} \pnum From dae6769d9767e2e47f2fe451d9c796dd07d0ae29 Mon Sep 17 00:00:00 2001 From: zhihaoy <43971430+zhihaoy@users.noreply.github.com> Date: Thu, 13 Jan 2022 14:03:25 -0800 Subject: [PATCH 045/182] [func.memfn] Correct target object by fixing typo (#5202) --- source/utilities.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/utilities.tex b/source/utilities.tex index edf6a7a6b3..276f46f99c 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -16013,7 +16013,7 @@ \tcode{pmd} is the target object of \tcode{fn} of type \tcode{R T::*} direct-non-list-initialized with \tcode{pm}, and \tcode{call_args} is an argument pack -used in a function call expression\iref{expr.call} of \tcode{pm}. +used in a function call expression\iref{expr.call} of \tcode{fn}. \end{itemdescr} \indextext{function object!\idxcode{mem_fn}|)} From 5f830f97829965cf791dfe6eef6b84d6283712be Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 24 Nov 2021 22:04:55 +0100 Subject: [PATCH 046/182] [lib] Add 'namespace std' wrappings around class definitions Those were missing in a few places, notably [rand]. Also add an automated check. --- source/numerics.tex | 258 +++++++++++++++++++++++++----------------- source/regex.tex | 12 +- source/utilities.tex | 36 +++--- tools/check-source.sh | 8 ++ 4 files changed, 191 insertions(+), 123 deletions(-) diff --git a/source/numerics.tex b/source/numerics.tex index 322ec98e0e..9448d6a94a 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -3010,7 +3010,8 @@ \indexlibraryglobal{linear_congruential_engine}% \indexlibrarymember{result_type}{linear_congruential_engine}% \begin{codeblock} -template +namespace std { + template class linear_congruential_engine { public: // types @@ -3047,6 +3048,7 @@ friend basic_istream& operator>>(basic_istream& is, linear_congruential_engine& x); }; +} \end{codeblock} \pnum @@ -3176,10 +3178,11 @@ \indexlibraryglobal{mersenne_twister_engine}% \indexlibrarymember{result_type}{mersenne_twister_engine}% \begin{codeblock} -template +namespace std { + template class mersenne_twister_engine { public: // types @@ -3225,6 +3228,7 @@ friend basic_istream& operator>>(basic_istream& is, mersenne_twister_engine& x); }; +} \end{codeblock} \pnum @@ -3352,7 +3356,8 @@ \indexlibraryglobal{subtract_with_carry_engine}% \indexlibrarymember{result_type}{subtract_with_carry_engine}% \begin{codeblock} -template +namespace std { + template class subtract_with_carry_engine { public: // types @@ -3389,6 +3394,7 @@ friend basic_istream& operator>>(basic_istream& is, subtract_with_carry_engine& x); }; +} \end{codeblock} \pnum @@ -3556,7 +3562,8 @@ \indexlibraryglobal{discard_block_engine}% \indexlibrarymember{result_type}{discard_block_engine}% \begin{codeblock} -template +namespace std { + template class discard_block_engine { public: // types @@ -3600,6 +3607,7 @@ Engine e; // \expos size_t n; // \expos }; +} \end{codeblock} \pnum @@ -3805,7 +3813,8 @@ \indexlibraryglobal{shuffle_order_engine}% \indexlibrarymember{result_type}{shuffle_order_engine}% \begin{codeblock} -template +namespace std { + template class shuffle_order_engine { public: // types @@ -3849,6 +3858,7 @@ result_type V[k]; // \expos result_type Y; // \expos }; +} \end{codeblock} \pnum @@ -4085,29 +4095,31 @@ \indexlibraryglobal{random_device}% \indexlibrarymember{result_type}{random_device}% \begin{codeblock} -class random_device { -public: - // types - using result_type = unsigned int; +namespace std { + class random_device { + public: + // types + using result_type = unsigned int; - // generator characteristics - static constexpr result_type min() { return numeric_limits::min(); } - static constexpr result_type max() { return numeric_limits::max(); } + // generator characteristics + static constexpr result_type min() { return numeric_limits::min(); } + static constexpr result_type max() { return numeric_limits::max(); } - // constructors - random_device() : random_device(@\textit{implementation-defined}@) {} - explicit random_device(const string& token); + // constructors + random_device() : random_device(@\textit{implementation-defined}@) {} + explicit random_device(const string& token); - // generating functions - result_type operator()(); + // generating functions + result_type operator()(); - // property functions - double entropy() const noexcept; + // property functions + double entropy() const noexcept; - @\textit{// no copy functions}@ - random_device(const random_device&) = delete; - void operator=(const random_device&) = delete; -}; + @\textit{// no copy functions}@ + random_device(const random_device&) = delete; + void operator=(const random_device&) = delete; + }; +} \end{codeblock} @@ -4202,34 +4214,36 @@ \indexlibraryglobal{seed_seq}% \indexlibrarymember{result_type}{seed_seq}% \begin{codeblock} -class seed_seq { -public: - // types - using result_type = uint_least32_t; +namespace std { + class seed_seq { + public: + // types + using result_type = uint_least32_t; - // constructors - seed_seq() noexcept; - template - seed_seq(initializer_list il); - template - seed_seq(InputIterator begin, InputIterator end); + // constructors + seed_seq() noexcept; + template + seed_seq(initializer_list il); + template + seed_seq(InputIterator begin, InputIterator end); - // generating functions - template - void generate(RandomAccessIterator begin, RandomAccessIterator end); + // generating functions + template + void generate(RandomAccessIterator begin, RandomAccessIterator end); - // property functions - size_t size() const noexcept; - template - void param(OutputIterator dest) const; + // property functions + size_t size() const noexcept; + template + void param(OutputIterator dest) const; - // no copy functions - seed_seq(const seed_seq&) = delete; - void operator=(const seed_seq&) = delete; + // no copy functions + seed_seq(const seed_seq&) = delete; + void operator=(const seed_seq&) = delete; -private: - vector v; // \expos -}; + private: + vector v; // \expos + }; +} \end{codeblock} @@ -4574,7 +4588,8 @@ \indexlibraryglobal{uniform_int_distribution}% \indexlibrarymember{result_type}{uniform_int_distribution}% \begin{codeblock} -template +namespace std { + template class uniform_int_distribution { public: // types @@ -4612,6 +4627,7 @@ friend basic_istream& operator>>(basic_istream& is, uniform_int_distribution& x); }; +} \end{codeblock} @@ -4675,7 +4691,8 @@ \indexlibraryglobal{uniform_real_distribution}% \indexlibrarymember{result_type}{uniform_real_distribution}% \begin{codeblock} -template +namespace std { + template class uniform_real_distribution { public: // types @@ -4714,6 +4731,7 @@ friend basic_istream& operator>>(basic_istream& is, uniform_real_distribution& x); }; +} \end{codeblock} @@ -4792,42 +4810,44 @@ \indexlibraryglobal{bernoulli_distribution}% \indexlibrarymember{result_type}{bernoulli_distribution}% \begin{codeblock} -class bernoulli_distribution { -public: - // types - using result_type = bool; - using param_type = @\unspec@; - - // constructors and reset functions - bernoulli_distribution() : bernoulli_distribution(0.5) {} - explicit bernoulli_distribution(double p); - explicit bernoulli_distribution(const param_type& parm); - void reset(); - - // equality operators - friend bool operator==(const bernoulli_distribution& x, const bernoulli_distribution& y); - - // generating functions - template - result_type operator()(URBG& g); - template - result_type operator()(URBG& g, const param_type& parm); - - // property functions - double p() const; - param_type param() const; - void param(const param_type& parm); - result_type min() const; - result_type max() const; - - // inserters and extractors - template - friend basic_ostream& - operator<<(basic_ostream& os, const bernoulli_distribution& x); - template - friend basic_istream& - operator>>(basic_istream& is, bernoulli_distribution& x); -}; +namespace std { + class bernoulli_distribution { + public: + // types + using result_type = bool; + using param_type = @\unspec@; + + // constructors and reset functions + bernoulli_distribution() : bernoulli_distribution(0.5) {} + explicit bernoulli_distribution(double p); + explicit bernoulli_distribution(const param_type& parm); + void reset(); + + // equality operators + friend bool operator==(const bernoulli_distribution& x, const bernoulli_distribution& y); + + // generating functions + template + result_type operator()(URBG& g); + template + result_type operator()(URBG& g, const param_type& parm); + + // property functions + double p() const; + param_type param() const; + void param(const param_type& parm); + result_type min() const; + result_type max() const; + + // inserters and extractors + template + friend basic_ostream& + operator<<(basic_ostream& os, const bernoulli_distribution& x); + template + friend basic_istream& + operator>>(basic_istream& is, bernoulli_distribution& x); + }; +} \end{codeblock} @@ -4875,7 +4895,8 @@ \indexlibraryglobal{binomial_distribution}% \indexlibrarymember{result_type}{binomial_distribution}% \begin{codeblock} -template +namespace std { + template class binomial_distribution { public: // types @@ -4913,6 +4934,7 @@ friend basic_istream& operator>>(basic_istream& is, binomial_distribution& x); }; +} \end{codeblock} @@ -4971,7 +4993,8 @@ \indexlibraryglobal{geometric_distribution}% \indexlibrarymember{result_type}{geometric_distribution}% \begin{codeblock} -template +namespace std { + template class geometric_distribution { public: // types @@ -5008,6 +5031,7 @@ friend basic_istream& operator>>(basic_istream& is, geometric_distribution& x); }; +} \end{codeblock} @@ -5059,7 +5083,8 @@ \indexlibraryglobal{negative_binomial_distribution}% \indexlibrarymember{result_type}{negative_binomial_distribution}% \begin{codeblock} -template +namespace std { + template class negative_binomial_distribution { public: // types @@ -5098,6 +5123,7 @@ friend basic_istream& operator>>(basic_istream& is, negative_binomial_distribution& x); }; +} \end{codeblock} @@ -5257,7 +5283,8 @@ \indexlibraryglobal{exponential_distribution}% \indexlibrarymember{result_type}{exponential_distribution}% \begin{codeblock} -template +namespace std { + template class exponential_distribution { public: // types @@ -5294,6 +5321,7 @@ friend basic_istream& operator>>(basic_istream& is, exponential_distribution& x); }; +} \end{codeblock} @@ -5342,7 +5370,8 @@ \indexlibraryglobal{gamma_distribution}% \indexlibrarymember{result_type}{gamma_distribution}% \begin{codeblock} -template +namespace std { + template class gamma_distribution { public: // types @@ -5380,6 +5409,7 @@ friend basic_istream& operator>>(basic_istream& is, gamma_distribution& x); }; +} \end{codeblock} @@ -5443,7 +5473,8 @@ \indexlibraryglobal{weibull_distribution}% \indexlibrarymember{result_type}{weibull_distribution}% \begin{codeblock} -template +namespace std { + template class weibull_distribution { public: // types @@ -5481,6 +5512,7 @@ friend basic_istream& operator>>(basic_istream& is, weibull_distribution& x); }; +} \end{codeblock} \indexlibraryctor{weibull_distribution}% @@ -5552,7 +5584,8 @@ \indexlibraryglobal{extreme_value_distribution}% \indexlibrarymember{result_type}{extreme_value_distribution}% \begin{codeblock} -template +namespace std { + template class extreme_value_distribution { public: // types @@ -5591,6 +5624,7 @@ friend basic_istream& operator>>(basic_istream& is, extreme_value_distribution& x); }; +} \end{codeblock} @@ -5676,7 +5710,8 @@ \indexlibraryglobal{normal_distribution}% \indexlibrarymember{result_type}{normal_distribution}% \begin{codeblock} -template +namespace std { + template class normal_distribution { public: // types @@ -5714,6 +5749,7 @@ friend basic_istream& operator>>(basic_istream& is, normal_distribution& x); }; +} \end{codeblock} @@ -5776,7 +5812,8 @@ \indexlibraryglobal{lognormal_distribution}% \indexlibrarymember{result_type}{lognormal_distribution}% \begin{codeblock} -template +namespace std { + template class lognormal_distribution { public: // types @@ -5814,6 +5851,7 @@ friend basic_istream& operator>>(basic_istream& is, lognormal_distribution& x); }; +} \end{codeblock} @@ -5874,7 +5912,8 @@ \indexlibraryglobal{chi_squared_distribution}% \indexlibrarymember{result_type}{chi_squared_distribution}% \begin{codeblock} -template +namespace std { + template class chi_squared_distribution { public: // types @@ -5911,6 +5950,7 @@ friend basic_istream& operator>>(basic_istream& is, chi_squared_distribution& x); }; +} \end{codeblock} @@ -5958,7 +5998,8 @@ \indexlibraryglobal{cauchy_distribution}% \indexlibrarymember{result_type}{cauchy_distribution}% \begin{codeblock} -template +namespace std { + template class cauchy_distribution { public: // types @@ -5996,6 +6037,7 @@ friend basic_istream& operator>>(basic_istream& is, cauchy_distribution& x); }; +} \end{codeblock} @@ -6060,7 +6102,8 @@ \indexlibraryglobal{fisher_f_distribution}% \indexlibrarymember{result_type}{fisher_distribution}% \begin{codeblock} -template +namespace std { + template class fisher_f_distribution { public: // types @@ -6098,6 +6141,7 @@ friend basic_istream& operator>>(basic_istream& is, fisher_f_distribution& x); }; +} \end{codeblock} @@ -6161,7 +6205,8 @@ \indexlibraryglobal{student_t_distribution}% \indexlibrarymember{result_type}{student_t_distribution}% \begin{codeblock} -template +namespace std { + template class student_t_distribution { public: // types @@ -6198,6 +6243,7 @@ friend basic_istream& operator>>(basic_istream& is, student_t_distribution& x); }; +} \end{codeblock} @@ -6269,7 +6315,8 @@ \indexlibraryglobal{discrete_distribution}% \indexlibrarymember{result_type}{discrete_distribution}% \begin{codeblock} -template +namespace std { + template class discrete_distribution { public: // types @@ -6310,6 +6357,7 @@ friend basic_istream& operator>>(basic_istream& is, discrete_distribution& x); }; +} \end{codeblock} \indexlibraryctor{discrete_distribution} @@ -6451,7 +6499,8 @@ \indexlibraryglobal{piecewise_constant_distribution}% \indexlibrarymember{result_type}{piecewise_constant_distribution}% \begin{codeblock} -template +namespace std { + template class piecewise_constant_distribution { public: // types @@ -6497,6 +6546,7 @@ friend basic_istream& operator>>(basic_istream& is, piecewise_constant_distribution& x); }; +} \end{codeblock} @@ -6685,7 +6735,8 @@ \indexlibraryglobal{piecewise_linear_distribution}% \indexlibrarymember{result_type}{piecewise_linear_distribution}% \begin{codeblock} -template +namespace std { + template class piecewise_linear_distribution { public: // types @@ -6730,6 +6781,7 @@ friend basic_istream& operator>>(basic_istream& is, piecewise_linear_distribution& x); }; +} \end{codeblock} \indexlibraryctor{piecewise_linear_distribution} diff --git a/source/regex.tex b/source/regex.tex index f326424900..0cf5800101 100644 --- a/source/regex.tex +++ b/source/regex.tex @@ -810,11 +810,13 @@ \rSec1[re.badexp]{Class \tcode{regex_error}} \indexlibraryglobal{regex_error}% \begin{codeblock} -class regex_error : public runtime_error { -public: - explicit regex_error(regex_constants::error_type ecode); - regex_constants::error_type code() const; -}; +namespace std { + class regex_error : public runtime_error { + public: + explicit regex_error(regex_constants::error_type ecode); + regex_constants::error_type code() const; + }; +} \end{codeblock} \pnum diff --git a/source/utilities.tex b/source/utilities.tex index 276f46f99c..72bc5d9c5f 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -3936,11 +3936,13 @@ \rSec2[optional.bad.access]{Class \tcode{bad_optional_access}} \begin{codeblock} -class bad_optional_access : public exception { -public: - // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; -}; +namespace std { + class bad_optional_access : public exception { + public: + // see \ref{exception} for the specification of the special member functions + const char* what() const noexcept override; + }; +} \end{codeblock} \pnum @@ -5782,11 +5784,13 @@ \indexlibraryglobal{bad_variant_access}% \begin{codeblock} -class bad_variant_access : public exception { -public: - // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; -}; +namespace std { + class bad_variant_access : public exception { + public: + // see \ref{exception} for the specification of the special member functions + const char* what() const noexcept override; + }; +} \end{codeblock} \pnum @@ -5881,11 +5885,13 @@ \indexlibraryglobal{bad_any_cast}% \begin{codeblock} -class bad_any_cast : public bad_cast { -public: - // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; -}; +namespace std { + class bad_any_cast : public bad_cast { + public: + // see \ref{exception} for the specification of the special member functions + const char* what() const noexcept override; + }; +} \end{codeblock} \pnum diff --git a/tools/check-source.sh b/tools/check-source.sh index 7637904661..9ea4895657 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -108,6 +108,14 @@ grep -Hne '^\\\(change\|rationale\|effect\|difficulty\|howwide\)\s.\+$' compatib grep -ne 'template\s]*>//;/\(class\|struct\)[A-Za-z0-9_: ]*{/{=;p;};};}' $f | + # prefix output with filename and line + sed '/^[0-9]\+$/{N;s/\n/:/;}' | sed "s/.*/$f:&/" +done | + fail 'No namespace around class definition' || failed=1 + # \begin{example/note} with non-whitespace in front on the same line. grep -ne '^.*[^ ]\s*\\\(begin\|end\){\(example\|note\)}' $texfiles | fail "non-whitespace before note/example begins" || failed=1 From 2a27c17f524606956cb3140954952946c08910f9 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 17 Dec 2021 01:24:51 +0100 Subject: [PATCH 047/182] [std] Fix bad \grammarterms --- source/classes.tex | 2 +- source/expressions.tex | 2 +- source/templates.tex | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index 8f8da3465f..54bb47a04d 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -3613,7 +3613,7 @@ in a class $D$ derived (directly or indirectly) from $B$, a declaration of a member function $G$ corresponds\iref{basic.scope.scope} to a declaration of $F$, -ignoring \grammarterm{trailing requires-clause}s, +ignoring trailing \grammarterm{requires-clause}s, \indextext{override|see{function, virtual, override}}% then $G$ \defnx{overrides}{function!virtual!override} \begin{footnote} diff --git a/source/expressions.tex b/source/expressions.tex index d63db2546f..0cc7bbd662 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -1450,7 +1450,7 @@ in a \grammarterm{lambda-expression} at program point $P$ and the entity is a local entity\iref{basic.pre} or a variable declared by an \grammarterm{init-capture}\iref{expr.prim.lambda.capture}, -then let $S$ be the \grammarterm{compound-expression} of +then let $S$ be the \grammarterm{compound-statement} of the innermost enclosing \grammarterm{lambda-expression} of $P$. If naming the entity from outside of an unevaluated operand within $S$ would refer to an entity diff --git a/source/templates.tex b/source/templates.tex index b68b7311c1..2c9d9e3d17 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -3655,7 +3655,7 @@ would satisfy the one-definition rule, except that the tokens used to name types and declarations may differ as long as they name the same entities, and -the tokens used to form \grammarterm{concept-id}s may differ +the tokens used to form concept-ids\iref{temp.names} may differ as long as the two \grammarterm{template-id}{s} are the same\iref{temp.type}. \begin{note} For instance, \tcode{A<42>} and \tcode{A<40+2>} name the same type. From 1d6372110803eab0375392bdabcbb18556eefce1 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 17 Dec 2021 01:25:09 +0100 Subject: [PATCH 048/182] [check] Add check for use of undefined \grammarterms --- tools/check-output.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/check-output.sh b/tools/check-output.sh index 3ea883bb94..519a839cf4 100755 --- a/tools/check-output.sh +++ b/tools/check-output.sh @@ -34,6 +34,13 @@ grep -o '\\see{[^}]*}' < std-generalindex.ind | done | fail || failed=1 rm -f tmp.txt +# Find grammar index entries missing a definition +cat std-grammarindex.ind | + awk 'BEGIN { def=1 } /^ .item/ { if (def==0) { gsub("[{},]", "", item); print item } item=$NF; def=0; next } /hyperindexformat/ { def=1 }' | + grep -v -- '-keyword$' | # xxx-keyword is special + sed 's/^\(.*\)$/grammar non-terminal \1 has no definition/' | + fail || failed=1 + # Cross references since the previous standard. function indexentries() { sed 's,\\glossaryentry{\(.*\)@.*,\1,' "$1" | LANG=C sort; } function removals() { diff -u "$1" "$2" | grep '^-' | grep -v '^---' | sed 's/^-//'; } From 1031a409dfacb84b9871b16502c73e15249160eb Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 19 Nov 2021 23:02:19 +0100 Subject: [PATCH 049/182] [chrono.syn] Use nested namespace definitions for clarity --- source/time.tex | 1578 +++++++++++++++++++++++------------------------ 1 file changed, 789 insertions(+), 789 deletions(-) diff --git a/source/time.tex b/source/time.tex index 63be16fd12..667d1fc334 100644 --- a/source/time.tex +++ b/source/time.tex @@ -65,15 +65,15 @@ \begin{codeblock} #include // see \ref{compare.syn} -namespace std { - namespace chrono { - // \ref{time.duration}, class template \tcode{duration} - template> class duration; +namespace std::chrono { + // \ref{time.duration}, class template \tcode{duration} + template> class duration; - // \ref{time.point}, class template \tcode{time_point} - template class time_point; - } + // \ref{time.point}, class template \tcode{time_point} + template class time_point; +} +namespace std { // \ref{time.traits.specializations}, \tcode{common_type} specializations template struct common_type, @@ -82,735 +82,737 @@ template struct common_type, chrono::time_point>; +} - namespace chrono { - // \ref{time.traits}, customization traits - template struct treat_as_floating_point; - template - inline constexpr bool treat_as_floating_point_v = treat_as_floating_point::value; - - template struct duration_values; - - template struct is_clock; - template inline constexpr bool is_clock_v = is_clock::value; - - // \ref{time.duration.nonmember}, \tcode{duration} arithmetic - template - constexpr common_type_t, duration> - operator+(const duration& lhs, const duration& rhs); - template - constexpr common_type_t, duration> - operator-(const duration& lhs, const duration& rhs); - template - constexpr duration, Period> - operator*(const duration& d, const Rep2& s); - template - constexpr duration, Period> - operator*(const Rep1& s, const duration& d); - template - constexpr duration, Period> - operator/(const duration& d, const Rep2& s); - template - constexpr common_type_t - operator/(const duration& lhs, const duration& rhs); - template - constexpr duration, Period> - operator%(const duration& d, const Rep2& s); - template - constexpr common_type_t, duration> - operator%(const duration& lhs, const duration& rhs); - - // \ref{time.duration.comparisons}, \tcode{duration} comparisons - template - constexpr bool operator==(const duration& lhs, - const duration& rhs); - template - constexpr bool operator< (const duration& lhs, - const duration& rhs); - template - constexpr bool operator> (const duration& lhs, - const duration& rhs); - template - constexpr bool operator<=(const duration& lhs, - const duration& rhs); - template - constexpr bool operator>=(const duration& lhs, - const duration& rhs); - template - requires @\seebelow@ - constexpr auto operator<=>(const duration& lhs, - const duration& rhs); - - // \ref{time.duration.cast}, conversions - template - constexpr ToDuration duration_cast(const duration& d); - template - constexpr ToDuration floor(const duration& d); - template - constexpr ToDuration ceil(const duration& d); - template - constexpr ToDuration round(const duration& d); - - // \ref{time.duration.io}, \tcode{duration} I/O - template - basic_ostream& - operator<<(basic_ostream& os, - const duration& d); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - duration& d, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // convenience typedefs - using nanoseconds = duration<@\term{signed integer type of at least 64 bits}@, nano>; - using microseconds = duration<@\term{signed integer type of at least 55 bits}@, micro>; - using milliseconds = duration<@\term{signed integer type of at least 45 bits}@, milli>; - using seconds = duration<@\term{signed integer type of at least 35 bits}@>; - using minutes = duration<@\term{signed integer type of at least 29 bits}@, ratio< 60>>; - using hours = duration<@\term{signed integer type of at least 23 bits}@, ratio<3600>>; - using days = duration<@\term{signed integer type of at least 25 bits}@, - ratio_multiply, hours::period>>; - using weeks = duration<@\term{signed integer type of at least 22 bits}@, - ratio_multiply, days::period>>; - using years = duration<@\term{signed integer type of at least 17 bits}@, - ratio_multiply, days::period>>; - using months = duration<@\term{signed integer type of at least 20 bits}@, - ratio_divide>>; - - // \ref{time.point.nonmember}, \tcode{time_point} arithmetic - template - constexpr time_point>> - operator+(const time_point& lhs, const duration& rhs); - template - constexpr time_point, Duration2>> - operator+(const duration& lhs, const time_point& rhs); - template - constexpr time_point>> - operator-(const time_point& lhs, const duration& rhs); - template - constexpr common_type_t - operator-(const time_point& lhs, - const time_point& rhs); - - // \ref{time.point.comparisons}, \tcode{time_point} comparisons - template - constexpr bool operator==(const time_point& lhs, - const time_point& rhs); - template - constexpr bool operator< (const time_point& lhs, - const time_point& rhs); - template - constexpr bool operator> (const time_point& lhs, - const time_point& rhs); - template - constexpr bool operator<=(const time_point& lhs, - const time_point& rhs); - template - constexpr bool operator>=(const time_point& lhs, - const time_point& rhs); - template Duration2> - constexpr auto operator<=>(const time_point& lhs, - const time_point& rhs); - - // \ref{time.point.cast}, conversions - template - constexpr time_point - time_point_cast(const time_point& t); - template - constexpr time_point floor(const time_point& tp); - template - constexpr time_point ceil(const time_point& tp); - template - constexpr time_point round(const time_point& tp); - - // \ref{time.duration.alg}, specialized algorithms - template - constexpr duration abs(duration d); - - // \ref{time.clock.system}, class \tcode{system_clock} - class system_clock; +namespace std::chrono { + // \ref{time.traits}, customization traits + template struct treat_as_floating_point; + template + inline constexpr bool treat_as_floating_point_v = treat_as_floating_point::value; - template - using sys_time = time_point; - using sys_seconds = sys_time; - using sys_days = sys_time; + template struct duration_values; - template - basic_ostream& - operator<<(basic_ostream& os, const sys_time& tp); + template struct is_clock; + template inline constexpr bool is_clock_v = is_clock::value; - template - basic_ostream& - operator<<(basic_ostream& os, const sys_days& dp); + // \ref{time.duration.nonmember}, \tcode{duration} arithmetic + template + constexpr common_type_t, duration> + operator+(const duration& lhs, const duration& rhs); + template + constexpr common_type_t, duration> + operator-(const duration& lhs, const duration& rhs); + template + constexpr duration, Period> + operator*(const duration& d, const Rep2& s); + template + constexpr duration, Period> + operator*(const Rep1& s, const duration& d); + template + constexpr duration, Period> + operator/(const duration& d, const Rep2& s); + template + constexpr common_type_t + operator/(const duration& lhs, const duration& rhs); + template + constexpr duration, Period> + operator%(const duration& d, const Rep2& s); + template + constexpr common_type_t, duration> + operator%(const duration& lhs, const duration& rhs); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - sys_time& tp, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); + // \ref{time.duration.comparisons}, \tcode{duration} comparisons + template + constexpr bool operator==(const duration& lhs, + const duration& rhs); + template + constexpr bool operator< (const duration& lhs, + const duration& rhs); + template + constexpr bool operator> (const duration& lhs, + const duration& rhs); + template + constexpr bool operator<=(const duration& lhs, + const duration& rhs); + template + constexpr bool operator>=(const duration& lhs, + const duration& rhs); + template + requires @\seebelow@ + constexpr auto operator<=>(const duration& lhs, + const duration& rhs); + + // \ref{time.duration.cast}, conversions + template + constexpr ToDuration duration_cast(const duration& d); + template + constexpr ToDuration floor(const duration& d); + template + constexpr ToDuration ceil(const duration& d); + template + constexpr ToDuration round(const duration& d); + + // \ref{time.duration.io}, \tcode{duration} I/O + template + basic_ostream& + operator<<(basic_ostream& os, + const duration& d); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + duration& d, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // convenience typedefs + using nanoseconds = duration<@\term{signed integer type of at least 64 bits}@, nano>; + using microseconds = duration<@\term{signed integer type of at least 55 bits}@, micro>; + using milliseconds = duration<@\term{signed integer type of at least 45 bits}@, milli>; + using seconds = duration<@\term{signed integer type of at least 35 bits}@>; + using minutes = duration<@\term{signed integer type of at least 29 bits}@, ratio< 60>>; + using hours = duration<@\term{signed integer type of at least 23 bits}@, ratio<3600>>; + using days = duration<@\term{signed integer type of at least 25 bits}@, + ratio_multiply, hours::period>>; + using weeks = duration<@\term{signed integer type of at least 22 bits}@, + ratio_multiply, days::period>>; + using years = duration<@\term{signed integer type of at least 17 bits}@, + ratio_multiply, days::period>>; + using months = duration<@\term{signed integer type of at least 20 bits}@, + ratio_divide>>; + + // \ref{time.point.nonmember}, \tcode{time_point} arithmetic + template + constexpr time_point>> + operator+(const time_point& lhs, const duration& rhs); + template + constexpr time_point, Duration2>> + operator+(const duration& lhs, const time_point& rhs); + template + constexpr time_point>> + operator-(const time_point& lhs, const duration& rhs); + template + constexpr common_type_t + operator-(const time_point& lhs, + const time_point& rhs); - // \ref{time.clock.utc}, class \tcode{utc_clock} - class utc_clock; + // \ref{time.point.comparisons}, \tcode{time_point} comparisons + template + constexpr bool operator==(const time_point& lhs, + const time_point& rhs); + template + constexpr bool operator< (const time_point& lhs, + const time_point& rhs); + template + constexpr bool operator> (const time_point& lhs, + const time_point& rhs); + template + constexpr bool operator<=(const time_point& lhs, + const time_point& rhs); + template + constexpr bool operator>=(const time_point& lhs, + const time_point& rhs); + template Duration2> + constexpr auto operator<=>(const time_point& lhs, + const time_point& rhs); + + // \ref{time.point.cast}, conversions + template + constexpr time_point + time_point_cast(const time_point& t); + template + constexpr time_point floor(const time_point& tp); + template + constexpr time_point ceil(const time_point& tp); + template + constexpr time_point round(const time_point& tp); + + // \ref{time.duration.alg}, specialized algorithms + template + constexpr duration abs(duration d); + + // \ref{time.clock.system}, class \tcode{system_clock} + class system_clock; - template - using utc_time = time_point; - using utc_seconds = utc_time; + template + using sys_time = time_point; + using sys_seconds = sys_time; + using sys_days = sys_time; - template - basic_ostream& - operator<<(basic_ostream& os, const utc_time& t); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - utc_time& tp, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); + template + basic_ostream& + operator<<(basic_ostream& os, const sys_time& tp); - struct leap_second_info; + template + basic_ostream& + operator<<(basic_ostream& os, const sys_days& dp); - template - leap_second_info get_leap_second_info(const utc_time& ut); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + sys_time& tp, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); - // \ref{time.clock.tai}, class \tcode{tai_clock} - class tai_clock; + // \ref{time.clock.utc}, class \tcode{utc_clock} + class utc_clock; - template - using tai_time = time_point; - using tai_seconds = tai_time; - - template - basic_ostream& - operator<<(basic_ostream& os, const tai_time& t); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - tai_time& tp, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.clock.gps}, class \tcode{gps_clock} - class gps_clock; + template + using utc_time = time_point; + using utc_seconds = utc_time; - template - using gps_time = time_point; - using gps_seconds = gps_time; - - template - basic_ostream& - operator<<(basic_ostream& os, const gps_time& t); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - gps_time& tp, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.clock.file}, type \tcode{file_clock} - using file_clock = @\seebelow@; + template + basic_ostream& + operator<<(basic_ostream& os, const utc_time& t); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + utc_time& tp, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); - template - using file_time = time_point; - - template - basic_ostream& - operator<<(basic_ostream& os, const file_time& tp); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - file_time& tp, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.clock.steady}, class \tcode{steady_clock} - class steady_clock; - - // \ref{time.clock.hires}, class \tcode{high_resolution_clock} - class high_resolution_clock; - - // \ref{time.clock.local}, local time - struct local_t {}; - template - using local_time = time_point; - using local_seconds = local_time; - using local_days = local_time; - - template - basic_ostream& - operator<<(basic_ostream& os, const local_time& tp); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - local_time& tp, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.clock.cast}, \tcode{time_point} conversions - template - struct clock_time_conversion; - - template - auto clock_cast(const time_point& t); - - // \ref{time.cal.last}, class \tcode{last_spec} - struct last_spec; - - // \ref{time.cal.day}, class \tcode{day} - class day; - - constexpr bool operator==(const day& x, const day& y) noexcept; - constexpr strong_ordering operator<=>(const day& x, const day& y) noexcept; - - constexpr day operator+(const day& x, const days& y) noexcept; - constexpr day operator+(const days& x, const day& y) noexcept; - constexpr day operator-(const day& x, const days& y) noexcept; - constexpr days operator-(const day& x, const day& y) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const day& d); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - day& d, basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.cal.month}, class \tcode{month} - class month; - - constexpr bool operator==(const month& x, const month& y) noexcept; - constexpr strong_ordering operator<=>(const month& x, const month& y) noexcept; - - constexpr month operator+(const month& x, const months& y) noexcept; - constexpr month operator+(const months& x, const month& y) noexcept; - constexpr month operator-(const month& x, const months& y) noexcept; - constexpr months operator-(const month& x, const month& y) noexcept; + struct leap_second_info; - template - basic_ostream& - operator<<(basic_ostream& os, const month& m); - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - month& m, basic_string* abbrev = nullptr, - minutes* offset = nullptr); + template + leap_second_info get_leap_second_info(const utc_time& ut); - // \ref{time.cal.year}, class \tcode{year} - class year; + // \ref{time.clock.tai}, class \tcode{tai_clock} + class tai_clock; - constexpr bool operator==(const year& x, const year& y) noexcept; - constexpr strong_ordering operator<=>(const year& x, const year& y) noexcept; + template + using tai_time = time_point; + using tai_seconds = tai_time; + + template + basic_ostream& + operator<<(basic_ostream& os, const tai_time& t); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + tai_time& tp, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.clock.gps}, class \tcode{gps_clock} + class gps_clock; - constexpr year operator+(const year& x, const years& y) noexcept; - constexpr year operator+(const years& x, const year& y) noexcept; - constexpr year operator-(const year& x, const years& y) noexcept; - constexpr years operator-(const year& x, const year& y) noexcept; + template + using gps_time = time_point; + using gps_seconds = gps_time; + + template + basic_ostream& + operator<<(basic_ostream& os, const gps_time& t); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + gps_time& tp, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.clock.file}, type \tcode{file_clock} + using file_clock = @\seebelow@; - template - basic_ostream& - operator<<(basic_ostream& os, const year& y); + template + using file_time = time_point; + + template + basic_ostream& + operator<<(basic_ostream& os, const file_time& tp); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + file_time& tp, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.clock.steady}, class \tcode{steady_clock} + class steady_clock; + + // \ref{time.clock.hires}, class \tcode{high_resolution_clock} + class high_resolution_clock; + + // \ref{time.clock.local}, local time + struct local_t {}; + template + using local_time = time_point; + using local_seconds = local_time; + using local_days = local_time; + + template + basic_ostream& + operator<<(basic_ostream& os, const local_time& tp); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + local_time& tp, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.clock.cast}, \tcode{time_point} conversions + template + struct clock_time_conversion; - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - year& y, basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.cal.wd}, class \tcode{weekday} - class weekday; - - constexpr bool operator==(const weekday& x, const weekday& y) noexcept; - - constexpr weekday operator+(const weekday& x, const days& y) noexcept; - constexpr weekday operator+(const days& x, const weekday& y) noexcept; - constexpr weekday operator-(const weekday& x, const days& y) noexcept; - constexpr days operator-(const weekday& x, const weekday& y) noexcept; + template + auto clock_cast(const time_point& t); - template - basic_ostream& - operator<<(basic_ostream& os, const weekday& wd); + // \ref{time.cal.last}, class \tcode{last_spec} + struct last_spec; - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - weekday& wd, basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.cal.wdidx}, class \tcode{weekday_indexed} - class weekday_indexed; - - constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept; + // \ref{time.cal.day}, class \tcode{day} + class day; - template - basic_ostream& - operator<<(basic_ostream& os, const weekday_indexed& wdi); + constexpr bool operator==(const day& x, const day& y) noexcept; + constexpr strong_ordering operator<=>(const day& x, const day& y) noexcept; - // \ref{time.cal.wdlast}, class \tcode{weekday_last} - class weekday_last; + constexpr day operator+(const day& x, const days& y) noexcept; + constexpr day operator+(const days& x, const day& y) noexcept; + constexpr day operator-(const day& x, const days& y) noexcept; + constexpr days operator-(const day& x, const day& y) noexcept; - constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const weekday_last& wdl); - - // \ref{time.cal.md}, class \tcode{month_day} - class month_day; - - constexpr bool operator==(const month_day& x, const month_day& y) noexcept; - constexpr strong_ordering operator<=>(const month_day& x, const month_day& y) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const month_day& md); - - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - month_day& md, basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.cal.mdlast}, class \tcode{month_day_last} - class month_day_last; - - constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept; - constexpr strong_ordering operator<=>(const month_day_last& x, - const month_day_last& y) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const month_day_last& mdl); - - // \ref{time.cal.mwd}, class \tcode{month_weekday} - class month_weekday; - - constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const month_weekday& mwd); - - // \ref{time.cal.mwdlast}, class \tcode{month_weekday_last} - class month_weekday_last; - - constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const month_weekday_last& mwdl); - - // \ref{time.cal.ym}, class \tcode{year_month} - class year_month; - - constexpr bool operator==(const year_month& x, const year_month& y) noexcept; - constexpr strong_ordering operator<=>(const year_month& x, const year_month& y) noexcept; - - constexpr year_month operator+(const year_month& ym, const months& dm) noexcept; - constexpr year_month operator+(const months& dm, const year_month& ym) noexcept; - constexpr year_month operator-(const year_month& ym, const months& dm) noexcept; - constexpr months operator-(const year_month& x, const year_month& y) noexcept; - constexpr year_month operator+(const year_month& ym, const years& dy) noexcept; - constexpr year_month operator+(const years& dy, const year_month& ym) noexcept; - constexpr year_month operator-(const year_month& ym, const years& dy) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const year_month& ym); - - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - year_month& ym, basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.cal.ymd}, class \tcode{year_month_day} - class year_month_day; - - constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept; - constexpr strong_ordering operator<=>(const year_month_day& x, - const year_month_day& y) noexcept; - - constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept; - constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept; - constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept; - constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) noexcept; - constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept; - constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const year_month_day& ymd); - - template> - basic_istream& - from_stream(basic_istream& is, const charT* fmt, - year_month_day& ymd, - basic_string* abbrev = nullptr, - minutes* offset = nullptr); - - // \ref{time.cal.ymdlast}, class \tcode{year_month_day_last} - class year_month_day_last; - - constexpr bool operator==(const year_month_day_last& x, - const year_month_day_last& y) noexcept; - constexpr strong_ordering operator<=>(const year_month_day_last& x, - const year_month_day_last& y) noexcept; - - constexpr year_month_day_last - operator+(const year_month_day_last& ymdl, const months& dm) noexcept; - constexpr year_month_day_last - operator+(const months& dm, const year_month_day_last& ymdl) noexcept; - constexpr year_month_day_last - operator+(const year_month_day_last& ymdl, const years& dy) noexcept; - constexpr year_month_day_last - operator+(const years& dy, const year_month_day_last& ymdl) noexcept; - constexpr year_month_day_last - operator-(const year_month_day_last& ymdl, const months& dm) noexcept; - constexpr year_month_day_last - operator-(const year_month_day_last& ymdl, const years& dy) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const year_month_day_last& ymdl); - - // \ref{time.cal.ymwd}, class \tcode{year_month_weekday} - class year_month_weekday; - - constexpr bool operator==(const year_month_weekday& x, - const year_month_weekday& y) noexcept; - - constexpr year_month_weekday - operator+(const year_month_weekday& ymwd, const months& dm) noexcept; - constexpr year_month_weekday - operator+(const months& dm, const year_month_weekday& ymwd) noexcept; - constexpr year_month_weekday - operator+(const year_month_weekday& ymwd, const years& dy) noexcept; - constexpr year_month_weekday - operator+(const years& dy, const year_month_weekday& ymwd) noexcept; - constexpr year_month_weekday - operator-(const year_month_weekday& ymwd, const months& dm) noexcept; - constexpr year_month_weekday - operator-(const year_month_weekday& ymwd, const years& dy) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const year_month_weekday& ymwdi); - - // \ref{time.cal.ymwdlast}, class \tcode{year_month_weekday_last} - class year_month_weekday_last; - - constexpr bool operator==(const year_month_weekday_last& x, - const year_month_weekday_last& y) noexcept; - - constexpr year_month_weekday_last - operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept; - constexpr year_month_weekday_last - operator+(const months& dm, const year_month_weekday_last& ymwdl) noexcept; - constexpr year_month_weekday_last - operator+(const year_month_weekday_last& ymwdl, const years& dy) noexcept; - constexpr year_month_weekday_last - operator+(const years& dy, const year_month_weekday_last& ymwdl) noexcept; - constexpr year_month_weekday_last - operator-(const year_month_weekday_last& ymwdl, const months& dm) noexcept; - constexpr year_month_weekday_last - operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept; - - template - basic_ostream& - operator<<(basic_ostream& os, const year_month_weekday_last& ymwdl); - - // \ref{time.cal.operators}, civil calendar conventional syntax operators - constexpr year_month - operator/(const year& y, const month& m) noexcept; - constexpr year_month - operator/(const year& y, int m) noexcept; - constexpr month_day - operator/(const month& m, const day& d) noexcept; - constexpr month_day - operator/(const month& m, int d) noexcept; - constexpr month_day - operator/(int m, const day& d) noexcept; - constexpr month_day - operator/(const day& d, const month& m) noexcept; - constexpr month_day - operator/(const day& d, int m) noexcept; - constexpr month_day_last - operator/(const month& m, last_spec) noexcept; - constexpr month_day_last - operator/(int m, last_spec) noexcept; - constexpr month_day_last - operator/(last_spec, const month& m) noexcept; - constexpr month_day_last - operator/(last_spec, int m) noexcept; - constexpr month_weekday - operator/(const month& m, const weekday_indexed& wdi) noexcept; - constexpr month_weekday - operator/(int m, const weekday_indexed& wdi) noexcept; - constexpr month_weekday - operator/(const weekday_indexed& wdi, const month& m) noexcept; - constexpr month_weekday - operator/(const weekday_indexed& wdi, int m) noexcept; - constexpr month_weekday_last - operator/(const month& m, const weekday_last& wdl) noexcept; - constexpr month_weekday_last - operator/(int m, const weekday_last& wdl) noexcept; - constexpr month_weekday_last - operator/(const weekday_last& wdl, const month& m) noexcept; - constexpr month_weekday_last - operator/(const weekday_last& wdl, int m) noexcept; - constexpr year_month_day - operator/(const year_month& ym, const day& d) noexcept; - constexpr year_month_day - operator/(const year_month& ym, int d) noexcept; - constexpr year_month_day - operator/(const year& y, const month_day& md) noexcept; - constexpr year_month_day - operator/(int y, const month_day& md) noexcept; - constexpr year_month_day - operator/(const month_day& md, const year& y) noexcept; - constexpr year_month_day - operator/(const month_day& md, int y) noexcept; - constexpr year_month_day_last - operator/(const year_month& ym, last_spec) noexcept; - constexpr year_month_day_last - operator/(const year& y, const month_day_last& mdl) noexcept; - constexpr year_month_day_last - operator/(int y, const month_day_last& mdl) noexcept; - constexpr year_month_day_last - operator/(const month_day_last& mdl, const year& y) noexcept; - constexpr year_month_day_last - operator/(const month_day_last& mdl, int y) noexcept; - constexpr year_month_weekday - operator/(const year_month& ym, const weekday_indexed& wdi) noexcept; - constexpr year_month_weekday - operator/(const year& y, const month_weekday& mwd) noexcept; - constexpr year_month_weekday - operator/(int y, const month_weekday& mwd) noexcept; - constexpr year_month_weekday - operator/(const month_weekday& mwd, const year& y) noexcept; - constexpr year_month_weekday - operator/(const month_weekday& mwd, int y) noexcept; - constexpr year_month_weekday_last - operator/(const year_month& ym, const weekday_last& wdl) noexcept; - constexpr year_month_weekday_last - operator/(const year& y, const month_weekday_last& mwdl) noexcept; - constexpr year_month_weekday_last - operator/(int y, const month_weekday_last& mwdl) noexcept; - constexpr year_month_weekday_last - operator/(const month_weekday_last& mwdl, const year& y) noexcept; - constexpr year_month_weekday_last - operator/(const month_weekday_last& mwdl, int y) noexcept; - - // \ref{time.hms}, class template \tcode{hh_mm_ss} - template class hh_mm_ss; - - template - basic_ostream& - operator<<(basic_ostream& os, const hh_mm_ss& hms); - - // \ref{time.12}, 12/24 hour functions - constexpr bool is_am(const hours& h) noexcept; - constexpr bool is_pm(const hours& h) noexcept; - constexpr hours make12(const hours& h) noexcept; - constexpr hours make24(const hours& h, bool is_pm) noexcept; - - // \ref{time.zone.db}, time zone database - struct tzdb; - class tzdb_list; - - // \ref{time.zone.db.access}, time zone database access - const tzdb& get_tzdb(); - tzdb_list& get_tzdb_list(); - const time_zone* locate_zone(string_view tz_name); - const time_zone* current_zone(); - - // \ref{time.zone.db.remote}, remote time zone database support - const tzdb& reload_tzdb(); - string remote_version(); - - // \ref{time.zone.exception}, exception classes - class nonexistent_local_time; - class ambiguous_local_time; - - // \ref{time.zone.info}, information classes - struct sys_info; - template - basic_ostream& - operator<<(basic_ostream& os, const sys_info& si); - - struct local_info; - template - basic_ostream& - operator<<(basic_ostream& os, const local_info& li); - - // \ref{time.zone.timezone}, class \tcode{time_zone} - enum class choose {earliest, latest}; - class time_zone; - - bool operator==(const time_zone& x, const time_zone& y) noexcept; - strong_ordering operator<=>(const time_zone& x, const time_zone& y) noexcept; - - // \ref{time.zone.zonedtraits}, class template \tcode{zoned_traits} - template struct zoned_traits; - - // \ref{time.zone.zonedtime}, class template \tcode{zoned_time} - template class zoned_time; - - using zoned_seconds = zoned_time; - - template - bool operator==(const zoned_time& x, - const zoned_time& y); - - template - basic_ostream& - operator<<(basic_ostream& os, - const zoned_time& t); - - // \ref{time.zone.leap}, leap second support - class leap_second; - - constexpr bool operator==(const leap_second& x, const leap_second& y); - constexpr strong_ordering operator<=>(const leap_second& x, const leap_second& y); + template + basic_ostream& + operator<<(basic_ostream& os, const day& d); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + day& d, basic_string* abbrev = nullptr, + minutes* offset = nullptr); - template - constexpr bool operator==(const leap_second& x, const sys_time& y); - template - constexpr bool operator< (const leap_second& x, const sys_time& y); - template - constexpr bool operator< (const sys_time& x, const leap_second& y); - template - constexpr bool operator> (const leap_second& x, const sys_time& y); - template - constexpr bool operator> (const sys_time& x, const leap_second& y); - template - constexpr bool operator<=(const leap_second& x, const sys_time& y); - template - constexpr bool operator<=(const sys_time& x, const leap_second& y); - template - constexpr bool operator>=(const leap_second& x, const sys_time& y); - template - constexpr bool operator>=(const sys_time& x, const leap_second& y); - template - requires @\libconcept{three_way_comparable_with}@> - constexpr auto operator<=>(const leap_second& x, const sys_time& y); + // \ref{time.cal.month}, class \tcode{month} + class month; - // \ref{time.zone.link}, class \tcode{time_zone_link} - class time_zone_link; + constexpr bool operator==(const month& x, const month& y) noexcept; + constexpr strong_ordering operator<=>(const month& x, const month& y) noexcept; - bool operator==(const time_zone_link& x, const time_zone_link& y); - strong_ordering operator<=>(const time_zone_link& x, const time_zone_link& y); + constexpr month operator+(const month& x, const months& y) noexcept; + constexpr month operator+(const months& x, const month& y) noexcept; + constexpr month operator-(const month& x, const months& y) noexcept; + constexpr months operator-(const month& x, const month& y) noexcept; - // \ref{time.format}, formatting - template struct @\placeholder{local-time-format-t}@; // \expos - template - @\placeholder{local-time-format-t}@ - local_time_format(local_time time, const string* abbrev = nullptr, - const seconds* offset_sec = nullptr); - } + template + basic_ostream& + operator<<(basic_ostream& os, const month& m); + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + month& m, basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.cal.year}, class \tcode{year} + class year; + + constexpr bool operator==(const year& x, const year& y) noexcept; + constexpr strong_ordering operator<=>(const year& x, const year& y) noexcept; + + constexpr year operator+(const year& x, const years& y) noexcept; + constexpr year operator+(const years& x, const year& y) noexcept; + constexpr year operator-(const year& x, const years& y) noexcept; + constexpr years operator-(const year& x, const year& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const year& y); + + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + year& y, basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.cal.wd}, class \tcode{weekday} + class weekday; + + constexpr bool operator==(const weekday& x, const weekday& y) noexcept; + + constexpr weekday operator+(const weekday& x, const days& y) noexcept; + constexpr weekday operator+(const days& x, const weekday& y) noexcept; + constexpr weekday operator-(const weekday& x, const days& y) noexcept; + constexpr days operator-(const weekday& x, const weekday& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const weekday& wd); + + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + weekday& wd, basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.cal.wdidx}, class \tcode{weekday_indexed} + class weekday_indexed; + + constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const weekday_indexed& wdi); + + // \ref{time.cal.wdlast}, class \tcode{weekday_last} + class weekday_last; + + constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const weekday_last& wdl); + + // \ref{time.cal.md}, class \tcode{month_day} + class month_day; + + constexpr bool operator==(const month_day& x, const month_day& y) noexcept; + constexpr strong_ordering operator<=>(const month_day& x, const month_day& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const month_day& md); + + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + month_day& md, basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.cal.mdlast}, class \tcode{month_day_last} + class month_day_last; + + constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept; + constexpr strong_ordering operator<=>(const month_day_last& x, + const month_day_last& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const month_day_last& mdl); + + // \ref{time.cal.mwd}, class \tcode{month_weekday} + class month_weekday; + + constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const month_weekday& mwd); + + // \ref{time.cal.mwdlast}, class \tcode{month_weekday_last} + class month_weekday_last; + + constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const month_weekday_last& mwdl); + + // \ref{time.cal.ym}, class \tcode{year_month} + class year_month; + + constexpr bool operator==(const year_month& x, const year_month& y) noexcept; + constexpr strong_ordering operator<=>(const year_month& x, const year_month& y) noexcept; + + constexpr year_month operator+(const year_month& ym, const months& dm) noexcept; + constexpr year_month operator+(const months& dm, const year_month& ym) noexcept; + constexpr year_month operator-(const year_month& ym, const months& dm) noexcept; + constexpr months operator-(const year_month& x, const year_month& y) noexcept; + constexpr year_month operator+(const year_month& ym, const years& dy) noexcept; + constexpr year_month operator+(const years& dy, const year_month& ym) noexcept; + constexpr year_month operator-(const year_month& ym, const years& dy) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const year_month& ym); + + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + year_month& ym, basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.cal.ymd}, class \tcode{year_month_day} + class year_month_day; + + constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept; + constexpr strong_ordering operator<=>(const year_month_day& x, + const year_month_day& y) noexcept; + + constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept; + constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept; + constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept; + constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) noexcept; + constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept; + constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const year_month_day& ymd); + + template> + basic_istream& + from_stream(basic_istream& is, const charT* fmt, + year_month_day& ymd, + basic_string* abbrev = nullptr, + minutes* offset = nullptr); + + // \ref{time.cal.ymdlast}, class \tcode{year_month_day_last} + class year_month_day_last; + + constexpr bool operator==(const year_month_day_last& x, + const year_month_day_last& y) noexcept; + constexpr strong_ordering operator<=>(const year_month_day_last& x, + const year_month_day_last& y) noexcept; + + constexpr year_month_day_last + operator+(const year_month_day_last& ymdl, const months& dm) noexcept; + constexpr year_month_day_last + operator+(const months& dm, const year_month_day_last& ymdl) noexcept; + constexpr year_month_day_last + operator+(const year_month_day_last& ymdl, const years& dy) noexcept; + constexpr year_month_day_last + operator+(const years& dy, const year_month_day_last& ymdl) noexcept; + constexpr year_month_day_last + operator-(const year_month_day_last& ymdl, const months& dm) noexcept; + constexpr year_month_day_last + operator-(const year_month_day_last& ymdl, const years& dy) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const year_month_day_last& ymdl); + + // \ref{time.cal.ymwd}, class \tcode{year_month_weekday} + class year_month_weekday; + + constexpr bool operator==(const year_month_weekday& x, + const year_month_weekday& y) noexcept; + + constexpr year_month_weekday + operator+(const year_month_weekday& ymwd, const months& dm) noexcept; + constexpr year_month_weekday + operator+(const months& dm, const year_month_weekday& ymwd) noexcept; + constexpr year_month_weekday + operator+(const year_month_weekday& ymwd, const years& dy) noexcept; + constexpr year_month_weekday + operator+(const years& dy, const year_month_weekday& ymwd) noexcept; + constexpr year_month_weekday + operator-(const year_month_weekday& ymwd, const months& dm) noexcept; + constexpr year_month_weekday + operator-(const year_month_weekday& ymwd, const years& dy) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const year_month_weekday& ymwdi); + + // \ref{time.cal.ymwdlast}, class \tcode{year_month_weekday_last} + class year_month_weekday_last; + + constexpr bool operator==(const year_month_weekday_last& x, + const year_month_weekday_last& y) noexcept; + + constexpr year_month_weekday_last + operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept; + constexpr year_month_weekday_last + operator+(const months& dm, const year_month_weekday_last& ymwdl) noexcept; + constexpr year_month_weekday_last + operator+(const year_month_weekday_last& ymwdl, const years& dy) noexcept; + constexpr year_month_weekday_last + operator+(const years& dy, const year_month_weekday_last& ymwdl) noexcept; + constexpr year_month_weekday_last + operator-(const year_month_weekday_last& ymwdl, const months& dm) noexcept; + constexpr year_month_weekday_last + operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept; + + template + basic_ostream& + operator<<(basic_ostream& os, const year_month_weekday_last& ymwdl); + + // \ref{time.cal.operators}, civil calendar conventional syntax operators + constexpr year_month + operator/(const year& y, const month& m) noexcept; + constexpr year_month + operator/(const year& y, int m) noexcept; + constexpr month_day + operator/(const month& m, const day& d) noexcept; + constexpr month_day + operator/(const month& m, int d) noexcept; + constexpr month_day + operator/(int m, const day& d) noexcept; + constexpr month_day + operator/(const day& d, const month& m) noexcept; + constexpr month_day + operator/(const day& d, int m) noexcept; + constexpr month_day_last + operator/(const month& m, last_spec) noexcept; + constexpr month_day_last + operator/(int m, last_spec) noexcept; + constexpr month_day_last + operator/(last_spec, const month& m) noexcept; + constexpr month_day_last + operator/(last_spec, int m) noexcept; + constexpr month_weekday + operator/(const month& m, const weekday_indexed& wdi) noexcept; + constexpr month_weekday + operator/(int m, const weekday_indexed& wdi) noexcept; + constexpr month_weekday + operator/(const weekday_indexed& wdi, const month& m) noexcept; + constexpr month_weekday + operator/(const weekday_indexed& wdi, int m) noexcept; + constexpr month_weekday_last + operator/(const month& m, const weekday_last& wdl) noexcept; + constexpr month_weekday_last + operator/(int m, const weekday_last& wdl) noexcept; + constexpr month_weekday_last + operator/(const weekday_last& wdl, const month& m) noexcept; + constexpr month_weekday_last + operator/(const weekday_last& wdl, int m) noexcept; + constexpr year_month_day + operator/(const year_month& ym, const day& d) noexcept; + constexpr year_month_day + operator/(const year_month& ym, int d) noexcept; + constexpr year_month_day + operator/(const year& y, const month_day& md) noexcept; + constexpr year_month_day + operator/(int y, const month_day& md) noexcept; + constexpr year_month_day + operator/(const month_day& md, const year& y) noexcept; + constexpr year_month_day + operator/(const month_day& md, int y) noexcept; + constexpr year_month_day_last + operator/(const year_month& ym, last_spec) noexcept; + constexpr year_month_day_last + operator/(const year& y, const month_day_last& mdl) noexcept; + constexpr year_month_day_last + operator/(int y, const month_day_last& mdl) noexcept; + constexpr year_month_day_last + operator/(const month_day_last& mdl, const year& y) noexcept; + constexpr year_month_day_last + operator/(const month_day_last& mdl, int y) noexcept; + constexpr year_month_weekday + operator/(const year_month& ym, const weekday_indexed& wdi) noexcept; + constexpr year_month_weekday + operator/(const year& y, const month_weekday& mwd) noexcept; + constexpr year_month_weekday + operator/(int y, const month_weekday& mwd) noexcept; + constexpr year_month_weekday + operator/(const month_weekday& mwd, const year& y) noexcept; + constexpr year_month_weekday + operator/(const month_weekday& mwd, int y) noexcept; + constexpr year_month_weekday_last + operator/(const year_month& ym, const weekday_last& wdl) noexcept; + constexpr year_month_weekday_last + operator/(const year& y, const month_weekday_last& mwdl) noexcept; + constexpr year_month_weekday_last + operator/(int y, const month_weekday_last& mwdl) noexcept; + constexpr year_month_weekday_last + operator/(const month_weekday_last& mwdl, const year& y) noexcept; + constexpr year_month_weekday_last + operator/(const month_weekday_last& mwdl, int y) noexcept; + + // \ref{time.hms}, class template \tcode{hh_mm_ss} + template class hh_mm_ss; + + template + basic_ostream& + operator<<(basic_ostream& os, const hh_mm_ss& hms); + + // \ref{time.12}, 12/24 hour functions + constexpr bool is_am(const hours& h) noexcept; + constexpr bool is_pm(const hours& h) noexcept; + constexpr hours make12(const hours& h) noexcept; + constexpr hours make24(const hours& h, bool is_pm) noexcept; + + // \ref{time.zone.db}, time zone database + struct tzdb; + class tzdb_list; + + // \ref{time.zone.db.access}, time zone database access + const tzdb& get_tzdb(); + tzdb_list& get_tzdb_list(); + const time_zone* locate_zone(string_view tz_name); + const time_zone* current_zone(); + + // \ref{time.zone.db.remote}, remote time zone database support + const tzdb& reload_tzdb(); + string remote_version(); + + // \ref{time.zone.exception}, exception classes + class nonexistent_local_time; + class ambiguous_local_time; + + // \ref{time.zone.info}, information classes + struct sys_info; + template + basic_ostream& + operator<<(basic_ostream& os, const sys_info& si); + + struct local_info; + template + basic_ostream& + operator<<(basic_ostream& os, const local_info& li); + + // \ref{time.zone.timezone}, class \tcode{time_zone} + enum class choose {earliest, latest}; + class time_zone; + + bool operator==(const time_zone& x, const time_zone& y) noexcept; + strong_ordering operator<=>(const time_zone& x, const time_zone& y) noexcept; + + // \ref{time.zone.zonedtraits}, class template \tcode{zoned_traits} + template struct zoned_traits; + + // \ref{time.zone.zonedtime}, class template \tcode{zoned_time} + template class zoned_time; + + using zoned_seconds = zoned_time; + + template + bool operator==(const zoned_time& x, + const zoned_time& y); + + template + basic_ostream& + operator<<(basic_ostream& os, + const zoned_time& t); + + // \ref{time.zone.leap}, leap second support + class leap_second; + + constexpr bool operator==(const leap_second& x, const leap_second& y); + constexpr strong_ordering operator<=>(const leap_second& x, const leap_second& y); + + template + constexpr bool operator==(const leap_second& x, const sys_time& y); + template + constexpr bool operator< (const leap_second& x, const sys_time& y); + template + constexpr bool operator< (const sys_time& x, const leap_second& y); + template + constexpr bool operator> (const leap_second& x, const sys_time& y); + template + constexpr bool operator> (const sys_time& x, const leap_second& y); + template + constexpr bool operator<=(const leap_second& x, const sys_time& y); + template + constexpr bool operator<=(const sys_time& x, const leap_second& y); + template + constexpr bool operator>=(const leap_second& x, const sys_time& y); + template + constexpr bool operator>=(const sys_time& x, const leap_second& y); + template + requires @\libconcept{three_way_comparable_with}@> + constexpr auto operator<=>(const leap_second& x, const sys_time& y); + + // \ref{time.zone.link}, class \tcode{time_zone_link} + class time_zone_link; + bool operator==(const time_zone_link& x, const time_zone_link& y); + strong_ordering operator<=>(const time_zone_link& x, const time_zone_link& y); + + // \ref{time.format}, formatting + template struct @\placeholder{local-time-format-t}@; // \expos + template + @\placeholder{local-time-format-t}@ + local_time_format(local_time time, const string* abbrev = nullptr, + const seconds* offset_sec = nullptr); +} + +namespace std { template struct formatter, charT>; template @@ -848,99 +850,97 @@ template struct formatter; template struct formatter, charT>; +} - namespace chrono { - // \ref{time.parse}, parsing - template - @\unspec@ - parse(const charT* fmt, Parsable& tp); - template - @\unspec@ - parse(const basic_string& fmt, Parsable& tp); - - template - @\unspec@ - parse(const charT* fmt, Parsable& tp, - basic_string& abbrev); - template - @\unspec@ - parse(const basic_string& fmt, Parsable& tp, - basic_string& abbrev); - - template - @\unspec@ - parse(const charT* fmt, Parsable& tp, minutes& offset); - template - @\unspec@ - parse(const basic_string& fmt, Parsable& tp, - minutes& offset); - - template - @\unspec@ - parse(const charT* fmt, Parsable& tp, - basic_string& abbrev, minutes& offset); - template - @\unspec@ - parse(const basic_string& fmt, Parsable& tp, - basic_string& abbrev, minutes& offset); - - // calendrical constants - inline constexpr last_spec last{}; - - inline constexpr weekday Sunday{0}; - inline constexpr weekday Monday{1}; - inline constexpr weekday Tuesday{2}; - inline constexpr weekday Wednesday{3}; - inline constexpr weekday Thursday{4}; - inline constexpr weekday Friday{5}; - inline constexpr weekday Saturday{6}; - - inline constexpr month January{1}; - inline constexpr month February{2}; - inline constexpr month March{3}; - inline constexpr month April{4}; - inline constexpr month May{5}; - inline constexpr month June{6}; - inline constexpr month July{7}; - inline constexpr month August{8}; - inline constexpr month September{9}; - inline constexpr month October{10}; - inline constexpr month November{11}; - inline constexpr month December{12}; - } +namespace std::chrono { + // \ref{time.parse}, parsing + template + @\unspec@ + parse(const charT* fmt, Parsable& tp); + template + @\unspec@ + parse(const basic_string& fmt, Parsable& tp); + + template + @\unspec@ + parse(const charT* fmt, Parsable& tp, + basic_string& abbrev); + template + @\unspec@ + parse(const basic_string& fmt, Parsable& tp, + basic_string& abbrev); + + template + @\unspec@ + parse(const charT* fmt, Parsable& tp, minutes& offset); + template + @\unspec@ + parse(const basic_string& fmt, Parsable& tp, + minutes& offset); + + template + @\unspec@ + parse(const charT* fmt, Parsable& tp, + basic_string& abbrev, minutes& offset); + template + @\unspec@ + parse(const basic_string& fmt, Parsable& tp, + basic_string& abbrev, minutes& offset); + + // calendrical constants + inline constexpr last_spec last{}; + + inline constexpr weekday Sunday{0}; + inline constexpr weekday Monday{1}; + inline constexpr weekday Tuesday{2}; + inline constexpr weekday Wednesday{3}; + inline constexpr weekday Thursday{4}; + inline constexpr weekday Friday{5}; + inline constexpr weekday Saturday{6}; + + inline constexpr month January{1}; + inline constexpr month February{2}; + inline constexpr month March{3}; + inline constexpr month April{4}; + inline constexpr month May{5}; + inline constexpr month June{6}; + inline constexpr month July{7}; + inline constexpr month August{8}; + inline constexpr month September{9}; + inline constexpr month October{10}; + inline constexpr month November{11}; + inline constexpr month December{12}; +} - inline namespace literals { - inline namespace chrono_literals { - // \ref{time.duration.literals}, suffixes for duration literals - constexpr chrono::hours operator""h(unsigned long long); - constexpr chrono::duration<@\unspec,@ ratio<3600, 1>> operator""h(long double); +namespace std::inline literals::inline chrono_literals { + // \ref{time.duration.literals}, suffixes for duration literals + constexpr chrono::hours operator""h(unsigned long long); + constexpr chrono::duration<@\unspec,@ ratio<3600, 1>> operator""h(long double); - constexpr chrono::minutes operator""min(unsigned long long); - constexpr chrono::duration<@\unspec,@ ratio<60, 1>> operator""min(long double); + constexpr chrono::minutes operator""min(unsigned long long); + constexpr chrono::duration<@\unspec,@ ratio<60, 1>> operator""min(long double); - constexpr chrono::seconds operator""s(unsigned long long); - constexpr chrono::duration<@\unspec@>@\itcorr[-1]@ operator""s(long double); + constexpr chrono::seconds operator""s(unsigned long long); + constexpr chrono::duration<@\unspec@>@\itcorr[-1]@ operator""s(long double); - constexpr chrono::milliseconds operator""ms(unsigned long long); - constexpr chrono::duration<@\unspec,@ milli> operator""ms(long double); + constexpr chrono::milliseconds operator""ms(unsigned long long); + constexpr chrono::duration<@\unspec,@ milli> operator""ms(long double); - constexpr chrono::microseconds operator""us(unsigned long long); - constexpr chrono::duration<@\unspec,@ micro> operator""us(long double); + constexpr chrono::microseconds operator""us(unsigned long long); + constexpr chrono::duration<@\unspec,@ micro> operator""us(long double); - constexpr chrono::nanoseconds operator""ns(unsigned long long); - constexpr chrono::duration<@\unspec,@ nano> operator""ns(long double); + constexpr chrono::nanoseconds operator""ns(unsigned long long); + constexpr chrono::duration<@\unspec,@ nano> operator""ns(long double); - // \ref{time.cal.day.nonmembers}, non-member functions - constexpr chrono::day operator""d(unsigned long long d) noexcept; + // \ref{time.cal.day.nonmembers}, non-member functions + constexpr chrono::day operator""d(unsigned long long d) noexcept; - // \ref{time.cal.year.nonmembers}, non-member functions - constexpr chrono::year operator""y(unsigned long long y) noexcept; - } - } + // \ref{time.cal.year.nonmembers}, non-member functions + constexpr chrono::year operator""y(unsigned long long y) noexcept; +} - namespace chrono { - using namespace literals::chrono_literals; - } +namespace std::chrono { + using namespace literals::chrono_literals; } \end{codeblock} From b6acc23582ee13667188d6af91e04a2f37a0d306 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 5 Jan 2021 08:51:08 +0100 Subject: [PATCH 050/182] [container.requirements] Improve indexing of members described in requirements --- source/containers.tex | 94 +++++++++++++++++++++++++++++++++++++++++++ source/macros.tex | 10 +++-- 2 files changed, 100 insertions(+), 4 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index 532888a1d8..745ec943ad 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -88,6 +88,24 @@ \tcode{rv} denotes a non-const rvalue of type \tcode{X}. \end{itemize} +% Local command to index names as members of all containers. +\newcommand{\indexcont}[1]{% +\indexlibrarymisc{#1}{containers}% +\indexlibrarymemberx{array}{#1}% +\indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{forward_list}{#1}% +\indexlibrarymemberx{list}{#1}% +\indexlibrarymemberx{vector}{#1}% +\indexlibrarymemberx{map}{#1}% +\indexlibrarymemberx{set}{#1}% +\indexlibrarymemberx{multiset}{#1}% +\indexlibrarymemberx{multimap}{#1}% +\indexlibrarymemberx{unordered_map}{#1}% +\indexlibrarymemberx{unordered_set}{#1}% +\indexlibrarymemberx{unordered_multiset}{#1}% +\indexlibrarymemberx{unordered_multimap}{#1}% +} + \begin{libreqtab5} {Container requirements} {container.req} @@ -103,24 +121,28 @@ & & \chdr{semantics} & \chdr{pre-/post-condition} & \\ \capsep \endhead +\indexcont{value_type}% \tcode{X::value_type} & \tcode{T} & & \expects \tcode{T} is \oldconcept{Erasable} from \tcode{X} (see~\ref{container.requirements.general}, below) & compile time \\ \rowsep +\indexcont{reference}% \tcode{X::reference} & \tcode{T\&} & & & compile time \\ \rowsep +\indexcont{const_reference}% \tcode{X::const_reference} & \tcode{const T\&} & & & compile time \\ \rowsep +\indexcont{iterator}% \tcode{X::iterator} & iterator type whose value type is \tcode{T} & & @@ -129,6 +151,7 @@ convertible to \tcode{X::const_iterator}. & compile time \\ \rowsep +\indexcont{const_iterator}% \tcode{X::const_iterator} & constant iterator type whose value type is \tcode{T} & & @@ -136,12 +159,14 @@ that meets the forward iterator requirements. & compile time \\ \rowsep +\indexcont{difference_type}% \tcode{X::dif\-ference_type} & signed integer type & & is identical to the difference type of \tcode{X::iterator} and \tcode{X::const_iterator} & compile time \\ \rowsep +\indexcont{size_type}% \tcode{X::size_type} & unsigned integer type & & @@ -198,24 +223,28 @@ \effects destroys every element of \tcode{a}; any memory obtained is deallocated. & linear \\ \rowsep +\indexcont{begin}% \tcode{a.begin()} & \tcode{iterator}; \tcode{const_iterator} for constant \tcode{a} & & & constant \\ \rowsep +\indexcont{end}% \tcode{a.end()} & \tcode{iterator}; \tcode{const_iterator} for constant \tcode{a} & & & constant \\ \rowsep +\indexcont{cbegin}% \tcode{a.cbegin()} & \tcode{const_iterator} & \tcode{const_cast<\brk{}X const\&\brk{}>(a)\brk{}.begin();} & & constant \\ \rowsep +\indexcont{cend}% \tcode{a.cend()} & \tcode{const_iterator} & \tcode{const_cast<\brk{}X const\&\brk{}>(a)\brk{}.end();} & @@ -228,6 +257,7 @@ \constraints \tcode{X::iterator} meets the random access iterator requirements. & constant \\ \rowsep +\indexcont{operator==}% \tcode{a == b} & convertible to \tcode{bool} & \tcode{==} is an equivalence relation. @@ -236,12 +266,14 @@ Constant if \tcode{a.size() != b.size()}, linear otherwise \\ \rowsep +\indexcont{operator!=}% \tcode{a != b} & convertible to \tcode{bool} & Equivalent to \tcode{!(a == b)} & & linear \\ \rowsep +\indexcont{swap}% \tcode{a.swap(b)} & \keyword{void} & & @@ -254,18 +286,21 @@ & (Note A) \\ \rowsep +\indexcont{operator=}% \tcode{r = a} & \tcode{X\&} & & \ensures \tcode{r == a}. & linear \\ \rowsep +\indexcont{size}% \tcode{a.size()} & \tcode{size_type} & \tcode{distance(\brk{}a.begin(), a.end())} & & constant \\ \rowsep +\indexcont{max_size}% \tcode{a.max_size()} & \tcode{size_type} & \tcode{distance(\brk{}begin(), end())} @@ -273,6 +308,7 @@ & constant \\ \rowsep +\indexcont{empty}% \tcode{a.empty()} & convertible to \tcode{bool} & \tcode{a.begin() == a.end()} & @@ -387,6 +423,23 @@ and meets the additional requirements in \tref{container.rev.req}. +% Local command to index names as members of all containers. +\renewcommand{\indexcont}[1]{% +\indexlibrarymisc{#1}{reversible containers}% +\indexlibrarymemberx{array}{#1}% +\indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{list}{#1}% +\indexlibrarymemberx{vector}{#1}% +\indexlibrarymemberx{map}{#1}% +\indexlibrarymemberx{set}{#1}% +\indexlibrarymemberx{multiset}{#1}% +\indexlibrarymemberx{multimap}{#1}% +\indexlibrarymemberx{unordered_map}{#1}% +\indexlibrarymemberx{unordered_set}{#1}% +\indexlibrarymemberx{unordered_multiset}{#1}% +\indexlibrarymemberx{unordered_multimap}{#1}% +} + \begin{libreqtab4a} {Reversible container requirements} {container.rev.req} @@ -401,26 +454,32 @@ \chdr{Assertion/note} & \rhdr{Complexity} \\ & & \chdr{pre-/post-condition} & \\ \capsep \endhead +\indexcont{reverse_iterator}% \tcode{X::reverse_iterator} & iterator type whose value type is \tcode{T} & \tcode{reverse_iterator} & compile time \\ \rowsep +\indexcont{const_reverse_iterator}% \tcode{X::const_reverse_iterator} & constant iterator type whose value type is \tcode{T} & \tcode{reverse_iterator} & compile time \\ \rowsep +\indexcont{rbegin}% \tcode{a.rbegin()} & \tcode{reverse_iterator; const_reverse_iterator} for constant \tcode{a} & \tcode{reverse_iterator(end())} & constant \\ \rowsep +\indexcont{rend}% \tcode{a.rend()} & \tcode{reverse_iterator; const_reverse_iterator} for constant \tcode{a} & \tcode{reverse_iterator(begin())} & constant \\ \rowsep +\indexcont{crbegin}% \tcode{a.crbegin()} & \tcode{const_reverse_iterator} & \tcode{const_cast(a).rbegin()} & constant \\ \rowsep +\indexcont{crend}% \tcode{a.crend()} & \tcode{const_reverse_iterator} & \tcode{const_cast(a).rend()} & @@ -636,6 +695,23 @@ \tcode{m} is a value of type \tcode{A}. \end{itemize} +% Local command to index names as members of all containers. +\renewcommand{\indexcont}[1]{% +\indexlibrarymisc{#1}{allocator-aware containers}% +\indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{forward_list}{#1}% +\indexlibrarymemberx{list}{#1}% +\indexlibrarymemberx{vector}{#1}% +\indexlibrarymemberx{map}{#1}% +\indexlibrarymemberx{set}{#1}% +\indexlibrarymemberx{multiset}{#1}% +\indexlibrarymemberx{multimap}{#1}% +\indexlibrarymemberx{unordered_map}{#1}% +\indexlibrarymemberx{unordered_set}{#1}% +\indexlibrarymemberx{unordered_multiset}{#1}% +\indexlibrarymemberx{unordered_multimap}{#1}% +} + \begin{libreqtab4a} {Allocator-aware container requirements} {container.alloc.req} @@ -652,11 +728,13 @@ & & \chdr{pre-/post-condition} & \\ \capsep \endhead +\indexcont{allocator_type}% \tcode{allocator_type} & \tcode{A} & \mandates \tcode{allocator_type::value_type} is the same as \tcode{X::value_type}. & compile time \\ \rowsep +\indexcont{get_allocator}% \tcode{get_-} \tcode{allocator()} & \tcode{A} & & @@ -716,6 +794,7 @@ \ensures \tcode{a == t} & linear \\ \rowsep +\indexcont{operator=}% \tcode{a = rv} & \tcode{X\&} & \expects If \tcode{allocator_-}\br @@ -732,6 +811,7 @@ this assignment. & linear \\ \rowsep +\indexcont{swap}% \tcode{a.swap(b)} & \keyword{void} & \effects exchanges the contents of \tcode{a} and \tcode{b} & @@ -854,6 +934,15 @@ \pnum The complexities of the expressions are sequence dependent. +% Local command to index names as members of all containers. +\renewcommand{\indexcont}[1]{% +\indexlibrarymisc{#1}{sequence containers}% +\indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{forward_list}{#1}% +\indexlibrarymemberx{list}{#1}% +\indexlibrarymemberx{vector}{#1}% +} + \begin{libreqtab3} {Sequence container requirements (in addition to container)} {container.seq.req} @@ -901,6 +990,7 @@ \returns\ \tcode{*this}. \\ \rowsep +\indexcont{emplace}% \tcode{a.emplace(p, args)} & \tcode{iterator} & \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. For \tcode{vector} and \tcode{deque}, @@ -914,6 +1004,7 @@ \end{tailnote} \\ \rowsep +\indexcont{insert}% \tcode{a.insert(p,t)} & \tcode{iterator} & \expects \tcode{T} is @@ -949,6 +1040,7 @@ \tcode{iterator} & \tcode{a.insert(p, il.begin(), il.end())}. \\ \rowsep +\indexcont{erase}% \tcode{a.erase(q)} & \tcode{iterator} & \expects For \tcode{vector} and \tcode{deque}, @@ -961,6 +1053,7 @@ \tcode{T} is \oldconcept{MoveAssignable}.\br \effects\ Erases the elements in the range \tcode{[q1, q2)}. \\ \rowsep +\indexcont{clear}% \tcode{a.clear()} & \keyword{void} & \effects Destroys all elements in \tcode{a}. Invalidates all references, pointers, and @@ -968,6 +1061,7 @@ \ensures \tcode{a.empty()} is \tcode{true}.\br \complexity Linear. \\ \rowsep +\indexcont{assign}% \tcode{a.assign(i,j)} & \keyword{void} & \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i} diff --git a/source/macros.tex b/source/macros.tex index 40286c0842..41113e9cd6 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -188,13 +188,15 @@ \newcommand{\idxxname}[1]{__#1@\xname{#1}} % library index entries +\newcommand{\indexlibrarymisc}[2]{\indexlibrary{\idxcode{#1}!#2}} \newcommand{\indexlibraryglobal}[1]{\indexlibrary{\idxcode{#1}}} -\newcommand{\indexlibraryctor}[1]{\indexlibrary{\idxcode{#1}!constructor}} -\newcommand{\indexlibrarydtor}[1]{\indexlibrary{\idxcode{#1}!destructor}} +\newcommand{\indexlibraryctor}[1]{\indexlibrarymisc{#1}{constructor}} +\newcommand{\indexlibrarydtor}[1]{\indexlibrarymisc{#1}{destructor}} % class member library index -\newcommand{\indexlibrarymember}[2]{\indexlibrary{\idxcode{#1}!\idxcode{#2}}\indexlibrary{\idxcode{#2}!\idxcode{#1}}} -\newcommand{\indexlibraryzombie}[1]{\indexlibrary{\idxcode{#1}!zombie}} +\newcommand{\indexlibrarymemberx}[2]{\indexlibrarymisc{#1}{\idxcode{#2}}} +\newcommand{\indexlibrarymember}[2]{\indexlibrarymemberx{#1}{#2}\indexlibrarymemberx{#2}{#1}} +\newcommand{\indexlibraryzombie}[1]{\indexlibrarymisc{#1}{zombie}} \newcommand{\libglobal}[1]{\indexlibraryglobal{#1}#1} \newcommand{\libmember}[2]{\indexlibrarymember{#1}{#2}#1} From dad631ac4bd30e7ab6de5a888f77ed2b5b44c17d Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 6 Nov 2021 09:39:55 +0100 Subject: [PATCH 051/182] [except.throw,except.handle] Move lvalue specification for copies --- source/exceptions.tex | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/source/exceptions.tex b/source/exceptions.tex index ddabdcc06f..6482b538ac 100644 --- a/source/exceptions.tex +++ b/source/exceptions.tex @@ -260,9 +260,6 @@ copy-initializes~(\ref{dcl.init}, \ref{class.copy.ctor}) a temporary object, called the \defnx{exception object}{exception handling!exception object}. -An lvalue denoting the temporary is used to initialize the -variable declared in the matching -\grammarterm{handler}\iref{except.handle}. If the type of the exception object would be an incomplete type, an abstract class type\iref{class.abstract}, @@ -655,11 +652,12 @@ of type \tcode{E}, as follows: \begin{itemize} \item -if \tcode{T} is a base class of \tcode{E}, the variable is -copy-initialized\iref{dcl.init} from the corresponding base class subobject +if \tcode{T} is a base class of \tcode{E}, +the variable is copy-initialized\iref{dcl.init} +from an lvalue of type \tcode{T} designating the corresponding base class subobject of the exception object; \item otherwise, the variable is copy-initialized\iref{dcl.init} -from the exception object. +from an lvalue of type \tcode{E} designating the exception object. \end{itemize} The lifetime of the variable ends From c6e5eea4f11efec62a4718acd4eb17fb99fd4899 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 25 Oct 2021 23:41:31 +0200 Subject: [PATCH 052/182] [expr.prim.req.general] Change requirement-seq to right-recursive consistent with the specification of other -seq non-terminals. --- source/expressions.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/expressions.tex b/source/expressions.tex index 0cc7bbd662..42a18a9d04 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -2682,7 +2682,7 @@ \begin{bnf} \nontermdef{requirement-seq}\br requirement\br - requirement-seq requirement + requirement requirement-seq \end{bnf} \begin{bnf} From 872fce6effc603735c9717981807eb6bb8b4f838 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 4 Dec 2021 11:33:32 +0100 Subject: [PATCH 053/182] [associative.reqmts.general] Fix confusing local use of 'r' --- source/containers.tex | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index 745ec943ad..c8abbf38f6 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -1804,21 +1804,24 @@ \tcode{c} denotes a possibly \keyword{const} value of type \tcode{X::key_compare}; \item \tcode{kl} is a value such that \tcode{a} is partitioned\iref{alg.sorting} -with respect to \tcode{c(r, kl)}, with \tcode{r} the key value of \tcode{e} -and \tcode{e} in \tcode{a}; +with respect to \tcode{c(x, kl)}, +with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}; \item \tcode{ku} is a value such that \tcode{a} is partitioned with respect to -\tcode{!c(ku, r)}; +\tcode{!c(ku, x)}, +with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}; \item \tcode{ke} is a value such that \tcode{a} is partitioned with respect to -\tcode{c(r, ke)} and \tcode{!c(ke, r)}, with \tcode{c(r, ke)} implying -\tcode{!c(ke, r)}; +\tcode{c(x, ke)} and \tcode{!c(ke, x)}, with \tcode{c(x, ke)} implying +\tcode{!c(ke, x)} and +with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}; \item \tcode{kx} is a value such that \begin{itemize} \item -\tcode{a} is partitioned with respect to \tcode{c(r, kx)} and \tcode{!c(kx, r)}, -with \tcode{c(r, kx)} implying \tcode{!c(kx, r)}, and +\tcode{a} is partitioned with respect to \tcode{c(x, kx)} and \tcode{!c(kx, x)}, +with \tcode{c(x, kx)} implying \tcode{!c(kx, x)} and +with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}, and \item \tcode{kx} is not convertible to either \tcode{iterator} or \tcode{const_iterator}; and From 3d1bf58b74860fc1e86cd1cf536b7022b90d688d Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 7 Jan 2022 20:26:15 +0100 Subject: [PATCH 054/182] [temp.res.general] Clarify binding of names --- source/templates.tex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/templates.tex b/source/templates.tex index 2c9d9e3d17..5ebe525254 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -4200,7 +4200,8 @@ \pnum A name that appears in a declaration $D$ of a template $T$ is looked up from where it appears -in an unspecified declaration of $T$ that is or is reachable from $D$ and +in an unspecified declaration of $T$ +that either is $D$ itself or is reachable from $D$ and from which no other declaration of $T$ that contains the usage of the name is reachable. If the name is dependent (as specified in \ref{temp.dep}), From 4123264d22c7617d828083c9ad954b5541934621 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 25 Oct 2021 18:15:14 +0200 Subject: [PATCH 055/182] [temp.constr.atomic] Fix phrasing in note --- source/templates.tex | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/templates.tex b/source/templates.tex index 5ebe525254..d31d17e7a8 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -1650,9 +1650,11 @@ } \end{codeblock} \end{example} -This similarity includes the situation where a program is ill-formed, no diagnostic required, -when the meaning of the program depends on whether two constructs are equivalent, -and they are functionally equivalent but not equivalent. +As specified in \ref{temp.over.link}, +if the validity or meaning of the program depends on +whether two constructs are equivalent, and +they are functionally equivalent but not equivalent, +the program is ill-formed, no diagnostic required. \begin{example} \begin{codeblock} template void f2() From 26ce304780d79bba03a791b2f4299f083f021238 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 14 Dec 2021 09:25:41 +0100 Subject: [PATCH 056/182] [dcl.meaning.general] Clarify correspondence for block-scope friends --- source/declarations.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/declarations.tex b/source/declarations.tex index dade96d3b3..02fcaaa862 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -2548,7 +2548,7 @@ Otherwise, the terminal name of $E$ is not looked up. The declaration's target scope is the innermost enclosing namespace scope; if the declaration is contained by a block scope, -the declaration shall correspond to a declaration +the declaration shall correspond to a reachable\iref{module.reach} declaration that inhabits the innermost block scope. \end{itemize} From 3c19e315dbb05a2c22b8f5b075af39a7572cdaa1 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 23 Dec 2021 11:18:17 +0100 Subject: [PATCH 057/182] [meta.rel] Avoid undefined term 'void types' --- source/utilities.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index 72bc5d9c5f..cffdb676f8 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -18686,8 +18686,8 @@ \end{codeblock} \begin{note} -This requirement gives well-defined results for reference types, void -types, array types, and function types. +This requirement gives well-defined results for reference types, +array types, function types, and \cv{}~\keyword{void}. \end{note} Access checking is performed in a context unrelated to \tcode{To} and \tcode{From}. Only the validity of From 90d178d022c7d597629853ebc70262489e49d5e9 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 14 Jan 2022 19:46:15 +0100 Subject: [PATCH 058/182] [class.default.ctor] Fix implicit invocation of default constructor (#4026) Initialization is fully specified in [dcl.init], so turn the list of default-initialization cases into a note and shorten it appropriately. --- source/classes.tex | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index 54bb47a04d..2ee73806ef 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -1304,7 +1304,7 @@ is \defnx{implicitly defined}{constructor!implicitly defined} when it is odr-used\iref{term.odr.use} -to create an object of its class type\iref{intro.object}, +to initialize an object of its class type\iref{intro.object}, when it is needed for constant evaluation\iref{expr.const}, or when it is explicitly defaulted after its first declaration. The implicitly-defined default constructor performs the set of @@ -1329,19 +1329,12 @@ \end{note} \pnum -\indextext{constructor!implicitly called}% -Default constructors are called implicitly to create class objects of static, thread, -or automatic storage duration~(\ref{basic.stc.static}, \ref{basic.stc.thread}, \ref{basic.stc.auto}) defined -without an initializer\iref{dcl.init}, -are called to create class objects of dynamic storage duration\iref{basic.stc.dynamic} created by a -\grammarterm{new-expression} -in which the -\grammarterm{new-initializer} -is omitted\iref{expr.new}, or -are called when the explicit type conversion syntax\iref{expr.type.conv} is -used. -A program is ill-formed if the default constructor for an object -is implicitly used and the constructor is not accessible\iref{class.access}. +\begin{note} +\indextext{constructor!implicitly invoked}% +A default constructor is implicitly invoked to initialize +a class object when no initializer is specified\iref{dcl.init.general}. +Such a default constructor is required to be accessible\iref{class.access}. +\end{note} \pnum \begin{note} From e1bfc25c56c7ab303241f980fa00d7ae402e1f5c Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 5 Jul 2021 23:51:41 +0200 Subject: [PATCH 059/182] [stmt.return,class.{ctor,dtor}] Clarify no return operand Highlight that constructors and destructors do not have a return type and thus a return statement within a constructor or destructor cannot have an operand. --- source/classes.tex | 16 +++++++++++----- source/statements.tex | 7 +++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index 2ee73806ef..8f0a1bb00b 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -1208,12 +1208,13 @@ most derived object\iref{intro.object} ends. \pnum -\indextext{restriction!constructor}% -A -\tcode{return} -statement in the body of a constructor shall not specify a return value. \indextext{constructor!address of}% The address of a constructor shall not be taken. +\indextext{restriction!constructor}% +\begin{note} +A \tcode{return} statement in the body of a constructor +cannot specify a return value\iref{stmt.return}. +\end{note} \pnum A constructor shall not be a coroutine. @@ -2071,8 +2072,13 @@ the selected destructor may be deleted\iref{dcl.fct.def.delete}. \pnum -\indextext{restriction!destructor}% +\indextext{destructor!address of}% The address of a destructor shall not be taken. +\indextext{restriction!destructor}% +\begin{note} +A \tcode{return} statement in the body of a destructor +cannot specify a return value\iref{stmt.return}. +\end{note} \indextext{\idxcode{const}!destructor and}% \indextext{\idxcode{volatile}!destructor and}% A destructor can be invoked for a diff --git a/source/statements.tex b/source/statements.tex index 6c2ffed294..ac3de0ef6c 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -811,15 +811,18 @@ \indextext{\idxcode{return}!constructor and}% \indextext{\idxcode{return}!constructor and}% A \tcode{return} statement with an operand of type \keyword{void} shall be used only -in a function whose return type is \cv{}~\keyword{void}. +in a function that has a \cv{}~\keyword{void} return type. A \tcode{return} statement with any other operand shall be used only -in a function whose return type is not \cv{}~\keyword{void}; +in a function that has a return type other than \cv{}~\keyword{void}; \indextext{conversion!return type}% the \tcode{return} statement initializes the returned reference or prvalue result object of the (explicit or implicit) function call by copy-initialization\iref{dcl.init} from the operand. \begin{note} +A constructor or destructor does not have a return type. +\end{note} +\begin{note} A \tcode{return} statement can involve an invocation of a constructor to perform a copy or move of the operand if it is not a prvalue or if its type differs from the return type of the function. From b345505b88b376d547220254fd858840efbfb937 Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Fri, 14 Jan 2022 10:10:11 +0800 Subject: [PATCH 060/182] [temp.param] Delete outdated wording at p15 The wording at [temp.param]/15 says: > A template-parameter shall not be given default arguments by two > different declarations if one is reachable from the other. But it is conflicted with [basic.def.odr]/13: > There can be more than one definition of a > ... > default template argument > ... > in a program provided that each definition appears in a different > translation unit and the definitions satisfy the [same-meaning > criteria of the ODR]. [temp.param] should be deleted otherwise we couldn't modularize a real project. --- source/templates.tex | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/source/templates.tex b/source/templates.tex index d31d17e7a8..b987d37584 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -558,17 +558,6 @@ \end{codeblock} \end{example} -\pnum -A \grammarterm{template-parameter} -shall not be given default arguments by two different declarations -if one is reachable from the other. -\begin{example} -\begin{codeblock} -template class X; -template class X { @\commentellip@ }; // error -\end{codeblock} -\end{example} - \indextext{\idxcode{<}!template and}% \pnum When parsing a From fc9818bcdaa08f65c8d99f7df70b418810c36893 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 15 Jan 2022 09:43:55 +0100 Subject: [PATCH 061/182] [util.smartptr.atomic] Add cross-reference to header (#5207) --- source/atomics.tex | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/atomics.tex b/source/atomics.tex index 2c314ce8ad..ae058da196 100644 --- a/source/atomics.tex +++ b/source/atomics.tex @@ -2735,6 +2735,9 @@ \pnum The library provides partial specializations of the \tcode{atomic} template for shared-ownership smart pointers\iref{smartptr}. +\begin{note} +The partial specializations are declared in header \libheaderref{memory}. +\end{note} The behavior of all operations is as specified in \ref{atomics.types.generic}, unless specified otherwise. The template parameter \tcode{T} of these partial specializations From 4cea882aa693bd6fe230d0f886960dd7db37c43c Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 17 Jan 2022 13:16:08 +0100 Subject: [PATCH 062/182] [macros] In \ucode, align size of digits and letters (#5211) * [macros] In \ucode, improve sizes of digits and letters. We do this by typesetting letters in small-caps of the body font, and digits using the font "smaller by 1 step" (e.g. 10pt -> 8pt). This combination seems to look perfectly harmonious for normal body text and notes. This works around the absence of "small-caps sized lining numerals" in Latin Modern. The fact that LMR has separate optical sizes for the size range in question makes this combination work well. --- source/macros.tex | 32 +++++++++++++++++++++++++++++++- source/std.tex | 1 + 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/source/macros.tex b/source/macros.tex index 41113e9cd6..46011ec26a 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -360,7 +360,37 @@ \renewcommand{\fref}[1]{\hyperref[fig:#1]{\figurerefname \nolinebreak[3] \ref*{fig:#1}}} %% NTBS, etc. -\newcommand{\ucode}[1]{\textsc{u}\textsmaller[1.5]{\kern-0.05em\protect\raisebox{.25ex}{\textsmaller[1]{+}}\uppercase{#1}}} +\verbtocs{\StrTextsmaller}|\textsmaller[1]{| +\verbtocs{\StrTextsc}|\textsc{| +\verbtocs{\StrClosingbrace}|}| +\newcommand{\ucode}[1]{% + \textsc{u}% + \textsmaller[2]{\kern-0.05em\protect\raisebox{.25ex}{+}}% + \begingroup% + \def\temp{#1}% + \StrSubstitute{\temp}{0}{X0Z}[\temp]% + \StrSubstitute{\temp}{1}{X1Z}[\temp]% + \StrSubstitute{\temp}{2}{X2Z}[\temp]% + \StrSubstitute{\temp}{3}{X3Z}[\temp]% + \StrSubstitute{\temp}{4}{X4Z}[\temp]% + \StrSubstitute{\temp}{5}{X5Z}[\temp]% + \StrSubstitute{\temp}{6}{X6Z}[\temp]% + \StrSubstitute{\temp}{7}{X7Z}[\temp]% + \StrSubstitute{\temp}{8}{X8Z}[\temp]% + \StrSubstitute{\temp}{9}{X9Z}[\temp]% + \StrSubstitute{\temp}{a}{YaZ}[\temp]% + \StrSubstitute{\temp}{b}{YbZ}[\temp]% + \StrSubstitute{\temp}{c}{YcZ}[\temp]% + \StrSubstitute{\temp}{d}{YdZ}[\temp]% + \StrSubstitute{\temp}{e}{YeZ}[\temp]% + \StrSubstitute{\temp}{f}{YfZ}[\temp]% + \StrSubstitute{\temp}{X}{\StrTextsmaller}[\temp]% + \StrSubstitute{\temp}{Y}{\StrTextsc}[\temp]% + \StrSubstitute{\temp}{Z}{\StrClosingbrace}[\temp]% + \tokenize\temp{\temp}% + \temp% + \endgroup% +} \newcommand{\uname}[1]{\textsc{#1}} \newcommand{\unicode}[2]{\ucode{#1} \uname{#2}} \newcommand{\NTS}[1]{\textsc{#1}} diff --git a/source/std.tex b/source/std.tex index 5b4a97f572..552d663558 100644 --- a/source/std.tex +++ b/source/std.tex @@ -47,6 +47,7 @@ \usepackage[active,header=false,handles=false,copydocumentclass=false,generate=std-gram.ext,extract-cmdline={gramSec},extract-env={bnf,simplebnf}]{extract} % Grammar extraction \usepackage{expl3} \usepackage{xparse} +\usepackage{xstring} \pdfminorversion=5 \pdfcompresslevel=9 From 5c59ede65b362afb418bda3cf82123ae2ca2553c Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 23 Dec 2021 11:36:39 +0100 Subject: [PATCH 063/182] [locale.ctype.virtuals] Clarify do_widen parameter --- source/locales.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/locales.tex b/source/locales.tex index 7c51ca862b..982f09962a 100644 --- a/source/locales.tex +++ b/source/locales.tex @@ -1227,7 +1227,7 @@ from a \tcode{char} value or sequence of \tcode{char} values to the corresponding \tcode{charT} value or values. \begin{footnote} -The char argument of \tcode{do_widen} is intended to +The parameter \tcode{c} of \tcode{do_widen} is intended to accept values derived from \grammarterm{character-literal}s for conversion to the locale's encoding. \end{footnote} From cec2d218209abf2979a3c7fabc9970d8677b9e63 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 23 Dec 2021 12:53:01 +0100 Subject: [PATCH 064/182] [diff.stmt] Properly refer to function return types Also annotate the 'void' and 'int' keywords. --- source/compatibility.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/compatibility.tex b/source/compatibility.tex index c4b75839dd..d358745932 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -2261,7 +2261,7 @@ promising to return a value of a given type, and then not returning such a value, has always been recognized to be a questionable practice, tolerated only because very-old C had no distinction between -void functions and int functions. +functions with \keyword{void} and \keyword{int} return types. \effect Deletion of semantically well-defined feature. \difficulty From ba9124e62ea85c922d501dfc52bc4d44c85933bd Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 21 Jan 2022 15:57:58 +0000 Subject: [PATCH 065/182] [util.smartptr.atomic.general] Fix cross-reference to shared_ptr (#5222) --- source/atomics.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/atomics.tex b/source/atomics.tex index ae058da196..3aa997d81e 100644 --- a/source/atomics.tex +++ b/source/atomics.tex @@ -2734,7 +2734,7 @@ \pnum The library provides partial specializations of the \tcode{atomic} template -for shared-ownership smart pointers\iref{smartptr}. +for shared-ownership smart pointers\iref{util.sharedptr}. \begin{note} The partial specializations are declared in header \libheaderref{memory}. \end{note} From a4994b45b2c2f2b2838b91f6ee78ab5e470b46eb Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 26 Dec 2021 22:46:09 +0100 Subject: [PATCH 066/182] [diff] Annotate keywords --- source/compatibility.tex | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/source/compatibility.tex b/source/compatibility.tex index d358745932..d35bda8e90 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -2116,7 +2116,7 @@ \diffref{conv.ptr} \change -Converting \tcode{void*} to a pointer-to-object type requires casting. +Converting \tcode{\keyword{void}*} to a pointer-to-object type requires casting. \begin{codeblock} char a[10]; @@ -2166,19 +2166,19 @@ \diffref{expr.post.incr,expr.pre.incr} \change -Decrement operator is not allowed with \tcode{bool} operand. +Decrement operator is not allowed with \keyword{bool} operand. \rationale Feature with surprising semantics. \effect A valid ISO C expression utilizing the decrement operator on -a \tcode{bool} lvalue +a \keyword{bool} lvalue (for instance, via the C typedef in \libheaderref{stdbool.h}) is ill-formed in \Cpp{}. \diffref{expr.sizeof,expr.cast} \change In \Cpp{}, types can only be defined in declarations, not in expressions.\\ -In C, a sizeof expression or cast expression may define a new type. +In C, a \keyword{sizeof} expression or cast expression may define a new type. For example, \begin{codeblock} p = (void*)(struct x {int i;} *)0; @@ -2570,7 +2570,7 @@ \diffref{dcl.enum} \change -In \Cpp{}, the type of an enumerator is its enumeration. In C, the type of an enumerator is \tcode{int}. +In \Cpp{}, the type of an enumerator is its enumeration. In C, the type of an enumerator is \keyword{int}. Example: \begin{codeblock} @@ -2653,7 +2653,7 @@ \rationale Several alternatives were debated at length. Changing the parameter to -\tcode{volatile} +\keyword{volatile} \keyword{const} \tcode{X\&} would greatly complicate the generation of @@ -2683,7 +2683,7 @@ \diffref{class.bit} \change \indextext{bit-field!implementation-defined sign of}% -Bit-fields of type plain \tcode{int} are signed. +Bit-fields of type plain \keyword{int} are signed. \rationale Leaving the choice of signedness to implementations could lead to inconsistent definitions of template specializations. For consistency, @@ -2849,18 +2849,18 @@ \pnum The tokens -\tcode{and}, -\tcode{and_eq}, -\tcode{bitand}, -\tcode{bitor}, -\tcode{compl}, -\tcode{not}, -\tcode{not_eq}, -\tcode{or}, -\tcode{or_eq}, -\tcode{xor}, +\keyword{and}, +\keyword{and_eq}, +\keyword{bitand}, +\keyword{bitor}, +\keyword{compl}, +\keyword{not}, +\keyword{not_eq}, +\keyword{or}, +\keyword{or_eq}, +\keyword{xor}, and -\tcode{xor_eq} +\keyword{xor_eq} are keywords in \Cpp{}\iref{lex.key}, and are not introduced as macros by \libheaderref{iso646.h}. @@ -2869,7 +2869,7 @@ \indexhdr{stdalign.h}% \pnum -The token \tcode{alignas} is a keyword in \Cpp{}\iref{lex.key}, +The token \keyword{alignas} is a keyword in \Cpp{}\iref{lex.key}, and is not introduced as a macro by \libheaderref{stdalign.h}. @@ -2877,7 +2877,7 @@ \indexhdr{stdbool.h}% \pnum -The tokens \tcode{bool}, \tcode{true}, and \tcode{false} +The tokens \keyword{bool}, \keyword{true}, and \keyword{false} are keywords in \Cpp{}\iref{lex.key}, and are not introduced as macros by \libheaderref{stdbool.h}. From 3cb2ee9d67360612e6361aa26d1805c8ed30c6e6 Mon Sep 17 00:00:00 2001 From: Chuanqi Xu <68680648+ChuanqiXu9@users.noreply.github.com> Date: Sat, 22 Jan 2022 17:43:22 +0800 Subject: [PATCH 067/182] [temp.dep.general] add trailing 'or' (#5186) --- source/templates.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/templates.tex b/source/templates.tex index b987d37584..62d609f6fe 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -4701,7 +4701,7 @@ \begin{itemize} \item any of the expressions in the \grammarterm{expression-list} is a pack -expansion\iref{temp.variadic}, +expansion\iref{temp.variadic}, or \item any of the expressions or \grammarterm{braced-init-list}{s} From 4e2dbd25fa137f12c8fa6b960bc2db45be994414 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 22 Jan 2022 13:38:10 +0100 Subject: [PATCH 068/182] [class.free] Move into [class.mem] The class-specific allocation and deallocation functions, whose declaration properties are specified in this section, are class member functions. --- source/classes.tex | 282 ++++++++++++++++++++++----------------------- 1 file changed, 141 insertions(+), 141 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index 8f0a1bb00b..cbb4dd87f0 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -2864,6 +2864,147 @@ \end{codeblock} \end{example} +\rSec2[class.free]{Free store}% +\indextext{free store}% + +\pnum +\indextext{\idxcode{new}!type of} +Any allocation function for a class +\tcode{T} +is a static member (even if not explicitly declared +\keyword{static}). + +\pnum +\begin{example} +\begin{codeblock} +class Arena; +struct B { + void* operator new(std::size_t, Arena*); +}; +struct D1 : B { +}; + +Arena* ap; +void foo(int i) { + new (ap) D1; // calls \tcode{B::operator new(std::size_t, Arena*)} + new D1[i]; // calls \tcode{::operator new[](std::size_t)} + new D1; // error: \tcode{::operator new(std::size_t)} hidden +} +\end{codeblock} +\end{example} + +\pnum +\indextext{\idxcode{delete}!type of}% +Any deallocation function for a class +\tcode{X} +is a static member (even if not explicitly declared +\keyword{static}). +\begin{example} +\begin{codeblock} +class X { + void operator delete(void*); + void operator delete[](void*, std::size_t); +}; + +class Y { + void operator delete(void*, std::size_t); + void operator delete[](void*); +}; +\end{codeblock} +\end{example} + +\pnum +Since member allocation and deallocation functions are +\keyword{static} +they cannot be virtual. +\begin{note} +However, when the +\grammarterm{cast-expression} +of a +\grammarterm{delete-expression} +refers to an object of class type with a virtual destructor, +because the deallocation function is chosen by the destructor +of the dynamic type of the object, the effect is the same in that case. +For example, +\begin{codeblock} +struct B { + virtual ~B(); + void operator delete(void*, std::size_t); +}; + +struct D : B { + void operator delete(void*); +}; + +struct E : B { + void log_deletion(); + void operator delete(E *p, std::destroying_delete_t) { + p->log_deletion(); + p->~E(); + ::operator delete(p); + } +}; + +void f() { + B* bp = new D; + delete bp; // 1: uses \tcode{D::operator delete(void*)} + bp = new E; + delete bp; // 2: uses \tcode{E::operator delete(E*, std::destroying_delete_t)} +} +\end{codeblock} +Here, storage for the object of class +\tcode{D} +is deallocated by +\tcode{D::operator delete()}, +and +the object of class \tcode{E} is destroyed +and its storage is deallocated +by \tcode{E::operator delete()}, +due to the virtual destructor. +\end{note} +\begin{note} +Virtual destructors have no effect on the deallocation function actually +called when the +\grammarterm{cast-expression} +of a +\grammarterm{delete-expression} +refers to an array of objects of class type. +For example, +\begin{codeblock} +struct B { + virtual ~B(); + void operator delete[](void*, std::size_t); +}; + +struct D : B { + void operator delete[](void*, std::size_t); +}; + +void f(int i) { + D* dp = new D[i]; + delete [] dp; // uses \tcode{D::operator delete[](void*, std::size_t)} + B* bp = new D[i]; + delete[] bp; // undefined behavior +} +\end{codeblock} +\end{note} + +\pnum +Access to the deallocation function is checked statically, +even if a different one is actually executed. +\begin{example} +For the call on line ``// 1'' above, +if +\tcode{B::operator delete()} +had been private, the delete expression would have been ill-formed. +\end{example} + +\pnum +\begin{note} +If a deallocation function has no explicit \grammarterm{noexcept-specifier}, it +has a non-throwing exception specification\iref{except.spec}. +\end{note} + \rSec2[class.nest]{Nested class declarations}% \indextext{definition!nested class}% @@ -6634,145 +6775,4 @@ \end{codeblock} \end{example} -\rSec1[class.free]{Free store}% -\indextext{free store}% - -\pnum -\indextext{\idxcode{new}!type of} -Any allocation function for a class -\tcode{T} -is a static member (even if not explicitly declared -\keyword{static}). - -\pnum -\begin{example} -\begin{codeblock} -class Arena; -struct B { - void* operator new(std::size_t, Arena*); -}; -struct D1 : B { -}; - -Arena* ap; -void foo(int i) { - new (ap) D1; // calls \tcode{B::operator new(std::size_t, Arena*)} - new D1[i]; // calls \tcode{::operator new[](std::size_t)} - new D1; // error: \tcode{::operator new(std::size_t)} hidden -} -\end{codeblock} -\end{example} - -\pnum -\indextext{\idxcode{delete}!type of}% -Any deallocation function for a class -\tcode{X} -is a static member (even if not explicitly declared -\keyword{static}). -\begin{example} -\begin{codeblock} -class X { - void operator delete(void*); - void operator delete[](void*, std::size_t); -}; - -class Y { - void operator delete(void*, std::size_t); - void operator delete[](void*); -}; -\end{codeblock} -\end{example} - -\pnum -Since member allocation and deallocation functions are -\keyword{static} -they cannot be virtual. -\begin{note} -However, when the -\grammarterm{cast-expression} -of a -\grammarterm{delete-expression} -refers to an object of class type with a virtual destructor, -because the deallocation function is chosen by the destructor -of the dynamic type of the object, the effect is the same in that case. -For example, -\begin{codeblock} -struct B { - virtual ~B(); - void operator delete(void*, std::size_t); -}; - -struct D : B { - void operator delete(void*); -}; - -struct E : B { - void log_deletion(); - void operator delete(E *p, std::destroying_delete_t) { - p->log_deletion(); - p->~E(); - ::operator delete(p); - } -}; - -void f() { - B* bp = new D; - delete bp; // 1: uses \tcode{D::operator delete(void*)} - bp = new E; - delete bp; // 2: uses \tcode{E::operator delete(E*, std::destroying_delete_t)} -} -\end{codeblock} -Here, storage for the object of class -\tcode{D} -is deallocated by -\tcode{D::operator delete()}, -and -the object of class \tcode{E} is destroyed -and its storage is deallocated -by \tcode{E::operator delete()}, -due to the virtual destructor. -\end{note} -\begin{note} -Virtual destructors have no effect on the deallocation function actually -called when the -\grammarterm{cast-expression} -of a -\grammarterm{delete-expression} -refers to an array of objects of class type. -For example, -\begin{codeblock} -struct B { - virtual ~B(); - void operator delete[](void*, std::size_t); -}; - -struct D : B { - void operator delete[](void*, std::size_t); -}; - -void f(int i) { - D* dp = new D[i]; - delete [] dp; // uses \tcode{D::operator delete[](void*, std::size_t)} - B* bp = new D[i]; - delete[] bp; // undefined behavior -} -\end{codeblock} -\end{note} - -\pnum -Access to the deallocation function is checked statically, -even if a different one is actually executed. -\begin{example} -For the call on line ``// 1'' above, -if -\tcode{B::operator delete()} -had been private, the delete expression would have been ill-formed. -\end{example} - -\pnum -\begin{note} -If a deallocation function has no explicit \grammarterm{noexcept-specifier}, it -has a non-throwing exception specification\iref{except.spec}. -\end{note} - \indextext{class|)} From 7987ef93488842bbdbbd6e4de996f463939fe0e8 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 22 Jan 2022 13:45:23 +0100 Subject: [PATCH 069/182] [class.free] Change subclause heading and add indexing Rename the heading to "Allocation and deallocation functions", which is more appropriate for the contents of the subclause. --- source/classes.tex | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index cbb4dd87f0..8af7dada1d 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -2864,11 +2864,12 @@ \end{codeblock} \end{example} -\rSec2[class.free]{Free store}% +\rSec2[class.free]{Allocation and deallocation functions}% \indextext{free store}% \pnum -\indextext{\idxcode{new}!type of} +\indextext{\idxcode{new}!type of}% +\indextext{allocation function!class-specific}% Any allocation function for a class \tcode{T} is a static member (even if not explicitly declared @@ -2895,6 +2896,7 @@ \pnum \indextext{\idxcode{delete}!type of}% +\indextext{deallocation function!class-specific}% Any deallocation function for a class \tcode{X} is a static member (even if not explicitly declared From f1bcf07c1343687a59f063cbf9f5d92f5554db17 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 22 Jan 2022 13:50:38 +0100 Subject: [PATCH 070/182] [basic.stc.dynamic.general] Fix index entries for de/allocation function Make the entries for 'allocation function' and 'deallocation function' singular. --- source/basic.tex | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 90685d5eea..dfd44e2ec6 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -3810,10 +3810,13 @@ \grammarterm{new-expression}{s}\iref{expr.new}, and destroyed using \indextext{\idxcode{delete}}% \grammarterm{delete-expression}{s}\iref{expr.delete}. A \Cpp{} implementation -provides access to, and management of, dynamic storage via the global -\defn{allocation functions} \tcode{\keyword{operator} \keyword{new}} and \tcode{\keyword{operator} -\keyword{new}[]} and the global \defn{deallocation functions} \tcode{\keyword{operator} -\keyword{delete}} and \tcode{\keyword{operator} \keyword{delete}[]}. +provides access to, and management of, dynamic storage via +the global \defnx{allocation functions}{allocation function} +\tcode{\keyword{operator} \keyword{new}} and +\tcode{\keyword{operator} \keyword{new}[]} and +the global \defnx{deallocation functions}{deallocation function} +\tcode{\keyword{operator} \keyword{delete}} and +\tcode{\keyword{operator} \keyword{delete}[]}. \begin{note} The non-allocating forms described in \ref{new.delete.placement} do not perform allocation or deallocation. From 07db0b3182495339b00221bba41549913e0a6a0e Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 22 Jan 2022 14:35:11 +0100 Subject: [PATCH 071/182] [stacktrace] Move into [diagnostics] --- source/diagnostics.tex | 726 ++++++++++++++++++++++++++++++++++++++++- source/utilities.tex | 720 ---------------------------------------- 2 files changed, 724 insertions(+), 722 deletions(-) diff --git a/source/diagnostics.tex b/source/diagnostics.tex index 438d911c5b..d145ced062 100644 --- a/source/diagnostics.tex +++ b/source/diagnostics.tex @@ -10,7 +10,8 @@ \pnum The following subclauses describe components for reporting several kinds of exceptional conditions, -documenting program assertions, and +documenting program assertions, +obtaining stacktraces, and a global variable for error number codes, as summarized in \tref{diagnostics.summary}. @@ -18,7 +19,8 @@ \ref{std.exceptions} & Exception classes & \tcode{} \\ \rowsep \ref{assertions} & Assertions & \tcode{} \\ \rowsep \ref{errno} & Error numbers & \tcode{} \\ \rowsep -\ref{syserr} & System error support & \tcode{} \\ +\ref{syserr} & System error support & \tcode{} \\ \rowsep +\ref{stacktrace} & Stacktrace & \tcode{} \\ \end{libsumtab} \rSec1[std.exceptions]{Exception classes} @@ -1677,3 +1679,723 @@ 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{} synopsis} + +\indexheader{stacktrace}% +\begin{codeblock} +namespace std { + // \ref{stacktrace.entry}, class \tcode{stacktrace_entry} + class stacktrace_entry; + + // \ref{stacktrace.basic}, class template \tcode{basic_stacktrace} + template + class basic_stacktrace; + + // \tcode{basic_stacktrace} \grammarterm{typedef-name}s + using stacktrace = basic_stacktrace>; + + // \ref{stacktrace.basic.nonmem}, non-member functions + template + void swap(basic_stacktrace& a, basic_stacktrace& b) + noexcept(noexcept(a.swap(b))); + + string to_string(const stacktrace_entry& f); + + template + string to_string(const basic_stacktrace& st); + + template + basic_ostream& + operator<<(basic_ostream& os, const stacktrace_entry& f); + + template + basic_ostream& + operator<<(basic_ostream& os, const basic_stacktrace& st); + + namespace pmr { + using stacktrace = basic_stacktrace>; + } + + // \ref{stacktrace.basic.hash}, hash support + template struct hash; + template<> struct hash; + template struct hash>; +} +\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.ctor}, 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}}\iref{cmp.concept}. + +\rSec3[stacktrace.entry.ctor]{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 @\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; + using const_reverse_iterator = std::reverse_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.ctor}, 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); + 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::propagate_on_container_move_assignment::value || + allocator_traits::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; + + [[nodiscard]] 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 + friend bool operator==(const basic_stacktrace& x, + const basic_stacktrace& y) noexcept; + template + friend strong_ordering operator<=>(const basic_stacktrace& x, + const basic_stacktrace& y) noexcept; + + // \ref{stacktrace.basic.mod}, modifiers + void swap(basic_stacktrace& other) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); + + private: + vector frames_; // \expos + }; +} +\end{codeblock} + +\pnum +The class template \tcode{basic_stacktrace} satisfies +the requirements of +an allocator-aware container (\tref{container.alloc.req}), +a sequence container\iref{sequence.reqmts}, and +a reversible container\iref{container.requirements.general} +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.ctor]{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 \tcode{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 \tcode{frames_} failed. +\tcode{alloc} is passed to the constructor of the \tcode{frames_} object. + +\begin{note} +If the stacktrace was successfully obtained, +then \tcode{frames_.front()} is the \tcode{stacktrace_entry} +representing approximately the current evaluation, and +\tcode{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 \tcode{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 \tcode{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 +\expects +\tcode{skip <= skip + max_depth} is \tcode{true}. + +\pnum +\returns +A \tcode{basic_stacktrace} object +where \tcode{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 \tcode{frames_} failed. +\end{itemdescr} + +\indexlibraryctor{basic_stacktrace}% +\begin{itemdecl} +basic_stacktrace() noexcept(is_nothrow_default_constructible_v); +\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 \tcode{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::propagate_on_container_move_assignment::value || + allocator_traits::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{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 \tcode{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} +[[nodiscard]] bool empty() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{frames_.empty()}. +\end{itemdescr} + +\indexlibrarymember{size}{basic_stacktrace}% +\begin{itemdecl} +size_type size() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{frames_.size()}. +\end{itemdescr} + +\indexlibrarymember{max_size}{basic_stacktrace}% +\begin{itemdecl} +size_type max_size() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{frames_.max_size()}. +\end{itemdescr} + +\indexlibrarymember{operator[]}{basic_stacktrace}% +\begin{itemdecl} +const_reference operator[](size_type frame_no) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{frame_no < size()} is \tcode{true}. + +\pnum +\returns +\tcode{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{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 +friend bool operator==(const basic_stacktrace& x, const basic_stacktrace& 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 +friend strong_ordering + operator<=>(const basic_stacktrace& x, const basic_stacktrace& 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::propagate_on_container_swap::value || + allocator_traits::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 +void swap(basic_stacktrace& a, basic_stacktrace& 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}. + +\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 +string to_string(const basic_stacktrace& 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} +template +basic_ostream& + operator<<(basic_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 +basic_ostream& + operator<<(basic_ostream& os, const basic_stacktrace& st); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return os << to_string(st);} +\end{itemdescr} + +\rSec3[stacktrace.basic.hash]{Hash support} + +\begin{itemdecl} +template<> struct hash; +template struct hash>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The specializations are enabled\iref{unord.hash}. +\end{itemdescr} diff --git a/source/utilities.tex b/source/utilities.tex index cffdb676f8..703d28592b 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -22674,723 +22674,3 @@ \ensures \tcode{strcmp(what(), what_arg) == 0}. \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{} synopsis} - -\indexheader{stacktrace}% -\begin{codeblock} -namespace std { - // \ref{stacktrace.entry}, class \tcode{stacktrace_entry} - class stacktrace_entry; - - // \ref{stacktrace.basic}, class template \tcode{basic_stacktrace} - template - class basic_stacktrace; - - // \tcode{basic_stacktrace} \grammarterm{typedef-name}s - using stacktrace = basic_stacktrace>; - - // \ref{stacktrace.basic.nonmem}, non-member functions - template - void swap(basic_stacktrace& a, basic_stacktrace& b) - noexcept(noexcept(a.swap(b))); - - string to_string(const stacktrace_entry& f); - - template - string to_string(const basic_stacktrace& st); - - template - basic_ostream& - operator<<(basic_ostream& os, const stacktrace_entry& f); - - template - basic_ostream& - operator<<(basic_ostream& os, const basic_stacktrace& st); - - namespace pmr { - using stacktrace = basic_stacktrace>; - } - - // \ref{stacktrace.basic.hash}, hash support - template struct hash; - template<> struct hash; - template struct hash>; -} -\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.ctor}, 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}}\iref{cmp.concept}. - -\rSec3[stacktrace.entry.ctor]{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 @\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; - using const_reverse_iterator = std::reverse_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.ctor}, 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); - 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::propagate_on_container_move_assignment::value || - allocator_traits::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; - - [[nodiscard]] 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 - friend bool operator==(const basic_stacktrace& x, - const basic_stacktrace& y) noexcept; - template - friend strong_ordering operator<=>(const basic_stacktrace& x, - const basic_stacktrace& y) noexcept; - - // \ref{stacktrace.basic.mod}, modifiers - void swap(basic_stacktrace& other) - noexcept(allocator_traits::propagate_on_container_swap::value || - allocator_traits::is_always_equal::value); - - private: - vector frames_; // \expos - }; -} -\end{codeblock} - -\pnum -The class template \tcode{basic_stacktrace} satisfies -the requirements of -an allocator-aware container (\tref{container.alloc.req}), -a sequence container\iref{sequence.reqmts}, and -a reversible container\iref{container.requirements.general} -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.ctor]{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 \tcode{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 \tcode{frames_} failed. -\tcode{alloc} is passed to the constructor of the \tcode{frames_} object. - -\begin{note} -If the stacktrace was successfully obtained, -then \tcode{frames_.front()} is the \tcode{stacktrace_entry} -representing approximately the current evaluation, and -\tcode{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 \tcode{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 \tcode{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 -\expects -\tcode{skip <= skip + max_depth} is \tcode{true}. - -\pnum -\returns -A \tcode{basic_stacktrace} object -where \tcode{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 \tcode{frames_} failed. -\end{itemdescr} - -\indexlibraryctor{basic_stacktrace}% -\begin{itemdecl} -basic_stacktrace() noexcept(is_nothrow_default_constructible_v); -\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 \tcode{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::propagate_on_container_move_assignment::value || - allocator_traits::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{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 \tcode{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} -[[nodiscard]] bool empty() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{frames_.empty()}. -\end{itemdescr} - -\indexlibrarymember{size}{basic_stacktrace}% -\begin{itemdecl} -size_type size() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{frames_.size()}. -\end{itemdescr} - -\indexlibrarymember{max_size}{basic_stacktrace}% -\begin{itemdecl} -size_type max_size() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{frames_.max_size()}. -\end{itemdescr} - -\indexlibrarymember{operator[]}{basic_stacktrace}% -\begin{itemdecl} -const_reference operator[](size_type frame_no) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{frame_no < size()} is \tcode{true}. - -\pnum -\returns -\tcode{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{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 -friend bool operator==(const basic_stacktrace& x, const basic_stacktrace& 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 -friend strong_ordering - operator<=>(const basic_stacktrace& x, const basic_stacktrace& 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::propagate_on_container_swap::value || - allocator_traits::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 -void swap(basic_stacktrace& a, basic_stacktrace& 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}. - -\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 -string to_string(const basic_stacktrace& 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} -template -basic_ostream& - operator<<(basic_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 -basic_ostream& - operator<<(basic_ostream& os, const basic_stacktrace& st); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return os << to_string(st);} -\end{itemdescr} - -\rSec3[stacktrace.basic.hash]{Hash support} - -\begin{itemdecl} -template<> struct hash; -template struct hash>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The specializations are enabled\iref{unord.hash}. -\end{itemdescr} From 0df02c99d04dd0e0d29ea520904ea64f69ea6c36 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 20 Jan 2022 19:42:09 +0100 Subject: [PATCH 072/182] [class.mem.general] Add cross-reference for 'layout-compatible type' --- source/classes.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/classes.tex b/source/classes.tex index 8af7dada1d..59c0cedd8b 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -782,7 +782,7 @@ types is the longest sequence of non-static data members and bit-fields in declaration order, starting with the first such entity in each of the structs, such that corresponding entities -have layout-compatible types, +have layout-compatible types\iref{basic.types}, either both entities are declared with the \tcode{no_unique_address} attribute\iref{dcl.attr.nouniqueaddr} or neither is, From 2e5976f894d821e442a6f98c3e235381f8067570 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 20 Jan 2022 19:36:15 +0100 Subject: [PATCH 073/182] [stmt.return] Clarify flowing off the end of a function --- source/statements.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/statements.tex b/source/statements.tex index ac3de0ef6c..68d3aecde5 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -849,7 +849,7 @@ a non-coroutine function with a \cv{}~\keyword{void} return type is equivalent to a \tcode{return} with no operand. Otherwise, flowing off the end of a function -other than \tcode{main}\iref{basic.start.main} or a coroutine\iref{dcl.fct.def.coroutine} +that is neither \tcode{main}\iref{basic.start.main} nor a coroutine\iref{dcl.fct.def.coroutine} results in undefined behavior. \pnum From 88541f7ad5de85389adb0e88f295091d29f00030 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 25 Jan 2022 23:12:55 +0100 Subject: [PATCH 074/182] [range.req.general] Remove incorrect normative duplication for 'view' (#5235) --- source/ranges.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/ranges.tex b/source/ranges.tex index 7616368c5f..db08470e2f 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -1044,8 +1044,8 @@ return an iterator and a sentinel, respectively. The \libconcept{sized_range} concept refines \libconcept{range} with the requirement that \tcode{ranges::size} be amortized \bigoh{1}. -The \libconcept{view} concept specifies requirements on a \libconcept{range} type -with constant-time destruction and move operations. +The \libconcept{view} concept specifies requirements on +a \libconcept{range} type to provide operations with predictable complexity. \pnum Several refinements of \libconcept{range} group requirements From 0539c5e2cdf7605c5704eb2b63916b6c5c3b9539 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 18 Feb 2021 13:42:57 +0100 Subject: [PATCH 075/182] [macros,structure.specifications] Add 'Result' element --- source/lib-intro.tex | 9 +++++++++ source/macros.tex | 1 + 2 files changed, 10 insertions(+) diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 7cf1ca4e43..8b91715a40 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -349,6 +349,15 @@ the conditions (sometimes termed observable results) established by the function. +\item +\result +for a \grammarterm{typename-specifier}, a description of the named type; +for an \grammarterm{expression}, +a description of the type of the expression; +the expression is an lvalue if the type is an lvalue reference type, +an xvalue if the type is an rvalue reference type, and +a prvalue otherwise. + \item \returns a description of the value(s) returned by the function. diff --git a/source/macros.tex b/source/macros.tex index 46011ec26a..89ee44f07a 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -339,6 +339,7 @@ \newcommand{\sync}{\Fundesc{Synchronization}} \newcommand{\implimits}{\Fundesc{Implementation limits}} \newcommand{\replaceable}{\Fundesc{Replaceable}} +\newcommand{\result}{\Fundesc{Result}} \newcommand{\returntype}{\Fundesc{Return type}} \newcommand{\cvalue}{\Fundesc{Value}} \newcommand{\ctype}{\Fundesc{Type}} From 408a22b1b58207de4af28d59afd20156e715e35f Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 7 Jan 2021 23:48:43 +0100 Subject: [PATCH 076/182] [re.req] Replace requirements table with \itemdescr --- source/regex.tex | 383 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 268 insertions(+), 115 deletions(-) diff --git a/source/regex.tex b/source/regex.tex index 0cf5800101..9800293c79 100644 --- a/source/regex.tex +++ b/source/regex.tex @@ -63,130 +63,283 @@ \indextext{requirements!regular expression traits}% \indextext{regular expression!requirements}% \indextext{locale}% -In \tref{re.req} \tcode{X} denotes a traits class -defining types and functions for the character container -type \tcode{charT}; \tcode{u} is an object of -type \tcode{X}; \tcode{v} is an object of type \tcode{const -X}; \tcode{p} is a value of type \tcode{const charT*}; \tcode{I1} -and \tcode{I2} are input iterators\iref{input.iterators}; +In the following requirements, +\begin{itemize} +\item +\tcode{X} denotes a traits class defining types and functions +for the character container type \tcode{charT}; +\item +\tcode{u} is an object of type \tcode{X}; +\item +\tcode{v} is an object of type \tcode{const X}; +\item +\tcode{p} is a value of type \tcode{const charT*}; +\item +\tcode{I1} and \tcode{I2} are input iterators\iref{input.iterators}; +\item \tcode{F1} and \tcode{F2} are forward iterators\iref{forward.iterators}; +\item \tcode{c} is a value of type \tcode{const charT}; +\item \tcode{s} is an object of type \tcode{X::string_type}; +\item \tcode{cs} is an object of type \tcode{const X::string_type}; +\item \tcode{b} is a value of type \tcode{bool}; +\item \tcode{I} is a value of type \tcode{int}; -\tcode{cl} is an object of type \tcode{X::char_class_type}, -and \tcode{loc} is an object of type \tcode{X::locale_type}. - -\begin{libreqtab3} - {Regular expression traits class requirements} - {re.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \rhdr{Assertion/note pre-/post-condition } \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & \rhdr{Assertion/note pre-/post-condition } \\ \capsep -\endhead -%% +\item +\tcode{cl} is an object of type \tcode{X::char_class_type}; and +\item +\tcode{loc} is an object of type \tcode{X::locale_type}. +\end{itemize} + +\pnum +A traits class \tcode{X} meets the regular expression traits requirements +if the following types and expressions are well-formed and have the specified +semantics. + +\begin{itemdecl} +typename X::char_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{charT}, +the character container type used in the implementation of class +template \tcode{basic_regex}. +\end{itemdescr} + +\begin{itemdecl} +typename X::string_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{basic_string} +\end{itemdescr} + +\begin{itemdecl} +typename X::locale_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A copy constructible type +that represents the locale used by the traits class. +\end{itemdescr} + +\begin{itemdecl} +typename X::char_class_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A bitmask type\iref{bitmask.types} +representing a particular character classification. +\end{itemdescr} + +\begin{itemdecl} +X::length(p) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_t} + +\pnum +\returns +The smallest \tcode{i} such that \tcode{p[i] == 0}. + +\pnum +\complexity +Linear in \tcode{i}. +\end{itemdescr} + +\begin{itemdecl} +v.translate(c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result \tcode{X::char_type} - & \tcode{charT} - & The character container type used in the implementation of class - template \tcode{basic_regex}. - \\ \rowsep + +\pnum +\returns +A character such that for any character \tcode{d} +that is to be considered equivalent to \tcode{c} +then \tcode{v.translate(c) == v.translate(d)}. +\end{itemdescr} + +\begin{itemdecl} +v.translate_nocase(c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::char_type} + +\pnum +\returns +For all characters \tcode{C} that are to be considered equivalent to \tcode{c} +when comparisons are to be performed without regard to case, +then \tcode{v.translate_nocase(c) == v.translate_nocase(C)}. +\end{itemdescr} + +\begin{itemdecl} +v.transform(F1, F2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result \tcode{X::string_type} - & \tcode{basic_string} - & - \\ \rowsep -\tcode{X::locale_type} - & A copy constructible type - & A type that represents the locale used by the traits class. \indextext{locale} - \\ \rowsep + +\pnum +\returns +A sort key for the character sequence designated by +the iterator range \range{F1}{F2} such that +if the character sequence \range{G1}{G2} sorts before +the character sequence \range{H1}{H2} +then \tcode{v.transform(G1, G2) < v.transform(H1, H2)}. +\end{itemdescr} + +\begin{itemdecl} +v.transform_primary(F1, F2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\indextext{regular expression traits!\idxcode{transform_primary}}% +\indextext{transform_primary@\tcode{transform_primary}!regular expression traits}% +\result +\tcode{X::string_type} + +\pnum +\returns +A sort key for the character sequence designated by +the iterator range \range{F1}{F2} such that +if the character sequence \range{G1}{G2} sorts before +the character sequence \range{H1}{H2} +when character case is not considered +then \tcode{v.transform_primary(G1, G2) < v.transform_primary(H1, H2)}. +\end{itemdescr} + +\begin{itemdecl} +v.lookup_collatename(F1, F2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::string_type} + +\pnum +\returns +A sequence of characters that represents the collating element +consisting of the character sequence designated by +the iterator range \range{F1}{F2}. +Returns an empty string +if the character sequence is not a valid collating element. +\end{itemdescr} + +\begin{itemdecl} +v.lookup_classname(F1, F2, b) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result \tcode{X::char_class_type} - & A bitmask type\iref{bitmask.types}. - & A bitmask type representing a particular character classification. - \\ \rowsep -\tcode{X::length(p)} - & \tcode{size_t} - & Yields the smallest \tcode{i} such that \tcode{p[i] == 0}. Complexity is - linear in \tcode{i}. - \\ \rowsep -\tcode{v.translate(c)} - & \tcode{X::char_type} - & Returns a character such that for any character \tcode{d} that is to - be considered equivalent to \tcode{c} then \tcode{v.translate(c) == v.translate(d)}. - \\ \rowsep -\tcode{v.translate_nocase(c)} - & \tcode{X::char_type} - & For all characters \tcode{C} that are to be considered equivalent - to \tcode{c} when comparisons are to be performed without regard to - case, then \tcode{v.translate_nocase(c) == v.translate_nocase(C)}. - \\ \rowsep -\tcode{v.transform(F1, F2)} - & \tcode{X::string_type} - & Returns a sort key for the character sequence designated by the - iterator range \range{F1}{F2} such that if the character sequence - \range{G1}{G2} sorts before the character sequence \range{H1}{H2} - then \tcode{v.transform(G1, G2) < v.transform(H1, H2)}. - \\ \rowsep -\tcode{v.transform_primary(F1, F2)} - & \tcode{X::string_type} - & Returns a sort key for the character sequence designated by the - iterator range \range{F1}{F2} such that if the character sequence - \range{G1}{G2} sorts before the character sequence \range{H1}{H2} - when character case is not considered - then \tcode{v.transform_primary(G1, G2) < v.transform_primary(H1, H2)}. - \indextext{regular expression traits!\idxcode{transform_primary}}% - \indextext{transform_primary@\tcode{transform_primary}!regular expression traits}% - \\ \rowsep -\tcode{v.lookup_collatename(F1, F2)} - & \tcode{X::string_type} - & Returns a sequence of characters that represents the collating element - consisting of the character sequence designated by the iterator range - \range{F1}{F2}. Returns an empty string if the character sequence is not - a valid collating element. - \\ \rowsep -\tcode{v.lookup_classname(F1, F2, b)} - & \tcode{X::char_class_type} - & Converts the character sequence designated by the iterator range - \range{F1}{F2} into a value of a bitmask type that can - subsequently be passed to \tcode{isctype}. Values returned from - \tcode{lookup_classname} can be bitwise \logop{OR}'ed together; the - resulting value represents membership in either of the - corresponding character classes. - If \tcode{b} is \tcode{true}, the returned bitmask is suitable for - matching characters without regard to their case. - Returns \tcode{0} if the character - sequence is not the name of a character class recognized by - \tcode{X}. The value returned shall be independent of the case of - the characters in the sequence. - \\ \rowsep -\tcode{v.isctype(c, cl)} - & \tcode{bool} - & Returns \tcode{true} if character \tcode{c} is a member of - one of the character classes designated by \tcode{cl}, - \tcode{false} otherwise. - \\ \rowsep -\tcode{v.value(c, I)} - & \tcode{int} - & Returns the value represented by the digit \textit{c} in base - \textit{I} if the character \textit{c} is a valid digit in base \textit{I}; - otherwise returns \tcode{-1}. -\begin{tailnote} -The value of \textit{I} will only - be 8, 10, or 16. -\end{tailnote} - \\ \rowsep -\tcode{u.imbue(loc)} - & \tcode{X::locale_type} - & Imbues \tcode{u} with the locale \tcode{loc} and returns the previous locale - used by \tcode{u} if any. \indextext{locale}% - \\ \rowsep -\tcode{v.getloc()} - & \tcode{X::locale_type} - & Returns the current locale used by \tcode{v}, if any. \indextext{locale}% - \\ -\end{libreqtab3} + +\pnum +\returns +Converts the character sequence designated by the iterator range +\range{F1}{F2} into a value of a bitmask type that can +subsequently be passed to \tcode{isctype}. +Values returned from \tcode{lookup_classname} can be bitwise \logop{OR}'ed together; +the resulting value represents membership +in either of the corresponding character classes. +If \tcode{b} is \tcode{true}, the returned bitmask is suitable for +matching characters without regard to their case. +Returns \tcode{0} +if the character sequence is not the name of +a character class recognized by \tcode{X}. +The value returned shall be independent of +the case of the characters in the sequence. +\end{itemdescr} + +\begin{itemdecl} +v.isctype(c, cl) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\returns +Returns \tcode{true} if character \tcode{c} is a member of +one of the character classes designated by \tcode{cl}, +\tcode{false} otherwise. +\end{itemdescr} + +\begin{itemdecl} +v.value(c, I) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{int} + +\pnum +\returns +Returns the value represented by the digit \textit{c} in base +\textit{I} if the character \textit{c} is a valid digit in base \textit{I}; +otherwise returns \tcode{-1}. +\begin{note} +The value of \textit{I} will only be 8, 10, or 16. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +u.imbue(loc) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::locale_type} + +\indextext{locale}% +\pnum +\effects +Imbues \tcode{u} with the locale \tcode{loc} and +returns the previous locale used by \tcode{u} if any. +\end{itemdescr} + +\begin{itemdecl} +v.getloc() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::locale_type} + +\pnum +\returns +Returns the current locale used by \tcode{v}, if any. \indextext{locale}% +\end{itemdescr} \pnum \begin{note} From 93ff092d1cd2b335f372b9546365b3d495caf2d8 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 14 Nov 2021 20:05:03 +0100 Subject: [PATCH 077/182] [container.requirements] Replace requirements tables with \itemdescr and adjust cross-references to container requirements tables throughout the standard library. --- source/containers.tex | 7828 ++++++++++++++++++++++++++-------------- source/diagnostics.tex | 8 +- source/strings.tex | 2 +- 3 files changed, 5036 insertions(+), 2802 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index c8abbf38f6..b5a4e8b4a0 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -31,10 +31,10 @@ \end{libsumtab} -\rSec1[container.requirements]{Container requirements}% +\rSec1[container.requirements]{Requirements}% \indextext{requirements!container} -\rSec2[container.requirements.general]{General container requirements} +\rSec2[container.requirements.pre]{Preamble} \pnum Containers are objects that store other objects. @@ -54,7 +54,7 @@ \end{example} \pnum -Allocator-aware containers (\tref{container.alloc.req}) +Allocator-aware containers\iref{container.alloc.reqmts} other than \tcode{basic_string} construct elements using the function \tcode{allocator_traits::rebind_traits::\brk{}construct} and destroy elements using the function @@ -69,10 +69,12 @@ aligned buffers and call \tcode{construct} to place the element into the buffer. \end{note} +\rSec2[container.gen.reqmts]{General containers} + +\rSec3[container.requirements.general]{General} + \pnum -In Tables~\ref{tab:container.req}, -\ref{tab:container.rev.req}, and -\ref{tab:container.opt}, +In subclause \ref{container.gen.reqmts}, \begin{itemize} \item \tcode{X} denotes a container class containing objects of type \tcode{T}, @@ -88,6 +90,8 @@ \tcode{rv} denotes a non-const rvalue of type \tcode{X}. \end{itemize} +\rSec3[container.reqmts]{Containers} + % Local command to index names as members of all containers. \newcommand{\indexcont}[1]{% \indexlibrarymisc{#1}{containers}% @@ -106,3109 +110,5318 @@ \indexlibrarymemberx{unordered_multimap}{#1}% } -\begin{libreqtab5} -{Container requirements} -{container.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Operational} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{semantics} & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Operational} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{semantics} & \chdr{pre-/post-condition} & \\ \capsep -\endhead +\pnum +A type \tcode{X} meets the \defn{container} requirements +if the following types, statements, and expressions are well-formed and +have the specified semantics. \indexcont{value_type}% -\tcode{X::value_type} & - \tcode{T} & - & - \expects \tcode{T} is \oldconcept{Erasable} from \tcode{X} (see~\ref{container.requirements.general}, below) & - compile time \\ \rowsep +\begin{itemdecl} +typename X::value_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{T} + +\pnum +\expects +\tcode{T} is \oldconcept{Erasable} from \tcode{X} +(see~\ref{container.alloc.reqmts}, below). +\end{itemdescr} \indexcont{reference}% -\tcode{X::reference} & - \tcode{T\&} & - & - & - compile time \\ \rowsep +\begin{itemdecl} +typename X::reference +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{T\&} +\end{itemdescr} \indexcont{const_reference}% -\tcode{X::const_reference} & - \tcode{const T\&} & - & - & - compile time \\ \rowsep +\begin{itemdecl} +typename X::const_reference +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{const T\&} +\end{itemdescr} \indexcont{iterator}% -\tcode{X::iterator} & - iterator type whose value type is \tcode{T} & - & - any iterator category - that meets the forward iterator requirements. - convertible to \tcode{X::const_iterator}. & - compile time \\ \rowsep +\begin{itemdecl} +typename X::iterator +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A type that meets the forward iterator requirements\iref{forward.iterators} +with value type \tcode{T}. +The type \tcode{X::iterator} is convertible to \tcode{X::const_iterator}. +\end{itemdescr} \indexcont{const_iterator}% -\tcode{X::const_iterator} & - constant iterator type whose value type is \tcode{T} & - & - any iterator category - that meets the forward iterator requirements. & - compile time \\ \rowsep +\begin{itemdecl} +typename X::const_iterator +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A type that meets the requirements of a constant iterator and +those of a forward iterator with value type \tcode{T}. +\end{itemdescr} \indexcont{difference_type}% -\tcode{X::dif\-ference_type} & - signed integer type & - & - is identical to the difference type of \tcode{X::iterator} and \tcode{X::const_iterator} & - compile time \\ \rowsep +\begin{itemdecl} +typename X::difference_type +\end{itemdecl} -\indexcont{size_type}% -\tcode{X::size_type} & - unsigned integer type & - & - \tcode{size_type} can represent any non-negative value of \tcode{difference_type} & - compile time \\ \rowsep - -\tcode{X u;} & - & - & - \ensures \tcode{u.empty()} & - constant \\ \rowsep - -\tcode{X()} & - & - & - \ensures \tcode{X().empty()} & - constant \\ \rowsep - -\tcode{X(a)} & - & - & - \expects \tcode{T} is \oldconcept{CopyInsertable} - into \tcode{X} (see below).\br \ensures \tcode{a == X(a)}. & - linear \\ \rowsep - -\tcode{X u(a);}\br -\tcode{X u = a;} & - & - & - \expects \tcode{T} is \oldconcept{CopyInsertable} - into \tcode{X} (see below).\br - \ensures \tcode{u == a} & - linear \\ \rowsep - -\tcode{X u(rv);}\br -\tcode{X u = rv;} & - & - & - \ensures \tcode{u} is equal to the value that \tcode{rv} had before this construction - & - (Note B) \\ \rowsep - -\tcode{a = rv} & - \tcode{X\&} & - All existing elements of \tcode{a} are either move assigned to or destroyed & - \ensures If \tcode{a} and \tcode{rv} do not refer to the same object, - \tcode{a} is equal to the value that \tcode{rv} - had before this assignment. & - linear \\ \rowsep - -\tcode{a.\~X()} & - \keyword{void} & - & - \effects destroys every element of \tcode{a}; any memory obtained is deallocated. & - linear \\ \rowsep +\begin{itemdescr} +\pnum +\result +A signed integer type, +identical to the difference type of +\tcode{X::iterator} and \tcode{X::const_iterator}. +\end{itemdescr} -\indexcont{begin}% -\tcode{a.begin()} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{a} & - & - & - constant \\ \rowsep +\indexcont{size_type}% +\begin{itemdecl} +typename X::size_type +\end{itemdecl} -\indexcont{end}% -\tcode{a.end()} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{a} & - & - & - constant \\ \rowsep +\begin{itemdescr} +\pnum +\result +An unsigned integer type +that can represent any non-negative value of \tcode{X::difference_type}. +\end{itemdescr} -\indexcont{cbegin}% -\tcode{a.cbegin()} & - \tcode{const_iterator} & - \tcode{const_cast<\brk{}X const\&\brk{}>(a)\brk{}.begin();} & - & - constant \\ \rowsep +\begin{itemdecl}{} +X u; +X u = X(); +\end{itemdecl} -\indexcont{cend}% -\tcode{a.cend()} & - \tcode{const_iterator} & - \tcode{const_cast<\brk{}X const\&\brk{}>(a)\brk{}.end();} & - & - constant \\ \rowsep - -\tcode{i <=> j} & - \tcode{strong_ordering} & - & - \constraints \tcode{X::iterator} meets the random access iterator requirements. & - constant \\ \rowsep +\begin{itemdescr} +\pnum +\ensures +\tcode{u.empty()} -\indexcont{operator==}% -\tcode{a == b} & - convertible to \tcode{bool} & - \tcode{==} is an equivalence relation. - \tcode{equal(\brk{}a.begin(), a.end(), b.begin(), b.end())} & - \expects \tcode{T} meets the \oldconcept{\-Equal\-ity\-Compar\-a\-ble} requirements & - Constant if \tcode{a.size() != b.size()}, - linear otherwise \\ \rowsep +\pnum +\complexity +Constant. +\end{itemdescr} -\indexcont{operator!=}% -\tcode{a != b} & - convertible to \tcode{bool} & - Equivalent to \tcode{!(a == b)} & - & - linear \\ \rowsep +\begin{itemdecl} +X u(a); +X u = a; +\end{itemdecl} -\indexcont{swap}% -\tcode{a.swap(b)} & - \keyword{void} & - & - \effects exchanges the contents of \tcode{a} and \tcode{b} & - (Note A) \\ \rowsep - -\tcode{swap(a, b)} & - \keyword{void} & - Equivalent to \tcode{a.swap(b)} & - & - (Note A) \\ \rowsep +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X} (see below). -\indexcont{operator=}% -\tcode{r = a} & - \tcode{X\&} & - & - \ensures \tcode{r == a}. & - linear \\ \rowsep +\pnum +\ensures +\tcode{u == a} -\indexcont{size}% -\tcode{a.size()} & - \tcode{size_type} & - \tcode{distance(\brk{}a.begin(), a.end())} & - & - constant \\ \rowsep +\pnum +\complexity +Linear. +\end{itemdescr} -\indexcont{max_size}% -\tcode{a.max_size()} & - \tcode{size_type} & - \tcode{distance(\brk{}begin(), end())} - for the largest possible container & - & - constant \\ \rowsep +\begin{itemdecl} +X u(rv); +X u = rv; +\end{itemdecl} -\indexcont{empty}% -\tcode{a.empty()} & - convertible to \tcode{bool} & - \tcode{a.begin() == a.end()} & - & -constant \\ +\begin{itemdescr} +\pnum +\ensures +\tcode{u} is equal to the value that \tcode{rv} had before this construction. -\end{libreqtab5} +\pnum +\complexity +Linear for \tcode{array} and constant for all other standard containers. +\end{itemdescr} -Those entries marked ``(Note A)'' or ``(Note B)'' -have linear complexity for \tcode{array} and have constant complexity -for all other standard containers. -\begin{note} -The algorithm \tcode{equal} is defined in \ref{algorithms}. -\end{note} +\begin{itemdecl} +a = rv +\end{itemdecl} +\begin{itemdescr} \pnum -The member function \tcode{size()} returns the number of elements in the container. -The number of elements is defined by the rules of -constructors, inserts, and erases. +\result +\tcode{X\&}. \pnum -\tcode{begin()} -returns an iterator referring to the first element in the container. -\tcode{end()} -returns an iterator which is the past-the-end value for the container. -If the container is empty, then -\tcode{begin() == end()}. +\effects +All existing elements of \tcode{a} are either move assigned to or destroyed. \pnum -In the expressions -\begin{codeblock} -i == j -i != j -i < j -i <= j -i >= j -i > j -i <=> j -i - j -\end{codeblock} -where \tcode{i} and \tcode{j} denote objects of a container's \tcode{iterator} -type, either or both may be replaced by an object of the container's -\tcode{const_iterator} type referring to the same element with no change in semantics. +\ensures +If \tcode{a} and \tcode{rv} do not refer to the same object, +\tcode{a} is equal to the value that \tcode{rv} had before this assignment. \pnum -Unless otherwise specified, all containers defined in this Clause obtain memory -using an allocator (see~\ref{allocator.requirements}). -\begin{note} -In particular, containers and iterators do not store references -to allocated elements other than through the allocator's pointer type, -i.e., as objects of type \tcode{P} or -\tcode{pointer_traits

::template re\-bind<\unspec>}, -where \tcode{P} is \tcode{allocator_traits::pointer}. -\end{note} -Copy constructors for these container types obtain an allocator by calling -\tcode{allocator_traits::select_on_container_copy_construction} -on the allocator belonging to the container being copied. -Move constructors obtain an allocator by move construction from the allocator belonging to -the container being moved. Such move construction of the allocator shall not exit via an -exception. -All other constructors for these container types take a -\tcode{const allocator_type\&} argument. -\begin{note} -If an invocation of a constructor uses the default value of an optional -allocator argument, then the allocator type must support value-initialization. -\end{note} -A copy of this allocator is used for any memory allocation and element construction -performed, by these constructors and by all member functions, -during the lifetime of each container object -or until the allocator is replaced. The allocator may be replaced only via assignment or -\tcode{swap()}. Allocator replacement is performed by -copy assignment, move assignment, or swapping of the allocator only if -\begin{itemize} -\item \tcode{allocator_traits::propagate_on_container_copy_assignment::value}, -\item \tcode{allocator_traits::propagate_on_container_move_assignment::value}, -or -\item \tcode{allocator_traits::propagate_on_container_swap::value} -\end{itemize} -is \tcode{true} -within the implementation of the corresponding container operation. -In all container types defined in this Clause, the member \tcode{get_allocator()} -returns a copy of the allocator used to construct the container or, if that allocator -has been replaced, a copy of the most recent replacement. +\complexity +Linear. +\end{itemdescr} + +\begin{itemdecl} +a.~X() +\end{itemdecl} +\begin{itemdescr} \pnum -The expression \tcode{a.swap(b)}, for containers \tcode{a} and \tcode{b} of a standard -container type other than \tcode{array}, shall exchange the values of \tcode{a} and -\tcode{b} without invoking any move, copy, or swap operations on the individual -container elements. -Lvalues of any \tcode{Compare}, \tcode{Pred}, or \tcode{Hash} types -belonging to \tcode{a} and \tcode{b} shall be swappable -and shall be exchanged by calling \tcode{swap} -as described in~\ref{swappable.requirements}. If -\tcode{allocator_traits::propagate_on_container_swap::value} is -\tcode{true}, then -lvalues of type \tcode{allocator_type} shall be swappable and -the allocators of \tcode{a} and \tcode{b} shall also be exchanged -by calling \tcode{swap} as described in~\ref{swappable.requirements}. -Otherwise, the allocators shall not be swapped, and the behavior is -undefined unless \tcode{a.get_allocator() == b.get_allocator()}. Every iterator -referring to an element in one container before the swap shall refer to the same -element in the other container after the swap. It is unspecified whether an iterator -with value \tcode{a.end()} before the swap will have value \tcode{b.end()} after the -swap. +\result +\keyword{void} \pnum -\indextext{reversible container|see{container, reversible}}% -If the iterator type of a container belongs to the bidirectional or -random access iterator categories\iref{iterator.requirements}, -the container is called -\defnx{reversible}{container!reversible} -and meets the additional requirements -in \tref{container.rev.req}. +\effects +Destroys every element of \tcode{a}; any memory obtained is deallocated. -% Local command to index names as members of all containers. -\renewcommand{\indexcont}[1]{% -\indexlibrarymisc{#1}{reversible containers}% -\indexlibrarymemberx{array}{#1}% -\indexlibrarymemberx{deque}{#1}% -\indexlibrarymemberx{list}{#1}% -\indexlibrarymemberx{vector}{#1}% -\indexlibrarymemberx{map}{#1}% -\indexlibrarymemberx{set}{#1}% -\indexlibrarymemberx{multiset}{#1}% -\indexlibrarymemberx{multimap}{#1}% -\indexlibrarymemberx{unordered_map}{#1}% -\indexlibrarymemberx{unordered_set}{#1}% -\indexlibrarymemberx{unordered_multiset}{#1}% -\indexlibrarymemberx{unordered_multimap}{#1}% -} +\pnum +\complexity +Linear. +\end{itemdescr} -\begin{libreqtab4a} -{Reversible container requirements} -{container.rev.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endhead -\indexcont{reverse_iterator}% -\tcode{X::reverse_iterator} & -iterator type whose value type is \tcode{T} & - \tcode{reverse_iterator} & - compile time \\ \rowsep -\indexcont{const_reverse_iterator}% -\tcode{X::const_reverse_iterator} & - constant iterator type whose value type is \tcode{T} & - \tcode{reverse_iterator} & - compile time \\ \rowsep -\indexcont{rbegin}% -\tcode{a.rbegin()} & - \tcode{reverse_iterator; const_reverse_iterator} for constant \tcode{a} & - \tcode{reverse_iterator(end())} & - constant \\ \rowsep -\indexcont{rend}% -\tcode{a.rend()} & - \tcode{reverse_iterator; const_reverse_iterator} for constant \tcode{a} & - \tcode{reverse_iterator(begin())} & - constant \\ \rowsep -\indexcont{crbegin}% -\tcode{a.crbegin()} & - \tcode{const_reverse_iterator} & - \tcode{const_cast(a).rbegin()} & - constant \\ \rowsep -\indexcont{crend}% -\tcode{a.crend()} & - \tcode{const_reverse_iterator} & - \tcode{const_cast(a).rend()} & - constant \\ -\end{libreqtab4a} +\indexcont{begin}% +\begin{itemdecl} +a.begin() +\end{itemdecl} +\begin{itemdescr} \pnum -Unless otherwise specified (see~\ref{associative.reqmts.except}, \ref{unord.req.except}, \ref{deque.modifiers}, and -\ref{vector.modifiers}) -all container types defined in this Clause meet -the following additional requirements: - -\begin{itemize} -\item -if an exception is thrown by an -\tcode{insert()} or \tcode{emplace()} -function while inserting a single element, that -function has no effects. -\item -if an exception is thrown by a -\tcode{push_back()}, -\tcode{push_front()}, -\tcode{emplace_back()}, or \tcode{emplace_front()} -function, that function has no effects. -\item -no -\tcode{erase()}, -\tcode{clear()}, -\tcode{pop_back()} -or -\tcode{pop_front()} -function throws an exception. -\item -no copy constructor or assignment operator of a returned iterator -throws an exception. -\item -no -\tcode{swap()} -function throws an exception. -\item -no -\tcode{swap()} -function invalidates any references, -pointers, or iterators referring to the elements -of the containers being swapped. -\begin{note} -The \tcode{end()} iterator does not refer to any element, so it can be invalidated. -\end{note} -\end{itemize} +\result +\tcode{iterator}; +\tcode{const_iterator} for constant \tcode{a}. \pnum -Unless otherwise specified (either explicitly or by defining a -function in terms of other functions), invoking a container member -function or passing a container as an argument to a library function -shall not invalidate iterators to, or change the values of, objects -within that container. +\cvalue +An iterator referring to the first element in the container. \pnum -A \defnadj{contiguous}{container} -is a container -whose member types \tcode{iterator} and \tcode{const_iterator} -meet the -\oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators} and -model \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}. +\complexity +Constant. +\end{itemdescr} + +\indexcont{end}% +\begin{itemdecl} +a.end() +\end{itemdecl} +\begin{itemdescr} \pnum -\tref{container.opt} lists operations that are provided -for some types of containers but not others. Those containers for which the -listed operations are provided shall implement the semantics described in -\tref{container.opt} unless otherwise stated. -If the iterators passed to \tcode{lexicographical_compare_three_way} -meet the constexpr iterator requirements\iref{iterator.requirements.general} -then the operations described in \tref{container.opt} -are implemented by constexpr functions. +\result +\tcode{iterator}; +\tcode{const_iterator} for constant \tcode{a}. -\begin{libreqtab5} -{Optional container operations} -{container.opt} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Operational} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{semantics} & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Operational} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{semantics} & \chdr{pre-/post-condition} & \\ \capsep -\endhead - -\tcode{a <=> b} & - \tcode{\placeholdernc{synth-three-\brk{}way-result}\brk{}} & - \tcode{lexicographical_compare_three_way(a.begin(), a.end(), - b.begin(), b.end(), \placeholdernc{synth-three-way})} & - \expects - Either \tcode{<=>} is defined for values of type (possibly const) \tcode{T}, - or \tcode{<} is defined for values of type (possibly const) \tcode{T} and - \tcode{<} is a total ordering relationship. & - linear \\ -\end{libreqtab5} +\pnum +\cvalue +An iterator which is the past-the-end value for the container. -\begin{note} -The algorithm \tcode{lexicographical_compare_three_way} -is defined in \ref{algorithms}. -\end{note} +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexcont{cbegin}% +\begin{itemdecl} +a.cbegin() +\end{itemdecl} +\begin{itemdescr} \pnum -All of the containers defined in this Clause and in~\ref{basic.string} except \tcode{array} -meet the additional requirements of an allocator-aware container, as described in -\tref{container.alloc.req}. +\result +\tcode{const_iterator}. \pnum -Given an allocator type \tcode{A} -and given a container type \tcode{X} having a \tcode{value_type} identical to \tcode{T} -and an \tcode{allocator_type} identical to \tcode{allocator_traits::rebind_alloc} -and given an lvalue \tcode{m} of type \tcode{A}, -a pointer \tcode{p} of type \tcode{T*}, -an expression \tcode{v} of type (possibly \keyword{const}) \tcode{T}, -and an rvalue \tcode{rv} of type \tcode{T}, -the following terms are defined. If \tcode{X} -is not allocator-aware or is a specialization of \tcode{basic_string}, -the terms below are defined as if \tcode{A} were -\tcode{allocator} --- no allocator object needs to be created -and user specializations of \tcode{allocator} are not instantiated: +\cvalue +\tcode{const_cast(a).begin()} -\begin{itemize} -\item -\tcode{T} is \defnx{\oldconcept{DefaultInsertable} into \tcode{X}} -{\oldconceptname{DefaultInsertable} into X@\oldconcept{DefaultInsertable} into \tcode{X}} -means that the following expression is well-formed: -\begin{codeblock} -allocator_traits::construct(m, p) -\end{codeblock} +\pnum +\complexity +Constant. +\end{itemdescr} -\item -An element of \tcode{X} is \defn{default-inserted} if it is initialized -by evaluation of the expression -\begin{codeblock} -allocator_traits::construct(m, p) -\end{codeblock} -where \tcode{p} is the address of the uninitialized storage for the element -allocated within \tcode{X}. +\indexcont{cend}% +\begin{itemdecl} +a.cend() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{const_iterator}. + +\pnum +\cvalue +\tcode{const_cast(a).end()} + +\pnum +\complexity +Constant. +\end{itemdescr} + +\begin{itemdecl} +i <=> j +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{strong_ordering}. + +\pnum +\constraints +\tcode{X::iterator} meets the random access iterator requirements. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexcont{operator==}% +\begin{itemdecl} +a == b +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} meets the \oldconcept{EqualityComparable} requirements. + +\pnum +\result +Convertible to \tcode{bool}. + +\pnum +\cvalue +\tcode{equal(a.begin(), a.end(), b.begin(), b.end())} -\item -\tcode{T} is \defnx{\oldconcept{MoveInsertable} into \tcode{X}} -{\oldconceptname{MoveInsertable} into X@\oldconcept{MoveInsertable} into \tcode{X}} -means that the following expression -is well-formed: -\begin{codeblock} -allocator_traits::construct(m, p, rv) -\end{codeblock} -and its evaluation causes the following postcondition to hold: The value -of \tcode{*p} is equivalent to the value of \tcode{rv} before the evaluation. \begin{note} -\tcode{rv} remains a valid object. Its state is unspecified +The algorithm \tcode{equal} is defined in \ref{alg.equal}. \end{note} -\item -\tcode{T} is \defnx{\oldconcept{CopyInsertable} into \tcode{X}} -{\oldconceptname{CopyInsertable} into X@\oldconcept{CopyInsertable} into \tcode{X}} -means that, in addition to \tcode{T} being \oldconcept{MoveInsertable} into -\tcode{X}, the following expression is well-formed: -\begin{codeblock} -allocator_traits::construct(m, p, v) -\end{codeblock} -and its evaluation causes the following postcondition to hold: -The value of \tcode{v} is unchanged and is equivalent to \tcode{*p}. +\pnum +\complexity +Constant if \tcode{a.size() != b.size()}, linear otherwise. -\item -\tcode{T} is -\defnx{\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}} -{\oldconceptname{EmplaceConstructible} into X from args@\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}}, -for zero -or more arguments \tcode{args}, means that the following expression is well-formed: -\begin{codeblock} -allocator_traits::construct(m, p, args) -\end{codeblock} +\pnum +\remarks +\tcode{==} is an equivalence relation. +\end{itemdescr} -\item -\tcode{T} is -\defnx{\oldconcept{Erasable} from \tcode{X}} -{\oldconceptname{Erasable} from X@\oldconcept{Erasable} from \tcode{X}} -means that the following expression is well-formed: +\indexcont{operator!=}% +\begin{itemdecl} +a != b +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{!(a == b)}. +\end{itemdescr} + +\indexcont{swap}% +\begin{itemdecl} +a.swap(b) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\effects +Exchanges the contents of \tcode{a} and \tcode{b}. + +\pnum +\complexity +Linear for \tcode{array} and constant for all other standard containers. +\end{itemdescr} + +\begin{itemdecl} +swap(a, b) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\effects +Equivalent to \tcode{a.swap(b)}. +\end{itemdescr} + +\indexcont{operator=}% +\begin{itemdecl} +r = a +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X\&}. + +\pnum +\ensures +\tcode{r == a}. + +\pnum +\complexity +Linear. +\end{itemdescr} + +\indexcont{size}% +\begin{itemdecl} +a.size() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type}. + +\pnum +\cvalue +\tcode{distance(a.begin(), a.end())}, +i.e. the number of elements in the container. + +\pnum +\complexity +Constant. + +\pnum +\remarks +The number of elements is defined by the rules of +constructors, inserts, and erases. +\end{itemdescr} + +\indexcont{max_size}% +\begin{itemdecl} +a.max_size() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type}. + +\pnum +\returns +\tcode{distance(begin(), end())} for the largest possible container. + +\complexity +Constant. +\end{itemdescr} + +\indexcont{empty}% +\begin{itemdecl} +a.empty() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Convertible to \tcode{bool}. + +\pnum +\cvalue +\tcode{a.begin() == a.end()} + +\pnum +\complexity +Constant. + +\pnum +\remarks +If the container is empty, then \tcode{a.empty()} is true. +\end{itemdescr} + +\pnum +In the expressions \begin{codeblock} -allocator_traits::destroy(m, p) +i == j +i != j +i < j +i <= j +i >= j +i > j +i <=> j +i - j \end{codeblock} -\end{itemize} +where \tcode{i} and \tcode{j} denote objects of a container's \tcode{iterator} +type, either or both may be replaced by an object of the container's +\tcode{const_iterator} type referring to the same element with no change in semantics. + +\pnum +Unless otherwise specified, all containers defined in this Clause obtain memory +using an allocator (see~\ref{allocator.requirements}). +\begin{note} +In particular, containers and iterators do not store references +to allocated elements other than through the allocator's pointer type, +i.e., as objects of type \tcode{P} or +\tcode{pointer_traits

::template re\-bind<\unspec>}, +where \tcode{P} is \tcode{allocator_traits::pointer}. +\end{note} +Copy constructors for these container types obtain an allocator by calling +\tcode{allocator_traits::select_on_container_copy_construction} +on the allocator belonging to the container being copied. +Move constructors obtain an allocator by move construction from the allocator belonging to +the container being moved. Such move construction of the allocator shall not exit via an +exception. +All other constructors for these container types take a +\tcode{const allocator_type\&} argument. +\begin{note} +If an invocation of a constructor uses the default value of an optional +allocator argument, then the allocator type must support value-initialization. +\end{note} +A copy of this allocator is used for any memory allocation and element construction +performed, by these constructors and by all member functions, +during the lifetime of each container object +or until the allocator is replaced. The allocator may be replaced only via assignment or +\tcode{swap()}. Allocator replacement is performed by +copy assignment, move assignment, or swapping of the allocator only if +\begin{itemize} +\item \tcode{allocator_traits::propagate_on_container_copy_assignment::value}, +\item \tcode{allocator_traits::propagate_on_container_move_assignment::value}, +or +\item \tcode{allocator_traits::propagate_on_container_swap::value} +\end{itemize} +is \tcode{true} +within the implementation of the corresponding container operation. +In all container types defined in this Clause, the member \tcode{get_allocator()} +returns a copy of the allocator used to construct the container or, if that allocator +has been replaced, a copy of the most recent replacement. + +\pnum +The expression \tcode{a.swap(b)}, for containers \tcode{a} and \tcode{b} of a standard +container type other than \tcode{array}, shall exchange the values of \tcode{a} and +\tcode{b} without invoking any move, copy, or swap operations on the individual +container elements. +Lvalues of any \tcode{Compare}, \tcode{Pred}, or \tcode{Hash} types +belonging to \tcode{a} and \tcode{b} shall be swappable +and shall be exchanged by calling \tcode{swap} +as described in~\ref{swappable.requirements}. If +\tcode{allocator_traits::propagate_on_container_swap::value} is +\tcode{true}, then +lvalues of type \tcode{allocator_type} shall be swappable and +the allocators of \tcode{a} and \tcode{b} shall also be exchanged +by calling \tcode{swap} as described in~\ref{swappable.requirements}. +Otherwise, the allocators shall not be swapped, and the behavior is +undefined unless \tcode{a.get_allocator() == b.get_allocator()}. Every iterator +referring to an element in one container before the swap shall refer to the same +element in the other container after the swap. It is unspecified whether an iterator +with value \tcode{a.end()} before the swap will have value \tcode{b.end()} after the +swap. + +\rSec3[container.rev.reqmts]{Reversible container requirements} + +% Local command to index names as members of all containers. +\renewcommand{\indexcont}[1]{% +\indexlibrarymisc{#1}{reversible containers}% +\indexlibrarymemberx{array}{#1}% +\indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{list}{#1}% +\indexlibrarymemberx{vector}{#1}% +\indexlibrarymemberx{map}{#1}% +\indexlibrarymemberx{set}{#1}% +\indexlibrarymemberx{multiset}{#1}% +\indexlibrarymemberx{multimap}{#1}% +\indexlibrarymemberx{unordered_map}{#1}% +\indexlibrarymemberx{unordered_set}{#1}% +\indexlibrarymemberx{unordered_multiset}{#1}% +\indexlibrarymemberx{unordered_multimap}{#1}% +} + +\pnum +A type \tcode{X} meets the \defnadj{reversible}{container} requirements if +\tcode{X} meets the container requirements, +the iterator type of \tcode{X} belongs to the +bidirectional or random access iterator categories\iref{iterator.requirements}, +and +the following types and expressions are well-formed and have +the specified semantics. + +\indexcont{reverse_iterator}% +\begin{itemdecl} +typename X::reverse_iterator +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +The type \tcode{reverse_iterator}, +an iterator type whose value type is \tcode{T}. +\end{itemdescr} + +\indexcont{const_reverse_iterator}% +\begin{itemdecl} +typename X::const_reverse_iterator +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +The type \tcode{reverse_iterator}, +a constant iterator type whose value type is \tcode{T}. +\end{itemdescr} + +\indexcont{rbegin}% +\begin{itemdecl} +a.rbegin() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reverse_iterator}; +\tcode{const_reverse_iterator} for constant \tcode{a}. + +\pnum +\cvalue +\tcode{reverse_iterator(end())} + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexcont{rend}% +\begin{itemdecl} +a.rend() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reverse_iterator}; +\tcode{const_reverse_iterator} for constant \tcode{a}. + +\pnum +\cvalue +\tcode{reverse_iterator(begin())} + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexcont{crbegin}% +\begin{itemdecl} +a.crbegin() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{const_reverse_iterator}. + +\pnum +\cvalue +\tcode{\keyword{const_cast}(a).rbegin()} + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexcont{crend}% +\begin{itemdecl} +a.crend() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{const_reverse_iterator}. + +\pnum +\cvalue +\tcode{\keyword{const_cast}(a).rend()} + +\pnum +\complexity +Constant. +\end{itemdescr} + +\pnum +Unless otherwise specified (see~\ref{associative.reqmts.except}, \ref{unord.req.except}, \ref{deque.modifiers}, and +\ref{vector.modifiers}) +all container types defined in this Clause meet +the following additional requirements: + +\begin{itemize} +\item +if an exception is thrown by an +\tcode{insert()} or \tcode{emplace()} +function while inserting a single element, that +function has no effects. +\item +if an exception is thrown by a +\tcode{push_back()}, +\tcode{push_front()}, +\tcode{emplace_back()}, or \tcode{emplace_front()} +function, that function has no effects. +\item +no +\tcode{erase()}, +\tcode{clear()}, +\tcode{pop_back()} +or +\tcode{pop_front()} +function throws an exception. +\item +no copy constructor or assignment operator of a returned iterator +throws an exception. +\item +no +\tcode{swap()} +function throws an exception. +\item +no +\tcode{swap()} +function invalidates any references, +pointers, or iterators referring to the elements +of the containers being swapped. +\begin{note} +The \tcode{end()} iterator does not refer to any element, so it can be invalidated. +\end{note} +\end{itemize} + +\pnum +Unless otherwise specified (either explicitly or by defining a +function in terms of other functions), invoking a container member +function or passing a container as an argument to a library function +shall not invalidate iterators to, or change the values of, objects +within that container. + +\pnum +A \defnadj{contiguous}{container} +is a container +whose member types \tcode{iterator} and \tcode{const_iterator} +meet the +\oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators} and +model \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}. + +\rSec3[container.opt.reqmts]{Optional container requirements} + +\pnum +The following operations are provided +for some types of containers but not others. Those containers for which the +listed operations are provided shall implement the semantics as described +unless otherwise stated. +If the iterators passed to \tcode{lexicographical_compare_three_way} +meet the constexpr iterator requirements\iref{iterator.requirements.general} +then the operations described below +are implemented by constexpr functions. + +\begin{itemdecl} +a <=> b +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{\exposid{synth-three-way-result}}. + +\pnum +\expects +Either \tcode{<=>} is defined for values of type (possibly const) \tcode{T}, +or \tcode{<} is defined for values of type (possibly const) \tcode{T} and +\tcode{<} is a total ordering relationship. + +\pnum +\cvalue +\tcode{lexicographical_compare_three_way(a.begin(), a.end(), +b.begin(), b.end(),\newline \exposidnc{synth-three-way})} +\begin{note} +The algorithm \tcode{lexicographical_compare_three_way} +is defined in \ref{algorithms}. +\end{note} + +\pnum +\complexity +Linear. +\end{itemdescr} + +\rSec3[container.alloc.reqmts]{Allocator-aware containers} + +\pnum +All of the containers defined in \ref{containers} and in~\ref{basic.string} except \tcode{array} +meet the additional requirements of an \defnadj{allocator-aware}{container}, +as described below. + +\pnum +Given an allocator type \tcode{A} +and given a container type \tcode{X} having a \tcode{value_type} identical to \tcode{T} +and an \tcode{allocator_type} identical to \tcode{allocator_traits::rebind_alloc} +and given an lvalue \tcode{m} of type \tcode{A}, +a pointer \tcode{p} of type \tcode{T*}, +an expression \tcode{v} of type (possibly \keyword{const}) \tcode{T}, +and an rvalue \tcode{rv} of type \tcode{T}, +the following terms are defined. If \tcode{X} +is not allocator-aware or is a specialization of \tcode{basic_string}, +the terms below are defined as if \tcode{A} were +\tcode{allocator} --- no allocator object needs to be created +and user specializations of \tcode{allocator} are not instantiated: + +\begin{itemize} +\item +\tcode{T} is \defnx{\oldconcept{DefaultInsertable} into \tcode{X}} +{\oldconceptname{DefaultInsertable} into X@\oldconcept{DefaultInsertable} into \tcode{X}} +means that the following expression is well-formed: +\begin{codeblock} +allocator_traits::construct(m, p) +\end{codeblock} + +\item +An element of \tcode{X} is \defn{default-inserted} if it is initialized +by evaluation of the expression +\begin{codeblock} +allocator_traits::construct(m, p) +\end{codeblock} +where \tcode{p} is the address of the uninitialized storage for the element +allocated within \tcode{X}. + +\item +\tcode{T} is \defnx{\oldconcept{MoveInsertable} into \tcode{X}} +{\oldconceptname{MoveInsertable} into X@\oldconcept{MoveInsertable} into \tcode{X}} +means that the following expression +is well-formed: +\begin{codeblock} +allocator_traits::construct(m, p, rv) +\end{codeblock} +and its evaluation causes the following postcondition to hold: The value +of \tcode{*p} is equivalent to the value of \tcode{rv} before the evaluation. +\begin{note} +\tcode{rv} remains a valid object. Its state is unspecified +\end{note} + +\item +\tcode{T} is \defnx{\oldconcept{CopyInsertable} into \tcode{X}} +{\oldconceptname{CopyInsertable} into X@\oldconcept{CopyInsertable} into \tcode{X}} +means that, in addition to \tcode{T} being \oldconcept{MoveInsertable} into +\tcode{X}, the following expression is well-formed: +\begin{codeblock} +allocator_traits::construct(m, p, v) +\end{codeblock} +and its evaluation causes the following postcondition to hold: +The value of \tcode{v} is unchanged and is equivalent to \tcode{*p}. + +\item +\tcode{T} is +\defnx{\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}} +{\oldconceptname{EmplaceConstructible} into X from args@\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}}, +for zero +or more arguments \tcode{args}, means that the following expression is well-formed: +\begin{codeblock} +allocator_traits::construct(m, p, args) +\end{codeblock} + +\item +\tcode{T} is +\defnx{\oldconcept{Erasable} from \tcode{X}} +{\oldconceptname{Erasable} from X@\oldconcept{Erasable} from \tcode{X}} +means that the following expression is well-formed: +\begin{codeblock} +allocator_traits::destroy(m, p) +\end{codeblock} +\end{itemize} + +\begin{note} +A container calls \tcode{allocator_traits::construct(m, p, args)} +to construct an element at \tcode{p} using \tcode{args}, +with \tcode{m == get_allocator()}. +The default \tcode{construct} in \tcode{allocator} will +call \tcode{::new((void*)p) T(args)}, +but specialized allocators can choose a different definition. +\end{note} + +\pnum +In this subclause, +\begin{itemize} +\item +\tcode{X} denotes an allocator-aware container class +with a \tcode{value_type} of \tcode{T} using an allocator of type \tcode{A}, +\item +\tcode{u} denotes a variable, +\item +\tcode{a} and \tcode{b} denote non-const lvalues of type \tcode{X}, +\item +\tcode{c} denotes an lvalue of type \tcode{\keyword{const} X}, +\item +\tcode{t} denotes an lvalue or a const rvalue of type \tcode{X}, +\item +\tcode{rv} denotes a non-const rvalue of type \tcode{X}, and +\item +\tcode{m} is a value of type \tcode{A}. +\end{itemize} + +% Local command to index names as members of all containers. +\renewcommand{\indexcont}[1]{% +\indexlibrarymisc{#1}{allocator-aware containers}% +\indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{forward_list}{#1}% +\indexlibrarymemberx{list}{#1}% +\indexlibrarymemberx{vector}{#1}% +\indexlibrarymemberx{map}{#1}% +\indexlibrarymemberx{set}{#1}% +\indexlibrarymemberx{multiset}{#1}% +\indexlibrarymemberx{multimap}{#1}% +\indexlibrarymemberx{unordered_map}{#1}% +\indexlibrarymemberx{unordered_set}{#1}% +\indexlibrarymemberx{unordered_multiset}{#1}% +\indexlibrarymemberx{unordered_multimap}{#1}% +} + +A type \tcode{X} meets the allocator-aware container requirements +if \tcode{X} meets the container requirements and +the following types, statements, and expressions are well-formed and have +the specified semantics. + +\indexcont{allocator_type}% +\begin{itemdecl} +typename X::allocator_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{A} + +\pnum +\expects +\tcode{allocator_type::value_type} is the same as \tcode{X::value_type}. +\end{itemdescr} + +\indexcont{get_allocator}% +\begin{itemdecl} +c.get_allocator() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{A} + +\pnum +\complexity +Constant. +\end{itemdescr} + +\begin{itemdecl} +X u; +X u = X(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{A} meets the \oldconcept{DefaultConstructible} requirements. + +\pnum +\ensures +\tcode{u.empty()} returns \tcode{true}, \tcode{u.get_allocator() == A()}. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\begin{itemdecl} +X u(m); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{u.empty()} returns \tcode{true}, \tcode{u.get_allocator() == m}. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\begin{itemdecl} +X u(t, m); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\ensures +\tcode{u == t}, \tcode{u.get_allocator() == m} + +\pnum +\complexity +Linear. +\end{itemdescr} + +\begin{itemdecl} +X u(rv); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{u} has the same elements as \tcode{rv} had before this construction; +the value of \tcode{u.get_allocator()} is the same as +the value of \tcode{rv.get_allocator()} before this construction. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\begin{itemdecl} +X u(rv, m); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X}. + +\pnum +\ensures +\tcode{u} has the same elements, or copies of the elements, +that \tcode{rv} had before this construction, +\tcode{u.get_allocator() == m}. + +\pnum +\complexity +Constant if \tcode{m == rv.get_allocator()}, otherwise linear. +\end{itemdescr} + +\begin{itemdecl} +a = t +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X\&}. + +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X} and +\oldconcept{CopyAssignable}. + +\pnum +\ensures +\tcode{a == t} is \tcode{true}. + +\pnum +\complexity +Linear. +\end{itemdescr} + +\indexcont{operator=}% +\begin{itemdecl} +a = rv +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X\&}. + +\pnum +\expects +If +\tcode{allocator_traits::propagate_on_container_move_assign\-ment::value} +is \tcode{false}, +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X} and +\oldconcept{MoveAssignable}. + +\pnum +\effects +All existing elements of \tcode{a} are either move assigned to or destroyed. + +\pnum +\ensures +If \tcode{a} and \tcode{rv} do not refer to the same object, +\tcode{a} is equal to the value that \tcode{rv} had before this assignment. + +\pnum +\complexity +Linear. +\end{itemdescr} + +\indexcont{swap}% +\begin{itemdecl} +a.swap(b) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\effects +Exchanges the contents of \tcode{a} and \tcode{b}. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\pnum +The behavior of certain container member functions and deduction guides +depends on whether types qualify as input iterators or allocators. +The extent to which an implementation determines that a type cannot be an input +iterator is unspecified, except that as a minimum integral types shall not qualify +as input iterators. +Likewise, the extent to which an implementation determines that a type cannot be +an allocator is unspecified, except that as a minimum a type \tcode{A} shall not qualify +as an allocator unless it meets both of the following conditions: + +\begin{itemize} +\item The \grammarterm{qualified-id} \tcode{A::value_type} +is valid and denotes a type\iref{temp.deduct}. + +\item The expression \tcode{declval().allocate(size_t\{\})} +is well-formed when treated as an unevaluated operand. +\end{itemize} + +\rSec2[container.requirements.dataraces]{Container data races} + +\pnum +For purposes of avoiding data races\iref{res.on.data.races}, implementations shall +consider the following functions to be \keyword{const}: \tcode{begin}, \tcode{end}, +\tcode{rbegin}, \tcode{rend}, \tcode{front}, \tcode{back}, \tcode{data}, \tcode{find}, +\tcode{lower_bound}, \tcode{upper_bound}, \tcode{equal_range}, \tcode{at} and, except in +associative or unordered associative containers, \tcode{operator[]}. + +\pnum +Notwithstanding~\ref{res.on.data.races}, implementations are required to avoid data +races when the contents of the contained object in different elements in the same +container, excepting \tcode{vector}, are modified concurrently. + +\pnum +\begin{note} +For a \tcode{vector x} with a size greater than one, \tcode{x[1] = 5} +and \tcode{*x.begin() = 10} can be executed concurrently without a data race, but +\tcode{x[0] = 5} and \tcode{*x.begin() = 10} executed concurrently can result in a data +race. +As an exception to the general rule, for a \tcode{vector y}, \tcode{y[0] = true} +can race with \tcode{y[1] = true}. +\end{note} + +\rSec2[sequence.reqmts]{Sequence containers} + +\pnum +A sequence container organizes a finite set of objects, all of the same type, into a strictly +linear arrangement. The library provides four basic kinds of sequence containers: +\tcode{vector}, \tcode{forward_list}, \tcode{list}, and \tcode{deque}. In addition, +\tcode{array} is provided as a sequence container which provides limited sequence operations +because it has a fixed number of elements. The library also provides container adaptors that +make it easy to construct abstract data types, such as \tcode{stack}s or \tcode{queue}s, out of +the basic sequence container kinds (or out of other kinds of sequence containers that the user defines). + +\pnum +\begin{note} +The sequence containers +offer the programmer different complexity trade-offs. +\tcode{vector} +is appropriate in most circumstances. +\tcode{array} +has a fixed size known during translation. +\tcode{list} or \tcode{forward_list} +support frequent insertions and deletions from the +middle of the sequence. +\tcode{deque} +supports efficient insertions and deletions taking place at the beginning or at the +end of the sequence. +When choosing a container, remember \tcode{vector} is best; +leave a comment to explain if you choose from the rest! +\end{note} + +\pnum +In this subclause, +\begin{itemize} +\item +\tcode{X} denotes a sequence container class, +\item +\tcode{a} denotes a value of type \tcode{X} containing elements of type \tcode{T}, +\item +\tcode{u} denotes the name of a variable being declared, +\item +\tcode{A} denotes \tcode{X::allocator_type} if +the \grammarterm{qualified-id} \tcode{X::allocator_type} is valid and denotes a +type\iref{temp.deduct} and +\tcode{allocator} if it doesn't, +\item +\tcode{i} and \tcode{j} +denote iterators that meet the \oldconcept{InputIterator} requirements +and refer to elements implicitly convertible to \tcode{value_type}, +\item +\tcode{[i, j)} denotes a valid range, +\item +\tcode{il} designates an object of type \tcode{initializer_list}, +\item +\tcode{n} denotes a value of type \tcode{X::size_type}, +\item +\tcode{p} denotes a valid constant iterator to \tcode{a}, +\item +\tcode{q} denotes a valid dereferenceable constant iterator to \tcode{a}, +\item +\tcode{[q1, q2)} denotes a valid range of constant iterators in \tcode{a}, +\item +\tcode{t} denotes an lvalue or a const rvalue of \tcode{X::value_type}, and +\item +\tcode{rv} denotes a non-const rvalue of \tcode{X::value_type}. +\item +\tcode{Args} denotes a template parameter pack; +\item +\tcode{args} denotes a function parameter pack with the pattern \tcode{Args\&\&}. +\end{itemize} + +\pnum +The complexities of the expressions are sequence dependent. + +% Local command to index names as members of all containers. +\renewcommand{\indexcont}[1]{% +\indexlibrarymisc{#1}{sequence containers}% +\indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{forward_list}{#1}% +\indexlibrarymemberx{list}{#1}% +\indexlibrarymemberx{vector}{#1}% +} + +\pnum +A type \tcode{X} meets the \defnadj{sequence}{container} requirements +if \tcode{X} meets the container requirements and +the following statements and expressions are well-formed and have +the specified semantics. + +\begin{itemdecl} +X u(n, t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Constructs a sequence container with \tcode{n} copies of \tcode{t}. + +\pnum +\ensures +\tcode{distance(u.begin(), u.end()) == n} is \tcode{true}. +\end{itemdescr} + +\begin{itemdecl} +X u(i, j); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. +For \tcode{vector}, +if the iterator does not meet +the \oldconcept{ForwardIterator} requirements\iref{forward.iterators}, +\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}. + +\pnum +\effects +Constructs a sequence container equal to the range \tcode{[i, j)}. +Each iterator in the range \range{i}{j} is dereferenced exactly once. + +\pnum +\ensures +\tcode{distance(u.begin(), u.end()) == distance(i, j)} is \tcode{true}. +\end{itemdescr} + +\begin{itemdecl} +X(il) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end())}. +\end{itemdescr} + +\begin{itemdecl} +a = il +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X\&}. + +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X} and +\oldconcept{CopyAssignable}. + +\pnum +\effects +Assigns the range \range{il.begin()}{il.end()} into \tcode{a}. +All existing elements of \tcode{a} are either assigned to or destroyed. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexcont{emplace}% +\begin{itemdecl} +a.emplace(p, args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. +For \tcode{vector} and \tcode{deque}, +\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X} and +\oldconcept{MoveAssignable}. + +\pnum +\effects +Inserts an object of type \tcode{T} +constructed with \tcode{std::forward(args)...} +before \tcode{p}. +\begin{note} +\tcode{args} can directly or indirectly refer to a value in \tcode{a}. +\end{note} + +\pnum +\returns +An iterator that points to +the new element constructed from \tcode{args} into \tcode{a}. +\end{itemdescr} + +\indexcont{insert}% +\begin{itemdecl} +a.insert(p, t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}. +For \tcode{vector} and \tcode{deque}, +\tcode{T} is also \oldconcept{CopyAssignable}. + +\pnum +\effects +Inserts a copy of \tcode{t} before \tcode{p}. + +\pnum +\returns +An iterator that points to the copy of \tcode{t} inserted into \tcode{a}. +\end{itemdescr} + +\begin{itemdecl} +a.insert(p, rv) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X}. +For \tcode{vector} and \tcode{deque}, +\tcode{T} is also \oldconcept{MoveAssignable}. + +\pnum +\effects +Inserts a copy of \tcode{rv} before \tcode{p}. + +\pnum +\returns +An iterator that points to the copy of \tcode{rv} inserted into \tcode{a}. +\end{itemdescr} + +\begin{itemdecl} +a.insert(p, n, t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X} +and \oldconcept{CopyAssignable}. + +\pnum +\effects +Inserts \tcode{n} copies of \tcode{t} before \tcode{p}. + +\pnum +\returns +An iterator +that points to the copy of the first element inserted into \tcode{a}, or +\tcode{p} if \tcode{n == 0}. +\end{itemdescr} + +\begin{itemdecl} +a.insert(p, i, j) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. +For \tcode{vector} and \tcode{deque}, +\tcode{T} is also +\oldconcept{MoveInsertable} into \tcode{X}, +\oldconcept{MoveConstructible}, +\oldconcept{MoveAssignable}, and +swappable\iref{swappable.requirements}. +Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}. + +\pnum +\effects +Inserts copies of elements in \tcode{[i, j)} before \tcode{p}. +Each iterator in the range \range{i}{j} shall be dereferenced exactly once. + +\pnum +\returns +An iterator +that points to the copy of the first element inserted into \tcode{a}, or +\tcode{p} if \tcode{i == j}. +\end{itemdescr} + +\begin{itemdecl} +a.insert(p, il) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Equivalent to \tcode{a.insert(p, il.begin(), il.end())}. + +\pnum +\returns +\begin{removedblock} +An iterator +that points to the copy of the first element inserted into \tcode{a}, or +\tcode{p} if \tcode{il} is empty. +\end{removedblock} +\end{itemdescr} + +\indexcont{erase}% +\begin{itemdecl} +a.erase(q) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +For \tcode{vector} and \tcode{deque}, +\tcode{T} is \oldconcept{MoveAssignable}. + +\pnum +\effects +Erases the element pointed to by \tcode{q}. + +\pnum +\returns +An iterator that points to the element immediately following \tcode{q} +prior to the element being erased. +If no such element exists, \tcode{a.end()} is returned. +\end{itemdescr} + +\begin{itemdecl} +a.erase(q1, q2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +For \tcode{vector} and \tcode{deque}, \tcode{T} is \oldconcept{MoveAssignable}. + +\pnum +\effects +Erases the elements in the range \tcode{[q1, q2)}. + +\pnum +\returns +An iterator that points to the element pointed to by \tcode{q2} +prior to any elements being erased. +If no such element exists, \tcode{a.end()} is returned. +\end{itemdescr} + +\indexcont{clear}% +\begin{itemdecl} +a.clear() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\effects +Destroys all elements in \tcode{a}. +Invalidates all references, pointers, and iterators +referring to the elements of \tcode{a} and +may invalidate the past-the-end iterator. + +\pnum +\ensures +\tcode{a.empty()} is \tcode{true}. + +\pnum +\complexity +Linear. +\end{itemdescr} + +\indexcont{assign}% +\begin{itemdecl} +a.assign(i, j) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i} +and assignable from \tcode{*i}. +For \tcode{vector}, +if the iterator does not meet +the forward iterator requirements\iref{forward.iterators}, +\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}. +Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}. + +\pnum +\effects +Replaces elements in \tcode{a} with a copy of \tcode{[i, j)}. +Invalidates all references, pointers and iterators +referring to the elements of \tcode{a}. +For \tcode{vector} and \tcode{deque}, +also invalidates the past-the-end iterator. +Each iterator in the range \range{i}{j} shall be dereferenced exactly once. +\end{itemdescr} + +\begin{itemdecl} +a.assign(il) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\effects +Equivalent to \tcode{a.assign(il.begin(), il.end())}. +\end{itemdescr} + +\begin{itemdecl} +a.assign(n, t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X} +and \oldconcept{CopyAssignable}. +\tcode{t} is not a reference into \tcode{a}. + +\pnum +\effects +Replaces elements in \tcode{a} with \tcode{n} copies of \tcode{t}. +Invalidates all references, pointers and iterators +referring to the elements of \tcode{a}. +For \tcode{vector} and \tcode{deque}, +also invalidates the past-the-end iterator. +\end{itemdescr} + +\pnum +For every sequence container defined in this Clause and in \ref{strings}: +\begin{itemize} +\item If the constructor +\begin{codeblock} +template + X(InputIterator first, InputIterator last, + const allocator_type& alloc = allocator_type()); +\end{codeblock} +is called with a type \tcode{InputIterator} that does not qualify as an input +iterator, then the constructor +shall not participate in overload resolution. + +\item If the member functions of the forms: +\begin{codeblock} +template + @\placeholdernc{return-type}@ @\placeholdernc{F}@(const_iterator p, + InputIterator first, InputIterator last); // such as \tcode{insert} + +template + @\placeholdernc{return-type}@ @\placeholdernc{F}@(InputIterator first, InputIterator last); // such as \tcode{append}, \tcode{assign} + +template + @\placeholdernc{return-type}@ @\placeholdernc{F}@(const_iterator i1, const_iterator i2, + InputIterator first, InputIterator last); // such as \tcode{replace} +\end{codeblock} +are called with a type \tcode{InputIterator} that does not qualify as an input +iterator, then these functions +shall not participate in overload resolution. + +\item A deduction guide for a sequence container shall not participate in overload resolution +if it has an \tcode{InputIterator} template parameter and a type that does not +qualify as an input iterator is deduced for that parameter, +or if it has an \tcode{Allocator} template parameter and a type that does not +qualify as an allocator is deduced for that parameter. +\end{itemize} + +\pnum +The following operations are provided for +some types of sequence containers but not others. +An implementation shall implement them so as to take amortized constant time. + +\begin{itemdecl} +a.front() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reference; const_reference} for constant \tcode{a}. + +\pnum +\returns +\tcode{*a.begin()} + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{array}, +\tcode{deque}, +\tcode{forward_list}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a.back() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reference; const_reference} for constant \tcode{a}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = a.end(); +--tmp; +return *tmp; +\end{codeblock} + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{array}, +\tcode{deque}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a.emplace_front(args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reference} + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. + +\pnum +\effects +Prepends an object of type \tcode{T} +constructed with \tcode{std::forward(args)...}. + +\pnum +\returns +\tcode{a.front()}. + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{forward_list}, and +\tcode{list}. +\end{itemdescr} + +\begin{itemdecl} +a.emplace_back(args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reference} + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. +For \tcode{vector}, +\tcode{T} is also \oldconcept{MoveIn\-sert\-able} into \tcode{X}. + +\pnum +\effects +Appends an object of type \tcode{T} +constructed with \tcode{std::forward(args)...}. + +\pnum +\returns +\tcode{a.back()}. + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a.push_front(t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Prepends a copy of \tcode{t}. + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{forward_list}, and +\tcode{list}. +\end{itemdescr} + +\begin{itemdecl} +a.push_front(rv) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X}. + +\pnum +\effects +Prepends a copy of \tcode{rv}. + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{forward_list}, and +\tcode{list}. +\end{itemdescr} + +\begin{itemdecl} +a.push_back(t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Appends a copy of \tcode{t}. + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{deque}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a.push_back(rv) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{X}. + +\pnum +\effects +Appends a copy of \tcode{rv}. + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{deque}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a.pop_front() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{a.empty()} is \tcode{false}. + +\pnum +\effects +Destroys the first element. + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{forward_list}, and +\tcode{list}. +\end{itemdescr} + +\begin{itemdecl} +a.pop_back() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{a.empty()} is \tcode{false}. + +\pnum +\effects +Destroys the last element. + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{deque}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a[n] +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reference; const_reference} for constant \tcode{a} + +\pnum +\returns +\tcode{*(a.begin() + n)} + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{array}, +\tcode{deque}, and +\tcode{vector}. +\end{itemdescr} + +\begin{itemdecl} +a.at(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{reference; const_reference} for constant \tcode{a} + +\pnum +\returns +\tcode{*(a.begin() + n)} + +\pnum +\throws +\tcode{out_of_range} if \tcode{n >= a.size()}. + +\pnum +\remarks +Required for +\tcode{basic_string}, +\tcode{array}, +\tcode{deque}, and +\tcode{vector}. +\end{itemdescr} + +\rSec2[container.node]{Node handles} + +\rSec3[container.node.overview]{Overview} + +\pnum +A \defn{node handle} is an object that accepts ownership of a single element +from an associative container\iref{associative.reqmts} or an unordered +associative container\iref{unord.req}. It may be used to transfer that +ownership to another container with compatible nodes. Containers with +compatible nodes have the same node handle type. Elements may be transferred in +either direction between container types in the same row of +\tref{container.node.compat}. + +\begin{floattable}{Container types with compatible nodes}{container.node.compat} +{ll} +\topline +\tcode{map} & \tcode{map} \\ +\rowsep +\tcode{map} & \tcode{multimap} \\ +\rowsep +\tcode{set} & \tcode{set} \\ +\rowsep +\tcode{set} & \tcode{multiset} \\ +\rowsep +\tcode{unordered_map} & \tcode{unordered_map} \\ +\rowsep +\tcode{unordered_map} & \tcode{unordered_multimap} \\ +\rowsep +\tcode{unordered_set} & \tcode{unordered_set} \\ +\rowsep +\tcode{unordered_set} & \tcode{unordered_multiset} \\ +\end{floattable} + +\pnum +If a node handle is not empty, then it contains an allocator that is equal to +the allocator of the container when the element was extracted. If a node handle +is empty, it contains no allocator. + +\pnum +Class \exposid{node-handle} is for exposition only. + +\pnum +If a user-defined specialization of \tcode{pair} exists for +\tcode{pair} or \tcode{pair}, where \tcode{Key} is the +container's \tcode{key_type} and \tcode{T} is the container's +\tcode{mapped_type}, the behavior of operations involving node handles is +undefined. + +\begin{codeblock} +template<@\unspecnc@> +class @\placeholder{node-handle}@ { +public: + // These type declarations are described in \ref{associative.reqmts} and \ref{unord.req}. + using value_type = @\seebelownc{}@; // not present for map containers + using key_type = @\seebelownc{}@; // not present for set containers + using mapped_type = @\seebelownc{}@; // not present for set containers + using allocator_type = @\seebelownc{}@; + +private: + using container_node_type = @\unspecnc@; // \expos + using ator_traits = allocator_traits; // \expos + + typename ator_traits::template + rebind_traits::pointer ptr_; // \expos + optional alloc_; // \expos + +public: + // \ref{container.node.cons}, constructors, copy, and assignment + constexpr @\placeholdernc{node-handle}@() noexcept : ptr_(), alloc_() {} + @\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&&) noexcept; + @\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&&); + + // \ref{container.node.dtor}, destructor + ~@\placeholdernc{node-handle}@(); + + // \ref{container.node.observers}, observers + value_type& value() const; // not present for map containers + key_type& key() const; // not present for set containers + mapped_type& mapped() const; // not present for set containers + + allocator_type get_allocator() const; + explicit operator bool() const noexcept; + [[nodiscard]] bool empty() const noexcept; + + // \ref{container.node.modifiers}, modifiers + void swap(@\placeholdernc{node-handle}@&) + noexcept(ator_traits::propagate_on_container_swap::value || + ator_traits::is_always_equal::value); + + friend void swap(@\placeholdernc{node-handle}@& x, @\placeholdernc{node-handle}@& y) noexcept(noexcept(x.swap(y))) { + x.swap(y); + } +}; +\end{codeblock} + +\rSec3[container.node.cons]{Constructors, copy, and assignment} + +\begin{itemdecl} +@\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&& nh) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \exposid{node-handle} object initializing +\tcode{ptr_} with \tcode{nh.ptr_}. Move constructs \tcode{alloc_} with +\tcode{nh.alloc_}. Assigns \keyword{nullptr} to \tcode{nh.ptr_} and assigns +\tcode{nullopt} to \tcode{nh.alloc_}. +\end{itemdescr} + +\begin{itemdecl} +@\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&& nh); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +Either \tcode{!alloc_}, or +\tcode{ator_traits::propagate_on_container_move_assignment::\-value} +is \tcode{true}, or \tcode{alloc_ == nh.alloc_}. + +\pnum +\effects +\begin{itemize} +\item +If \tcode{ptr_ != nullptr}, destroys the \tcode{value_type} +subobject in the \tcode{container_node_type} object pointed to by \tcode{ptr_} +by calling \tcode{ator_traits::destroy}, then deallocates \tcode{ptr_} by +calling \tcode{ator_traits::template rebind_traits::deallocate}. +\item +Assigns \tcode{nh.ptr_} to \tcode{ptr_}. +\item +If \tcode{!alloc\textunderscore} or \tcode{ator_traits::propagate_on_container_move_assignment::value} +is \tcode{true}, \linebreak +move assigns \tcode{nh.alloc_} to \tcode{alloc_}. +\item +Assigns +\keyword{nullptr} to \tcode{nh.ptr_} and assigns \tcode{nullopt} to +\tcode{nh.alloc_}. +\end{itemize} + +\pnum +\returns +\tcode{*this}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\rSec3[container.node.dtor]{Destructor} + +\begin{itemdecl} +~@\placeholdernc{node-handle}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{ptr_ != nullptr}, destroys the \tcode{value_type} subobject +in the \tcode{container_node_type} object pointed to by \tcode{ptr_} by calling +\tcode{ator_traits::destroy}, then deallocates \tcode{ptr_} by calling +\tcode{ator_traits::template rebind_traits::deallocate}. +\end{itemdescr} + +\rSec3[container.node.observers]{Observers} + +\begin{itemdecl} +value_type& value() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{empty() == false}. + +\pnum +\returns +A reference to the \tcode{value_type} subobject in the +\tcode{container_node_type} object pointed to by \tcode{ptr_}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +key_type& key() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{empty() == false}. + +\pnum +\returns +A non-const reference to the \tcode{key_type} member of the +\tcode{value_type} subobject in the \tcode{contain\-er_node_type} object +pointed to by \tcode{ptr_}. + +\pnum +\throws +Nothing. + +\pnum +\remarks +Modifying the key through the returned reference is permitted. +\end{itemdescr} + +\begin{itemdecl} +mapped_type& mapped() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{empty() == false}. + +\pnum +\returns +A reference to the \tcode{mapped_type} member of the +\tcode{value_type} subobject in the \tcode{container_node_type} object +pointed to by \tcode{ptr_}. + +\pnum +\throws +Nothing. +\end{itemdescr} + + +\begin{itemdecl} +allocator_type get_allocator() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{empty() == false}. + +\pnum +\returns +\tcode{*alloc_}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +explicit operator bool() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{ptr_ != nullptr}. +\end{itemdescr} + +\begin{itemdecl} +[[nodiscard]] bool empty() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{ptr_ == nullptr}. +\end{itemdescr} + +\rSec3[container.node.modifiers]{Modifiers} + +\begin{itemdecl} +void swap(@\placeholdernc{node-handle}@& nh) + noexcept(ator_traits::propagate_on_container_swap::value || + ator_traits::is_always_equal::value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{!alloc_}, or \tcode{!nh.alloc_}, or +\tcode{ator_traits::propagate_on_container_swap::value} is \tcode{true}, +or \tcode{alloc_ == nh.alloc_}. + +\pnum +\effects +Calls \tcode{swap(ptr_, nh.ptr_)}. If \tcode{!alloc_}, or +\tcode{!nh.alloc_}, or \tcode{ator_traits::propagate_on_container_swap::value} +is \tcode{true} calls \tcode{swap(alloc_, nh.alloc_)}. +\end{itemdescr} + +\rSec2[container.insert.return]{Insert return type} + +\pnum +The associative containers with unique keys and the unordered containers with unique keys +have a member function \tcode{insert} that returns a nested type \tcode{insert_return_type}. +That return type is a specialization of the template specified in this subclause. + +\begin{codeblock} +template +struct @\placeholder{insert-return-type}@ +{ + Iterator position; + bool inserted; + NodeType node; +}; +\end{codeblock} + +\pnum +The name \exposid{insert-return-type} is exposition only. +\exposid{insert-return-type} has the template parameters, +data members, and special members specified above. +It has no base classes or members other than those specified. + +\rSec2[associative.reqmts]{Associative containers} + +\rSec3[associative.reqmts.general]{General} + +\pnum +Associative containers provide fast retrieval of data based on keys. +The library provides four basic kinds of associative containers: +\tcode{set}, +\tcode{multiset}, +\tcode{map} +and +\tcode{multimap}. + +\pnum +Each associative container is parameterized on +\tcode{Key} +and an ordering relation +\tcode{Compare} +that induces a strict weak ordering\iref{alg.sorting} on +elements of +\tcode{Key}. +In addition, +\tcode{map} +and +\tcode{multimap} +associate an arbitrary \term{mapped type} +\tcode{T} +with the +\tcode{Key}. +The object of type +\tcode{Compare} +is called the +\term{comparison object} +of a container. + +\pnum +The phrase ``equivalence of keys'' means the equivalence relation imposed by the +comparison object. +That is, two keys +\tcode{k1} +and +\tcode{k2} +are considered to be equivalent if for the +comparison object +\tcode{comp}, +\tcode{comp(k1, k2) == false \&\& comp(k2, k1) == false}. +\begin{note} +This is not necessarily the same as the result of \tcode{k1 == k2}. +\end{note} +For any two keys +\tcode{k1} +and +\tcode{k2} +in the same container, calling +\tcode{comp(k1, k2)} +shall always return the same value. + +\pnum +An associative container supports \term{unique keys} if it may contain at +most one element for each key. Otherwise, it supports \term{equivalent keys}. +The \tcode{set} and \tcode{map} classes support unique keys; the \tcode{multiset} +and \tcode{multimap} classes support equivalent keys. +For \tcode{multiset} and \tcode{multimap}, +\tcode{insert}, \tcode{emplace}, and \tcode{erase} preserve the relative ordering +of equivalent elements. + +\pnum +For \tcode{set} and \tcode{multiset} the value type is the same as the key type. +For \tcode{map} and \tcode{multimap} it is equal to \tcode{pair}. + +\pnum +\tcode{iterator} +of an associative container is of the bidirectional iterator category. +For associative containers where the value type is the same as the key type, both +\tcode{iterator} +and +\tcode{const_iterator} +are constant iterators. It is unspecified whether or not +\tcode{iterator} +and +\tcode{const_iterator} +are the same type. +\begin{note} +\tcode{iterator} and \tcode{const_iterator} have identical semantics in this case, and \tcode{iterator} is convertible to \tcode{const_iterator}. Users can avoid violating the one-definition rule by always using \tcode{const_iterator} in their function parameter lists. +\end{note} + +\pnum +In this subclause, +\begin{itemize} +\item +\tcode{X} denotes an associative container class, +\item +\tcode{a} denotes a value of type \tcode{X}, +\item +\tcode{a2} denotes a value of a type with nodes compatible with type +\tcode{X} (\tref{container.node.compat}), +\item +\tcode{b} denotes a possibly \keyword{const} value of type \tcode{X}, +\item +\tcode{u} denotes the name of a variable being declared, +\item +\tcode{a_uniq} denotes a value of type \tcode{X} +when \tcode{X} supports unique keys, +\item +\tcode{a_eq} denotes a value of type \tcode{X} +when \tcode{X} supports multiple keys, +\item +\tcode{a_tran} denotes a possibly \keyword{const} value of type \tcode{X} +when the \grammarterm{qualified-id} +\tcode{X::key_compare::is_transpa\-rent} is valid +and denotes a type\iref{temp.deduct}, +\item +\tcode{i} and \tcode{j} +meet the \oldconcept{InputIterator} requirements and refer to elements +implicitly convertible to +\tcode{value_type}, +\item +\range{i}{j} denotes a valid range, +\item +\tcode{p} denotes a valid constant iterator to \tcode{a}, +\item +\tcode{q} denotes a valid dereferenceable constant iterator to \tcode{a}, +\item +\tcode{r} denotes a valid dereferenceable iterator to \tcode{a}, +\item +\tcode{[q1, q2)} denotes a valid range of constant iterators in \tcode{a}, +\item +\tcode{il} designates an object of type \tcode{initializer_list}, +\item +\tcode{t} denotes a value of type \tcode{X::value_type}, +\item +\tcode{k} denotes a value of type \tcode{X::key_type}, and +\item +\tcode{c} denotes a possibly \keyword{const} value of type \tcode{X::key_compare}; +\item +\tcode{kl} is a value such that \tcode{a} is partitioned\iref{alg.sorting} +with respect to \tcode{c(x, kl)}, +with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}; +\item +\tcode{ku} is a value such that \tcode{a} is partitioned with respect to +\tcode{!c(ku, x)}, +with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}; +\item +\tcode{ke} is a value such that \tcode{a} is partitioned with respect to +\tcode{c(x, ke)} and \tcode{!c(ke, x)}, with \tcode{c(x, ke)} implying +\tcode{!c(ke, x)} and +with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}; +\item +\tcode{kx} is a value such that +\begin{itemize} +\item +\tcode{a} is partitioned with respect to \tcode{c(x, kx)} and \tcode{!c(kx, x)}, +with \tcode{c(x, kx)} implying \tcode{!c(kx, x)} and +with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}, and +\item +\tcode{kx} is not convertible to +either \tcode{iterator} or \tcode{const_iterator}; and +\end{itemize} +\item +\tcode{A} denotes the storage allocator used by \tcode{X}, if any, or \tcode{allocator} otherwise, +\item +\tcode{m} denotes an allocator of a type convertible to \tcode{A}, +and \tcode{nh} denotes a non-const rvalue of type \tcode{X::node_type}. +\end{itemize} + +\pnum +A type \tcode{X} meets the \defnadj{associative}{container} requirements +if \tcode{X} meets all the requirements of an allocator-aware +container\iref{container.requirements.general} and +the following types, statements, and expressions are well-formed and +have the specified semantics, +except that for +\tcode{map} and \tcode{multimap}, the requirements placed on \tcode{value_type} +in \ref{container.alloc.reqmts} apply instead to \tcode{key_type} +and \tcode{mapped_type}. +\begin{note} +For example, in some cases \tcode{key_type} and \tcode{mapped_type} +are required to be \oldconcept{CopyAssignable} even though the associated +\tcode{value_type}, \tcode{pair}, is not +\oldconcept{CopyAssignable}. +\end{note} + +% Local command to index names as members of all ordered containers. +\newcommand{\indexordmem}[1]{% +\indexlibrary{\idxcode{#1}!ordered associative containers}% +\indexlibrary{\idxcode{set}!\idxcode{#1}}% +\indexlibrary{\idxcode{map}!\idxcode{#1}}% +\indexlibrary{\idxcode{multiset}!\idxcode{#1}}% +\indexlibrary{\idxcode{multimap}!\idxcode{#1}}% +} + +\indexordmem{key_type}% +\begin{itemdecl} +typename X::key_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Key}. +\end{itemdescr} + +\indexordmem{mapped_type}% +\begin{itemdecl} +typename X::mapped_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{T}. + +\pnum +\remarks +For \tcode{map} and \tcode{multimap} only. +\end{itemdescr} + +\indexordmem{value_type}% +\begin{itemdecl} +typename X::value_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Key} for \tcode{set} and \tcode{multiset} only; +\tcode{pair} for \tcode{map} and \tcode{multimap} only. + +\pnum +\expects +\tcode{X::value_type} is \oldconcept{Erasable} from \tcode{X}. +\end{itemdescr} + +\indexordmem{key_compare}% +\begin{itemdecl} +typename X::key_compare +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Compare}. + +\pnum +\expects +\tcode{key_compare} is \oldconcept{CopyConstructible}. +\end{itemdescr} + +\indexordmem{value_compare}% +\begin{itemdecl} +typename X::value_compare +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A binary predicate type. +It is the same as \tcode{key_compare} for \tcode{set} and +\tcode{multiset}; is an ordering relation on pairs induced by the +first component (i.e., \tcode{Key}) for \tcode{map} and \tcode{multimap}. +\end{itemdescr} + +\indexordmem{node_type}% +\begin{itemdecl} +typename X::node_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A specialization of +the \exposid{node-handle} class template\iref{container.node}, +such that the public nested types are +the same types as the corresponding types in \tcode{X}. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty container. +Uses a copy of \tcode{c} as a comparison object. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X u = X(); +X u; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements. + +\pnum +\effects +Constructs an empty container. +Uses \tcode{Compare()} as a comparison object. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(i, j, c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. + +\pnum +\effects +Constructs an empty container and +inserts elements from the range \range{i}{j} into it; +uses \tcode{c} as a comparison object. + +\pnum +\complexity +$N \log N$ in general, where $N$ has the value \tcode{distance(i, j)}; +linear if \range{i}{j} is sorted with \tcode{value_comp()}. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(i, j) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. + +\pnum +\effects +Constructs an empty container and +inserts elements from the range \range{i}{j} into it; +uses \tcode{Compare()} as a comparison object. + +\pnum +\complexity +$N \log N$ in general, where $N$ has the value \tcode{distance(i, j)}; +linear if \range{i}{j} is sorted with \tcode{value_comp()}. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(il, c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end(), c)}. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(il) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end())}. +\end{itemdescr} + +\begin{itemdecl} +a = il +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X\&} + +\pnum +\expects +\tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X} +and \oldconcept{CopyAssignable}. + +\pnum +\effects +Assigns the range \range{il.begin()}{il.end()} into \tcode{a}. +All existing elements of \tcode{a} are either assigned to or destroyed. + +\pnum +\complexity +$N \log N$ in general, where $N$ has the value \tcode{il.size() + a.size()}; +linear if \range{il.begin()}{il.end()} is sorted with \tcode{value_comp()}. +\end{itemdescr} + +\indexordmem{key_comp}% +\begin{itemdecl} +b.key_comp() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::key_compare} + +\pnum +\returns +The comparison object out of which \tcode{b} was constructed. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexordmem{value_comp}% +\begin{itemdecl} +b.value_comp() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::value_compare} + +\pnum +\returns +An object of \tcode{value_compare} constructed out of the comparison object. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexordmem{emplace}% +\begin{itemdecl} +a_uniq.emplace(args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{pair} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. + +\pnum +\effects +Inserts a \tcode{value_type} object \tcode{t} +constructed with \tcode{std::forward(args)...} +if and only if there is no element in the container +with key equivalent to the key of \tcode{t}. + +\pnum +\returns +The \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion takes place, and +the iterator component of the pair points to +the element with key equivalent to the key of \tcode{t}. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{emplace}% +\begin{itemdecl} +a_eq.emplace(args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. + +\pnum +\effects +Inserts a \tcode{value_type} object \tcode{t} +constructed with \tcode{std::forward(args)...}. +If a range containing elements equivalent to \tcode{t} exists in \tcode{a_eq}, +\tcode{t} is inserted at the end of that range. + +\pnum +\returns +An iterator pointing to the newly inserted element. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{emplace_hint}% +\begin{itemdecl} +a.emplace_hint(p, args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Equivalent to \tcode{a.emplace(std::forward(args)...)}, +except that the element is inserted as close as possible to +the position just prior to \tcode{p}. + +\pnum +\returns +An iterator pointing to the element +with the key equivalent to the newly inserted element. + +\pnum +\complexity +Logarithmic in general, but +amortized constant if the element is inserted right before \tcode{p}. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a_uniq.insert(t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{pair} + +\pnum +\expects +If \tcode{t} is a non-const rvalue, +\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X}; +otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Inserts \tcode{t} if and only if there is no element in the container +with key equivalent to the key of \tcode{t}. + +\pnum +\returns +The \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion takes place, and +the \tcode{iterator} component of the pair points to +the element with key equivalent to the key of \tcode{t}. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a_eq.insert(t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +If \tcode{t} is a non-const rvalue, +\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X}; +otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Inserts \tcode{t} and returns the iterator pointing to +the newly inserted element. +If a range containing elements equivalent to \tcode{t} exists in \tcode{a_eq}, +\tcode{t} is inserted at the end of that range. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a.insert(p, t) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +If \tcode{t} is a non-const rvalue, +\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X}; +otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}. + +\pnum +\effects +Inserts \tcode{t} if and only if there is no element +with key equivalent to the key of \tcode{t} in containers with unique keys; +always inserts \tcode{t} in containers with equivalent keys. +\tcode{t} is inserted as close as possible to +the position just prior to \tcode{p}. + +\pnum +\returns +An iterator pointing to the element with key equivalent to the key of \tcode{t}. + +\pnum +\complexity +Logarithmic in general, but +amortized constant if \tcode{t} is inserted right before \tcode{p}. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a.insert(i, j) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. +Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}. + +\pnum +\effects +Inserts each element from the range \range{i}{j} +if and only if there is no element +with key equivalent to the key of that element in containers with unique keys; +always inserts that element in containers with equivalent keys. + +\pnum +\complexity +$N \log (\tcode{a.size()} + N)$, where $N$ has the value \tcode{distance(i, j)}. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a.insert(il) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\effects +Equivalent to \tcode{a.insert(il.begin(), il.end())}. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a_uniq.insert(nh) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{insert_return_type} + +\pnum +\expects +\tcode{nh} is empty or +\tcode{a_uniq.get_allocator() == nh.get_allocator()} is \tcode{true}. + +\pnum +\effects +If \tcode{nh} is empty, has no effect. +Otherwise, inserts the element owned by \tcode{nh} if and only if +there is no element in the container with a key equivalent to \tcode{nh.key()}. + +\pnum +\returns +If \tcode{nh} is empty, \tcode{inserted} is \tcode{false}, +\tcode{position} is \tcode{end()}, and \tcode{node} is empty. +Otherwise if the insertion took place, \tcode{inserted} is \tcode{true}, +\tcode{position} points to the inserted element, and \tcode{node} is empty; +if the insertion failed, \tcode{inserted} is \tcode{false}, +\tcode{node} has the previous value of \tcode{nh}, and +\tcode{position} points to an element with a key equivalent to \tcode{nh.key()}. + +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a_eq.insert(nh) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +\tcode{nh} is empty or +\tcode{a_eq.get_allocator() == nh.get_allocator()} is \tcode{true}. + +\pnum +\effects +If \tcode{nh} is empty, has no effect and returns \tcode{a_eq.end()}. +Otherwise, inserts the element owned by \tcode{nh} and +returns an iterator pointing to the newly inserted element. +If a range containing elements with keys equivalent to \tcode{nh.key()} +exists in \tcode{a_eq}, +the element is inserted at the end of that range. + +\pnum +\ensures +\tcode{nh} is empty. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{insert}% +\begin{itemdecl} +a.insert(p, nh) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +\tcode{nh} is empty or +\tcode{a.get_allocator() == nh.get_allocator()} is \tcode{true}. + +\pnum +\effects +If \tcode{nh} is empty, has no effect and returns \tcode{a.end()}. +Otherwise, inserts the element owned by \tcode{nh} if and only if +there is no element with key equivalent to \tcode{nh.key()} +in containers with unique keys; +always inserts the element owned by \tcode{nh} +in containers with equivalent keys. +The element is inserted as close as possible to +the position just prior to \tcode{p}. + +\pnum +\ensures +\tcode{nh} is empty if insertion succeeds, unchanged if insertion fails. + +\pnum +\returns +An iterator pointing to the element with key equivalent to \tcode{nh.key()}. + +\pnum +\complexity +Logarithmic in general, but +amortized constant if the element is inserted right before \tcode{p}. +\end{itemdescr} + + +\indexordmem{extract}% +\begin{itemdecl} +a.extract(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{node_type} + +\pnum +\effects +Removes the first element in the container with key equivalent to \tcode{k}. + +\pnum +\returns +A \tcode{node_type} owning the element if found, +otherwise an empty \tcode{node_type}. + +\pnum +\complexity +$\log (\tcode{a.size()})$ +\end{itemdescr} + +\indexordmem{extract}% +\begin{itemdecl} +a_tran.extract(kx) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{node_type} + +\pnum +\effects +Removes the first element in the container with key \tcode{r} +such that \tcode{!c(r, kx) \&\& !c(kx, r)} is \tcode{true}. + +\pnum +\returns +A \tcode{node_type} owning the element if found, +otherwise an empty \tcode{node_type}. + +\pnum +\complexity +$\log(\tcode{a_tran.size()})$ +\end{itemdescr} + +\indexordmem{extract}% +\begin{itemdecl} +a.extract(q) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{node_type} + +\pnum +\effects +Removes the element pointed to by \tcode{q}. + +\pnum +\returns +A \tcode{node_type} owning that element. + +\pnum +\complexity +Amortized constant. +\end{itemdescr} + +\indexordmem{merge}% +\begin{itemdecl} +a.merge(a2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{a.get_allocator() == a2.get_allocator()}. + +\pnum +\effects +Attempts to extract each element in \tcode{a2} and insert it into \tcode{a} +using the comparison object of \tcode{a}. +In containers with unique keys, +if there is an element in \tcode{a} with key equivalent to +the key of an element from \tcode{a2}, +then that element is not extracted from \tcode{a2}. + +\pnum +\ensures +Pointers and references to the transferred elements of \tcode{a2} +refer to those same elements but as members of \tcode{a}. +Iterators referring to the transferred elements +will continue to refer to their elements, +but they now behave as iterators into \tcode{a}, not into \tcode{a2}. + +\pnum +\throws +Nothing unless the comparison object throws. + +\pnum +\complexity +$N \log(\tcode{a.size()+} N)$, where $N$ has the value \tcode{a2.size()}. +\end{itemdescr} + +\indexordmem{erase}% +\begin{itemdecl} +a.erase(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\effects +Erases all elements in the container with key equivalent to \tcode{k}. + +\pnum +\returns +The number of erased elements. + +\pnum +\complexity +$\log (\tcode{a.size()}) + \tcode{a.count(k)}$ +\end{itemdescr} + +\indexordmem{erase}% +\begin{itemdecl} +a_tran.erase(kx) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\effects +Erases all elements in the container with key \tcode{r} +such that \tcode{!c(r, kx) \&\& !c(kx, r)} is \tcode{true}. + +\pnum +\returns +The number of erased elements. + +\pnum +\complexity +$\log(\tcode{a_tran.size())} + \tcode{a_tran.count(kx)}$ +\end{itemdescr} + +\indexordmem{erase}% +\begin{itemdecl} +a.erase(q) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Erases the element pointed to by \tcode{q}. + +\returns +An iterator pointing to the element immediately following \tcode{q} +prior to the element being erased. +If no such element exists, returns \tcode{a.end()}. + +\pnum +\complexity +Amortized constant. +\end{itemdescr} + +\indexordmem{erase}% +\begin{itemdecl} +a.erase(r) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Erases the element pointed to by \tcode{r}. + +\pnum +\returns +An iterator pointing to the element immediately following \tcode{r} +prior to the element being erased. +If no such element exists, returns \tcode{a.end()}. + +\pnum +\complexity +Amortized constant. +\end{itemdescr} + +\indexordmem{erase}% +\begin{itemdecl} +a.erase(q1, q2) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Erases all the elements in the range \range{q1}{q2}. + +\pnum +\returns +An iterator pointing to the element pointed to by \tcode{q2} +prior to any elements being erased. +If no such element exists, \tcode{a.end()} is returned. + +\pnum +\complexity +$\log(\tcode{a.size()}) + N$, where $N$ has the value \tcode{distance(q1, q2)}. +\end{itemdescr} + +\indexordmem{clear}% +\begin{itemdecl} +a.clear() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\effects +Equivalent to \tcode{a.erase(a.begin(), a.end())}. + +\pnum +\ensures +\tcode{a.empty()} is \tcode{true}. + +\pnum +\complexity +Linear in \tcode{a.size()}. +\end{itemdescr} + +\indexordmem{find}% +\begin{itemdecl} +b.find(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for constant \tcode{b}. + +\pnum +\returns +An iterator pointing to an element with the key equivalent to \tcode{k}, or +\tcode{b.end()} if such an element is not found. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{find}% +\begin{itemdecl} +a_tran.find(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}. + +\pnum +\returns +An iterator pointing to an element with key \tcode{r} +such that \tcode{!c(r, ke) \&\& !c(ke, r)} is \tcode{true}, or +\tcode{a_tran.end()} if such an element is not found. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{count}% +\begin{itemdecl} +b.count(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\returns +The number of elements with key equivalent to \tcode{k}. + +\pnum +\complexity +$\log (\tcode{b.size()}) + \tcode{b.count(k)}$ +\end{itemdescr} + +\indexordmem{count}% +\begin{itemdecl} +a_tran.count(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} + +\pnum +\returns +The number of elements with key \tcode{r} +such that \tcode{!c(r, ke) \&\& !c(ke, r)}. + +\pnum +\complexity +$\log (\tcode{a_tran.size()}) + \tcode{a_tran.count(ke)}$ +\end{itemdescr} + +\indexordmem{contains}% +\begin{itemdecl} +b.contains(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\effects +Equivalent to: \tcode{return b.find(k) != b.end();} + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{contains}% +\begin{itemdecl} +a_tran.contains(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\effects +Equivalent to: \tcode{return a_tran.find(ke) != a_tran.end();} + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{lower_bound}% +\begin{itemdecl} +b.lower_bound(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for constant \tcode{b}. + +\pnum +\returns +An iterator pointing to the first element with key not less than \tcode{k}, +or \tcode{b.end()} if such an element is not found. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{lower_bound}% +\begin{itemdecl} +a_tran.lower_bound(kl) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}. + +\pnum +\returns +An iterator pointing to the first element with key \tcode{r} +such that \tcode{!c(r, kl)}, +or \tcode{a_tran.end()} if such an element is not found. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{upper_bound}% +\begin{itemdecl} +b.upper_bound(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for constant \tcode{b}. + +\pnum +\returns +An iterator pointing to the first element with key greater than \tcode{k}, +or \tcode{b.end()} if such an element is not found. + +\pnum +\complexity +Logarithmic, +\end{itemdescr} + +\indexordmem{upper_bound}% +\begin{itemdecl} +a_tran.upper_bound(ku) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}. + +\pnum +\returns +An iterator pointing to the first element with key \tcode{r} +such that \tcode{c(ku, r)}, +or \tcode{a_tran.end()} if such an element is not found. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{equal_range}% +\begin{itemdecl} +b.equal_range(k) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{pair}; +\tcode{pair} for constant \tcode{b}. + +\pnum +\effects +Equivalent to: \tcode{return make_pair(b.lower_bound(k), b.upper_bound(k));} + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexordmem{equal_range}% +\begin{itemdecl} +a_tran.equal_range(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{pair}; +\tcode{pair} for constant \tcode{a_tran}. + +\pnum +\effects +Equivalent to: +\tcode{return make_pair(a_tran.lower_bound(ke), a_tran.upper_bound(ke));} + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\pnum +The \tcode{insert} and \tcode{emplace} members shall not affect the validity of +iterators and references to the container, +and the \tcode{erase} members shall invalidate only iterators and +references to the erased elements. + +\pnum +The \tcode{extract} members invalidate only iterators to the removed element; +pointers and references to the removed element remain valid. However, accessing +the element through such pointers and references while the element is owned by +a \tcode{node_type} is undefined behavior. References and pointers to an element +obtained while it is owned by a \tcode{node_type} are invalidated if the element +is successfully inserted. + +\pnum +The fundamental property of iterators of associative containers is that they iterate through the containers +in the non-descending order of keys where non-descending is defined by the comparison that was used to +construct them. +For any two dereferenceable iterators +\tcode{i} +and +\tcode{j} +such that distance from +\tcode{i} +to +\tcode{j} +is positive, the following condition holds: + +\begin{codeblock} +value_comp(*j, *i) == false +\end{codeblock} + +\pnum +For associative containers with unique keys the stronger condition holds: + +\begin{codeblock} +value_comp(*i, *j) != false +\end{codeblock} + +\pnum +When an associative container is constructed by passing a comparison object the +container shall not store a pointer or reference to the passed object, +even if that object is passed by reference. +When an associative container is copied, through either a copy constructor +or an assignment operator, +the target container shall then use the comparison object from the container +being copied, +as if that comparison object had been passed to the target container in +its constructor. + +\pnum +The member function templates +\tcode{find}, \tcode{count}, \tcode{contains}, +\tcode{lower_bound}, \tcode{upper_bound}, \tcode{equal_range}, +\tcode{erase}, and \tcode{extract} +shall not participate in overload resolution unless +the \grammarterm{qualified-id} \tcode{Compare::is_transparent} is valid +and denotes a type\iref{temp.deduct}. +Additionally, the member function templates \tcode{extract} and \tcode{erase} +shall not participate in overload resolution if +\tcode{is_convertible_v || is_convertible_v} +is \tcode{true}, +where \tcode{K} is the type substituted as the first template argument. + +\pnum +A deduction guide for an associative container shall not participate in overload resolution +if any of the following are true: +\begin{itemize} +\item It has an \tcode{InputIterator} template parameter +and a type that does not qualify as an input iterator is deduced for that parameter. + +\item It has an \tcode{Allocator} template parameter +and a type that does not qualify as an allocator is deduced for that parameter. + +\item It has a \tcode{Compare} template parameter +and a type that qualifies as an allocator is deduced for that parameter. +\end{itemize} + +\rSec3[associative.reqmts.except]{Exception safety guarantees}% +\indextext{associative containers!exception safety}% +\indextext{associative containers!requirements}% + +\pnum +For associative containers, no \tcode{clear()} function throws an exception. +\tcode{erase(k)} does not throw an exception unless that exception is thrown +by the container's \tcode{Compare} object (if any). + +\pnum +For associative containers, if an exception is thrown by any operation from +within an \tcode{insert} or \tcode{emplace} function inserting a single element, the +insertion has no effect. + +\pnum +For associative containers, no \tcode{swap} function throws an exception unless +that exception is thrown by the +swap of the container's \tcode{Compare} object (if any). + +\rSec2[unord.req]{Unordered associative containers}% +\indextext{associative containers!unordered|see{unordered associative containers}} +\indextext{hash tables|see{unordered associative containers}} + +\rSec3[unord.req.general]{General} + +\pnum +\indextext{unordered associative containers!complexity}% +Unordered associative containers provide an ability for fast retrieval +of data based on keys. The worst-case complexity for most operations +is linear, but the average case is much faster. The library provides +four unordered associative containers: \tcode{unordered_set}, +\tcode{unordered_map}, \tcode{unordered_multiset}, and +\tcode{unordered_multimap}. + +\pnum +\indextext{unordered associative containers!lack of comparison functions}% +\indextext{unordered associative containers!requirements}% +\indextext{requirements!container!not required for unordered associated containers}% +Unordered associative containers conform to the requirements for +Containers\iref{container.requirements}, except that +the expressions +\tcode{a == b} and \tcode{a != b} have different semantics than for the other +container types. + +\pnum +Each unordered associative container is parameterized by \tcode{Key}, +by a function object type \tcode{Hash} that meets the \oldconcept{Hash} +requirements\iref{hash.requirements} and acts as a hash function for +argument values of type \tcode{Key}, and by a binary predicate \tcode{Pred} +that induces an equivalence relation on values of type \tcode{Key}. +Additionally, \tcode{unordered_map} and \tcode{unordered_multimap} associate +an arbitrary \textit{mapped type} \tcode{T} with the \tcode{Key}. + +\pnum +\indextext{unordered associative containers!hash function}% +\indextext{hash function}% +The container's object of type \tcode{Hash} --- denoted by +\tcode{hash} --- is called the \term{hash function} of the +container. The container's object of type \tcode{Pred} --- +denoted by \tcode{pred} --- is called the +\term{key equality predicate} of the container. + +\pnum +\indextext{unordered associative containers!equality function}% +Two values \tcode{k1} and \tcode{k2} are +considered equivalent if the container's +key equality predicate +\tcode{pred(k1, k2)} is valid and returns +\tcode{true} when passed those values. If \tcode{k1} and +\tcode{k2} are equivalent, the container's hash function shall +return the same value for both. +\begin{note} +Thus, when an unordered associative container is instantiated with +a non-default \tcode{Pred} parameter it usually needs a non-default \tcode{Hash} +parameter as well. +\end{note} +For any two keys \tcode{k1} and \tcode{k2} in the same container, +calling \tcode{pred(k1, k2)} shall always return the same value. +For any key \tcode{k} in a container, calling \tcode{hash(k)} +shall always return the same value. + +\pnum +\indextext{unordered associative containers!unique keys}% +\indextext{unordered associative containers!equivalent keys}% +An unordered associative container supports \textit{unique keys} if it +may contain at most one element for each key. Otherwise, it supports +\textit{equivalent keys}. \tcode{unordered_set} and \tcode{unordered_map} +support unique keys. \tcode{unordered_multiset} and \tcode{unordered_multimap} +support equivalent keys. In containers that support equivalent keys, +elements with equivalent keys are adjacent to each other +in the iteration order of the container. Thus, although the absolute order +of elements in an unordered container is not specified, its elements are +grouped into \defnx{equivalent-key groups}{equivalent-key group} such that all elements of each +group have equivalent keys. Mutating operations on unordered containers shall +preserve the relative order of elements within each equivalent-key group +unless otherwise specified. + +\pnum +For \tcode{unordered_set} and \tcode{unordered_multiset} the value type is +the same as the key type. For \tcode{unordered_map} and +\tcode{unordered_multimap} it is \tcode{pair}. + +\pnum +For unordered containers where the value type is the same as the key +type, both \tcode{iterator} and \tcode{const_iterator} are constant +iterators. It is unspecified whether or not \tcode{iterator} and +\tcode{const_iterator} are the same type. +\begin{note} +\tcode{iterator} and \tcode{const_iterator} have identical +semantics in this case, and \tcode{iterator} is convertible to +\tcode{const_iterator}. Users can avoid violating the one-definition rule +by always using \tcode{const_iterator} in their function parameter lists. +\end{note} + +\pnum +\indextext{buckets}% +\indextext{hash code}% +The elements of an unordered associative container are organized into +\textit{buckets}. Keys with the same hash code appear in the same +bucket. The number of buckets is automatically increased as elements +are added to an unordered associative container, so that the average +number of elements per bucket is kept below a bound. Rehashing +invalidates iterators, changes ordering between elements, and changes +which buckets elements appear in, but does not invalidate pointers or +references to elements. For \tcode{unordered_multiset} and +\tcode{unordered_multimap}, rehashing preserves the relative ordering of +equivalent elements. + +\pnum +\indextext{unordered associative containers}% +\indextext{unordered associative containers!requirements}% +\indextext{requirements!unordered associative container}% +\indextext{unordered associative containers!unique keys}% +\indextext{unordered associative containers!equivalent keys}% +\indextext{requirements!container}% +In this subclause, +\begin{itemize} +\item +\tcode{X} denotes an unordered associative container class, +\item +\tcode{a} denotes a value of type \tcode{X}, +\item +\tcode{a2} denotes a value of a type with nodes compatible + with type \tcode{X} (\tref{container.node.compat}), +\item +\tcode{b} denotes a possibly const value of type \tcode{X}, +\item +\tcode{a_uniq} denotes a value of type \tcode{X} + when \tcode{X} supports unique keys, +\item +\tcode{a_eq} denotes a value of type \tcode{X} + when \tcode{X} supports equivalent keys, +\item +\tcode{a_tran} denotes a possibly const value of type \tcode{X} + when the \grammarterm{qualified-id}s + \tcode{X::key_equal::is_transparent} and + \tcode{X::hasher::is_transparent} + are both valid and denote types\iref{temp.deduct}, +\item +\tcode{i} and \tcode{j} denote input iterators + that refer to \tcode{value_type}, +\item +\tcode{[i, j)} denotes a valid range, +\item +\tcode{p} and \tcode{q2} denote valid constant iterators to \tcode{a}, +\item +\tcode{q} and \tcode{q1} denote + valid dereferenceable constant iterators to \tcode{a}, +\item +\tcode{r} denotes a valid dereferenceable iterator to \tcode{a}, +\item +\tcode{[q1, q2)} denotes a valid range in \tcode{a}, +\item +\tcode{il} denotes a value of type \tcode{initializer_list}, +\item +\tcode{t} denotes a value of type \tcode{X::value_type}, +\item +\tcode{k} denotes a value of type \tcode{key_type}, +\item +\tcode{hf} denotes a possibly const value of type \tcode{hasher}, +\item +\tcode{eq} denotes a possibly const value of type \tcode{key_equal}, +\item +\tcode{ke} is a value such that + \begin{itemize} + \item \tcode{eq(r1, ke) == eq(ke, r1)}, + \item \tcode{hf(r1) == hf(ke)} if \tcode{eq(r1, ke)} is \tcode{true}, and + \item \tcode{(eq(r1, ke) \&\& eq(r1, r2)) == eq(r2, ke)}, + \end{itemize} + where \tcode{r1} and \tcode{r2} are keys of elements in \tcode{a_tran}, +\item +\tcode{kx} is a value such that + \begin{itemize} + \item \tcode{eq(r1, kx) == eq(kx, r1)}, + \item \tcode{hf(r1) == hf(kx)} if \tcode{eq(r1, kx)} is \tcode{true}, + \item \tcode{(eq(r1, kx) \&\& eq(r1, r2)) == eq(r2, kx)}, and + \item \tcode{kx} is not convertible to + either \tcode{iterator} or \tcode{const_iterator}, + \end{itemize} + where \tcode{r1} and \tcode{r2} are keys of elements in \tcode{a_tran}, +\item +\tcode{n} denotes a value of type \tcode{size_type}, +\item +\tcode{z} denotes a value of type \tcode{float}, and +\item +\tcode{nh} denotes a non-const rvalue of type \tcode{X::node_type}. +\end{itemize} + +\pnum +A type \tcode{X} meets +the \defnadj{unordered associative}{container} requirements +if \tcode{X} meets all the requirements of +an allocator-aware container\iref{container.requirements.general} and +the following types, statements, and expressions are well-formed and +have the specified semantics, +except that for \tcode{unordered_map} and \tcode{unordered_multimap}, +the requirements placed on \tcode{value_type} in \ref{container.alloc.reqmts} +apply instead to \tcode{key_type} and \tcode{mapped_type}. +\begin{note} +For example, \tcode{key_type} and \tcode{mapped_type} +are sometimes required to be \oldconcept{CopyAssignable} +even though the associated \tcode{value_type}, +\tcode{pair}, +is not \oldconcept{CopyAssignable}. +\end{note} + +% Local command to index names as members of all unordered containers. +\newcommand{\indexunordmem}[1]{% +\indexlibrary{\idxcode{#1}!unordered associative containers}% +\indexlibrary{\idxcode{unordered_set}!\idxcode{#1}}% +\indexlibrary{\idxcode{unordered_map}!\idxcode{#1}}% +\indexlibrary{\idxcode{unordered_multiset}!\idxcode{#1}}% +\indexlibrary{\idxcode{unordered_multimap}!\idxcode{#1}}% +} + +\indexunordmem{key_type}% +\begin{itemdecl} +typename X::key_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Key}. +\end{itemdescr} + +\indexunordmem{mapped_type}% +\begin{itemdecl} +typename X::mapped_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{T}. + +\pnum +\remarks +For \tcode{unordered_map} and \tcode{unordered_multimap} only. +\end{itemdescr} + +\indexunordmem{value_type}% +\begin{itemdecl} +typename X::value_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Key} for \tcode{unordered_set} and \tcode{unordered_multiset} only; +\tcode{pair} +for \tcode{unordered_map} and \tcode{unordered_multimap} only. + +\pnum +\expects +\tcode{value_type} is \oldconcept{Erasable} from \tcode{X}. +\end{itemdescr} + +\indexunordmem{hasher}% +\begin{itemdecl} +typename X::hasher +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Hash}. + +\pnum +\expects +\tcode{Hash} is a unary function object type +such that the expression \tcode{hf(k)} has type \tcode{size_t}. +\end{itemdescr} + +\indexunordmem{key_equal}% +\begin{itemdecl} +typename X::key_equal +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Pred}. + +\pnum +\expects +\tcode{Pred} meets the \oldconcept{CopyConstructible} requirements. +\tcode{Pred} is a binary predicate that takes two arguments of type \tcode{Key}. +\tcode{Pred} is an equivalence relation. +\end{itemdescr} + +\indexunordmem{local_iterator}% +\begin{itemdecl} +typename X::local_iterator +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +An iterator type +whose category, value type, difference type, and pointer and reference types +are the same as \tcode{X::iterator}'s. +\begin{note} +A \tcode{local_iterator} object can be used to iterate through a single bucket, +but cannot be used to iterate across buckets. +\end{note} +\end{itemdescr} + +\indexunordmem{const_local_iterator}% +\begin{itemdecl} +typename X::const_local_iterator +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +An iterator type +whose category, value type, difference type, and pointer and reference types +are the same as \tcode{X::const_iterator}'s. +\begin{note} +A \tcode{const_local_iterator} object can be used to iterate +through a single bucket, +but cannot be used to iterate across buckets. +\end{note} +\end{itemdescr} + +\indexunordmem{node_type}% +\begin{itemdecl} +typename X::node_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A specialization of a \exposid{node-handle} class template\iref{container.node}, +such that the public nested types are the same types +as the corresponding types in \tcode{X}. +\end{itemdescr} + +\indexlibraryctor{unordered_set}% +\indexlibraryctor{unordered_map}% +\indexlibraryctor{unordered_multiset}% +\indexlibraryctor{unordered_multimap}% +\begin{itemdecl} +X(n, hf, eq) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{eq} as the key equality predicate. + +\pnum +\complexity +\bigoh{\tcode{n}} +\end{itemdescr} + +\begin{itemdecl} +X(n, hf) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{key_equal()} as the key equality predicate. + +\pnum +\complexity +\bigoh{\tcode{n}} +\end{itemdescr} + +\begin{itemdecl} +X(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{hasher} and \tcode{key_equal} +meet the \oldconcept{DefaultConstructible} requirements. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate. + +\pnum +\complexity +\bigoh{\tcode{n}} +\end{itemdescr} + +\begin{itemdecl} +X a = X(); +X a; +\end{itemdecl} + +\begin{itemdescr} +\expects +\tcode{hasher} and \tcode{key_equal} meet +the \oldconcept{DefaultConstructible} requirements. + +\pnum +\effects +Constructs an empty container with an unspecified number of buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\begin{itemdecl} +X(i, j, n, hf, eq) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{eq} as the key equality predicate, and +inserts elements from \range{i}{j} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(i, j, n, hf) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{\-EmplaceConstructible} into \tcode{X} from \tcode{*i}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \range{i}{j} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(i, j, n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{hasher} and \tcode{key_equal} meet +the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \range{i}{j} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(i, j) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{hasher} and \tcode{key_equal} meet +the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. + +\pnum +\effects +Constructs an empty container with an unspecified number of buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \range{i}{j} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(il) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end())}. +\end{itemdescr} + +\begin{itemdecl} +X(il, n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end(), n)}. +\end{itemdescr} + +\begin{itemdecl} +X(il, n, hf) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end(), n, hf)}. +\end{itemdescr} + +\begin{itemdecl} +X(il, n, hf, eq) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{X(il.begin(), il.end(), n, hf, eq)}. +\end{itemdescr} + +\begin{itemdecl} +X(b) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +In addition to the container requirements\iref{container.requirements.general}, +copies the hash function, predicate, and maximum load factor. + +\pnum +\complexity +Average case linear in \tcode{b.size()}, worst case quadratic. +\end{itemdescr} + +\begin{itemdecl} +a = b +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X\&} + +\pnum +\effects +In addition to the container requirements, +copies the hash function, predicate, and maximum load factor. + +\pnum +\complexity +Average case linear in \tcode{b.size()}, worst case quadratic. +\end{itemdescr} + +\begin{itemdecl} +a = il +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X\&} + +\pnum +\expects +\tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X} +and \oldconcept{CopyAssignable}. + +\pnum +\effects +Assigns the range \range{il.begin()}{il.end()} into \tcode{a}. +All existing elements of \tcode{a} are either assigned to or destroyed. + +\pnum +\complexity +Average case linear in \tcode{il.size()}, worst case quadratic. +\end{itemdescr} + +\indexunordmem{hash_function}% +\begin{itemdecl} +b.hash_function() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{hasher} + +\pnum +\returns +\tcode{b}'s hash function. + +\pnum +\complexity +Constant. +\end{itemdescr} -\begin{note} -A container calls \tcode{allocator_traits::construct(m, p, args)} -to construct an element at \tcode{p} using \tcode{args}, -with \tcode{m == get_allocator()}. -The default \tcode{construct} in \tcode{allocator} will -call \tcode{::new((void*)p) T(args)}, -but specialized allocators can choose a different definition. -\end{note} +\indexunordmem{key_eq}% +\begin{itemdecl} +b.key_eq() +\end{itemdecl} +\begin{itemdescr} \pnum -In \tref{container.alloc.req}, -\begin{itemize} -\item -\tcode{X} denotes an allocator-aware container class -with a \tcode{value_type} of \tcode{T} using allocator of type \tcode{A}, -\item -\tcode{u} denotes a variable, -\item -\tcode{a} and \tcode{b} denote non-const lvalues of type \tcode{X}, -\item -\tcode{t} denotes an lvalue or a const rvalue of type \tcode{X}, -\item -\tcode{rv} denotes a non-const rvalue of type \tcode{X}, and -\item -\tcode{m} is a value of type \tcode{A}. -\end{itemize} +\result +\tcode{key_equal} -% Local command to index names as members of all containers. -\renewcommand{\indexcont}[1]{% -\indexlibrarymisc{#1}{allocator-aware containers}% -\indexlibrarymemberx{deque}{#1}% -\indexlibrarymemberx{forward_list}{#1}% -\indexlibrarymemberx{list}{#1}% -\indexlibrarymemberx{vector}{#1}% -\indexlibrarymemberx{map}{#1}% -\indexlibrarymemberx{set}{#1}% -\indexlibrarymemberx{multiset}{#1}% -\indexlibrarymemberx{multimap}{#1}% -\indexlibrarymemberx{unordered_map}{#1}% -\indexlibrarymemberx{unordered_set}{#1}% -\indexlibrarymemberx{unordered_multiset}{#1}% -\indexlibrarymemberx{unordered_multimap}{#1}% -} +\pnum +\returns +\tcode{b}'s key equality predicate. -\begin{libreqtab4a} -{Allocator-aware container requirements} -{container.alloc.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline - -\lhdr{Expression} & \chdr{Return type} & -\chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endhead +\pnum +\complexity +Constant. +\end{itemdescr} -\indexcont{allocator_type}% -\tcode{allocator_type} & - \tcode{A} & - \mandates \tcode{allocator_type::value_type} is the same as \tcode{X::value_type}. & - compile time \\ \rowsep +\indexunordmem{emplace}% +\begin{itemdecl} +a_uniq.emplace(args) +\end{itemdecl} -\indexcont{get_allocator}% -\tcode{get_-} \tcode{allocator()} & - \tcode{A} & - & - constant \\ \rowsep - -\tcode{X()}\br -\tcode{X u;} & - & - \expects \tcode{A} meets the \oldconcept{DefaultConstructible} requirements.\br - \ensures \tcode{u.empty()} returns \tcode{true}, - \tcode{u.get_allocator() == A()} & - constant \\ \rowsep - -\tcode{X(m)} & - & - \ensures - \tcode{u.empty()} returns \tcode{true}, & - constant \\ -\tcode{X u(m);} & - & -\tcode{u.get_allocator() == m} & - \\ \rowsep - -\tcode{X(t, m)}\br -\tcode{X u(t, m);} & - & - \expects - \tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}.\br - \ensures - \tcode{u == t}, \tcode{u.get_allocator() == m} & - linear \\ \rowsep - -\tcode{X(rv)}\br -\tcode{X u(rv);} - & - & - \ensures \tcode{u} has the same elements as \tcode{rv} had before this - construction; the value of \tcode{u.get_allocator()} is the same as the - value of \tcode{rv.get_allocator()} before this construction. & - constant \\ \rowsep - -\tcode{X(rv, m)}\br -\tcode{X u(rv, m);} & - & - \expects \tcode{T} is - \oldconcept{MoveInsertable} into \tcode{X}.\br - \ensures \tcode{u} has the same elements, - or copies of the elements, that \tcode{rv} had before - this construction, \tcode{u.get_allocator() == m} & - constant if \tcode{m ==} \tcode{rv.get_allocator()}, otherwise linear \\ \rowsep - -\tcode{a = t} & - \tcode{X\&} & - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X} - and \oldconcept{CopyAssignable}.\br - \ensures \tcode{a == t} & - linear \\ \rowsep +\begin{itemdescr} +\pnum +\result +\tcode{pair} -\indexcont{operator=}% -\tcode{a = rv} & - \tcode{X\&} & - \expects If \tcode{allocator_-}\br - \tcode{traits}\br - \tcode{::propagate_on_container_-}\br - \tcode{move_assignment::value} is\br - \tcode{false}, \tcode{T} is - \oldconcept{MoveInsertable} into \tcode{X} and - \oldconcept{MoveAssignable}.\br - \effects All existing elements of \tcode{a} - are either move assigned to or destroyed.\br - \ensures If \tcode{a} and \tcode{rv} do not refer to the same object, - \tcode{a} is equal to the value that \tcode{rv} had before - this assignment. & - linear \\ \rowsep +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. -\indexcont{swap}% -\tcode{a.swap(b)} & - \keyword{void} & - \effects exchanges the contents of \tcode{a} and \tcode{b} & - constant \\ \rowsep +\pnum +\effects +Inserts a \tcode{value_type} object \tcode{t} +constructed with \tcode{std::forward(args)...} if and only if +there is no element in the container +with key equivalent to the key of \tcode{t}. -\end{libreqtab4a} +\pnum +\returns +The \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion takes place, and +the iterator component of the pair points to +the element with key equivalent to the key of \tcode{t}. \pnum -The behavior of certain container member functions and deduction guides -depends on whether types qualify as input iterators or allocators. -The extent to which an implementation determines that a type cannot be an input -iterator is unspecified, except that as a minimum integral types shall not qualify -as input iterators. -Likewise, the extent to which an implementation determines that a type cannot be -an allocator is unspecified, except that as a minimum a type \tcode{A} shall not qualify -as an allocator unless it meets both of the following conditions: +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_uniq.size()}}. +\end{itemdescr} -\begin{itemize} -\item The \grammarterm{qualified-id} \tcode{A::value_type} -is valid and denotes a type\iref{temp.deduct}. +\indexunordmem{emplace}% +\begin{itemdecl} +a_eq.emplace(args) +\end{itemdecl} -\item The expression \tcode{declval().allocate(size_t\{\})} -is well-formed when treated as an unevaluated operand. -\end{itemize} +\begin{itemdescr} +\pnum +\result +\tcode{iterator} -\rSec2[container.requirements.dataraces]{Container data races} +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. \pnum -For purposes of avoiding data races\iref{res.on.data.races}, implementations shall -consider the following functions to be \keyword{const}: \tcode{begin}, \tcode{end}, -\tcode{rbegin}, \tcode{rend}, \tcode{front}, \tcode{back}, \tcode{data}, \tcode{find}, -\tcode{lower_bound}, \tcode{upper_bound}, \tcode{equal_range}, \tcode{at} and, except in -associative or unordered associative containers, \tcode{operator[]}. +\effects +Inserts a \tcode{value_type} object \tcode{t} +constructed with \tcode{std::forward(args)...} and \pnum -Notwithstanding~\ref{res.on.data.races}, implementations are required to avoid data -races when the contents of the contained object in different elements in the same -container, excepting \tcode{vector}, are modified concurrently. +\returns +An iterator pointing to the newly inserted element. \pnum -\begin{note} -For a \tcode{vector x} with a size greater than one, \tcode{x[1] = 5} -and \tcode{*x.begin() = 10} can be executed concurrently without a data race, but -\tcode{x[0] = 5} and \tcode{*x.begin() = 10} executed concurrently can result in a data -race. -As an exception to the general rule, for a \tcode{vector y}, \tcode{y[0] = true} -can race with \tcode{y[1] = true}. -\end{note} +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_eq.size()}}. +\end{itemdescr} -\rSec2[sequence.reqmts]{Sequence containers} +\indexunordmem{emplace_hint}% +\begin{itemdecl} +a.emplace_hint(p, args) +\end{itemdecl} +\begin{itemdescr} \pnum -A sequence container organizes a finite set of objects, all of the same type, into a strictly -linear arrangement. The library provides four basic kinds of sequence containers: -\tcode{vector}, \tcode{forward_list}, \tcode{list}, and \tcode{deque}. In addition, -\tcode{array} is provided as a sequence container which provides limited sequence operations -because it has a fixed number of elements. The library also provides container adaptors that -make it easy to construct abstract data types, such as \tcode{stack}s or \tcode{queue}s, out of -the basic sequence container kinds (or out of other kinds of sequence containers that the user defines). +\result +\tcode{iterator} \pnum -\begin{note} -The sequence containers -offer the programmer different complexity trade-offs. -\tcode{vector} -is appropriate in most circumstances. -\tcode{array} -has a fixed size known during translation. -\tcode{list} or \tcode{forward_list} -support frequent insertions and deletions from the -middle of the sequence. -\tcode{deque} -supports efficient insertions and deletions taking place at the beginning or at the -end of the sequence. -When choosing a container, remember \tcode{vector} is best; -leave a comment to explain if you choose from the rest! -\end{note} +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. \pnum -In Tables~\ref{tab:container.seq.req} -and \ref{tab:container.seq.opt}, -\begin{itemize} -\item -\tcode{X} denotes a sequence container class, -\item -\tcode{a} denotes a value of type \tcode{X} containing elements of type \tcode{T}, -\item -\tcode{u} denotes the name of a variable being declared, -\item -\tcode{A} denotes \tcode{X::allocator_type} if -the \grammarterm{qualified-id} \tcode{X::allocator_type} is valid and denotes a -type\iref{temp.deduct} and -\tcode{allocator} if it doesn't, -\item -\tcode{i} and \tcode{j} -denote iterators that meet the \oldconcept{InputIterator} requirements -and refer to elements implicitly convertible to \tcode{value_type}, -\item -\tcode{[i, j)} denotes a valid range, -\item -\tcode{il} designates an object of type \tcode{initializer_list}, -\item -\tcode{n} denotes a value of type \tcode{X::size_type}, -\item -\tcode{p} denotes a valid constant iterator to \tcode{a}, -\item -\tcode{q} denotes a valid dereferenceable constant iterator to \tcode{a}, -\item -\tcode{[q1, q2)} denotes a valid range of constant iterators in \tcode{a}, -\item -\tcode{t} denotes an lvalue or a const rvalue of \tcode{X::value_type}, and -\item -\tcode{rv} denotes a non-const rvalue of \tcode{X::value_type}. -\item -\tcode{Args} denotes a template parameter pack; -\item -\tcode{args} denotes a function parameter pack with the pattern \tcode{Args\&\&}. -\end{itemize} +\effects +Equivalent to \tcode{a.emplace(std::forward(args)...)}. \pnum -The complexities of the expressions are sequence dependent. +\returns +An iterator pointing to the element +with the key equivalent to the newly inserted element. +The \tcode{const_iterator} \tcode{p} is a hint +pointing to where the search should start. +Implementations are permitted to ignore the hint. -% Local command to index names as members of all containers. -\renewcommand{\indexcont}[1]{% -\indexlibrarymisc{#1}{sequence containers}% -\indexlibrarymemberx{deque}{#1}% -\indexlibrarymemberx{forward_list}{#1}% -\indexlibrarymemberx{list}{#1}% -\indexlibrarymemberx{vector}{#1}% -} +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} -\begin{libreqtab3} -{Sequence container requirements (in addition to container)} -{container.seq.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \rhdr{Assertion/note} \\ - & & \rhdr{pre-/post-condition} \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & \rhdr{Assertion/note} \\ - & & \rhdr{pre-/post-condition} \\ \capsep -\endhead -\tcode{X(n, t)}\br -\tcode{X u(n, t);} & - & - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \ensures \tcode{distance(begin(), end()) == n}\br - \effects Constructs a sequence container with \tcode{n} copies of \tcode{t} \\ \rowsep - -\tcode{X(i, j)}\br -\tcode{X u(i, j);} & - & - \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. - For \tcode{vector}, if the iterator does - not meet the \oldconcept{\-Forward\-Iterator} requirements\iref{forward.iterators}, \tcode{T} - is also - \oldconcept{MoveInsertable} into \tcode{X}.\br - \ensures \tcode{distance(begin(), end()) ==} - \tcode{distance(i, j)}\br - \effects Constructs a sequence container equal to the range \tcode{[i, j)}. - Each iterator in the range \range{i}{j} is dereferenced exactly once. \\ \rowsep - -\tcode{X(il)} & - & - Equivalent to \tcode{X(il.begin(), il.end())} \\ \rowsep - -\tcode{a = il} & - \tcode{X\&} & - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X} - and \oldconcept{CopyAssignable}.\br - \effects Assigns the range \range{il.begin()}{il.end()} into \tcode{a}. All existing - elements of \tcode{a} are either assigned to or destroyed.\br - \returns\ \tcode{*this}. - \\ \rowsep +\indexunordmem{insert}% +\begin{itemdecl} +a_uniq.insert(t) +\end{itemdecl} -\indexcont{emplace}% -\tcode{a.emplace(p, args)} & - \tcode{iterator} & - \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. For \tcode{vector} and \tcode{deque}, - \tcode{T} is also - \oldconcept{MoveInsertable} into \tcode{X} and \oldconcept{MoveAssignable}.\br - \effects Inserts an object of type \tcode{T} constructed with - \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...} before \tcode{p}. - \begin{tailnote} -\tcode{args} can directly or indirectly refer to - a value in \tcode{a}. -\end{tailnote} - \\ \rowsep +\begin{itemdescr} +\pnum +\result +\tcode{pair} -\indexcont{insert}% -\tcode{a.insert(p,t)} & - \tcode{iterator} & - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X}. For \tcode{vector} and \tcode{deque}, - \tcode{T} is also \oldconcept{CopyAssignable}.\br - \effects\ Inserts a copy of \tcode{t} before \tcode{p}. \\ \rowsep - -\tcode{a.insert(p,rv)} & - \tcode{iterator} & - \expects \tcode{T} is - \oldconcept{MoveInsertable} into \tcode{X}. For \tcode{vector} and \tcode{deque}, - \tcode{T} is also \oldconcept{MoveAssignable}.\br - \effects\ Inserts a copy of \tcode{rv} before \tcode{p}. \\ \rowsep - -\tcode{a.insert(p,n,t)} & - \tcode{iterator} & - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X} - and \oldconcept{CopyAssignable}.\br - \effects Inserts \tcode{n} copies of \tcode{t} before \tcode{p}. \\ \rowsep - -\tcode{a.insert(p,i,j)} & - \tcode{iterator} & - \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. - For \tcode{vector} and \tcode{deque}, \tcode{T} is also - \oldconcept{MoveInsertable} into \tcode{X}, \oldconcept{MoveConstructible}, \oldconcept{MoveAssignable}, - and swappable\iref{swappable.requirements}. - Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}.\br - \effects Inserts copies of elements in \tcode{[i, j)} before \tcode{p}. - Each iterator in the range \range{i}{j} shall be dereferenced exactly once. \\ \rowsep - -\tcode{a.insert(p, il)} & - \tcode{iterator} & - \tcode{a.insert(p, il.begin(), il.end())}. \\ \rowsep +\pnum +\expects +If \tcode{t} is a non-const rvalue, +\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X}; +otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}. -\indexcont{erase}% -\tcode{a.erase(q)} & - \tcode{iterator} & - \expects For \tcode{vector} and \tcode{deque}, - \tcode{T} is \oldconcept{MoveAssignable}.\br - \effects\ Erases the element pointed to by \tcode{q}. \\ \rowsep - -\tcode{a.erase(q1,q2)} & - \tcode{iterator} & - \expects For \tcode{vector} and \tcode{deque}, - \tcode{T} is \oldconcept{MoveAssignable}.\br - \effects\ Erases the elements in the range \tcode{[q1, q2)}. \\ \rowsep +\pnum +\effects +Inserts \tcode{t} if and only if there is no element in the container +with key equivalent to the key of \tcode{t}. -\indexcont{clear}% -\tcode{a.clear()} & - \keyword{void} & - \effects Destroys all elements in \tcode{a}. Invalidates all references, pointers, and - iterators referring to the elements of \tcode{a} and may invalidate the past-the-end iterator.\br - \ensures \tcode{a.empty()} is \tcode{true}.\br - \complexity Linear. \\ \rowsep +\pnum +\returns +The \tcode{bool} component of the returned pair indicates +whether the insertion takes place, and +the \tcode{iterator} component points to +the element with key equivalent to the key of \tcode{t}. -\indexcont{assign}% -\tcode{a.assign(i,j)} & - \keyword{void} & - \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i} - and assignable from \tcode{*i}. For \tcode{vector}, if the iterator does not - meet the forward iterator requirements\iref{forward.iterators}, \tcode{T} - is also - \oldconcept{MoveInsertable} into \tcode{X}. - Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}.\br - \effects - Replaces elements in \tcode{a} with a copy of \tcode{[i, j)}. - Invalidates all references, pointers and iterators - referring to the elements of \tcode{a}. - For \tcode{vector} and \tcode{deque}, - also invalidates the past-the-end iterator. - Each iterator in the range \range{i}{j} shall be dereferenced exactly once. \\ \rowsep +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_uniq.size()}}. +\end{itemdescr} + +\indexunordmem{insert}% +\begin{itemdecl} +a_eq.insert(t) +\end{itemdecl} -\tcode{a.assign(il)} & - \keyword{void} & - \tcode{a.assign(il.begin(), il.end())}. \\ \rowsep +\begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\expects +If \tcode{t} is a non-const rvalue, +\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X}; +otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}. -\tcode{a.assign(n,t)} & - \keyword{void} & - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X} - and \oldconcept{CopyAssignable}. - \tcode{t} is not a reference into \tcode{a}.\br - \effects Replaces elements in \tcode{a} with \tcode{n} copies of \tcode{t}. - Invalidates all references, pointers and iterators - referring to the elements of \tcode{a}. - For \tcode{vector} and \tcode{deque}, - also invalidates the past-the-end iterator. \\ -\end{libreqtab3} +\pnum +\effects +Inserts \tcode{t}. \pnum -The iterator returned from -\tcode{a.insert(p, t)} -points to the copy of -\tcode{t} -inserted into -\tcode{a}. +\returns +An iterator pointing to the newly inserted element. \pnum -The iterator returned from \tcode{a.insert(p, rv)} points to the copy of \tcode{rv} -inserted into \tcode{a}. +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_eq.size()}}. +\end{itemdescr} + +\indexunordmem{insert}% +\begin{itemdecl} +a.insert(p, t) +\end{itemdecl} +\begin{itemdescr} \pnum -The iterator returned from \tcode{a.insert(p, n, t)} points to the copy of the first -element inserted into \tcode{a}, or \tcode{p} if \tcode{n == 0}. +\result +\tcode{iterator} \pnum -The iterator returned from \tcode{a.insert(p, i, j)} points to the copy of the first -element inserted into \tcode{a}, or \tcode{p} if \tcode{i == j}. +\expects +If \tcode{t} is a non-const rvalue, +\tcode{value_type} is \oldconcept{MoveInsertable} into \tcode{X}; +otherwise, \tcode{value_type} is \oldconcept{CopyInsertable} into \tcode{X}. \pnum -The iterator returned from \tcode{a.insert(p, il)} points to the copy of the first -element inserted into \tcode{a}, or \tcode{p} if \tcode{il} is empty. +\effects +Equivalent to \tcode{a.insert(t)}. +The iterator \tcode{p} is a hint pointing to where the search should start. +Implementations are permitted to ignore the hint. \pnum -The iterator returned from \tcode{a.emplace(p, args)} points to the new element -constructed from \tcode{args} into \tcode{a}. +\returns +An iterator pointing to +the element with the key equivalent to that of \tcode{t}. \pnum -The iterator returned from -\tcode{a.erase(q)} -points to the element immediately following -\tcode{q} -prior to the element being erased. -If no such element exists, -\tcode{a.end()} -is returned. +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} + +\indexunordmem{insert}% +\begin{itemdecl} +a.insert(i, j) +\end{itemdecl} +\begin{itemdescr} \pnum -The iterator returned by -\tcode{a.erase(q1, q2)} -points to the element pointed to by -\tcode{q2} -prior to any elements being erased. -If no such element exists, -\tcode{a.end()} -is returned. +\result +\keyword{void} \pnum -For every sequence container defined in this Clause and in \ref{strings}: -\begin{itemize} -\item If the constructor -\begin{codeblock} -template - X(InputIterator first, InputIterator last, - const allocator_type& alloc = allocator_type()); -\end{codeblock} -is called with a type \tcode{InputIterator} that does not qualify as an input -iterator, then the constructor -shall not participate in overload resolution. +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. +Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}. -\item If the member functions of the forms: -\begin{codeblock} -template - @\placeholdernc{return-type}@ @\placeholdernc{F}@(const_iterator p, - InputIterator first, InputIterator last); // such as \tcode{insert} +\pnum +\effects +Equivalent to \tcode{a.insert(t)} for each element in \tcode{[i,j)}. -template - @\placeholdernc{return-type}@ @\placeholdernc{F}@(InputIterator first, InputIterator last); // such as \tcode{append}, \tcode{assign} +\pnum +\complexity +Average case \bigoh{N}, where $N$ is \tcode{distance(i, j)}, +worst case \bigoh{N(\tcode{a.size()} + 1)}. +\end{itemdescr} -template - @\placeholdernc{return-type}@ @\placeholdernc{F}@(const_iterator i1, const_iterator i2, - InputIterator first, InputIterator last); // such as \tcode{replace} -\end{codeblock} -are called with a type \tcode{InputIterator} that does not qualify as an input -iterator, then these functions -shall not participate in overload resolution. +\indexunordmem{insert}% +\begin{itemdecl} +a.insert(il) +\end{itemdecl} -\item A deduction guide for a sequence container shall not participate in overload resolution -if it has an \tcode{InputIterator} template parameter and a type that does not -qualify as an input iterator is deduced for that parameter, -or if it has an \tcode{Allocator} template parameter and a type that does not -qualify as an allocator is deduced for that parameter. -\end{itemize} +\begin{itemdescr} +\pnum +\result +\keyword{void} \pnum -\tref{container.seq.opt} lists operations -that are provided for some types of -sequence containers but not others. -An implementation shall provide -these operations for all container types shown in the ``container'' -column, and shall implement them so as to take amortized constant -time. - -\begin{libreqtab4a} -{Optional sequence container operations} -{container.seq.opt} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Operational semantics} & \rhdr{Container} \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & \chdr{Operational semantics} & \rhdr{Container} \\ \capsep -\endhead - -\tcode{a.front()} & - \tcode{reference; const_reference} for constant \tcode{a} & - \tcode{*a.begin()} & - \tcode{basic_string}, - \tcode{array}, - \tcode{deque}, - \tcode{forward_list}, - \tcode{list}, - \tcode{vector} - \\ \rowsep - -\tcode{a.back()} & - \tcode{reference; const_reference} for constant \tcode{a} & - \tcode{\{ auto tmp = a.end();}\br - \tcode{ --tmp;}\br - \tcode{ return *tmp; \}} & - \tcode{basic_string}, - \tcode{array}, - \tcode{deque}, - \tcode{list}, - \tcode{vector} - \\ \rowsep - -\tcode{a.emplace_\-front(args)} & - \tcode{reference} & - \effects Prepends an object of type \tcode{T} constructed with \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...}.\br - \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.\br - \returns \tcode{a.front()}. & - \tcode{deque}, - \tcode{forward_list}, - \tcode{list} - \\ \rowsep - -\tcode{a.emplace_\-back(args)} & - \tcode{reference} & - \effects Appends an object of type \tcode{T} constructed with \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...}.\br - \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. For \tcode{vector}, \tcode{T} - is also - \oldconcept{MoveInsertable} into \tcode{X}. - \returns \tcode{a.back()}. & - \tcode{deque}, - \tcode{list}, - \tcode{vector} - \\ \rowsep - -\tcode{a.push_front(t)} & - \keyword{void} & - \effects Prepends a copy of \tcode{t}.\br - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X}. - & - \tcode{deque}, - \tcode{forward_list}, - \tcode{list} - \\ \rowsep - -\tcode{a.push_front(rv)} & - \keyword{void} & - \effects Prepends a copy of \tcode{rv}.\br - \expects \tcode{T} is - \oldconcept{MoveInsertable} into \tcode{X}. - & - \tcode{deque}, - \tcode{forward_list}, - \tcode{list} - \\ \rowsep - -\tcode{a.push_back(t)} & - \keyword{void} & - \effects Appends a copy of \tcode{t}.\br - \expects \tcode{T} is - \oldconcept{CopyInsertable} into \tcode{X}. - & - \tcode{basic_string}, - \tcode{deque}, - \tcode{list}, - \tcode{vector} - \\ \rowsep - -\tcode{a.push_back(rv)} & - \keyword{void} & - \effects Appends a copy of \tcode{rv}.\br - \expects \tcode{T} is - \oldconcept{MoveInsertable} into \tcode{X}. - & - \tcode{basic_string}, - \tcode{deque}, - \tcode{list}, - \tcode{vector} - \\ \rowsep - -\tcode{a.pop_front()} & - \keyword{void} & - \effects Destroys the first element.\br - \expects \tcode{a.empty()} is \tcode{false}. & - \tcode{deque}, - \tcode{forward_list}, - \tcode{list} - \\ \rowsep - -\tcode{a.pop_back()} & - \keyword{void} & - \effects Destroys the last element.\br - \expects \tcode{a.empty()} is \tcode{false}. & - \tcode{basic_string}, - \tcode{deque}, - \tcode{list}, - \tcode{vector} - \\ \rowsep - -\tcode{a[n]} & - \tcode{reference; const_reference} for constant \tcode{a} & - \tcode{*(a.begin() + n)} & - \tcode{basic_string}, - \tcode{array}, - \tcode{deque}, - \tcode{vector} - \\ \rowsep - -\tcode{a.at(n)} & - \tcode{reference; const_reference} for constant \tcode{a} & - \tcode{*(a.begin() + n)} & - \tcode{basic_string}, - \tcode{array}, - \tcode{deque}, - \tcode{vector} - \\ - -\end{libreqtab4a} - -\pnum -The member function -\tcode{at()} -provides bounds-checked access to container elements. -\tcode{at()} -throws -\tcode{out_of_range} -if -\tcode{n >= a.size()}. +\effects +Equivalent to \tcode{a.insert(il.begin(), il.end())}. +\end{itemdescr} +\indexunordmem{insert}% +\begin{itemdecl} +a_uniq.insert(nh) +\end{itemdecl} -\rSec2[container.node]{Node handles} +\begin{itemdescr} +\pnum +\result +\tcode{insert_return_type} -\rSec3[container.node.overview]{Overview} +\pnum +\expects +\tcode{nh} is empty or +\tcode{a_uniq.get_allocator() == nh.get_allocator()} is \tcode{true}. \pnum -A \defn{node handle} is an object that accepts ownership of a single element -from an associative container\iref{associative.reqmts} or an unordered -associative container\iref{unord.req}. It may be used to transfer that -ownership to another container with compatible nodes. Containers with -compatible nodes have the same node handle type. Elements may be transferred in -either direction between container types in the same row of -\tref{container.node.compat}. +\effects +If \tcode{nh} is empty, has no effect. +Otherwise, inserts the element owned by \tcode{nh} if and only if +there is no element in the container with a key equivalent to \tcode{nh.key()}. -\begin{floattable}{Container types with compatible nodes}{container.node.compat} -{ll} -\topline -\tcode{map} & \tcode{map} \\ -\rowsep -\tcode{map} & \tcode{multimap} \\ -\rowsep -\tcode{set} & \tcode{set} \\ -\rowsep -\tcode{set} & \tcode{multiset} \\ -\rowsep -\tcode{unordered_map} & \tcode{unordered_map} \\ -\rowsep -\tcode{unordered_map} & \tcode{unordered_multimap} \\ -\rowsep -\tcode{unordered_set} & \tcode{unordered_set} \\ -\rowsep -\tcode{unordered_set} & \tcode{unordered_multiset} \\ -\end{floattable} +\pnum +\ensures +If \tcode{nh} is empty, \tcode{inserted} is \tcode{false}, +\tcode{position} is \tcode{end()}, and \tcode{node} is empty. +Otherwise if the insertion took place, \tcode{inserted} is \tcode{true}, +\tcode{position} points to the inserted element, and \tcode{node} is empty; +if the insertion failed, \tcode{inserted} is \tcode{false}, +\tcode{node} has the previous value of \tcode{nh}, and \tcode{position} +points to an element with a key equivalent to \tcode{nh.key()}. \pnum -If a node handle is not empty, then it contains an allocator that is equal to -the allocator of the container when the element was extracted. If a node handle -is empty, it contains no allocator. +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_uniq.size()}}. +\end{itemdescr} + +\indexunordmem{insert}% +\begin{itemdecl} +a_eq.insert(nh) +\end{itemdecl} +\begin{itemdescr} \pnum -Class \exposid{node-handle} is for exposition only. +\result +\tcode{iterator} \pnum -If a user-defined specialization of \tcode{pair} exists for -\tcode{pair} or \tcode{pair}, where \tcode{Key} is the -container's \tcode{key_type} and \tcode{T} is the container's -\tcode{mapped_type}, the behavior of operations involving node handles is -undefined. +\expects +\tcode{nh} is empty or +\tcode{a_eq.get_allocator() == nh.get_allocator()} is \tcode{true}. -\begin{codeblock} -template<@\unspecnc@> -class @\placeholder{node-handle}@ { -public: - // These type declarations are described in Tables \ref{tab:container.assoc.req} and \ref{tab:container.hash.req}. - using value_type = @\seebelownc{}@; // not present for map containers - using key_type = @\seebelownc{}@; // not present for set containers - using mapped_type = @\seebelownc{}@; // not present for set containers - using allocator_type = @\seebelownc{}@; +\pnum +\effects +If \tcode{nh} is empty, has no effect and returns \tcode{a_eq.end()}. +Otherwise, inserts the element owned by \tcode{nh} and +returns an iterator pointing to the newly inserted element. -private: - using container_node_type = @\unspecnc@; // \expos - using ator_traits = allocator_traits; // \expos +\pnum +\ensures +\tcode{nh} is empty. - typename ator_traits::template - rebind_traits::pointer ptr_; // \expos - optional alloc_; // \expos +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_eq.size()}}. +\end{itemdescr} -public: - // \ref{container.node.cons}, constructors, copy, and assignment - constexpr @\placeholdernc{node-handle}@() noexcept : ptr_(), alloc_() {} - @\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&&) noexcept; - @\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&&); +\indexunordmem{insert}% +\begin{itemdecl} +a.insert(q, nh) +\end{itemdecl} - // \ref{container.node.dtor}, destructor - ~@\placeholdernc{node-handle}@(); +\begin{itemdescr} +\pnum +\result +\tcode{iterator} - // \ref{container.node.observers}, observers - value_type& value() const; // not present for map containers - key_type& key() const; // not present for set containers - mapped_type& mapped() const; // not present for set containers +\pnum +\expects +\tcode{nh} is empty or +\tcode{a.get_allocator() == nh.get_allocator()} is \tcode{true}. - allocator_type get_allocator() const; - explicit operator bool() const noexcept; - [[nodiscard]] bool empty() const noexcept; +\pnum +\effects +If \tcode{nh} is empty, has no effect and returns \tcode{a.end()}. +Otherwise, inserts the element owned by \tcode{nh} if and only if +there is no element with key equivalent to \tcode{nh.key()} +in containers with unique keys; +always inserts the element owned by \tcode{nh} +in containers with equivalent keys. +The iterator \tcode{q} is a hint pointing to where the search should start. +Implementations are permitted to ignore the hint. - // \ref{container.node.modifiers}, modifiers - void swap(@\placeholdernc{node-handle}@&) - noexcept(ator_traits::propagate_on_container_swap::value || - ator_traits::is_always_equal::value); +\ensures +\tcode{nh} is empty if insertion succeeds, unchanged if insertion fails. - friend void swap(@\placeholdernc{node-handle}@& x, @\placeholdernc{node-handle}@& y) noexcept(noexcept(x.swap(y))) { - x.swap(y); - } -}; -\end{codeblock} +\pnum +\returns +An iterator pointing to the element with key equivalent to \tcode{nh.key()}. -\rSec3[container.node.cons]{Constructors, copy, and assignment} +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} +\indexunordmem{extract}% \begin{itemdecl} -@\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&& nh) noexcept; +a.extract(k) \end{itemdecl} \begin{itemdescr} +\pnum +\result +\tcode{node_type} + \pnum \effects -Constructs a \exposid{node-handle} object initializing -\tcode{ptr_} with \tcode{nh.ptr_}. Move constructs \tcode{alloc_} with -\tcode{nh.alloc_}. Assigns \keyword{nullptr} to \tcode{nh.ptr_} and assigns -\tcode{nullopt} to \tcode{nh.alloc_}. +Removes an element in the container with key equivalent to \tcode{k}. + +\pnum +\returns +A \tcode{node_type} owning the element if found, +otherwise an empty \tcode{node_type}. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. \end{itemdescr} +\indexunordmem{extract}% \begin{itemdecl} -@\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&& nh); +a_tran.extract(kx) \end{itemdecl} \begin{itemdescr} \pnum -\expects -Either \tcode{!alloc_}, or -\tcode{ator_traits::propagate_on_container_move_assignment::\-value} -is \tcode{true}, or \tcode{alloc_ == nh.alloc_}. +\result +\tcode{node_type} \pnum \effects -\begin{itemize} -\item -If \tcode{ptr_ != nullptr}, destroys the \tcode{value_type} -subobject in the \tcode{container_node_type} object pointed to by \tcode{ptr_} -by calling \tcode{ator_traits::destroy}, then deallocates \tcode{ptr_} by -calling \tcode{ator_traits::template rebind_traits::deallocate}. -\item -Assigns \tcode{nh.ptr_} to \tcode{ptr_}. -\item -If \tcode{!alloc\textunderscore} or \tcode{ator_traits::propagate_on_container_move_assignment::value} -is \tcode{true}, \linebreak -move assigns \tcode{nh.alloc_} to \tcode{alloc_}. -\item -Assigns -\keyword{nullptr} to \tcode{nh.ptr_} and assigns \tcode{nullopt} to -\tcode{nh.alloc_}. -\end{itemize} +Removes an element in the container with key equivalent to \tcode{kx}. \pnum \returns -\tcode{*this}. +A \tcode{node_type} owning the element if found, +otherwise an empty \tcode{node_type}. \pnum -\throws -Nothing. +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_tran.size()}}. \end{itemdescr} -\rSec3[container.node.dtor]{Destructor} - +\indexunordmem{extract}% \begin{itemdecl} -~@\placeholdernc{node-handle}@(); +a.extract(q) \end{itemdecl} \begin{itemdescr} +\pnum +\result +\tcode{node_type} + \pnum \effects -If \tcode{ptr_ != nullptr}, destroys the \tcode{value_type} subobject -in the \tcode{container_node_type} object pointed to by \tcode{ptr_} by calling -\tcode{ator_traits::destroy}, then deallocates \tcode{ptr_} by calling -\tcode{ator_traits::template rebind_traits::deallocate}. -\end{itemdescr} +Removes the element pointed to by \tcode{q}. -\rSec3[container.node.observers]{Observers} +\returns +A \tcode{node_type} owning that element. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} +\indexunordmem{merge}% \begin{itemdecl} -value_type& value() const; +a.merge(a2) \end{itemdecl} \begin{itemdescr} +\pnum +\result +\keyword{void} + \pnum \expects -\tcode{empty() == false}. +\tcode{a.get_allocator() == a2.get_allocator()}. \pnum -\returns -A reference to the \tcode{value_type} subobject in the -\tcode{container_node_type} object pointed to by \tcode{ptr_}. +\effects +Attempts to extract each element in \tcode{a2} and insert it into \tcode{a} +using the hash function and key equality predicate of \tcode{a}. +In containers with unique keys, if there is an element in \tcode{a} +with key equivalent to the key of an element from \tcode{a2}, +then that element is not extracted from \tcode{a2}. \pnum -\throws -Nothing. +\ensures +Pointers and references to the transferred elements of \tcode{a2} refer to +those same elements but as members of \tcode{a}. +Iterators referring to the transferred elements and +all iterators referring to \tcode{a} will be invalidated, +but iterators to elements remaining in \tcode{a2} will remain valid. + +\pnum +\complexity +Average case \bigoh{N}, where $N$ is \tcode{a2.size()}, +worst case \bigoh{N\tcode{*a.size() + N}}. \end{itemdescr} +\indexunordmem{erase}% \begin{itemdecl} -key_type& key() const; +a.erase(k) \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{empty() == false}. +\result +\tcode{size_type} \pnum -\returns -A non-const reference to the \tcode{key_type} member of the -\tcode{value_type} subobject in the \tcode{contain\-er_node_type} object -pointed to by \tcode{ptr_}. +\effects +Erases all elements with key equivalent to \tcode{k}. \pnum -\throws -Nothing. +\returns +The number of elements erased. \pnum -\remarks -Modifying the key through the returned reference is permitted. +\complexity +Average case \bigoh{\tcode{a.count(k)}}, worst case \bigoh{\tcode{a.size()}}. \end{itemdescr} +\indexunordmem{erase}% \begin{itemdecl} -mapped_type& mapped() const; +a_tran.erase(kx) \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{empty() == false}. +\result +\tcode{size_type} + +\pnum +\effects +Erases all elements with key equivalent to \tcode{kx}. \pnum \returns -A reference to the \tcode{mapped_type} member of the -\tcode{value_type} subobject in the \tcode{container_node_type} object -pointed to by \tcode{ptr_}. +The number of elements erased. \pnum -\throws -Nothing. +\complexity +Average case \bigoh{\tcode{a_tran.count(kx)}}, +worst case \bigoh{\tcode{a_tran.size()}}. \end{itemdescr} - +\indexunordmem{erase}% \begin{itemdecl} -allocator_type get_allocator() const; +a.erase(q) \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{empty() == false}. +\result +\tcode{iterator} + +\pnum +\effects +Erases the element pointed to by \tcode{q}. \pnum \returns -\tcode{*alloc_}. +The iterator immediately following \tcode{q} prior to the erasure. \pnum -\throws -Nothing. +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. \end{itemdescr} +\indexunordmem{erase}% \begin{itemdecl} -explicit operator bool() const noexcept; +a.erase(r) \end{itemdecl} \begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Erases the element pointed to by \tcode{r}. + \pnum \returns -\tcode{ptr_ != nullptr}. +The iterator immediately following \tcode{r} prior to the erasure. + +\pnum +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. \end{itemdescr} +\indexunordmem{erase}% \begin{itemdecl} -[[nodiscard]] bool empty() const noexcept; +a.erase(q1, q2) \end{itemdecl} \begin{itemdescr} +\pnum +\result +\tcode{iterator} + +\pnum +\effects +Erases all elements in the range \tcode{[q1, q2)}. + \pnum \returns -\tcode{ptr_ == nullptr}. -\end{itemdescr} +The iterator immediately following the erased elements prior to the erasure. -\rSec3[container.node.modifiers]{Modifiers} +\pnum +\complexity +Average case linear in \tcode{distance(q1, q2)}, +worst case \bigoh{\tcode{a.size()}}. +\end{itemdescr} +\indexunordmem{clear}% \begin{itemdecl} -void swap(@\placeholdernc{node-handle}@& nh) - noexcept(ator_traits::propagate_on_container_swap::value || - ator_traits::is_always_equal::value); +a.clear() \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{!alloc_}, or \tcode{!nh.alloc_}, or -\tcode{ator_traits::propagate_on_container_swap::value} is \tcode{true}, -or \tcode{alloc_ == nh.alloc_}. +\result +\keyword{void} \pnum \effects -Calls \tcode{swap(ptr_, nh.ptr_)}. If \tcode{!alloc_}, or -\tcode{!nh.alloc_}, or \tcode{ator_traits::propagate_on_container_swap::value} -is \tcode{true} calls \tcode{swap(alloc_, nh.alloc_)}. -\end{itemdescr} - -\rSec2[container.insert.return]{Insert return type} +Erases all elements in the container. \pnum -The associative containers with unique keys and the unordered containers with unique keys -have a member function \tcode{insert} that returns a nested type \tcode{insert_return_type}. -That return type is a specialization of the template specified in this subclause. - -\begin{codeblock} -template -struct @\placeholder{insert-return-type}@ -{ - Iterator position; - bool inserted; - NodeType node; -}; -\end{codeblock} +\ensures +\tcode{a.empty()} is \tcode{true}. \pnum -The name \exposid{insert-return-type} is exposition only. -\exposid{insert-return-type} has the template parameters, -data members, and special members specified above. -It has no base classes or members other than those specified. +\complexity +Linear in \tcode{a.size()}. +\end{itemdescr} -\rSec2[associative.reqmts]{Associative containers} +\indexunordmem{find}% +\begin{itemdecl} +b.find(k) +\end{itemdecl} -\rSec3[associative.reqmts.general]{General} +\begin{itemdescr} +\pnum +\result +\tcode{iterator}; \tcode{const_iterator} for const \tcode{b}. \pnum -Associative containers provide fast retrieval of data based on keys. -The library provides four basic kinds of associative containers: -\tcode{set}, -\tcode{multiset}, -\tcode{map} -and -\tcode{multimap}. +\returns +An iterator pointing to an element with key equivalent to \tcode{k}, or +\tcode{b.end()} if no such element exists. \pnum -Each associative container is parameterized on -\tcode{Key} -and an ordering relation -\tcode{Compare} -that induces a strict weak ordering\iref{alg.sorting} on -elements of -\tcode{Key}. -In addition, -\tcode{map} -and -\tcode{multimap} -associate an arbitrary \term{mapped type} -\tcode{T} -with the -\tcode{Key}. -The object of type -\tcode{Compare} -is called the -\term{comparison object} -of a container. +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{b.size()}}. +\end{itemdescr} + +\indexunordmem{find}% +\begin{itemdecl} +a_tran.find(ke) +\end{itemdecl} +\begin{itemdescr} \pnum -The phrase ``equivalence of keys'' means the equivalence relation imposed by the -comparison object. -That is, two keys -\tcode{k1} -and -\tcode{k2} -are considered to be equivalent if for the -comparison object -\tcode{comp}, -\tcode{comp(k1, k2) == false \&\& comp(k2, k1) == false}. -\begin{note} -This is not necessarily the same as the result of \tcode{k1 == k2}. -\end{note} -For any two keys -\tcode{k1} -and -\tcode{k2} -in the same container, calling -\tcode{comp(k1, k2)} -shall always return the same value. +\result +\tcode{iterator}; \tcode{const_iterator} for const \tcode{a_tran}. \pnum -An associative container supports \term{unique keys} if it may contain at -most one element for each key. Otherwise, it supports \term{equivalent keys}. -The \tcode{set} and \tcode{map} classes support unique keys; the \tcode{multiset} -and \tcode{multimap} classes support equivalent keys. -For \tcode{multiset} and \tcode{multimap}, -\tcode{insert}, \tcode{emplace}, and \tcode{erase} preserve the relative ordering -of equivalent elements. +\returns +An iterator pointing to an element with key equivalent to \tcode{ke}, or +\tcode{a_tran.end()} if no such element exists. \pnum -For \tcode{set} and \tcode{multiset} the value type is the same as the key type. -For \tcode{map} and \tcode{multimap} it is equal to \tcode{pair}. +\complexity +Average case \bigoh{1}, worst case \bigoh{\tcode{a_tran.size()}}. +\end{itemdescr} +\indexunordmem{count}% +\begin{itemdecl} +b.count(k) +\end{itemdecl} + +\begin{itemdescr} \pnum -\tcode{iterator} -of an associative container is of the bidirectional iterator category. -For associative containers where the value type is the same as the key type, both -\tcode{iterator} -and -\tcode{const_iterator} -are constant iterators. It is unspecified whether or not -\tcode{iterator} -and -\tcode{const_iterator} -are the same type. -\begin{note} -\tcode{iterator} and \tcode{const_iterator} have identical semantics in this case, and \tcode{iterator} is convertible to \tcode{const_iterator}. Users can avoid violating the one-definition rule by always using \tcode{const_iterator} in their function parameter lists. -\end{note} +\result +\tcode{size_type} \pnum -The associative containers meet all the requirements of Allocator-aware -containers\iref{container.requirements.general}, except that for -\tcode{map} and \tcode{multimap}, the requirements placed on \tcode{value_type} -in \tref{container.alloc.req} apply instead to \tcode{key_type} -and \tcode{mapped_type}. -\begin{note} -For example, in some cases \tcode{key_type} and \tcode{mapped_type} -are required to be \oldconcept{CopyAssignable} even though the associated -\tcode{value_type}, \tcode{pair}, is not -\oldconcept{CopyAssignable}. -\end{note} +\returns +The number of elements with key equivalent to \tcode{k}. \pnum -In \tref{container.assoc.req}, -\begin{itemize} -\item -\tcode{X} denotes an associative container class, -\item -\tcode{a} denotes a value of type \tcode{X}, -\item -\tcode{a2} denotes a value of a type with nodes compatible with type -\tcode{X} (\tref{container.node.compat}), -\item -\tcode{b} denotes a possibly \keyword{const} value of type \tcode{X}, -\item -\tcode{u} denotes the name of a variable being declared, -\item -\tcode{a_uniq} denotes a value of type \tcode{X} -when \tcode{X} supports unique keys, -\item -\tcode{a_eq} denotes a value of type \tcode{X} -when \tcode{X} supports multiple keys, -\item -\tcode{a_tran} denotes a possibly \keyword{const} value of type \tcode{X} -when the \grammarterm{qualified-id} -\tcode{X::key_compare::is_transpa\-rent} is valid -and denotes a type\iref{temp.deduct}, -\item -\tcode{i} and \tcode{j} -meet the \oldconcept{InputIterator} requirements and refer to elements -implicitly convertible to -\tcode{value_type}, -\item -\range{i}{j} denotes a valid range, -\item -\tcode{p} denotes a valid constant iterator to \tcode{a}, -\item -\tcode{q} denotes a valid dereferenceable constant iterator to \tcode{a}, -\item -\tcode{r} denotes a valid dereferenceable iterator to \tcode{a}, -\item -\tcode{[q1, q2)} denotes a valid range of constant iterators in \tcode{a}, -\item -\tcode{il} designates an object of type \tcode{initializer_list}, -\item -\tcode{t} denotes a value of type \tcode{X::value_type}, -\item -\tcode{k} denotes a value of type \tcode{X::key_type}, and -\item -\tcode{c} denotes a possibly \keyword{const} value of type \tcode{X::key_compare}; -\item -\tcode{kl} is a value such that \tcode{a} is partitioned\iref{alg.sorting} -with respect to \tcode{c(x, kl)}, -with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}; -\item -\tcode{ku} is a value such that \tcode{a} is partitioned with respect to -\tcode{!c(ku, x)}, -with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}; -\item -\tcode{ke} is a value such that \tcode{a} is partitioned with respect to -\tcode{c(x, ke)} and \tcode{!c(ke, x)}, with \tcode{c(x, ke)} implying -\tcode{!c(ke, x)} and -with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}; -\item -\tcode{kx} is a value such that -\begin{itemize} -\item -\tcode{a} is partitioned with respect to \tcode{c(x, kx)} and \tcode{!c(kx, x)}, -with \tcode{c(x, kx)} implying \tcode{!c(kx, x)} and -with \tcode{x} the key value of \tcode{e} and \tcode{e} in \tcode{a}, and -\item -\tcode{kx} is not convertible to -either \tcode{iterator} or \tcode{const_iterator}; and -\end{itemize} -\item -\tcode{A} denotes the storage allocator used by \tcode{X}, if any, or \tcode{allocator} otherwise, -\item -\tcode{m} denotes an allocator of a type convertible to \tcode{A}, -and \tcode{nh} denotes a non-const rvalue of type \tcode{X::node_type}. -\end{itemize} +\complexity +Average case \bigoh{\tcode{b.count(k)}}, worst case \bigoh{\tcode{b.size()}}. +\end{itemdescr} + +\indexunordmem{count}% +\begin{itemdecl} +a_tran.count(ke) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{size_type} -% Local command to index names as members of all ordered containers. -\newcommand{\indexordmem}[1]{% -\indexlibrary{\idxcode{#1}!ordered associative containers}% -\indexlibrary{\idxcode{set}!\idxcode{#1}}% -\indexlibrary{\idxcode{map}!\idxcode{#1}}% -\indexlibrary{\idxcode{multiset}!\idxcode{#1}}% -\indexlibrary{\idxcode{multimap}!\idxcode{#1}}% -} +\pnum +\returns +The number of elements with key equivalent to \tcode{ke}. -\begin{libreqtab4b} -{Associative container requirements (in addition to container)} -{container.assoc.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & \chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endhead +\pnum +\complexity +Average case \bigoh{\tcode{a_tran.count(ke)}}, +worst case \bigoh{\tcode{a_tran.size()}}. +\end{itemdescr} -\indexordmem{key_type}% -\tcode{X::key_type} & - \tcode{Key} & - & - compile time \\ \rowsep +\indexunordmem{contains}% +\begin{itemdecl} +b.contains(k) +\end{itemdecl} -\indexordmem{mapped_type}% -\tcode{X::mapped_type} (\tcode{map} and \tcode{multimap} only) & - \tcode{T} & - & - compile time \\ \rowsep +\begin{itemdescr} +\pnum +\result +\tcode{bool} -\indexordmem{value_type}% -\tcode{X::value_type} (\tcode{set} and \tcode{multiset} only) & - \tcode{Key} & - \expects \tcode{value_type} is \oldconcept{Erasable} from \tcode{X} & - compile time \\ \rowsep +\pnum +\effects +Equivalent to \tcode{b.find(k) != b.end()}. +\end{itemdescr} -\tcode{X::value_type} (\tcode{map} and \tcode{multimap} only) & - \tcode{pair} & - \expects \tcode{value_type} is \oldconcept{Erasable} from \tcode{X} & - compile time \\ \rowsep +\indexunordmem{contains}% +\begin{itemdecl} +a_tran.contains(ke) +\end{itemdecl} -\indexordmem{key_compare}% -\tcode{X::key_compare} & - \tcode{Compare} & - \expects \tcode{key_compare} is \oldconcept{CopyConstructible}. & - compile time \\ \rowsep +\begin{itemdescr} +\pnum +\result +\tcode{bool} -\indexordmem{value_compare}% -\tcode{X::value_compare} & - a binary predicate type & - is the same as \tcode{key_compare} for \tcode{set} and - \tcode{multiset}; is an ordering relation on pairs induced by the - first component (i.e., \tcode{Key}) for \tcode{map} and \tcode{multimap}. & - compile time \\ \rowsep +\pnum +\effects +Equivalent to \tcode{a_tran.find(ke) != a_tran.end()}. +\end{itemdescr} -\indexordmem{node_type}% -\tcode{X::node_type} & - A specialization of a \exposid{node-handle} - class template, such that the public nested types are - the same types as the corresponding types in \tcode{X}. & - see~\ref{container.node} & - compile time \\ \rowsep +\indexunordmem{equal_range}% +\begin{itemdecl} +b.equal_range(k) +\end{itemdecl} -\indexlibraryctor{set}% -\indexlibraryctor{map}% -\indexlibraryctor{multiset}% -\indexlibraryctor{multimap}% -\tcode{X(c)}\br -\tcode{X u(c);} & - & - \effects\ Constructs an empty container. - Uses a copy of \tcode{c} as a comparison object. & - constant \\ \rowsep - -\tcode{X()}\br\tcode{X u;} & - & - \expects \tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements.\br - \effects\ Constructs an empty container. - Uses \tcode{Compare()} as a comparison object & - constant \\ \rowsep - -\tcode{X(i,j,c)}\br -\tcode{X~u(i,j,c);} & - & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.\br - \effects\ Constructs an empty container and inserts elements from the - range \tcode{[i, j)} into it; uses \tcode{c} as a comparison object. & - $N \log N$ in general, where $N$ has the value \tcode{distance(i, j)}; - linear if \tcode{[i, j)} is sorted with \tcode{value_comp()} \\ \rowsep - -\tcode{X(i,j)}\br\tcode{X~u(i,j);} & - & - \expects \tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements. - \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.\br - \effects\ Same as above, but uses \tcode{Compare()} as a comparison object. & - same as above \\ \rowsep - -\tcode{X(il)} & - & - same as \tcode{X(il.begin(), il.end())} & - same as \tcode{X(il.begin(), il.end())} \\ \rowsep - -\tcode{X(il,c)} & - & - same as \tcode{X(il.begin(), il.end(), c)} & - same as \tcode{X(il.begin(), il.end(), c)} \\ \rowsep - -\tcode{a = il} & - \tcode{X\&} & - \expects \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X} - and \oldconcept{CopyAssignable}.\br - \effects Assigns the range \range{il.begin()}{il.end()} into \tcode{a}. All - existing elements of \tcode{a} are either assigned to or destroyed. & - $N \log N$ in general, where $N$ has the value \tcode{il.size() + a.size()}; - linear if \range{il.begin()}{il.end()} is sorted with \tcode{value_comp()} - \\ \rowsep +\begin{itemdescr} +\pnum +\result +\tcode{pair}; +\tcode{pair} for const \tcode{b}. -\indexordmem{key_comp}% -\tcode{b.key_comp()} & - \tcode{X::key_compare} & - \returns the comparison object out of which \tcode{b} was constructed. & - constant \\ \rowsep +\pnum +\returns +A range containing all elements with keys equivalent to \tcode{k}. +Returns \tcode{make_pair(b.end(), b.end())} if no such elements exist. -\indexordmem{value_comp}% -\tcode{b.value_comp()} & - \tcode{X::value_compare} & - \returns an object of \tcode{value_compare} constructed out of the comparison object & - constant \\ \rowsep +\pnum +\complexity +Average case \bigoh{\tcode{b.count(k)}}, worst case \bigoh{\tcode{b.size()}}. +\end{itemdescr} -\indexordmem{emplace}% -\tcode{a_uniq.\brk{}emplace(\brk{}args)} & - \tcode{pair<\brk{}iterator, bool>} & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.\br - \effects\ Inserts a \tcode{value_type} object \tcode{t} constructed with - \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...} if and only if there is no - element in the container with key equivalent to the key of \tcode{t}. - The \tcode{bool} component of the returned - pair is \tcode{true} if and only if the insertion takes place, and the iterator - component of the pair points to the element with key equivalent to the - key of \tcode{t}. & - logarithmic \\ \rowsep - -\tcode{a_eq.\brk{}emplace(\brk{}args)} & - \tcode{iterator} & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.\br - \effects\ Inserts a \tcode{value_type} object \tcode{t} constructed with - \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...} and returns the iterator pointing - to the newly inserted element. - If a range containing elements equivalent to \tcode{t} exists in \tcode{a_eq}, - \tcode{t} is inserted at the end of that range. & - logarithmic \\ \rowsep +\indexunordmem{equal_range}% +\begin{itemdecl} +a_tran.equal_range(ke) +\end{itemdecl} -\indexordmem{emplace_hint}% -\tcode{a.emplace_\-hint(\brk{}p, args)} & - \tcode{iterator} & - \effects - Equivalent to \tcode{a.emplace(} \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...)}. - Return value is an iterator pointing to the element with the key equivalent - to the newly inserted element. - The element is inserted as close as possible to the position just prior - to \tcode{p}. & - logarithmic in general, but amortized constant if the element - is inserted right before \tcode{p} \\ \rowsep +\begin{itemdescr} +\pnum +\result +\tcode{pair}; +\tcode{pair} for const \tcode{a_tran}. -\indexordmem{insert}% -\tcode{a_uniq.\brk{}insert(\brk{}t)} & - \tcode{pair<\brk{}iterator, bool>} & - \expects If \tcode{t} is a non-const rvalue, \tcode{value_type} is - \oldconcept{MoveInsertable} into \tcode{X}; otherwise, \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \effects\ Inserts \tcode{t} if and only if there is no element in the container - with key equivalent to the key of \tcode{t}. The \tcode{bool} component of - the returned pair is \tcode{true} if and only if the insertion - takes place, and the \tcode{iterator} - component of the pair points to the element with key - equivalent to the key of \tcode{t}. & - logarithmic \\ \rowsep - -\tcode{a_eq.\brk{}insert(\brk{}t)} & - \tcode{iterator} & - \expects If \tcode{t} is a non-const rvalue, \tcode{value_type} is - \oldconcept{MoveInsertable} into \tcode{X}; otherwise, \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \effects\ Inserts \tcode{t} and returns the iterator pointing - to the newly inserted element. - If a range containing elements equivalent to - \tcode{t} exists in \tcode{a_eq}, \tcode{t} - is inserted at the end of that range. & - logarithmic \\ \rowsep - -\tcode{a.\brk{}insert(\brk{}p, t)} & - \tcode{iterator} & - \expects If \tcode{t} is a non-const rvalue, \tcode{value_type} is - \oldconcept{MoveInsertable} into \tcode{X}; otherwise, \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \effects\ Inserts \tcode{t} if and only if there is no element with key - equivalent to the key of \tcode{t} in containers with unique keys; - always inserts \tcode{t} in containers with equivalent keys. Always - returns the iterator pointing to the element with key equivalent to - the key of \tcode{t}. \tcode{t} is inserted as close as possible to the position - just prior to \tcode{p}.& - logarithmic in general, but amortized constant if \tcode{t} - is inserted right before \tcode{p}. \\ \rowsep - -\tcode{a.\brk{}insert(\brk{}i, j)} & - \keyword{void} & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. - Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}.\br - \effects Inserts each element from the range \range{i}{j} if and only if there - is no element with key equivalent to the key of that element in containers - with unique keys; always inserts that element in containers with equivalent keys. & - $N \log (\tcode{a.size()} + N)$, where $N$ has the value \tcode{distance(i, j)} \\ \rowsep - -\tcode{a.\brk{}insert(\brk{}il)} & - \keyword{void} & - \effects - Equivalent to \tcode{a.insert(il.begin(), il.end())} & - \\ \rowsep - -\tcode{a_uniq.\brk{}insert(\brk{}nh)} & - \tcode{insert_return_type} & - \expects \tcode{nh} is empty or - \tcode{a_uniq.get_allocator() == nh.get_allocator()}.\br - \effects If \tcode{nh} is empty, has no effect. Otherwise, inserts the - element owned by \tcode{nh} if and only if there is no element in the - container with a key equivalent to \tcode{nh.key()}.\br - \ensures If \tcode{nh} is empty, \tcode{inserted} is \tcode{false}, - \tcode{position} is \tcode{end()}, and \tcode{node} is empty. - Otherwise if the insertion took place, \tcode{inserted} is \tcode{true}, - \tcode{position} points to the inserted element, and \tcode{node} is empty; - if the insertion failed, \tcode{inserted} is \tcode{false}, - \tcode{node} has the previous value of \tcode{nh}, and \tcode{position} - points to an element with a key equivalent to \tcode{nh.key()}. & - logarithmic \\ \rowsep - -\tcode{a_eq.\brk{}insert(\brk{}nh)} & - \tcode{iterator} & - \expects \tcode{nh} is empty or - \tcode{a_eq.get_allocator() == nh.get_allocator()}.\br - \effects If \tcode{nh} is empty, has no effect and returns \tcode{a_eq.end()}. - Otherwise, inserts the element owned by \tcode{nh} and returns an iterator - pointing to the newly inserted element. If a range containing elements with - keys equivalent to \tcode{nh.key()} exists in \tcode{a_eq}, the element is - inserted at the end of that range.\br - \ensures \tcode{nh} is empty. & - logarithmic \\ \rowsep - -\tcode{a.\brk{}insert(\brk{}p, nh)} & - \tcode{iterator} & - \expects \tcode{nh} is empty or - \tcode{a.get_allocator() == nh.get_allocator()}.\br - \effects If \tcode{nh} is empty, has no effect and returns \tcode{a.end()}. - Otherwise, inserts the element owned by \tcode{nh} if and only if there - is no element with key equivalent to \tcode{nh.key()} in containers with - unique keys; always inserts the element owned by \tcode{nh} in containers - with equivalent keys. Always returns the iterator pointing to the element - with key equivalent to \tcode{nh.key()}. The element is inserted as close - as possible to the position just prior to \tcode{p}.\br - \ensures \tcode{nh} is empty if insertion succeeds, unchanged if insertion fails. & - logarithmic in general, but amortized constant if the element is inserted right - before \tcode{p}. \\ \rowsep +\pnum +\returns +A range containing all elements with keys equivalent to \tcode{ke}. +Returns \tcode{make_pair(a_tran.end(), a_tran.end())} if no such elements exist. -\indexordmem{extract}% -\tcode{a.\brk{}extract(\brk{}k)} & - \tcode{node_type} & - \effects Removes the first element in the container with key equivalent to \tcode{k}.\br - \returns A \tcode{node_type} owning the element if found, otherwise an empty - \tcode{node_type}. & - $\log (\tcode{a.size()})$ \\ \rowsep - -\tcode{a_tran.\brk{}extract(\brk{}kx)} & - \tcode{node_type} & - \effects Removes the first element in the container with key \tcode{r} - such that \tcode{!c(r, kx) \&\& !c(kx, r)} is \tcode{true}.\br - \returns A \tcode{node_type} owning the element if found, - otherwise an empty \tcode{node_type}. & - $\log(\tcode{a_tran.size()})$ \\ \rowsep - -\tcode{a.\brk{}extract(\brk{}q)} & - \tcode{node_type} & - \effects Removes the element pointed to by \tcode{q}.\br - \returns A \tcode{node_type} owning that element. & - amortized constant \\ \rowsep +\pnum +\complexity +Average case \bigoh{\tcode{a_tran.count(ke)}}, +worst case \bigoh{\tcode{a_tran.size()}}. +\end{itemdescr} -\indexordmem{merge}% -\tcode{a.merge(a2)} & - \keyword{void} & - \expects \tcode{a.get_allocator() == a2.get_allocator()}.\br - \effects Attempts to extract each element in \tcode{a2} and insert it into \tcode{a} - using the comparison object of \tcode{a}. In containers with unique keys, - if there is an element in \tcode{a} with key equivalent to the key of an - element from \tcode{a2}, then that element is not extracted from \tcode{a2}.\br - \ensures Pointers and references to the transferred elements of \tcode{a2} - refer to those same elements but as members of \tcode{a}. Iterators referring - to the transferred elements will continue to refer to their elements, but - they now behave as iterators into \tcode{a}, not into \tcode{a2}.\br - \throws Nothing unless the comparison object throws. & - $N \log(\tcode{a.size()+} N)$, where $N$ has the value \tcode{a2.size()}. \\ \rowsep +\indexunordmem{bucket_count}% +\begin{itemdecl} +b.bucket_count() +\end{itemdecl} -\indexordmem{erase}% -\tcode{a.erase(k)} & - \tcode{size_type} & - \effects Erases all elements in the container with key equivalent to - \tcode{k}.\br - \returns The number of erased elements. & - $\log (\tcode{a.size()}) + \tcode{a.count(k)}$ \\ \rowsep - -\tcode{a_tran.\brk{}erase(kx)} & - \tcode{size_type} & - \effects Erases all elements in the container with key \tcode{r} - such that \tcode{!c(r, kx) \&\& !c(kx, r)} is \tcode{true}.\br - \returns The number of erased elements. & - $\log(\tcode{a_tran.size())} + \tcode{a_tran.count(kx)}$ \\ \rowsep - -\tcode{a.erase(q)} & - \tcode{iterator} & - \effects Erases the element pointed to by \tcode{q}.\br - \returns An iterator pointing to - the element immediately following \tcode{q} prior to the element being erased. - If no such element exists, returns \tcode{a.end()}. & - amortized constant \\ \rowsep - -\tcode{a.erase(r)} & - \tcode{iterator} & - \effects Erases the element pointed to by \tcode{r}.\br - \returns An iterator pointing to - the element immediately following \tcode{r} prior to the element being erased. - If no such element exists, returns \tcode{a.end()}. & - amortized constant \\ \rowsep - -\tcode{a.erase(}\br - \tcode{q1, q2)} & - \tcode{iterator} & - \effects Erases all the elements in the range \range{q1}{q2}.\br - \returns An iterator pointing to - the element pointed to by \tcode{q2} prior to any elements being erased. If no such element - exists, \tcode{a.end()} is returned. & - $\log(\tcode{a.size()}) + N$, where $N$ has the value \tcode{distance(q1, q2)}. \\ \rowsep +\begin{itemdescr} +\pnum +\result +\tcode{size_type} -\indexordmem{clear}% -\tcode{a.clear()} & - \keyword{void} & - \effects Equivalent to \tcode{a.erase(a.begin(), a.end())}.\br - \ensures \tcode{a.empty()} is \tcode{true}. & - linear in \tcode{a.size()}. \\ \rowsep +\pnum +\returns +The number of buckets that \tcode{b} contains. -\indexordmem{find}% -\tcode{b.find(k)} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{b}. & - \returns An iterator pointing to an element with the key equivalent - to \tcode{k}, or \tcode{b.end()} if such an element is not found. & - logarithmic \\ \rowsep - -\tcode{a_tran.}\br - \tcode{find(ke)} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}. & - \returns An iterator pointing to an element with key \tcode{r} such that - \tcode{!c(r, ke) \&\& !c(ke, r)}, or \tcode{a_tran.end()} if such an element - is not found. & - logarithmic \\ \rowsep +\pnum +\complexity +Constant. +\end{itemdescr} -\indexordmem{count}% -\tcode{b.count(k)} & - \tcode{size_type} & - \returns The number of elements with key equivalent to \tcode{k}. & - $\log (\tcode{b.size()}) + \tcode{b.count(k)}$ \\ \rowsep - -\tcode{a_tran.}\br - \tcode{count(ke)} & - \tcode{size_type} & - \returns The number of elements with key \tcode{r} such that - \tcode{!c(r, ke) \&\& !c(ke, r)} & - $\log (\tcode{a_tran.size()}) + \tcode{a_tran.count(ke)}$ \\ \rowsep +\indexunordmem{max_bucket_count}% +\begin{itemdecl} +b.max_bucket_count() +\end{itemdecl} -\indexordmem{contains}% -\tcode{b.}\br - \tcode{contains(k)} & - \tcode{bool} & - \effects Equivalent to: \tcode{return b.find(k) != b.end();} & - logarithmic \\ \rowsep - -\tcode{a_tran.}\br - \tcode{con\-tains(ke)} & - \tcode{bool} & - \effects Equivalent to: \tcode{return a_tran.find(ke) != a_tran.end();} & - logarithmic \\ \rowsep +\begin{itemdescr} +\pnum +\result +\tcode{size_type} -\indexordmem{lower_bound}% -\tcode{b.lower_bound(k)} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{b}. & - \returns An iterator pointing to the first element with - key not less than \tcode{k}, - or \tcode{b.end()} if such an element is not found. & - logarithmic \\ \rowsep - -\tcode{a_tran.}\br - \tcode{lower_bound(kl)} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}. & - \returns An iterator pointing to the first element with - key \tcode{r} such that \tcode{!c(r, kl)}, - or \tcode{a_tran.end()} if such an element is not found. & - logarithmic \\ \rowsep +\pnum +\returns +An upper bound on the number of buckets that \tcode{b} can ever contain. -\indexordmem{upper_bound}% -\tcode{b.upper_bound(k)} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{b}. & - \returns An iterator pointing to the first element with - key greater than \tcode{k}, - or \tcode{b.end()} if such an element is not found. & - logarithmic \\ \rowsep - -\tcode{a_tran.}\br - \tcode{upper_bound(ku)} & - \tcode{iterator}; \tcode{const_iterator} for constant \tcode{a_tran}. & - \returns An iterator pointing to the first element with - key \tcode{r} such that \tcode{c(ku, r)}, - or \tcode{a_tran.end()} if such an element is not found. & - logarithmic \\ \rowsep +\pnum +\complexity +Constant. +\end{itemdescr} -\indexordmem{equal_range}% -\tcode{b.equal_range(k)} & - \tcode{pair<\brk{}iterator, iterator>}; - \tcode{pair<\brk{}const_iterator, const_iterator>} for constant \tcode{b}. & - \effects Equivalent to: \tcode{return make_pair(b.lower_bound(k), b.upper_bound(k));} & - logarithmic \\ \rowsep - -\tcode{a_tran.}\br - \tcode{equal_range(ke)} & - \tcode{pair<\brk{}iterator, iterator>}; - \tcode{pair<\brk{}const_iterator, const_iterator>} for constant \tcode{a_tran}. & - \effects Equivalent to: \tcode{return make_pair(}\br - \tcode{a_tran.lower_bound(ke), a_tran.upper_bound(ke));} & - logarithmic \\ -\end{libreqtab4b} +\indexunordmem{bucket}% +\begin{itemdecl} +b.bucket(k) +\end{itemdecl} +\begin{itemdescr} \pnum -The \tcode{insert} and \tcode{emplace} members shall not affect the validity of -iterators and references to the container, -and the \tcode{erase} members shall invalidate only iterators and -references to the erased elements. +\result +\tcode{size_type} \pnum -The \tcode{extract} members invalidate only iterators to the removed element; -pointers and references to the removed element remain valid. However, accessing -the element through such pointers and references while the element is owned by -a \tcode{node_type} is undefined behavior. References and pointers to an element -obtained while it is owned by a \tcode{node_type} are invalidated if the element -is successfully inserted. +\expects +\tcode{b.bucket_count() > 0}. \pnum -The fundamental property of iterators of associative containers is that they iterate through the containers -in the non-descending order of keys where non-descending is defined by the comparison that was used to -construct them. -For any two dereferenceable iterators -\tcode{i} -and -\tcode{j} -such that distance from -\tcode{i} -to -\tcode{j} -is positive, the following condition holds: +\returns +The index of the bucket +in which elements with keys equivalent to \tcode{k} would be found, +if any such element existed. +The return value is in the range \tcode{[0, b.bucket_count())}. -\begin{codeblock} -value_comp(*j, *i) == false -\end{codeblock} +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexunordmem{bucket_size}% +\begin{itemdecl} +b.bucket_size(n) +\end{itemdecl} +\begin{itemdescr} \pnum -For associative containers with unique keys the stronger condition holds: +\result +\tcode{size_type} -\begin{codeblock} -value_comp(*i, *j) != false -\end{codeblock} +\pnum +\expects +\tcode{n} shall be in the range \tcode{[0, b.bucket_count())}. \pnum -When an associative container is constructed by passing a comparison object the -container shall not store a pointer or reference to the passed object, -even if that object is passed by reference. -When an associative container is copied, through either a copy constructor -or an assignment operator, -the target container shall then use the comparison object from the container -being copied, -as if that comparison object had been passed to the target container in -its constructor. +\returns +The number of elements in the $\tcode{n}^\text{th}$ bucket. \pnum -The member function templates -\tcode{find}, \tcode{count}, \tcode{contains}, -\tcode{lower_bound}, \tcode{upper_bound}, \tcode{equal_range}, -\tcode{erase}, and \tcode{extract} -shall not participate in overload resolution unless -the \grammarterm{qualified-id} \tcode{Compare::is_transparent} is valid -and denotes a type\iref{temp.deduct}. -Additionally, the member function templates \tcode{extract} and \tcode{erase} -shall not participate in overload resolution if -\tcode{is_convertible_v || is_convertible_v} -is \tcode{true}, -where \tcode{K} is the type substituted as the first template argument. +\complexity +\bigoh{\tcode{b.bucket_size(n)}} +\end{itemdescr} + +\indexunordmem{begin}% +\begin{itemdecl} +b.begin(n) +\end{itemdecl} +\begin{itemdescr} \pnum -A deduction guide for an associative container shall not participate in overload resolution -if any of the following are true: -\begin{itemize} -\item It has an \tcode{InputIterator} template parameter -and a type that does not qualify as an input iterator is deduced for that parameter. +\result +\tcode{local_iterator}; \tcode{const_local_iterator} for const \tcode{b}. -\item It has an \tcode{Allocator} template parameter -and a type that does not qualify as an allocator is deduced for that parameter. +\pnum +\expects +\tcode{n} is in the range \tcode{[0, b.bucket_count())}. -\item It has a \tcode{Compare} template parameter -and a type that qualifies as an allocator is deduced for that parameter. -\end{itemize} +\pnum +\returns +An iterator referring to the first element in the bucket. +If the bucket is empty, then \tcode{b.begin(n) == b.end(n)}. -\rSec3[associative.reqmts.except]{Exception safety guarantees}% -\indextext{associative containers!exception safety}% -\indextext{associative containers!requirements}% +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexunordmem{end}% +\begin{itemdecl} +b.end(n) +\end{itemdecl} +\begin{itemdescr} \pnum -For associative containers, no \tcode{clear()} function throws an exception. -\tcode{erase(k)} does not throw an exception unless that exception is thrown -by the container's \tcode{Compare} object (if any). +\result +\tcode{local_iterator}; \tcode{const_local_iterator} for const \tcode{b}. \pnum -For associative containers, if an exception is thrown by any operation from -within an \tcode{insert} or \tcode{emplace} function inserting a single element, the -insertion has no effect. +\expects +\tcode{n} is in the range \tcode{[0, b.bucket_count())}. \pnum -For associative containers, no \tcode{swap} function throws an exception unless -that exception is thrown by the -swap of the container's \tcode{Compare} object (if any). +\returns +An iterator which is the past-the-end value for the bucket. -\rSec2[unord.req]{Unordered associative containers}% -\indextext{associative containers!unordered|see{unordered associative containers}} -\indextext{hash tables|see{unordered associative containers}} +\pnum +\complexity +Constant. +\end{itemdescr} -\rSec3[unord.req.general]{General} +\indexunordmem{cbegin}% +\begin{itemdecl} +b.cbegin(n) +\end{itemdecl} +\begin{itemdescr} \pnum -\indextext{unordered associative containers!complexity}% -Unordered associative containers provide an ability for fast retrieval -of data based on keys. The worst-case complexity for most operations -is linear, but the average case is much faster. The library provides -four unordered associative containers: \tcode{unordered_set}, -\tcode{unordered_map}, \tcode{unordered_multiset}, and -\tcode{unordered_multimap}. +\result +\tcode{const_local_iterator} \pnum -\indextext{unordered associative containers!lack of comparison functions}% -\indextext{unordered associative containers!requirements}% -\indextext{requirements!container!not required for unordered associated containers}% -Unordered associative containers conform to the requirements for -Containers\iref{container.requirements}, except that -the expressions -\tcode{a == b} and \tcode{a != b} have different semantics than for the other -container types. +\expects +\tcode{n} shall be in the range \tcode{[0, b.bucket_count())}. \pnum -Each unordered associative container is parameterized by \tcode{Key}, -by a function object type \tcode{Hash} that meets the \oldconcept{Hash} -requirements\iref{hash.requirements} and acts as a hash function for -argument values of type \tcode{Key}, and by a binary predicate \tcode{Pred} -that induces an equivalence relation on values of type \tcode{Key}. -Additionally, \tcode{unordered_map} and \tcode{unordered_multimap} associate -an arbitrary \textit{mapped type} \tcode{T} with the \tcode{Key}. +\returns +An iterator referring to the first element in the bucket. +If the bucket is empty, then \tcode{b.cbegin(n) == b.cend(n)}. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexunordmem{cend}% +\begin{itemdecl} +b.cend(n) +\end{itemdecl} +\begin{itemdescr} \pnum -\indextext{unordered associative containers!hash function}% -\indextext{hash function}% -The container's object of type \tcode{Hash} --- denoted by -\tcode{hash} --- is called the \term{hash function} of the -container. The container's object of type \tcode{Pred} --- -denoted by \tcode{pred} --- is called the -\term{key equality predicate} of the container. +\result +\tcode{const_local_iterator} \pnum -\indextext{unordered associative containers!equality function}% -Two values \tcode{k1} and \tcode{k2} are -considered equivalent if the container's -key equality predicate -\tcode{pred(k1, k2)} is valid and returns -\tcode{true} when passed those values. If \tcode{k1} and -\tcode{k2} are equivalent, the container's hash function shall -return the same value for both. -\begin{note} -Thus, when an unordered associative container is instantiated with -a non-default \tcode{Pred} parameter it usually needs a non-default \tcode{Hash} -parameter as well. -\end{note} -For any two keys \tcode{k1} and \tcode{k2} in the same container, -calling \tcode{pred(k1, k2)} shall always return the same value. -For any key \tcode{k} in a container, calling \tcode{hash(k)} -shall always return the same value. +\expects +\tcode{n} is in the range \tcode{[0, b.bucket_count())}. \pnum -\indextext{unordered associative containers!unique keys}% -\indextext{unordered associative containers!equivalent keys}% -An unordered associative container supports \textit{unique keys} if it -may contain at most one element for each key. Otherwise, it supports -\textit{equivalent keys}. \tcode{unordered_set} and \tcode{unordered_map} -support unique keys. \tcode{unordered_multiset} and \tcode{unordered_multimap} -support equivalent keys. In containers that support equivalent keys, -elements with equivalent keys are adjacent to each other -in the iteration order of the container. Thus, although the absolute order -of elements in an unordered container is not specified, its elements are -grouped into \defnx{equivalent-key groups}{equivalent-key group} such that all elements of each -group have equivalent keys. Mutating operations on unordered containers shall -preserve the relative order of elements within each equivalent-key group -unless otherwise specified. +\returns +An iterator which is the past-the-end value for the bucket. \pnum -For \tcode{unordered_set} and \tcode{unordered_multiset} the value type is -the same as the key type. For \tcode{unordered_map} and -\tcode{unordered_multimap} it is \tcode{pair}. +\complexity +Constant. +\end{itemdescr} -\pnum -For unordered containers where the value type is the same as the key -type, both \tcode{iterator} and \tcode{const_iterator} are constant -iterators. It is unspecified whether or not \tcode{iterator} and -\tcode{const_iterator} are the same type. -\begin{note} -\tcode{iterator} and \tcode{const_iterator} have identical -semantics in this case, and \tcode{iterator} is convertible to -\tcode{const_iterator}. Users can avoid violating the one-definition rule -by always using \tcode{const_iterator} in their function parameter lists. -\end{note} +\indexunordmem{load_factor}% +\begin{itemdecl} +b.load_factor() +\end{itemdecl} +\begin{itemdescr} \pnum -\indextext{buckets}% -\indextext{hash code}% -The elements of an unordered associative container are organized into -\textit{buckets}. Keys with the same hash code appear in the same -bucket. The number of buckets is automatically increased as elements -are added to an unordered associative container, so that the average -number of elements per bucket is kept below a bound. Rehashing -invalidates iterators, changes ordering between elements, and changes -which buckets elements appear in, but does not invalidate pointers or -references to elements. For \tcode{unordered_multiset} and -\tcode{unordered_multimap}, rehashing preserves the relative ordering of -equivalent elements. +\result +\tcode{float} \pnum -The unordered associative containers meet all the requirements of Allocator-aware -containers\iref{container.requirements.general}, except that for -\tcode{unordered_map} and \tcode{unordered_multimap}, the requirements placed on \tcode{value_type} -in \tref{container.alloc.req} apply instead to \tcode{key_type} -and \tcode{mapped_type}. -\begin{note} -For example, \tcode{key_type} and \tcode{mapped_type} -are sometimes required to be \oldconcept{CopyAssignable} even though the associated -\tcode{value_type}, \tcode{pair}, is not -\oldconcept{CopyAssignable}. -\end{note} +\returns +The average number of elements per bucket. \pnum -\indextext{unordered associative containers}% -\indextext{unordered associative containers!requirements}% -\indextext{requirements!unordered associative container}% -\indextext{unordered associative containers!unique keys}% -\indextext{unordered associative containers!equivalent keys}% -\indextext{requirements!container}% -In \tref{container.hash.req}, -\begin{itemize} -\item -\tcode{X} denotes an unordered associative container class, -\item -\tcode{a} denotes a value of type \tcode{X}, -\item -\tcode{a2} denotes a value of a type with nodes compatible - with type \tcode{X} (\tref{container.node.compat}), -\item -\tcode{b} denotes a possibly const value of type \tcode{X}, -\item -\tcode{a_uniq} denotes a value of type \tcode{X} - when \tcode{X} supports unique keys, -\item -\tcode{a_eq} denotes a value of type \tcode{X} - when \tcode{X} supports equivalent keys, -\item -\tcode{a_tran} denotes a possibly const value of type \tcode{X} - when the \grammarterm{qualified-id}s - \tcode{X::key_equal::is_transparent} and - \tcode{X::hasher::is_transparent} - are both valid and denote types\iref{temp.deduct}, -\item -\tcode{i} and \tcode{j} denote input iterators - that refer to \tcode{value_type}, -\item -\tcode{[i, j)} denotes a valid range, -\item -\tcode{p} and \tcode{q2} denote valid constant iterators to \tcode{a}, -\item -\tcode{q} and \tcode{q1} denote - valid dereferenceable constant iterators to \tcode{a}, -\item -\tcode{r} denotes a valid dereferenceable iterator to \tcode{a}, -\item -\tcode{[q1, q2)} denotes a valid range in \tcode{a}, -\item -\tcode{il} denotes a value of type \tcode{initializer_list}, -\item -\tcode{t} denotes a value of type \tcode{X::value_type}, -\item -\tcode{k} denotes a value of type \tcode{key_type}, -\item -\tcode{hf} denotes a possibly const value of type \tcode{hasher}, -\item -\tcode{eq} denotes a possibly const value of type \tcode{key_equal}, -\item -\tcode{ke} is a value such that - \begin{itemize} - \item \tcode{eq(r1, ke) == eq(ke, r1)}, - \item \tcode{hf(r1) == hf(ke)} if \tcode{eq(r1, ke)} is \tcode{true}, and - \item \tcode{(eq(r1, ke) \&\& eq(r1, r2)) == eq(r2, ke)}, - \end{itemize} - where \tcode{r1} and \tcode{r2} are keys of elements in \tcode{a_tran}, -\item -\tcode{kx} is a value such that - \begin{itemize} - \item \tcode{eq(r1, kx) == eq(kx, r1)}, - \item \tcode{hf(r1) == hf(kx)} if \tcode{eq(r1, kx)} is \tcode{true}, - \item \tcode{(eq(r1, kx) \&\& eq(r1, r2)) == eq(r2, kx)}, and - \item \tcode{kx} is not convertible to - either \tcode{iterator} or \tcode{const_iterator}, - \end{itemize} - where \tcode{r1} and \tcode{r2} are keys of elements in \tcode{a_tran}, -\item -\tcode{n} denotes a value of type \tcode{size_type}, -\item -\tcode{z} denotes a value of type \tcode{float}, and -\item -\tcode{nh} denotes a non-const rvalue of type \tcode{X::node_type}. -\end{itemize} +\complexity +Constant. +\end{itemdescr} -% Local command to index names as members of all unordered containers. -\newcommand{\indexunordmem}[1]{% -\indexlibrary{\idxcode{#1}!unordered associative containers}% -\indexlibrary{\idxcode{unordered_set}!\idxcode{#1}}% -\indexlibrary{\idxcode{unordered_map}!\idxcode{#1}}% -\indexlibrary{\idxcode{unordered_multiset}!\idxcode{#1}}% -\indexlibrary{\idxcode{unordered_multimap}!\idxcode{#1}}% -} +\indexunordmem{max_load_factor}% +\begin{itemdecl} +b.max_load_factor() +\end{itemdecl} -\begin{libreqtab4d} - {Unordered associative container requirements (in addition to container)} - {container.hash.req} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & \chdr{Assertion/note} & \rhdr{Complexity} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endhead -%% -\indexunordmem{key_type}% -\tcode{X::key_type} & - \tcode{Key} & - & - compile time \\ \rowsep +\begin{itemdescr} +\pnum +\result +\tcode{float} -\indexunordmem{mapped_type}% -\tcode{X::mapped_type} (\tcode{unordered_map} and \tcode{unordered_multimap} only) & - \tcode{T} & - & - compile time \\ \rowsep +\pnum +\returns +A positive number +that the container attempts to keep the load factor less than or equal to. +The container automatically increases the number of buckets as necessary +to keep the load factor below this number. -\indexunordmem{value_type}% -\tcode{X::value_type} (\tcode{unordered_set} and \tcode{unordered_multiset} only) & - \tcode{Key} & - \expects \tcode{value_type} is \oldconcept{Erasable} from \tcode{X} & - compile time \\ \rowsep +\pnum +\complexity +Constant. +\end{itemdescr} -\tcode{X::value_type} (\tcode{unordered_map} and \tcode{unordered_multimap} only) & - \tcode{pair} & - \expects \tcode{value_type} is \oldconcept{Erasable} from \tcode{X} & - compile time \\ \rowsep +\indexunordmem{max_load_factor}% +\begin{itemdecl} +a.max_load_factor(z) +\end{itemdecl} -\indexunordmem{hasher}% -\tcode{X::hasher} -& \tcode{Hash} -& \expects \tcode{Hash} is a unary function object type such that the expression - \tcode{hf(k)} has type \tcode{size_t}.% -& compile time -\\ \rowsep -% -\indexunordmem{key_equal}% -\tcode{X::key_equal} -& \tcode{Pred} -& \expects \tcode{Pred} meets the \oldconcept{CopyConstructible} requirements.\br - \tcode{Pred} is a binary predicate that takes two arguments - of type \tcode{Key}. \tcode{Pred} is an equivalence relation.% -& compile time -\\ \rowsep -% -\indexunordmem{local_iterator}% -\tcode{X::local_iterator} -& An iterator type whose category, value type, - difference type, and pointer and reference types are the same as - \tcode{X::iterator}'s. \indextext{\idxcode{local_iterator}} -& A \tcode{local_iterator} object may be used to iterate through a - single bucket, but may not be used to iterate across - buckets.% -& compile time -\\ \rowsep -% -\indexunordmem{const_local_iterator}% -\tcode{X::const_local_iterator} -& An iterator type whose category, value type, - difference type, and pointer and reference types are the same as - \tcode{X::const_iterator}'s. \indextext{\idxcode{const_local_iterator}} -& A \tcode{const_local_iterator} object may be used to iterate through a - single bucket, but may not be used to iterate across - buckets.% -& compile time -\\ \rowsep -% -\indexunordmem{node_type}% -\tcode{X::node_type} & - a specialization of a \exposid{node-handle} - class template, such that the public nested types are - the same types as the corresponding types in \tcode{X}. & - see~\ref{container.node} & - compile time \\ \rowsep -% -\indexlibraryctor{unordered_set}% -\indexlibraryctor{unordered_map}% -\indexlibraryctor{unordered_multiset}% -\indexlibraryctor{unordered_multimap}% -\tcode{X(n, hf, eq)}\br \tcode{X a(n, hf, eq);} -& \tcode{X} -& \effects\ Constructs an empty container with at least \tcode{n} buckets, -using \tcode{hf} as the hash function and \tcode{eq} as the key -equality predicate. -& \bigoh{\tcode{n}} -\\ \rowsep -% -\tcode{X(n, hf)}\br \tcode{X a(n, hf);} -& \tcode{X} -& \expects \tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements.\br - \effects\ Constructs an empty container with at least \tcode{n} buckets, -using \tcode{hf} as the hash function and \tcode{key_equal()} as the key -equality predicate. -& \bigoh{\tcode{n}} -\\ \rowsep -% -\tcode{X(n)}\br \tcode{X a(n);} -& \tcode{X} -& \expects \tcode{hasher} and \tcode{key_equal} meet the \oldconcept{DefaultConstructible} requirements.\br - \effects\ Constructs an empty container with at least \tcode{n} buckets, -using \tcode{hasher()} as the hash function and \tcode{key_equal()} -as the key equality predicate. -& \bigoh{\tcode{n}} -\\ \rowsep -% -\tcode{X()}\br \tcode{X a;} -& \tcode{X} -& \expects \tcode{hasher} and \tcode{key_equal} meet the \oldconcept{DefaultConstructible} requirements.\br - \effects\ Constructs an empty container with an unspecified number of - buckets, using \tcode{hasher()} as the hash function and - \tcode{key_equal()} as the key equality predicate. -& constant -\\ \rowsep -% -\tcode{X(i, j, n, hf, eq)}\br \tcode{X a(i, j, n, hf, eq);} -& \tcode{X} -& \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.\br - \effects\ Constructs an empty container with at least \tcode{n} buckets, -using \tcode{hf} as the hash function and \tcode{eq} as the key -equality predicate, and inserts elements from \tcode{[i, j)} into it. -& Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case -\bigoh{N^2} -\\ \rowsep -% -\tcode{X(i, j, n, hf)}\br \tcode{X a(i, j, n, hf);} -& \tcode{X} -& \expects \tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements. - \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.\br - \effects\ Constructs an empty container with at least \tcode{n} buckets, -using \tcode{hf} as the hash function and \tcode{key_equal()} as the key -equality predicate, and inserts elements from \tcode{[i, j)} into it. -& Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case -\bigoh{N^2} -\\ \rowsep -% -\tcode{X(i, j, n)}\br \tcode{X a(i, j, n);} -& \tcode{X} -& \expects \tcode{hasher} and \tcode{key_equal} meet the \oldconcept{DefaultConstructible} requirements. - \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.\br - \effects\ Constructs an empty container with at least \tcode{n} buckets, -using \tcode{hasher()} as the hash function and \tcode{key_equal()} -as the key equality predicate, and inserts elements from \tcode{[i, j)} -into it. -& Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case -\bigoh{N^2} -\\ \rowsep -% -\tcode{X(i, j)}\br \tcode{X a(i, j);} -& \tcode{X} -& \expects \tcode{hasher} and \tcode{key_equal} meet the \oldconcept{DefaultConstructible} requirements. - \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}.\br - \effects\ Constructs an empty container with an unspecified number of -buckets, using \tcode{hasher()} as the hash function and -\tcode{key_equal()} as the key equality predicate, and inserts elements -from \tcode{[i, j)} into it. -& Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case -\bigoh{N^2} -\\ \rowsep -% -\tcode{X(il)} -& \tcode{X} -& Same as \tcode{X(il.begin(), il.end())}. -& Same as \tcode{X(il.begin(),} \tcode{il.end())}. -\\ \rowsep -% -\tcode{X(il, n)} -& \tcode{X} -& Same as \tcode{X(il.begin(), il.end(), n)}. -& Same as \tcode{X(il.begin(),} \tcode{il.end(), n)}. -\\ \rowsep -% -\tcode{X(il, n, hf)} -& \tcode{X} -& Same as \tcode{X(il.begin(), il.end(), n, hf)}. -& Same as \tcode{X(il.begin(),} \tcode{il.end(), n, hf)}. -\\ \rowsep -% -\tcode{X(il, n, hf, eq)} -& \tcode{X} -& Same as \tcode{X(il.begin(), il.end(), n, hf, eq)}. -& Same as \tcode{X(il.begin(),} \tcode{il.end(), n, hf, eq)}. -\\ \rowsep -% -\tcode{X(b)}\br \tcode{X a(b);} -& \tcode{X} -& Copy constructor. In addition to the requirements - of \tref{container.req}, copies the - hash function, predicate, and maximum load factor. -& Average case linear in \tcode{b.size()}, worst case quadratic. -\\ \rowsep -% -\tcode{a = b} -& \tcode{X\&} -& Copy assignment operator. In addition to the - requirements of \tref{container.req}, copies - the hash function, predicate, and maximum load factor. -& Average case linear in \tcode{b.size()}, worst case quadratic. -\\ \rowsep -% -\tcode{a = il} -& \tcode{X\&} -& \expects \tcode{value_type} is -\oldconcept{CopyInsertable} into \tcode{X} -and \oldconcept{CopyAssignable}.\br - \effects\ Assigns the range \range{il.begin()}{il.end()} into \tcode{a}. All - existing elements of \tcode{a} are either assigned to or destroyed. -& Same as \tcode{a = X(il)}. -\\ \rowsep -% -\indexunordmem{hash_function}% -\tcode{b.hash_function()} -& \tcode{hasher} -& \returns \tcode{b}'s hash function.% -& constant -\\ \rowsep -% -\indexunordmem{key_eq}% -\tcode{b.key_eq()} -& \tcode{key_equal} -& \returns \tcode{b}'s key equality predicate.% -& constant -\\ \rowsep -% +\begin{itemdescr} +\pnum +\result +\keyword{void} -\indexunordmem{emplace}% -\tcode{a_uniq.} \tcode{emplace(args)} & - \tcode{pair} & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.\br - \effects\ Inserts a \tcode{value_type} object \tcode{t} constructed with - \tcode{std::forward<\brk{}Args\brk{}>(\brk{}args)...} if and only if there is no - element in the container with key equivalent to the key of \tcode{t}. - The \tcode{bool} component of the returned - pair is \tcode{true} if and only if the insertion takes place, and the iterator - component of the pair points to the element with key equivalent to the - key of \tcode{t}. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a_uniq.}\br\tcode{size()}}. -\\ \rowsep - -\tcode{a_eq.}\tcode{emplace(args)} & - \tcode{iterator} & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.\br - \effects\ Inserts a \tcode{value_type} object \tcode{t} constructed with - \tcode{std::forward<\brk{}Args>(\brk{}args)...} and returns the iterator pointing - to the newly inserted element. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a_eq.}\br\tcode{size()}}. -\\ \rowsep +\pnum +\expects +\tcode{z} is positive. +May change the container's maximum load factor, using \tcode{z} as a hint. -\indexunordmem{emplace_hint}% -\tcode{a.emplace_hint(p, args)} & - \tcode{iterator} & - \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}.\br - \effects\ Equivalent to \tcode{a.emplace(} \tcode{std::forward<\brk{}Args>(\brk{}args)...)}. - Return value is an iterator pointing to the element with the key equivalent - to the newly inserted element. The \tcode{const_iterator} \tcode{p} - is a hint pointing to where the search should start. Implementations are - permitted to ignore the hint. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a.} \tcode{size()}}. -\\ \rowsep +\pnum +\complexity +Constant. +\end{itemdescr} -\indexunordmem{insert}% -\tcode{a_uniq.insert(t)} -& \tcode{pair} -& \expects If \tcode{t} is a non-const rvalue, \tcode{value_type} is - \oldconcept{MoveInsertable} into \tcode{X}; otherwise, \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \effects\ Inserts \tcode{t} if and only if there is no element in the container - with key equivalent to the key of \tcode{t}. The \tcode{bool} - component of the returned pair indicates whether the insertion - takes place, and the \tcode{iterator} component points to the element - with key equivalent to the key of \tcode{t}.% -& Average case \bigoh{1}, worst case \bigoh{\tcode{a_uniq.}\br\tcode{size()}}. -\\ \rowsep -% -\tcode{a_eq.insert(t)} -& \tcode{iterator} -& \expects If \tcode{t} is a non-const rvalue, \tcode{value_type} is - \oldconcept{MoveInsertable} into \tcode{X}; otherwise, \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \effects\ Inserts \tcode{t}, and returns an iterator pointing to the newly - inserted element. -& Average case \bigoh{1}, worst case \bigoh{\tcode{a_eq.}\br\tcode{size()}}. -\\ \rowsep -% -\tcode{a.insert(p, t)} -& \tcode{iterator} -& \expects If \tcode{t} is a non-const rvalue, \tcode{value_type} is - \oldconcept{MoveInsertable} into \tcode{X}; otherwise, \tcode{value_type} is - \oldconcept{CopyInsertable} into \tcode{X}.\br - \effects Equivalent to \tcode{a.insert(t)}. Return value is an iterator pointing -to the element with the key equivalent to that of \tcode{t}. The -iterator \tcode{p} is a hint pointing to where the search should -start. Implementations are permitted to ignore the hint.% -& Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. -\\ \rowsep -% -\tcode{a.insert(i, j)} -& \keyword{void} -& \expects \tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. - Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}.\br - \effects Equivalent to \tcode{a.insert(t)} for each element in \tcode{[i,j)}.% -& Average case \bigoh{N}, where $N$ is \tcode{distance(i, j)}, - worst case \bigoh{N(\tcode{a.size()}\brk{}+\brk{}1)}. -\\ \rowsep -% -\tcode{a.insert(il)} -& \keyword{void} -& Same as \tcode{a.insert(il.begin(), il.end())}. -& Same as \tcode{a.insert(} \tcode{il.begin(),} \tcode{il.end())}. -\\ \rowsep -% -\tcode{a_uniq.}\br - \tcode{insert(nh)} & - \tcode{insert_return_type} & - \expects \tcode{nh} is empty or - \tcode{a_uniq.get_allocator() == nh.get_allocator()}.\br - \effects If \tcode{nh} is empty, has no effect. Otherwise, inserts the - element owned by \tcode{nh} if and only if there is no element in the - container with a key equivalent to \tcode{nh.key()}.\br - \ensures If \tcode{nh} is empty, \tcode{inserted} is \tcode{false}, - \tcode{position} is \tcode{end()}, and \tcode{node} is empty. - Otherwise if the insertion took place, \tcode{inserted} is \tcode{true}, - \tcode{position} points to the inserted element, and \tcode{node} is empty; - if the insertion failed, \tcode{inserted} is \tcode{false}, - \tcode{node} has the previous value of \tcode{nh}, and \tcode{position} - points to an element with a key equivalent to \tcode{nh.key()}. & - Average case \bigoh{1}, worst case \bigoh{\brk{}\tcode{a_uniq.}\brk{}\tcode{size()}}. \\ \rowsep -% -\tcode{a_eq.}\br - \tcode{insert(nh)} & - \tcode{iterator} & - \expects \tcode{nh} is empty or - \tcode{a_eq.get_allocator() == nh.get_allocator()}.\br - \effects If \tcode{nh} is empty, has no effect and returns \tcode{a_eq.end()}. - Otherwise, inserts the element owned by \tcode{nh} and returns an iterator - pointing to the newly inserted element.\br - \ensures \tcode{nh} is empty. & - Average case \bigoh{1}, worst case \bigoh{\brk{}\tcode{a_eq.}\brk{}\tcode{size()}}. \\ \rowsep -% -\tcode{a.insert(q, nh)} & - \tcode{iterator} & - \expects \tcode{nh} is empty or - \tcode{a.get_allocator() == nh.get_allocator()}.\br - \effects If \tcode{nh} is empty, has no effect and returns \tcode{a.end()}. - Otherwise, inserts the element owned by \tcode{nh} if and only if there - is no element with key equivalent to \tcode{nh.key()} in containers with - unique keys; always inserts the element owned by \tcode{nh} in containers - with equivalent keys. Always returns the iterator pointing to the element - with key equivalent to \tcode{nh.key()}. The iterator \tcode{q} is a hint - pointing to where the search should start. Implementations are permitted - to ignore the hint.\br - \ensures \tcode{nh} is empty if insertion succeeds, unchanged if insertion fails. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. \\ \rowsep -% -\indexunordmem{extract}% -\tcode{a.extract(k)} & - \tcode{node_type} & - \effects Removes an element in the container with key equivalent to \tcode{k}.\br - \returns A \tcode{node_type} owning the element if found, otherwise an empty - \tcode{node_type}. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. \\ \rowsep -% -\tcode{a_tran.\brk{}extract(kx)} & - \tcode{node_type} & - \effects Removes an element in the container with key equivalent to \tcode{kx}.\br - \returns A \tcode{node_type} owning the element if found, - otherwise an empty \tcode{node_type}. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a_tran.}\br{}\tcode{size()}}. \\ \rowsep -% -\tcode{a.extract(q)} & - \tcode{node_type} & - \effects Removes the element pointed to by \tcode{q}.\br - \returns A \tcode{node_type} owning that element. & - Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. \\ \rowsep -% -\indexunordmem{merge}% -\tcode{a.merge(a2)} & - \keyword{void} & - \expects \tcode{a.get_allocator() == a2.get_allocator()}.\br - Attempts to extract each element in \tcode{a2} and insert it into \tcode{a} - using the hash function and key equality predicate of \tcode{a}. - In containers with unique keys, if there is an element in \tcode{a} with - key equivalent to the key of an element from \tcode{a2}, then that - element is not extracted from \tcode{a2}.\par - \ensures Pointers and references to the transferred elements of \tcode{a2} - refer to those same elements but as members of \tcode{a}. Iterators referring - to the transferred elements and all iterators referring to \tcode{a} will - be invalidated, but iterators to elements remaining in \tcode{a2} will - remain valid. & - Average case \bigoh{N}, where $N$ is \tcode{a2.size()}, - worst case \bigoh{N\tcode{*a.size()}\br\tcode{+} N}. \\ \rowsep -% -\indexunordmem{erase}% -\tcode{a.erase(k)} -& \tcode{size_type} -& \effects Erases all elements with key equivalent to \tcode{k}.\br - \returns The number of elements erased. -& Average case \bigoh{\tcode{a.count(k)}}, worst case - \bigoh{\tcode{a.size()}}. -\\ \rowsep -% -\tcode{a_tran.\brk{}erase(kx)} -& \tcode{size_type} -& \effects Erases all elements with key equivalent to \tcode{kx}.\br - \returns The number of elements erased. -& Average case \bigoh{\tcode{a_tran.}\br{}\tcode{count(kx)}}, worst case - \bigoh{\tcode{a_tran.}\br{}\tcode{size()}}. -\\ \rowsep -% -\tcode{a.erase(q)} -& \tcode{iterator} -& \effects Erases the element pointed to by \tcode{q}.\br - \returns The iterator immediately following \tcode{q} prior to the erasure. -& Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. -\\ \rowsep -% -\tcode{a.erase(r)} -& \tcode{iterator} -& \effects Erases the element pointed to by \tcode{r}.\br - \returns The iterator immediately following \tcode{r} prior to the erasure. -& Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. -\\ \rowsep -% -\tcode{a.erase(q1, q2)} -& \tcode{iterator} -& \effects Erases all elements in the range \tcode{[q1, q2)}.\br - \returns The iterator immediately following the erased elements prior to the - erasure. -& Average case linear in \tcode{distance(q1, q2)}, - worst case \bigoh{\tcode{a.size()}}. -\\ \rowsep -% -\indexunordmem{clear}% -\tcode{a.clear()} -& \keyword{void} -& \effects Erases all elements in the container.\br - \ensures \tcode{a.empty()} is \tcode{true}% -& Linear in \tcode{a.size()}. -\\ \rowsep -% -\indexunordmem{find}% -\tcode{b.find(k)} -& \tcode{iterator}; \br \tcode{const_iterator} for const \tcode{b}. -& \returns An iterator pointing to an element with key equivalent to - \tcode{k}, or \tcode{b.end()} if no such element exists. -& Average case \bigoh{1}, worst case \bigoh{\tcode{b.size()}}. -\\ \rowsep -% -\tcode{a_tran.find(ke)} -& \tcode{iterator}; \br \tcode{const_iterator} for const \tcode{a_tran}. -& \returns An iterator pointing to an element with key equivalent to - \tcode{ke}, or \tcode{a_tran.end()} if no such element exists. -& Average case \bigoh{1}, - worst case \bigoh{\tcode{a_tran.}\br{}\tcode{size()}}. % avoid overfull -\\ \rowsep -% -\indexunordmem{count}% -\tcode{b.count(k)} -& \tcode{size_type} -& \returns The number of elements with key equivalent to \tcode{k}.% -& Average case \bigoh{\tcode{b.count(k)}}, worst case \bigoh{\tcode{b.size()}}. -\\ \rowsep -% -\tcode{a_tran.count(ke)} -& \tcode{size_type} -& \returns The number of elements with key equivalent to \tcode{ke}.% -& Average case - \bigoh{\tcode{a_tran.}\br{}\tcode{count(ke)}}, % avoid overfull - worst case \bigoh{\tcode{a_tran.}\br{}\tcode{size()}}. % avoid overfull -\\ \rowsep -% -\indexunordmem{contains}% -\tcode{b.contains(k)} -& \tcode{bool} -& \effects Equivalent to \tcode{b.find(k) != b.end()}% -& Average case \bigoh{1}, worst case \bigoh{\tcode{b.size()}}. -\\ \rowsep -% -\tcode{a_tran.contains(ke)} -& \tcode{bool} -& \effects Equivalent to \tcode{a_tran.find(ke) != a_tran.end()}% -& Average case \bigoh{1}, - worst case \bigoh{\tcode{a_tran.}\br{}\tcode{size()}}. % avoid overfull -\\ \rowsep -% -\indexunordmem{equal_range}% -\tcode{b.equal_range(k)} -& \tcode{pair}; \br - \tcode{pair} for const \tcode{b}. -& \returns A range containing all elements with keys equivalent to - \tcode{k}. Returns \tcode{make_pair(b.end(), b.end())} if - no such elements exist.% -& Average case \bigoh{\tcode{b.count(k)}}, worst case - \bigoh{\tcode{b.size()}}. -\\ \rowsep -% -\tcode{a_tran.equal_range(ke)} -& \tcode{pair}; \br - \tcode{pair} for const \tcode{a_tran}. -& \returns A range containing all elements with keys equivalent to - \tcode{ke}. Returns \tcode{make_pair(a_tran.end(), a_tran.end())} if - no such elements exist.% -& Average case - \bigoh{\tcode{a_tran.}\br{}\tcode{count(ke)}}, % avoid overfull - worst case \bigoh{\tcode{a_tran.}\br{}\tcode{size()}}. % avoid overfull -\\ \rowsep -% -\indexunordmem{bucket_count}% -\tcode{b.bucket_count()} -& \tcode{size_type} -& \returns The number of buckets that \tcode{b} contains.% -& Constant -\\ \rowsep -% -\indexunordmem{max_bucket_count}% -\tcode{b.max_bucket_count()} -& \tcode{size_type} -& \returns An upper bound on the number of buckets that \tcode{b} can - ever contain.% -& Constant -\\ \rowsep -% -\indexunordmem{bucket}% -\tcode{b.bucket(k)} -& \tcode{size_type} -& - \expects \tcode{b.bucket_count() > 0}.\br - \returns The index of the bucket in which elements with keys equivalent - to \tcode{k} would be found, if any such element existed.\br - \ensures The return value is in the range \tcode{[0, b.bucket_count())}.% -& Constant -\\ \rowsep -% -\indexunordmem{bucket_size}% -\tcode{b.bucket_size(n)} -& \tcode{size_type} -& \expects \tcode{n} shall be in the range \tcode{[0, b.bucket_count())}. - \returns The number of elements in the $\tcode{n}^\text{th}$ bucket.% -& \bigoh{\tcode{b.bucket_}\-\tcode{size(n)}} -\\ \rowsep -% -\indexunordmem{begin}% -\tcode{b.begin(n)} -& \tcode{local_iterator}; \br - \tcode{const_local_iterator} for const \tcode{b}. -& \expects \tcode{n} is in the range \tcode{[0, b.bucket_count())}.\br - \returns An iterator referring to the - first element in the bucket. If the bucket is empty, then - \tcode{b.begin(n) == b.end(n)}.% -& Constant -\\ \rowsep -% -\indexunordmem{end}% -\tcode{b.end(n)} -& \tcode{local_iterator}; \br - \tcode{const_local_iterator} for const \tcode{b}. -& \expects \tcode{n} is in the range \tcode{[0, b.bucket_count())}.\br - \returns An iterator which is the past-the-end - value for the bucket.% -& Constant -\\ \rowsep -% -\indexunordmem{cbegin}% -\tcode{b.cbegin(n)} -& \tcode{const_local_iterator} -& \expects \tcode{n} shall be in the range \tcode{[0, b.bucket_count())}.\br - \returns An iterator referring to the - first element in the bucket. If the bucket is empty, then - \tcode{b.cbegin(n) == b.cend(n)}.% -& Constant -\\ \rowsep -% -\indexunordmem{cend}% -\tcode{b.cend(n)} -& \tcode{const_local_iterator} -& \expects \tcode{n} is in the range \tcode{[0, b.bucket_count())}.\br - \returns An iterator which is the past-the-end - value for the bucket.% -& Constant -\\ \rowsep -% -\indexunordmem{load_factor}% -\tcode{b.load_factor()} -& \tcode{float} -& \returns The average number of elements per bucket.% -& Constant -\\ \rowsep -% -\indexunordmem{max_load_factor}% -\tcode{b.max_load_factor()} -& \tcode{float} -& \returns A positive number that the container attempts to keep the load factor - less than or equal to. The container automatically increases the - number of buckets as necessary to keep the load factor below this - number.% -& Constant -\\ \rowsep -% -\tcode{a.max_load_factor(z)} -& \keyword{void} -& \expects \tcode{z} is positive. - May change the container's maximum load factor, using \tcode{z} as a hint.% -& Constant -\\ \rowsep -% \indexunordmem{rehash}% -\tcode{a.rehash(n)} -& \keyword{void} -& \ensures \tcode{a.bucket_count() >= a.size() / a.max_load_factor()} and - \tcode{a.bucket_count() >= n}.% -& Average case linear in \tcode{a.size()}, worst case quadratic. -\\ \rowsep +\begin{itemdecl} +a.rehash(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\ensures +\tcode{a.bucket_count() >= a.size() / a.max_load_factor()} and +\tcode{a.bucket_count() >= n}.% + +\pnum +\complexity +Average case linear in \tcode{a.size()}, worst case quadratic. +\end{itemdescr} \indexunordmem{reserve}% -\tcode{a.reserve(n)} & - \keyword{void} & - Same as \tcode{a.rehash(ceil(n /} \tcode{a.max_load_factor()))}. & - Average case linear in \tcode{a.size()}, worst case quadratic. \\ +\begin{itemdecl} +a.reserve(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\effects +Equivalent to \tcode{a.rehash(ceil(n / a.max_load_factor()))}. + +\pnum +\complexity +Average case linear in \tcode{a.size()}, worst case quadratic. +\end{itemdescr} -\end{libreqtab4d} \pnum Two unordered containers \tcode{a} and \tcode{b} compare equal if \tcode{a.size() == b.size()} and, for every equivalent-key group @@ -3572,8 +5785,10 @@ \pnum \indextext{requirements!container}% -An \tcode{array} meets all of the requirements of a container and -of a reversible container\iref{container.requirements}, except that a default +An \tcode{array} meets all of the requirements +of a container\iref{container.reqmts} and +of a reversible container\iref{container.rev.reqmts}, +except that a default constructed \tcode{array} object is not empty and that \tcode{swap} does not have constant complexity. An \tcode{array} meets some of the requirements of a sequence container\iref{sequence.reqmts}. @@ -3887,11 +6102,12 @@ Storage management is handled automatically. \pnum -A -\tcode{deque} -meets all of the requirements of a container, of a reversible container -(given in tables in~\ref{container.requirements}), of a sequence container, -including the optional sequence container requirements\iref{sequence.reqmts}, and of an allocator-aware container (\tref{container.alloc.req}). +A \tcode{deque} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of a sequence container, +including the optional sequence container requirements\iref{sequence.reqmts}. Descriptions are provided here only for operations on \tcode{deque} that are not described in one of these tables @@ -4303,14 +6519,15 @@ \end{note} \pnum -A \tcode{forward_list} meets all of the requirements of a container -(\tref{container.req}), except that the \tcode{size()} -member function is not provided and \tcode{operator==} has linear complexity. -A \tcode{forward_list} also meets all of the requirements for an allocator-aware -container (\tref{container.alloc.req}). In addition, a \tcode{forward_list} -provides the \tcode{assign} member functions -(\tref{container.seq.req}) and several of the optional -container requirements (\tref{container.seq.opt}). +A \tcode{forward_list} meets all of the requirements +of a container\iref{container.reqmts}, +except that the \tcode{size()} member function is not provided and +\tcode{operator==} has linear complexity, +A \tcode{forward_list} also meets all of the requirements +for an allocator-aware container\iref{container.alloc.reqmts}. +In addition, a \tcode{forward_list} +provides the \tcode{assign} member functions and +several of the optional sequence container requirements\iref{sequence.reqmts}. Descriptions are provided here only for operations on \tcode{forward_list} that are not described in that table or for operations where there is additional semantic information. @@ -5104,12 +7321,13 @@ algorithms only need sequential access anyway. \pnum -A \tcode{list} meets all of the requirements of a container, of -a reversible container (given in two tables in -\ref{container.requirements}), of a sequence container, +A \tcode{list} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of a sequence container, including most of the optional sequence container -requirements\iref{sequence.reqmts}, and of an allocator-aware container -(\tref{container.alloc.req}). +requirements\iref{sequence.reqmts}. The exceptions are the \tcode{operator[]} and @@ -5816,11 +8034,12 @@ to improve efficiency. \pnum -A \tcode{vector} meets all of the requirements of a container and of a -reversible container (given in two tables in~\ref{container.requirements}), of a -sequence container, including most of the optional sequence container -requirements\iref{sequence.reqmts}, of an allocator-aware container -(\tref{container.alloc.req}), +A \tcode{vector} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, +of a sequence container, including most of the optional sequence container +requirements\iref{sequence.reqmts}, and, for an element type other than \tcode{bool}, of a contiguous container\iref{container.requirements.general}. The exceptions are the @@ -6695,10 +8914,11 @@ on the keys. The \tcode{map} class supports bidirectional iterators. \pnum -A -\tcode{map} -meets all of the requirements of a container, of a reversible container\iref{container.requirements}, of -an associative container\iref{associative.reqmts}, and of an allocator-aware container (\tref{container.alloc.req}). +A \tcode{map} meets all of the requirements of +a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}. and +of an associative container\iref{associative.reqmts}. A \tcode{map} also provides most operations described in~\ref{associative.reqmts} @@ -7242,11 +9462,11 @@ supports bidirectional iterators. \pnum -A -\tcode{multimap} meets all of the requirements of a container and of a -reversible container\iref{container.requirements}, of an associative -container\iref{associative.reqmts}, and of an allocator-aware container -(\tref{container.alloc.req}). +A \tcode{multimap} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an associative container\iref{associative.reqmts}. A \tcode{multimap} also provides most operations described in~\ref{associative.reqmts} @@ -7563,10 +9783,11 @@ supports bidirectional iterators. \pnum -A \tcode{set} meets all of the requirements of a container, of a reversible -container\iref{container.requirements}, of an associative -container\iref{associative.reqmts}, and of an allocator-aware container -(\tref{container.alloc.req}). +A \tcode{set} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}. and +of an associative container\iref{associative.reqmts}. A \tcode{set} also provides most operations described in~\ref{associative.reqmts} @@ -7841,10 +10062,11 @@ supports bidirectional iterators. \pnum -A \tcode{multiset} meets all of the requirements of a container, of a -reversible container\iref{container.requirements}, of an associative -container\iref{associative.reqmts}, and of an allocator-aware container -(\tref{container.alloc.req}). +A \tcode{multiset} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, +of an associative container\iref{associative.reqmts}. \tcode{multiset} also provides most operations described in~\ref{associative.reqmts} for duplicate keys. @@ -8272,7 +10494,11 @@ supports forward iterators. \pnum -An \tcode{unordered_map} meets all of the requirements of a container, of an unordered associative container, and of an allocator-aware container (\tref{container.alloc.req}). It provides the operations described in the preceding requirements table for unique keys; that is, an \tcode{unordered_map} supports the \tcode{a_uniq} operations in that table, not the \tcode{a_eq} operations. For an \tcode{unordered_map} the \tcode{key type} is \tcode{Key}, the mapped type is \tcode{T}, and the value type is \tcode{pair}. +An \tcode{unordered_map} meets all of the requirements +of a container\iref{container.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an unordered associative container\iref{unord.req}. +It provides the operations described in the preceding requirements table for unique keys; that is, an \tcode{unordered_map} supports the \tcode{a_uniq} operations in that table, not the \tcode{a_eq} operations. For an \tcode{unordered_map} the \tcode{key type} is \tcode{Key}, the mapped type is \tcode{T}, and the value type is \tcode{pair}. \pnum Subclause~\ref{unord.map} only describes operations on \tcode{unordered_map} that @@ -8864,9 +11090,11 @@ supports forward iterators. \pnum -An \tcode{unordered_multimap} meets all of the requirements of a container, of an -unordered associative container, and of an allocator-aware container -(\tref{container.alloc.req}). It provides the operations described in the +An \tcode{unordered_multimap} meets all of the requirements +of a container\iref{container.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an unordered associative container\iref{unord.req}. +It provides the operations described in the preceding requirements table for equivalent keys; that is, an \tcode{unordered_multimap} supports the \tcode{a_eq} operations in that table, not the \tcode{a_uniq} operations. For an \tcode{unordered_multimap} the \tcode{key type} is \tcode{Key}, the @@ -9240,7 +11468,11 @@ supports forward iterators. \pnum -An \tcode{unordered_set} meets all of the requirements of a container, of an unordered associative container, and of an allocator-aware container (\tref{container.alloc.req}). It provides the operations described in the preceding requirements table for unique keys; that is, an \tcode{unordered_set} supports the \tcode{a_uniq} operations in that table, not the \tcode{a_eq} operations. For an \tcode{unordered_set} the \tcode{key type} and the value type are both \tcode{Key}. The \tcode{iterator} and \tcode{const_iterator} types are both constant iterator types. It is unspecified whether they are the same type. +An \tcode{unordered_set} meets all of the requirements +of a container\iref{container.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, +of an unordered associative container\iref{unord.req}. +It provides the operations described in the preceding requirements table for unique keys; that is, an \tcode{unordered_set} supports the \tcode{a_uniq} operations in that table, not the \tcode{a_eq} operations. For an \tcode{unordered_set} the \tcode{key type} and the value type are both \tcode{Key}. The \tcode{iterator} and \tcode{const_iterator} types are both constant iterator types. It is unspecified whether they are the same type. \pnum Subclause~\ref{unord.set} only describes operations on \tcode{unordered_set} that @@ -9561,9 +11793,11 @@ supports forward iterators. \pnum -An \tcode{unordered_multiset} meets all of the requirements of a container, of an -unordered associative container, and of an allocator-aware container -(\tref{container.alloc.req}). It provides the operations described in the +An \tcode{unordered_multiset} meets all of the requirements +of a container\iref{container.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an unordered associative container\iref{unord.req}. +It provides the operations described in the preceding requirements table for equivalent keys; that is, an \tcode{unordered_multiset} supports the \tcode{a_eq} operations in that table, not the \tcode{a_uniq} operations. For an \tcode{unordered_multiset} the \tcode{key type} and the value type are diff --git a/source/diagnostics.tex b/source/diagnostics.tex index d145ced062..76ffd019eb 100644 --- a/source/diagnostics.tex +++ b/source/diagnostics.tex @@ -1991,10 +1991,10 @@ \pnum The class template \tcode{basic_stacktrace} satisfies -the requirements of -an allocator-aware container (\tref{container.alloc.req}), -a sequence container\iref{sequence.reqmts}, and -a reversible container\iref{container.requirements.general} +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 diff --git a/source/strings.tex b/source/strings.tex index ee30bed8c1..b54fb590de 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -1317,7 +1317,7 @@ \pnum \effects Constructs a string from the values in the range \range{begin}{end}, -as indicated in \tref{container.seq.req}. +as specified in \ref{sequence.reqmts}. \end{itemdescr} \indexlibraryctor{basic_string}% From 4b1a735f393aa5c864d0a5aba45514aec63f5a90 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 27 Jun 2021 11:26:39 +0200 Subject: [PATCH 078/182] [container.requirements] Omit redundant specification where "Effects: Equivalent to" wording is used. --- source/containers.tex | 56 ------------------------------------------- 1 file changed, 56 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index b5a4e8b4a0..dd8d197967 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -455,10 +455,6 @@ \end{itemdecl} \begin{itemdescr} -\pnum -\result -\keyword{void} - \pnum \effects Equivalent to \tcode{a.swap(b)}. @@ -1529,21 +1525,9 @@ \end{itemdecl} \begin{itemdescr} -\pnum -\result -\tcode{iterator} - \pnum \effects Equivalent to \tcode{a.insert(p, il.begin(), il.end())}. - -\pnum -\returns -\begin{removedblock} -An iterator -that points to the copy of the first element inserted into \tcode{a}, or -\tcode{p} if \tcode{il} is empty. -\end{removedblock} \end{itemdescr} \indexcont{erase}% @@ -1657,10 +1641,6 @@ \end{itemdecl} \begin{itemdescr} -\pnum -\result -\keyword{void} - \pnum \effects Equivalent to \tcode{a.assign(il.begin(), il.end())}. @@ -3045,10 +3025,6 @@ \end{itemdecl} \begin{itemdescr} -\pnum -\result -\keyword{void} - \pnum \effects Equivalent to \tcode{a.insert(il.begin(), il.end())}. @@ -3402,10 +3378,6 @@ \end{itemdecl} \begin{itemdescr} -\pnum -\result -\keyword{void} - \pnum \effects Equivalent to \tcode{a.erase(a.begin(), a.end())}. @@ -3512,10 +3484,6 @@ \pnum \effects Equivalent to: \tcode{return b.find(k) != b.end();} - -\pnum -\complexity -Logarithmic. \end{itemdescr} \indexordmem{contains}% @@ -3531,10 +3499,6 @@ \pnum \effects Equivalent to: \tcode{return a_tran.find(ke) != a_tran.end();} - -\pnum -\complexity -Logarithmic. \end{itemdescr} \indexordmem{lower_bound}% @@ -4630,10 +4594,6 @@ \end{itemdecl} \begin{itemdescr} -\pnum -\result -\keyword{void} - \pnum \effects Equivalent to \tcode{a.insert(il.begin(), il.end())}. @@ -5074,10 +5034,6 @@ \end{itemdecl} \begin{itemdescr} -\pnum -\result -\tcode{bool} - \pnum \effects Equivalent to \tcode{b.find(k) != b.end()}. @@ -5089,10 +5045,6 @@ \end{itemdecl} \begin{itemdescr} -\pnum -\result -\tcode{bool} - \pnum \effects Equivalent to \tcode{a_tran.find(ke) != a_tran.end()}. @@ -5409,17 +5361,9 @@ \end{itemdecl} \begin{itemdescr} -\pnum -\result -\keyword{void} - \pnum \effects Equivalent to \tcode{a.rehash(ceil(n / a.max_load_factor()))}. - -\pnum -\complexity -Average case linear in \tcode{a.size()}, worst case quadratic. \end{itemdescr} \pnum From e7fb089f968caba096f2d49aade774aeea6b3ad8 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 19:08:18 +0100 Subject: [PATCH 079/182] CWG1726 Declarator operators and conversion function --- source/classes.tex | 52 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index 59c0cedd8b..28fb507b5d 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -2472,8 +2472,6 @@ \indextext{fundamental type conversion|see{conversion, user-defined}}% \indextext{conversion!user-defined}% -\pnum -A member function of a class \tcode{X} with a name of the form \begin{bnf} \nontermdef{conversion-function-id}\br \keyword{operator} conversion-type-id @@ -2488,18 +2486,52 @@ \nontermdef{conversion-declarator}\br ptr-operator \opt{conversion-declarator} \end{bnf} -shall have no non-object parameters and -specifies a conversion from \tcode{X} to + +\pnum +A declaration +whose \grammarterm{declarator-id} has +an \grammarterm{unqualified-id} that is a \grammarterm{conversion-function-id} +declares a \defnadj{conversion}{function}; +its \grammarterm{declarator} shall be +a function declarator\iref{dcl.fct} of the form +\begin{ncsimplebnf} +ptr-declarator \terminal{(} parameter-declaration-clause \terminal{)} \opt{cv-qualifier-seq}\br +\bnfindent \opt{ref-qualifier-seq} \opt{noexcept-specifier} \opt{attribute-specifier-seq} +\end{ncsimplebnf} +where the \grammarterm{ptr-declarator} consists solely of +an \grammarterm{id-expression}, +an optional \grammarterm{attribute-specifier-seq}, and +optional surrounding parentheses, and +the \grammarterm{id-expression} has one of the following forms: +\begin{itemize} +\item +in a \grammarterm{member-declaration} that belongs to +the \grammarterm{member-specification} of a class or class template +but is not a friend declaration\iref{class.friend}, +the \grammarterm{id-expression} is a \grammarterm{conversion-function-id}; +\item +otherwise, the \grammarterm{id-expression} is a \grammarterm{qualified-id} +whose \grammarterm{unqualified-id} is a \grammarterm{conversion-function-id}. +\end{itemize} + +\pnum +A conversion function shall have no non-object parameters and +shall be a non-static member function of a class or class template \tcode{X}; +it specifies a conversion from \tcode{X} to the type specified by the \grammarterm{conversion-type-id}, interpreted as a \grammarterm{type-id}\iref{dcl.name}. -Such functions are called \defnx{conversion functions}{conversion function}. A \grammarterm{decl-specifier} in the \grammarterm{decl-specifier-seq} -of a conversion function (if any) shall be neither -a \grammarterm{defining-type-specifier} nor \keyword{static}. +of a conversion function (if any) shall not be +a \grammarterm{defining-type-specifier}. + +\pnum \indextext{conversion!type of}% -The type of the conversion function\iref{dcl.fct} is -``function taking no parameter returning -\grammarterm{conversion-type-id}''. +The type of the conversion function is +``\opt{\tcode{noexcept}} function taking no parameter +\opt{\grammarterm{cv-qualifier-seq}} \opt{\grammarterm{ref-qualifier}} +returning \grammarterm{conversion-type-id}''. + +\pnum A conversion function is never used to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it), From a53083bc9f055386d5125d415ca8e3c36d1ec615 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 15 Feb 2022 22:28:02 +0100 Subject: [PATCH 080/182] CWG2494 Multiple definitions of non-odr-used entities --- source/basic.tex | 49 +++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index dfd44e2ec6..b4fbc5b834 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -329,11 +329,22 @@ \indextext{enumerator!definition}% \indextext{one-definition rule|(}% +\pnum +Each of the following is termed a \defnadj{definable}{item}: +\begin{itemize} +\item a class type\iref{class}, +\item an enumeration type\iref{dcl.enum}, +\item a function\iref{dcl.fct}, +\item a variable\iref{basic.pre}, +\item a templated entity\iref{temp.pre}, +\item a default argument for a parameter +(for a function in a given scope)\iref{dcl.fct.default}, or +\item a default template argument\iref{temp.param}. +\end{itemize} + \pnum No translation unit shall contain more than one definition of any -variable, function, class type, enumeration type, template, -default argument for a parameter (for a function in a given scope), or -default template argument. +definable item. \pnum \indextext{expression!potentially evaluated}% @@ -527,7 +538,7 @@ \end{example} \pnum -Every program shall contain exactly one definition of every non-inline +Every program shall contain at least one definition of every function or variable that is odr-used in that program outside of a discarded statement\iref{stmt.if}; no diagnostic required. The definition can appear explicitly in the program, it can be found in @@ -611,20 +622,19 @@ \end{note} \pnum -There can be more than one definition of a +For any definable item \tcode{D} with definitions in multiple translation units, \begin{itemize} -\item class type\iref{class}, -\item enumeration type\iref{dcl.enum}, -\item inline function or variable\iref{dcl.inline}, -\item templated entity\iref{temp.pre}, -\item default argument for a parameter (for a function in a given scope)% -\iref{dcl.fct.default}, or -\item default template argument\iref{temp.param} +\item +if \tcode{D} is a non-inline non-templated function or variable, or +\item +if the definitions in different translation units +do not satisfy the following requirements, \end{itemize} -in a program provided that -each definition appears in a different translation unit and -the definitions satisfy the following requirements. -Given such an entity \tcode{D} defined in more than one translation unit, +the program is ill-formed; +a diagnostic is required only +if the definable item is attached to a named module and +a prior definition is reachable at the point where a later definition occurs. +Given such an item, for all definitions of \tcode{D}, or, if \tcode{D} is an unnamed enumeration, for all definitions of \tcode{D} that are reachable at any given program point, @@ -745,13 +755,6 @@ might still denote different types in different translation units. \end{note} -\pnum -If these definitions do not satisfy these requirements, -then the program is ill-formed; -a diagnostic is required only if -the entity is attached to a named module and -a prior definition is reachable at the point where a later definition occurs. - \pnum \begin{example} \begin{codeblock} From bd7606cfe60c2063edf1c314e403f9b169a4f877 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 19:57:22 +0100 Subject: [PATCH 081/182] CWG2499 Inconsistency in definition of pointer-interconvertibility --- source/basic.tex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index b4fbc5b834..e33f332139 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -5182,8 +5182,7 @@ the other is a non-static data member of that object\iref{class.union}, or \item one is a standard-layout class object and -the other is the first non-static data member of that object, or, -if the object has no non-static data members, +the other is the first non-static data member of that object or any base class subobject of that object\iref{class.mem}, or \item there exists an object \placeholder{c} such that From d2c8bd8de2c6235db292fa0e22d439cb2eedb846 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 20:00:56 +0100 Subject: [PATCH 082/182] CWG2502 Unintended declaration conflicts in nested statement scopes --- source/basic.tex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/basic.tex b/source/basic.tex index e33f332139..3445633caa 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -1225,7 +1225,8 @@ \grammarterm{compound-statement} of a \grammarterm{lambda-expression}, \grammarterm{function-body}, or \grammarterm{function-try-block}, \item -substatement of a selection or iteration statement, or +substatement of a selection or iteration statement +that is not itself a selection or iteration statement, or \item \grammarterm{handler} of a \grammarterm{function-try-block} \end{itemize} From dc697e52e8bbfd1d4d189386a07bdc19b4517192 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 20:04:46 +0100 Subject: [PATCH 083/182] CWG2506 Structured bindings and array cv-qualifiers --- source/declarations.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/declarations.tex b/source/declarations.tex index 02fcaaa862..d4026574ea 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -6714,7 +6714,7 @@ see~\ref{depr.volatile.type}. First, a variable with a unique name \exposid{e} is introduced. If the \grammarterm{assignment-expression} in the \grammarterm{initializer} -has array type \tcode{A} and no \grammarterm{ref-qualifier} is present, +has array type \cvqual{cv1} \tcode{A} and no \grammarterm{ref-qualifier} is present, \exposid{e} is defined by \begin{ncbnf} \opt{attribute-specifier-seq} \placeholder{S} \cv{} \terminal{A} \exposid{e} \terminal{;} From 0fbb2f2e9c0d72c4a43891a135ff283f9bf7e054 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 20:55:14 +0100 Subject: [PATCH 084/182] CWG2509 decl-specifier-seq in lambda-specifiers --- source/expressions.tex | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/source/expressions.tex b/source/expressions.tex index 42a18a9d04..59461a20e2 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -1690,7 +1690,20 @@ \begin{bnf} \nontermdef{lambda-specifiers}\br - \opt{decl-specifier-seq} \opt{noexcept-specifier} \opt{attribute-specifier-seq} \opt{trailing-return-type} + \opt{lambda-specifier-seq} \opt{noexcept-specifier} \opt{attribute-specifier-seq} \opt{trailing-return-type} +\end{bnf} + +\begin{bnf} +\nontermdef{lambda-specifier}\br + \keyword{consteval}\br + \keyword{constexpr}\br + \keyword{mutable} +\end{bnf} + +\begin{bnf} +\nontermdef{lambda-specifier-seq}\br + lambda-specifier\br + lambda-specifier lambda-specifier-seq \end{bnf} \pnum @@ -1715,12 +1728,12 @@ \end{note} \pnum -In the \grammarterm{decl-specifier-seq} of the \grammarterm{lambda-declarator}, -each \grammarterm{decl-specifier} -shall be one of \keyword{mutable}, \keyword{constexpr}, or \keyword{consteval}. +A \grammarterm{lambda-specifier-seq} +shall contain at most one of each \grammarterm{lambda-specifier} and +shall not contain both \keyword{constexpr} and \keyword{consteval}. If the \grammarterm{lambda-declarator} contains an explicit object parameter\iref{dcl.fct}, -then no \grammarterm{decl-specifier} in the \grammarterm{decl-specifier-seq} +then no \grammarterm{lambda-specifier} in the \grammarterm{lambda-specifier-seq} shall be \keyword{mutable}. \begin{note} The trailing \grammarterm{requires-clause} is described in \ref{dcl.decl}. From e941a31b9005efd5ad0ab2d71bf9ab18c4cd352e Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 21:05:48 +0100 Subject: [PATCH 085/182] CWG2511 cv-qualified bit-fields --- source/classes.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/classes.tex b/source/classes.tex index 28fb507b5d..e2103e4fe9 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -2815,7 +2815,7 @@ to the entity being declared. A bit-field shall not be a static member. \indextext{bit-field!type of}% -A bit-field shall have integral or enumeration type; +A bit-field shall have integral or (possibly cv-qualified) enumeration type; the bit-field semantic property is not part of the type of the class member. The \grammarterm{constant-expression} shall be an integral constant expression with a value greater than or equal to zero and From ff0882bd93d518a9f61ea3e04f774a778959461d Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 7 Feb 2022 21:32:18 +0100 Subject: [PATCH 086/182] P2173R1 Attributes on lambda-expressions Reconciled with prior CWG2509 by replacing decl-specifier-seq with lambda-specifier-seq. --- source/declarations.tex | 15 ++++++------- source/expressions.tex | 50 ++++++++++++++++++++++++++++------------- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/source/declarations.tex b/source/declarations.tex index d4026574ea..5697f1c628 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -8600,12 +8600,11 @@ dependency propagation into and out of functions. No \grammarterm{attribute-argument-clause} shall be present. The attribute may be -applied to the \grammarterm{declarator-id} of a -\grammarterm{parameter-declaration} in a function declaration or lambda, in +applied to a parameter of a function or lambda, in which case it specifies that the initialization of the parameter carries a dependency to\iref{intro.multithread} each lvalue-to-rvalue conversion\iref{conv.lval} of that object. The attribute may also be applied -to the \grammarterm{declarator-id} of a function declaration, in which case it +to a function or a lambda call operator, in which case it specifies that the return value, if any, carries a dependency to the evaluation of the function call expression. @@ -8894,8 +8893,8 @@ \pnum The \grammarterm{attribute-token} \tcode{nodiscard} -may be applied to the \grammarterm{declarator-id} -in a function declaration or to the declaration of a class or enumeration. +may be applied to a function or a lambda call operator or +to the declaration of a class or enumeration. An \grammarterm{attribute-argument-clause} may be present and, if present, shall have the form: @@ -8985,9 +8984,9 @@ \pnum The \grammarterm{attribute-token} \tcode{noreturn} specifies that a function does not return. -No -\grammarterm{attribute-argument-clause} shall be present. The attribute may be applied to the -\grammarterm{declarator-id} in a function declaration. The first declaration of a function shall +No \grammarterm{attribute-argument-clause} shall be present. +The attribute may be applied to a function or a lambda call operator. +The first declaration of a function shall specify the \tcode{noreturn} attribute if any declaration of that function specifies the \tcode{noreturn} attribute. If a function is declared with the \tcode{noreturn} attribute in one translation unit and the same function is declared without the \tcode{noreturn} attribute in another diff --git a/source/expressions.tex b/source/expressions.tex index 59461a20e2..8a3fab39bf 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -1673,8 +1673,9 @@ \begin{bnf} \nontermdef{lambda-expression}\br - lambda-introducer lambda-declarator compound-statement\br - lambda-introducer \terminal{<} template-parameter-list \terminal{>} \opt{requires-clause} lambda-declarator compound-statement + lambda-introducer \opt{attribute-specifier-seq} lambda-declarator compound-statement\br + lambda-introducer \terminal{<} template-parameter-list \terminal{>} \opt{requires-clause} \opt{attribute-specifier-seq}\br + \bnfindent lambda-declarator compound-statement \end{bnf} \begin{bnf} @@ -1684,13 +1685,11 @@ \begin{bnf} \nontermdef{lambda-declarator}\br - lambda-specifiers\br - \terminal{(} parameter-declaration-clause \terminal{)} lambda-specifiers \opt{requires-clause} -\end{bnf} - -\begin{bnf} -\nontermdef{lambda-specifiers}\br - \opt{lambda-specifier-seq} \opt{noexcept-specifier} \opt{attribute-specifier-seq} \opt{trailing-return-type} + lambda-specifier-seq \opt{noexcept-specifier} \opt{attribute-specifier-seq} \opt{trailing-return-type}\br + noexcept-specifier \opt{attribute-specifier-seq} \opt{trailing-return-type}\br + \opt{trailing-return-type}\br + \terminal{(} parameter-declaration-clause \terminal{)} \opt{lambda-specifier-seq} \opt{noexcept-specifier} \opt{attribute-specifier-seq}\br + \bnfindent \opt{trailing-return-type} \opt{requires-clause} \end{bnf} \begin{bnf} @@ -1727,6 +1726,20 @@ object\iref{function.objects}. \end{note} +\pnum +An ambiguity can arise +because a \grammarterm{requires-clause} can end in +an \grammarterm{attribute-specifier-seq}, +which collides with +the \grammarterm{attribute-specifier-seq} in \grammarterm{lambda-expression}. +In such cases, +any attributes are treated as +\grammarterm{attribute-specifier-seq} in \grammarterm{lambda-expression}. +\begin{note} +Such ambiguous cases cannot have valid semantics +because the constraint expression would not have type \keyword{bool}. +\end{note} + \pnum A \grammarterm{lambda-specifier-seq} shall contain at most one of each \grammarterm{lambda-specifier} and @@ -1740,13 +1753,15 @@ \end{note} \pnum -If a \grammarterm{lambda-expression} includes an empty -\grammarterm{lambda-declarator}, it is as if the \grammarterm{lambda-declarator} were -\tcode{()}. -The lambda return type is \keyword{auto}, which is replaced by the -type specified by the -\grammarterm{trailing-return-type} if provided and/or deduced from -\tcode{return} statements as described in~\ref{dcl.spec.auto}. +If a \grammarterm{lambda-declarator} does not include +a \grammarterm{parameter-declaration-clause}, +it is as if \tcode{()} were inserted +at the start of the \grammarterm{lambda-declarator}. +If the \grammarterm{lambda-declarator} +does not include a \grammarterm{trailing-return-type}, +the lambda return type is \keyword{auto}, +which is deduced from \keyword{return} statements +as described in \ref{dcl.spec.auto}. \begin{example} \begin{codeblock} auto x1 = [](int i) { return i; }; // OK, return type is \tcode{int} @@ -1888,6 +1903,9 @@ applies to the corresponding function call operator or operator template. An \grammarterm{attribute-specifier-seq} in a \grammarterm{lambda-declarator} appertains to the type of the corresponding function call operator or operator template. +An \grammarterm{attribute-specifier-seq} in a \grammarterm{lambda-expression} +preceding a \grammarterm{lambda-declarator} +appertains to the corresponding function call operator or operator template. The function call operator or any given operator template specialization is a constexpr function if either the corresponding \grammarterm{lambda-expression}{'s} From 64d8317007c30dc1e5073f97722feedadc3ec5c7 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 7 Feb 2022 22:44:34 +0100 Subject: [PATCH 087/182] P2493R0 Missing feature test macros for C++20 core papers --- source/preprocessor.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/preprocessor.tex b/source/preprocessor.tex index fb03b852f9..465b3420bd 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -1754,7 +1754,7 @@ \defnxname{cpp_binary_literals} & \tcode{201304L} \\ \rowsep \defnxname{cpp_capture_star_this} & \tcode{201603L} \\ \rowsep \defnxname{cpp_char8_t} & \tcode{201811L} \\ \rowsep -\defnxname{cpp_concepts} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_concepts} & \tcode{202002L} \\ \rowsep \defnxname{cpp_conditional_explicit} & \tcode{201806L} \\ \rowsep \defnxname{cpp_constexpr} & \tcode{202110L} \\ \rowsep \defnxname{cpp_constexpr_dynamic_alloc} & \tcode{201907L} \\ \rowsep From a41e33caf8e3d05636019249947f2a33c793b837 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 21:26:03 +0100 Subject: [PATCH 088/182] LWG3088 forward_list::merge behavior unclear when passed *this --- source/containers.tex | 55 ++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index dd8d197967..72b49c7066 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -7156,18 +7156,22 @@ \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{comp} be \tcode{less<>{}} for the first two overloads. + \pnum \expects -\tcode{*this} and \tcode{x} are both sorted with respect to -the comparator \tcode{operator<} (for the first two overloads) or -\tcode{comp} (for the last two overloads), and +\tcode{*this} and \tcode{x} are both sorted +with respect to the comparator \tcode{comp}, and \tcode{get_allocator() == x.get_allocator()} is \tcode{true}. \pnum \effects -Merges the two sorted ranges \tcode{[begin(), end())} and -\tcode{[x.begin(), x.end())}. \tcode{x} is empty after the merge. If an -exception is thrown other than by a comparison there are no effects. +If \tcode{addressof(x) == this}, there are no effects. +Otherwise, merges +the two sorted ranges \range{begin()}{end()} and \range{x.begin()}{x.end()}. +The result is a range +that is sorted with respect to the comparator \tcode{comp}. Pointers and references to the moved elements of \tcode{x} now refer to those same elements but as members of \tcode{*this}. Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into \tcode{*this}, not into @@ -7176,11 +7180,15 @@ \pnum \complexity At most \tcode{distance(begin(), -end()) + distance(x.begin(), x.end()) - 1} comparisons. +end()) + distance(x.begin(), x.end()) - 1} comparisons +if \tcode{addressof(x) != this}; otherwise, no comparisons are performed. \pnum \remarks Stable\iref{algorithm.stable}. +If \tcode{addressof(x) != this}, \tcode{x} is empty after the merge. +No elements are copied by this operation. +If an exception is thrown other than by a comparison, there are no effects. \end{itemdescr} \indexlibrarymember{sort}{forward_list}% @@ -7857,21 +7865,22 @@ \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{comp} be \tcode{less<>{}} for the first two overloads. + \pnum \expects -Both the list and the argument list -shall be sorted with respect to -the comparator \tcode{operator<} (for the first two overloads) or -\tcode{comp} (for the last two overloads), and +\tcode{*this} and \tcode{x} are both sorted +with respect to the comparator \tcode{comp}, and \tcode{get_allocator() == x.get_allocator()} is \tcode{true}. \pnum \effects -If \tcode{addressof(x) == this}, does nothing; otherwise, merges the two sorted ranges \tcode{[begin(), -end())} and \tcode{[x.\brk{}begin(), x.end())}. The result is a range in which the elements -will be sorted in non-decreasing order according to the ordering defined by \tcode{comp}; that -is, for every iterator \tcode{i}, in the range other than the first, the condition -\tcode{comp(*i, *(i - 1))} will be \tcode{false}. +If \tcode{addressof(x) == this}, there are no effects. +Otherwise, merges +the two sorted ranges \range{begin()}{end()} and \range{x.begin()}{x.end()}. +The result is a range +that is sorted with respect to the comparator \tcode{comp}. Pointers and references to the moved elements of \tcode{x} now refer to those same elements but as members of \tcode{*this}. Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into \tcode{*this}, not into @@ -7879,18 +7888,16 @@ \pnum \complexity -At most -\tcode{size() + x.size() - 1} -applications of \tcode{comp} if -\tcode{addressof(x) != this}; -otherwise, no applications of \tcode{comp} are performed. -If an exception is thrown other than by a comparison there are no effects. +At most \tcode{size() + x.size() - 1} comparisons +if \tcode{addressof(x) != this}; +otherwise, no comparisons are performed. \pnum \remarks -Stable\iref{algorithm.stable}. If \tcode{addressof(x) != this}, the range \tcode{[x.begin(), x.end())} -is empty after the merge. +Stable\iref{algorithm.stable}. +If \tcode{addressof(x) != this}, \tcode{x} is empty after the merge. No elements are copied by this operation. +If an exception is thrown other than by a comparison there are no effects. \end{itemdescr} \indexlibrarymember{reverse}{list}% From 26afca84ea5613ab48f6e8003249ad404d9c44ad Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 21:41:26 +0100 Subject: [PATCH 089/182] LWG3471 polymorphic_allocator::allocate does not satisfy Cpp17Allocator requirements --- source/utilities.tex | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/source/utilities.tex b/source/utilities.tex index 703d28592b..0110634bf3 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -12518,7 +12518,17 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return do_allocate(bytes, alignment);} +Allocates storage by calling \tcode{do_allocate(bytes, alignment)} and +implicitly creates objects within the allocated region of storage. + +\pnum +\returns +A pointer to a suitable created object\iref{intro.object} +in the allocated region of storage. + +\pnum +\throws +What and when the call to \tcode{do_allocate} throws. \end{itemdescr} \indexlibrarymember{deallocate}{memory_resource}% From 24a304f757d9f3c6125a31737987e8925f3818af Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 22:40:28 +0100 Subject: [PATCH 090/182] LWG3525 uses_allocator_construction_args fails to handle types convertible to pair --- source/utilities.tex | 54 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/source/utilities.tex b/source/utilities.tex index 0110634bf3..be95d8b26b 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -7409,6 +7409,8 @@ template constexpr auto uses_allocator_construction_args(const Alloc& alloc, const pair&& pr) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept; template constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args); template @@ -8347,6 +8349,58 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \exposid{FUN} be the function template: +\begin{codeblock} +template + void @\exposid{FUN}@(const pair&); +\end{codeblock} + +\pnum +\constraints +\tcode{T} is a specialization of \tcode{pair}, and +the expression \tcode{\exposid{FUN}(u)} is not well-formed +when considered as an unevaluated operand. + +\pnum +Let \exposid{pair-constructor} be an exposition-only class defined as follows: + +\begin{codeblock} +class @\exposid{pair-constructor}@ { + using @\exposid{pair-type}@ = remove_cv_t; // \expos + + constexpr auto @\exposid{do-construct}@(const @\exposid{pair-type}@& p) const { // \expos + return make_obj_using_allocator<@\exposid{pair-type}@>(@\exposid{alloc_}@, p); + } + constexpr auto @\exposid{do-construct}@(@\exposid{pair-type}@&& p) const { // \expos + return make_obj_using_allocator<@\exposid{pair-type}@>(@\exposid{alloc_}@, std::move(p)); + } + + const Alloc& @\exposid{alloc_}@; // \expos + U& @\exposid{u_}@; // \expos + +public: + constexpr operator @\exposid{pair-type}@() const { + return @\exposid{do-construct}@(std::forward(@\exposid{u_}@)); + } +}; +\end{codeblock} + +\pnum +\returns +\tcode{make_tuple(pc)}, +where \tcode{pc} is a \exposid{pair-constructor} object +whose \exposid{alloc_} member is initialized with \tcode{alloc} and +whose \exposid{u_} member is initialized with \tcode{u}. +\end{itemdescr} + \indexlibraryglobal{make_obj_using_allocator}% \begin{itemdecl} template From 23b74d7ffc4c1a21fd4ddb1ed464b87ba34b949e Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 22:42:54 +0100 Subject: [PATCH 091/182] LWG3598 system_category().default_error_condition(0) is underspecified --- source/diagnostics.tex | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/source/diagnostics.tex b/source/diagnostics.tex index 76ffd019eb..b17a6e6fa0 100644 --- a/source/diagnostics.tex +++ b/source/diagnostics.tex @@ -1046,11 +1046,13 @@ pointer to the string \tcode{"system"}. The object's \tcode{default_error_condition} virtual function shall behave as follows: -If the argument \tcode{ev} corresponds to a POSIX \tcode{errno} value \tcode{posv}, the -function shall return \tcode{error_condition(posv, generic_category())}. -Otherwise, the function shall return \tcode{error_condition(ev, -system_category())}. What constitutes correspondence for any given operating -system is unspecified. +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 From 9c4644f63d97090e23798e43a3db15a858216597 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 22:52:16 +0100 Subject: [PATCH 092/182] LWG3601 common_iterator's postfix-proxy needs indirectly_readable --- source/iterators.tex | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/iterators.tex b/source/iterators.tex index ce9786e65a..f987b40932 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -5060,8 +5060,11 @@ Otherwise, if \tcode{requires(I\& i) \{ \{ *i++ \} -> \exposconceptnc{can-reference}; \}} is \tcode{true} or -\tcode{\libconceptx{constructible_\newline{}from}{constructible_from}, iter_reference_t> \&\& \libconcept{move_constructible}>} -is \linebreak \tcode{false}, +\begin{codeblock} +@\libconcept{indirectly_readable}@ && @\libconcept{constructible_from}@, iter_reference_t> && +@\libconcept{move_constructible}@> +\end{codeblock} +is \tcode{false}, equivalent to: \begin{codeblock} return get(v_)++; From 23f68f8fd04885e8451dc023546e3c4d00e9eb7a Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 23:04:11 +0100 Subject: [PATCH 093/182] LWG3607 contiguous_iterator should not be allowed to have custom iter_move and iter_swap behavior --- source/iterators.tex | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/source/iterators.tex b/source/iterators.tex index f987b40932..28db8dbca4 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -1911,8 +1911,12 @@ The type \tcode{I} models \libconcept{contiguous_iterator} only if \begin{itemize} \item \tcode{to_address(a) == addressof(*a)}, -\item \tcode{to_address(b) == to_address(a) + D(b - a)}, and -\item \tcode{to_address(c) == to_address(a) + D(c - a)}. +\item \tcode{to_address(b) == to_address(a) + D(b - a)}, +\item \tcode{to_address(c) == to_address(a) + D(c - a)}, +\item \tcode{ranges::iter_move(a)} has +the same type, value category, and effects as \tcode{std::move(*a)}, and +\item if \tcode{ranges::iter_swap(a, b)} is well-formed, +it has effects equivalent to \tcode{ranges::swap(*a, *b)}. \end{itemize} \rSec2[iterator.cpp17]{\Cpp{}17 iterator requirements} @@ -2088,6 +2092,9 @@ The implementation of an algorithm on input iterators should never attempt to pass through the same iterator twice; such an algorithm should be a single pass algorithm. + +\newpage + \begin{note} For input iterators, \tcode{a == b} does not imply \tcode{++a == ++b}. (Equality does not guarantee the substitution property or referential transparency.) @@ -2107,8 +2114,6 @@ and the expressions in \tref{outputiterator} are valid and have the indicated semantics. -\newpage - \begin{libreqtab4b}[floattable] {\defnoldconcept{OutputIterator} requirements (in addition to \oldconcept{Iterator})} {outputiterator} From bf3fad576a1ccddf75c6c4533838659941c2cfe1 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 23:10:20 +0100 Subject: [PATCH 094/182] LWG3610 iota_view::size sometimes rejects integer-class types --- source/ranges.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/ranges.tex b/source/ranges.tex index db08470e2f..bdfae2eea8 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -2471,7 +2471,7 @@ \remarks The expression in the \grammarterm{requires-clause} is equivalent to: \begin{codeblock} -(@\libconcept{same_as}@ && @\exposconcept{advanceable}@) || (@\libconcept{integral}@ && @\libconcept{integral}@) || +(@\libconcept{same_as}@ && @\exposconcept{advanceable}@) || (@\exposid{is-integer-like}@ && @\exposid{is-integer-like}@) || @\libconcept{sized_sentinel_for}@ \end{codeblock} \end{itemdescr} From 5a8a894cd0c12e3b69a27c365e188f0fc419a2b9 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 23:19:28 +0100 Subject: [PATCH 095/182] LWG3612 Inconsistent pointer alignment in std::format --- source/utilities.tex | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index be95d8b26b..2f579508f2 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -20973,14 +20973,15 @@ \tcode{<} & Forces the field to be aligned to the start of the available space. This is the default for -non-arithmetic types, \tcode{charT}, and \tcode{bool}, +non-arithmetic non-pointer types, \tcode{charT}, and \tcode{bool}, unless an integer presentation type is specified. \\ \rowsep % \tcode{>} & Forces the field to be aligned to the end of the available space. This is the default for -arithmetic types other than \tcode{charT} and \tcode{bool} +arithmetic types other than \tcode{charT} and \tcode{bool}, +pointer types, or when an integer presentation type is specified. \\ \rowsep % From d82020d34e29dd1a7277031e29dcf95e916742af Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 11 Feb 2022 00:05:23 +0100 Subject: [PATCH 096/182] LWG3618 Unnecessary iter_move for transform_view::iterator --- source/ranges.tex | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/source/ranges.tex b/source/ranges.tex index bdfae2eea8..3121b25f21 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -4125,7 +4125,8 @@ constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; constexpr iterator_t<@\exposid{Base}@> base() &&; - constexpr decltype(auto) operator*() const { + constexpr decltype(auto) operator*() const + noexcept(noexcept(invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *@\exposid{current_}@))) { return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *@\exposid{current_}@); } @@ -4169,14 +4170,6 @@ requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; - - friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& i) - noexcept(noexcept(invoke(*i.@\exposid{parent_}@->@\exposid{fun_}@, *i.@\exposid{current_}@))) { - if constexpr (is_lvalue_reference_v) - return std::move(*i); - else - return *i; - } }; } \end{codeblock} From 095b2c235f2a3b04774454abcbe4120abd41da9c Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 11 Feb 2022 00:09:57 +0100 Subject: [PATCH 097/182] LWG3619 Specification of vformat_to contains ill-formed formatted_size calls --- source/utilities.tex | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index 2f579508f2..9491e8109f 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -21655,9 +21655,7 @@ the arguments provided by \tcode{args}, formatted according to the specifications given in \tcode{fmt}, into the range \range{out}{out + N}, -where \tcode{N} is -\tcode{formatted_size(fmt, args...)} for the functions without a \tcode{loc} parameter and -\tcode{formatted_size(loc, fmt, args...)} for the functions with a \tcode{loc} parameter. +where \tcode{N} is the number of characters in that character representation. If present, \tcode{loc} is used for locale-specific formatting. \pnum From d45eb35f76cc355fcce1dbb7a32a5ab38ad55d4e Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 11 Feb 2022 00:11:44 +0100 Subject: [PATCH 098/182] LWG3621 Remove feature-test macro __cpp_lib_monadic_optional --- source/support.tex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/support.tex b/source/support.tex index d3f888b167..a86e05dfb9 100644 --- a/source/support.tex +++ b/source/support.tex @@ -650,7 +650,6 @@ #define @\defnlibxname{cpp_lib_math_constants}@ 201907L // also in \libheader{numbers} #define @\defnlibxname{cpp_lib_math_special_functions}@ 201603L // also in \libheader{cmath} #define @\defnlibxname{cpp_lib_memory_resource}@ 201603L // also in \libheader{memory_resource} -#define @\defnlibxname{cpp_lib_monadic_optional}@ 202110L // also in \libheader{optional} #define @\defnlibxname{cpp_lib_move_only_function}@ 202110L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_node_extract}@ 201606L // also in \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set} @@ -659,7 +658,7 @@ // \libheader{unordered_map}, \libheader{unordered_set}, \libheader{vector} #define @\defnlibxname{cpp_lib_not_fn}@ 201603L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_null_iterators}@ 201304L // also in \libheader{iterator} -#define @\defnlibxname{cpp_lib_optional}@ 202106L // also in \libheader{optional} +#define @\defnlibxname{cpp_lib_optional}@ 202110L // also in \libheader{optional} #define @\defnlibxname{cpp_lib_out_ptr}@ 202106L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_parallel_algorithm}@ 201603L // also in \libheader{algorithm}, \libheader{numeric} #define @\defnlibxname{cpp_lib_polymorphic_allocator}@ 201902L // also in \libheader{memory_resource} From 04a75f457682409e07e2291cda60521b37bdce73 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 11 Feb 2022 00:15:51 +0100 Subject: [PATCH 099/182] LWG3632 unique_ptr "Mandates: This constructor is not selected by class template argument deduction" --- source/utilities.tex | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index 9491e8109f..eb4a635280 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -9140,9 +9140,9 @@ // \ref{unique.ptr.single.ctor}, constructors constexpr unique_ptr() noexcept; - explicit unique_ptr(pointer p) noexcept; - unique_ptr(pointer p, @\seebelow@ d1) noexcept; - unique_ptr(pointer p, @\seebelow@ d2) noexcept; + explicit unique_ptr(type_identity_t p) noexcept; + unique_ptr(type_identity_t p, @\seebelow@ d1) noexcept; + unique_ptr(type_identity_t p, @\seebelow@ d2) noexcept; unique_ptr(unique_ptr&& u) noexcept; constexpr unique_ptr(nullptr_t) noexcept; template @@ -9241,7 +9241,7 @@ \indexlibraryctor{unique_ptr}% \begin{itemdecl} -explicit unique_ptr(pointer p) noexcept; +explicit unique_ptr(type_identity_t p) noexcept; \end{itemdecl} \begin{itemdescr} @@ -9250,11 +9250,6 @@ \tcode{is_pointer_v} is \tcode{false} and \tcode{is_default_constructible_v} is \tcode{true}. -\pnum -\mandates -This constructor is not selected by -class template argument deduction\iref{over.match.class.deduct}. - \pnum \expects \tcode{D} meets the \oldconcept{DefaultConstructible} requirements (\tref{cpp17.defaultconstructible}), @@ -9274,8 +9269,8 @@ \indexlibraryctor{unique_ptr}% \begin{itemdecl} -unique_ptr(pointer p, const D& d) noexcept; -unique_ptr(pointer p, remove_reference_t&& d) noexcept; +unique_ptr(type_identity_t p, const D& d) noexcept; +unique_ptr(type_identity_t p, remove_reference_t&& d) noexcept; \end{itemdecl} \begin{itemdescr} @@ -9283,11 +9278,6 @@ \constraints \tcode{is_constructible_v} is \tcode{true}. -\pnum -\mandates -These constructors are not selected by -class template argument deduction\iref{over.match.class.deduct}. - \pnum \expects For the first constructor, if \tcode{D} is not a reference type, From 66c75800f4a31c44250bcec7fdabc3a71d17d520 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 11 Feb 2022 00:18:32 +0100 Subject: [PATCH 100/182] LWG3643 Missing constexpr in std::counted_iterator --- source/iterators.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/iterators.tex b/source/iterators.tex index 28db8dbca4..93def71f92 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -5281,7 +5281,7 @@ requires @\libconcept{contiguous_iterator}@; constexpr counted_iterator& operator++(); - decltype(auto) operator++(int); + constexpr decltype(auto) operator++(int); constexpr counted_iterator operator++(int) requires @\libconcept{forward_iterator}@; constexpr counted_iterator& operator--() @@ -5499,7 +5499,7 @@ \indexlibrarymember{operator++}{counted_iterator}% \begin{itemdecl} -decltype(auto) operator++(int); +constexpr decltype(auto) operator++(int); \end{itemdecl} \begin{itemdescr} From 49131ae4e7695c0d2c1867a80b49ef00d40a38e4 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 11 Feb 2022 00:21:22 +0100 Subject: [PATCH 101/182] LWG3648 format should not print bool with 'c' --- source/utilities.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/utilities.tex b/source/utilities.tex index eb4a635280..89af386c02 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -21311,7 +21311,7 @@ Copies textual representation, either \tcode{true} or \tcode{false}, to the output. \\ \rowsep % -\tcode{b}, \tcode{B}, \tcode{c}, \tcode{d}, \tcode{o}, \tcode{x}, \tcode{X} & +\tcode{b}, \tcode{B}, \tcode{d}, \tcode{o}, \tcode{x}, \tcode{X} & As specified in \tref{format.type.int} for the value \tcode{static_cast(value)}. From 972e5787a187f7ad2232fba7cd2ba06bb35d90e9 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 11 Feb 2022 00:30:41 +0100 Subject: [PATCH 102/182] LWG3650 Are std::basic_string's iterator and const_iterator constexpr iterators? --- source/strings.tex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/strings.tex b/source/strings.tex index b54fb590de..7400a02ff0 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -1088,6 +1088,10 @@ 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 From 2e371d955f59e2eded6afe909ea81a6e00439a62 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 11 Feb 2022 00:36:53 +0100 Subject: [PATCH 103/182] LWG3654 basic_format_context::arg(size_t) should be noexcept --- source/utilities.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index 89af386c02..60f0e94e61 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -22143,7 +22143,7 @@ using char_type = charT; template using formatter_type = formatter; - basic_format_arg arg(size_t id) const; + basic_format_arg arg(size_t id) const noexcept; std::locale locale(); iterator out(); @@ -22186,7 +22186,7 @@ \indexlibrarymember{arg}{basic_format_context}% \begin{itemdecl} -basic_format_arg arg(size_t id) const; +basic_format_arg arg(size_t id) const noexcept; \end{itemdecl} \begin{itemdescr} From 351afbf938603aec1b42074f154a6fffa626c521 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 11 Feb 2022 00:41:04 +0100 Subject: [PATCH 104/182] LWG3657 std::hash is not enabled --- source/iostreams.tex | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/source/iostreams.tex b/source/iostreams.tex index 3554d361ca..31a2bc1e20 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -12668,6 +12668,12 @@ path weakly_canonical(const path& p, error_code& ec); } +// \ref{fs.path.hash}, hash support +namespace std { + template struct hash; + template<> struct hash; +} + namespace std::ranges { template<> inline constexpr bool enable_borrowed_range = true; @@ -14618,6 +14624,19 @@ Equivalent to: \tcode{return path(lhs) /= rhs;} \end{itemdescr} +\rSec3[fs.path.hash]{Hash support} + +\begin{itemdecl} +template<> struct hash; +\end{itemdecl} + +\begin{itemdescr} +\pnum +For an object \tcode{p} of type \tcode{filesystem::path}, +\tcode{hash()(p)} evaluates to the same result as +\tcode{filesystem::hash_value(p)}. +\end{itemdescr} + \rSec2[fs.class.filesystem.error]{Class \tcode{filesystem_error}} \rSec3[fs.class.filesystem.error.general]{General} From 148fab5eac010f6110f4b2736d36ae50726b9700 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 11 Feb 2022 00:51:25 +0100 Subject: [PATCH 105/182] LWG3660 iterator_traits::pointer should conform to [iterator.traits] --- source/iterators.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/iterators.tex b/source/iterators.tex index 93def71f92..dea2a48780 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -4872,9 +4872,9 @@ otherwise it denotes \tcode{input_iterator_tag}. \item +Let \tcode{a} denote an lvalue of type \tcode{const common_iterator}. If the expression \tcode{a.operator->()} is well-formed, -where \tcode{a} is an lvalue of type \tcode{const common_iterator}, -then \tcode{pointer} denotes the type of that expression. +then \tcode{pointer} denotes \tcode{decltype(a.operator->())}. Otherwise, \tcode{pointer} denotes \keyword{void}. \end{itemize} From 3452bc77715048f3779c962cb4348c7f30fb12e0 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 11 Feb 2022 00:54:09 +0100 Subject: [PATCH 106/182] LWG3661 constinit atomic> a(nullptr); should work --- source/atomics.tex | 1 + 1 file changed, 1 insertion(+) diff --git a/source/atomics.tex b/source/atomics.tex index 3aa997d81e..687f2fec09 100644 --- a/source/atomics.tex +++ b/source/atomics.tex @@ -2801,6 +2801,7 @@ bool is_lock_free() const noexcept; constexpr atomic() noexcept; + constexpr atomic(nullptr_t) noexcept : atomic() { } atomic(shared_ptr desired) noexcept; atomic(const atomic&) = delete; void operator=(const atomic&) = delete; From 91fa7b0815291efe8c1a3830e65e8bc3f77b38a8 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 8 Feb 2022 22:36:18 +0100 Subject: [PATCH 107/182] P0323R12 std::expected - Introduce "General" subclauses to avoid hanging paragraphs. - Introduce "Returns: *this" to avoid duplication. - Add missing "friend" from item description of expected::operator==. --- source/lib-intro.tex | 1 - source/support.tex | 1 + source/utilities.tex | 2037 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 2038 insertions(+), 1 deletion(-) diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 8b91715a40..a4e4fe6889 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -2480,7 +2480,6 @@ \item \indexlibraryzombie{uncaught_exception} \tcode{uncaught_exception}, \item \indexlibraryzombie{undeclare_no_pointers} \tcode{undeclare_no_pointers}, \item \indexlibraryzombie{undeclare_reachable} \tcode{undeclare_reachable}, -\item \indexlibraryzombie{unexpected} \tcode{unexpected}, and \item \indexlibraryzombie{unexpected_handler} \tcode{unexpected_handler}. \end{itemize} diff --git a/source/support.tex b/source/support.tex index a86e05dfb9..e8ccd20800 100644 --- a/source/support.tex +++ b/source/support.tex @@ -610,6 +610,7 @@ // \libheader{unordered_set} #define @\defnlibxname{cpp_lib_exchange_function}@ 201304L // also in \libheader{utility} #define @\defnlibxname{cpp_lib_execution}@ 201902L // also in \libheader{execution} +#define @\defnlibxname{cpp_lib_expected}@ 202202L // also in \libheader{expected} #define @\defnlibxname{cpp_lib_filesystem}@ 201703L // also in \libheader{filesystem} #define @\defnlibxname{cpp_lib_format}@ 202110L // also in \libheader{format} #define @\defnlibxname{cpp_lib_gcd_lcm}@ 201606L // also in \libheader{numeric} diff --git a/source/utilities.tex b/source/utilities.tex index 60f0e94e61..6308313a8b 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -16,6 +16,7 @@ \ref{optional} & Optional objects & \tcode{} \\ \rowsep \ref{variant} & Variants & \tcode{} \\ \rowsep \ref{any} & Storage for any type & \tcode{} \\ \rowsep +\ref{expected} & Expected objects & \tcode{} \\ \rowsep \ref{bitset} & Fixed-size sequences of bits & \tcode{} \\ \rowsep \ref{memory} & Memory & \tcode{}, \tcode{} \\ \rowsep \ref{smartptr} & Smart pointers & \tcode{} \\ \rowsep @@ -6463,6 +6464,2042 @@ \end{example} \end{itemdescr} +\rSec1[expected]{Expected objects} +\indexlibraryglobal{expected}% + +\rSec2[expected.general]{In general} + +\pnum +This subclause describes the class template \tcode{expected} +that represents expected objects. +An \tcode{expected} object holds +an object of type \tcode{T} or an object of type \tcode{unexpected} and +manages the lifetime of the contained objects. + +\rSec2[expected.syn]{Header \tcode{} synopsis} + +\indexlibraryglobal{unexpect_t}% +\indexlibraryglobal{unexpect}% +\begin{codeblock} +namespace std { + // \ref{expected.un.object}, class template \tcode{unexpected} + template class unexpected; + + // \ref{expected.bad}, class \tcode{bad_expected_access} + template class bad_expected_access; + + // \ref{expected.bad.void}, specialization for \tcode{void} + template<> class bad_expected_access; + + // in-place construction of unexpected values + struct unexpect_t { + explicit unexpect_t() = default; + }; + inline constexpr unexpect_t unexpect{}; + + // \ref{expected.expected}, class template \tcode{expected} + template class expected; + + // \ref{expected.void}, partial specialization of \tcode{expected} for \tcode{void} types + template requires is_void_v class expected; +} +\end{codeblock} + +\rSec2[expected.unexpected]{Unexpected objects} + +\rSec3[expected.un.general]{General} + +\pnum +This subclause describes the class template \tcode{unexpected} +that represents unexpected objects stored in \tcode{expected} objects. + +\rSec3[expected.un.object]{Class template \tcode{unexpected}} + +\rSec4[expected.un.object.general]{General} + +\indexlibraryglobal{unexpected}% +\begin{codeblock} +namespace std { + template + class unexpected { + public: + constexpr unexpected(const unexpected&) = default; + constexpr unexpected(unexpected&&) = default; + template + constexpr explicit unexpected(in_place_t, Args&&...); + template + constexpr explicit unexpected(in_place_t, initializer_list, Args&&...); + template + constexpr explicit unexpected(Err&&); + + constexpr unexpected& operator=(const unexpected&) = default; + constexpr unexpected& operator=(unexpected&&) = default; + + constexpr const E& value() const& noexcept; + constexpr E& value() & noexcept; + constexpr const E&& value() const&& noexcept; + constexpr E&& value() && noexcept; + + constexpr void swap(unexpected& other) noexcept(@\seebelow@); + + template + friend constexpr bool operator==(const unexpected&, const unexpected&); + + friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y))); + + private: + E @\exposid{val}@; // \expos + }; + + template unexpected(E) -> unexpected; +} +\end{codeblock} + +\pnum +A program that instantiates the definition of \tcode{unexpected} for +a non-object type, +an array type, +a specialization of \tcode{unexpected}, or +a cv-qualified type +is ill-formed. + +\rSec4[expected.un.ctor]{Constructors} + +\indexlibraryctor{unexpected}% +\begin{itemdecl} +template + constexpr explicit unexpected(Err&& e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_same_v, unexpected>} is \tcode{false}; and +\item +\tcode{is_same_v, in_place_t>} is \tcode{false}; and +\item +\tcode{is_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Direct-non-list-initializes \exposid{val} with \tcode{std::forward(e)}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. +\end{itemdescr} + +\indexlibraryctor{unexpected}% +\begin{itemdecl} +template + constexpr explicit unexpected(in_place_t, Args&&...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +Direct-non-list-initializes +\exposid{val} with \tcode{std::forward(args)...}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. +\end{itemdescr} + +\indexlibraryctor{unexpected}% +\begin{itemdecl} +template + constexpr explicit unexpected(in_place_t, initializer_list, Args&&...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. + +\pnum +\effects +Direct-non-list-initializes +\exposid{val} with \tcode{std::forward(args)...}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. +\end{itemdescr} + +\rSec4[expected.un.obs]{Observers} + +\indexlibrarymember{value}{unexpected}% +\begin{itemdecl} +constexpr const E& value() const& noexcept; +constexpr E& value() & noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{val}. +\end{itemdescr} + +\indexlibrarymember{value}{unexpected}% +\begin{itemdecl} +constexpr E&& value() && noexcept; +constexpr const E&& value() const&& noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{std::move(\exposid{val})}. +\end{itemdescr} + +\rSec4[expected.un.swap]{Swap} + +\indexlibrarymember{swap}{unexpected}% +\begin{itemdecl} +constexpr void swap(unexpected& other) noexcept(is_nothrow_swappable_v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_swappable_v} is \tcode{true}. + +\pnum +\effects +Equivalent to: +\tcode{using std::swap; swap(\exposid{val}, other.\exposid{val});} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y))); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_swappable_v} is \tcode{true}. + +\pnum +\effects +Equivalent to \tcode{x.swap(y)}. +\end{itemdescr} + +\rSec4[expected.un.eq]{Equality operator} + +\indexlibrarymember{operator==}{unexpected}% +\begin{itemdecl} +template + friend constexpr bool operator==(const unexpected& x, const unexpected& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{x.value() == y.value()} is well-formed and +its result is convertible to \tcode{bool}. + +\pnum +\returns +\tcode{x.value() == y.value()}. +\end{itemdescr} + +\rSec2[expected.bad]{Class template \tcode{bad_expected_access}} + +\indexlibraryglobal{bad_expected_access}% +\begin{codeblock} +namespace std { + template + class bad_expected_access : public bad_expected_access { + public: + explicit bad_expected_access(E); + const char* what() const noexcept override; + E& error() & noexcept; + const E& error() const& noexcept; + E&& error() && noexcept; + const E&& error() const&& noexcept; + private: + E @\exposid{val}@; // \expos + }; +} +\end{codeblock} + +\pnum +The class template \tcode{bad_expected_access} +defines the type of objects thrown as exceptions to report the situation +where an attempt is made to access the value of an \tcode{expected} object +for which \tcode{has_value()} is \tcode{false}. + +\indexlibraryctor{bad_expected_access}% +\begin{itemdecl} +explicit bad_expected_access(E e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{val} with \tcode{std::move(e)}. +\end{itemdescr} + +\indexlibrarymember{error}{bad_expected_access}% +\begin{itemdecl} +const E& error() const& noexcept; +E& error() & noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{val}. +\end{itemdescr} + +\indexlibrarymember{error}{bad_expected_access}% +\begin{itemdecl} +E&& error() && noexcept; +const E&& error() const&& noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{std::move(\exposid{val})}. +\end{itemdescr} + +\indexlibrarymember{what}{bad_expected_access}% +\begin{itemdecl} +const char* what() const noexcept override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An implementation-defined \ntbs. +\end{itemdescr} + +\rSec2[expected.bad.void]{Class template specialization \tcode{bad_expected_access}} + +\begin{codeblock} +namespace std { + template<> + class bad_expected_access : public exception { + protected: + bad_expected_access() noexcept; + bad_expected_access(const bad_expected_access&); + bad_expected_access(bad_expected_access&&); + bad_expected_access& operator=(const bad_expected_access&); + bad_expected_access& operator=(bad_expected_access&&); + ~bad_expected_access(); + public: + const char* what() const noexcept override; + }; +} +\end{codeblock} + +\indexlibrarymember{what}{bad_expected_access}% +\begin{itemdecl} +const char* what() const noexcept override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An implementation-defined \ntbs. +\end{itemdescr} + +\rSec2[expected.expected]{Class template \tcode{expected}} + +\rSec3[expected.object.general]{General} + +\begin{codeblock} +namespace std { + template + class expected { + public: + using @\libmember{value_type}{expected}@ = T; + using @\libmember{error_type}{expected}@ = E; + using @\libmember{unexpected_type}{expected}@ = unexpected; + + template + using @\libmember{rebind}{expected}@ = expected; + + // \ref{expected.object.ctor}, constructors + constexpr expected(); + constexpr explicit(@\seebelow@) expected(const expected&); + constexpr explicit(@\seebelow@) expected(expected&&) noexcept(@\seebelow@); + template + constexpr explicit(@\seebelow@) expected(const expected&); + template + constexpr explicit(@\seebelow@) expected(expected&&); + + template + constexpr explicit(@\seebelow@) expected(U&& v); + + template + constexpr expected(const unexpected&); + template + constexpr expected(unexpected&&); + + template + constexpr explicit expected(in_place_t, Args&&...); + template + constexpr explicit expected(in_place_t, initializer_list, Args&&...); + template + constexpr explicit expected(unexpect_t, Args&&...); + template + constexpr explicit expected(unexpect_t, initializer_list, Args&&...); + + // \ref{expected.object.dtor}, destructor + constexpr ~expected(); + + // \ref{expected.object.assign}, assignment + constexpr expected& operator=(const expected&); + constexpr expected& operator=(expected&&) noexcept(@\seebelow@); + template constexpr expected& operator=(U&&); + template + constexpr expected& operator=(const unexpected&); + template + constexpr expected& operator=(unexpected&&); + + template + constexpr T& emplace(Args&&...) noexcept; + template + constexpr T& emplace(initializer_list, Args&&...) noexcept; + + // \ref{expected.object.swap}, swap + constexpr void swap(expected&) noexcept(@\seebelow@); + friend constexpr void swap(expected&, expected&) noexcept(@\seebelow@); + + // \ref{expected.object.obs}, observers + constexpr const T* operator->() const noexcept; + constexpr T* operator->() noexcept; + constexpr const T& operator*() const& noexcept; + constexpr T& operator*() & noexcept; + constexpr const T&& operator*() const&& noexcept; + constexpr T&& operator*() && noexcept; + constexpr explicit operator bool() const noexcept; + constexpr bool has_value() const noexcept; + constexpr const T& value() const&; + constexpr T& value() &; + constexpr const T&& value() const&&; + constexpr T&& value() &&; + constexpr const E& error() const&; + constexpr E& error() &; + constexpr const E&& error() const&&; + constexpr E&& error() &&; + template constexpr T value_or(U&&) const&; + template constexpr T value_or(U&&) &&; + + // \ref{expected.object.eq}, equality operators + template + friend constexpr bool operator==(const expected& x, const expected& y); + template + friend constexpr bool operator==(const expected&, const T2&); + template + friend constexpr bool operator==(const expected&, const unexpected&); + + private: + bool @\exposid{has_val}@; // \expos + union { + T @\exposid{val}@; // \expos + E @\exposid{unex}@; // \expos + }; + }; +} +\end{codeblock} + +\pnum +Any object of type \tcode{expected} either +contains a value of type \tcode{T} or +a value of type \tcode{E} within its own storage. +Implementations are not permitted to use additional storage, +such as dynamic memory, +to allocate the object of type \tcode{T} or the object of type E. +These objects are allocated in a region of the \tcode{expected} storage +suitably aligned for the types \tcode{T} and \tcode{E}. +Members \exposid{has_val}, \exposid{val}, and \exposid{unex} +are provided for exposition only. +\exposid{has_val} indicates whether the \tcode{expected} object +contains an object of type \tcode{T}. + +\pnum +A program +that instantiates the definition of template \tcode{expected} +for a reference type, a function type, or +for possibly cv-qualified types \tcode{in_place_t}, \tcode{unexpect_t}, or +a specialization of \tcode{unexpected} for the \tcode{T} parameter +is ill-formed. +A program that instantiates +the definition of the template \tcode{expected} +with a type for the \tcode{E} parameter +that is not a valid template argument for \tcode{unexpected} is ill-formed. + +\pnum +When \tcode{T} is not \cv{} \tcode{void}, it shall meet +the \oldconcept{Destructible} requirements (\tref{cpp17.destructible}). +\tcode{E} shall meet +the \oldconcept{Destructible} requirements. + +\rSec3[expected.object.ctor]{Constructors} + +\indexlibraryctor{expected}% +\begin{itemdecl} +constexpr expected(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_default_constructible_v} is \tcode{true}. + +\pnum +\effects +Value-initializes \exposid{val}. + +\pnum +\ensures +\tcode{has_value()} is \tcode{true}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +constexpr expected(const expected& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{rhs.has_value()} is \tcode{true}, +direct-non-list-initializes \exposid{val} with \tcode{*rhs}. +Otherwise, direct-non-list-initializes \exposid{unex} with \tcode{rhs.error()}. + +\pnum +\ensures +\tcode{rhs.has_value() == this->has_value()}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val} or \exposid{unex}. + +\pnum +\remarks +This constructor is defined as deleted unless +\begin{itemize} +\item +\tcode{is_copy_constructible_v} is \tcode{true} and +\item +\tcode{is_copy_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +This constructor is trivial if +\begin{itemize} +\item +\tcode{is_trivially_copy_constructible_v} is \tcode{true} and +\item +\tcode{is_trivially_copy_constructible_v} is \tcode{true}. +\end{itemize} +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +constexpr expected(expected&& rhs) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_move_constructible_v} is \tcode{true} and +\item +\tcode{is_move_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +If \tcode{rhs.has_value()} is \tcode{true}, +direct-non-list-initializes \exposid{val} with \tcode{std::move(*rhs)}. +Otherwise, +direct-non-list-initializes \exposid{unex} with \tcode{std::move(rhs.error())}. + +\pnum +\ensures +\tcode{rhs.has_value()} is unchanged; +\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val} or \exposid{unex}. + +\pnum +\remarks +The exception specification is +\tcode{is_nothrow_move_constructible_v \&\& +is_nothrow_move_constructible_v}. + +\pnum +This constructor is trivial if +\begin{itemize} +\item +\tcode{is_trivially_move_constructible_v} is \tcode{true} and +\item +\tcode{is_trivially_move_constructible_v} is \tcode{true}. +\end{itemize} +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit(@\seebelow@) expected(const expected& rhs); +template + constexpr explicit(@\seebelow@) expected(expected&& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let: +\begin{itemize} +\item +\tcode{UF} be \tcode{const U\&} for the first overload and +\tcode{U} for the second overload. +\item +\tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. +\end{itemize} + +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_constructible_v} is \tcode{true}; and +\item +\tcode{is_constructible_v} is \tcode{true}; and +\item +\tcode{is_constructible_v\&>} is \tcode{false}; and +\item +\tcode{is_constructible_v>} is \tcode{false}; and +\item +\tcode{is_constructible_v\&>} is \tcode{false}; and +\item +\tcode{is_constructible_v>} is \tcode{false}; and +\item +\tcode{is_convertible_v\&, T>} is \tcode{false}; and +\item +\tcode{is_convertible_v\&\&, T>} is \tcode{false}; and +\item +\tcode{is_convertible_v\&, T>} is \tcode{false}; and +\item +\tcode{is_convertible_v\&\&, T>} is \tcode{false}; and +\item +\tcode{is_constructible_v, expected\&>} is \tcode{false}; and +\item +\tcode{is_constructible_v, expected>} is \tcode{false}; and +\item +\tcode{is_constructible_v, const expected\&>} is \tcode{false}; and +\item +\tcode{is_constructible_v, const expected>} is \tcode{false}. +\end{itemize} + +\pnum +\effects +If \tcode{rhs.has_value()}, +direct-non-list-initializes \exposid{val} with \tcode{std::forward(*rhs)}. +Otherwise, +direct-non-list-initializes \exposid{unex} with \tcode{std::forward(rhs.error())}. + +\pnum +\ensures +\tcode{rhs.has_value()} is unchanged; +\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val} or \exposid{unex}. + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to +\tcode{!is_convertible_v || !is_convertible_v}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit(!is_convertible_v) expected(U&& v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_same_v, in_place_t>} is \tcode{false}; and +\item +\tcode{is_same_v, remove_cvref_t>} is \tcode{false}; and +\item +\tcode{remove_cvref_t} is not a specialization of \tcode{unexpected}; and +\item +\tcode{is_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Direct-non-list-initializes \exposid{val} with \tcode{std::forward(v)}. + +\pnum +\ensures +\tcode{has_value()} is \tcode{true}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit(!is_convertible_v) expected(const unexpected& e); +template + constexpr explicit(!is_convertible_v) expected(unexpected&& e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. + +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +Direct-non-list-initializes \exposid{unex} with \tcode{std::forward(e.error())}. + +\pnum +\ensures +\tcode{has_value()} is \tcode{false}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit expected(in_place_t, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +Direct-non-list-initializes \exposid{val} with \tcode{std::forward(args)...}. + +\pnum +\ensures +\tcode{has_value()} is \tcode{true}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit expected(in_place_t, initializer_list il, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. + +\pnum +\effects +Direct-non-list-initializes \exposid{val} with +\tcode{il, std::forward(args)...}. + +\pnum +\ensures +\tcode{has_value()} is \tcode{true}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit expected(unexpect_t, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +Direct-non-list-initializes \exposid{unex} with +\tcode{std::forward(args)...}. + +\pnum +\ensures +\tcode{has_value()} is \tcode{false}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit expected(unexpect_t, initializer_list il, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. + +\pnum +\effects +Direct-non-list-initializes \exposid{unex} with +\tcode{il, std::forward(args)...}. + +\pnum +\ensures +\tcode{has_value()} is \tcode{false}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. +\end{itemdescr} + +\rSec3[expected.object.dtor]{Destructor} + +\indexlibrarydtor{expected}% +\begin{itemdecl} +constexpr ~expected(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{has_value()} is \tcode{true}, destroys \exposid{val}, +otherwise destroys \exposid{unex}. + +\pnum +\remarks +If \tcode{is_trivially_destructible_v} is \tcode{true}, and +\tcode{is_trivially_destructible_v} is \tcode{true}, +then this destructor is a trivial destructor. +\end{itemdescr} + +\rSec3[expected.object.assign]{Assignment} + +\pnum +This subclause makes use of the following exposition-only function: +\begin{codeblock} +template +constexpr void @\exposid{reinit-expected}@(T& newval, U& oldval, Args&&... args) { // \expos + if constexpr (is_nothrow_constructible_v) { + destroy_at(addressof(oldval)); + construct_at(addressof(newval), std::forward(args)...); + } else if constexpr (is_nothrow_move_constructible_v) { + T tmp(std::forward(args)...); + destroy_at(addressof(oldval)); + construct_at(addressof(newval), std::move(tmp)); + } else { + U tmp(std::move(oldval)); + destroy_at(addressof(oldval)); + try { + construct_at(addressof(newval), std::forward(args)...); + } catch (...) { + construct_at(addressof(oldval), std::move(tmp)); + throw; + } + } +} +\end{codeblock} + +\indexlibrarymember{operator=}{expected}% +\begin{itemdecl} +constexpr expected& operator=(const expected& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +If \tcode{this->has_value() \&\& rhs.has_value()} is \tcode{true}, +equivalent to \tcode{\exposid{val} = *rhs}. +\item +Otherwise, if \tcode{this->has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +@\exposid{reinit-expected}@(@\exposid{unex}@, @\exposid{val}@, rhs.error()) +\end{codeblock} +\item +Otherwise, if \tcode{rhs.has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +@\exposid{reinit-expected}@(@\exposid{val}@, @\exposid{unex}@, *rhs) +\end{codeblock} +\item +Otherwise, equivalent to \tcode{\exposid{unex} = rhs.error()}. +\end{itemize} +Then, if no exception was thrown, +equivalent to: \tcode{\exposid{has_val} = rhs.has_value(); return *this;} + +\pnum +\remarks +This operator is defined as deleted unless: +\begin{itemize} +\item +\tcode{is_copy_assignable_v} is \tcode{true} and +\item +\tcode{is_copy_constructible_v} is \tcode{true} and +\item +\tcode{is_copy_assignable_v} is \tcode{true} and +\item +\tcode{is_copy_constructible_v} is \tcode{true} and +\item +\tcode{is_nothrow_move_constructible_v || is_nothrow_move_constructible_v} +is \tcode{true}. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{operator=}{expected}% +\begin{itemdecl} +constexpr expected& operator=(expected&& rhs) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_move_constructible_v} is \tcode{true} and +\item +\tcode{is_move_assignable_v} is \tcode{true} and +\item +\tcode{is_move_constructible_v} is \tcode{true} and +\item +\tcode{is_move_assignable_v} is \tcode{true} and +\item +\tcode{is_nothrow_move_constructible_v || is_nothrow_move_constructible_v} +is \tcode{true}. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +If \tcode{this->has_value() \&\& rhs.has_value()} is \tcode{true}, +equivalent to \tcode{\exposid{val} = std::move(*rhs)}. +\item +Otherwise, if \tcode{this->has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +@\exposid{reinit-expected}@(@\exposid{unex}@, @\exposid{val}@, std::move(rhs.error())) +\end{codeblock} +\item +Otherwise, if \tcode{rhs.has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +@\exposid{reinit-expected}@(@\exposid{val}@, @\exposid{unex}@, std::move(*rhs)) +\end{codeblock} +\item +Otherwise, equivalent to \tcode{\exposid{unex} = std::move(rhs.error())}. +\end{itemize} +Then, if no exception was thrown, +equivalent to: \tcode{has_val = rhs.has_value(); return *this;} + +\pnum +\remarks +The exception specification is +\begin{codeblock} +is_nothrow_move_assignable_v && is_nothrow_move_constructible_v && +is_nothrow_move_assignable_v && is_nothrow_move_constructible_v +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator=}{expected}% +\begin{itemdecl} +template + constexpr expected& operator=(U&& v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_same_v>} is \tcode{false}; and +\item +\tcode{remove_cvref_t} is not a specialization of \tcode{unexpected}; and +\item +\tcode{is_constructible_v} is \tcode{true}; and +\item +\tcode{is_assignable_v} is \tcode{true}; and +\item +\tcode{is_nothrow_constructible_v || is_nothrow_move_constructible_v ||\newline +is_nothrow_move_constructible_v} +is \tcode{true}. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +If \tcode{has_value()} is \tcode{true}, +equivalent to: \tcode{\exposid{val} = std::forward(v);} +\item +Otherwise, equivalent to: +\begin{codeblock} +@\exposid{reinit-expected}@(@\exposid{val}@, @\exposid{unex}@, std::forward(v)); +@\exposid{has_val}@ = true; +\end{codeblock} +\end{itemize} + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{operator=}{expected}% +\begin{itemdecl} +template + constexpr expected& operator=(const unexpected& e); +template + constexpr expected& operator=(unexpected&& e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. + +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_constructible_v} is \tcode{true}; and +\item +\tcode{is_assignable_v} is \tcode{true}; and +\item +\tcode{is_nothrow_constructible_v || is_nothrow_move_constructible_v ||\newline +is_nothrow_move_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +If \tcode{has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +@\exposid{reinit-expected}@(@\exposid{unex}@, @\exposid{val}@, std::forward(e.value())); +@\exposid{has_val}@ = false; +\end{codeblock} +\item +Otherwise, equivalent to: +\tcode{\exposid{unex} = std::forward(e.value());} +\end{itemize} + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{emplace}{expected}% +\begin{itemdecl} +template + constexpr T& emplace(Args&&... args) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_nothrow_constructible_v} is \tcode{true}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (has_value()) { + destroy_at(addressof(@\exposid{val}@)); +} else { + destroy_at(addressof(@\exposid{unex}@)); + @\exposid{has_val}@ = true; +} +return *construct_at(addressof(@\exposid{val}@), std::forward(args)...); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{emplace}{expected}% +\begin{itemdecl} +template + constexpr T& emplace(initializer_list il, Args&&... args) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_nothrow_constructible_v\&, Args...>} +is \tcode{true}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (has_value()) { + destroy_at(addressof(@\exposid{val}@)); +} else { + destroy_at(addressof(@\exposid{unex}@)); + @\exposid{has_val}@ = true; +} +return *construct_at(addressof(@\exposid{val}@), il, std::forward(args)...); +\end{codeblock} +\end{itemdescr} + +\rSec3[expected.object.swap]{Swap} + +\indexlibrarymember{swap}{expected}% +\begin{itemdecl} +constexpr void swap(expected& rhs) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_swappable_v} is \tcode{true} and +\item +\tcode{is_swappable_v} is \tcode{true} and +\item +\tcode{is_move_constructible_v \&\& is_move_constructible_v} +is \tcode{true}, and +\item +\tcode{is_nothrow_move_constructible_v || is_nothrow_move_constructible_v} +is \tcode{true}. +\end{itemize} + +\pnum +\effects +See \tref{expected.object.swap}. + +\begin{floattable}{\tcode{swap(expected\&)} effects}{expected.object.swap} +{lx{0.35\hsize}x{0.35\hsize}} +\topline +& \chdr{\tcode{this->has_value()}} & \rhdr{\tcode{!has_value()}} \\ \capsep +\lhdr{\tcode{rhs.has_value()}} & + equivalent to: \tcode{using std::swap; swap(\exposid{val}, rhs.\exposid{val});} & + calls \tcode{rhs.swap(*this)} \\ +\lhdr{\tcode{!rhs.has_value()}} & + \seebelow & + equivalent to: \tcode{using std::swap; swap(\exposid{unex}, rhs.\exposid{unex});} \\ +\end{floattable} + +For the case where \tcode{rhs.value()} is \tcode{false} and +\tcode{this->has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +if constexpr (is_nothrow_move_constructible_v) { + E tmp(std::move(rhs.@\exposid{unex}@)); + destroy_at(addressof(rhs.@\exposid{unex}@)); + try { + construct_at(addressof(rhs.@\exposid{val}@), std::move(@\exposid{val}@)); + destroy_at(addressof(@\exposid{val}@)); + construct_at(addressof(@\exposid{unex}@), std::move(tmp)); + } catch(...) { + construct_at(addressof(rhs.@\exposid{unex}@), std::move(tmp)); + throw; + } +} else { + T tmp(std::move(@\exposid{val}@)); + destroy_at(addressof(@\exposid{val}@)); + try { + construct_at(addressof(@\exposid{unex}@), std::move(rhs.@\exposid{unex}@)); + destroy_at(addressof(rhs.@\exposid{unex}@)); + construct_at(addressof(rhs.@\exposid{val}@), std::move(tmp)); + } catch (...) { + construct_at(addressof(@\exposid{val}@), std::move(tmp)); + throw; + } +} +@\exposid{has_val}@ = false; +rhs.@\exposid{has_val}@ = true; +\end{codeblock} + +\pnum +\throws +Any exception thrown by the expressions in the \Fundescx{Effects}. + +\pnum +\remarks +The exception specification is: +\begin{codeblock} +is_nothrow_move_constructible_v && is_nothrow_swappable_v && +is_nothrow_move_constructible_v && is_nothrow_swappable_v +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{swap}{expected}% +\begin{itemdecl} +friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{x.swap(y)}. +\end{itemdescr} + +\rSec3[expected.object.obs]{Observers} + +\indexlibrarymember{operator->}{expected}% +\begin{itemdecl} +constexpr const T* operator->() const noexcept; +constexpr T* operator->() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{has_value()} is \tcode{true}. + +\pnum +\returns +\tcode{addressof(\exposid{val})}. +\end{itemdescr} + +\indexlibrarymember{operator*}{expected}% +\begin{itemdecl} +constexpr const T& operator*() const& noexcept; +constexpr T& operator*() & noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{has_value()} is \tcode{true}. + +\pnum +\returns +\exposid{val}. +\end{itemdescr} + +\indexlibrarymember{operator*}{expected}% +\begin{itemdecl} +constexpr T&& operator*() && noexcept; +constexpr const T&& operator*() const&& noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{has_value()} is \tcode{true}. + +\pnum +\returns +\tcode{std::move(\exposid{val})}. +\end{itemdescr} + +\indexlibrarymember{operator bool}{expected}% +\indexlibrarymember{has_value}{expected}% +\begin{itemdecl} +constexpr explicit operator bool() const noexcept; +constexpr bool has_value() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{has_val}. +\end{itemdescr} + +\indexlibrarymember{value}{expected}% +\begin{itemdecl} +constexpr const T& value() const&; +constexpr T& value() &; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{val}, if \tcode{has_value()} is \tcode{true}. + +\pnum +\throws +\tcode{bad_expected_access(error())} if \tcode{has_value()} is \tcode{false}. +\end{itemdescr} + +\indexlibrarymember{value}{expected}% +\begin{itemdecl} +constexpr T&& value() &&; +constexpr const T&& value() const&&; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{std::move(\exposid{val})}, if \tcode{has_value()} is \tcode{true}. + +\pnum +\throws +\tcode{bad_expected_access(std::move(error()))} +if \tcode{has_value()} is \tcode{false}. +\end{itemdescr} + +\indexlibrarymember{error}{expected}% +\begin{itemdecl} +constexpr const E& error() const& noexcept; +constexpr E& error() & noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{has_value()} is \tcode{false}. + +\pnum +\returns +\exposid{unex}. +\end{itemdescr} + +\indexlibrarymember{error}{expected}% +\begin{itemdecl} +constexpr E&& error() && noexcept; +constexpr const E&& error() const&& noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{has_value()} is \tcode{false}. + +\pnum +\returns +\tcode{std::move(\exposid{unex})}. +\end{itemdescr} + +\indexlibrarymember{value_or}{expected}% +\begin{itemdecl} +template constexpr T value_or(U&& v) const&; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_copy_constructible_v} is \tcode{true} and +\tcode{is_convertible} is \tcode{true}. + +\pnum +\returns +\tcode{has_value() ? **this : static_cast(std::forward(v))}. +\end{itemdescr} + +\indexlibrarymember{value_or}{expected}% +\begin{itemdecl} +template constexpr T value_or(U&& v) &&; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_move_constructible_v} is \tcode{true} and +\tcode{is_convertible} is \tcode{true}. + +\pnum +\returns +\tcode{has_value() ? std::move(**this) : static_cast(std::forward(v))}. +\end{itemdescr} + +\rSec3[expected.object.eq]{Equality operators} + +\indexlibrarymember{operator==}{expected}% +\begin{itemdecl} +template requires (!is_void_v) + friend constexpr bool operator==(const expected& x, const expected& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expressions \tcode{*x == *y} and \tcode{x.error() == y.error()} +are well-formed and their results are convertible to \tcode{bool}. + +\pnum +\returns +If \tcode{x.has_value()} does not equal \tcode{y.has_value()}, \tcode{false}; +otherwise if \tcode{x.has_value()} is \tcode{true}, \tcode{*x == *y}; +otherwise \tcode{x.error() == y.error()}. +\end{itemdescr} + +\indexlibrarymember{operator==}{expected}% +\begin{itemdecl} +template constexpr bool operator==(const expected& x, const T2& v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{*x == v} is well-formed and +its result is convertible to \tcode{bool}. +\begin{note} +\tcode{T1} need not be \oldconcept{EqualityComparable}. +\end{note} + +\pnum +\returns +\tcode{x.has_value() \&\& static_cast(*x == v)}. +\end{itemdescr} + +\indexlibrarymember{operator==}{expected}% +\begin{itemdecl} +template constexpr bool operator==(const expected& x, const unexpected& e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{x.error() == e.value()} is well-formed and +its result is convertible to \tcode{bool}. + +\pnum +\returns +\tcode{!x.has_value() \&\& static_cast(x.error() == e.value())}. +\end{itemdescr} + +\rSec2[expected.void]{Partial specialization of \tcode{expected} for \tcode{void} types} + +\rSec3[expected.void.general]{General} + +\begin{codeblock} +template requires is_void_v +class expected { +public: + using @\libmember{value_type}{expected}@ = T; + using @\libmember{error_type}{expected}@ = E; + using @\libmember{unexpected_type}{expected}@ = unexpected; + + template + using @\libmember{rebind}{expected}@ = expected; + + // \ref{expected.void.ctor}, constructors + constexpr expected() noexcept; + constexpr explicit(@\seebelow@) expected(const expected&); + constexpr explicit(@\seebelow@) expected(expected&&) noexcept(@\seebelow@); + template + constexpr explicit(@\seebelow@) expected(const expected&); + template + constexpr explicit(@\seebelow@) expected(expected&&); + + template + constexpr expected(const unexpected&); + template + constexpr expected(unexpected&&); + + constexpr explicit expected(in_place_t) noexcept; + template + constexpr explicit expected(unexpect_t, Args&&...); + template + constexpr explicit expected(unexpect_t, initializer_list, Args&&...); + + + // \ref{expected.void.dtor}, destructor + constexpr ~expected(); + + // \ref{expected.void.assign}, assignment + constexpr expected& operator=(const expected&); + constexpr expected& operator=(expected&&) noexcept(@\seebelow@); + template + constexpr expected& operator=(const unexpected&); + template + constexpr expected& operator=(unexpected&&); + constexpr void emplace() noexcept; + + // \ref{expected.void.swap}, swap + constexpr void swap(expected&) noexcept(@\seebelow@); + friend constexpr void swap(expected&, expected&) noexcept(@\seebelow@); + + // \ref{expected.void.obs}, observers + constexpr explicit operator bool() const noexcept; + constexpr bool has_value() const noexcept; + constexpr void operator*() const noexcept; + constexpr void value() const&; + constexpr void value() &&; + constexpr const E& error() const&; + constexpr E& error() &; + constexpr const E&& error() const&&; + constexpr E&& error() &&; + + // \ref{expected.void.eq}, equality operators + template requires is_void_v + friend constexpr bool operator==(const expected& x, const expected& y); + template + friend constexpr bool operator==(const expected&, const unexpected&); + +private: + bool @\exposid{has_val}@; // \expos + union { + E @\exposid{unex}@; // \expos + }; +}; +\end{codeblock} + +\pnum +\tcode{E} shall meet the requirements of +\oldconcept{Destructible} (\tref{cpp17.destructible}). + +\rSec3[expected.void.ctor]{Constructors} + +\indexlibraryctor{expected}% +\begin{itemdecl} +constexpr expected() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{has_value()} is \tcode{true}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +constexpr expected(const expected& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{rhs.has_value()} is \tcode{false}, +direct-non-list-initializes \exposid{unex} with \tcode{rhs.error()}. + +\pnum +\ensures +\tcode{rhs.has_value() == this->has_value()}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. + +\pnum +\remarks +This constructor is defined as deleted +unless \tcode{is_copy_constructible_v} is \tcode{true}. + +\pnum +This constructor is trivial +if \tcode{is_trivially_copy_constructible_v} is \tcode{true}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +constexpr expected(expected&& rhs) noexcept(is_nothrow_move_constructible_v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_move_constructible_v} is \tcode{true}. + +\pnum +\effects +If \tcode{rhs.has_value()} is \tcode{false}, +direct-non-list-initializes \exposid{unex} with \tcode{std::move(rhs.error())}. + +\pnum +\ensures +\tcode{rhs.has_value()} is unchanged; +\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. + +\pnum +\remarks +This constructor is trivial +if \tcode{is_trivially_move_constructible_v} is \tcode{true}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit(!is_convertible_v) expected(const expected& rhs); +template + constexpr explicit(!is_convertible_v) expected(expected&& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. + +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_void_v} is \tcode{true}; and +\item +\tcode{is_constructible_v} is \tcode{true}; and +\item +\tcode{is_constructible_v, expected\&>} +is \tcode{false}; and +\item +\tcode{is_constructible_v, expected>} +is \tcode{false}; and +\item +\tcode{is_constructible_v, const expected\&>} +is \tcode{false}; and +\item +\tcode{is_constructible_v, const expected>} +is \tcode{false}. +\end{itemize} + +\pnum +\effects +If \tcode{rhs.has_value()} is \tcode{false}, +direct-non-list-initializes \exposid{unex} +with \tcode{std::forward(rhs.er\-ror())}. + +\pnum +\ensures +\tcode{rhs.has_value()} is unchanged; +\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit(!is_convertible_v) expected(const unexpected& e); +template + constexpr explicit(!is_convertible_v) expected(unexpected&& e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. + +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +Direct-non-list-initializes \exposid{unex} +with \tcode{std::forward(e.value())}. + +\pnum +\ensures +\tcode{has_value()} is \tcode{false}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +constexpr explicit expected(in_place_t) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{has_value()} is \tcode{true}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit expected(unexpect_t, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +Direct-non-list-initializes \exposid{unex} +with \tcode{std::forward(args)...}. + +\pnum +\ensures +\tcode{has_value()} is \tcode{false}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. +\end{itemdescr} + +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit expected(unexpect_t, initializer_list il, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. + +\pnum +\effects +Direct-non-list-initializes \exposid{unex} +with \tcode{il, std::forward(args)...}. + +\pnum +\ensures +\tcode{has_value()} is \tcode{false}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. +\end{itemdescr} + +\rSec3[expected.void.dtor]{Destructor} + +\indexlibrarydtor{expected}% +\begin{itemdecl} +constexpr ~expected(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{has_value()} is \tcode{false}, destroys \exposid{unex}. + +\pnum +\remarks +If \tcode{is_trivially_destructible_v} is \tcode{true}, +then this destructor is a trivial destructor. +\end{itemdescr} + +\rSec3[expected.void.assign]{Assignment} + +\indexlibrarymember{operator=}{expected}% +\begin{itemdecl} +constexpr expected& operator=(const expected& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +If \tcode{this->has_value() \&\& rhs.has_value()} is \tcode{true}, no effects. +\item +Otherwise, if \tcode{this->has_value()} is \tcode{true}, +equivalent to: \tcode{construct_at(addressof(\exposid{unex}), rhs.\exposid{unex}); \exposid{has_val} = false;} +\item +Otherwise, if \tcode{rhs.has_value()} is \tcode{true}, +destroys \exposid{unex} and sets \exposid{has_val} to \tcode{true}. +\item +Otherwise, equivalent to \tcode{\exposid{unex} = rhs.error()}. +\end{itemize} + +\pnum +\returns +\tcode{*this}. + +\pnum +\remarks +This operator is defined as deleted unless +\tcode{is_copy_assignable_v} is \tcode{true} and +\tcode{is_copy_constructible_v} is \tcode{true}. +\end{itemdescr} + +\indexlibrarymember{operator=}{expected}% +\begin{itemdecl} +constexpr expected& operator=(expected&& rhs) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +If \tcode{this->has_value() \&\& rhs.has_value()} is \tcode{true}, no effects. +\item +Otherwise, if \tcode{this->has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +construct_at(addressof(@\exposid{unex}@), std::move(rhs.@\exposid{unex}@)); +@\exposid{has_val}@ = false; +\end{codeblock} +\item +Otherwise, if \tcode{rhs.has_value()} is \tcode{true}, +destroys \exposid{unex} and sets \exposid{has_val} to \tcode{true}. +\item +Otherwise, equivalent to \tcode{\exposid{unex} = rhs.error()}. +\end{itemize} + +\pnum +\returns +\tcode{*this}. + +\pnum +\remarks +The exception specification is +\tcode{is_nothrow_move_constructible_v \&\& is_nothrow_move_assignable_v}. + +\pnum +This operator is defined as deleted unless +\tcode{is_move_constructible_v} is \tcode{true} and +\tcode{is_move_assignable_v} is \tcode{true}. +\end{itemdescr} + +\indexlibrarymember{operator=}{expected}% +\begin{itemdecl} +template + constexpr expected& operator=(const unexpected& e); +template + constexpr expected& operator=(unexpected&& e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. + +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true} and +\tcode{is_assignable_v} is \tcode{true}. + +\pnum +\effects +\begin{itemize} +\item +If \tcode{has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +construct_at(addressof(@\exposid{unex}@), std::forward(e.value())); +@\exposid{has_val}@ = false; +\end{codeblock} +\item +Otherwise, equivalent to: +\tcode{\exposid{unex} = std::forward(e.value());} +\end{itemize} + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{emplace}{expected}% +\begin{itemdecl} +constexpr void emplace() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{has_value()} is \tcode{false}, +destroys \exposid{unex} and sets \exposid{has_val} to \tcode{true}. +\end{itemdescr} + +\rSec3[expected.void.swap]{Swap} + +\indexlibrarymember{swap}{expected}% +\begin{itemdecl} +constexpr void swap(expected& rhs) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_swappable_v} is \tcode{true} and +\tcode{is_move_constructible_v} is \tcode{true}. + +\pnum +\effects +See \tref{expected.void.swap}. + +\begin{floattable}{\tcode{swap(expected\&)} effects}{expected.void.swap} +{lx{0.35\hsize}x{0.35\hsize}} +\topline +& \chdr{\tcode{this->has_value()}} & \rhdr{\tcode{!has_value()}} \\ \capsep +\lhdr{\tcode{rhs.has_value()}} & + no effects & + calls \tcode{rhs.swap(*this)} \\ +\lhdr{\tcode{!rhs.has_value()}} & + \seebelow & + equivalent to: \tcode{using std::swap; swap(\exposid{unex}, rhs.\exposid{unex});} \\ +\end{floattable} + +For the case where \tcode{rhs.value()} is \tcode{false} and +\tcode{this->has_value()} is \tcode{true}, equivalent to: +\begin{codeblock} +construct_at(addressof(@\exposid{unex}@), std::move(rhs.@\exposid{unex}@)); +destroy_at(addressof(rhs.@\exposid{unex}@)); +@\exposid{has_val}@ = false; +rhs.@\exposid{has_val}@ = true; +\end{codeblock} + +\pnum +\throws +Any exception thrown by the expressions in the \Fundescx{Effects}. + +\pnum +\remarks +The exception specification is +\tcode{is_nothrow_move_constructible_v \&\& is_nothrow_swappable_v}. +\end{itemdescr} + +\indexlibrarymember{swap}{expected}% +\begin{itemdecl} +friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{x.swap(y)}. +\end{itemdescr} + +\rSec3[expected.void.obs]{Observers} + +\indexlibrarymember{operator bool}{expected}% +\indexlibrarymember{has_value}{expected}% +\begin{itemdecl} +constexpr explicit operator bool() const noexcept; +constexpr bool has_value() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{has_val}. +\end{itemdescr} + +\indexlibrarymember{operator*}{expected}% +\begin{itemdecl} +constexpr void operator*() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{has_value()} is \tcode{true}. +\end{itemdescr} + +\indexlibrarymember{value}{expected}% +\begin{itemdecl} +constexpr void value() const&; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\throws +\tcode{bad_expected_access(error())} if \tcode{has_value()} is \tcode{false}. +\end{itemdescr} + +\indexlibrarymember{value}{expected}% +\begin{itemdecl} +constexpr void value() &&; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\throws +\tcode{bad_expected_access(std::move(error()))} +if \tcode{has_value()} is \tcode{false}. +\end{itemdescr} + +\indexlibrarymember{error}{expected}% +\begin{itemdecl} +constexpr const E& error() const&; +constexpr E& error() &; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{has_value()} is \tcode{false}. + +\pnum +\returns +\exposid{unex}. +\end{itemdescr} + +\indexlibrarymember{error}{expected}% +\begin{itemdecl} +constexpr E&& error() &&; +constexpr const E&& error() const&&; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{has_value()} is \tcode{false}. + +\pnum +\returns +\tcode{std::move(\exposid{unex})}. +\end{itemdescr} + +\rSec3[expected.void.eq]{Equality operators} + +\indexlibrarymember{operator==}{expected}% +\begin{itemdecl} +template requires is_void_v + friend constexpr bool operator==(const expected& x, const expected& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{x.error() == y.error()} is well-formed and +its result is convertible to \tcode{bool}. + +\pnum +\returns +If \tcode{x.has_value()} does not equal \tcode{y.has_value()}, \tcode{false}; +otherwise \tcode{x.has_value() || static_cast(x.error() == y.error())}. +\end{itemdescr} + +\indexlibrarymember{operator==}{expected}% +\begin{itemdecl} +template + friend constexpr bool operator==(const expected& x, const unexpected& e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{x.error() == e.value()} is well-formed and +its result is convertible to \tcode{bool}. + +\pnum +\returns +\tcode{!x.has_value() \&\& static_cast(x.error() == e.value())}. +\end{itemdescr} + \rSec1[bitset]{Bitsets} \indexlibraryglobal{bitset}% From 71f6e85eaa6bba99f6901074eebeabc9f3352719 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 11 Feb 2022 10:27:27 +0100 Subject: [PATCH 108/182] [expected] Fixes for issues introduced with P0323R12. Includes fixing a misspelled function name in [expected.object.ctor] and misspelled parameters in [expected.un.ctor]. Changes "This subclause" to "Subclause " to accommodate the additional sectioning that was introduced to avoid hanging paragraphs. --- source/utilities.tex | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index 6308313a8b..981ddd26c9 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -6470,7 +6470,7 @@ \rSec2[expected.general]{In general} \pnum -This subclause describes the class template \tcode{expected} +Subclause \ref{expected} describes the class template \tcode{expected} that represents expected objects. An \tcode{expected} object holds an object of type \tcode{T} or an object of type \tcode{unexpected} and @@ -6485,7 +6485,7 @@ // \ref{expected.un.object}, class template \tcode{unexpected} template class unexpected; - // \ref{expected.bad}, class \tcode{bad_expected_access} + // \ref{expected.bad}, class template \tcode{bad_expected_access} template class bad_expected_access; // \ref{expected.bad.void}, specialization for \tcode{void} @@ -6510,7 +6510,7 @@ \rSec3[expected.un.general]{General} \pnum -This subclause describes the class template \tcode{unexpected} +Subclause \ref{expected.unexpected} describes the class template \tcode{unexpected} that represents unexpected objects stored in \tcode{expected} objects. \rSec3[expected.un.object]{Class template \tcode{unexpected}} @@ -6595,7 +6595,7 @@ \indexlibraryctor{unexpected}% \begin{itemdecl} template - constexpr explicit unexpected(in_place_t, Args&&...); + constexpr explicit unexpected(in_place_t, Args&&... args); \end{itemdecl} \begin{itemdescr} @@ -6616,7 +6616,7 @@ \indexlibraryctor{unexpected}% \begin{itemdecl} template - constexpr explicit unexpected(in_place_t, initializer_list, Args&&...); + constexpr explicit unexpected(in_place_t, initializer_list il, Args&&... args); \end{itemdecl} \begin{itemdescr} @@ -6627,7 +6627,7 @@ \pnum \effects Direct-non-list-initializes -\exposid{val} with \tcode{std::forward(args)...}. +\exposid{val} with \tcode{il, std::forward(args)...}. \pnum \throws @@ -6874,7 +6874,7 @@ // \ref{expected.object.swap}, swap constexpr void swap(expected&) noexcept(@\seebelow@); - friend constexpr void swap(expected&, expected&) noexcept(@\seebelow@); + friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); // \ref{expected.object.obs}, observers constexpr const T* operator->() const noexcept; @@ -6897,7 +6897,7 @@ template constexpr T value_or(U&&) &&; // \ref{expected.object.eq}, equality operators - template + template requires (!is_void_v) friend constexpr bool operator==(const expected& x, const expected& y); template friend constexpr bool operator==(const expected&, const T2&); @@ -7044,7 +7044,7 @@ \pnum \remarks -The exception specification is +The exception specification is equivalent to \tcode{is_nothrow_move_constructible_v \&\& is_nothrow_move_constructible_v}. @@ -7185,7 +7185,7 @@ \pnum \effects -Direct-non-list-initializes \exposid{unex} with \tcode{std::forward(e.error())}. +Direct-non-list-initializes \exposid{unex} with \tcode{std::forward(e.value())}. \pnum \ensures @@ -7383,7 +7383,7 @@ \item \tcode{is_copy_constructible_v} is \tcode{true} and \item -\tcode{is_nothrow_move_constructible_v || is_nothrow_move_constructible_v} +\tcode{is_nothrow_move_constructible_v || is_nothrow_move_constructible_v} is \tcode{true}. \end{itemize} \end{itemdescr} @@ -7434,7 +7434,7 @@ \pnum \remarks -The exception specification is +The exception specification is equivalent to: \begin{codeblock} is_nothrow_move_assignable_v && is_nothrow_move_constructible_v && is_nothrow_move_assignable_v && is_nothrow_move_constructible_v @@ -7609,7 +7609,7 @@ \begin{floattable}{\tcode{swap(expected\&)} effects}{expected.object.swap} {lx{0.35\hsize}x{0.35\hsize}} \topline -& \chdr{\tcode{this->has_value()}} & \rhdr{\tcode{!has_value()}} \\ \capsep +& \chdr{\tcode{this->has_value()}} & \rhdr{\tcode{!this->has_value()}} \\ \capsep \lhdr{\tcode{rhs.has_value()}} & equivalent to: \tcode{using std::swap; swap(\exposid{val}, rhs.\exposid{val});} & calls \tcode{rhs.swap(*this)} \\ @@ -7654,7 +7654,7 @@ \pnum \remarks -The exception specification is: +The exception specification is equivalent to: \begin{codeblock} is_nothrow_move_constructible_v && is_nothrow_swappable_v && is_nothrow_move_constructible_v && is_nothrow_swappable_v @@ -7809,7 +7809,7 @@ \pnum \mandates \tcode{is_copy_constructible_v} is \tcode{true} and -\tcode{is_convertible} is \tcode{true}. +\tcode{is_convertible_v} is \tcode{true}. \pnum \returns @@ -7825,7 +7825,7 @@ \pnum \mandates \tcode{is_move_constructible_v} is \tcode{true} and -\tcode{is_convertible} is \tcode{true}. +\tcode{is_convertible_v} is \tcode{true}. \pnum \returns @@ -7855,7 +7855,7 @@ \indexlibrarymember{operator==}{expected}% \begin{itemdecl} -template constexpr bool operator==(const expected& x, const T2& v); +template friend constexpr bool operator==(const expected& x, const T2& v); \end{itemdecl} \begin{itemdescr} @@ -7874,7 +7874,7 @@ \indexlibrarymember{operator==}{expected}% \begin{itemdecl} -template constexpr bool operator==(const expected& x, const unexpected& e); +template friend constexpr bool operator==(const expected& x, const unexpected& e); \end{itemdecl} \begin{itemdescr} @@ -7938,7 +7938,7 @@ // \ref{expected.void.swap}, swap constexpr void swap(expected&) noexcept(@\seebelow@); - friend constexpr void swap(expected&, expected&) noexcept(@\seebelow@); + friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); // \ref{expected.void.obs}, observers constexpr explicit operator bool() const noexcept; @@ -8265,7 +8265,7 @@ \pnum \remarks -The exception specification is +The exception specification is equivalent to \tcode{is_nothrow_move_constructible_v \&\& is_nothrow_move_assignable_v}. \pnum @@ -8343,7 +8343,7 @@ \begin{floattable}{\tcode{swap(expected\&)} effects}{expected.void.swap} {lx{0.35\hsize}x{0.35\hsize}} \topline -& \chdr{\tcode{this->has_value()}} & \rhdr{\tcode{!has_value()}} \\ \capsep +& \chdr{\tcode{this->has_value()}} & \rhdr{\tcode{!this->has_value()}} \\ \capsep \lhdr{\tcode{rhs.has_value()}} & no effects & calls \tcode{rhs.swap(*this)} \\ @@ -8367,7 +8367,7 @@ \pnum \remarks -The exception specification is +The exception specification is equivalent to \tcode{is_nothrow_move_constructible_v \&\& is_nothrow_swappable_v}. \end{itemdescr} From fb1d235e5fbd029616fabda4a5fd0e213a6bf433 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 9 Feb 2022 13:58:43 +0100 Subject: [PATCH 109/182] P0533R9 constexpr for and --- source/expressions.tex | 6 +- source/intro.tex | 6 + source/lib-intro.tex | 24 +++ source/numerics.tex | 372 ++++++++++++++++++++--------------------- source/support.tex | 31 ++-- 5 files changed, 237 insertions(+), 202 deletions(-) diff --git a/source/expressions.tex b/source/expressions.tex index 8a3fab39bf..3962861606 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -7393,7 +7393,11 @@ an \grammarterm{asm-declaration}\iref{dcl.asm}; \item -an invocation of the \tcode{va_arg} macro\iref{cstdarg.syn}; or +an invocation of the \tcode{va_arg} macro\iref{cstdarg.syn}; + +\item +a non-constant library call\iref{defns.nonconst.libcall}; +or \item a \keyword{goto} statement\iref{stmt.goto}. diff --git a/source/intro.tex b/source/intro.tex index cbee223c7b..4bde4a91a0 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -423,6 +423,12 @@ sequence of one or more bytes representing the code unit sequence for an encoded character of the execution character set +\indexdefn{library call!non-constant}% +\definition{non-constant library call}{defns.nonconst.libcall} +invocation of a library function that, +as part of evaluating any expression \tcode{E}, +prevents \tcode{E} from being a core constant expression + \definition{NTCTS}{defns.ntcts} \defncontext{library} \indexdefn{NTCTS}% diff --git a/source/lib-intro.tex b/source/lib-intro.tex index a4e4fe6889..bf960caa7e 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -136,6 +136,30 @@ ISO C \tcode{restrict} qualifier) are the same unless otherwise stated. +\pnum +A call to a C standard library function is +a non-constant library call\iref{defns.nonconst.libcall} +if it raises a floating-point exception other than \tcode{FE_INEXACT}. +The semantics of a call to a C standard library function +evaluated as a core constant expression +are those specified in Annex F of the C standard +\begin{footnote} +See also ISO/IEC 9899:2018 section 7.6. +\end{footnote} +to the extent applicable to the floating-point types\iref{basic.fundamental} +that are parameter types of the called function. +\begin{note} +Annex F specifies +the conditions under which floating-point exceptions are raised and +the behavior when NaNs and/or infinities are passed as arguments. +\end{note} +\begin{note} +Equivalently, a call to a C standard library function is +a non-constant library call +if \tcode{errno} is set +when \tcode{math_errhandling \& MATH_ERRNO} is \tcode{true}. +\end{note} + \rSec1[description]{Method of description} \rSec2[description.general]{General} diff --git a/source/numerics.tex b/source/numerics.tex index 9448d6a94a..dcb43333ab 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -9538,23 +9538,23 @@ float expm1f(float x); long double expm1l(long double x); - float frexp(float value, int* exp); // see \ref{library.c} - double frexp(double value, int* exp); - long double frexp(long double value, int* exp); // see \ref{library.c} - float frexpf(float value, int* exp); - long double frexpl(long double value, int* exp); - - int ilogb(float x); // see \ref{library.c} - int ilogb(double x); - int ilogb(long double x); // see \ref{library.c} - int ilogbf(float x); - int ilogbl(long double x); - - float ldexp(float x, int exp); // see \ref{library.c} - double ldexp(double x, int exp); - long double ldexp(long double x, int exp); // see \ref{library.c} - float ldexpf(float x, int exp); - long double ldexpl(long double x, int exp); + constexpr float frexp(float value, int* exp); // see \ref{library.c} + constexpr double frexp(double value, int* exp); + constexpr long double frexp(long double value, int* exp); // see \ref{library.c} + constexpr float frexpf(float value, int* exp); + constexpr long double frexpl(long double value, int* exp); + + constexpr int ilogb(float x); // see \ref{library.c} + constexpr int ilogb(double x); + constexpr int ilogb(long double x); // see \ref{library.c} + constexpr int ilogbf(float x); + constexpr int ilogbl(long double x); + + constexpr float ldexp(float x, int exp); // see \ref{library.c} + constexpr double ldexp(double x, int exp); + constexpr long double ldexp(long double x, int exp); // see \ref{library.c} + constexpr float ldexpf(float x, int exp); + constexpr long double ldexpl(long double x, int exp); float log(float x); // see \ref{library.c} double log(double x); @@ -9580,29 +9580,29 @@ float log2f(float x); long double log2l(long double x); - float logb(float x); // see \ref{library.c} - double logb(double x); - long double logb(long double x); // see \ref{library.c} - float logbf(float x); - long double logbl(long double x); - - float modf(float value, float* iptr); // see \ref{library.c} - double modf(double value, double* iptr); - long double modf(long double value, long double* iptr); // see \ref{library.c} - float modff(float value, float* iptr); - long double modfl(long double value, long double* iptr); - - float scalbn(float x, int n); // see \ref{library.c} - double scalbn(double x, int n); - long double scalbn(long double x, int n); // see \ref{library.c} - float scalbnf(float x, int n); - long double scalbnl(long double x, int n); - - float scalbln(float x, long int n); // see \ref{library.c} - double scalbln(double x, long int n); - long double scalbln(long double x, long int n); // see \ref{library.c} - float scalblnf(float x, long int n); - long double scalblnl(long double x, long int n); + constexpr float logb(float x); // see \ref{library.c} + constexpr double logb(double x); + constexpr long double logb(long double x); // see \ref{library.c} + constexpr float logbf(float x); + constexpr long double logbl(long double x); + + constexpr float modf(float value, float* iptr); // see \ref{library.c} + constexpr double modf(double value, double* iptr); + constexpr long double modf(long double value, long double* iptr); // see \ref{library.c} + constexpr float modff(float value, float* iptr); + constexpr long double modfl(long double value, long double* iptr); + + constexpr float scalbn(float x, int n); // see \ref{library.c} + constexpr double scalbn(double x, int n); + constexpr long double scalbn(long double x, int n); // see \ref{library.c} + constexpr float scalbnf(float x, int n); + constexpr long double scalbnl(long double x, int n); + + constexpr float scalbln(float x, long int n); // see \ref{library.c} + constexpr double scalbln(double x, long int n); + constexpr long double scalbln(long double x, long int n); // see \ref{library.c} + constexpr float scalblnf(float x, long int n); + constexpr long double scalblnl(long double x, long int n); float cbrt(float x); // see \ref{library.c} double cbrt(double x); @@ -9611,18 +9611,18 @@ long double cbrtl(long double x); // \ref{c.math.abs}, absolute values - int abs(int j); - long int abs(long int j); - long long int abs(long long int j); - float abs(float j); - double abs(double j); - long double abs(long double j); - - float fabs(float x); // see \ref{library.c} - double fabs(double x); - long double fabs(long double x); // see \ref{library.c} - float fabsf(float x); - long double fabsl(long double x); + constexpr int abs(int j); + constexpr long int abs(long int j); + constexpr long long int abs(long long int j); + constexpr float abs(float j); + constexpr double abs(double j); + constexpr long double abs(long double j); + + constexpr float fabs(float x); // see \ref{library.c} + constexpr double fabs(double x); + constexpr long double fabs(long double x); // see \ref{library.c} + constexpr float fabsf(float x); + constexpr long double fabsl(long double x); float hypot(float x, float y); // see \ref{library.c} double hypot(double x, double y); @@ -9671,17 +9671,17 @@ float tgammaf(float x); long double tgammal(long double x); - float ceil(float x); // see \ref{library.c} - double ceil(double x); - long double ceil(long double x); // see \ref{library.c} - float ceilf(float x); - long double ceill(long double x); + constexpr float ceil(float x); // see \ref{library.c} + constexpr double ceil(double x); + constexpr long double ceil(long double x); // see \ref{library.c} + constexpr float ceilf(float x); + constexpr long double ceill(long double x); - float floor(float x); // see \ref{library.c} - double floor(double x); - long double floor(long double x); // see \ref{library.c} - float floorf(float x); - long double floorl(long double x); + constexpr float floor(float x); // see \ref{library.c} + constexpr double floor(double x); + constexpr long double floor(long double x); // see \ref{library.c} + constexpr float floorf(float x); + constexpr long double floorl(long double x); float nearbyint(float x); // see \ref{library.c} double nearbyint(double x); @@ -9707,93 +9707,93 @@ long long int llrintf(float x); long long int llrintl(long double x); - float round(float x); // see \ref{library.c} - double round(double x); - long double round(long double x); // see \ref{library.c} - float roundf(float x); - long double roundl(long double x); - - long int lround(float x); // see \ref{library.c} - long int lround(double x); - long int lround(long double x); // see \ref{library.c} - long int lroundf(float x); - long int lroundl(long double x); - - long long int llround(float x); // see \ref{library.c} - long long int llround(double x); - long long int llround(long double x); // see \ref{library.c} - long long int llroundf(float x); - long long int llroundl(long double x); - - float trunc(float x); // see \ref{library.c} - double trunc(double x); - long double trunc(long double x); // see \ref{library.c} - float truncf(float x); - long double truncl(long double x); - - float fmod(float x, float y); // see \ref{library.c} - double fmod(double x, double y); - long double fmod(long double x, long double y); // see \ref{library.c} - float fmodf(float x, float y); - long double fmodl(long double x, long double y); - - float remainder(float x, float y); // see \ref{library.c} - double remainder(double x, double y); - long double remainder(long double x, long double y); // see \ref{library.c} - float remainderf(float x, float y); - long double remainderl(long double x, long double y); - - float remquo(float x, float y, int* quo); // see \ref{library.c} - double remquo(double x, double y, int* quo); - long double remquo(long double x, long double y, int* quo); // see \ref{library.c} - float remquof(float x, float y, int* quo); - long double remquol(long double x, long double y, int* quo); - - float copysign(float x, float y); // see \ref{library.c} - double copysign(double x, double y); - long double copysign(long double x, long double y); // see \ref{library.c} - float copysignf(float x, float y); - long double copysignl(long double x, long double y); + constexpr float round(float x); // see \ref{library.c} + constexpr double round(double x); + constexpr long double round(long double x); // see \ref{library.c} + constexpr float roundf(float x); + constexpr long double roundl(long double x); + + constexpr long int lround(float x); // see \ref{library.c} + constexpr long int lround(double x); + constexpr long int lround(long double x); // see \ref{library.c} + constexpr long int lroundf(float x); + constexpr long int lroundl(long double x); + + constexpr long long int llround(float x); // see \ref{library.c} + constexpr long long int llround(double x); + constexpr long long int llround(long double x); // see \ref{library.c} + constexpr long long int llroundf(float x); + constexpr long long int llroundl(long double x); + + constexpr float trunc(float x); // see \ref{library.c} + constexpr double trunc(double x); + constexpr long double trunc(long double x); // see \ref{library.c} + constexpr float truncf(float x); + constexpr long double truncl(long double x); + + constexpr float fmod(float x, float y); // see \ref{library.c} + constexpr double fmod(double x, double y); + constexpr long double fmod(long double x, long double y); // see \ref{library.c} + constexpr float fmodf(float x, float y); + constexpr long double fmodl(long double x, long double y); + + constexpr float remainder(float x, float y); // see \ref{library.c} + constexpr double remainder(double x, double y); + constexpr long double remainder(long double x, long double y); // see \ref{library.c} + constexpr float remainderf(float x, float y); + constexpr long double remainderl(long double x, long double y); + + constexpr float remquo(float x, float y, int* quo); // see \ref{library.c} + constexpr double remquo(double x, double y, int* quo); + constexpr long double remquo(long double x, long double y, int* quo); // see \ref{library.c} + constexpr float remquof(float x, float y, int* quo); + constexpr long double remquol(long double x, long double y, int* quo); + + constexpr float copysign(float x, float y); // see \ref{library.c} + constexpr double copysign(double x, double y); + constexpr long double copysign(long double x, long double y); // see \ref{library.c} + constexpr float copysignf(float x, float y); + constexpr long double copysignl(long double x, long double y); double nan(const char* tagp); float nanf(const char* tagp); long double nanl(const char* tagp); - float nextafter(float x, float y); // see \ref{library.c} - double nextafter(double x, double y); - long double nextafter(long double x, long double y); // see \ref{library.c} - float nextafterf(float x, float y); - long double nextafterl(long double x, long double y); - - float nexttoward(float x, long double y); // see \ref{library.c} - double nexttoward(double x, long double y); - long double nexttoward(long double x, long double y); // see \ref{library.c} - float nexttowardf(float x, long double y); - long double nexttowardl(long double x, long double y); - - float fdim(float x, float y); // see \ref{library.c} - double fdim(double x, double y); - long double fdim(long double x, long double y); // see \ref{library.c} - float fdimf(float x, float y); - long double fdiml(long double x, long double y); - - float fmax(float x, float y); // see \ref{library.c} - double fmax(double x, double y); - long double fmax(long double x, long double y); // see \ref{library.c} - float fmaxf(float x, float y); - long double fmaxl(long double x, long double y); - - float fmin(float x, float y); // see \ref{library.c} - double fmin(double x, double y); - long double fmin(long double x, long double y); // see \ref{library.c} - float fminf(float x, float y); - long double fminl(long double x, long double y); - - float fma(float x, float y, float z); // see \ref{library.c} - double fma(double x, double y, double z); - long double fma(long double x, long double y, long double z); // see \ref{library.c} - float fmaf(float x, float y, float z); - long double fmal(long double x, long double y, long double z); + constexpr float nextafter(float x, float y); // see \ref{library.c} + constexpr double nextafter(double x, double y); + constexpr long double nextafter(long double x, long double y); // see \ref{library.c} + constexpr float nextafterf(float x, float y); + constexpr long double nextafterl(long double x, long double y); + + constexpr float nexttoward(float x, long double y); // see \ref{library.c} + constexpr double nexttoward(double x, long double y); + constexpr long double nexttoward(long double x, long double y); // see \ref{library.c} + constexpr float nexttowardf(float x, long double y); + constexpr long double nexttowardl(long double x, long double y); + + constexpr float fdim(float x, float y); // see \ref{library.c} + constexpr double fdim(double x, double y); + constexpr long double fdim(long double x, long double y); // see \ref{library.c} + constexpr float fdimf(float x, float y); + constexpr long double fdiml(long double x, long double y); + + constexpr float fmax(float x, float y); // see \ref{library.c} + constexpr double fmax(double x, double y); + constexpr long double fmax(long double x, long double y); // see \ref{library.c} + constexpr float fmaxf(float x, float y); + constexpr long double fmaxl(long double x, long double y); + + constexpr float fmin(float x, float y); // see \ref{library.c} + constexpr double fmin(double x, double y); + constexpr long double fmin(long double x, long double y); // see \ref{library.c} + constexpr float fminf(float x, float y); + constexpr long double fminl(long double x, long double y); + + constexpr float fma(float x, float y, float z); // see \ref{library.c} + constexpr double fma(double x, double y, double z); + constexpr long double fma(long double x, long double y, long double z); // see \ref{library.c} + constexpr float fmaf(float x, float y, float z); + constexpr long double fmal(long double x, long double y, long double z); // \ref{c.math.lerp}, linear interpolation constexpr float lerp(float a, float b, float t) noexcept; @@ -9801,53 +9801,53 @@ constexpr long double lerp(long double a, long double b, long double t) noexcept; // \ref{c.math.fpclass}, classification / comparison functions - int fpclassify(float x); - int fpclassify(double x); - int fpclassify(long double x); + constexpr int fpclassify(float x); + constexpr int fpclassify(double x); + constexpr int fpclassify(long double x); - bool isfinite(float x); - bool isfinite(double x); - bool isfinite(long double x); + constexpr bool isfinite(float x); + constexpr bool isfinite(double x); + constexpr bool isfinite(long double x); - bool isinf(float x); - bool isinf(double x); - bool isinf(long double x); + constexpr bool isinf(float x); + constexpr bool isinf(double x); + constexpr bool isinf(long double x); - bool isnan(float x); - bool isnan(double x); - bool isnan(long double x); + constexpr bool isnan(float x); + constexpr bool isnan(double x); + constexpr bool isnan(long double x); - bool isnormal(float x); - bool isnormal(double x); - bool isnormal(long double x); + constexpr bool isnormal(float x); + constexpr bool isnormal(double x); + constexpr bool isnormal(long double x); - bool signbit(float x); - bool signbit(double x); - bool signbit(long double x); + constexpr bool signbit(float x); + constexpr bool signbit(double x); + constexpr bool signbit(long double x); - bool isgreater(float x, float y); - bool isgreater(double x, double y); - bool isgreater(long double x, long double y); + constexpr bool isgreater(float x, float y); + constexpr bool isgreater(double x, double y); + constexpr bool isgreater(long double x, long double y); - bool isgreaterequal(float x, float y); - bool isgreaterequal(double x, double y); - bool isgreaterequal(long double x, long double y); + constexpr bool isgreaterequal(float x, float y); + constexpr bool isgreaterequal(double x, double y); + constexpr bool isgreaterequal(long double x, long double y); - bool isless(float x, float y); - bool isless(double x, double y); - bool isless(long double x, long double y); + constexpr bool isless(float x, float y); + constexpr bool isless(double x, double y); + constexpr bool isless(long double x, long double y); - bool islessequal(float x, float y); - bool islessequal(double x, double y); - bool islessequal(long double x, long double y); + constexpr bool islessequal(float x, float y); + constexpr bool islessequal(double x, double y); + constexpr bool islessequal(long double x, long double y); - bool islessgreater(float x, float y); - bool islessgreater(double x, double y); - bool islessgreater(long double x, long double y); + constexpr bool islessgreater(float x, float y); + constexpr bool islessgreater(double x, double y); + constexpr bool islessgreater(long double x, long double y); - bool isunordered(float x, float y); - bool isunordered(double x, double y); - bool isunordered(long double x, long double y); + constexpr bool isunordered(float x, float y); + constexpr bool isunordered(double x, double y); + constexpr bool isunordered(long double x, long double y); // \ref{sf.cmath}, mathematical special functions @@ -10014,12 +10014,12 @@ \indexlibraryglobal{abs}% \begin{itemdecl} -int abs(int j); -long int abs(long int j); -long long int abs(long long int j); -float abs(float j); -double abs(double j); -long double abs(long double j); +constexpr int abs(int j); +constexpr long int abs(long int j); +constexpr long long int abs(long long int j); +constexpr float abs(float j); +constexpr double abs(double j); +constexpr long double abs(long double j); \end{itemdecl} \begin{itemdescr} diff --git a/source/support.tex b/source/support.tex index e8ccd20800..cbd48c58be 100644 --- a/source/support.tex +++ b/source/support.tex @@ -219,21 +219,21 @@ void srand(unsigned int seed); // \ref{c.math.abs}, absolute values - int abs(int j); - long int abs(long int j); - long long int abs(long long int j); - float abs(float j); - double abs(double j); - long double abs(long double j); - - long int labs(long int j); - long long int llabs(long long int j); - - div_t div(int numer, int denom); - ldiv_t div(long int numer, long int denom); // see \ref{library.c} - lldiv_t div(long long int numer, long long int denom); // see \ref{library.c} - ldiv_t ldiv(long int numer, long int denom); - lldiv_t lldiv(long long int numer, long long int denom); + constexpr int abs(int j); + constexpr long int abs(long int j); + constexpr long long int abs(long long int j); + constexpr float abs(float j); + constexpr double abs(double j); + constexpr long double abs(long double j); + + constexpr long int labs(long int j); + constexpr long long int llabs(long long int j); + + constexpr div_t div(int numer, int denom); + constexpr ldiv_t div(long int numer, long int denom); // see \ref{library.c} + constexpr lldiv_t div(long long int numer, long long int denom); // see \ref{library.c} + constexpr ldiv_t ldiv(long int numer, long int denom); + constexpr lldiv_t lldiv(long long int numer, long long int denom); } \end{codeblock} @@ -589,6 +589,7 @@ #define @\defnlibxname{cpp_lib_complex_udls}@ 201309L // also in \libheader{complex} #define @\defnlibxname{cpp_lib_concepts}@ 202002L // also in \libheader{concepts} #define @\defnlibxname{cpp_lib_constexpr_algorithms}@ 201806L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_constexpr_cmath}@ 202202L // also in \libheader{cmath}, \libheader{cstdlib} #define @\defnlibxname{cpp_lib_constexpr_complex}@ 201711L // also in \libheader{complex} #define @\defnlibxname{cpp_lib_constexpr_dynamic_alloc}@ 201907L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_constexpr_functional}@ 201907L // also in \libheader{functional} From 82ebf568da1295a6676acff4505160133694554d Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 9 Feb 2022 17:25:32 +0100 Subject: [PATCH 110/182] P0627R6 Function to mark unreachable code --- source/support.tex | 1 + source/utilities.tex | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/source/support.tex b/source/support.tex index cbd48c58be..a25fd74be2 100644 --- a/source/support.tex +++ b/source/support.tex @@ -707,6 +707,7 @@ #define @\defnlibxname{cpp_lib_type_trait_variable_templates}@ 201510L // also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_uncaught_exceptions}@ 201411L // also in \libheader{exception} #define @\defnlibxname{cpp_lib_unordered_map_try_emplace}@ 201411L // also in \libheader{unordered_map} +#define @\defnlibxname{cpp_lib_unreachable}@ 202202L // also in \libheader{utility} #define @\defnlibxname{cpp_lib_unwrap_ref}@ 201811L // also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_variant}@ 202106L // also in \libheader{variant} #define @\defnlibxname{cpp_lib_void_t}@ 201411L // also in \libheader{type_traits} diff --git a/source/utilities.tex b/source/utilities.tex index 981ddd26c9..12451a592a 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -99,6 +99,9 @@ template constexpr underlying_type_t to_underlying(T value) noexcept; + // \ref{utility.unreachable}, unreachable + [[noreturn]] void unreachable(); + // \ref{intseq}, compile-time integer sequences% \indexlibraryglobal{index_sequence}% \indexlibraryglobal{make_index_sequence}% @@ -611,6 +614,39 @@ \tcode{static_cast>(value)}. \end{itemdescr} +\rSec2[utility.unreachable]{Function \tcode{unreachable}} + +\indexlibraryglobal{unreachable}% +\begin{itemdecl} +[[noreturn]] void unreachable(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{false} is \tcode{true}. +\begin{note} +This precondition cannot be satisfied, thus the behavior +of calling \tcode{unreachable} is undefined. +\end{note} + +\pnum +\begin{example} +\begin{codeblock} +int f(int x) { + switch (x) { + case 0: + case 1: + return x; + default: + std::unreachable(); + } +} +int a = f(1); // OK, \tcode{a} has value \tcode{1} +int b = f(3); // undefined behavior +\end{codeblock} +\end{example} +\end{itemdescr} \rSec1[intseq]{Compile-time integer sequences} From 6d4a94f35cb9e567c0c1acab3483dbfeb74693d2 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 9 Feb 2022 17:55:57 +0100 Subject: [PATCH 111/182] P1206R7 Conversions from ranges to containers - Fix misnamed constructor in [multiset.cons] - Fix garbled constructor in [stack.defn] - Fix bad pack expansion "std::forward(args)..." --- source/containers.tex | 1127 ++++++++++++++++++++++++++++++++++++++++- source/ranges.tex | 228 +++++++++ source/strings.tex | 90 ++++ source/support.tex | 4 + 4 files changed, 1424 insertions(+), 25 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index 72b49c7066..4641fdbdbf 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -945,6 +945,14 @@ but specialized allocators can choose a different definition. \end{note} +\pnum +The following exposition-only concept is used in the definition of containers: +\begin{codeblock} +template +concept @\defexposconcept{container-compatible-range}@ = // \expos + ranges::@\libconcept{input_range}@ && @\libconcept{convertible_to}@, T>; +\end{codeblock} + \pnum In this subclause, \begin{itemize} @@ -1270,6 +1278,9 @@ \item \tcode{[i, j)} denotes a valid range, \item +\tcode{rg} denotes a value of a type \tcode{R} +that models \tcode{\exposconcept{container-compatible-range}}, +\item \tcode{il} designates an object of type \tcode{initializer_list}, \item \tcode{n} denotes a value of type \tcode{X::size_type}, @@ -1348,6 +1359,30 @@ \tcode{distance(u.begin(), u.end()) == distance(i, j)} is \tcode{true}. \end{itemdescr} +\begin{itemdecl} +X(from_range, rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +For \tcode{vector}, +if \tcode{R} models +neither \libconcept{sized_range} nor \libconcept{forward_range}, +\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}. + +\pnum +\effects +Constructs a sequence container equal to the range \tcode{rg}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. + +\pnum +\ensures +\tcode{distance(begin(), end()) == ranges::distance(rg)} is \tcode{true}. +\end{itemdescr} + \begin{itemdecl} X(il) \end{itemdecl} @@ -1520,6 +1555,40 @@ \tcode{p} if \tcode{i == j}. \end{itemdescr} +\indexcont{insert_range}% +\begin{itemdecl} +a.insert_range(p, rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +For \tcode{vector} and \tcode{deque}, +\tcode{T} is also +\oldconcept{MoveInsertable} into \tcode{X}, +\oldconcept{MoveConstructible}, +\oldconcept{MoveAssignable}, and +swappable\iref{swappable.requirements}. +\tcode{rg} and \tcode{a} do not overlap. + +\pnum +\effects +Inserts copies of elements in \tcode{rg} before \tcode{p}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. + +\pnum +\returns +An iterator +that points to the copy of the first element inserted into \tcode{a}, or +\tcode{p} if \tcode{rg} is empty. +\end{itemdescr} + \begin{itemdecl} a.insert(p, il) \end{itemdecl} @@ -1633,7 +1702,42 @@ referring to the elements of \tcode{a}. For \tcode{vector} and \tcode{deque}, also invalidates the past-the-end iterator. -Each iterator in the range \range{i}{j} shall be dereferenced exactly once. +Each iterator in the range \range{i}{j} is dereferenced exactly once. +\end{itemdescr} + +\indexcont{assign_range}% +\begin{itemdecl} +a.assign_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\mandates +\tcode{\libconcept{assignable_from}>} +is modeled. + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +For \tcode{vector}, +if \tcode{R} models +neither \libconcept{sized_range} nor \libconcept{forward_range}, +\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}. +\tcode{rg} and \tcode{a} do not overlap. + +\pnum +\effects +Replaces elements in \tcode{a} with a copy of each element in \tcode{rg}. +Invalidates all references, pointers, and iterators +referring to the elements of \tcode{a}. +For \tcode{vector} and \tcode{deque}, +also invalidates the past-the-end iterator. +Each iterator in the range \tcode{rg} is dereferenced exactly once. \end{itemdescr} \begin{itemdecl} @@ -1876,6 +1980,36 @@ \tcode{list}. \end{itemdescr} +\begin{itemdecl} +a.prepend_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Inserts copies of elements in \tcode{rg} before \tcode{begin()}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. +\begin{note} +The order of elements in \tcode{rg} is not reversed. +\end{note} + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{forward_list}, and +\tcode{list}. +\end{itemdescr} + \begin{itemdecl} a.push_back(t) \end{itemdecl} @@ -1928,6 +2062,36 @@ \tcode{vector}. \end{itemdescr} +\begin{itemdecl} +a.append_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +For \tcode{vector}, +\tcode{T} is also +\oldconcept{MoveInsertable} into \tcode{X}. + +\pnum +\effects +Inserts copies of elements in \tcode{rg} before \tcode{end()}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + \begin{itemdecl} a.pop_front() \end{itemdecl} @@ -2460,6 +2624,9 @@ \item \range{i}{j} denotes a valid range, \item +\tcode{rg} denotes a value of a type \tcode{R} +that models \tcode{\exposconcept{container-compatible-range}}, +\item \tcode{p} denotes a valid constant iterator to \tcode{a}, \item \tcode{q} denotes a valid dereferenceable constant iterator to \tcode{a}, @@ -2713,6 +2880,59 @@ linear if \range{i}{j} is sorted with \tcode{value_comp()}. \end{itemdescr} +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(from_range, rg, c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*range::begin(rg)}. + +\pnum +\effects +Constructs an empty container and +inserts each element from \tcode{rg} into it. +Uses \tcode{c} as the comparison object. + +\pnum +\complexity +$N \log N$ in general, where $N$ has the value \tcode{ranges::distance(rg)}; +linear if \tcode{rg} is sorted with \tcode{value_comp()}. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(from_range, rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container and +inserts each element from \tcode{rg} into it. +Uses \tcode{Compare()} as the comparison object. + +\pnum +\complexity +Same as \tcode{X(from_range, rg, c)}. +\end{itemdescr} + \indexlibraryctor{set}% \indexlibraryctor{map}% \indexlibraryctor{multiset}% @@ -3019,6 +3239,36 @@ $N \log (\tcode{a.size()} + N)$, where $N$ has the value \tcode{distance(i, j)}. \end{itemdescr} +\indexordmem{insert}% +\begin{itemdecl} +a.insert_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +\tcode{rg} and \tcode{a} do not overlap. + +\pnum +\effects +Inserts each element from \tcode{rg} if and only if +there is no element with key equivalent to the key of that element +in containers with unique keys; +always inserts that element in containers with equivalent keys. + +\pnum +\complexity +$N \log (\tcode{a.size()} + N)$, +where $N$ has the value \tcode{ranges::distance(rg)}. +\end{itemdescr} + \indexordmem{insert}% \begin{itemdecl} a.insert(il) @@ -3625,7 +3875,8 @@ \end{itemdescr} \pnum -The \tcode{insert} and \tcode{emplace} members shall not affect the validity of +The \tcode{insert}, \tcode{insert_range}, and \tcode{emplace} members +shall not affect the validity of iterators and references to the container, and the \tcode{erase} members shall invalidate only iterators and references to the erased elements. @@ -3867,6 +4118,9 @@ \item \tcode{[i, j)} denotes a valid range, \item +\tcode{rg} denotes a value of a type \tcode{R} +that models \tcode{\exposconcept{container-compatible-range}}, +\item \tcode{p} and \tcode{q2} denote valid constant iterators to \tcode{a}, \item \tcode{q} and \tcode{q1} denote @@ -4237,6 +4491,107 @@ Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}. \end{itemdescr} +\begin{itemdecl} +X(from_range, rg, n, hf, eq) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{eq} as the key equality predicate, and +inserts elements from \tcode{rg} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}), +worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(from_range, rg, n, hf) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{\-EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \tcode{rg} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}), +worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(from_range, rg, n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{hasher} and \tcode{key_equal} meet +the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \tcode{rg} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}), +worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(from_range, rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{hasher} and \tcode{key_equal} meet +the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container with an unspecified number of buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \tcode{rg} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}), +worst case \bigoh{N^2}. +\end{itemdescr} + \begin{itemdecl} X(il) \end{itemdecl} @@ -4588,6 +4943,33 @@ worst case \bigoh{N(\tcode{a.size()} + 1)}. \end{itemdescr} +\indexunordmem{insert_range}% +\begin{itemdecl} +a.insert_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +\tcode{rg} and \tcode{a} do not overlap. + +\pnum +\effects +Equivalent to \tcode{a.insert(t)} for each element \tcode{t} in \tcode{rg}. + +\pnum +\complexity +Average case \bigoh{N}, where $N$ is \tcode{ranges::distance(rg)}, +worst case \bigoh{N(\tcode{a.size()} + 1)}. +\end{itemdescr} + \indexunordmem{insert}% \begin{itemdecl} a.insert(il) @@ -5410,7 +5792,8 @@ \pnum \indextext{unordered associative containers!iterator invalidation}% -The \tcode{insert} and \tcode{emplace} members shall not affect the validity of references to +The \tcode{insert}, \tcode{insert_range}, and \tcode{emplace} members +shall not affect the validity of references to container elements, but may invalidate all iterators to the container. The \tcode{erase} members shall invalidate only iterators and references to the erased elements, and preserve the relative order of the @@ -5419,7 +5802,8 @@ \pnum \indextext{unordered associative containers!iterator invalidation}% \indextext{unordered associative containers!requirements}% -The \tcode{insert} and \tcode{emplace} members shall not affect the validity of iterators if +The \tcode{insert}, \tcode{insert_range}, and \tcode{emplace} members +shall not affect the validity of iterators if \tcode{(N+n) <= z * B}, where \tcode{N} is the number of elements in the container prior to the insert operation, \tcode{n} is the number of elements inserted, \tcode{B} is the container's bucket count, and @@ -6083,6 +6467,8 @@ deque(size_type n, const T& value, const Allocator& = Allocator()); template deque(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + deque(from_range_t, R&& rg, const Allocator& = Allocator()); deque(const deque& x); deque(deque&&); deque(const deque&, const type_identity_t&); @@ -6096,6 +6482,8 @@ deque& operator=(initializer_list); template void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void assign_range(R&& rg); void assign(size_type n, const T& t); void assign(initializer_list); allocator_type get_allocator() const noexcept; @@ -6140,14 +6528,20 @@ void push_front(const T& x); void push_front(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void push_back(const T& x); void push_back(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void append_range(R&& rg); iterator insert(const_iterator position, const T& x); iterator insert(const_iterator position, T&& x); iterator insert(const_iterator position, size_type n, const T& x); template iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list); void pop_front(); @@ -6163,6 +6557,10 @@ template>> deque(InputIterator, InputIterator, Allocator = Allocator()) -> deque<@\placeholder{iter-value-type}@, Allocator>; + + template>> + deque(from_range_t, R&&, Allocator = Allocator()) + -> deque, Allocator>; } \end{codeblock} @@ -6247,6 +6645,23 @@ Linear in \tcode{distance(first, last)}. \end{itemdescr} +\indexlibraryctor{deque}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + deque(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{deque} with the elements of the range \tcode{rg}, +using the specified allocator. + +\pnum +\complexity +Linear in \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[deque.capacity]{Capacity} \indexlibrarymember{resize}{deque}% @@ -6333,6 +6748,8 @@ template iterator insert(const_iterator position, InputIterator first, InputIterator last); +template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list); template reference emplace_front(Args&&... args); @@ -6340,8 +6757,12 @@ template iterator emplace(const_iterator position, Args&&... args); void push_front(const T& x); void push_front(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void push_back(const T& x); void push_back(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + void append_range(R&& rg); \end{itemdecl} \begin{itemdescr} @@ -6509,6 +6930,8 @@ forward_list(size_type n, const T& value, const Allocator& = Allocator()); template forward_list(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); forward_list(const forward_list& x); forward_list(forward_list&& x); forward_list(const forward_list& x, const type_identity_t&); @@ -6521,6 +6944,8 @@ forward_list& operator=(initializer_list); template void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void assign_range(R&& rg); void assign(size_type n, const T& t); void assign(initializer_list); allocator_type get_allocator() const noexcept; @@ -6549,6 +6974,8 @@ template reference emplace_front(Args&&... args); void push_front(const T& x); void push_front(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void pop_front(); template iterator emplace_after(const_iterator position, Args&&... args); @@ -6559,6 +6986,8 @@ template iterator insert_after(const_iterator position, InputIterator first, InputIterator last); iterator insert_after(const_iterator position, initializer_list il); + template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range_after(const_iterator position, R&& rg); iterator erase_after(const_iterator position); iterator erase_after(const_iterator position, const_iterator last); @@ -6599,6 +7028,10 @@ template>> forward_list(InputIterator, InputIterator, Allocator = Allocator()) -> forward_list<@\placeholder{iter-value-type}@, Allocator>; + + template>> + forward_list(from_range_t, R&&, Allocator = Allocator()) + -> forward_list, Allocator>; } \end{codeblock} @@ -6681,6 +7114,23 @@ Linear in \tcode{distance(first, last)}. \end{itemdescr} +\indexlibraryctor{forward_list}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{forward_list} object +with the elements of the range \tcode{rg}. + +\pnum +\complexity +Linear in \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[forward.list.iter]{Iterators} \indexlibrarymember{before_begin}{forward_list}% @@ -6757,6 +7207,20 @@ Inserts a copy of \tcode{x} at the beginning of the list. \end{itemdescr} +\indexlibrarymember{prepend_range}{forward_list}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Inserts a copy of each element of \tcode{rg} at the beginning of the list. +\begin{note} +The order of elements is not reversed. +\end{note} +\end{itemdescr} \indexlibrarymember{pop}{forward_list}% \begin{itemdecl} @@ -6812,24 +7276,47 @@ \indexlibrarymember{insert_after}{forward_list}% \begin{itemdecl} -template - iterator insert_after(const_iterator position, InputIterator first, InputIterator last); +template + iterator insert_after(const_iterator position, InputIterator first, InputIterator last); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{position} is \tcode{before_begin()} or is a dereferenceable +iterator in the range \range{begin()}{end()}. +Neither \tcode{first} nor \tcode{last} are iterators in \tcode{*this}. + +\pnum +\effects +Inserts copies of elements in \range{first}{last} after \tcode{position}. + +\pnum +\returns +An iterator pointing to the last inserted element or \tcode{position} if \tcode{first == last}. +\end{itemdescr} + +\indexlibrarymember{insert_range_after}{forward_list}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range_after(const_iterator position, R&& rg); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{position} is \tcode{before_begin()} or is a dereferenceable -iterator in the range \range{begin()}{end()}. -Neither \tcode{first} nor \tcode{last} are iterators in \tcode{*this}. +\tcode{position} is \tcode{before_begin()} or +is a dereferenceable iterator in the range \range{begin()}{end()}. +\tcode{rg} and \tcode{*this} do not overlap. \pnum \effects -Inserts copies of elements in \range{first}{last} after \tcode{position}. +Inserts copies of elements in the range \tcode{rg} after \tcode{position}. \pnum \returns -An iterator pointing to the last inserted element or \tcode{position} if \tcode{first == last}. +An iterator pointing to the last inserted element, +or \tcode{position} if \tcode{rg} is empty. \end{itemdescr} \indexlibrarymember{insert_after}{forward_list}% @@ -7321,6 +7808,8 @@ list(size_type n, const T& value, const Allocator& = Allocator()); template list(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + list(from_range_t, R&& rg, const Allocator& = Allocator()); list(const list& x); list(list&& x); list(const list&, const type_identity_t&); @@ -7333,6 +7822,8 @@ list& operator=(initializer_list); template void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void assign_range(R&& rg); void assign(size_type n, const T& t); void assign(initializer_list); allocator_type get_allocator() const noexcept; @@ -7370,9 +7861,13 @@ template reference emplace_back(Args&&... args); void push_front(const T& x); void push_front(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void pop_front(); void push_back(const T& x); void push_back(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void append_range(R&& rg); void pop_back(); template iterator emplace(const_iterator position, Args&&... args); @@ -7381,6 +7876,8 @@ iterator insert(const_iterator position, size_type n, const T& x); template iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list il); iterator erase(const_iterator position); @@ -7417,6 +7914,10 @@ template>> list(InputIterator, InputIterator, Allocator = Allocator()) -> list<@\placeholder{iter-value-type}@, Allocator>; + + template>> + list(from_range_t, R&&, Allocator = Allocator()) + -> list, Allocator>; } \end{codeblock} @@ -7511,6 +8012,22 @@ \tcode{distance(first, last)}. \end{itemdescr} +\indexlibraryctor{list}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + list(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{list} object with the elements of the range \tcode{rg}. + +\pnum +\complexity +Linear in \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[list.capacity]{Capacity} \indexlibrarymember{resize}{list}% @@ -7573,6 +8090,8 @@ template iterator insert(const_iterator position, InputIterator first, InputIterator last); +template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list); template reference emplace_front(Args&&... args); @@ -7580,8 +8099,12 @@ template iterator emplace(const_iterator position, Args&&... args); void push_front(const T& x); void push_front(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void push_back(const T& x); void push_back(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + void append_range(R&& rg); \end{itemdecl} \begin{itemdescr} @@ -7994,7 +8517,7 @@ and, for an element type other than \tcode{bool}, of a contiguous container\iref{container.requirements.general}. The exceptions are the -\tcode{push_front}, \tcode{pop_front}, and \tcode{emplace_front} member functions, which are not +\tcode{push_front}, \tcode{prepend_range}, \tcode{pop_front}, and \tcode{emplace_front} member functions, which are not provided. Descriptions are provided here only for operations on \tcode{vector} that are not described in one of these tables or for operations where there is additional semantic information. @@ -8029,6 +8552,8 @@ constexpr vector(size_type n, const T& value, const Allocator& = Allocator()); template constexpr vector(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); constexpr vector(const vector& x); constexpr vector(vector&&) noexcept; constexpr vector(const vector&, const type_identity_t&); @@ -8042,6 +8567,8 @@ constexpr vector& operator=(initializer_list); template constexpr void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void assign_range(R&& rg); constexpr void assign(size_type n, const T& u); constexpr void assign(initializer_list); constexpr allocator_type get_allocator() const noexcept; @@ -8089,6 +8616,8 @@ template constexpr reference emplace_back(Args&&... args); constexpr void push_back(const T& x); constexpr void push_back(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void append_range(R&& rg); constexpr void pop_back(); template constexpr iterator emplace(const_iterator position, Args&&... args); @@ -8098,6 +8627,8 @@ template constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator position, R&& rg); constexpr iterator insert(const_iterator position, initializer_list il); constexpr iterator erase(const_iterator position); constexpr iterator erase(const_iterator first, const_iterator last); @@ -8110,6 +8641,10 @@ template>> vector(InputIterator, InputIterator, Allocator = Allocator()) -> vector<@\placeholder{iter-value-type}@, Allocator>; + + template>> + vector(from_range_t, R&&, Allocator = Allocator()) + -> vector, Allocator>; } \end{codeblock}% \indexlibrarymember{vector}{operator==}% @@ -8190,7 +8725,6 @@ \end{itemdecl} \begin{itemdescr} - \pnum \effects Constructs a \tcode{vector} equal to the @@ -8216,6 +8750,29 @@ reallocations if they are just input iterators. \end{itemdescr} +\indexlibraryctor{vector}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{vector} object with the elements of the range \tcode{rg}, +using the specified allocator. + +\pnum +\complexity +Initializes exactly $N$ elements +from the results of dereferencing successive iterators of \tcode{rg}, +where $N$ is \tcode{ranges::distance(rg)}. +Performs no reallocations if \tcode{R} models +\tcode{ranges::\libconcept{forward_range}} or \tcode{ranges::\libconcept{sized_range}}; +otherwise, performs order $\log N$ reallocations and +order $N$ calls to the copy or move constructor of \tcode{T}. +\end{itemdescr} + \rSec3[vector.capacity]{Capacity} \indexlibrarymember{capacity}{vector}% @@ -8421,12 +8978,16 @@ constexpr iterator insert(const_iterator position, size_type n, const T& x); template constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); +template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator position, R&& rg); constexpr iterator insert(const_iterator position, initializer_list); template constexpr reference emplace_back(Args&&... args); template constexpr iterator emplace(const_iterator position, Args&&... args); constexpr void push_back(const T& x); constexpr void push_back(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + constexpr void append_range(R&& rg); \end{itemdecl} \begin{itemdescr} @@ -8574,6 +9135,8 @@ constexpr vector(size_type n, const bool& value, const Allocator& = Allocator()); template constexpr vector(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); constexpr vector(const vector& x); constexpr vector(vector&& x); constexpr vector(const vector&, const type_identity_t&); @@ -8585,6 +9148,8 @@ constexpr vector& operator=(initializer_list); template constexpr void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void assign_range(R&& rg); constexpr void assign(size_type n, const bool& t); constexpr void assign(initializer_list); constexpr allocator_type get_allocator() const noexcept; @@ -8626,6 +9191,8 @@ // modifiers template constexpr reference emplace_back(Args&&... args); constexpr void push_back(const bool& x); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void append_range(R&& rg); constexpr void pop_back(); template constexpr iterator emplace(const_iterator position, Args&&... args); constexpr iterator insert(const_iterator position, const bool& x); @@ -8633,6 +9200,8 @@ template constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator position, R&& rg); constexpr iterator insert(const_iterator position, initializer_list il); constexpr iterator erase(const_iterator position); @@ -8729,6 +9298,15 @@ using @\placeholder{iter-to-alloc-type}@ = pair< add_const_t::value_type::first_type>, typename iterator_traits::value_type::second_type>; // \expos +template + using @\exposid{range-key-type}@ = + remove_const_t::first_type>; // \expos +template + using @\exposid{range-mapped-type}@ = typename ranges::range_value_t::second_type; // \expos +template + using @\exposid{range-to-alloc-type}@ = + pair::first_type>, + typename ranges::range_value_t::second_type>; // \expos \end{codeblock} \rSec2[associative.map.syn]{Header \tcode{} synopsis} @@ -8941,6 +9519,8 @@ template map(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); map(const map& x); map(map&& x); explicit map(const Allocator&); @@ -8952,6 +9532,9 @@ template map(InputIterator first, InputIterator last, const Allocator& a) : map(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + map(from_range_t, R&& rg, const Allocator& a)) + : map(from_range, std::forward(rg), Compare(), a) { } map(initializer_list il, const Allocator& a) : map(il, Compare(), a) { } ~map(); @@ -9001,6 +9584,8 @@ iterator insert(const_iterator position, P&&); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -9084,6 +9669,11 @@ map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) -> map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Compare, Allocator>; + template, + class Allocator = allocator<@\exposid{range-to-alloc-type}@>> + map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Compare, Allocator>; + template, class Allocator = allocator>> map(initializer_list>, Compare = Compare(), Allocator = Allocator()) @@ -9094,6 +9684,10 @@ -> map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, less<@\placeholder{iter-key-type}@>, Allocator>; + template + map(from_range_t, R&&, Allocator) + -> map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, less<@\exposid{range-key-type}@>, Allocator>; + template map(initializer_list>, Allocator) -> map, Allocator>; } @@ -9146,6 +9740,25 @@ is \tcode{last - first}. \end{itemdescr} +\indexlibraryctor{map}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{map} +using the specified comparison object and allocator, +and inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted using \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[map.access]{Element access} \indexlibrary{\idxcode{operator[]}!\idxcode{map}}% @@ -9489,6 +10102,9 @@ multimap(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + multimap(from_range_t, R&& rg, + const Compare& comp = Compare(), const Allocator& = Allocator()); multimap(const multimap& x); multimap(multimap&& x); explicit multimap(const Allocator&); @@ -9500,6 +10116,9 @@ template multimap(InputIterator first, InputIterator last, const Allocator& a) : multimap(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + multimap(from_range_t, R&& rg, const Allocator& a)) + : multimap(from_range, std::forward(rg), Compare(), a) { } multimap(initializer_list il, const Allocator& a) : multimap(il, Compare(), a) { } ~multimap(); @@ -9542,6 +10161,8 @@ template iterator insert(const_iterator position, P&& x); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -9609,6 +10230,11 @@ -> multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Compare, Allocator>; + template>, + class Allocator = allocator<@\exposid{range-to-alloc-type}@>> + multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Compare, Allocator>; + template, class Allocator = allocator>> multimap(initializer_list>, Compare = Compare(), Allocator = Allocator()) @@ -9619,6 +10245,10 @@ -> multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, less<@\placeholder{iter-key-type}@>, Allocator>; + template + multimap(from_range_t, R&&, Allocator) + -> multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, less<@\exposid{range-key-type}@>, Allocator>; + template multimap(initializer_list>, Allocator) -> multimap, Allocator>; @@ -9673,6 +10303,25 @@ \tcode{last - first}. \end{itemdescr} +\indexlibraryctor{multimap}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + multimap(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{multimap} +using the specified comparison object and allocator, and +inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted using \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[multimap.modifiers]{Modifiers} \indexlibrarymember{insert}{multimap}% @@ -9795,6 +10444,8 @@ template set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); set(const set& x); set(set&& x); explicit set(const Allocator&); @@ -9805,6 +10456,9 @@ template set(InputIterator first, InputIterator last, const Allocator& a) : set(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + set(from_range_t, R&& rg, const Allocator& a)) + : set(from_range, std::forward(rg), Compare(), a) { } set(initializer_list il, const Allocator& a) : set(il, Compare(), a) { } ~set(); @@ -9845,6 +10499,8 @@ iterator insert(const_iterator position, value_type&& x); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -9913,6 +10569,11 @@ Compare = Compare(), Allocator = Allocator()) -> set<@\placeholder{iter-value-type}@, Compare, Allocator>; + template>, + class Allocator = allocator>> + set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> set, Compare, Allocator>; + template, class Allocator = allocator> set(initializer_list, Compare = Compare(), Allocator = Allocator()) -> set; @@ -9922,6 +10583,10 @@ -> set<@\placeholder{iter-value-type}@, less<@\placeholder{iter-value-type}@>, Allocator>; + template + set(from_range_t, R&&, Allocator) + -> set, less>, Allocator>; + template set(initializer_list, Allocator) -> set, Allocator>; } @@ -9972,6 +10637,24 @@ \tcode{last - first}. \end{itemdescr} +\indexlibraryctor{set}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{set} using the specified comparison object and allocator, +and inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted using \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[set.erasure]{Erasure} \indexlibrarymember{erase_if}{set}% @@ -10072,6 +10755,9 @@ template multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + multiset(from_range_t, R&& rg, + const Compare& comp = Compare(), const Allocator& = Allocator()); multiset(const multiset& x); multiset(multiset&& x); explicit multiset(const Allocator&); @@ -10082,6 +10768,9 @@ template multiset(InputIterator first, InputIterator last, const Allocator& a) : multiset(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + multiset(from_range_t, R&& rg, const Allocator& a)) + : multiset(from_range, std::forward(rg), Compare(), a) { } multiset(initializer_list il, const Allocator& a) : multiset(il, Compare(), a) { } ~multiset(); @@ -10122,6 +10811,8 @@ iterator insert(const_iterator position, value_type&& x); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -10190,6 +10881,11 @@ Compare = Compare(), Allocator = Allocator()) -> multiset<@\placeholder{iter-value-type}@, Compare, Allocator>; + template>, + class Allocator = allocator>> + multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> multiset, Compare, Allocator>; + template, class Allocator = allocator> multiset(initializer_list, Compare = Compare(), Allocator = Allocator()) -> multiset; @@ -10199,6 +10895,10 @@ -> multiset<@\placeholder{iter-value-type}@, less<@\placeholder{iter-value-type}@>, Allocator>; + template + multiset(from_range_t, R&&, Allocator) + -> multiset, less>, Allocator>; + template multiset(initializer_list, Allocator) -> multiset, Allocator>; } @@ -10249,6 +10949,25 @@ \tcode{last - first}. \end{itemdescr} +\indexlibraryctor{multiset}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + multiset(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{multiset} +using the specified comparison object and allocator, and +inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted using \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[multiset.erasure]{Erasure} \indexlibrarymember{erase_if}{multiset}% @@ -10499,6 +11218,11 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + + template<@\exposconcept{container-compatible-range}@ R> + unordered_map(from_range_t, R&& rg, size_type n = @\seebelow@, + const hasher& hf = hasher(), const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_map(const unordered_map&); unordered_map(unordered_map&&); explicit unordered_map(const Allocator&); @@ -10520,6 +11244,12 @@ unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_map(f, l, n, hf, key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_map(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_map(from_range, std::forward(rg), n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_map(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) + : unordered_map(from_range, std::forward(rg), n, hf, key_equal(), a) { } unordered_map(initializer_list il, size_type n, const allocator_type& a) : unordered_map(il, n, hasher(), key_equal(), a) { } unordered_map(initializer_list il, size_type n, const hasher& hf, @@ -10557,6 +11287,8 @@ iterator insert(const_iterator hint, value_type&& obj); template iterator insert(const_iterator hint, P&& obj); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -10662,6 +11394,13 @@ -> unordered_map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, Pred, Allocator>; + template>, + class Pred = equal_to<@\exposid{range-key-type}@>, + class Allocator = allocator<@\exposid{range-to-alloc-type}@>> + unordered_map(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Hash, Pred, Allocator>; + template, class Pred = equal_to, class Allocator = allocator>> unordered_map(initializer_list>, @@ -10686,6 +11425,21 @@ -> unordered_map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, equal_to<@\placeholder{iter-key-type}@>, Allocator>; + template + unordered_map(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, hash<@\exposid{range-key-type}@>, + equal_to<@\exposid{range-key-type}@>, Allocator>; + + template + unordered_map(from_range_t, R&&, Allocator) + -> unordered_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, hash<@\exposid{range-key-type}@>, + equal_to<@\exposid{range-key-type}@>, Allocator>; + + template + unordered_map(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Hash, + equal_to<@\exposid{range-key-type}@>, Allocator>; + template unordered_map(initializer_list>, typename @\seebelow@::size_type, Allocator) @@ -10740,6 +11494,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + unordered_map(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_map(initializer_list il, size_type n = @\seebelow@, const hasher& hf = hasher(), @@ -10755,9 +11515,8 @@ using at least \tcode{n} buckets. If \tcode{n} is not provided, the number of buckets is \impldef{default number of buckets in \tcode{unordered_map}}. Then -inserts elements from the range \range{f}{l} -for the first form, or from the range -\range{il.begin()}{il.end()} for the second form. +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. \tcode{max_load_factor()} returns \tcode{1.0}. \pnum @@ -11098,6 +11857,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + template<@\exposconcept{container-compatible-range}@ R> + unordered_multimap(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_multimap(const unordered_multimap&); unordered_multimap(unordered_multimap&&); explicit unordered_multimap(const Allocator&); @@ -11119,6 +11884,14 @@ unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(f, l, n, hf, key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_multimap(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_multimap(from_range, std::forward(rg), + n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_multimap(from_range_t, R&& rg, size_type n, const hasher& hf, + const allocator_type& a) + : unordered_multimap(from_range, std::forward(rg), n, hf, key_equal(), a) { } unordered_multimap(initializer_list il, size_type n, const allocator_type& a) : unordered_multimap(il, n, hasher(), key_equal(), a) { } unordered_multimap(initializer_list il, size_type n, const hasher& hf, @@ -11156,6 +11929,8 @@ iterator insert(const_iterator hint, value_type&& obj); template iterator insert(const_iterator hint, P&& obj); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -11238,6 +12013,14 @@ -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, Pred, Allocator>; + template>, + class Pred = equal_to<@\exposid{range-key-type}@>, + class Allocator = allocator<@\exposid{range-to-alloc-type}@>> + unordered_multimap(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Hash, Pred, Allocator>; + template, class Pred = equal_to, class Allocator = allocator>> unordered_multimap(initializer_list>, @@ -11263,6 +12046,21 @@ -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, equal_to<@\placeholder{iter-key-type}@>, Allocator>; + template + unordered_multimap(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, hash<@\exposid{range-key-type}@>, + equal_to<@\exposid{range-key-type}@>, Allocator>; + + template + unordered_multimap(from_range_t, R&&, Allocator) + -> unordered_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, hash<@\exposid{range-key-type}@>, + equal_to<@\exposid{range-key-type}@>, Allocator>; + + template + unordered_multimap(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Hash, + equal_to<@\exposid{range-key-type}@>, Allocator>; + template unordered_multimap(initializer_list>, typename @\seebelow@::size_type, Allocator) @@ -11317,6 +12115,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + unordered_multimap(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_multimap(initializer_list il, size_type n = @\seebelow@, const hasher& hf = hasher(), @@ -11332,9 +12136,8 @@ using at least \tcode{n} buckets. If \tcode{n} is not provided, the number of buckets is \impldef{default number of buckets in \tcode{unordered_multimap}}. Then -inserts elements from the range \range{f}{l} -for the first form, or from the range -\range{il.begin()}{il.end()} for the second form. +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. \tcode{max_load_factor()} returns \tcode{1.0}. \pnum @@ -11471,6 +12274,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + template<@\exposconcept{container-compatible-range}@ R> + unordered_set(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_set(const unordered_set&); unordered_set(unordered_set&&); explicit unordered_set(const Allocator&); @@ -11494,6 +12303,12 @@ : unordered_set(f, l, n, hf, key_equal(), a) { } unordered_set(initializer_list il, size_type n, const allocator_type& a) : unordered_set(il, n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_set(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_set(from_range, std::forward(rg), n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_set(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) + : unordered_set(from_range, std::forward(rg), n, hf, key_equal(), a) { } unordered_set(initializer_list il, size_type n, const hasher& hf, const allocator_type& a) : unordered_set(il, n, hf, key_equal(), a) { } @@ -11527,6 +12342,8 @@ iterator insert(const_iterator hint, const value_type& obj); iterator insert(const_iterator hint, value_type&& obj); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -11608,6 +12425,14 @@ -> unordered_set<@\placeholder{iter-value-type}@, Hash, Pred, Allocator>; + template>, + class Pred = equal_to>, + class Allocator = allocator>> + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, +Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_set, Hash, Pred, Allocator>; + template, class Pred = equal_to, class Allocator = allocator> unordered_set(initializer_list, typename @\seebelow@::size_type = @\seebelow@, @@ -11628,6 +12453,21 @@ equal_to<@\placeholder{iter-value-type}@>, Allocator>; + template + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_set, hash>, + equal_to>, Allocator>; + + template + unordered_set(from_range_t, R&&, Allocator) + -> unordered_set, hash>, + equal_to>, Allocator>; + + template + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_set, Hash, + equal_to>, Allocator>; + template unordered_set(initializer_list, typename @\seebelow@::size_type, Allocator) -> unordered_set, equal_to, Allocator>; @@ -11677,6 +12517,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_set(initializer_list il, size_type n = @\seebelow@, const hasher& hf = hasher(), @@ -11692,9 +12538,8 @@ using at least \tcode{n} buckets. If \tcode{n} is not provided, the number of buckets is \impldef{default number of buckets in \tcode{unordered_set}}. Then -inserts elements from the range \range{f}{l} -for the first form, or from the range -\range{il.begin()}{il.end()} for the second form. +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. \tcode{max_load_factor()} returns \tcode{1.0}. \pnum @@ -11800,6 +12645,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_multiset(const unordered_multiset&); unordered_multiset(unordered_multiset&&); explicit unordered_multiset(const Allocator&); @@ -11821,6 +12672,14 @@ unordered_multiset(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_multiset(f, l, n, hf, key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_multiset(from_range, std::forward(rg), + n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, size_type n, const hasher& hf, + const allocator_type& a) + : unordered_multiset(from_range, std::forward(rg), n, hf, key_equal(), a) { } unordered_multiset(initializer_list il, size_type n, const allocator_type& a) : unordered_multiset(il, n, hasher(), key_equal(), a) { } unordered_multiset(initializer_list il, size_type n, const hasher& hf, @@ -11856,6 +12715,8 @@ iterator insert(const_iterator hint, const value_type& obj); iterator insert(const_iterator hint, value_type&& obj); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -11937,6 +12798,14 @@ -> unordered_multiset<@\placeholder{iter-value-type}@, Hash, Pred, Allocator>; + template>, + class Pred = equal_to>, + class Allocator = allocator>> + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multiset, Hash, Pred, Allocator>; + template, class Pred = equal_to, class Allocator = allocator> unordered_multiset(initializer_list, typename @\seebelow@::size_type = @\seebelow@, @@ -11957,6 +12826,21 @@ equal_to<@\placeholder{iter-value-type}@>, Allocator>; + template + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_multiset, hash>, + equal_to>, Allocator>; + + template + unordered_multiset(from_range_t, R&&, Allocator) + -> unordered_multiset, hash>, + equal_to>, Allocator>; + + template + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_multiset, Hash, equal_to>, + Allocator>; + template unordered_multiset(initializer_list, typename @\seebelow@::size_type, Allocator) -> unordered_multiset, equal_to, Allocator>; @@ -12006,6 +12890,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_multiset(initializer_list il, size_type n = @\seebelow@, const hasher& hf = hasher(), @@ -12021,9 +12911,8 @@ using at least \tcode{n} buckets. If \tcode{n} is not provided, the number of buckets is \impldef{default number of buckets in \tcode{unordered_multiset}}. Then -inserts elements from the range \range{f}{l} -for the first form, or from the range -\range{il.begin()}{il.end()} for the second form. +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. \tcode{max_load_factor()} returns \tcode{1.0}. \pnum @@ -12215,6 +13104,7 @@ explicit queue(const Container&); explicit queue(Container&&); template queue(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> queue(from_range_t, R&& rg); template explicit queue(const Alloc&); template queue(const Container&, const Alloc&); template queue(Container&&, const Alloc&); @@ -12222,6 +13112,8 @@ template queue(queue&&, const Alloc&); template queue(InputIterator first, InputIterator last, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + queue(from_range_t, R&& rg, const Alloc&); [[nodiscard]] bool empty() const { return c.empty(); } size_type size() const { return c.size(); } @@ -12231,6 +13123,7 @@ const_reference back() const { return c.back(); } void push(const value_type& x) { c.push_back(x); } void push(value_type&& x) { c.push_back(std::move(x)); } + template<@\exposconcept{container-compatible-range}@ R> void push_range(R&& rg); template decltype(auto) emplace(Args&&... args) { return c.emplace_back(std::forward(args)...); } @@ -12245,6 +13138,9 @@ template queue(InputIterator, InputIterator) -> queue<@\exposid{iter-value-type}@>; + template + queue(from_range_t, R&&) -> queue>; + template queue(Container, Allocator) -> queue; @@ -12253,6 +13149,10 @@ -> queue<@\exposid{iter-value-type}@, deque<@\exposid{iter-value-type}@, Allocator>>; + template + queue(from_range_t, R&&, Allocator) + -> queue, deque, Allocator>>; + template struct uses_allocator, Alloc> : uses_allocator::type { }; @@ -12296,6 +13196,18 @@ \tcode{first} as the first argument and \tcode{last} as the second argument. \end{itemdescr} +\indexlibraryctor{queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + queue(from_range_t, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{ranges::to(std::forward(rg))}. +\end{itemdescr} + \rSec3[queue.cons.alloc]{Constructors with allocators} \pnum @@ -12376,6 +13288,35 @@ \tcode{alloc} as the third argument. \end{itemdescr} +\indexlibraryctor{queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + queue(from_range_t, R&& rg, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with +\tcode{ranges::to(std::forward(rg), a)}. +\end{itemdescr} + +\rSec3[queue.mod]{Modifiers} + +\indexlibrarymember{push_range}{queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{c.append_range(std::forward(rg))} +if that is a valid expression, +otherwise \tcode{ranges::copy(rg, back_inserter(c))}. +\end{itemdescr} + \rSec3[queue.ops]{Operators} \indexlibrarymember{operator==}{queue}% @@ -12536,6 +13477,8 @@ template priority_queue(InputIterator first, InputIterator last, const Compare& x, Container&&); + template<@\exposconcept{container-compatible-range}@ R> + priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); template explicit priority_queue(const Alloc&); template priority_queue(const Compare&, const Alloc&); template priority_queue(const Compare&, const Container&, const Alloc&); @@ -12551,12 +13494,18 @@ const Alloc&); template priority_queue(InputIterator, InputIterator, const Compare&, Container&&, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + priority_queue(from_range_t, R&& rg, const Compare&, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + priority_queue(from_range_t, R&& rg, const Alloc&); [[nodiscard]] bool empty() const { return c.empty(); } size_type size() const { return c.size(); } const_reference top() const { return c.front(); } void push(const value_type& x); void push(value_type&& x); + template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); template void emplace(Args&&... args); void pop(); void swap(priority_queue& q) noexcept(is_nothrow_swappable_v && @@ -12574,6 +13523,10 @@ priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) -> priority_queue<@\exposid{iter-value-type}@, Container, Compare>; + template> + priority_queue(from_range_t, R&&, Compare = Compare()) + -> priority_queue, vector>, Compare>; + template priority_queue(Compare, Container, Allocator) -> priority_queue; @@ -12593,6 +13546,15 @@ priority_queue(InputIterator, InputIterator, Compare, Container, Allocator) -> priority_queue; + template + priority_queue(from_range_t, R&&, Compare, Allocator) + -> priority_queue, vector, Allocator>, + Compare>; + + template + priority_queue(from_range_t, R&&, Allocator) + -> priority_queue, vector, Allocator>>; + // no equality is provided template @@ -12671,6 +13633,24 @@ \tcode{make_heap(c.begin(), c.end(), comp)}. \end{itemdescr} +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x} defines a strict weak ordering\iref{alg.sorting}. + +\pnum +\effects +Initializes \tcode{comp} with \tcode{x} and +\tcode{c} with \tcode{ranges::to(std::forward(rg))} and +finally calls \tcode{make_heap(c.begin(), c.end(), comp)}. +\end{itemdescr} + \rSec3[priqueue.cons.alloc]{Constructors with allocators} \pnum @@ -12820,6 +13800,34 @@ finally calls \tcode{make_heap(c.begin(), c.end(), comp)}. \end{itemdescr} +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + priority_queue(from_range_t, R&& rg, const Compare& compare, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{comp} with \tcode{compare} and +\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}; +calls \tcode{make_heap(c.begin(), c.end(), comp)}. +\end{itemdescr} + +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + priority_queue(from_range_t, R&& rg, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes +\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}; +calls \tcode{make_heap(c.\linebreak begin(), c.end(), comp)}. +\end{itemdescr} + \rSec3[priqueue.members]{Members} \indexlibrarymember{push}{priority_queue}% @@ -12852,6 +13860,22 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{push_range}{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Insert all elements of \tcode{rg} in \tcode{c}. + +\pnum +\ensures +\tcode{is_heap(c.begin(), c.end(), comp)} is \tcode{true}. +\end{itemdescr} + \indexlibrarymember{emplace}{priority_queue}% \begin{itemdecl} template void emplace(Args&&... args); @@ -12944,6 +13968,7 @@ explicit stack(const Container&); explicit stack(Container&&); template stack(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> stack(from_range_t, R&& rg); template explicit stack(const Alloc&); template stack(const Container&, const Alloc&); template stack(Container&&, const Alloc&); @@ -12951,6 +13976,8 @@ template stack(stack&&, const Alloc&); template stack(InputIterator first, InputIterator last, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + stack(from_range_t, R&& rg, const Alloc&); [[nodiscard]] bool empty() const { return c.empty(); } size_type size() const { return c.size(); } @@ -12958,6 +13985,8 @@ const_reference top() const { return c.back(); } void push(const value_type& x) { c.push_back(x); } void push(value_type&& x) { c.push_back(std::move(x)); } + template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); template decltype(auto) emplace(Args&&... args) { return c.emplace_back(std::forward(args)...); } @@ -12972,6 +14001,9 @@ template stack(InputIterator, InputIterator) -> stack<@\exposid{iter-value-type}@>; + template + stack(from_range_t, R&&) -> stack>; + template stack(Container, Allocator) -> stack; @@ -12980,6 +14012,10 @@ -> stack<@\exposid{iter-value-type}@, deque<@\exposid{iter-value-type}@, Allocator>>; + template + stack(from_range_t, R&&, Allocator) + -> stack, deque, Allocator>>; + template struct uses_allocator, Alloc> : uses_allocator::type { }; @@ -13023,6 +14059,18 @@ \tcode{first} as the first argument and \tcode{last} as the second argument. \end{itemdescr} +\indexlibraryctor{stack}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + stack(from_range_t, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{ranges::to(std::forward(rg))}. +\end{itemdescr} + \rSec3[stack.cons.alloc]{Constructors with allocators} \pnum @@ -13103,6 +14151,35 @@ \tcode{alloc} as the third argument. \end{itemdescr} +\indexlibraryctor{stack}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + stack(from_range_t, R&& rg, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes +\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}. +\end{itemdescr} + +\rSec3[stack.mod]{Modifiers} + +\indexlibrarymember{push_range}{stack}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{c.append_range(std::forward(rg))} +if that is a valid expression, +otherwise \tcode{ranges::copy(rg, back_inserter(c))}. +\end{itemdescr} + \rSec3[stack.ops]{Operators} \indexlibrarymember{operator==}{stack}% diff --git a/source/ranges.tex b/source/ranges.tex index 3121b25f21..7e0ebb1bd0 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -139,6 +139,16 @@ template<@\libconcept{range}@ R> using borrowed_subrange_t = @\seebelow@; + // \ref{range.utility.conv}, range conversions + template requires (!@\libconcept{view}@) + constexpr C to(R&& r, Args&&... args); + template class C, @\libconcept{input_range}@ R, class... Args> + constexpr auto to(R&& r, Args&&... args) -> @\seebelow@; + template requires (!@\libconcept{view}@) + constexpr auto to(Args&&... args) -> @\seebelow@; + template class C, class... Args> + constexpr auto to(Args&&... args) -> @\seebelow@; + // \ref{range.empty}, empty view template requires is_object_v @@ -402,6 +412,9 @@ struct tuple_element<1, const ranges::subrange> { using type = S; }; + + struct from_range_t { explicit from_range_t() = default; }; + inline constexpr from_range_t from_range{}; } \end{codeblock} @@ -1987,6 +2000,221 @@ denote \tcode{dangling}. \end{itemize} +\rSec2[range.utility.conv]{Range conversions} + +\rSec3[range.utility.conv.general]{General} + +\pnum +The range conversion functions construct +an object (usually a container) from a range, +by using a constructor taking a range, +a \tcode{from_range_t} tagged constructor, or +a constructor taking a pair of iterators, or +by inserting each element of the range into the default-constructed object. + +\pnum +\tcode{ranges::to} is applied recursively, +allowing the conversion of a range of ranges. + +\begin{example} +\begin{codeblock} +string_view str = "the quick brown fox"; +auto words = views::split(str, ' ') | to>(); +// \tcode{words} is \tcode{vector\{"the", "quick", "brown", "fox"\}} +\end{codeblock} +\end{example} + +\pnum +Let \exposid{reservable-container} be defined as follows: +\begin{codeblock} +template +constexpr bool @\exposid{reservable-container}@ = // \expos + @\libconcept{sized_range}@ && + requires(Container& c, range_size_t n) { + c.reserve(n); + { c.capacity() } -> @\libconcept{same_as}@; + { c.max_size() } -> @\libconcept{same_as}@; + }; +\end{codeblock} + +\pnum +Let \exposid{container-insertable} be defined as follows: +\begin{codeblock} +template +constexpr bool @\exposid{container-insertable}@ = // \expos + requires(Container& c, Ref&& ref) { + requires (requires { c.push_back(std::forward(ref)); } || + requires { c.insert(c.end(), std::forward(ref)); }); + }; +\end{codeblock} + +\pnum +Let \exposid{container-inserter} be defined as follows: +\begin{codeblock} +template +auto @\exposid{container-inserter}@(C& c) { // \expos + if constexpr (requires { c.push_back(declval()); }) + return back_inserter(c); + else + return inserter(c, c.end()); +}; +\end{codeblock} + +\rSec3[range.utility.conv.to]{\tcode{ranges::to}} + +\indexlibrarymember{to}{ranges}% +\begin{itemdecl} +template requires (!@\libconcept{view}@) + constexpr C to(R&& r, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An object of type \tcode{C} +constructed from the elements of \tcode{r} in the following manner: +\begin{itemize} +\item +If \tcode{\libconcept{convertible_to}, range_value_t>} +is \tcode{true}: +\begin{itemize} +\item +If \tcode{\libconcept{constructible_from}} is \tcode{true}: +\begin{codeblock} +C(std::forward(r), std::forward(args)...) +\end{codeblock} +\item +Otherwise, if +\tcode{\libconcept{constructible_from}} +is \tcode{true}: +\begin{codeblock} +C(from_range, std::forward(r), std::forward(args)...) +\end{codeblock} +\item +Otherwise, if +\begin{itemize} +\item +\tcode{\libconcept{common_range}} is \tcode{true}, +\item +\tcode{\exposconcept{cpp17-input-iterator}>} is \tcode{true}, and +\item +\tcode{\libconcept{constructible_from}, sentinel_t, Args...>} +is \tcode{true}: +\end{itemize} +\begin{codeblock} +C(ranges::begin(r), ranges::end(r), std::forward(args)...) +\end{codeblock} +\item +Otherwise, if +\begin{itemize} +\item +\tcode{\libconcept{constructible_from}} is \tcode{true}, and +\item +\tcode{\exposid{container-insertable}>} is \tcode{true}: +\end{itemize} +\begin{codeblock} +C c(std::forward(args)...); +if constexpr (@\libconcept{sized_range}@ && @\exposid{reservable-container}@) + c.reserve(ranges::size(r)); +ranges::copy(r, @\exposid{container-inserter}@>(c)); +\end{codeblock} +\end{itemize} + +\item +Otherwise, +if \tcode{\libconcept{input_range}>} is \tcode{true}: +\begin{codeblock} +to(r | views::transform([](auto&& elem) { + return to>(std::forward(elem)); +}), std::forward(args)...); +\end{codeblock} + +\item +Otherwise, the program is ill-formed. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{to}{ranges}% +\begin{itemdecl} +template class C, @\libconcept{input_range}@ R, class... Args> + constexpr auto to(R&& r, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \exposid{input-iterator} be an exposition-only type: +\begin{codeblock} +struct @\exposid{input-iterator}@ { // \expos + using iterator_category = input_iterator_tag; + using value_type = range_value_t; + using difference_type = ptrdiff_t; + using pointer = add_pointer_t>; + using reference = range_reference_t; + reference operator*() const; + pointer operator->() const; + @\exposid{input-iterator}@& operator++(); + @\exposid{input-iterator}@ operator++(int); + bool operator==(const @\exposid{input-iterator}@&) const; +}; +\end{codeblock} +\begin{note} +\exposid{input-iterator} meets +the syntactic requirements of \oldconcept{InputIterator}. +\end{note} + +\pnum +Let \tcode{\placeholder{DEDUCE_EXPR}} be defined as follows: +\begin{itemize} +\item +\tcode{C(declval(), declval()...)} if that is a valid expression, +\item +otherwise, \tcode{C(from_range, declval(), declval()...)} +if that is a valid expression, +\item +otherwise, +\begin{codeblock} +C(declval<@\exposid{input-iterator}@>(), declval<@\exposid{input-iterator}@>(), declval()...) +\end{codeblock} +if that is a valid expression, +\item +otherwise, the program is ill-formed. +\end{itemize} + +\pnum +\returns +\tcode{to(std::forward(r), std::forward(args)...)}. +\end{itemdescr} + +\rSec3[range.utility.conv.adaptors]{\tcode{ranges::to} adaptors} + +\indexlibrarymember{to}{ranges}% +\begin{itemdecl} +template requires (!@\libconcept{view}@) + constexpr auto to(Args&&... args); +template class C, class... Args> + constexpr auto to(Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A range adaptor closure object\iref{range.adaptor.object} \tcode{f} +that is a perfect forwarding call wrapper\iref{func.require} +with the following properties: +\begin{itemize} +\item +It has no target object. +\item +Its bound argument entities \tcode{bound_args} consist of +objects of types \tcode{decay_t...} +direct-non-list-initialized with \tcode{std::forward(args)...}, +respectively. +\item +Its call pattern is \tcode{to(r, bound_args...)}, +where \tcode{r} is the argument used in a function call expression of \tcode{f}. +\end{itemize} +\end{itemdescr} + \rSec1[range.factories]{Range factories} \rSec2[range.factories.general]{General} diff --git a/source/strings.tex b/source/strings.tex index 7400a02ff0..ef41984dde 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -831,6 +831,8 @@ template constexpr basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string(from_range_t, R&& rg, const Allocator& a = Allocator()); constexpr basic_string(initializer_list, const Allocator& = Allocator()); constexpr basic_string(const basic_string&, const Allocator&); constexpr basic_string(basic_string&&, const Allocator&); @@ -905,6 +907,8 @@ constexpr basic_string& append(size_type n, charT c); template constexpr basic_string& append(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& append_range(R&& rg); constexpr basic_string& append(initializer_list); constexpr void push_back(charT c); @@ -923,6 +927,8 @@ constexpr basic_string& assign(size_type n, charT c); template constexpr basic_string& assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& assign_range(R&& rg); constexpr basic_string& assign(initializer_list); constexpr basic_string& insert(size_type pos, const basic_string& str); @@ -940,6 +946,8 @@ constexpr iterator insert(const_iterator p, size_type n, charT c); template constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator p, R&& rg); constexpr iterator insert(const_iterator p, initializer_list); constexpr basic_string& erase(size_type pos = 0, size_type n = npos); @@ -970,6 +978,8 @@ template constexpr basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); + template<@\exposconcept{container-compatible-range}@ 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); constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; @@ -1066,6 +1076,12 @@ char_traits::value_type>, Allocator>; + template>> + basic_string(from_range_t, R&&, Allocator = Allocator()) + -> basic_string, char_traits>, + Allocator>; + template> @@ -1324,6 +1340,19 @@ as specified in \ref{sequence.reqmts}. \end{itemdescr} +\indexlibraryctor{basic_string}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ 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 il, const Allocator& a = Allocator()); @@ -2076,6 +2105,18 @@ 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}@ 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(rg), get_allocator()));} +\end{itemdescr} + \indexlibrarymember{append}{basic_string}% \begin{itemdecl} constexpr basic_string& append(initializer_list il); @@ -2269,6 +2310,18 @@ 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}@ 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(rg), get_allocator()));} +\end{itemdescr} + \rSec4[string.insert]{\tcode{basic_string::insert}} \indexlibrarymember{insert}{basic_string}% @@ -2486,6 +2539,28 @@ \tcode{p} if \tcode{first == last}. \end{itemdescr} +\indexlibrarymember{insert_range}{basic_string}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ 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(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 il); @@ -2851,6 +2926,21 @@ 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}@ 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(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 il); diff --git a/source/support.tex b/source/support.tex index a25fd74be2..9e116d660a 100644 --- a/source/support.tex +++ b/source/support.tex @@ -602,6 +602,9 @@ #define @\defnlibxname{cpp_lib_constexpr_typeinfo}@ 202106L // also in \libheader{typeinfo} #define @\defnlibxname{cpp_lib_constexpr_utility}@ 201811L // also in \libheader{utility} #define @\defnlibxname{cpp_lib_constexpr_vector}@ 201907L // also in \libheader{vector} +#define @\defnlibxname{cpp_lib_containers_ranges}@ 202202L + // also in \libheader{vector}, \libheader{list}, \libheader{forward_list}, \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set}, + // \libheader{deque}, \libheader{queue}, \libheader{priority_queue}, \libheader{stack}, \libheader{string} #define @\defnlibxname{cpp_lib_coroutine}@ 201902L // also in \libheader{coroutine} #define @\defnlibxname{cpp_lib_destroying_delete}@ 201806L // also in \libheader{new} #define @\defnlibxname{cpp_lib_enable_shared_from_this}@ 201603L // also in \libheader{memory} @@ -668,6 +671,7 @@ #define @\defnlibxname{cpp_lib_ranges}@ 202110L // also in \libheader{algorithm}, \libheader{functional}, \libheader{iterator}, \libheader{memory}, \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_starts_ends_with}@ 202106L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_ranges_to_container}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_zip}@ 202110L // also in \libheader{ranges}, \libheader{tuple}, \libheader{utility} #define @\defnlibxname{cpp_lib_raw_memory_algorithms}@ 201606L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_remove_cvref}@ 201711L // also in \libheader{type_traits} From 55b4e4dea9ff340bf031f6c7d490eb7d28eb9f8e Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 08:37:48 +0100 Subject: [PATCH 112/182] P1413R3 Deprecate std::aligned_storage and std::aligned_union - Replace 'shall be' with 'is'. - Also move a note following [tab:meta.trans.other] to the annex. --- source/future.tex | 76 ++++++++++++++++++++++++++++++++++++++++++++ source/utilities.tex | 52 ------------------------------ 2 files changed, 76 insertions(+), 52 deletions(-) diff --git a/source/future.tex b/source/future.tex index 44b4b31aa1..561272faeb 100644 --- a/source/future.tex +++ b/source/future.tex @@ -1369,6 +1369,14 @@ namespace std { template struct is_pod; template inline constexpr bool is_pod_v = is_pod::value; + template // \seebelow + struct aligned_storage; + template // \seebelow + using @\libglobal{aligned_storage_t}@ = typename aligned_storage::type; + template + struct aligned_union; + template + using @\libglobal{aligned_union_t}@ = typename aligned_union::type; } \end{codeblock} @@ -1403,6 +1411,74 @@ \end{note} \end{itemdescr} +\indexlibraryglobal{aligned_storage}% +\begin{itemdecl} +template + struct aligned_storage; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The value of \exposid{default-alignment} is the most +stringent alignment requirement for any object type whose size +is no greater than \tcode{Len}\iref{basic.types}. + +\pnum +\mandates +\tcode{Len} is not zero. +\tcode{Align} is equal to \tcode{alignof(T)} for some type \tcode{T} or +to \exposid{default-alignment}. + +\pnum +The member typedef \tcode{type} is a trivial standard-layout type +suitable for use as uninitialized storage for any object +whose size is at most \tcode{Len} and +whose alignment is a divisor of \tcode{Align}. + +\pnum +\begin{note} +Uses of \tcode{aligned_storage::type} can be replaced +by an array \tcode{std::byte[Len]} declared with \tcode{alignas(Align)}. +\end{note} + +\pnum +\begin{note} +A typical implementation would define \tcode{aligned_storage} as: +\begin{codeblock} +template +struct aligned_storage { + typedef struct { + alignas(Alignment) unsigned char __data[Len]; + } type; +}; +\end{codeblock} +\end{note} + +\end{itemdescr} + +\indexlibraryglobal{aligned_union}% +\begin{itemdecl} +template + struct aligned_union; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +At least one type is provided. +Each type in the template parameter pack \tcode{Types} +is a complete object type. + +\pnum +The member typedef \tcode{type} is a trivial standard-layout type +suitable for use as uninitialized storage for any object +whose type is listed in \tcode{Types}; +its size shall be at least \tcode{Len}. +The static member \tcode{alignment_value} +is an integral constant of type \tcode{size_t} +whose value is the strictest alignment of all types listed in \tcode{Types}. +\end{itemdescr} + \rSec1[depr.tuple]{Tuple} \pnum diff --git a/source/utilities.tex b/source/utilities.tex index 12451a592a..f14fea67fa 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -19635,9 +19635,6 @@ // \ref{meta.trans.other}, other transformations template struct type_identity; - template // see \ref{meta.trans.other} - struct aligned_storage; - template struct aligned_union; template struct remove_cvref; template struct decay; template struct enable_if; @@ -19653,10 +19650,6 @@ template using @\libglobal{type_identity_t}@ = typename type_identity::type; - template // see \ref{meta.trans.other} - using @\libglobal{aligned_storage_t}@ = typename aligned_storage::type; - template - using @\libglobal{aligned_union_t}@ = typename aligned_union::type; template using @\libglobal{remove_cvref_t}@ = typename remove_cvref::type; template @@ -21095,36 +21088,6 @@ & The member typedef \tcode{type} names the type \tcode{T}. \\ \rowsep -\indexlibraryglobal{aligned_storage}% -\tcode{template\br - struct aligned_storage;} - & - The value of \textit{default-alignment} shall be the most - stringent alignment requirement for any object type whose size - is no greater than \tcode{Len}\iref{basic.types}. - The member typedef \tcode{type} shall be a trivial standard-layout type - suitable for use as uninitialized storage for any object whose size - is at most \tcode{Len} and whose alignment is a divisor of \tcode{Align}.\br - \mandates \tcode{Len} is not zero. \tcode{Align} is equal to - \tcode{alignof(T)} for some type \tcode{T} or to \textit{default-alignment}.\\ \rowsep - -\indexlibraryglobal{aligned_union}% -\tcode{template\br - struct aligned_union;} - & - The member typedef \tcode{type} shall be a trivial standard-layout type suitable for use as - uninitialized storage for any object whose type is listed in \tcode{Types}; - its size shall be at least \tcode{Len}. The static member \tcode{alignment_value} - shall be an integral constant of type \tcode{size_t} whose value is the - strictest alignment of all types listed in \tcode{Types}.\br - \mandates At least one type is provided. - Each type in the template parameter pack \tcode{Types} - is a complete object type. - \\ \rowsep - \indexlibraryglobal{remove_cvref}% \tcode{template\br struct remove_cvref;} & @@ -21235,21 +21198,6 @@ denotes the type \tcode{unwrap_reference_t>}.\\ \end{libreqtab2a} -\indexlibraryglobal{aligned_storage}% -\pnum -\begin{note} -A typical implementation would define \tcode{aligned_storage} as: - -\begin{codeblock} -template -struct aligned_storage { - typedef struct { - alignas(Alignment) unsigned char __data[Len]; - } type; -}; -\end{codeblock} -\end{note} - \pnum In addition to being available via inclusion of the \tcode{} header, the templates From d34af4247ae8d6bc841ee0100eab2abe7bbe35b1 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 09:04:03 +0100 Subject: [PATCH 113/182] P2255R2 A type trait to detect reference binding to temporary --- source/support.tex | 1 + source/utilities.tex | 90 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/source/support.tex b/source/support.tex index 9e116d660a..f3ac0cc663 100644 --- a/source/support.tex +++ b/source/support.tex @@ -674,6 +674,7 @@ #define @\defnlibxname{cpp_lib_ranges_to_container}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_zip}@ 202110L // also in \libheader{ranges}, \libheader{tuple}, \libheader{utility} #define @\defnlibxname{cpp_lib_raw_memory_algorithms}@ 201606L // also in \libheader{memory} +#define @\defnlibxname{cpp_lib_reference_from_temporary}@ 202202L // also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_remove_cvref}@ 201711L // also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_result_of_sfinae}@ 201210L // also in \libheader{functional}, \libheader{type_traits} #define @\defnlibxname{cpp_lib_robust_nonmodifying_seq_ops}@ 201304L // also in \libheader{algorithm} diff --git a/source/utilities.tex b/source/utilities.tex index f14fea67fa..800b309a6c 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -872,6 +872,11 @@ \begin{codeblock} !is_convertible_v || !is_convertible_v \end{codeblock} +This constructor is defined as deleted if +\tcode{reference_constructs_from_temporary_v} +is \tcode{true} or +\tcode{reference_constructs_from_temporary_v} +is \tcode{true}. \end{itemdescr} \indexlibraryctor{pair}% @@ -909,6 +914,12 @@ !is_convertible_v(@\exposid{FWD}@(p))), T1> || !is_convertible_v(@\exposid{FWD}@(p))), T2> \end{codeblock} +The constructor is defined as deleted if +\begin{codeblock} +reference_constructs_from_temporary_v(@\exposid{FWD}@(p)))> || +reference_constructs_from_temporary_v(@\exposid{FWD}@(p)))> +\end{codeblock} +is \tcode{true}. \end{itemdescr} \indexlibraryctor{pair}% @@ -936,6 +947,11 @@ \tcode{std::forward(x)}.) This form of construction, whereby constructor arguments for \tcode{first} and \tcode{second} are each provided in a separate \tcode{tuple} object, is called \defn{piecewise construction}. +\begin{note} +If a data member of \tcode{pair} is of reference type and +its initialization binds it to a temporary object, +the program is ill-formed\iref{class.base.init}. +\end{note} \end{itemdescr} \indexlibrarymember{operator=}{pair}% @@ -1731,6 +1747,11 @@ \begin{codeblock} !conjunction_v...> \end{codeblock} +This constructor is defined as deleted if +\begin{codeblock} +(reference_constructs_from_temporary_v || ...) +\end{codeblock} +is \tcode{true}. \end{itemdescr} \indexlibraryctor{tuple}% @@ -1806,6 +1827,11 @@ \begin{codeblock} !(is_convertible_v(@\exposid{FWD}@(u))), Types> && ...) \end{codeblock} +The constructor is defined as deleted if +\begin{codeblock} +(reference_constructs_from_temporary_v(@\exposid{FWD}@(u)))> || ...) +\end{codeblock} +is \tcode{true}. \end{itemdescr} \indexlibraryctor{tuple}% @@ -1843,6 +1869,12 @@ !is_convertible_v(@\exposid{FWD}@(u))), @$\tcode{T}_0$@> || !is_convertible_v(@\exposid{FWD}@(u))), @$\tcode{T}_1$@> \end{codeblock} +The constructor is defined as deleted if +\begin{codeblock} +reference_constructs_from_temporary_v<@$\tcode{T}_0$@, decltype(get<0>(@\exposid{FWD}@(u)))> || +reference_constructs_from_temporary_v<@$\tcode{T}_1$@, decltype(get<1>(@\exposid{FWD}@(u)))> +\end{codeblock} +is \tcode{true}. \end{itemdescr} \indexlibraryctor{tuple}% @@ -2404,6 +2436,13 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +If \tcode{tuple_size_v>} is 1, +then +\tcode{reference_constructs_from_temporary_v(declval()))>} +is \tcode{false}. + \pnum \effects Given the exposition-only function: @@ -16393,6 +16432,11 @@ if \tcode{R} is \cv{}~\keyword{void}, otherwise \tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} implicitly converted to \tcode{R}. +If +\tcode{reference_converts_from_temporary_v} +is \tcode{true}, +\tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} +is ill-formed. \pnum \indextext{call wrapper}% @@ -19554,6 +19598,9 @@ template struct has_unique_object_representations; + template struct reference_constructs_from_temporary; + template struct reference_converts_from_temporary; + // \ref{meta.unary.prop.query}, type property queries template struct alignment_of; template struct rank; @@ -19826,6 +19873,12 @@ template inline constexpr bool has_unique_object_representations_v = has_unique_object_representations::value; + template + inline constexpr bool @\libglobal{reference_constructs_from_temporary_v}@ + = reference_constructs_from_temporary::value; + template + inline constexpr bool @\libglobal{reference_converts_from_temporary_v}@ + = reference_converts_from_temporary::value; // \ref{meta.unary.prop.query}, type property queries template @@ -20081,6 +20134,24 @@ in the context of the corresponding definition notwithstanding the restrictions of~\ref{declval}. +\pnum +For the purpose of defining the templates in this subclause, +let \tcode{\placeholdernc{VAL}} for some type \tcode{T} be +an expression defined as follows: +\begin{itemize} +\item +If \tcode{T} is a reference or function type, +\tcode{\placeholdernc{VAL}} is an expression +with the same type and value category as \tcode{declval()}. +\item +Otherwise, \tcode{\placeholdernc{VAL}} is a prvalue +that initially has type \tcode{T}. +\begin{note} +If \tcode{T} is cv-qualified, +the cv-qualification is subject to adjustment\iref{expr.type}. +\end{note} +\end{itemize} + \begin{libreqtab3b}{Type property predicates}{meta.unary.prop} \\ \topline \lhdr{Template} & \chdr{Condition} & \rhdr{Preconditions} \\ \capsep @@ -20492,6 +20563,25 @@ \tcode{T} shall be a complete type, \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep +\indexlibraryglobal{reference_constructs_from_temporary}% +\tcode{template}\br + \tcode{struct reference_constructs_from_temporary;} & + \tcode{conjunction_v, is_constructible>} + is \tcode{true}, and + the initialization \tcode{T t(\exposidnc{VAL});} binds \tcode{t} to + a temporary object whose lifetime is extended\iref{class.temporary}. & + \tcode{T} and \tcode{U} shall be + complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{reference_converts_from_temporary}% +\tcode{template}\br + \tcode{struct reference_converts_from_temporary;} & + \tcode{conjunction_v, is_convertible>} is \tcode{true}, + and the initialization \tcode{T t = \exposidnc{VAL};} binds \tcode{t} to + a temporary object whose lifetime is extended\iref{class.temporary}. & + \tcode{T} and \tcode{U} shall be + complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep + \end{libreqtab3b} \pnum From fef512ac222b871b99173df8d14d6078eddeec71 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 10:51:11 +0100 Subject: [PATCH 114/182] P2273R3 Making std::unique_ptr constexpr - Fix position of 'constexpr' operator<=>(nullptr_t) --- source/support.tex | 2 +- source/utilities.tex | 204 +++++++++++++++++++++---------------------- 2 files changed, 103 insertions(+), 103 deletions(-) diff --git a/source/support.tex b/source/support.tex index f3ac0cc663..9eb63bc7b7 100644 --- a/source/support.tex +++ b/source/support.tex @@ -594,7 +594,7 @@ #define @\defnlibxname{cpp_lib_constexpr_dynamic_alloc}@ 201907L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_constexpr_functional}@ 201907L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_constexpr_iterator}@ 201811L // also in \libheader{iterator} -#define @\defnlibxname{cpp_lib_constexpr_memory}@ 201811L // also in \libheader{memory} +#define @\defnlibxname{cpp_lib_constexpr_memory}@ 202202L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_constexpr_numeric}@ 201911L // also in \libheader{numeric} #define @\defnlibxname{cpp_lib_constexpr_string}@ 201907L // also in \libheader{string} #define @\defnlibxname{cpp_lib_constexpr_string_view}@ 201811L // also in \libheader{string_view} diff --git a/source/utilities.tex b/source/utilities.tex index 800b309a6c..216efc596c 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -9771,24 +9771,24 @@ template class unique_ptr; template - unique_ptr make_unique(Args&&... args); // \tcode{T} is not array + constexpr unique_ptr make_unique(Args&&... args); // \tcode{T} is not array template - unique_ptr make_unique(size_t n); // \tcode{T} is \tcode{U[]} + constexpr unique_ptr make_unique(size_t n); // \tcode{T} is \tcode{U[]} template @\unspecnc@ make_unique(Args&&...) = delete; // \tcode{T} is \tcode{U[N]} template - unique_ptr make_unique_for_overwrite(); // \tcode{T} is not array + constexpr unique_ptr make_unique_for_overwrite(); // \tcode{T} is not array template - unique_ptr make_unique_for_overwrite(size_t n); // \tcode{T} is \tcode{U[]} + constexpr unique_ptr make_unique_for_overwrite(size_t n); // \tcode{T} is \tcode{U[]} template @\unspecnc@ make_unique_for_overwrite(Args&&...) = delete; // \tcode{T} is \tcode{U[N]} template - void swap(unique_ptr& x, unique_ptr& y) noexcept; + constexpr void swap(unique_ptr& x, unique_ptr& y) noexcept; template - bool operator==(const unique_ptr& x, const unique_ptr& y); + constexpr bool operator==(const unique_ptr& x, const unique_ptr& y); template bool operator<(const unique_ptr& x, const unique_ptr& y); template @@ -9805,26 +9805,26 @@ operator<=>(const unique_ptr& x, const unique_ptr& y); template - bool operator==(const unique_ptr& x, nullptr_t) noexcept; + constexpr bool operator==(const unique_ptr& x, nullptr_t) noexcept; template - bool operator<(const unique_ptr& x, nullptr_t); + constexpr bool operator<(const unique_ptr& x, nullptr_t); template - bool operator<(nullptr_t, const unique_ptr& y); + constexpr bool operator<(nullptr_t, const unique_ptr& y); template - bool operator>(const unique_ptr& x, nullptr_t); + constexpr bool operator>(const unique_ptr& x, nullptr_t); template - bool operator>(nullptr_t, const unique_ptr& y); + constexpr bool operator>(nullptr_t, const unique_ptr& y); template - bool operator<=(const unique_ptr& x, nullptr_t); + constexpr bool operator<=(const unique_ptr& x, nullptr_t); template - bool operator<=(nullptr_t, const unique_ptr& y); + constexpr bool operator<=(nullptr_t, const unique_ptr& y); template - bool operator>=(const unique_ptr& x, nullptr_t); + constexpr bool operator>=(const unique_ptr& x, nullptr_t); template - bool operator>=(nullptr_t, const unique_ptr& y); + constexpr bool operator>=(nullptr_t, const unique_ptr& y); template requires @\libconcept{three_way_comparable}@::pointer> - compare_three_way_result_t::pointer> + constexpr compare_three_way_result_t::pointer> operator<=>(const unique_ptr& x, nullptr_t); template @@ -11154,15 +11154,15 @@ namespace std { template struct default_delete { constexpr default_delete() noexcept = default; - template default_delete(const default_delete&) noexcept; - void operator()(T*) const; + template constexpr default_delete(const default_delete&) noexcept; + constexpr void operator()(T*) const; }; } \end{codeblock} \indexlibraryctor{default_delete}% \begin{itemdecl} -template default_delete(const default_delete& other) noexcept; +template constexpr default_delete(const default_delete& other) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11178,7 +11178,7 @@ \indexlibrarymember{operator()}{default_delete}% \begin{itemdecl} -void operator()(T* ptr) const; +constexpr void operator()(T* ptr) const; \end{itemdecl} \begin{itemdescr} @@ -11197,15 +11197,15 @@ namespace std { template struct default_delete { constexpr default_delete() noexcept = default; - template default_delete(const default_delete&) noexcept; - template void operator()(U* ptr) const; + template constexpr default_delete(const default_delete&) noexcept; + template constexpr void operator()(U* ptr) const; }; } \end{codeblock} \indexlibraryctor{default_delete} \begin{itemdecl} -template default_delete(const default_delete& other) noexcept; +template constexpr default_delete(const default_delete& other) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11220,7 +11220,7 @@ \indexlibrarymember{operator()}{default_delete}% \begin{itemdecl} -template void operator()(U* ptr) const; +template constexpr void operator()(U* ptr) const; \end{itemdecl} \begin{itemdescr} @@ -11252,35 +11252,35 @@ // \ref{unique.ptr.single.ctor}, constructors constexpr unique_ptr() noexcept; - explicit unique_ptr(type_identity_t p) noexcept; - unique_ptr(type_identity_t p, @\seebelow@ d1) noexcept; - unique_ptr(type_identity_t p, @\seebelow@ d2) noexcept; - unique_ptr(unique_ptr&& u) noexcept; + constexpr explicit unique_ptr(type_identity_t p) noexcept; + constexpr unique_ptr(type_identity_t p, @\seebelow@ d1) noexcept; + constexpr unique_ptr(type_identity_t p, @\seebelow@ d2) noexcept; + constexpr unique_ptr(unique_ptr&& u) noexcept; constexpr unique_ptr(nullptr_t) noexcept; template - unique_ptr(unique_ptr&& u) noexcept; + constexpr unique_ptr(unique_ptr&& u) noexcept; // \ref{unique.ptr.single.dtor}, destructor - ~unique_ptr(); + constexpr ~unique_ptr(); // \ref{unique.ptr.single.asgn}, assignment - unique_ptr& operator=(unique_ptr&& u) noexcept; + constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; template - unique_ptr& operator=(unique_ptr&& u) noexcept; - unique_ptr& operator=(nullptr_t) noexcept; + constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; + constexpr unique_ptr& operator=(nullptr_t) noexcept; // \ref{unique.ptr.single.observers}, observers - add_lvalue_reference_t operator*() const noexcept(@\seebelow@); - pointer operator->() const noexcept; - pointer get() const noexcept; - deleter_type& get_deleter() noexcept; - const deleter_type& get_deleter() const noexcept; - explicit operator bool() const noexcept; + constexpr add_lvalue_reference_t operator*() const noexcept(@\seebelow@); + constexpr pointer operator->() const noexcept; + constexpr pointer get() const noexcept; + constexpr deleter_type& get_deleter() noexcept; + constexpr const deleter_type& get_deleter() const noexcept; + constexpr explicit operator bool() const noexcept; // \ref{unique.ptr.single.modifiers}, modifiers - pointer release() noexcept; - void reset(pointer p = pointer()) noexcept; - void swap(unique_ptr& u) noexcept; + constexpr pointer release() noexcept; + constexpr void reset(pointer p = pointer()) noexcept; + constexpr void swap(unique_ptr& u) noexcept; // disable copy from lvalue unique_ptr(const unique_ptr&) = delete; @@ -11353,7 +11353,7 @@ \indexlibraryctor{unique_ptr}% \begin{itemdecl} -explicit unique_ptr(type_identity_t p) noexcept; +constexpr explicit unique_ptr(type_identity_t p) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11381,8 +11381,8 @@ \indexlibraryctor{unique_ptr}% \begin{itemdecl} -unique_ptr(type_identity_t p, const D& d) noexcept; -unique_ptr(type_identity_t p, remove_reference_t&& d) noexcept; +constexpr unique_ptr(type_identity_t p, const D& d) noexcept; +constexpr unique_ptr(type_identity_t p, remove_reference_t&& d) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11432,7 +11432,7 @@ \indexlibraryctor{unique_ptr}% \begin{itemdecl} -unique_ptr(unique_ptr&& u) noexcept; +constexpr unique_ptr(unique_ptr&& u) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11473,7 +11473,7 @@ \indexlibraryctor{unique_ptr}% \begin{itemdecl} -template unique_ptr(unique_ptr&& u) noexcept; +template constexpr unique_ptr(unique_ptr&& u) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11519,7 +11519,7 @@ \indexlibrarydtor{unique_ptr}% \begin{itemdecl} -~unique_ptr(); +constexpr ~unique_ptr(); \end{itemdecl} \begin{itemdescr} @@ -11541,7 +11541,7 @@ \indexlibrarymember{operator=}{unique_ptr}% \begin{itemdecl} -unique_ptr& operator=(unique_ptr&& u) noexcept; +constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11577,7 +11577,7 @@ \indexlibrarymember{operator=}{unique_ptr}% \begin{itemdecl} -template unique_ptr& operator=(unique_ptr&& u) noexcept; +template constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11614,7 +11614,7 @@ \indexlibrarymember{operator=}{unique_ptr}% \begin{itemdecl} -unique_ptr& operator=(nullptr_t) noexcept; +constexpr unique_ptr& operator=(nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11635,7 +11635,7 @@ \indexlibrarymember{operator*}{unique_ptr}% \begin{itemdecl} -add_lvalue_reference_t operator*() const noexcept(noexcept(*declval())); +constexpr add_lvalue_reference_t operator*() const noexcept(noexcept(*declval())); \end{itemdecl} \begin{itemdescr} @@ -11651,7 +11651,7 @@ \indexlibrarymember{operator->}{unique_ptr}% \begin{itemdecl} -pointer operator->() const noexcept; +constexpr pointer operator->() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -11671,7 +11671,7 @@ \indexlibrarymember{get}{unique_ptr}% \begin{itemdecl} -pointer get() const noexcept; +constexpr pointer get() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -11682,8 +11682,8 @@ \indexlibrarymember{get_deleter}{unique_ptr}% \begin{itemdecl} -deleter_type& get_deleter() noexcept; -const deleter_type& get_deleter() const noexcept; +constexpr deleter_type& get_deleter() noexcept; +constexpr const deleter_type& get_deleter() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -11694,7 +11694,7 @@ \indexlibrarymember{operator bool}{unique_ptr}% \begin{itemdecl} -explicit operator bool() const noexcept; +constexpr explicit operator bool() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -11707,7 +11707,7 @@ \indexlibrarymember{release}{unique_ptr}% \begin{itemdecl} -pointer release() noexcept; +constexpr pointer release() noexcept; \end{itemdecl} \begin{itemdescr} @@ -11723,7 +11723,7 @@ \indexlibrarymember{reset}{unique_ptr}% \begin{itemdecl} -void reset(pointer p = pointer()) noexcept; +constexpr void reset(pointer p = pointer()) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11753,7 +11753,7 @@ \indexlibrarymember{swap}{unique_ptr}% \begin{itemdecl} -void swap(unique_ptr& u) noexcept; +constexpr void swap(unique_ptr& u) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11783,35 +11783,35 @@ // \ref{unique.ptr.runtime.ctor}, constructors constexpr unique_ptr() noexcept; - template explicit unique_ptr(U p) noexcept; - template unique_ptr(U p, @\seebelow@ d) noexcept; - template unique_ptr(U p, @\seebelow@ d) noexcept; - unique_ptr(unique_ptr&& u) noexcept; + template constexpr explicit unique_ptr(U p) noexcept; + template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; + template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; + constexpr unique_ptr(unique_ptr&& u) noexcept; template - unique_ptr(unique_ptr&& u) noexcept; + constexpr unique_ptr(unique_ptr&& u) noexcept; constexpr unique_ptr(nullptr_t) noexcept; // destructor - ~unique_ptr(); + constexpr ~unique_ptr(); // assignment - unique_ptr& operator=(unique_ptr&& u) noexcept; + constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; template - unique_ptr& operator=(unique_ptr&& u) noexcept; - unique_ptr& operator=(nullptr_t) noexcept; + constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; + constexpr unique_ptr& operator=(nullptr_t) noexcept; // \ref{unique.ptr.runtime.observers}, observers - T& operator[](size_t i) const; - pointer get() const noexcept; - deleter_type& get_deleter() noexcept; - const deleter_type& get_deleter() const noexcept; - explicit operator bool() const noexcept; + constexpr T& operator[](size_t i) const; + constexpr pointer get() const noexcept; + constexpr deleter_type& get_deleter() noexcept; + constexpr const deleter_type& get_deleter() const noexcept; + constexpr explicit operator bool() const noexcept; // \ref{unique.ptr.runtime.modifiers}, modifiers - pointer release() noexcept; - template void reset(U p) noexcept; - void reset(nullptr_t = nullptr) noexcept; - void swap(unique_ptr& u) noexcept; + constexpr pointer release() noexcept; + template constexpr void reset(U p) noexcept; + constexpr void reset(nullptr_t = nullptr) noexcept; + constexpr void swap(unique_ptr& u) noexcept; // disable copy from lvalue unique_ptr(const unique_ptr&) = delete; @@ -11853,7 +11853,7 @@ \indexlibraryctor{unique_ptr}% \begin{itemdecl} -template explicit unique_ptr(U p) noexcept; +template constexpr explicit unique_ptr(U p) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11874,8 +11874,8 @@ \indexlibraryctor{unique_ptr}% \begin{itemdecl} -template unique_ptr(U p, @\seebelow@ d) noexcept; -template unique_ptr(U p, @\seebelow@ d) noexcept; +template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; +template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11897,7 +11897,7 @@ \indexlibraryctor{unique_ptr}% \begin{itemdecl} -template unique_ptr(unique_ptr&& u) noexcept; +template constexpr unique_ptr(unique_ptr&& u) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11925,7 +11925,7 @@ \indexlibrarymember{operator=}{unique_ptr}% \begin{itemdecl} -template unique_ptr& operator=(unique_ptr&& u) noexcept; +template constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11952,7 +11952,7 @@ \indexlibrarymember{operator[]}{unique_ptr}% \begin{itemdecl} -T& operator[](size_t i) const; +constexpr T& operator[](size_t i) const; \end{itemdecl} \begin{itemdescr} @@ -11971,7 +11971,7 @@ \indexlibrarymember{reset}{unique_ptr}% \begin{itemdecl} -void reset(nullptr_t p = nullptr) noexcept; +constexpr void reset(nullptr_t p = nullptr) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11982,7 +11982,7 @@ \indexlibrarymember{reset}{unique_ptr}% \begin{itemdecl} -template void reset(U p) noexcept; +constexpr template void reset(U p) noexcept; \end{itemdecl} \begin{itemdescr} @@ -12004,7 +12004,7 @@ \indexlibraryglobal{make_unique}% \begin{itemdecl} -template unique_ptr make_unique(Args&&... args); +template constexpr unique_ptr make_unique(Args&&... args); \end{itemdecl} \begin{itemdescr} @@ -12020,7 +12020,7 @@ \indexlibraryglobal{make_unique}% \begin{itemdecl} -template unique_ptr make_unique(size_t n); +template constexpr unique_ptr make_unique(size_t n); \end{itemdecl} \begin{itemdescr} @@ -12048,7 +12048,7 @@ \indexlibraryglobal{make_unique}% \begin{itemdecl} -template unique_ptr make_unique_for_overwrite(); +template constexpr unique_ptr make_unique_for_overwrite(); \end{itemdecl} \begin{itemdescr} @@ -12063,7 +12063,7 @@ \indexlibraryglobal{make_unique}% \begin{itemdecl} -template unique_ptr make_unique_for_overwrite(size_t n); +template constexpr unique_ptr make_unique_for_overwrite(size_t n); \end{itemdecl} \begin{itemdescr} @@ -12091,7 +12091,7 @@ \indexlibrary{\idxcode{swap(unique_ptr\&, unique_ptr\&)}}% \begin{itemdecl} -template void swap(unique_ptr& x, unique_ptr& y) noexcept; +template constexpr void swap(unique_ptr& x, unique_ptr& y) noexcept; \end{itemdecl} \begin{itemdescr} @@ -12107,7 +12107,7 @@ \indexlibrarymember{operator==}{unique_ptr}% \begin{itemdecl} template - bool operator==(const unique_ptr& x, const unique_ptr& y); + constexpr bool operator==(const unique_ptr& x, const unique_ptr& y); \end{itemdecl} \begin{itemdescr} @@ -12203,7 +12203,7 @@ \indexlibrarymember{operator==}{unique_ptr}% \begin{itemdecl} template - bool operator==(const unique_ptr& x, nullptr_t) noexcept; + constexpr bool operator==(const unique_ptr& x, nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} @@ -12215,9 +12215,9 @@ \indexlibrarymember{operator<}{unique_ptr}% \begin{itemdecl} template - bool operator<(const unique_ptr& x, nullptr_t); + constexpr bool operator<(const unique_ptr& x, nullptr_t); template - bool operator<(nullptr_t, const unique_ptr& x); + constexpr bool operator<(nullptr_t, const unique_ptr& x); \end{itemdecl} \begin{itemdescr} @@ -12242,9 +12242,9 @@ \indexlibrarymember{operator>}{unique_ptr}% \begin{itemdecl} template - bool operator>(const unique_ptr& x, nullptr_t); + constexpr bool operator>(const unique_ptr& x, nullptr_t); template - bool operator>(nullptr_t, const unique_ptr& x); + constexpr bool operator>(nullptr_t, const unique_ptr& x); \end{itemdecl} \begin{itemdescr} @@ -12257,9 +12257,9 @@ \indexlibrarymember{operator<=}{unique_ptr}% \begin{itemdecl} template - bool operator<=(const unique_ptr& x, nullptr_t); + constexpr bool operator<=(const unique_ptr& x, nullptr_t); template - bool operator<=(nullptr_t, const unique_ptr& x); + constexpr bool operator<=(nullptr_t, const unique_ptr& x); \end{itemdecl} \begin{itemdescr} @@ -12272,9 +12272,9 @@ \indexlibrarymember{operator>=}{unique_ptr}% \begin{itemdecl} template - bool operator>=(const unique_ptr& x, nullptr_t); + constexpr bool operator>=(const unique_ptr& x, nullptr_t); template - bool operator>=(nullptr_t, const unique_ptr& x); + constexpr bool operator>=(nullptr_t, const unique_ptr& x); \end{itemdecl} \begin{itemdescr} @@ -12288,7 +12288,7 @@ \begin{itemdecl} template requires @\libconcept{three_way_comparable}@::pointer> - compare_three_way_result_t::pointer> + constexpr compare_three_way_result_t::pointer> operator<=>(const unique_ptr& x, nullptr_t); \end{itemdecl} From 24afe257887f36ba75596eb02dde91afa94113d1 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 12:52:08 +0100 Subject: [PATCH 115/182] P2387R3 Pipe support for user-defined range adaptors --- source/ranges.tex | 47 +++++++++++++++++++++++++++++++++++++++++--- source/support.tex | 3 ++- source/utilities.tex | 21 ++++++++++++++++---- source/xrefdelta.tex | 3 +++ 4 files changed, 66 insertions(+), 8 deletions(-) diff --git a/source/ranges.tex b/source/ranges.tex index 7e0ebb1bd0..faafdeb2f8 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -193,6 +193,11 @@ namespace views { template inline constexpr @\unspec@ istream = @\unspec@; } + // \ref{range.adaptor.object}, range adaptor objects + template + requires is_class_v && @\libconcept{same_as}@> + class range_adaptor_closure { }; + // \ref{range.all}, all view namespace views { inline constexpr @\unspec@ all = @\unspec@; @@ -3365,10 +3370,10 @@ \pnum A \term{range adaptor closure object} is a unary function object that accepts -a \libconcept{viewable_range} argument and returns a \libconcept{view}. For +a \libconcept{range} argument. For a range adaptor closure object \tcode{C} and an expression \tcode{R} such that -\tcode{decltype((R))} models \libconcept{viewable_range}, the following -expressions are equivalent and yield a \libconcept{view}: +\tcode{decltype((R))} models \libconcept{range}, the following +expressions are equivalent: \begin{codeblock} C(R) R | C @@ -3394,6 +3399,42 @@ The expression \tcode{C | D} is well-formed if and only if the initializations of the state entities of \tcode{E} are all well-formed. +\pnum +Given an object \tcode{t} of type \tcode{T}, where +\begin{itemize} +\item +\tcode{t} is a unary function object that accepts a \libconcept{range} argument, +\item +\tcode{T} models \tcode{\libconcept{derived_from}>}, +\item +\tcode{T} has no other base classes of type \tcode{range_adaptor_closure} for any other type \tcode{U}, and +\item +\tcode{T} does not model \libconcept{range} +\end{itemize} +then the implementation ensures +that \tcode{t} is a range adaptor closure object. + +\pnum +The template parameter \tcode{D} for \tcode{range_adaptor_closure} +may be an incomplete type. +If an expression of type \cv{} \tcode{D} +is used as an operand to the \tcode{|} operator, +\tcode{D} shall be complete and +model \tcode{\libconcept{derived_from}>}. +The behavior of an expression involving an object of type \cv{} \tcode{D} +as an operand to the \tcode{|} operator is undefined +if overload resolution selects a program-defined \tcode{operator|} function. + +\pnum +If an expression of type \cv{} \tcode{U} +is used as an operand to the \tcode{|} operator, +where \tcode{U} has a base class of type \tcode{range_adaptor_closure} +for some type \tcode{T} other than \tcode{U}, the behavior is undefined. + +\pnum +The behavior of a program +that adds a specialization for \tcode{range_adaptor_closure} is undefined. + \pnum A \term{range adaptor object} is a customization point object\iref{customization.point.object} diff --git a/source/support.tex b/source/support.tex index 9eb63bc7b7..35cbe37ccc 100644 --- a/source/support.tex +++ b/source/support.tex @@ -573,6 +573,7 @@ #define @\defnlibxname{cpp_lib_atomic_value_initialization}@ 201911L // also in \libheader{atomic}, \libheader{memory} #define @\defnlibxname{cpp_lib_atomic_wait}@ 201907L // also in \libheader{atomic} #define @\defnlibxname{cpp_lib_barrier}@ 201907L // also in \libheader{barrier} +#define @\defnlibxname{cpp_lib_bind_back}@ 202202L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_bind_front}@ 201907L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_bit_cast}@ 201806L // also in \libheader{bit} #define @\defnlibxname{cpp_lib_bitops}@ 201907L // also in \libheader{bit} @@ -668,7 +669,7 @@ #define @\defnlibxname{cpp_lib_parallel_algorithm}@ 201603L // also in \libheader{algorithm}, \libheader{numeric} #define @\defnlibxname{cpp_lib_polymorphic_allocator}@ 201902L // also in \libheader{memory_resource} #define @\defnlibxname{cpp_lib_quoted_string_io}@ 201304L // also in \libheader{iomanip} -#define @\defnlibxname{cpp_lib_ranges}@ 202110L +#define @\defnlibxname{cpp_lib_ranges}@ 202202L // also in \libheader{algorithm}, \libheader{functional}, \libheader{iterator}, \libheader{memory}, \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_starts_ends_with}@ 202106L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_to_container}@ 202202L // also in \libheader{ranges} diff --git a/source/utilities.tex b/source/utilities.tex index 216efc596c..c9a0f03518 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -16256,8 +16256,9 @@ // \ref{func.not.fn}, function template \tcode{not_fn} template constexpr @\unspec@ not_fn(F&& f); - // \ref{func.bind.front}, function template \tcode{bind_front} + // \ref{func.bind.partial}, function templates \tcode{bind_front} and \tcode{bind_back} template constexpr @\unspec@ bind_front(F&&, Args&&...); + template constexpr @\unspec@ bind_back(F&&, Args&&...); // \ref{func.bind}, bind template struct is_bind_expression; @@ -17907,19 +17908,23 @@ Any exception thrown by the initialization of \tcode{fd}. \end{itemdescr} -\rSec2[func.bind.front]{Function template \tcode{bind_front}} +\rSec2[func.bind.partial]{Function templates \tcode{bind_front} and \tcode{bind_back}} \indexlibraryglobal{bind_front}% +\indexlibraryglobal{bind_back}% \begin{itemdecl} template constexpr @\unspec@ bind_front(F&& f, Args&&... args); +template + constexpr @\unspec@ bind_back(F&& f, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum Within this subclause: \begin{itemize} -\item \tcode{g} is a value of the result of a \tcode{bind_front} invocation, +\item \tcode{g} is a value of +the result of a \tcode{bind_front} or \tcode{bind_back} invocation, \item \tcode{FD} is the type \tcode{decay_t}, \item \tcode{fd} is the target object of \tcode{g}\iref{func.def} of type \tcode{FD}, @@ -17955,7 +17960,15 @@ \pnum \returns A perfect forwarding call wrapper \tcode{g} -with call pattern \tcode{invoke(fd, bound_args..., call_args...)}. +with call pattern: +\begin{itemize} +\item +\tcode{invoke(fd, bound_args..., call_args...)} +for a \tcode{bind_front} invocation, or +\item +\tcode{invoke(fd, call_args..., bound_args...)} +for a \tcode{bind_back} invocation. +\end{itemize} \pnum \throws diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index fbd137a397..a58c53dce7 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -89,5 +89,8 @@ \movedxref{ofstream.assign}{ofstream.swap} \movedxref{fstream.assign}{fstream.swap} +% P2387R3 Pipe support for user-defined range adaptors +\movedxref{func.bind.front}{func.bind.partial} + % Deprecated features. %\deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) From 812b81a6b5214fd12e39b304ba46397e26fb2f86 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 18:26:17 +0100 Subject: [PATCH 116/182] P2440R1 ranges::iota, ranges::shift_left, and ranges::shift_right --- source/algorithms.tex | 134 +++++++++++++++++++++++++++++++++++++----- source/support.tex | 3 +- 2 files changed, 122 insertions(+), 15 deletions(-) diff --git a/source/algorithms.tex b/source/algorithms.tex index c6f00f2971..9f791a1c32 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -641,6 +641,9 @@ template struct in_found_result; + + template + struct out_value_result; } // \ref{alg.nonmodifying}, non-modifying sequence operations @@ -1815,6 +1818,15 @@ shift_left(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, typename iterator_traits::difference_type n); + + namespace ranges { + template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S> + constexpr subrange shift_left(I first, S last, iter_difference_t n); + template<@\libconcept{forward_range}@ R> + requires @\libconcept{permutable}@> + constexpr borrowed_subrange_t shift_left(R&& r, range_difference_t n); + } + template constexpr ForwardIterator shift_right(ForwardIterator first, ForwardIterator last, @@ -1825,6 +1837,14 @@ ForwardIterator first, ForwardIterator last, typename iterator_traits::difference_type n); + namespace ranges { + template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S> + constexpr subrange shift_right(I first, S last, iter_difference_t n); + template<@\libconcept{forward_range}@ R> + requires @\libconcept{permutable}@> + constexpr borrowed_subrange_t shift_right(R&& r, range_difference_t n); + } + // \ref{alg.sorting}, sorting and related operations // \ref{alg.sort}, sorting template @@ -2741,7 +2761,7 @@ ForwardIterator first, ForwardIterator last, Compare comp); - namespace ranges { + namespace ranges { template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr I max_element(I first, S last, Comp comp = {}, Proj proj = {}); @@ -3037,6 +3057,24 @@ return {std::move(in), found}; } }; + + template + struct out_value_result { + [[no_unique_address]] O out; + [[no_unique_address]] T value; + + template + requires @\libconcept{convertible_to}@ && @\libconcept{convertible_to}@ + constexpr operator out_value_result() const & { + return {out, value}; + } + + template + requires @\libconcept{convertible_to}@ && @\libconcept{convertible_to}@ + constexpr operator out_value_result() && { + return {std::move(out), std::move(value)}; + } + }; } \end{codeblock} @@ -6003,14 +6041,20 @@ ForwardIterator shift_left(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, typename iterator_traits::difference_type n); + +template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S> + constexpr subrange ranges::shift_left(I first, S last, iter_difference_t n); +template<@\libconcept{forward_range}@ R> + requires @\libconcept{permutable}@> + constexpr borrowed_subrange_t ranges::shift_left(R&& r, range_difference_t n) \end{itemdecl} \begin{itemdescr} \pnum \expects \tcode{n >= 0} is \tcode{true}. -The type of \tcode{*first} meets -the \oldconcept{MoveAssignable} requirements. +For the overloads in namespace \tcode{std}, +the type of \tcode{*first} meets the \oldconcept{MoveAssignable} requirements. \pnum \effects @@ -6019,14 +6063,22 @@ from position \tcode{first + n + i} into position \tcode{first + i} for each non-negative integer \tcode{i < (last - first) - n}. -In the first overload case, does so in order starting +For the overloads without an \tcode{ExecutionPolicy} template parameter, +does so in order starting from \tcode{i = 0} and proceeding to \tcode{i = (last - first) - n - 1}. \pnum \returns -\tcode{first + (last - first - n)} +Let \exposid{NEW_LAST} be \tcode{first + (last - first - n)} if \tcode{n < last - first}, otherwise \tcode{first}. +\begin{itemize} +\item +\exposid{NEW_LAST} for the overloads in namespace \tcode{std}. +\item +\tcode{\{first, \exposid{NEW_LAST}\}} +for the overloads in namespace \tcode{ranges}. +\end{itemize} \pnum \complexity @@ -6043,15 +6095,21 @@ ForwardIterator shift_right(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, typename iterator_traits::difference_type n); + +template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S> + constexpr subrange ranges::shift_right(I first, S last, iter_difference_t n); +template<@\libconcept{forward_range}@ R> + requires @\libconcept{permutable}@> + constexpr borrowed_subrange_t ranges::shift_right(R&& r, range_difference_t n); \end{itemdecl} \begin{itemdescr} \pnum \expects \tcode{n >= 0} is \tcode{true}. -The type of \tcode{*first} meets -the \oldconcept{MoveAssignable} requirements. -\tcode{ForwardIterator} meets +For the overloads in namespace \tcode{std}, +the type of \tcode{*first} meets the \oldconcept{MoveAssignable} requirements, +and \tcode{ForwardIterator} meets the \oldconcept{BidirectionalIterator} requirements\iref{bidirectional.iterators} or the \oldconcept{ValueSwap\-pable} requirements. @@ -6061,16 +6119,29 @@ Otherwise, moves the element from position \tcode{first + i} into position \tcode{first + n + i} for each non-negative integer \tcode{i < (last - first) - n}. -In the first overload case, if \tcode{ForwardIterator} meets -the \oldconcept{BidirectionalIterator} requirements, -does so in order starting -from \tcode{i = (last - first) - n - 1} and proceeding to \tcode{i = 0}. +Does so in order starting +from \tcode{i = (last - first) - n - 1} and proceeding to \tcode{i = 0} if: +\begin{itemize} +\item +for the overload in namespace \tcode{std} +without an \tcode{ExecutionPolicy} template parameter, +\tcode{Forward\-Iterator} meets the \oldconcept{BidirectionalIterator} requirements, +\item +for the overloads in namespace \tcode{ranges}, +\tcode{I} models \libconcept{bidirectional_iterator}. +\end{itemize} \pnum \returns -\tcode{first + n} -if \tcode{n < last - first}, +Let \exposid{NEW_FIRST} be \tcode{first + n} if \tcode{n < last - first}, otherwise \tcode{last}. +\begin{itemize} +\item +\exposid{NEW_FIRST} for the overloads in namespace \tcode{std}. +\item +\tcode{\{\exposid{NEW_FIRST}, last\}} +for the overloads in namespace \tcode{ranges}. +\end{itemize} \pnum \complexity @@ -9104,6 +9175,18 @@ template constexpr void iota(ForwardIterator first, ForwardIterator last, T value); + namespace ranges { + template + using iota_result = out_value_result; + + template<@\libconcept{input_or_output_iterator}@ O, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ T> + requires @\libconcept{indirectly_writable}@ + constexpr iota_result iota(O first, S last, T value); + + template<@\libconcept{weakly_incrementable}@ T, @\libconcept{output_range}@ R> + constexpr iota_result, T> iota(R&& r, T value); + } + // \ref{numeric.ops.gcd}, greatest common divisor template constexpr common_type_t gcd(M m, N n); @@ -10105,6 +10188,29 @@ Exactly \tcode{last - first} increments and assignments. \end{itemdescr} +\indexlibraryglobal{iota}% +\begin{itemdecl} +template<@\libconcept{input_or_output_iterator}@ O, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ T> + requires @\libconcept{indirectly_writable}@ + constexpr ranges::iota_result ranges::iota(O first, S last, T value); +template<@\libconcept{weakly_incrementable}@ T, @\libconcept{output_range}@ R> + constexpr ranges::iota_result, T> ranges::iota(R&& r, T value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +while (first != last) { + *first = as_const(value); + ++first; + ++value; +} +return {std::move(first), std::move(value)}; +\end{codeblock} +\end{itemdescr} + \rSec2[numeric.ops.gcd]{Greatest common divisor} \indexlibraryglobal{gcd}% diff --git a/source/support.tex b/source/support.tex index 35cbe37ccc..aee6b78e5c 100644 --- a/source/support.tex +++ b/source/support.tex @@ -671,6 +671,7 @@ #define @\defnlibxname{cpp_lib_quoted_string_io}@ 201304L // also in \libheader{iomanip} #define @\defnlibxname{cpp_lib_ranges}@ 202202L // also in \libheader{algorithm}, \libheader{functional}, \libheader{iterator}, \libheader{memory}, \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_iota}@ 202202L // also in \libheader{numeric} #define @\defnlibxname{cpp_lib_ranges_starts_ends_with}@ 202106L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_to_container}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_zip}@ 202110L // also in \libheader{ranges}, \libheader{tuple}, \libheader{utility} @@ -686,7 +687,7 @@ #define @\defnlibxname{cpp_lib_shared_ptr_arrays}@ 201707L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_shared_ptr_weak_type}@ 201606L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_shared_timed_mutex}@ 201402L // also in \libheader{shared_mutex} -#define @\defnlibxname{cpp_lib_shift}@ 201806L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_shift}@ 202202L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_smart_ptr_for_overwrite}@ 202002L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_source_location}@ 201907L // also in \libheader{source_location} #define @\defnlibxname{cpp_lib_span}@ 202002L // also in \libheader{span} From 6fbab5c305ab86239c2ac655fec535547cd87af6 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 31 Jan 2022 23:32:37 +0100 Subject: [PATCH 117/182] P2441R2 views::join_with --- source/ranges.tex | 594 +++++++++++++++++++++++++++++++++++++++++++++ source/support.tex | 1 + 2 files changed, 595 insertions(+) diff --git a/source/ranges.tex b/source/ranges.tex index faafdeb2f8..196ebb341f 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -281,6 +281,18 @@ namespace views { inline constexpr @\unspec@ join = @\unspec@; } + // \ref{range.join.with}, join with view + template + concept @\exposconcept{compatible-joinable-ranges}@ = @\seebelow@; // \expos + + template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> + requires @\libconcept{view}@ && @\libconcept{input_range}@> + && @\libconcept{view}@ + && @\exposconcept{compatible-joinable-ranges}@, Pattern> + class join_with_view; + + namespace views { inline constexpr @\unspec@ join_with = @\unspec@; } + // \ref{range.lazy.split}, lazy split view template concept @\exposconcept{tiny-range}@ = @\seebelow@; // \expos @@ -6066,6 +6078,588 @@ Equivalent to: \tcode{return x.\exposid{outer_} == y.\exposid{end_};} \end{itemdescr} +\rSec2[range.join.with]{Join with view} + +\rSec3[range.join.with.overview]{Overview} + +\pnum +\tcode{join_with_view} takes a \libconcept{view} and a delimiter, and +flattens the \libconcept{view}, +inserting every element of the delimiter +in between elements of the \libconcept{view}. +The delimiter can be a single element or a \libconcept{view} of elements. + +\pnum +\indexlibrarymember{join_with}{views}% +The name \tcode{views::join_with} denotes +a range adaptor object\iref{range.adaptor.object}. +Given subexpressions \tcode{E} and \tcode{F}, +the expression \tcode{views::join_with(E, F)} is expression-equivalent to +\tcode{join_with_view(E, F)}. + +\pnum +\begin{example} +\begin{codeblock} +vector vs = {"the", "quick", "brown", "fox"}; +for (char c : vs | join_with('-')) { + cout << c; +} +\end{codeblock} +The above prints: \tcode{the-quick-brown-fox} +\end{example} + +\rSec3[range.join.with.view]{Class template \tcode{join_with_view}} + +\begin{codeblock} +namespace std::ranges { + template + concept @\defexposconcept{compatible-joinable-ranges}@ = // \expos + @\libconcept{common_with}@, range_value_t

> && + @\libconcept{common_reference_with}@, range_reference_t

> && + @\libconcept{common_reference_with}@, range_rvalue_reference_t

>; + + template + concept @\defexposconcept{bidirectional-common}@ = @\libconcept{bidirectional_range}@ && @\libconcept{common_range}@; // \expos + + template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> + requires @\libconcept{view}@ && @\libconcept{input_range}@> + && @\libconcept{view}@ + && @\exposconcept{compatible-joinable-ranges}@, Pattern> + class join_with_view : public view_interface> { + using @\exposid{InnerRng}@ = range_reference_t; // \expos + + V @\exposid{base_}@ = V(); // \expos + @\exposid{non-propagating-cache}@> @\exposid{inner_}@; // \expos, present only + // when \tcode{!is_reference_v<\exposid{InnerRng}>} + Pattern @\exposid{pattern_}@ = Pattern(); // \expos + + // \ref{range.join.with.iterator}, class template \tcode{join_with_view::\exposid{iterator}} + template struct @\exposid{iterator}@; // \expos + + // \ref{range.join.with.sentinel}, class template \tcode{join_with_view::\exposid{sentinel}} + template struct @\exposid{sentinel}@; // \expos + + public: + join_with_view() + requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; + + constexpr join_with_view(V base, Pattern pattern); + + template + requires @\libconcept{constructible_from}@> && + @\libconcept{constructible_from}@>> + constexpr join_with_view(R&& r, range_value_t<@\exposid{InnerRng}@> e); + + constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + + constexpr auto begin() { + constexpr bool use_const = + @\exposconcept{simple-view}@ && is_reference_v<@\exposid{InnerRng}@> && @\exposconcept{simple-view}@; + return @\exposid{iterator}@{*this, ranges::begin(@\exposid{base_}@)}; + } + constexpr auto begin() const + requires @\libconcept{input_range}@ && + @\libconcept{forward_range}@ && + is_reference_v> { + return @\exposid{iterator}@{*this, ranges::begin(@\exposid{base_}@)}; + } + + constexpr auto end() { + if constexpr (@\libconcept{forward_range}@ && + is_reference_v<@\exposid{InnerRng}@> && @\libconcept{forward_range}@<@\exposid{InnerRng}@> && + @\libconcept{common_range}@ && @\libconcept{common_range}@<@\exposid{InnerRng}@>) + return @\exposid{iterator}@<@\exposconcept{simple-view}@ && @\exposconcept{simple-view}@>{*this, ranges::end(@\exposid{base_}@)}; + else + return @\exposid{sentinel}@<@\exposconcept{simple-view}@ && @\exposconcept{simple-view}@>{*this}; + } + constexpr auto end() const + requires @\libconcept{input_range}@ && @\libconcept{forward_range}@ && + is_reference_v> { + using InnerConstRng = range_reference_t; + if constexpr (@\libconcept{forward_range}@ && @\libconcept{forward_range}@ && + @\libconcept{common_range}@ && common_range) + return @\exposid{iterator}@{*this, ranges::end(@\exposid{base_}@)}; + else + return @\exposid{sentinel}@{*this}; + } + }; + + template + join_with_view(R&&, P&&) -> join_with_view, views::all_t

>; + + template<@\libconcept{input_range}@ R> + join_with_view(R&&, range_value_t>) + -> join_with_view, single_view>>>; +} +\end{codeblock} + +\begin{itemdecl} +constexpr join_with_view(V base, Pattern pattern); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{pattern_} with \tcode{std::move(pattern)}. +\end{itemdescr} + +\begin{itemdecl} +template<@\libconcept{input_range}@ R> + requires @\libconcept{constructible_from}@> && + @\libconcept{constructible_from}@>> +constexpr join_with_view(R&& r, range_value_t<@\exposid{InnerRng}@> e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{views::all(std::forward(r))} and +\exposid{pattern_} with \tcode{views::sin\-gle(std::move(e))}. +\end{itemdescr} + +\rSec3[range.join.with.iterator]{Class template \tcode{join_with_view::\exposid{iterator}}} + +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> + requires @\libconcept{view}@ && @\libconcept{input_range}@> + && @\libconcept{view}@ && @\exposconcept{compatible-joinable-ranges}@, Pattern> + template + class join_with_view::@\exposid{iterator}@ { + using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{InnerBase}@ = range_reference_t; // \expos + using @\exposid{PatternBase}@ = @\exposid{maybe-const}@; // \expos + + using @\exposid{OuterIter}@ = iterator_t<@\exposid{Base}@>; // \expos + using @\exposid{InnerIter}@ = iterator_t<@\exposid{InnerBase}@>; // \expos + using @\exposid{PatternIter}@ = iterator_t<@\exposid{PatternBase}@>; // \expos + + static constexpr bool @\exposid{ref-is-glvalue}@ = is_reference_v<@\exposid{InnerBase}@>; // \expos + + @\exposid{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + @\exposid{OuterIter}@ @\exposid{outer_it_}@ = @\exposid{OuterIter}@(); // \expos + variant<@\exposid{PatternIter}@, @\exposid{InnerIter}@> @\exposid{inner_it_}@; // \expos + + constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> outer); // \expos + constexpr auto&& @\exposid{update-inner}@(const @\exposid{OuterIter}@&); // \expos + constexpr auto&& @\exposid{get-inner}@(const @\exposid{OuterIter}@&); // \expos + constexpr void @\exposid{satisfy}@(); // \expos + + public: + using iterator_concept = @\seebelow@; + using iterator_category = @\seebelow@; // not always present + using value_type = @\seebelow@; + using difference_type = @\seebelow@; + + @\exposid{iterator}@() requires @\libconcept{default_initializable}@<@\exposid{OuterIter}@> = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, @\exposid{OuterIter}@> && + @\libconcept{convertible_to}@, @\exposid{InnerIter}@> && + @\libconcept{convertible_to}@, @\exposid{PatternIter}@>; + + constexpr decltype(auto) operator*() const; + + constexpr @\exposid{iterator}@& operator++(); + constexpr void operator++(int); + constexpr @\exposid{iterator}@ operator++(int) + requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_iterator}@<@\exposid{OuterIter}@> && + @\libconcept{forward_iterator}@<@\exposid{InnerIter}@>; + + constexpr @\exposid{iterator}@& operator--() + requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && + @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>; + constexpr @\exposid{iterator}@ operator--(int) + requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && + @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposid{ref-is-glvalue}@ && @\libconcept{equality_comparable}@<@\exposid{OuterIter}@> && + @\libconcept{equality_comparable}@<@\exposid{InnerIter}@>; + + friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& x) { + using rvalue_reference = common_reference_t< + iter_rvalue_reference_t<@\exposid{InnerIter}@>, + iter_rvalue_reference_t<@\exposid{PatternIter}@>>; + return visit(ranges::iter_move, x.@\exposid{inner_it_}@); + } + + friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{indirectly_swappable}@<@\exposid{InnerIter}@, @\exposid{PatternIter}@> { + visit(ranges::iter_swap, x.@\exposid{inner_it_}@, y.@\exposid{inner_it_}@); + } + }; +} +\end{codeblock} + +\pnum +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +\begin{itemize} +\item +If \exposid{ref-is-glvalue} is \tcode{true}, +\exposid{Base} models \libconcept{bidirectional_range}, and +\exposid{InnerBase} and \exposid{PatternBase} +each model \exposconcept{bidirectional-common}, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, if \exposid{ref-is-glvalue} is \tcode{true} and +\exposid{Base} and \exposid{InnerBase} each model \libconcept{forward_range}, +then \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. +\item +Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. +\end{itemize} + +\pnum +The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +if and only if \exposid{ref-is-glvalue} is \tcode{true}, and +\exposid{Base} and \exposid{InnerBase} each model \libconcept{forward_range}. +In that case, +\tcode{\exposid{iterator}::iterator_category} is defined as follows: + +\begin{itemize} +\item +Let \placeholder{OUTERC} denote +\tcode{iterator_traits<\exposid{OuterIter}>::iterator_category}, +let \placeholder{INNERC} denote +\tcode{iterator_traits<\exposid{InnerIter}>::iterator_category}, and +let \placeholder{PATTERNC} denote +\tcode{iterator_-\linebreak traits<\exposid{PatternIter}>::iterator_category}. +\item +If +\begin{codeblock} +is_lvalue_reference_v, + iter_reference_t<@\exposid{PatternIter}@>>> +\end{codeblock} +is \tcode{false}, +\tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\item +Otherwise, +if \placeholder{OUTERC}, \placeholder{INNERC}, and \placeholder{PATTERNC} +each model \tcode{\libconcept{derived_from}} +and \exposid{InnerBase} and \exposid{PatternBase} +each model \libconcept{common_range}, +\tcode{iterator_cate\-gory} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, +if \placeholder{OUTERC}, \placeholder{INNERC}, and \placeholder{PATTERNC} +each model \tcode{\libconcept{derived_from}}, +\tcode{iterator_category} denotes \tcode{forward_iterator_tag}. +\item +Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\end{itemize} + +\pnum +\tcode{\exposid{iterator}::value_type} denotes the type: +\begin{codeblock} +common_type_t, iter_value_t<@\exposid{PatternIter}@>> +\end{codeblock} + +\pnum +\tcode{\exposid{iterator}::difference_type} denotes the type: +\begin{codeblock} +common_type_t< + iter_difference_t<@\exposid{OuterIter}@>, + iter_difference_t<@\exposid{InnerIter}@>, + iter_difference_t<@\exposid{PatternIter}@>> +\end{codeblock} + +\begin{itemdecl} +constexpr auto&& @\exposid{update-inner}@(const @\exposid{OuterIter}@& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if constexpr (@\exposid{ref-is-glvalue}@) + return *x; +else + return @\exposid{parent_}@->@\exposid{inner_}@.@\exposid{emplace-deref}@(x); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr auto&& @\exposid{get-inner}@(const @\exposid{OuterIter}@& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if constexpr (@\exposid{ref-is-glvalue}@) + return *x; +else + return *@\exposid{parent_}@->@\exposid{inner_}@; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr void @\exposid{satisfy}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +while (true) { + if (@\exposid{inner_it_}@.index() == 0) { + if (std::get<0>(@\exposid{inner_it_}@) != ranges::end(@\exposid{parent_}@->@\exposid{pattern_}@)) + break; + auto&& inner = @\exposid{update-inner}@(@\exposid{outer_it_}@); + @\exposid{inner_it_}@.emplace<1>(ranges::begin(inner)); + } else { + auto&& inner = @\exposid{get-inner}@(@\exposid{outer_it_}@); + if (std::get<1>(@\exposid{inner_it_}@) != ranges::end(inner)) + break; + if (++@\exposid{outer_it_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { + if constexpr (@\exposid{ref-is-glvalue}@) + @\exposid{inner_it_}@.emplace<0>(); + break; + } + @\exposid{inner_it_}@.emplace<0>(ranges::begin(@\exposid{parent_}@->@\exposid{pattern_}@)); + } +} +\end{codeblock} + +\begin{note} +\tcode{join_with_view} iterators use the \exposid{satisfy} function +to skip over empty inner ranges. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +constexpr iterator(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> outer); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{addressof(parent)} and +\exposid{outer_it_} with \tcode{std::move(outer)}. +Then, equivalent to: +\begin{codeblock} +if (@\exposid{outer_it_}@ != ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { + auto&& inner = @\exposid{update-inner}@(@\exposid{outer_it_}@); + @\exposid{inner_it_}@.emplace<1>(ranges::begin(inner)); + @\exposidnc{satisfy}@(); +} +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && convertible_to, @\exposid{OuterIter}@> && + convertible_to, @\exposid{InnerIter}@> && + convertible_to, @\exposid{PatternIter}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{outer_it_} with +\tcode{std::move(i.\exposid{outer_it_})} and +\exposid{parent_} with \tcode{i.\exposid{parent_}}. +Then, equivalent to: +\begin{codeblock} +if (i.@\exposid{inner_it_}@.index() == 0) + @\exposid{inner_it_}@.emplace<0>(std::get<0>(std::move(i.@\exposid{inner_it_}@))); +else + @\exposid{inner_it_}@.emplace<1>(std::get<1>(std::move(i.@\exposid{inner_it_}@))); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr decltype(auto) operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +using reference = + common_reference_t, iter_reference_t<@\exposid{PatternIter}@>>; +return visit([](auto& it) -> reference { return *it; }, @\exposid{inner_it_}@); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +visit([](auto& it){ ++it; }, @\exposid{inner_it_}@); +@\exposidnc{satisfy}@(); +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{++*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int) + requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_iterator}@<@\exposid{OuterIter}@> && @\libconcept{forward_iterator}@<@\exposid{InnerIter}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{iterator}@ tmp = *this; +++*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() + requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && + @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (@\exposid{outer_it_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { + auto&& inner = *--@\exposid{outer_it_}@; + @\exposid{inner_it_}@.emplace<1>(ranges::end(inner)); +} + +while (true) { + if (@\exposid{inner_it_}@.index() == 0) { + auto& it = std::get<0>(@\exposid{inner_it_}@); + if (it == ranges::begin(@\exposid{parent_}@->@\exposid{pattern_}@)) { + auto&& inner = *--@\exposid{outer_it_}@; + @\exposid{inner_it_}@.emplace<1>(ranges::end(inner)); + } else { + break; + } + } else { + auto& it = std::get<1>(@\exposid{inner_it_}@); + auto&& inner = *@\exposid{outer_it_}@; + if (it == ranges::begin(inner)) { + @\exposid{inner_it_}@.emplace<0>(ranges::end(@\exposid{parent_}@->@\exposid{pattern_}@)); + } else { + break; + } + } +} +visit([](auto& it){ --it; }, @\exposid{inner_it_}@); +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) + requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && + @\exposconcept{bidirectional-common}@<@\exposid{InnerBase}@> && @\exposconcept{bidirectional-common}@<@\exposid{PatternBase}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{iterator}@ tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposid{ref-is-glvalue}@ && @\libconcept{equality_comparable}@<@\exposid{OuterIter}@> && + @\libconcept{equality_comparable}@<@\exposid{InnerIter}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return x.@\exposid{outer_it_}@ == y.@\exposid{outer_it_}@ && x.@\exposid{inner_it_}@ == y.@\exposid{inner_it_}@; +\end{codeblock} +\end{itemdescr} + +\rSec3[range.join.with.sentinel]{Class template \tcode{join_with_view::\exposid{sentinel}}} + +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@ V, @\libconcept{forward_range}@ Pattern> + requires @\libconcept{view}@ && @\libconcept{input_range}@> + && @\libconcept{view}@ && @\exposconcept{compatible-joinable-ranges}@, Pattern> + template + class join_with_view::@\exposid{sentinel}@ { + using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos + + constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent); // \expos + + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ s) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; + + template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +}; +\end{codeblock} + +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ s) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{std::move(s.\exposid{end_})}. +\end{itemdescr} + +\begin{itemdecl} +template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{outer_it_} == y.\exposid{end_};} +\end{itemdescr} + \rSec2[range.lazy.split]{Lazy split view} \rSec3[range.lazy.split.overview]{Overview} diff --git a/source/support.tex b/source/support.tex index aee6b78e5c..501b738208 100644 --- a/source/support.tex +++ b/source/support.tex @@ -672,6 +672,7 @@ #define @\defnlibxname{cpp_lib_ranges}@ 202202L // also in \libheader{algorithm}, \libheader{functional}, \libheader{iterator}, \libheader{memory}, \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_iota}@ 202202L // also in \libheader{numeric} +#define @\defnlibxname{cpp_lib_ranges_join_with}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_starts_ends_with}@ 202106L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_to_container}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_zip}@ 202110L // also in \libheader{ranges}, \libheader{tuple}, \libheader{utility} From 4b1c80d860bfcbe61e0a7311a1c72cf7133cc03f Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 2 Feb 2022 23:03:08 +0100 Subject: [PATCH 118/182] P2442R1 Windowing range adaptors: views::chunk and views::slide - Fix return type in description of chunk_view::inner-iterator::operator++. - Add reference to last_ele_ for ambiguous "if present" phrases --- source/ranges.tex | 1636 ++++++++++++++++++++++++++++++++++++++++++++ source/support.tex | 2 + 2 files changed, 1638 insertions(+) diff --git a/source/ranges.tex b/source/ranges.tex index 196ebb341f..4e12ad28e2 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -402,6 +402,32 @@ inline constexpr @\unspec@ adjacent_transform = @\unspec@; inline constexpr auto @\libmember{pairwise_transform}{views}@ = adjacent_transform<2>; } + + // \ref{range.chunk}, chunk view + template<@\libconcept{view}@ V> + requires @\libconcept{input_range}@ + class chunk_view; + + template<@\libconcept{view}@ V> + requires @\libconcept{forward_range}@ + class chunk_view; + + template + inline constexpr bool enable_borrowed_range> = + @\libconcept{forward_range}@ && enable_borrowed_range; + + namespace views { inline constexpr @\unspec@ chunk = @\unspec@; } + + // \ref{range.slide}, slide view + template<@\libconcept{view}@ V> + requires @\libconcept{forward_range}@ + class slide_view; + + template + inline constexpr bool enable_borrowed_range> = + enable_borrowed_range; + + namespace views { inline constexpr @\unspec@ slide = @\unspec@; } } namespace std { @@ -10896,3 +10922,1613 @@ \effects Equivalent to \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} \end{itemdescr} + +\rSec2[range.chunk]{Chunk view} + +\rSec3[range.chunk.overview]{Overview} + +\pnum +\tcode{chunk_view} takes a \libconcept{view} and a number \tcode{N} and +produces a range of \libconcept{view}s +that are \tcode{N}-sized non-overlapping successive chunks of +the elements of the original \libconcept{view}, in order. +The last \libconcept{view} in the range can have fewer than \tcode{N} elements. + +\pnum +\indexlibrarymember{chunk}{views}% +The name \tcode{views::chunk} denotes +a range adaptor object\iref{range.adaptor.object}. +Given subexpressions \tcode{E} and \tcode{N}, +the expression \tcode{views::chunk(E, N)} is expression-equivalent to +\tcode{chunk_view(E, N)}. + +\begin{example} +\begin{codeblock} +vector v = {1, 2, 3, 4, 5}; + +for (auto r : v | views::chunk(2)) { + cout << '['; + auto sep = ""; + for(auto i : r) { + cout << sep << i; + sep = ", "; + } + cout << "] "; +} +\end{codeblock} +The above prints: \tcode{[1, 2] [3, 4] [5]} +\end{example} + +\rSec3[range.chunk.view.input]{\tcode{chunk_view} for input ranges} + +\indexlibrarymember{begin}{chunk_view}% +\indexlibrarymember{end}{chunk_view}% +\indexlibrarymember{size}{chunk_view}% +\begin{codeblock} +namespace std::ranges { + template + constexpr I @\exposidnc{div-ceil}@(I num, I denom) { // \expos + I r = num / denom; + if (num % denom) + ++r; + return r; + } + + template<@\libconcept{view}@ V> + requires @\libconcept{input_range}@ + class chunk_view : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + range_difference_t @\exposid{n_}@ = 0; // \expos + range_difference_t @\exposid{remainder_}@ = 0; // \expos + + @\exposid{non-propagating-cache}@> @\exposid{current_}@; // \expos + + // \ref{range.chunk.outer.iter}, class \tcode{chunk_view::\exposid{outer-iterator}} + class @\exposid{outer-iterator}@; // \expos + + // \ref{range.chunk.inner.iter}, class \tcode{chunk_view::\exposid{inner-iterator}} + class @\exposid{inner-iterator}@; // \expos + + public: + chunk_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit chunk_view(V base, range_difference_t n); + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + + constexpr @\exposid{outer-iterator}@ begin(); + constexpr default_sentinel_t end() noexcept; + + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; + }; + + template + chunk_view(R&& r, range_difference_t) -> chunk_view>; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit chunk_view(V base, range_difference_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{n > 0} is \tcode{true}. + +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{n_} with \tcode{n}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{outer-iterator}@ begin(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +current_ = ranges::begin(base_); +remainder_ = n_; +return @\exposid{outer-iterator}@(*this); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr default_sentinel_t end() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{default_sentinel}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{to-unsigned-like}@(@\exposidnc{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{n_}@)); +\end{codeblock} +\end{itemdescr} + +\rSec3[range.chunk.outer.iter]{Class \tcode{chunk_view::\exposid{outer-iterator}}} + +\indexlibraryglobal{chunk_view::outer-iterator}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\libconcept{input_range}@ + class chunk_view::@\exposid{outer-iterator}@ { + chunk_view* @\exposid{parent_}@; // \expos + + constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent); // \expos + + public: + using iterator_concept = input_iterator_tag; + using difference_type = range_difference_t; + + // \ref{range.chunk.outer.value}, class \tcode{chunk_view::\exposid{outer-iterator}::value_type} + struct value_type; + + @\exposid{outer-iterator}@(@\exposid{outer-iterator}@&&) = default; + @\exposid{outer-iterator}@& operator=(@\exposid{outer-iterator}@&&) = default; + + constexpr value_type operator*() const; + constexpr @\exposid{outer-iterator}@& operator++(); + constexpr void operator++(int); + + friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t); + + friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{outer-iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; + friend constexpr difference_type operator-(const @\exposid{outer-iterator}@& x, default_sentinel_t y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{addressof(parent)}. +\end{itemdescr} + +\begin{itemdecl} +constexpr value_type operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{*this == default_sentinel} is \tcode{false}. + +\pnum +\returns +\tcode{value_type(*\exposid{parent_})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{outer-iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{*this == default_sentinel} is \tcode{false}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +ranges::advance(*@\exposid{parent_}@->@\exposid{current_}@, @\exposid{parent_}@->@\exposid{remainder_}@, ranges::end(@\exposid{parent_}@->@\exposid{base_}@)); +@\exposid{parent_}@->@\exposid{remainder_}@ = @\exposid{parent_}@->@\exposid{n_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{++*this}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return *x.@\exposid{parent_}@->@\exposid{current_}@ == ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) && x.@\exposid{parent_}@->@\exposid{remainder_}@ != 0; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{outer-iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +const auto dist = ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) - *x.@\exposid{parent_}@->@\exposid{current_}@; +if (dist < x.@\exposid{parent_}@->@\exposid{remainder_}@) { + return dist == 0 ? 0 : 1; +} +return @\exposidnc{div-ceil}@(dist - x.@\exposid{parent_}@->@\exposid{remainder_}@, x.@\exposid{parent_}@->@\exposid{n_}@) + 1; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{outer-iterator}@& x, default_sentinel_t y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return -(y - x);} +\end{itemdescr} + +\rSec3[range.chunk.outer.value]{Class \tcode{chunk_view::\exposid{outer-iterator}::value_type}} + +\indexlibraryglobal{chunk_view::outer-iterator::value_type}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\libconcept{input_range}@ + struct chunk_view::@\exposid{outer-iterator}@::value_type : view_interface { + chunk_view* @\exposid{parent_}@; // \expos + + constexpr explicit value_type(chunk_view& parent); // \expos + + public: + constexpr @\exposid{inner-iterator}@ begin() const noexcept; + constexpr default_sentinel_t end() const noexcept; + + constexpr auto size() const + requires @\libconcept{sized_sentinel_for}@, iterator_t>; + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit value_type(chunk_view& parent); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{addressof(parent)}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{inner-iterator}@ begin() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{inner-iterator}(*\exposid{parent_}). +\end{itemdescr} + +\begin{itemdecl} +constexpr default_sentinel_t end() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{default_sentinel}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto size() const + requires @\libconcept{sized_sentinel_for}@, iterator_t>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return ranges::min(@\exposid{parent_}@->@\exposid{remainder_}@, ranges::end(@\exposid{parent_}@->@\exposid{base_}@) - *@\exposid{parent_}@->@\exposid{current_}@); +\end{codeblock} +\end{itemdescr} + +\rSec3[range.chunk.inner.iter]{Class \tcode{chunk_view::\exposid{inner-iterator}}} + +\indexlibraryglobal{chunk_view::inner-iterator}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\libconcept{input_range}@ + class chunk_view::@\exposid{inner-iterator}@ { + chunk_view* @\exposid{parent_}@; // \expos + + constexpr explicit @\exposid{inner-iterator}@(chunk_view& parent) noexcept; // \expos + + public: + using iterator_concept = input_iterator_tag; + using difference_type = range_difference_t; + using value_type = range_value_t; + + @\exposid{inner-iterator}@(@\exposid{inner-iterator}@&&) = default; + @\exposid{inner-iterator}@& operator=(@\exposid{inner-iterator}@&&) = default; + + constexpr const iterator_t& base() const &; + + constexpr range_reference_t operator*() const; + constexpr @\exposid{inner-iterator}@& operator++(); + constexpr void operator++(int); + + friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t); + + friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{inner-iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; + friend constexpr difference_type operator-(const @\exposid{inner-iterator}@& x, default_sentinel_t y) + requires @\libconcept{sized_sentinel_fo}@r, iterator_t>; + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit @\exposid{inner-iterator}@(chunk_view& parent) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{addressof(parent)}. +\end{itemdescr} + +\begin{itemdecl} +constexpr const iterator_t& base() const &; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return *\exposid{parent_}->\exposid{current_};} +\end{itemdescr} + +\begin{itemdecl} +constexpr range_reference_t operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{*this == default_sentinel} is \tcode{false}. + +\pnum +\effects +Equivalent to: \tcode{return **\exposid{parent_}->\exposid{current_};} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{inner-iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{*this == default_sentinel} is \tcode{false}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +++*@\exposid{parent_}@->@\exposid{current_}@; +if (*@\exposid{parent_}@->@\exposid{current_}@ == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) + @\exposid{parent_}@->@\exposid{remainder_}@ = 0; +else + --@\exposid{parent_}@->@\exposid{remainder_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{++*this}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{parent_}->\exposid{remainder_} == 0}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{inner-iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return ranges::min(x.@\exposid{parent_}@->@\exposid{remainder_}@, + ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) - *x.@\exposid{parent_}@->@\exposid{current_}@); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{inner-iterator}@& x, default_sentinel_t y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return -(y - x);} +\end{itemdescr} + +\rSec3[range.chunk.view.fwd]{\tcode{chunk_view} for forward ranges} + +\indexlibrarymember{begin}{chunk_view}% +\indexlibrarymember{end}{chunk_view}% +\indexlibrarymember{size}{chunk_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\libconcept{forward_range}@ + class chunk_view : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + range_difference_t @\exposid{n_}@ = 0; // \expos + + // \ref{range.chunk.fwd.iter}, class template \tcode{chunk_view::\exposid{iterator}} + template class @\exposid{iterator}@; // \expos + + public: + chunk_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit chunk_view(V base, range_difference_t n); + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + + constexpr auto begin() requires (!@\exposconcept{simple-view}@) { + return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); + } + + constexpr auto begin() const requires @\libconcept{forward_range}@ { + return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); + } + + constexpr auto end() requires (!@\exposconcept{simple-view}@) { + if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) { + auto missing = (@\exposid{n_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{n_}@) % @\exposid{n_}@; + return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@), missing); + } else if constexpr (@\libconcept{common_range}@ && !@\libconcept{bidirectional_range}@) { + return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@)); + } else { + return default_sentinel; + } + } + + constexpr auto end() const requires @\libconcept{forward_range}@ { + if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) { + auto missing = (@\exposid{n_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{n_}@) % @\exposid{n_}@; + return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@), missing); + } else if constexpr (@\libconcept{common_range}@ && !@\libconcept{bidirectional_range}@) { + return @\exposid{iterator}@(this, ranges::end(@\exposid{base_}@)); + } else { + return default_sentinel; + } + } + + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit chunk_view(V base, range_difference_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{n > 0} is \tcode{true}. + +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{n_} with \tcode{n}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{n_}@)); +\end{codeblock} +\end{itemdescr} + +\rSec3[range.chunk.fwd.iter]{Class template \tcode{chunk_view::\exposid{iterator}} for forward ranges} + +\indexlibraryglobal{chunk_view::iterator}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\libconcept{forward_range}@ + template + class chunk_view::@\exposid{iterator}@ { + using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + + iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos + sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos + range_difference_t<@\exposid{Base}@> @\exposid{n_}@ = 0; // \expos + range_difference_t<@\exposid{Base}@> @\exposid{missing_}@ = 0; // \expos + + constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current, // \expos + range_difference_t<@\exposid{Base}@> missing = 0); + + public: + using iterator_category = input_iterator_tag; + using iterator_concept = @\seebelow@; + using value_type = decltype(views::take(subrange(@\exposid{current_}@, @\exposid{end_}@), @\exposid{n_}@)); + using difference_type = range_difference_t<@\exposid{Base}@>; + + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> + && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; + + constexpr iterator_t<@\exposid{Base}@> base() const; + + constexpr value_type operator*() const; + constexpr @\exposid{iterator}@& operator++(); + constexpr @\exposid{iterator}@ operator++(int); + + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + + constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + constexpr value_type operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); + + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && + @\libconcept{three_way_comparable}@>; + + friend constexpr iterator operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr iterator operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; + + friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; + }; +} +\end{codeblock} + +\pnum +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +\begin{itemize} +\item +If \exposid{Base} models \libconcept{random_access_range}, +then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, if \exposid{Base} models \libconcept{bidirectional_range}, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. +\end{itemize} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current, + range_difference_t<@\exposid{Base}@> missing = 0); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{current}, +\exposid{end_} with \tcode{ranges::end(parent->\exposid{base_})}, +\exposid{n_} with \tcode{parent\linebreak ->\exposid{n_}}, and +\exposid{missing_} with \tcode{missing}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> + && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}, +\exposid{end_} with \tcode{std::move(i.\exposid{end_})}, +\exposid{n_} with \tcode{i.\exposid{n_}}, and +\exposid{missing_} with \tcode{i.\exposid{missing_}}. +\end{itemdescr} + +\begin{itemdecl} +constexpr iterator_t<@\exposid{Base}@> base() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{current_}. +\end{itemdescr} + +\begin{itemdecl} +constexpr value_type operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}. + +\pnum +\returns +\tcode{views::take(subrange(\exposid{current_}, \exposid{end_}), \exposid{n_})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{n_}@, @\exposid{end_}@); +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +ranges::advance(@\exposid{current_}@, @\exposid{missing_}@ - @\exposid{n_}@); +@\exposid{missing_}@ = 0; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +If \tcode{x} is positive, +\tcode{ranges::distance(\exposid{current_}, \exposid{end_}) > \exposid{n_} * (x - 1)} +is \tcode{true}. +\begin{note} +If \tcode{x} is negative, the \Fundescx{Effects} paragraph implies a precondition. +\end{note} + +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (x > 0) { + @\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{n_}@ * x, @\exposid{end_}@); +} else if (x < 0) { + ranges::advance(@\exposid{current_}@, @\exposid{n_}@ * x + @\exposid{missing_}@); + @\exposid{missing_}@ = 0; +} +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return *this += -x}; +\end{itemdescr} + +\begin{itemdecl} +constexpr value_type operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{*(*this + n)}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} == y.\exposid{current_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} == x.\exposid{end_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} < y.\exposid{current_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return y < x;} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(y < x);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(x < y);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && + @\libconcept{three_way_comparable}@>; +\end{itemdecl} + +\begin{itemdescr} +\returns +\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto r = i; +r += n; +return r; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto r = i; +r -= n; +return r; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{(x.\exposid{current_} - y.\exposid{current_} + x.\exposid{missing_} - y.\exposid{missing_}) / x.\exposid{n_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{div-ceil}(x.\exposid{end_} - x.\exposid{current_}, x.\exposid{n_})}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return -(y - x);} +\end{itemdescr} + +\rSec2[range.slide]{Slide view} + +\rSec3[range.slide.overview]{Overview} + +\pnum +\tcode{slide_view} takes a \libconcept{view} and a number \tcode{N} and +produces a \libconcept{view} +whose $\tcode{M}^\text{th}$ element is a \libconcept{view} over +the $\tcode{M}^\text{th}$ through +$(\tcode{M} + \tcode{N} - 1)^\text{th}$ elements +of the original \libconcept{view}. +If the original \libconcept{view} has fewer than \tcode{N} elements, +the resulting \libconcept{view} is empty. + +\pnum +\indexlibrarymember{slide}{views}% +The name \tcode{views::slide} denotes +a range adaptor object\iref{range.adaptor.object}. +Given subexpressions \tcode{E} and \tcode{N}, +the expression \tcode{views::slide(E, N)} is expression-equivalent to +\tcode{slide_view(E, N)}. +\begin{example} +\begin{codeblock} +vector v = {1, 2, 3, 4}; + +for (auto i : v | views::slide(2)) { + cout << '[' << i[0] << ', ' << i[1] << "] "; // prints: [1, 2] [2, 3] [3, 4] +} +\end{codeblock} +\end{example} + +\rSec3[range.slide.view]{Class template \tcode{slide_view}} + +\indexlibrarymember{begin}{slide_view}% +\indexlibrarymember{end}{slide_view}% +\indexlibrarymember{size}{slide_view}% +\begin{codeblock} +namespace std::ranges { + template + concept @\defexposconcept{slide-caches-nothing}@ = @\libconcept{random_access_range}@ && @\libconcept{sized_range}@; // \expos + + template + concept @\defexposconcept{slide-caches-last}@ = // \expos + !@\exposconcept{slide-caches-nothing}@ && @\libconcept{bidirectional_range}@ && @\libconcept{common_range}@; + + template + concept @\defexposconcept{slide-caches-first}@ = // \expos + !@\exposconcept{slide-caches-nothing}@ && !@\exposconcept{slide-caches-last}@; + + template<@\libconcept{forward_range}@ V> + requires @\libconcept{view}@ + class slide_view : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + range_difference_t @\exposid{n_}@ = 0; // \expos + + // \ref{range.slide.iterator}, class template \tcode{slide_view::\exposid{iterator}} + template class @\exposid{iterator}@; // \expos + + // \ref{range.slide.sentinel}, class \tcode{slide_view::\exposid{sentinel}} + class @\exposid{sentinel}@; // \expos + + public: + slide_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit slide_view(V base, range_difference_t n); + + constexpr auto begin() + requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); + constexpr auto begin() const requires @\exposconcept{slide-caches-nothing}@; + + constexpr auto end() + requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); + constexpr auto end() const requires @\exposconcept{slide-caches-nothing}@; + + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; + }; + + template + slide_view(R&& r, range_difference_t) -> slide_view>; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit slide_view(V base, range_difference_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{n_} with \tcode{n}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto begin() + requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +If \tcode{V} models \exposconcept{slide-caches-first}, +\begin{codeblock} +@\exposid{iterator}@(ranges::begin(@\exposid{base_}@), + ranges::next(ranges::begin(@\exposid{base_}@), @\exposid{n_}@ - 1, ranges::end(@\exposid{base_}@)), @\exposid{n_}@) +\end{codeblock} +\item +Otherwise, \tcode{\exposid{iterator}(ranges::begin(\exposid{base_}), \exposid{n_})}. +\end{itemize} + +\remarks +In order to provide the amortized constant-time complexity +required by the \libconcept{range} concept, +this function caches the result within the \tcode{slide_view} +for use on subsequent calls +when \tcode{V} models \exposconcept{slide-caches-first}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto begin() const requires @\exposconcept{slide-caches-nothing}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{iterator}(ranges::begin(\exposid{base_}), \exposid{n_})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto end() + requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +If \tcode{V} models \exposconcept{slide-caches-nothing}, +\begin{codeblock} +@\exposid{iterator}@(ranges::begin(@\exposid{base_}@) + range_difference_t(size()), @\exposid{n_}@) +\end{codeblock} +\item +Otherwise, if \tcode{V} models \exposconcept{slide-caches-last}, +\begin{codeblock} +@\exposid{iterator}@(ranges::prev(ranges::end(@\exposid{base_}@), @\exposid{n_}@ - 1, ranges::begin(@\exposid{base_}@)), @\exposid{n_}@) +\end{codeblock} +\item +Otherwise, if \tcode{V} models \libconcept{common_range}, +\begin{codeblock} +@\exposid{iterator}@(ranges::end(@\exposid{base_}@), ranges::end(@\exposid{base_}@), @\exposid{n_}@) +\end{codeblock} +\item +Otherwise, \tcode{\exposid{sentinel}(ranges::end(\exposid{base_}))}. +\end{itemize} + +\pnum +\remarks +In order to provide the amortized constant-time complexity +required by the \libconcept{range} concept, +this function caches the result within the \tcode{slide_view} +for use on subsequent calls +when \tcode{V} models \exposconcept{slide-caches-last}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto end() const requires @\exposconcept{slide-caches-nothing}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{begin() + range_difference_t(size())}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto sz = ranges::distance(@\exposid{base_}@) - @\exposid{n_}@ + 1; +if (sz < 0) sz = 0; +return @\exposid{to-unsigned-like}@(sz); +\end{codeblock} +\end{itemdescr} + +\rSec3[range.slide.iterator]{Class template \tcode{slide_view::\exposid{iterator}}} + +\indexlibraryglobal{slide_view::iterator}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V> + requires @\libconcept{view}@ + template + class slide_view::@\exposid{iterator}@ { + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos + iterator_t<@\exposid{Base}@> @\exposid{last_ele_}@ = iterator_t<@\exposid{Base}@>(); // \expos, + // present only if \tcode{\exposid{Base}} models \tcode{\exposconcept{slide-caches-first}} + range_difference_t<@\exposid{Base}@> @\exposid{n_}@ = 0; // \expos + + constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, range_difference_t<@\exposid{Base}@> n) // \expos + requires (!@\exposconcept{slide-caches-first}@<@\exposid{Base}@>); + + constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, iterator_t<@\exposid{Base}@> last_ele, // \expos + range_difference_t<@\exposid{Base}@> n) + requires @\exposconcept{slide-caches-first}@<@\exposid{Base}@>; + + public: + using iterator_category = input_iterator_tag; + using iterator_concept = @\seebelow@; + using value_type = decltype(views::counted(@\exposid{current_}@, @\exposid{n_}@)); + using difference_type = range_difference_t<@\exposid{Base}@>; + + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; + + constexpr auto operator*() const; + constexpr @\exposid{iterator}@& operator++(); + constexpr @\exposid{iterator}@ operator++(int); + + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + + constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + constexpr auto operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && + @\libconcept{three_way_comparable}@>; + + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; + }; +} +\end{codeblock} + +\pnum +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +\begin{itemize} +\item +If \exposid{Base} models \libconcept{random_access_range}, +then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, if \exposid{Base} models \libconcept{bidirectional_range}, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. +\end{itemize} + +\pnum +If the invocation of any non-const member function of \exposid{iterator} +exits via an exception, the \exposid{iterator} acquires a singular value. + +\begin{itemdecl} +constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, range_difference_t<@\exposid{Base}@> n) + requires (!@\exposconcept{slide-caches-first}@<@\exposid{Base}@>); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{current} and +\exposid{n_} with \tcode{n}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, iterator_t<@\exposid{Base}@> last_ele, + range_difference_t<@\exposid{Base}@> n) + requires @\exposconcept{slide-caches-first}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{current}, +\exposid{last_ele_} with \tcode{last_ele}, and +\exposid{n_} with \tcode{n}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})} and +\exposid{n_} with \tcode{i.\exposid{n_}}. +\begin{note} +\tcode{\exposid{iterator}} can only be formed +when \exposid{Base} models \exposconcept{slide-caches-nothing}, +in which case \exposid{last_ele_} is not present. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +constexpr auto operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{views::counted(\exposid{current_}, \exposid{n_})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\exposid{current_} and \exposid{last_ele_} (if present) are incrementable. + +\ensures +\exposid{current_} and \exposid{last_ele_} (if present) are +each equal to \tcode{ranges::next(i)}, +where \tcode{i} is the value of that data member before the call. + +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\exposid{current_} and \exposid{last_ele_} (if present) are decrementable. + +\pnum +\ensures +\exposid{current_} and \exposid{last_ele_} (if present) are +each equal to \tcode{ranges::prev(i)}, +where \tcode{i} is the value of that data member before the call. + +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr iterator& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_} + x} and \tcode{\exposid{last_ele_} + x} (if \exposid{last_ele_} is present) +have well-defined behavior. + +\ensures +\exposid{current_} and \exposid{last_ele_} (if present) are +each equal to \tcode{i + x}, +where \tcode{i} is the value of that data member before the call. + +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_} - x} and \tcode{\exposid{last_ele_} - x} (if \exposid{last_ele_} is present) +have well-defined behavior. + +\ensures +\exposid{current_} and \exposid{last_ele_} (if present) are +each equal to \tcode{i - x}, +where \tcode{i} is the value of that data member before the call. + +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return views::counted(\exposid{current_} + n, @\exposid{n_}@);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \exposid{last_ele_} is present, +\tcode{x.\exposid{last_ele_} == y.\exposid{last_ele_}}; +otherwise, \tcode{x.\exposid{current_} == y.\exposid{cur\-rent_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} < y.\exposid{current_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return y < x;} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(y < x);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(x < y);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && + @\libconcept{three_way_comparable}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto r = i; +r += n; +return r; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto r = i; +r -= n; +return r; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \exposid{last_ele_} is present, +\tcode{x.\exposid{last_ele_} - y.\exposid{last_ele_}}; +otherwise, \tcode{x.\exposid{current_} - y.\exposid{cur\-rent_}}. +\end{itemdescr} + +\rSec3[range.slide.sentinel]{Class \tcode{slide_view::\exposid{sentinel}}} + +\indexlibraryglobal{chunk_view::sentinel}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V> + requires @\libconcept{view}@ + class slide_view::@\exposid{sentinel}@ { + sentinel_t @\exposid{end_}@ = sentinel_t(); // \expos + constexpr explicit @\exposid{sentinel}@(sentinel_t end); // \expos + + public: + @\exposid{sentinel}@() = default; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + friend constexpr range_difference_t + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; + + friend constexpr range_difference_t + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; + }; +} +\end{codeblock} + +\pnum +\begin{note} +\exposid{sentinel} is used +only when \tcode{\exposconcept{slide-caches-first}} is \tcode{true}. +\end{note} + +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(sentinel_t end); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{end}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{last_ele_} == y.\exposid{end_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr range_difference_t + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{last_ele_} - y.\exposid{end_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr range_difference_t + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{y.\exposid{end_} - x.\exposid{last_ele_}}. +\end{itemdescr} diff --git a/source/support.tex b/source/support.tex index 501b738208..5d7f721fb5 100644 --- a/source/support.tex +++ b/source/support.tex @@ -671,8 +671,10 @@ #define @\defnlibxname{cpp_lib_quoted_string_io}@ 201304L // also in \libheader{iomanip} #define @\defnlibxname{cpp_lib_ranges}@ 202202L // also in \libheader{algorithm}, \libheader{functional}, \libheader{iterator}, \libheader{memory}, \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_chunk}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_iota}@ 202202L // also in \libheader{numeric} #define @\defnlibxname{cpp_lib_ranges_join_with}@ 202202L // also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_slide}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_starts_ends_with}@ 202106L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_to_container}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_zip}@ 202110L // also in \libheader{ranges}, \libheader{tuple}, \libheader{utility} From 04fb7cbc7083c733ab71fa8add92d7ea2ec55678 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 5 Feb 2022 23:37:21 +0100 Subject: [PATCH 119/182] P2443R1 views::chunk_by --- source/ranges.tex | 336 +++++++++++++++++++++++++++++++++++++++++++++ source/support.tex | 1 + 2 files changed, 337 insertions(+) diff --git a/source/ranges.tex b/source/ranges.tex index 4e12ad28e2..8c3643eb47 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -428,6 +428,13 @@ enable_borrowed_range; namespace views { inline constexpr @\unspec@ slide = @\unspec@; } + + // \ref{range.chunk.by}, chunk by view + template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@, iterator_t> Pred> + requires @\libconcept{view}@ && is_object_v + class chunk_by_view; + + namespace views { inline constexpr @\unspec@ chunk_by = @\unspec@; } } namespace std { @@ -12532,3 +12539,332 @@ \returns \tcode{y.\exposid{end_} - x.\exposid{last_ele_}}. \end{itemdescr} + +\rSec2[range.chunk.by]{Chunk by view} + +\rSec3[range.chunk.by.overview]{Overview} + +\pnum +\tcode{chunk_by_view} takes a \libconcept{view} and a predicate, and +splits the \libconcept{view} into \tcode{subrange}s +between each pair of adjacent elements +for which the predicate returns \tcode{false}. + +\pnum +\indexlibrarymember{chunk_by}{views}% +The name \tcode{views::chunk_by} denotes +a range adaptor object\iref{range.adaptor.object}. +Given subexpressions \tcode{E} and \tcode{F}, +the expression \tcode{views::chunk_by(E, F)} is expression-equivalent to +\tcode{chunk_by_view(E, F)}. +\begin{example} +\begin{codeblock} +vector v = {1, 2, 2, 3, 0, 4, 5, 2}; + +for (auto r : v | views::chunk_by(ranges::less_equal{})) { + cout << '['; + auto sep = ""; + for(auto i : r) { + cout << sep << i; + sep = ", "; + } + cout << "] "; +} +\end{codeblock} +The above prints: \tcode{[1, 2, 2, 3] [0, 4, 5] [2]} +\end{example} + +\rSec3[range.chunk.by.view]{Class template \tcode{chunk_by_view}} + +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@, iterator_t> Pred> + requires @\libconcept{view}@ && is_object_v + class chunk_by_view : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + @\exposid{copyable-box}@ @\exposid{pred_}@ = Pred(); // \expos + + // \ref{range.chunk.by.iter}, class \tcode{chunk_by_view::\exposid{iterator}} + class @\exposid{iterator}@; // \expos + + public: + chunk_by_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; + constexpr explicit chunk_by_view(V base, Pred pred); + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + + constexpr const Pred& pred() const; + + constexpr @\exposid{iterator}@ begin(); + constexpr auto end(); + + constexpr iterator_t @\exposid{find-next}@(iterator_t); // \expos + constexpr iterator_t @\exposid{find-prev}@(iterator_t) // \expos + requires @\libconcept{bidirectional_range}@; + }; + + template + chunk_by_view(R&&, Pred) -> chunk_by_view, Pred>; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit chunk_by_view(V base, Pred pred); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{pred_} with \tcode{std::move(pred)}. +\end{itemdescr} + +\indexlibrarymember{pred}{chunk_by_view}% +\begin{itemdecl} +constexpr const Pred& pred() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return *\exposid{pred_};} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ begin(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. + +\pnum +\returns +\tcode{\exposid{iterator}(*this, ranges::begin(\exposid{base_}), \exposid{find-next}(ranges::begin(\exposid{base_})))}. + +\pnum +\remarks +In order to provide +the amortized constant-time complexity required by the \libconcept{range} concept, +this function caches the result within the \tcode{chunk_by_view} +for use on subsequent calls. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto end(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(*this, ranges::end(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); +} else { + return default_sentinel; +} +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr iterator_t @\exposid{find-next}@(iterator_t current); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. + +\pnum +\returns +\begin{codeblock} +ranges::next(ranges::adjacent_find(current, ranges::end(@\exposid{base_}@), not_fn(ref(*@\exposid{pred_}@))), + 1, ranges::end(@\exposid{base_}@)) +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr iterator_t @\exposid{find-prev}@(iterator_t current) requires @\libconcept{bidirectional_range}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\begin{itemize} +\item +\tcode{current} is not equal to \tcode{ranges::begin(\exposid{base_})}. +\item +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. +\end{itemize} + +\pnum +\returns +An iterator \tcode{i} +in the range \range{ranges::begin(\exposid{base_})}{current} such that: +\begin{itemize} +\item +\tcode{ranges::adjacent_find(i, current, not_fn(ref(*\exposid{pred_})))} is equal to \tcode{current}; and +\item +if \tcode{i} is not equal to \tcode{ranges::begin(\exposid{base_})}, +then \tcode{bool(invoke(*\exposid{pred_}, *ranges::prev(i), *i))} +is \tcode{false}. +\end{itemize} +\end{itemdescr} + +\rSec3[range.chunk.by.iter]{Class \tcode{chunk_by_view::\exposid{iterator}}} + +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, @\libconcept{indirect_binary_predicate}@, iterator_t> Pred> + requires @\libconcept{view}@ && is_object_v + class chunk_by_view::@\exposid{iterator}@ { + chunk_by_view* @\exposid{parent_}@ = nullptr; // \expos + iterator_t @\exposid{current_}@ = iterator_t(); // \expos + iterator_t @\exposid{next_}@ = iterator_t(); // \expos + + constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t current, // \expos + iterator_t next); + + public: + using value_type = subrange>; + using difference_type = range_difference_t; + using iterator_category = input_iterator_tag; + using iterator_concept = @\seebelow@; + + @\exposid{iterator}@() = default; + + constexpr value_type operator*() const; + constexpr @\exposid{iterator}@& operator++(); + constexpr @\exposid{iterator}@ operator++(int); + + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); + }; +} +\end{codeblock} + +\pnum +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +\begin{itemize} +\item +If \tcode{V} models \libconcept{bidirectional_range}, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. +\end{itemize} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t current, iterator_t next); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{addressof(parent)}, +\exposid{current_} with \tcode{current}, and +\exposid{next_} with \tcode{next}. +\end{itemdescr} + +\begin{itemdecl} +constexpr value_type operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\exposid{current_} is not equal to \exposid{next_}. + +\pnum +\returns +\tcode{subrange(\exposid{current_}, \exposid{next_})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\exposid{current_} is not equal to \exposid{next_}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{current_}@ = @\exposid{next_}@; +@\exposid{next_}@ = @\exposid{parent_}@->@\exposid{find-next}@(@\exposid{current_}@); +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{next_}@ = @\exposid{current_}@; +@\exposid{current_}@ = @\exposid{parent_}@->@\exposid{find-prev}@(@\exposid{next_}@); +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} == y.\exposid{current_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} == x.\exposid{next_}}. +\end{itemdescr} diff --git a/source/support.tex b/source/support.tex index 5d7f721fb5..7d2410874b 100644 --- a/source/support.tex +++ b/source/support.tex @@ -672,6 +672,7 @@ #define @\defnlibxname{cpp_lib_ranges}@ 202202L // also in \libheader{algorithm}, \libheader{functional}, \libheader{iterator}, \libheader{memory}, \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_chunk}@ 202202L // also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_chunk_by}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_iota}@ 202202L // also in \libheader{numeric} #define @\defnlibxname{cpp_lib_ranges_join_with}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_slide}@ 202202L // also in \libheader{ranges} From 7592f9c9cafc71e75992d1a42f45fffad72161b2 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 10 Feb 2022 08:39:13 +0100 Subject: [PATCH 120/182] [depr.meta.types] Add 'is_pod' to library index --- source/future.tex | 1 + 1 file changed, 1 insertion(+) diff --git a/source/future.tex b/source/future.tex index 561272faeb..d9da8342e2 100644 --- a/source/future.tex +++ b/source/future.tex @@ -1385,6 +1385,7 @@ any of the templates defined in this subclause is undefined, unless explicitly permitted by the specification of the corresponding template. +\indexlibraryglobal{is_pod}% \begin{itemdecl} template struct is_pod; \end{itemdecl} From 03567956e848b881e366286855e053ff4c26251f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Sun, 20 Feb 2022 21:42:35 +0000 Subject: [PATCH 121/182] [range.adjacent.transform.iterator] Fix exposition-only formatting. --- source/ranges.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/ranges.tex b/source/ranges.tex index 8c3643eb47..05ff9b91f4 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -10587,7 +10587,7 @@ friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires random_access_range; + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) From d37470de0392f032d96c85610c947918269532a9 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 20 Feb 2022 00:09:56 +0100 Subject: [PATCH 122/182] [lex.name] Rephrase note to avoid upper/lower-case --- source/lex.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/lex.tex b/source/lex.tex index 3576c7406e..c6afecf493 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -760,7 +760,7 @@ if an \grammarterm{identifier} does not conform to Normalization Form C as specified in ISO/IEC 10646. \begin{note} -Upper- and lower-case letters are considered different for all identifiers. +Identifiers are case-sensitive. \end{note} \begin{note} In translation phase 4, From 009ea2725309ec6e3de0eaceabfb7a57df83259a Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 20 Feb 2022 14:28:31 +0100 Subject: [PATCH 123/182] [char.traits.require] Add leading whitespace to descriptive elements Otherwise, those are mistreated by automated checks. --- source/strings.tex | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/source/strings.tex b/source/strings.tex index ef41984dde..67d7f43579 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -134,31 +134,31 @@ \tcode{X::state_type} & & (described in~\ref{char.traits.typedefs}) & compile-time \\ \rowsep \tcode{X::eq(c,d)} & \tcode{bool} & -\returns + \returns whether \tcode{c} is to be treated as equal to \tcode{d}. & constant \\ \rowsep \tcode{X::lt(c,d)} & \tcode{bool} & -\returns + \returns whether \tcode{c} is to be treated as less than \tcode{d}. & constant \\ \rowsep \tcode{X::compare(p,q,n)} & \tcode{int} & -\returns + \returns \tcode{0} if for each \tcode{i} in \tcode{[0,n)}, \tcode{X::eq(p[i],q[i])} is \tcode{true}; else, a negative value if, for some \tcode{j} in \tcode{[0,n)}, \tcode{X::lt(p[j],q[j])} is \tcode{true} and for each \tcode{i} in \tcode{[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 + \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 + \returns the smallest \tcode{q} in \tcode{[p,p+n)} such that \tcode{X::eq(*q,c)} is \tcode{true}, zero otherwise. & linear \\ \rowsep \tcode{X::move(s,p,n)} & \tcode{X::char_type*} & for each \tcode{i} in \tcode{[0,n)}, performs \tcode{X::assign(s[i],p[i])}. Copies correctly even where the ranges \tcode{[p,p+n)} and \tcode{[s,s+n)} overlap.\br \returns \tcode{s}. & linear \\ \rowsep \tcode{X::copy(s,p,n)} & \tcode{X::char_type*} & -\expects + \expects \tcode{p} not in \tcode{[s,s+n)}.\par -\returns + \returns \tcode{s}.\br for each \tcode{i} in \tcode{[0,n)}, performs \tcode{X::assign(s[i],p[i])}. & linear \\ \rowsep @@ -167,30 +167,30 @@ \tcode{X::assign\-(s,n,c)} & \tcode{X::char_type*} & for each \tcode{i} in \tcode{[0,n)}, performs \tcode{X::assign(s[i],c)}.\br -\returns + \returns \tcode{s}. & linear \\ \rowsep \tcode{X::not_eof(e)} & \tcode{int_type} & -\returns + \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 + \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 + \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 + \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 + \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} From efd0cab6f2d11f29f205c15672108f6e20de6010 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 20 Feb 2022 14:28:36 +0100 Subject: [PATCH 124/182] [lib] Add missing \pnum before descriptive elements Also fix the ineffective check script by rewriting the check in straightforward awk. --- source/containers.tex | 7 +++++++ source/iostreams.tex | 1 + source/numerics.tex | 1 + source/ranges.tex | 10 ++++++++++ source/utilities.tex | 2 ++ tools/check-source.sh | 4 +--- 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index 4641fdbdbf..03a553f564 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -518,6 +518,7 @@ \returns \tcode{distance(begin(), end())} for the largest possible container. +\pnum \complexity Constant. \end{itemdescr} @@ -3311,6 +3312,7 @@ \tcode{node} has the previous value of \tcode{nh}, and \tcode{position} points to an element with a key equivalent to \tcode{nh.key()}. +\pnum \complexity Logarithmic. \end{itemdescr} @@ -3562,6 +3564,7 @@ \effects Erases the element pointed to by \tcode{q}. +\pnum \returns An iterator pointing to the element immediately following \tcode{q} prior to the element being erased. @@ -4383,6 +4386,7 @@ \end{itemdecl} \begin{itemdescr} +\pnum \expects \tcode{hasher} and \tcode{key_equal} meet the \oldconcept{DefaultConstructible} requirements. @@ -5073,6 +5077,7 @@ The iterator \tcode{q} is a hint pointing to where the search should start. Implementations are permitted to ignore the hint. +\pnum \ensures \tcode{nh} is empty if insertion succeeds, unchanged if insertion fails. @@ -5147,6 +5152,7 @@ \effects Removes the element pointed to by \tcode{q}. +\pnum \returns A \tcode{node_type} owning that element. @@ -11732,6 +11738,7 @@ \mandates \tcode{is_assignable_v} is \tcode{true}. +\pnum \expects \tcode{value_type} is \oldconcept{Emplace\-Constructible} into \tcode{unordered_map} from \tcode{std::move(k)}, \tcode{std::\brk{}forward(obj)}. diff --git a/source/iostreams.tex b/source/iostreams.tex index 31a2bc1e20..bad291c296 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -15290,6 +15290,7 @@ then \tcode{refresh()} or \tcode{refresh(ec)}, respectively. If an error occurs, the values of any cached attributes are unspecified. +\pnum \throws As specified in~\ref{fs.err.report}. \end{itemdescr} diff --git a/source/numerics.tex b/source/numerics.tex index dcb43333ab..7a2adb52c4 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -7393,6 +7393,7 @@ \expects \range{p}{p + n} is a valid range. +\pnum \effects Constructs a \tcode{valarray} that has length \tcode{n}. The values of the elements of the array are initialized with the diff --git a/source/ranges.tex b/source/ranges.tex index 05ff9b91f4..46d2d9871d 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -9894,6 +9894,7 @@ \end{itemdecl} \begin{itemdescr} +\pnum \effects Equivalent to: \begin{codeblock} @@ -11823,6 +11824,7 @@ \end{itemdecl} \begin{itemdescr} +\pnum \returns \tcode{x.\exposid{current_} <=> y.\exposid{current_}}. \end{itemdescr} @@ -12006,6 +12008,7 @@ Otherwise, \tcode{\exposid{iterator}(ranges::begin(\exposid{base_}), \exposid{n_})}. \end{itemize} +\pnum \remarks In order to provide the amortized constant-time complexity required by the \libconcept{range} concept, @@ -12239,11 +12242,13 @@ \expects \exposid{current_} and \exposid{last_ele_} (if present) are incrementable. +\pnum \ensures \exposid{current_} and \exposid{last_ele_} (if present) are each equal to \tcode{ranges::next(i)}, where \tcode{i} is the value of that data member before the call. +\pnum \returns \tcode{*this}. \end{itemdescr} @@ -12278,6 +12283,7 @@ each equal to \tcode{ranges::prev(i)}, where \tcode{i} is the value of that data member before the call. +\pnum \returns \tcode{*this}. \end{itemdescr} @@ -12308,11 +12314,13 @@ \tcode{\exposid{current_} + x} and \tcode{\exposid{last_ele_} + x} (if \exposid{last_ele_} is present) have well-defined behavior. +\pnum \ensures \exposid{current_} and \exposid{last_ele_} (if present) are each equal to \tcode{i + x}, where \tcode{i} is the value of that data member before the call. +\pnum \returns \tcode{*this}. \end{itemdescr} @@ -12328,11 +12336,13 @@ \tcode{\exposid{current_} - x} and \tcode{\exposid{last_ele_} - x} (if \exposid{last_ele_} is present) have well-defined behavior. +\pnum \ensures \exposid{current_} and \exposid{last_ele_} (if present) are each equal to \tcode{i - x}, where \tcode{i} is the value of that data member before the call. +\pnum \returns \tcode{*this}. \end{itemdescr} diff --git a/source/utilities.tex b/source/utilities.tex index c9a0f03518..700d121e84 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -1138,6 +1138,7 @@ \tcode{is_assignable_v} is \tcode{true}. \end{itemize} +\pnum \effects Assigns \tcode{std::forward(p.first)} to \tcode{first} and \tcode{std::forward(u.second)} to \tcode{second}. @@ -18981,6 +18982,7 @@ \effects Destroys the target object of \tcode{*this}, if any. +\pnum \returns \tcode{*this}. \end{itemdescr} diff --git a/tools/check-source.sh b/tools/check-source.sh index 9ea4895657..19d408efeb 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -198,9 +198,7 @@ done | fail 'subclause without siblings' || failed=1 # Library descriptive macros not immediately preceded by \pnum. for f in $texlibdesc; do - sed -n '/^\\pnum/{h;:x;n;/^\\index/b x;/^\\\(constraints\|mandates\|expects\|effects\|sync\|ensures\|returns\|throws\|complexity\|remarks\|errors\)/{x;/\n/{x;=;p;};d;};/^\\pnum/D;H;b x;}' $f | - # prefix output with filename and line - sed '/^[0-9]\+$/{N;s/\n/:/;}' | sed "s/.*/$f:&/" + awk '/^\\pnum/ { seenpnum=1; next } /^\\index/ { next } /^\\(constraints|mandates|expects|effects|sync|ensures|returns|throws|complexity|remarks|errors)/ { if(seenpnum == 0) { print FILENAME ":" FNR ":" $0 } } { seenpnum=0 }' $f done | fail '\\pnum missing' || failed=1 From ff92c80b70b9cd887512f96e5d5525c20550d12f Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 6 Feb 2022 09:52:01 +0100 Subject: [PATCH 125/182] [iterator.concept.winc] Remove duplicate paragraph This fixes a bad merge between P2393R1 Cleaning up integer-class types and P2321R2 zip. --- source/iterators.tex | 8 -------- 1 file changed, 8 deletions(-) diff --git a/source/iterators.tex b/source/iterators.tex index dea2a48780..c2fe9a94da 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -1472,14 +1472,6 @@ If both \tcode{I1} and \tcode{I2} are signed-integer-like types, then \tcode{common_type_t} is also a signed-integer-like type. -\pnum -For any two integer-like types \tcode{I1} and \tcode{I2}, -at least one of which is an integer-class type, -\tcode{common_type_t} denotes an integer-like type -whose width is not less than that of \tcode{I1} or \tcode{I2}. -If both \tcode{I1} and \tcode{I2} are signed-integer-like types, -then \tcode{common_type_t} is also a signed-integer-like type. - \pnum \tcode{\exposid{is-integer-like}} is \tcode{true} if and only if \tcode{I} is an integer-like type. From a4dfa1f0c46152d3a3399bc32a60fcf11edd4a5d Mon Sep 17 00:00:00 2001 From: Chuanqi Xu <68680648+ChuanqiXu9@users.noreply.github.com> Date: Mon, 21 Feb 2022 07:18:41 +0800 Subject: [PATCH 126/182] [module.interface] Add adjective 'exported' (#5290) It was clear in context that "the declaration" is exported, but it is easier to understand if we restate "an exported declaration". --- source/modules.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/modules.tex b/source/modules.tex index d22202e246..0f0249c09f 100644 --- a/source/modules.tex +++ b/source/modules.tex @@ -266,7 +266,7 @@ \end{example} \pnum -If the declaration is a \grammarterm{using-declaration}\iref{namespace.udecl} +If an exported declaration is a \grammarterm{using-declaration}\iref{namespace.udecl} and is not within a header unit, all entities to which all of the \grammarterm{using-declarator}{s} ultimately refer (if any) From 90ef396f088a4e1730a3f73f3db44d9ad8b872b7 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 1 Feb 2022 13:58:38 +0000 Subject: [PATCH 127/182] [fs.class.directory.iterator.general] Fix grammar --- source/iostreams.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/iostreams.tex b/source/iostreams.tex index bad291c296..09ff08579a 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -15676,7 +15676,7 @@ \pnum The result of calling the \tcode{path()} member of the \tcode{directory_entry} object obtained by dereferencing a \tcode{directory_iterator} is a reference to a \tcode{path} object composed of the directory argument from which the iterator was -constructed with filename of the directory entry appended as if by \tcode{operator/=}. +constructed with the filename of the directory entry appended as if by \tcode{operator/=}. \pnum Directory iteration shall not yield directory entries for the current (dot) From a168ad9baa2d6cea6bf3c34077af69a6c8489dc5 Mon Sep 17 00:00:00 2001 From: "S. B. Tam" Date: Mon, 21 Feb 2022 16:11:20 +0800 Subject: [PATCH 128/182] [range.slide.iterator] Remove `@` in `\tcode` (#5309) --- source/ranges.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/ranges.tex b/source/ranges.tex index 46d2d9871d..4e7c301cf0 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -12355,7 +12355,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return views::counted(\exposid{current_} + n, @\exposid{n_}@);} +Equivalent to: \tcode{return views::counted(\exposid{current_} + n, \exposid{n_});} \end{itemdescr} \begin{itemdecl} From 1155c4a361c446eee4602b7fd2e82eba7a4f8c4f Mon Sep 17 00:00:00 2001 From: languagelawyer Date: Sat, 22 Jan 2022 23:27:49 +0300 Subject: [PATCH 129/182] [temp.res] Move a note outside itemize environment --- source/templates.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/templates.tex b/source/templates.tex index 62d609f6fe..3e4426f160 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -4438,6 +4438,7 @@ is different from the interpretation of the corresponding construct in any actual instantiation of the template. +\end{itemize} \begin{note} This can happen in situations including the following: \begin{itemize} @@ -4470,7 +4471,6 @@ specialization that was not declared when the template was defined. \end{itemize} \end{note} -\end{itemize} Otherwise, no diagnostic shall be issued for a template for which a valid specialization can be generated. From 44c79f59de6c4ea179bacc698272d713e696b117 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sat, 29 Jan 2022 09:37:59 +0100 Subject: [PATCH 130/182] [derivation] Remove 'basic integral type' from footnote Also switch footnote to note. --- source/lib-intro.tex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/lib-intro.tex b/source/lib-intro.tex index bf960caa7e..e772f8b038 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -3175,12 +3175,12 @@ \item Unless explicitly stated otherwise, types with distinct names shall be distinct types. -\begin{footnote} +\begin{note} There is an implicit exception to this rule for types that are -described as synonyms for basic integral types, such as +described as synonyms~(\ref{dcl.typedef}, \ref{namespace.udecl}), such as \tcode{size_t}\iref{support.types} and \tcode{streamoff}\iref{stream.types}. -\end{footnote} +\end{note} \end{itemize} \pnum From 785b0a84e7b0f8108b5140f33494ceff3d0bd282 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 23 Dec 2021 11:40:48 +0100 Subject: [PATCH 131/182] [diff.expr] Replace 'will' with present tense Also annotate the 'void' keyword. --- source/compatibility.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/compatibility.tex b/source/compatibility.tex index d35bda8e90..9b07e9ba52 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -2126,9 +2126,9 @@ } \end{codeblock} -ISO C will accept this usage of pointer to void being assigned +ISO C accepts this usage of pointer to \keyword{void} being assigned to a pointer to object type. -\Cpp{} will not. +\Cpp{} does not. \rationale \Cpp{} tries harder than C to enforce compile-time type safety. \effect From 97a72e1c4f1616f2163d34deafea010d68099a7c Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 5 Dec 2021 21:22:48 +0100 Subject: [PATCH 132/182] [temp.local] Fix type-name interpretation of injected-class-name --- source/templates.tex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/templates.tex b/source/templates.tex index 3e4426f160..07e0896be6 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -4528,7 +4528,8 @@ class template itself. Otherwise, it is a \grammarterm{type-name} equivalent to the \grammarterm{template-name} -followed by the \grammarterm{template-parameter}{s} of the class template +followed by the template argument list~(\ref{temp.decls.general}, +\ref{temp.arg.general}) of the class template enclosed in \tcode{<>}. \pnum From a8e63922a5f049ab2c58a33117913688b8dc096a Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Mon, 21 Feb 2022 20:27:01 +0800 Subject: [PATCH 133/182] [container.gen.reqmts] Replace "Value:" with "Returns:" (#5256) --- source/containers.tex | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index 03a553f564..f9ab3e8128 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -305,7 +305,7 @@ \tcode{const_iterator} for constant \tcode{a}. \pnum -\cvalue +\returns An iterator referring to the first element in the container. \pnum @@ -325,7 +325,7 @@ \tcode{const_iterator} for constant \tcode{a}. \pnum -\cvalue +\returns An iterator which is the past-the-end value for the container. \pnum @@ -344,7 +344,7 @@ \tcode{const_iterator}. \pnum -\cvalue +\returns \tcode{const_cast(a).begin()} \pnum @@ -363,7 +363,7 @@ \tcode{const_iterator}. \pnum -\cvalue +\returns \tcode{const_cast(a).end()} \pnum @@ -404,7 +404,7 @@ Convertible to \tcode{bool}. \pnum -\cvalue +\returns \tcode{equal(a.begin(), a.end(), b.begin(), b.end())} \begin{note} @@ -490,7 +490,7 @@ \tcode{size_type}. \pnum -\cvalue +\returns \tcode{distance(a.begin(), a.end())}, i.e. the number of elements in the container. @@ -534,7 +534,7 @@ Convertible to \tcode{bool}. \pnum -\cvalue +\returns \tcode{a.begin() == a.end()} \pnum @@ -687,7 +687,7 @@ \tcode{const_reverse_iterator} for constant \tcode{a}. \pnum -\cvalue +\returns \tcode{reverse_iterator(end())} \pnum @@ -707,7 +707,7 @@ \tcode{const_reverse_iterator} for constant \tcode{a}. \pnum -\cvalue +\returns \tcode{reverse_iterator(begin())} \pnum @@ -726,7 +726,7 @@ \tcode{const_reverse_iterator}. \pnum -\cvalue +\returns \tcode{\keyword{const_cast}(a).rbegin()} \pnum @@ -745,7 +745,7 @@ \tcode{const_reverse_iterator}. \pnum -\cvalue +\returns \tcode{\keyword{const_cast}(a).rend()} \pnum @@ -840,7 +840,7 @@ \tcode{<} is a total ordering relationship. \pnum -\cvalue +\returns \tcode{lexicographical_compare_three_way(a.begin(), a.end(), b.begin(), b.end(),\newline \exposidnc{synth-three-way})} \begin{note} From d267cde4fcc2c13ef87170d68f94f1ae6e499c23 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 21 Feb 2022 13:51:45 +0100 Subject: [PATCH 134/182] [over.best.ics] Clarify phrasing around user-defined conversion sequence (#5086) This replaces the use of "with" that is popular in mathematical writing with a more common construction. --- source/overloading.tex | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/overloading.tex b/source/overloading.tex index 2b65b63002..fb83380ea9 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -2154,8 +2154,8 @@ \end{example} If the parameter binds directly to the result of applying a conversion function to the argument expression, the implicit -conversion sequence is a user-defined conversion sequence\iref{over.ics.user}, -with the second standard conversion sequence either an identity conversion or, +conversion sequence is a user-defined conversion sequence\iref{over.ics.user} +whose second standard conversion sequence is either an identity conversion or, if the conversion function returns an entity of a type that is a derived class of the parameter type, a derived-to-base conversion. @@ -2319,7 +2319,7 @@ or Conversion rank if \tcode{U} is derived from \tcode{X}. \item Otherwise, the implicit conversion sequence is a user-defined -conversion sequence with the second standard conversion sequence an +conversion sequence whose second standard conversion sequence is an identity conversion. \end{itemize} If multiple constructors are viable but none is better than @@ -2363,8 +2363,8 @@ Otherwise, if the parameter has an aggregate type which can be initialized from the initializer list according to the rules for aggregate initialization\iref{dcl.init.aggr}, the implicit conversion sequence is a -user-defined conversion sequence with the second standard conversion -sequence an identity conversion. +user-defined conversion sequence whose second standard conversion +sequence is an identity conversion. \begin{example} \begin{codeblock} struct A { From 7424b45d8470b8765cdf3b25bcfd9a9a89c0c936 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 3 Jan 2022 22:24:23 +0100 Subject: [PATCH 135/182] [expr] Cleanup for 'discarded-value expression' --- source/expressions.tex | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/source/expressions.tex b/source/expressions.tex index 3962861606..4763fa258c 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -471,15 +471,14 @@ Using an overloaded operator causes a function call; the above covers only operators with built-in meaning. \end{note} -If the (possibly converted) expression is a prvalue, -the temporary materialization conversion\iref{conv.rval} is applied. +The temporary materialization conversion\iref{conv.rval} is applied +if the (possibly converted) expression is a prvalue of object type. \begin{note} -If the expression is an lvalue of -class type, it must have a volatile copy constructor to initialize the -temporary object that is the result object of the lvalue-to-rvalue -conversion. +If the original expression is an lvalue of class type, +it must have a volatile copy constructor to initialize the temporary object +that is the result object of the temporary materialization conversion. \end{note} -The glvalue expression is evaluated and its value is discarded. +The expression is evaluated and its result (if any) is discarded. \rSec1[conv]{Standard conversions} @@ -3904,7 +3903,7 @@ the result refers to the object or the specified base class subobject thereof; otherwise, the lvalue-to-rvalue conversion\iref{conv.lval} is applied to the bit-field and the resulting prvalue is used as the -\grammarterm{expression} of the \keyword{static_cast} for the remainder of this subclause. +operand of the \keyword{static_cast} for the remainder of this subclause. If \tcode{T2} is an inaccessible\iref{class.access} or ambiguous\iref{class.member.lookup} base class of \tcode{T1}, a program that necessitates such a cast is ill-formed. @@ -3944,8 +3943,11 @@ \pnum Any expression can be explicitly converted to type \cv{}~\keyword{void}, -in which case it becomes a discarded-value -expression\iref{expr.prop}. +in which case the operand is a discarded-value expression\iref{expr.prop}. +\begin{note} +Such a \keyword{static_cast} has no result +as it is a prvalue of type \keyword{void}; see~\ref{basic.lval}. +\end{note} \begin{note} However, if the value is in a temporary object\iref{class.temporary}, the destructor for that From b5ce71b34217f9d974e96cc366984cbd5f4b71e6 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 17 Dec 2021 20:31:57 +0100 Subject: [PATCH 136/182] [atomics] Harmonize references to atomics operations tables --- source/atomics.tex | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/source/atomics.tex b/source/atomics.tex index 687f2fec09..b80acf29a9 100644 --- a/source/atomics.tex +++ b/source/atomics.tex @@ -1218,7 +1218,7 @@ \pnum The following operations perform arithmetic computations. -The key, operator, and computation correspondence is identified +The correspondence among key, operator, and computation is specified in \tref{atomic.types.int.comp}. \indexlibrarymember{fetch_add}{atomic_ref<\placeholder{integral}>}% @@ -1340,7 +1340,7 @@ \pnum The following operations perform arithmetic computations. -The key, operator, and computation correspondence are identified +The correspondence among key, operator, and computation is specified in \tref{atomic.types.int.comp}. \indexlibrarymember{fetch_add}{atomic_ref<\placeholder{floating-point}>}% @@ -1448,7 +1448,7 @@ \pnum The following operations perform arithmetic computations. -The key, operator, and computation correspondence is identified +The correspondence among key, operator, and computation is specified in \tref{atomic.types.pointer.comp}. \indexlibrarymember{fetch_add}{atomic_ref}% @@ -2220,7 +2220,9 @@ Descriptions are provided below only for members that differ from the primary template. \pnum -The following operations perform arithmetic computations. The key, operator, and computation correspondence is: +The following operations perform arithmetic computations. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.int.comp}. \begin{floattable} {Atomic arithmetic computations}{atomic.types.int.comp}{lll|lll} @@ -2417,8 +2419,8 @@ \pnum The following operations perform arithmetic addition and subtraction computations. -The key, operator, and computation correspondence are identified in -\tref{atomic.types.int.comp}. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.int.comp}. \indexlibraryglobal{atomic_fetch_add}% \indexlibraryglobal{atomic_fetch_sub}% @@ -2573,8 +2575,9 @@ Descriptions are provided below only for members that differ from the primary template. \pnum -The following operations perform pointer arithmetic. The key, operator, -and computation correspondence is: +The following operations perform pointer arithmetic. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.pointer.comp}. \begin{floattable} {Atomic pointer computations}{atomic.types.pointer.comp}{lll|lll} From ef78018c8d61d79dc9cddc5f4b2d00a7929964fa Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 21 Jan 2022 23:01:25 +0100 Subject: [PATCH 137/182] [std] Replace hyphen with period in labels and add a check. --- source/basic.tex | 2 +- source/classes.tex | 4 ++-- source/expressions.tex | 14 +++++++------- source/intro.tex | 4 ++-- source/support.tex | 12 ++++++------ source/templates.tex | 2 +- source/utilities.tex | 4 ++-- source/xrefdelta.tex | 6 +++++- tools/check-output.sh | 7 +++++++ tools/check-source.sh | 4 ++-- 10 files changed, 35 insertions(+), 24 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 3445633caa..08f66e09a5 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -466,7 +466,7 @@ \pnum \tcode{*\keyword{this}} is odr-used if \keyword{this} appears as a potentially-evaluated expression (including as the result of the implicit transformation in the body of a non-static -member function~(\ref{class.mfct.non-static})). +member function\iref{class.mfct.non.static}). \pnum A virtual member diff --git a/source/classes.tex b/source/classes.tex index e2103e4fe9..c2fac93429 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -555,7 +555,7 @@ of the class. Any other data member or member function is a \defnadj{non-static}{member} (a \defnadj{non-static}{data member} or -\defnadj{non-static}{member function}~(\ref{class.mfct.non-static}), respectively). +\defnadj{non-static}{member function}\iref{class.mfct.non.static}, respectively). \begin{note} A non-static data member of non-reference type is a member subobject of a class object\iref{intro.object}. @@ -913,7 +913,7 @@ Also see~\ref{temp.arg}. \end{note} -\rSec2[class.mfct.non-static]{Non-static member functions}% +\rSec2[class.mfct.non.static]{Non-static member functions}% \indextext{member function!non-static} diff --git a/source/expressions.tex b/source/expressions.tex index 4763fa258c..1b77ea9519 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -1197,7 +1197,7 @@ \pnum \indextext{\idxcode{this}}% The keyword \keyword{this} names a pointer to the object for which an implicit object member -function\iref{class.mfct.non-static} is invoked or a non-static data member's +function\iref{class.mfct.non.static} is invoked or a non-static data member's initializer\iref{class.mem} is evaluated. \pnum @@ -1305,7 +1305,7 @@ \item If $U$ is a non-static data member, $E$ refers to $M$ as a member of the lookup context of the terminal name of $E$ (after any transformation to -a class member access expression\iref{class.mfct.non-static}). +a class member access expression\iref{class.mfct.non.static}). \begin{example} \tcode{o.x} is interpreted as \tcode{o.$u$.x}, where $u$ names the anonymous union member. @@ -1332,7 +1332,7 @@ refers to the member's class \begin{footnote} This also applies when the object expression -is an implicit \tcode{(*\keyword{this})}~(\ref{class.mfct.non-static}). +is an implicit \tcode{(*\keyword{this})}\iref{class.mfct.non.static}. \end{footnote} or a class derived from that class, or @@ -1421,7 +1421,7 @@ see~\ref{expr.prim.id.dtor}. Within the definition of a non-static member function, an \grammarterm{identifier} that names a non-static member is transformed to a -class member access expression~(\ref{class.mfct.non-static}). +class member access expression\iref{class.mfct.non.static}. \end{note} \pnum @@ -1892,7 +1892,7 @@ \pnum The function call operator or operator template is declared -\keyword{const}~(\ref{class.mfct.non-static}) if and only if the +\keyword{const}\iref{class.mfct.non.static} if and only if the \grammarterm{lambda-expression}'s \grammarterm{parameter-declaration-clause} is not followed by \keyword{mutable} and the \grammarterm{lambda-declarator} does not contain @@ -3114,7 +3114,7 @@ \pnum For a call to a non-static member function, the postfix expression shall be an -implicit~(\ref{class.mfct.non-static}, \ref{class.static}) or explicit +implicit~(\ref{class.mfct.non.static}, \ref{class.static}) or explicit class member access\iref{expr.ref} whose \grammarterm{id-expression} is a function member name, or a pointer-to-member expression\iref{expr.mptr.oper} selecting a function member; the call is as a member of @@ -3123,7 +3123,7 @@ member access, the implied object is the one pointed to by \keyword{this}. \begin{note} A member function call of the form \tcode{f()} is interpreted as -\tcode{(*\keyword{this}).f()} (see~\ref{class.mfct.non-static}). +\tcode{(*\keyword{this}).f()} (see~\ref{class.mfct.non.static}). \end{note} \pnum diff --git a/source/intro.tex b/source/intro.tex index 4bde4a91a0..9200f81357 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -283,7 +283,7 @@ message belonging to an \impldef{diagnostic message} subset of the implementation's output messages -\definition{direct-non-list-initialization}{defns.direct-non-list-init} +\definition{direct-non-list-initialization}{defns.direct.non.list.init} \indexdefn{direct-non-list-initialization}% direct-initialization that is not list-initialization @@ -305,7 +305,7 @@ \definition{dynamic type}{defns.dynamic.type.prvalue} \defncontext{prvalue} static type of the prvalue expression -\definition{expression-equivalent}{defns.expression-equivalent} +\definition{expression-equivalent}{defns.expression.equivalent} \defncontext{library} \indexdefn{expression-equivalent}% expressions that all have the same effects, diff --git a/source/support.tex b/source/support.tex index 7d2410874b..3ee53ce66c 100644 --- a/source/support.tex +++ b/source/support.tex @@ -4848,7 +4848,7 @@ a customization point object\iref{customization.point.object}. Given subexpressions \tcode{E} and \tcode{F}, the expression \tcode{strong_order(E, F)} -is expression-equivalent\iref{defns.expression-equivalent} to the following: +is expression-equivalent\iref{defns.expression.equivalent} to the following: \begin{itemize} \item If the decayed types of \tcode{E} and \tcode{F} differ, @@ -4886,7 +4886,7 @@ a customization point object\iref{customization.point.object}. Given subexpressions \tcode{E} and \tcode{F}, the expression \tcode{weak_order(E, F)} -is expression-equivalent\iref{defns.expression-equivalent} to the following: +is expression-equivalent\iref{defns.expression.equivalent} to the following: \begin{itemize} \item If the decayed types of \tcode{E} and \tcode{F} differ, @@ -4938,7 +4938,7 @@ a customization point object\iref{customization.point.object}. Given subexpressions \tcode{E} and \tcode{F}, the expression \tcode{partial_order(E, F)} -is expression-equivalent\iref{defns.expression-equivalent} to the following: +is expression-equivalent\iref{defns.expression.equivalent} to the following: \begin{itemize} \item If the decayed types of \tcode{E} and \tcode{F} differ, @@ -4970,7 +4970,7 @@ denotes a customization point object\iref{customization.point.object}. Given subexpressions \tcode{E} and {F}, the expression \tcode{compare_strong_order_fallback(E, F)} -is expression-equivalent\iref{defns.expression-equivalent} to: +is expression-equivalent\iref{defns.expression.equivalent} to: \begin{itemize} \item If the decayed types of \tcode{E} and \tcode{F} differ, @@ -5002,7 +5002,7 @@ a customization point object\iref{customization.point.object}. Given subexpressions \tcode{E} and \tcode{F}, the expression \tcode{compare_weak_order_fallback(E, F)} -is expression-equivalent\iref{defns.expression-equivalent} to: +is expression-equivalent\iref{defns.expression.equivalent} to: \begin{itemize} \item If the decayed types of \tcode{E} and \tcode{F} differ, @@ -5034,7 +5034,7 @@ a customization point object\iref{customization.point.object}. Given subexpressions \tcode{E} and \tcode{F}, the expression \tcode{compare_partial_order_fallback(E, F)} -is expression-equivalent\iref{defns.expression-equivalent} to: +is expression-equivalent\iref{defns.expression.equivalent} to: \begin{itemize} \item If the decayed types of \tcode{E} and \tcode{F} differ, diff --git a/source/templates.tex b/source/templates.tex index 07e0896be6..5c3b07c319 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -4968,7 +4968,7 @@ template int C::f(); // error: finds both \tcode{A::m} and \tcode{B::m} template int C::g(); // OK, transformation to class member access syntax - // does not occur in the template definition context; see~\ref{class.mfct.non-static} + // does not occur in the template definition context; see~\ref{class.mfct.non.static} \end{codeblock} \end{example} diff --git a/source/utilities.tex b/source/utilities.tex index 700d121e84..1e5903d28b 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -16476,7 +16476,7 @@ A \defn{call pattern} defines the semantics of invoking a perfect forwarding call wrapper. A postfix call performed on a perfect forwarding call wrapper is -expression-equivalent\iref{defns.expression-equivalent} to +expression-equivalent\iref{defns.expression.equivalent} to an expression \tcode{e} determined from its call pattern \tcode{cp} by replacing all occurrences of the arguments of the call wrapper and its state entities @@ -18089,7 +18089,7 @@ is ill-formed. When \tcode{g} is not volatile-qualified, invocation of \tcode{g($\tcode{u}_1$, $\tcode{u}_2$, $\dotsc$, $\tcode{u}_M$)} -is expression-equivalent\iref{defns.expression-equivalent} to +is expression-equivalent\iref{defns.expression.equivalent} to \begin{codeblock} @\placeholdernc{INVOKE}@(static_cast<@$\tcode{V}_\tcode{fd}$@>(@$\tcode{v}_\tcode{fd}$@), static_cast<@$\tcode{V}_1$@>(@$\tcode{v}_1$@), static_cast<@$\tcode{V}_2$@>(@$\tcode{v}_2$@), @$\dotsc$@, static_cast<@$\tcode{V}_N$@>(@$\tcode{v}_N$@)) diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index a58c53dce7..719ca93f9c 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -30,7 +30,7 @@ \movedxref{basic.lookup.classref}{basic.lookup.qual} \movedxref{namespace.memdef}{namespace.def} \movedxref{class.this}{expr.prim.this} -\movedxref{class.mfct.non-static.general}{class.mfct.non-static} +\movedxref{class.mfct.non-static.general}{class.mfct.non.static} \movedxref{class.nested.type}{diff.basic} \movedxref{over.load}{basic.scope.scope} \movedxref{over.dcl}{basic.link} @@ -92,5 +92,9 @@ % P2387R3 Pipe support for user-defined range adaptors \movedxref{func.bind.front}{func.bind.partial} +\movedxref{class.mfct.non-static}{class.mfct.non.static} +\movedxref{defns.direct-non-list-init}{defns.direct.non.list.init} +\movedxref{defns.expression-equivalent}{defns.expression.equivalent} + % Deprecated features. %\deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) diff --git a/tools/check-output.sh b/tools/check-output.sh index 519a839cf4..257ec2fd63 100755 --- a/tools/check-output.sh +++ b/tools/check-output.sh @@ -34,6 +34,13 @@ grep -o '\\see{[^}]*}' < std-generalindex.ind | done | fail || failed=1 rm -f tmp.txt +# Find bad labels +grep newlabel `ls *.aux | grep -v std.aux` | awk -F '{' '{ print $2 }' | + sed 's/}//g' | sed 's/^tab://;s/fig://;s/idx.*\..//' | + grep -v '^[a-z.0-9]*$' | + sed 's/^\(.*\)$/bad label \1/' | + fail || failed=1 + # Find grammar index entries missing a definition cat std-grammarindex.ind | awk 'BEGIN { def=1 } /^ .item/ { if (def==0) { gsub("[{},]", "", item); print item } item=$NF; def=0; next } /hyperindexformat/ { def=1 }' | diff --git a/tools/check-source.sh b/tools/check-source.sh index 19d408efeb..de4caf3c7d 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -153,8 +153,8 @@ grep -n "&[ 0-9a-z_]\+) = delete" $texfiles | fail 'named parameter in deleted special member' || failed=1 # to fix: sed '/= delete/s/&[ 0-9a-z_]\+)/\&)/' -# Bad characters in label. "-" is allowed due to a single remaining offender. -grep -n '^\\rSec.\[[^]]*[^-a-z.0-9][^]]*\]{' $texfiles | +# Bad characters in label. +grep -n '^\\rSec.\[[^]]*[^a-z.0-9][^]]*\]{' $texfiles | fail 'bad character in label' || failed=1 # Use of parenthesized \ref From 58ea575dd9b4a410dcf457b3357bef4a720e1608 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 13 Jan 2022 23:21:05 +0100 Subject: [PATCH 138/182] [function.objects,ranges] Introduce labels for call wrappers In particular, 'term.perfect.forwarding.call.wrapper' and 'term.simple.call.wrapper', and refer to them. --- source/ranges.tex | 6 +++--- source/utilities.tex | 11 ++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/source/ranges.tex b/source/ranges.tex index 4e7c301cf0..201cbec456 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -2249,7 +2249,7 @@ \pnum \returns A range adaptor closure object\iref{range.adaptor.object} \tcode{f} -that is a perfect forwarding call wrapper\iref{func.require} +that is a perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} with the following properties: \begin{itemize} \item @@ -3426,7 +3426,7 @@ Given an additional range adaptor closure object \tcode{D}, the expression \tcode{C | D} produces another range adaptor closure object \tcode{E}. -\tcode{E} is a perfect forwarding call wrapper\iref{func.require} +\tcode{E} is a perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} with the following properties: \begin{itemize} \item @@ -3500,7 +3500,7 @@ let \tcode{BoundArgs} be a pack that denotes \tcode{decay_t...}. The expression \tcode{adaptor(args...)} produces a range adaptor closure object \tcode{f} -that is a perfect forwarding call wrapper with the following properties: +that is a perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} with the following properties: \begin{itemize} \item Its target object is a copy of \tcode{adaptor}. diff --git a/source/utilities.tex b/source/utilities.tex index 1e5903d28b..88a4260a35 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -16461,8 +16461,8 @@ \end{note} \pnum -\indextext{call wrapper!perfect forwarding}% -A \defn{perfect forwarding call wrapper} is +\label{term.perfect.forwarding.call.wrapper}% +A \defnadj{perfect forwarding}{call wrapper} is an argument forwarding call wrapper that forwards its state entities to the underlying call expression. This forwarding step delivers a state entity of type \tcode{T} @@ -16483,6 +16483,7 @@ with references as described in the corresponding forwarding steps. \pnum +\label{term.simple.call.wrapper}% A \defn{simple call wrapper} is a perfect forwarding call wrapper that meets the \oldconcept{CopyConstructible} and \oldconcept{CopyAssignable} requirements and whose copy constructor, move constructor, and assignment operators @@ -17901,7 +17902,7 @@ \pnum \returns -A perfect forwarding call wrapper \tcode{g} +A perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} \tcode{g} with call pattern \tcode{!invoke(fd, call_args...)}. \pnum @@ -17960,7 +17961,7 @@ \pnum \returns -A perfect forwarding call wrapper \tcode{g} +A perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} \tcode{g} with call pattern: \begin{itemize} \item @@ -18199,7 +18200,7 @@ \begin{itemdescr} \pnum \returns -A simple call wrapper\iref{func.def} \tcode{fn} +A simple call wrapper\iref{term.simple.call.wrapper} \tcode{fn} with call pattern \tcode{invoke(pmd, call_args...)}, where \tcode{pmd} is the target object of \tcode{fn} of type \tcode{R T::*} direct-non-list-initialized with \tcode{pm}, and From fa644daccda45ae98c426c77987a93139d380fdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Tue, 22 Feb 2022 00:32:15 +0000 Subject: [PATCH 139/182] [container.reqmts] Fix index entry (escaping `!`) --- source/containers.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/containers.tex b/source/containers.tex index f9ab3e8128..bfbc782dcf 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -420,7 +420,7 @@ \tcode{==} is an equivalence relation. \end{itemdescr} -\indexcont{operator!=}% +\indexcont{operator"!=}% \begin{itemdecl} a != b \end{itemdecl} From 5a33e1a94876ca57c90887f0d43eccc40d855f54 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 11 Nov 2021 22:17:49 +0100 Subject: [PATCH 140/182] [std] Introduce the label 'term.trivially.copyable.type' --- source/basic.tex | 1 + source/containers.tex | 3 ++- source/strings.tex | 3 ++- source/utilities.tex | 5 +++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 08f66e09a5..8579e91696 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4695,6 +4695,7 @@ cv-qualified\iref{basic.type.qualifier} versions of these types are collectively called \defnadjx{scalar}{types}{type}. +\label{term.trivially.copyable.type}% Scalar types, trivially copyable class types\iref{class.prop}, arrays of such types, and cv-qualified versions of these types are collectively called \defnadjx{trivially copyable}{types}{type}. diff --git a/source/containers.tex b/source/containers.tex index bfbc782dcf..8bbfcebd33 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -14429,7 +14429,8 @@ \end{codeblock} \pnum -\tcode{span} is a trivially copyable type\iref{basic.types.general}. +\tcode{span} is +a trivially copyable type\iref{term.trivially.copyable.type}. \pnum \tcode{ElementType} is required to be diff --git a/source/strings.tex b/source/strings.tex index 67d7f43579..12309bd71c 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -4368,7 +4368,8 @@ unless otherwise specified. \pnum -\tcode{basic_string_view} is a trivially copyable type\iref{basic.types.general}. +\tcode{basic_string_view} is +a trivially copyable type\iref{term.trivially.copyable.type}. \rSec3[string.view.cons]{Construction and assignment} diff --git a/source/utilities.tex b/source/utilities.tex index 88a4260a35..e59be6a618 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -16582,7 +16582,8 @@ around a reference to an object or function of type \tcode{T}. \pnum -\tcode{reference_wrapper} is a trivially copyable type\iref{basic.types}. +\tcode{reference_wrapper} is +a trivially copyable type\iref{term.trivially.copyable.type}. \pnum The template parameter \tcode{T} of \tcode{reference_wrapper} @@ -20198,7 +20199,7 @@ \indexlibraryglobal{is_trivially_copyable}% \tcode{template}\br \tcode{struct is_trivially_copyable;} & - \tcode{T} is a trivially copyable type\iref{basic.types} & + \tcode{T} is a trivially copyable type\iref{term.trivially.copyable.type} & \tcode{remove_all_extents_t} shall be a complete type or \cv{}~\keyword{void}. \\ \rowsep From 62ba9c9158a9d5aab7a7ced393341ab97cc5ec59 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 11 Nov 2021 22:22:21 +0100 Subject: [PATCH 141/182] [std] Introduce the label 'term.incomplete.type' --- source/basic.tex | 5 +++-- source/classes.tex | 4 ++-- source/expressions.tex | 8 ++++---- source/lib-intro.tex | 2 +- source/templates.tex | 4 ++-- source/utilities.tex | 4 ++-- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 8579e91696..52deebde47 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -318,7 +318,7 @@ \indextext{type!incomplete}% In the definition of an object, the type of that object shall not be -an incomplete type\iref{basic.types.general}, +an incomplete type\iref{term.incomplete.type}, an abstract class type\iref{class.abstract}, or a (possibly multi-dimensional) array thereof. @@ -4625,8 +4625,9 @@ The size and layout of an instance of an incompletely-defined object type is unknown. \end{footnote} +\label{term.incomplete.type}% Incompletely-defined object types and \cv{}~\keyword{void} are -\defnx{incomplete types}{type!incomplete}\iref{basic.fundamental}. +\defnadjx{incomplete}{types}{type}\iref{basic.fundamental}. \begin{note} Objects cannot be defined to have an incomplete type\iref{basic.def}. \end{note} diff --git a/source/classes.tex b/source/classes.tex index c2fac93429..3501a49d38 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -602,7 +602,7 @@ \pnum A class is considered a completely-defined object -type\iref{basic.types} (or complete type) at the closing \tcode{\}} of +type\iref{term.incomplete.type} (or complete type) at the closing \tcode{\}} of the \grammarterm{class-specifier}. The class is regarded as complete within its complete-class contexts; otherwise it is regarded as incomplete within its own class @@ -689,7 +689,7 @@ \pnum \indextext{class object!member}% The type of a non-static data member shall not be an -incomplete type\iref{basic.types}, +incomplete type\iref{term.incomplete.type}, an abstract class type\iref{class.abstract}, or a (possibly multi-dimensional) array thereof. \begin{note} diff --git a/source/expressions.tex b/source/expressions.tex index 1b77ea9519..700fa8fb19 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -2863,7 +2863,7 @@ \pnum A \grammarterm{type-requirement} that names a class template specialization -does not require that type to be complete\iref{basic.types}. +does not require that type to be complete\iref{term.incomplete.type}. \rSec3[expr.prim.req.compound]{Compound requirements} \indextext{requirement!compound}% @@ -4952,9 +4952,9 @@ \grammarterm{type-id}\iref{dcl.name} or \grammarterm{new-type-id} to which it is applied. The type of that object is the \defnadj{allocated}{type}. \indextext{type!incomplete}% -This type shall be a complete object type, but not an abstract class -type or array -thereof~(\ref{intro.object}, \ref{basic.types}, \ref{class.abstract}). +This type shall be a complete object type\iref{term.incomplete.type}, +but not an abstract class type\iref{class.abstract} or array +thereof\iref{intro.object}. \begin{note} Because references are not objects, references cannot be created by \grammarterm{new-expression}{s}. diff --git a/source/lib-intro.tex b/source/lib-intro.tex index e772f8b038..28af1aa88f 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -2807,7 +2807,7 @@ \required paragraph. \item -If an incomplete type\iref{basic.types} is used as a template +If an incomplete type\iref{term.incomplete.type} is used as a template argument when instantiating a template component or evaluating a concept, unless specifically allowed for that component. \end{itemize} diff --git a/source/templates.tex b/source/templates.tex index 5c3b07c319..a831fc7687 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -1157,7 +1157,7 @@ \end{codeblock} \end{example} \begin{note} -A template type argument can be an incomplete type\iref{basic.types}. +A template type argument can be an incomplete type\iref{term.incomplete.type}. \end{note} \rSec2[temp.arg.nontype]{Template non-type arguments} @@ -5724,7 +5724,7 @@ If the template selected for the specialization\iref{temp.spec.partial.match} has been declared, but not defined, at the point of instantiation\iref{temp.point}, -the instantiation yields an incomplete class type\iref{basic.types}. +the instantiation yields an incomplete class type\iref{term.incomplete.type}. \begin{example} \begin{codeblock} template class X; diff --git a/source/utilities.tex b/source/utilities.tex index e59be6a618..e02e133086 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -10917,7 +10917,7 @@ \begin{itemdescr} \pnum \mandates -\tcode{T} is not an incomplete type\iref{basic.types}. +\tcode{T} is not an incomplete type\iref{term.incomplete.type}. \pnum \returns @@ -10947,7 +10947,7 @@ \begin{itemdescr} \pnum \mandates -\tcode{T} is not an incomplete type\iref{basic.types}. +\tcode{T} is not an incomplete type\iref{term.incomplete.type}. \pnum \returns From 21c807fe66dfa7309f21087436d960772e481c73 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 11 Nov 2021 23:10:36 +0100 Subject: [PATCH 142/182] [std] Introduce the label 'term.scalar.type' --- source/basic.tex | 1 + source/declarations.tex | 2 +- source/utilities.tex | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 52deebde47..8bb0cfb9c4 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4689,6 +4689,7 @@ \indextext{class!trivial}% \indextext{class!trivially copyable}% \indextext{class!standard-layout}% +\label{term.scalar.type}% Arithmetic types\iref{basic.fundamental}, enumeration types, pointer types, pointer-to-member types\iref{basic.compound}, \tcode{std::nullptr_t}, diff --git a/source/declarations.tex b/source/declarations.tex index 5697f1c628..419fa47781 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -4367,7 +4367,7 @@ \item if \tcode{T} -is a scalar type\iref{basic.types}, the +is a scalar type\iref{term.scalar.type}, the object is initialized to the value obtained by converting the integer literal \tcode{0} (zero) to diff --git a/source/utilities.tex b/source/utilities.tex index e02e133086..1025b4068d 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -20115,7 +20115,7 @@ \indexlibraryglobal{is_scalar}% \tcode{template}\br \tcode{struct is_scalar;} & - \tcode{T} is a scalar type\iref{basic.types} & \\ \rowsep + \tcode{T} is a scalar type\iref{term.scalar.type} & \\ \rowsep \indexlibraryglobal{is_compound}% \tcode{template}\br \tcode{struct is_compound;} & From 8d8438ad61af7d936b12f6e8020c1c773ceaf8fd Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 11 Nov 2021 23:12:57 +0100 Subject: [PATCH 143/182] [std] Introduce the label 'term.padding.bits' --- source/atomics.tex | 2 +- source/basic.tex | 1 + source/classes.tex | 2 +- source/declarations.tex | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/source/atomics.tex b/source/atomics.tex index b80acf29a9..a68674b232 100644 --- a/source/atomics.tex +++ b/source/atomics.tex @@ -1918,7 +1918,7 @@ \begin{note} For example, the effect of \tcode{compare_exchange_strong} -on objects without padding bits\iref{basic.types} is +on objects without padding bits\iref{term.padding.bits} is \begin{codeblock} if (memcmp(this, &expected, sizeof(*this)) == 0) memcpy(this, &desired, sizeof(*this)); diff --git a/source/basic.tex b/source/basic.tex index 8bb0cfb9c4..5d825a21f4 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4603,6 +4603,7 @@ The \defnx{value representation}{representation!value} of an object of type \tcode{T} is the set of bits that participate in representing a value of type \tcode{T}. +\label{term.padding.bits}% Bits in the object representation that are not part of the value representation are \defn{padding bits}. For trivially copyable types, the value representation is diff --git a/source/classes.tex b/source/classes.tex index 3501a49d38..fe9232a01c 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -2823,7 +2823,7 @@ If the width of a bit-field is larger than the width of the bit-field's type (or, in case of an enumeration type, of its underlying type), -the extra bits are padding bits\iref{basic.types}. +the extra bits are padding bits\iref{term.padding.bits}. \indextext{allocation!implementation-defined bit-field}% Allocation of bit-fields within a class object is \impldef{allocation of bit-fields within a class object}. diff --git a/source/declarations.tex b/source/declarations.tex index 419fa47781..badf50f8e9 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -4383,7 +4383,7 @@ if \tcode{T} is a (possibly cv-qualified) non-union class type, -its padding bits\iref{basic.types} are initialized to zero bits and +its padding bits\iref{term.padding.bits} are initialized to zero bits and each non-static data member, each non-virtual base class subobject, and, if the object is not a base class subobject, @@ -4394,7 +4394,7 @@ if \tcode{T} is a (possibly cv-qualified) union type, -its padding bits\iref{basic.types} are initialized to zero bits and +its padding bits\iref{term.padding.bits} are initialized to zero bits and the object's first non-static named data member From 915eeeb439df54a928a7ea68561e3dd3507a60a2 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 11 Nov 2021 23:30:26 +0100 Subject: [PATCH 144/182] [std] Introduce the label 'term.object.representation' --- source/basic.tex | 1 + source/classes.tex | 4 ++-- source/expressions.tex | 2 +- source/utilities.tex | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 5d825a21f4..d2ad170e43 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4595,6 +4595,7 @@ \indextext{object!byte copying and|)} \pnum +\label{term.object.representation}% The \defnx{object representation}{representation!object} of an object of type \tcode{T} is the sequence of \placeholder{N} \tcode{\keyword{unsigned} \keyword{char}} objects taken up diff --git a/source/classes.tex b/source/classes.tex index fe9232a01c..89f52d1e54 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -1659,7 +1659,7 @@ \pnum The implicitly-defined copy/move constructor for a union -\tcode{X} copies the object representation\iref{basic.types} of \tcode{X}. +\tcode{X} copies the object representation\iref{term.object.representation} of \tcode{X}. For each object nested within\iref{intro.object} the object that is the source of the copy, a corresponding object $o$ nested within the destination @@ -1984,7 +1984,7 @@ \pnum The implicitly-defined copy assignment operator for a -union \tcode{X} copies the object representation\iref{basic.types} of \tcode{X}. +union \tcode{X} copies the object representation\iref{term.object.representation} of \tcode{X}. If the source and destination of the assignment are not the same object, then for each object nested within\iref{intro.object} the object that is the source of the copy, diff --git a/source/expressions.tex b/source/expressions.tex index 700fa8fb19..08d450de78 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -4826,7 +4826,7 @@ \end{note} \begin{note} See~\ref{intro.memory} for the definition of byte -and~\ref{basic.types} for the definition of object representation. +and~\ref{term.object.representation} for the definition of object representation. \end{note} \pnum diff --git a/source/utilities.tex b/source/utilities.tex index 1025b4068d..4c609bd8eb 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -8764,7 +8764,7 @@ Initializes the first \tcode{M} bit positions to the corresponding bit values in \tcode{val}. \tcode{M} is the smaller of \tcode{N} and the number of bits in the value -representation\iref{basic.types} of \tcode{unsigned long long}. +representation\iref{term.object.representation} of \tcode{unsigned long long}. If \tcode{M < N}, the remaining bit positions are initialized to zero. \end{itemdescr} From a75fb53c69170bcb6fc2b641190ea58af72d9bcc Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 11 Nov 2021 23:47:01 +0100 Subject: [PATCH 145/182] [std] Introduce the label 'term.standard.layout.type' --- source/basic.tex | 4 +++- source/strings.tex | 2 +- source/utilities.tex | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index d2ad170e43..e191c0e964 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4706,7 +4706,9 @@ Scalar types, trivial class types\iref{class.prop}, arrays of such types and cv-qualified versions of these types are collectively called -\defnadjx{trivial}{types}{type}. Scalar types, standard-layout class +\defnadjx{trivial}{types}{type}. +\label{term.standard.layout.type}% +Scalar types, standard-layout class types\iref{class.prop}, arrays of such types and cv-qualified versions of these types are collectively called \defnadjx{standard-layout}{types}{type}. diff --git a/source/strings.tex b/source/strings.tex index 12309bd71c..783a688896 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -5,7 +5,7 @@ \pnum This Clause describes components for manipulating sequences of -any non-array trivial standard-layout\iref{basic.types} type. +any non-array trivial standard-layout\iref{term.standard.layout.type} type. 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 diff --git a/source/utilities.tex b/source/utilities.tex index 4c609bd8eb..9e1ba22476 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -20206,7 +20206,7 @@ \indexlibraryglobal{is_standard_layout}% \tcode{template}\br \tcode{struct is_standard_layout;} & - \tcode{T} is a standard-layout type\iref{basic.types} & + \tcode{T} is a standard-layout type\iref{term.standard.layout.type} & \tcode{remove_all_extents_t} shall be a complete type or \cv{}~\keyword{void}. \\ \rowsep From dd2c51e33377057a063623562530c96d7f3cf804 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 11 Nov 2021 23:50:35 +0100 Subject: [PATCH 146/182] [std] Introduce the label 'term.literal.type' --- source/basic.tex | 1 + source/concepts.tex | 2 +- source/numerics.tex | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index e191c0e964..15f1c79053 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4717,6 +4717,7 @@ are collectively called \defnadjx{implicit-lifetime}{types}{type}. \pnum +\label{term.literal.type}% A type is a \defnadj{literal}{type} if it is: \begin{itemize} \item \cv{}~\keyword{void}; or diff --git a/source/concepts.tex b/source/concepts.tex index 1359fb4608..439f541970 100644 --- a/source/concepts.tex +++ b/source/concepts.tex @@ -637,7 +637,7 @@ \tcode{S} is an expression that exchanges the denoted values. \tcode{S} is a constant expression if \begin{itemize} - \item \tcode{T} is a literal type\iref{basic.types}, + \item \tcode{T} is a literal type\iref{term.literal.type}, \item both \tcode{E1 = std::move(E2)} and \tcode{E2 = std::move(E1)} are constant subexpressions\iref{defns.const.subexpr}, and \item the full-expressions of the initializers in the declarations diff --git a/source/numerics.tex b/source/numerics.tex index 7a2adb52c4..735d2a3238 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -197,7 +197,7 @@ The specializations \tcode{complex}, \tcode{complex}, and -\tcode{complex} are literal types\iref{basic.types}. +\tcode{complex} are literal types\iref{term.literal.type}. \pnum If the result of a function is not mathematically defined or not in From 263ff5d4c2e71e632af35e2e73cb7770cc0c521d Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 11 Nov 2021 23:54:28 +0100 Subject: [PATCH 147/182] [std] Introduce the label 'term.trivial.type' --- source/basic.tex | 1 + source/utilities.tex | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 15f1c79053..ae86174f82 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4703,6 +4703,7 @@ Scalar types, trivially copyable class types\iref{class.prop}, arrays of such types, and cv-qualified versions of these types are collectively called \defnadjx{trivially copyable}{types}{type}. +\label{term.trivial.type}% Scalar types, trivial class types\iref{class.prop}, arrays of such types and cv-qualified versions of these types are collectively called diff --git a/source/utilities.tex b/source/utilities.tex index 9e1ba22476..86ed83ee40 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -20146,7 +20146,7 @@ \pnum For the purpose of defining the templates in this subclause, a function call expression \tcode{declval()} for any type \tcode{T} -is considered to be a trivial~(\ref{basic.types}, \ref{special}) function call +is considered to be a trivial~(\ref{term.trivial.type}, \ref{special}) function call that is not an odr-use\iref{term.odr.use} of \tcode{declval} in the context of the corresponding definition notwithstanding the restrictions of~\ref{declval}. @@ -20192,7 +20192,7 @@ \indexlibraryglobal{is_trivial}% \tcode{template}\br \tcode{struct is_trivial;} & - \tcode{T} is a trivial type\iref{basic.types} & + \tcode{T} is a trivial type\iref{term.trivial.type} & \tcode{remove_all_extents_t} shall be a complete type or \cv{}~\keyword{void}. \\ \rowsep @@ -20406,7 +20406,7 @@ \tcode{is_constructible_v} is \tcode{true} and the variable definition for \tcode{is_constructible}, as defined below, is known to call - no operation that is not trivial~(\ref{basic.types}, \ref{special}). & + no operation that is not trivial~(\ref{term.trivial.type}, \ref{special}). & \tcode{T} and all types in the template parameter pack \tcode{Args} shall be complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep @@ -20441,7 +20441,7 @@ \tcode{struct is_trivially_assignable;} & \tcode{is_assignable_v} is \tcode{true} and the assignment, as defined by \tcode{is_assignable}, is known to call no operation that is not trivial - ~(\ref{basic.types}, \ref{special}). & + ~(\ref{term.trivial.type}, \ref{special}). & \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep @@ -20876,7 +20876,7 @@ \pnum For the purpose of defining the templates in this subclause, a function call expression \tcode{declval()} for any type \tcode{T} -is considered to be a trivial~(\ref{basic.types}, \ref{special}) function call +is considered to be a trivial~(\ref{term.trivial.type}, \ref{special}) function call that is not an odr-use\iref{term.odr.use} of \tcode{declval} in the context of the corresponding definition notwithstanding the restrictions of~\ref{declval}. From 767203e2bc040899406c06793cb71dbddefaf85c Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 12 Nov 2021 13:57:19 +0100 Subject: [PATCH 148/182] [std] Introduce the label 'term.object.type' --- source/basic.tex | 1 + source/lib-intro.tex | 2 +- source/utilities.tex | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index ae86174f82..2ce855f3be 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4684,6 +4684,7 @@ \end{note} \pnum +\label{term.object.type}% An \defn{object type} is a (possibly cv-qualified) type that is not a function type, not a reference type, and not \cv{}~\keyword{void}. diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 28af1aa88f..0685cc3c32 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -1836,7 +1836,7 @@ {allocator.req.var} \topline \lhdr{Variable} & \rhdr{Definition} \\ \capsep -\tcode{T, U, C} & any \cv-unqualified object type\iref{basic.types} \\ \rowsep +\tcode{T, U, C} & any \cv-unqualified object type\iref{term.object.type} \\ \rowsep \tcode{X} & an allocator class for type \tcode{T} \\ \rowsep \tcode{Y} & the corresponding allocator class for type \tcode{U} \\ \rowsep \tcode{XX} & the type \tcode{allocator_traits} \\ \rowsep diff --git a/source/utilities.tex b/source/utilities.tex index 86ed83ee40..2d5173e792 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -16160,7 +16160,7 @@ \pnum A \defnx{function object type}{function object!type} is an object -type\iref{basic.types} that can be the type of the +type\iref{term.object.type} that can be the type of the \grammarterm{postfix-expression} in a function call (\ref{expr.call}, \ref{over.match.call}). \begin{footnote} @@ -20111,7 +20111,7 @@ \indexlibraryglobal{is_object}% \tcode{template}\br \tcode{struct is_object;} & - \tcode{T} is an object type\iref{basic.types} & \\ \rowsep + \tcode{T} is an object type\iref{term.object.type} & \\ \rowsep \indexlibraryglobal{is_scalar}% \tcode{template}\br \tcode{struct is_scalar;} & From e6c0390dda54e296643c8924208476697cacd510 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 12 Nov 2021 14:00:10 +0100 Subject: [PATCH 149/182] [std] Introduce the label 'term.layout.compatible.type' --- source/basic.tex | 4 ++-- source/classes.tex | 2 +- source/utilities.tex | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index 2ce855f3be..b32f487d25 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4751,9 +4751,9 @@ \end{note} \pnum -\indextext{layout-compatible type}% +\label{term.layout.compatible.type}% Two types \cvqual{cv1} \tcode{T1} and \cvqual{cv2} \tcode{T2} are -\defn{layout-compatible} types +\defnadjx{layout-compatible}{types}{type} if \tcode{T1} and \tcode{T2} are the same type, layout-compatible enumerations\iref{dcl.enum}, or layout-compatible standard-layout class types\iref{class.mem}. diff --git a/source/classes.tex b/source/classes.tex index 89f52d1e54..bba2a790c8 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -812,7 +812,7 @@ Two standard-layout unions are layout-compatible if they have the same number of non-static data members and corresponding non-static data members (in any order) have layout-compatible -types\iref{basic.types}. +types\iref{term.layout.compatible.type}. \pnum In a standard-layout union with an active member\iref{class.union} diff --git a/source/utilities.tex b/source/utilities.tex index 2d5173e792..20f6895a1d 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -20814,7 +20814,7 @@ \indexlibraryglobal{is_layout_compatible}% \tcode{template}\br \tcode{struct is_layout_compatible;} & - \tcode{T} and \tcode{U} are layout-compatible\iref{basic.types} & + \tcode{T} and \tcode{U} are layout-compatible\iref{term.layout.compatible.type} & \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep From 0c53beacef2289e4cc4fabbdff99eb3b6c7ae4ad Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 5 Jul 2021 23:16:20 +0200 Subject: [PATCH 150/182] [unique.ptr.single] Rephrase destruction --- source/utilities.tex | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index 20f6895a1d..113e3191aa 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -11525,17 +11525,17 @@ \begin{itemdescr} \pnum -\expects -The expression \tcode{get_deleter()(get())} is well-formed, -has well-defined behavior, and does not throw exceptions. +\effects +Equivalent to: +\tcode{if (get()) get_deleter()(get());} \begin{note} The use of \tcode{default_delete} requires \tcode{T} to be a complete type. \end{note} \pnum -\effects -If \tcode{get() == nullptr} there are no effects. -Otherwise \tcode{get_deleter()(get())}. +\remarks +The behavior is undefined +if the evaluation of \tcode{get_deleter()(get())} throws an exception. \end{itemdescr} \rSec4[unique.ptr.single.asgn]{Assignment} @@ -11728,16 +11728,11 @@ \end{itemdecl} \begin{itemdescr} -\pnum -\expects -The expression \tcode{get_deleter()(get())} is well-formed, -has well-defined behavior, and does not throw exceptions. - \pnum \effects -Assigns \tcode{p} to the stored pointer, and then if and only if the old value of the -stored pointer, \tcode{old_p}, was not equal to \keyword{nullptr}, calls -\tcode{get_deleter()(old_p)}. +Assigns \tcode{p} to the stored pointer, and then, +with the old value of the stored pointer, \tcode{old_p}, +evaluates \tcode{if (old_p) get_deleter()(old_p);} \begin{note} The order of these operations is significant because the call to \tcode{get_deleter()} might destroy \tcode{*this}. @@ -11750,6 +11745,11 @@ The postcondition does not hold if the call to \tcode{get_deleter()} destroys \tcode{*this} since \tcode{this->get()} is no longer a valid expression. \end{note} + +\pnum +\remarks +The behavior is undefined +if the evaluation of \tcode{get_deleter()(old_p)} throws an exception. \end{itemdescr} \indexlibrarymember{swap}{unique_ptr}% From 3acd7a092d2e7549cf4cedd0217f1c168a708999 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 27 Oct 2021 20:54:30 +0200 Subject: [PATCH 151/182] [macros] Allow \keyword and \grammarterm in section headings by disabling all indexing when typesetting the table-of-contents. --- source/declarations.tex | 10 +++++----- source/front.tex | 8 ++++++++ source/macros.tex | 4 ++-- source/statements.tex | 20 ++++++++++---------- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/source/declarations.tex b/source/declarations.tex index badf50f8e9..4989015973 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -559,7 +559,7 @@ \end{codeblock} \end{example} -\rSec2[dcl.typedef]{The \tcode{typedef} specifier}% +\rSec2[dcl.typedef]{The \keyword{typedef} specifier}% \indextext{specifier!\idxcode{typedef}} \pnum @@ -698,14 +698,14 @@ \end{codeblock} \end{example} -\rSec2[dcl.friend]{The \tcode{friend} specifier}% +\rSec2[dcl.friend]{The \keyword{friend} specifier}% \indextext{specifier!\idxcode{friend}} \pnum The \keyword{friend} specifier is used to specify access to class members; see~\ref{class.friend}. -\rSec2[dcl.constexpr]{The \tcode{constexpr} and \tcode{consteval} specifiers}% +\rSec2[dcl.constexpr]{The \keyword{constexpr} and \keyword{consteval} specifiers}% \indextext{specifier!\idxcode{constexpr}} \indextext{specifier!\idxcode{consteval}} @@ -953,7 +953,7 @@ \end{codeblock} \end{example} -\rSec2[dcl.constinit]{The \tcode{constinit} specifier} +\rSec2[dcl.constinit]{The \keyword{constinit} specifier} \indextext{specifier!\idxcode{constinit}} \pnum @@ -982,7 +982,7 @@ \end{codeblock} \end{example} -\rSec2[dcl.inline]{The \tcode{inline} specifier}% +\rSec2[dcl.inline]{The \keyword{inline} specifier}% \indextext{specifier!\idxcode{inline}} \pnum diff --git a/source/front.tex b/source/front.tex index 1961ad74cf..ef9189eb80 100644 --- a/source/front.tex +++ b/source/front.tex @@ -12,6 +12,11 @@ \renewcommand\@pnumwidth{2.5em} \makeatother +% Disable indexing within the table of contents +\newcommand{\indexoff}[2][generalindex]{} +\let\oindex\index +\let\index\indexoff + %% Include table of contents. Do not list "Contents" %% within it (per ISO request) but do include a %% bookmark for it in the PDF. @@ -19,4 +24,7 @@ \pdfbookmark{\contentsname}{toctarget} \hypertarget{toctarget}{\tableofcontents*} +% Restore indexing +\let\index\oindex + \setcounter{tocdepth}{5} diff --git a/source/macros.tex b/source/macros.tex index 89ee44f07a..af55ae9fae 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -226,8 +226,8 @@ \newcommand{\term}[1]{\textit{#1}} \newcommand{\gterm}[1]{\GrammarStylex{#1}} \newcommand{\fakegrammarterm}[1]{\gterm{#1}} -\newcommand{\keyword}[1]{\tcode{#1}\indextext{\idxcode{#1}!keyword}} % macro length: 8 -\newcommand{\grammarterm}[1]{\indexgram{\idxgram{#1}}\gterm{#1}} +\newcommand{\keyword}[1]{\texorpdfstring{\tcode{#1}\protect\indextext{\idxcode{#1}!keyword}}{#1}} % macro length: 8 +\newcommand{\grammarterm}[1]{\texorpdfstring{\protect\indexgram{\idxgram{#1}}\gterm{#1}}{#1}} \newcommand{\grammartermnc}[1]{\indexgram{\idxgram{#1}}\gterm{#1\nocorr}} \newcommand{\regrammarterm}[1]{\textit{#1}} \newcommand{\placeholder}[1]{\textit{#1}} % macro length: 12 diff --git a/source/statements.tex b/source/statements.tex index 68d3aecde5..e384cbd5c1 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -231,7 +231,7 @@ has a block scope\iref{basic.scope.block}. \end{note} -\rSec2[stmt.if]{The \tcode{if} statement}% +\rSec2[stmt.if]{The \keyword{if} statement}% \indextext{statement!\idxcode{if}} \pnum @@ -376,7 +376,7 @@ \keyword{if} \keyword{consteval} statement$_2$ \keyword{else} compound-statement$_1$ \end{ncsimplebnf} -\rSec2[stmt.switch]{The \tcode{switch} statement}% +\rSec2[stmt.switch]{The \keyword{switch} statement}% \indextext{statement!\idxcode{switch}} \pnum @@ -518,7 +518,7 @@ Thus after the \keyword{while} statement, \tcode{i} is no longer in scope. \end{example} -\rSec2[stmt.while]{The \tcode{while} statement}% +\rSec2[stmt.while]{The \keyword{while} statement}% \indextext{statement!\idxcode{while}} \pnum @@ -562,7 +562,7 @@ \end{example} \end{note} -\rSec2[stmt.do]{The \tcode{do} statement}% +\rSec2[stmt.do]{The \keyword{do} statement}% \indextext{statement!\idxcode{do}} \pnum @@ -614,7 +614,7 @@ makes the implied \keyword{while} clause equivalent to \tcode{while(true)}. -\rSec2[stmt.ranged]{The range-based \tcode{for} statement}% +\rSec2[stmt.ranged]{The range-based \keyword{for} statement}% \indextext{statement!range based for@range based \tcode{for}} \pnum @@ -736,7 +736,7 @@ A suspension of a coroutine\iref{expr.await} is not considered to be an exit from a scope. \end{note} -\rSec2[stmt.break]{The \tcode{break} statement}% +\rSec2[stmt.break]{The \keyword{break} statement}% \indextext{statement!\idxcode{break}} \pnum @@ -748,7 +748,7 @@ \keyword{switch} statement; control passes to the statement following the terminated statement, if any. -\rSec2[stmt.cont]{The \tcode{continue} statement}% +\rSec2[stmt.cont]{The \keyword{continue} statement}% \indextext{statement!\idxcode{continue}} \pnum @@ -795,7 +795,7 @@ a \keyword{continue} not contained in an enclosed iteration statement is equivalent to \tcode{goto} \exposid{contin}. -\rSec2[stmt.return]{The \tcode{return} statement}% +\rSec2[stmt.return]{The \keyword{return} statement}% \indextext{\idxcode{return}}% \indextext{function return|see{\tcode{return}}}% @@ -859,7 +859,7 @@ before the destruction of local variables\iref{stmt.jump} of the block enclosing the \tcode{return} statement. -\rSec2[stmt.return.coroutine]{The \tcode{co_return} statement}% +\rSec2[stmt.return.coroutine]{The \keyword{co_return} statement}% \indextext{\idxcode{co_return}}% \indextext{coroutine return|see{\tcode{co_return}}}% @@ -910,7 +910,7 @@ otherwise flowing off the end of a coroutine's \grammarterm{function-body} results in undefined behavior. -\rSec2[stmt.goto]{The \tcode{goto} statement}% +\rSec2[stmt.goto]{The \keyword{goto} statement}% \indextext{statement!\idxcode{goto}} \pnum From 03b9040814ecd548f2de18668df0655ef7b37efb Mon Sep 17 00:00:00 2001 From: "S. B. Tam" Date: Tue, 22 Feb 2022 09:39:37 +0800 Subject: [PATCH 152/182] [version.syn] Remove mention of nonexistent header `` --- source/support.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/support.tex b/source/support.tex index 3ee53ce66c..ac603a4846 100644 --- a/source/support.tex +++ b/source/support.tex @@ -605,7 +605,7 @@ #define @\defnlibxname{cpp_lib_constexpr_vector}@ 201907L // also in \libheader{vector} #define @\defnlibxname{cpp_lib_containers_ranges}@ 202202L // also in \libheader{vector}, \libheader{list}, \libheader{forward_list}, \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set}, - // \libheader{deque}, \libheader{queue}, \libheader{priority_queue}, \libheader{stack}, \libheader{string} + // \libheader{deque}, \libheader{queue}, \libheader{stack}, \libheader{string} #define @\defnlibxname{cpp_lib_coroutine}@ 201902L // also in \libheader{coroutine} #define @\defnlibxname{cpp_lib_destroying_delete}@ 201806L // also in \libheader{new} #define @\defnlibxname{cpp_lib_enable_shared_from_this}@ 201603L // also in \libheader{memory} From 97430e8f867f5b97f79c8064c32dd1bde117198a Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 22 Nov 2021 22:20:16 +0100 Subject: [PATCH 153/182] [allocator.adaptor.members] Fix select_on_container_copy_construction The description was confusing objects and types. --- source/utilities.tex | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index 113e3191aa..69c0c4ad75 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -16126,10 +16126,12 @@ \begin{itemdescr} \pnum \returns -A new \tcode{scoped_allocator_adaptor} object where each allocator \tcode{A} in the -adaptor is initialized from the result of calling -\tcode{allocator_traits::select_on_container_copy_construction()} on the -corresponding allocator in \tcode{*this}. +A new \tcode{scoped_allocator_adaptor} object +where each allocator \tcode{a1} within the adaptor +is initialized with +\tcode{allocator_traits::select_on_container_copy_construction(a2)}, +where \tcode{A1} is the type of \tcode{a1} and +\tcode{a2} is the corresponding allocator in \tcode{*this}. \end{itemdescr} \rSec2[scoped.adaptor.operators]{Operators} From 2878217d9b127aeb63b930aee4ecba3b54f5b0c3 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 14 Dec 2021 23:41:27 +0100 Subject: [PATCH 154/182] [std] Extend \iref to accept a list of cross-references --- source/algorithms.tex | 12 +++--- source/basic.tex | 74 ++++++++++++++++++------------------- source/classes.tex | 58 ++++++++++++++--------------- source/compatibility.tex | 3 +- source/concepts.tex | 5 +-- source/containers.tex | 2 +- source/declarations.tex | 73 ++++++++++++++++++------------------- source/exceptions.tex | 16 ++++---- source/expressions.tex | 79 +++++++++++++++++++--------------------- source/future.tex | 5 ++- source/grammar.tex | 2 +- source/iostreams.tex | 26 ++++++------- source/iterators.tex | 8 ++-- source/lex.tex | 4 +- source/lib-intro.tex | 23 ++++++------ source/limits.tex | 2 +- source/locales.tex | 4 +- source/macros.tex | 15 +++++++- source/modules.tex | 6 +-- source/overloading.tex | 27 ++++++-------- source/preprocessor.tex | 2 +- source/regex.tex | 4 +- source/statements.tex | 2 +- source/support.tex | 15 +++++--- source/templates.tex | 26 ++++++------- source/threads.tex | 3 +- source/utilities.tex | 23 ++++++------ 27 files changed, 257 insertions(+), 262 deletions(-) diff --git a/source/algorithms.tex b/source/algorithms.tex index 9f791a1c32..4352a1fedd 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -3333,7 +3333,7 @@ \pnum \mandates The type \tcode{Size} is convertible -to an integral type~(\ref{conv.integral}, \ref{class.conv}). +to an integral type\iref{conv.integral,class.conv}. \pnum \expects @@ -3373,7 +3373,7 @@ \pnum \mandates The type \tcode{Size} is convertible -to an integral type~(\ref{conv.integral}, \ref{class.conv}). +to an integral type\iref{conv.integral,class.conv}. \pnum \expects @@ -4245,7 +4245,7 @@ \pnum \mandates The type \tcode{Size} -is convertible to an integral type~(\ref{conv.integral}, \ref{class.conv}). +is convertible to an integral type\iref{conv.integral,class.conv}. \pnum \returns @@ -4485,7 +4485,7 @@ \pnum \mandates The type \tcode{Size} is convertible -to an integral type~(\ref{conv.integral}, \ref{class.conv}). +to an integral type\iref{conv.integral,class.conv}. \pnum \effects @@ -5226,7 +5226,7 @@ The expression \tcode{value} is writable\iref{iterator.requirements.general} to the output iterator. The type \tcode{Size} is convertible -to an integral type~(\ref{conv.integral}, \ref{class.conv}). +to an integral type\iref{conv.integral,class.conv}. \pnum \effects @@ -5280,7 +5280,7 @@ \pnum \mandates \tcode{Size} is convertible -to an integral type~(\ref{conv.integral}, \ref{class.conv}). +to an integral type\iref{conv.integral,class.conv}. \pnum \effects diff --git a/source/basic.tex b/source/basic.tex index b32f487d25..fcc799b661 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -50,7 +50,7 @@ \item \grammarterm{declaration}, \grammarterm{block-declaration}, or -\grammarterm{member-declaration} (\ref{dcl.pre}, \ref{class.mem}), +\grammarterm{member-declaration}\iref{dcl.pre,class.mem}, \item \grammarterm{init-declarator}\iref{dcl.decl}, \item @@ -178,7 +178,7 @@ \item \indextext{declaration!static member@\tcode{static} member}% it declares a non-inline static data member in a class -definition~(\ref{class.mem}, \ref{class.static}), +definition\iref{class.mem,class.static}, \item it declares a static data member outside a class definition and the variable was defined within the class with the \keyword{constexpr} @@ -404,7 +404,7 @@ \item A function is named by an expression or conversion if it is the selected member - of an overload set~(\ref{basic.lookup}, \ref{over.match}, \ref{over.over}) + of an overload set\iref{basic.lookup,over.match,over.over} in an overload resolution performed as part of forming that expression or conversion, unless it is a pure virtual function and either @@ -413,7 +413,7 @@ the expression forms a pointer to member\iref{expr.unary.op}. \begin{note} This covers - taking the address of functions~(\ref{conv.func}, \ref{expr.unary.op}), + taking the address of functions\iref{conv.func,expr.unary.op}, calls to named functions\iref{expr.call}, operator overloading\iref{over}, user-defined conversions\iref{class.conv.fct}, @@ -597,8 +597,8 @@ a glvalue referring to an object of type \tcode{T}\iref{conv.lval}, or \item an expression is converted (either implicitly or explicitly) to -type \tcode{T} (\ref{conv}, \ref{expr.type.conv}, -\ref{expr.dynamic.cast}, \ref{expr.static.cast}, \ref{expr.cast}), or +type \tcode{T}\iref{conv,expr.type.conv, +expr.dynamic.cast,expr.static.cast,expr.cast}, or \item an expression that is not a null pointer constant, and has type other than \cv{}~\tcode{\keyword{void}*}, is converted to the type pointer to \tcode{T} or reference to \tcode{T} using a standard conversion\iref{conv}, @@ -690,7 +690,7 @@ is subject to the requirements described in this paragraph (recursively). \item If \tcode{D} is a class with an implicitly-declared -constructor (\ref{class.default.ctor}, \ref{class.copy.ctor}), +constructor\iref{class.default.ctor,class.copy.ctor}, it is as if the constructor was implicitly defined in every translation unit where it is odr-used, and the implicit definition in every translation unit shall call the same @@ -1190,7 +1190,7 @@ Each \begin{itemize} \item -selection or iteration statement (\ref{stmt.select}, \ref{stmt.iter}), +selection or iteration statement\iref{stmt.select,stmt.iter}, \item substatement of such a statement, \item @@ -1400,7 +1400,7 @@ if the declarations found by name lookup do not all denote the same entity, \indextext{lookup!ambiguous}% they are \defn{ambiguous} and the program is ill-formed. -Overload resolution~(\ref{over.match}, \ref{over.over}) +Overload resolution\iref{over.match,over.over} takes place after name lookup has succeeded. The access rules\iref{class.access} are considered only once name lookup and function overload resolution (if applicable) have succeeded. Only after @@ -1698,7 +1698,7 @@ \begin{note} Even if the result of name lookup is unambiguous, use of a name found in multiple subobjects might still be -ambiguous~(\ref{conv.mem}, \ref{expr.ref}, \ref{class.access.base}). +ambiguous\iref{conv.mem,expr.ref,class.access.base}. \end{note} \begin{example} \begin{codeblock} @@ -2025,7 +2025,7 @@ have the same innermost enclosing non-inline namespace scope as a declaration of an associated entity attached to \tcode{M}\iref{basic.link}. \end{itemize} -If the lookup is for a dependent name (\ref{temp.dep}, \ref{temp.dep.candidate}), +If the lookup is for a dependent name\iref{temp.dep,temp.dep.candidate}, the above lookup is also performed from each point in the instantiation context\iref{module.context} of the lookup, additionally ignoring any declaration that @@ -2703,7 +2703,7 @@ \pnum Two declarations of entities declare the same entity if, considering declarations of unnamed types to introduce their names -for linkage purposes, if any (\ref{dcl.typedef}, \ref{dcl.enum}), +for linkage purposes, if any\iref{dcl.typedef,dcl.enum}, they correspond\iref{basic.scope.scope}, have the same target scope that is not a function or template parameter scope, and either @@ -2716,8 +2716,8 @@ they both declare names with external linkage. \end{itemize} \begin{note} -There are other circumstances in which declarations declare the same entity -(\ref{dcl.link}, \ref{temp.type}, \ref{temp.spec.partial}). +There are other circumstances in which declarations declare the same entity% +\iref{dcl.link,temp.type,temp.spec.partial}. \end{note} \pnum @@ -3072,7 +3072,7 @@ by an operation that implicitly creates objects (see below), when implicitly changing the active member of a union\iref{class.union}, or -when a temporary object is created~(\ref{conv.rval}, \ref{class.temporary}). +when a temporary object is created\iref{conv.rval,class.temporary}. An object occupies a region of storage in its period of construction\iref{class.cdtor}, throughout its lifetime\iref{basic.life}, @@ -3327,8 +3327,8 @@ implicitly creates objects in the returned region of storage and returns a pointer to a suitable created object. \begin{note} -Some functions in the \Cpp{} standard library implicitly create objects -(\ref{allocator.traits.members}, \ref{c.malloc}, \ref{cstring.syn}, \ref{bit.cast}). +Some functions in the \Cpp{} standard library implicitly create objects% +\iref{allocator.traits.members,c.malloc,cstring.syn,bit.cast}. \end{note} \indextext{object model|)} @@ -3351,7 +3351,7 @@ \end{itemize} except that if the object is a union member or subobject thereof, its lifetime only begins if that union member is the -initialized member in the union~(\ref{dcl.init.aggr}, \ref{class.base.init}), +initialized member in the union\iref{dcl.init.aggr,class.base.init}, or as described in \ref{class.union} and \ref{class.copy.ctor}, and except as described in \ref{allocator.members}. The lifetime of an object \placeholder{o} of type \tcode{T} ends when: @@ -3639,8 +3639,8 @@ \item the right operand of a comma expression\iref{expr.comma}, \item - the operand of a cast or conversion~(\ref{conv.integral}, - \ref{expr.type.conv}, \ref{expr.static.cast}, \ref{expr.cast}) + the operand of a cast or conversion\iref{conv.integral, + expr.type.conv,expr.static.cast,expr.cast} to an unsigned ordinary character type or \tcode{std::byte} type\iref{cstddef.syn}, or \item @@ -3743,7 +3743,7 @@ \end{itemize} have \defn{static storage duration}. The storage for these entities lasts for the duration of the -program~(\ref{basic.start.static}, \ref{basic.start.term}). +program\iref{basic.start.static,basic.start.term}. \pnum If a variable with static storage duration has initialization or a @@ -4067,7 +4067,7 @@ \rSec2[basic.align]{Alignment} \pnum -Object types have \defnx{alignment requirements}{alignment requirement!implementation-defined}~(\ref{basic.fundamental}, \ref{basic.compound}) +Object types have \defnx{alignment requirements}{alignment requirement!implementation-defined}\iref{basic.fundamental,basic.compound} which place restrictions on the addresses at which an object of that type may be allocated. An \defn{alignment} is an \impldef{alignment} integer value representing the number of bytes between successive addresses @@ -4195,16 +4195,16 @@ Temporary objects are materialized: \begin{itemize} \item -when binding a reference to a prvalue~(\ref{dcl.init.ref}, \ref{expr.type.conv}, -\ref{expr.dynamic.cast}, \ref{expr.static.cast}, \ref{expr.const.cast}, \ref{expr.cast}), +when binding a reference to a prvalue\iref{dcl.init.ref,expr.type.conv, +expr.dynamic.cast,expr.static.cast,expr.const.cast,expr.cast}, \item -when performing member access on a class prvalue~(\ref{expr.ref}, \ref{expr.mptr.oper}), +when performing member access on a class prvalue\iref{expr.ref,expr.mptr.oper}, \item -when performing an array-to-pointer conversion or subscripting on an array prvalue~(\ref{conv.array}, \ref{expr.sub}), +when performing an array-to-pointer conversion or subscripting on an array prvalue\iref{conv.array,expr.sub}, \item when initializing an object of type \tcode{std::initializer_list} from a \grammarterm{braced-init-list}\iref{dcl.init.list}, \item -for certain unevaluated operands~(\ref{expr.typeid}, \ref{expr.sizeof}), and +for certain unevaluated operands\iref{expr.typeid,expr.sizeof}, and \item when a prvalue that has type other than \cv{}~\keyword{void} appears as a discarded-value expression\iref{expr.context}. \end{itemize} @@ -4279,7 +4279,7 @@ \indextext{temporary!destructor for}% \indextext{temporary!destruction of}% When an implementation introduces a temporary object of a class that has a -non-trivial constructor~(\ref{class.default.ctor}, \ref{class.copy.ctor}), +non-trivial constructor\iref{class.default.ctor,class.copy.ctor}, it shall ensure that a constructor is called for the temporary object. Similarly, the destructor shall be called for a temporary with a non-trivial destructor\iref{class.dtor}. @@ -4305,7 +4305,7 @@ The first context is when a default constructor is called to initialize an element of an array with no corresponding initializer\iref{dcl.init}. The second context is when a copy constructor is called to copy an element of -an array while the entire array is copied~(\ref{expr.prim.lambda.capture}, \ref{class.copy.ctor}). +an array while the entire array is copied\iref{expr.prim.lambda.capture,class.copy.ctor}. In either case, if the constructor has one or more default arguments, the destruction of every temporary created in a default argument is sequenced before the construction of the next array element, if any. @@ -4371,7 +4371,7 @@ \end{codeblock} \end{example} \begin{note} -An explicit type conversion~(\ref{expr.type.conv}, \ref{expr.cast}) +An explicit type conversion\iref{expr.type.conv,expr.cast} is interpreted as a sequence of elementary casts, covered above. @@ -4430,7 +4430,7 @@ completion of their construction. In addition, the destruction of temporaries bound to references shall take into account the ordering of destruction of objects with static, thread, or -automatic storage duration~(\ref{basic.stc.static}, \ref{basic.stc.thread}, \ref{basic.stc.auto}); +automatic storage duration\iref{basic.stc.static,basic.stc.thread,basic.stc.auto}; that is, if \tcode{obj1} is an object with the same storage duration as the temporary and @@ -5021,8 +5021,8 @@ is an incomplete type that cannot be completed; such a type has an empty set of values. It is used as the return type for functions that do not return a value. Any expression can be -explicitly converted to type \cv{}~\keyword{void}~(\ref{expr.type.conv}, -\ref{expr.static.cast}, \ref{expr.cast}). +explicitly converted to type +\cv{}~\keyword{void}\iref{expr.type.conv,expr.static.cast,expr.cast}. An expression of type \cv{}~\keyword{void} shall be used only as an expression statement\iref{stmt.expr}, as an operand of a comma expression\iref{expr.comma}, as a second or third operand @@ -5035,7 +5035,7 @@ \pnum A value of type \tcode{std::nullptr_t} is a null pointer constant\iref{conv.ptr}. Such values participate in the pointer and the -pointer-to-member conversions~(\ref{conv.ptr}, \ref{conv.mem}). +pointer-to-member conversions\iref{conv.ptr,conv.mem}. \tcode{\keyword{sizeof}(std::nullptr_t)} shall be equal to \tcode{\keyword{sizeof}(\keyword{void}*)}. \pnum @@ -5165,7 +5165,7 @@ see \ref{basic.stc}. \end{note} For purposes of pointer arithmetic\iref{expr.add} -and comparison~(\ref{expr.rel}, \ref{expr.eq}), +and comparison\iref{expr.rel,expr.eq}, a pointer past the end of the last element of an array \tcode{x} of $n$ elements is considered to be equivalent to @@ -6325,7 +6325,7 @@ \indextext{program!startup|(}% A program shall contain exactly one function called \tcode{main} that belongs to the global scope. -Executing a program starts a main thread of execution~(\ref{intro.multithread}, \ref{thread.threads}) +Executing a program starts a main thread of execution\iref{intro.multithread,thread.threads} in which the \tcode{main} function is invoked. \indextext{implementation!freestanding}% It is \impldef{defining \tcode{main} in freestanding environment} @@ -6576,7 +6576,7 @@ A non-block variable with static storage duration having initialization with side effects is initialized in this case, -even if it is not itself odr-used~(\ref{term.odr.use}, \ref{basic.stc.static}). +even if it is not itself odr-used\iref{term.odr.use,basic.stc.static}. \end{footnote} It is \impldef{threads and program points at which deferred dynamic initialization is performed} in which threads and at which points in the program such deferred dynamic initialization occurs. diff --git a/source/classes.tex b/source/classes.tex index bba2a790c8..fa73256323 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -149,8 +149,8 @@ \pnum \begin{note} -Class objects can be assigned~(\ref{over.ass}, \ref{class.copy.assign}), -passed as arguments to functions~(\ref{dcl.init}, \ref{class.copy.ctor}), and +Class objects can be assigned\iref{over.ass,class.copy.assign}, +passed as arguments to functions\iref{dcl.init,class.copy.ctor}, and returned by functions (except objects of classes for which copying or moving has been restricted; see~\ref{dcl.fct.def.delete} and \ref{class.access}). Other plausible operators, such as equality comparison, @@ -165,7 +165,7 @@ \item that has at least one eligible copy constructor, move constructor, copy assignment operator, or -move assignment operator~(\ref{special}, \ref{class.copy.ctor}, \ref{class.copy.assign}), +move assignment operator\iref{special,class.copy.ctor,class.copy.assign}, \item where each eligible copy constructor, move constructor, copy assignment operator, and move assignment operator is trivial, and \item that has a trivial, non-deleted destructor\iref{class.dtor}. @@ -539,7 +539,7 @@ A \defn{data member} is a non-function member introduced by a \grammarterm{member-declarator}. A \defn{member function} is a member that is a function. -Nested types are classes~(\ref{class.name}, \ref{class.nest}) and +Nested types are classes\iref{class.name,class.nest} and enumerations\iref{dcl.enum} declared in the class and arbitrary types declared as members by use of a typedef declaration\iref{dcl.typedef} or \grammarterm{alias-declaration}. @@ -580,7 +580,7 @@ A redeclaration of a class member outside its class definition shall be a definition, an explicit specialization, or -an explicit instantiation (\ref{temp.expl.spec}, \ref{temp.explicit}). +an explicit instantiation\iref{temp.expl.spec,temp.explicit}. The member shall not be a non-static data member. \pnum @@ -848,7 +848,7 @@ \end{note} \begin{note} The object and its first subobject are -pointer-interconvertible~(\ref{basic.compound}, \ref{expr.static.cast}). +pointer-interconvertible\iref{basic.compound,expr.static.cast}. \end{note} \rSec2[class.mfct]{Member functions}% @@ -921,9 +921,9 @@ A non-static member function may be called for an object of its class type, or for an object of a class derived\iref{class.derived} from its class type, using the class member -access syntax~(\ref{expr.ref}, \ref{over.match.call}). A non-static +access syntax\iref{expr.ref,over.match.call}. A non-static member function may also be called directly using the function call -syntax~(\ref{expr.call}, \ref{over.match.call}) from within +syntax\iref{expr.call,over.match.call} from within its class or a class derived from its class, or a member thereof, as described below. @@ -1564,7 +1564,7 @@ \begin{note} A defaulted move constructor that is defined as deleted is ignored by overload -resolution~(\ref{over.match}, \ref{over.over}). +resolution\iref{over.match,over.over}. Such a constructor would otherwise interfere with initialization from an rvalue which can use the copy constructor instead. \end{note} @@ -1610,7 +1610,7 @@ when it is explicitly defaulted after its first declaration. \begin{note} The copy/move constructor is implicitly defined even if the implementation elided -its odr-use~(\ref{term.odr.use}, \ref{class.temporary}). +its odr-use\iref{term.odr.use,class.temporary}. \end{note} If the implicitly-defined constructor would satisfy the requirements of a constexpr constructor\iref{dcl.constexpr}, the implicitly-defined @@ -1853,7 +1853,7 @@ \begin{note} A defaulted move assignment operator that is defined as deleted is ignored by -overload resolution~(\ref{over.match}, \ref{over.over}). +overload resolution\iref{over.match,over.over}. \end{note} \pnum @@ -2212,7 +2212,7 @@ \item for a constructed object with automatic storage duration\iref{basic.stc.auto} when the block in which an object is created exits\iref{stmt.dcl}, -\item for a constructed temporary object when its lifetime ends~(\ref{conv.rval}, \ref{class.temporary}). +\item for a constructed temporary object when its lifetime ends\iref{conv.rval,class.temporary}. \end{itemize} \indextext{\idxcode{delete}!destructor and}% @@ -2365,11 +2365,11 @@ \defnx{user-defined conversions}{conversion!user-defined} and are used for implicit type conversions\iref{conv}, for initialization\iref{dcl.init}, -and for explicit type conversions~(\ref{expr.type.conv}, \ref{expr.cast}, -\ref{expr.static.cast}). +and for explicit type conversions\iref{expr.type.conv,expr.cast, +expr.static.cast}. \pnum -User-defined conversions are applied only where they are unambiguous~(\ref{class.member.lookup}, \ref{class.conv.fct}). +User-defined conversions are applied only where they are unambiguous\iref{class.member.lookup,class.conv.fct}. Conversions obey the access control rules\iref{class.access}. Access control is applied after ambiguity resolution\iref{basic.lookup}. @@ -2432,7 +2432,7 @@ \begin{note} An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax\iref{dcl.init} -or where casts~(\ref{expr.static.cast}, \ref{expr.cast}) are explicitly +or where casts\iref{expr.static.cast,expr.cast} are explicitly used; see also~\ref{over.match.copy}. A default constructor can be an explicit constructor; such a constructor will be used to perform default-initialization @@ -2538,7 +2538,7 @@ or to \cv{}~\keyword{void}. \begin{footnote} These conversions are considered -as standard conversions for the purposes of overload resolution~(\ref{over.best.ics}, \ref{over.ics.ref}) and therefore initialization\iref{dcl.init} and explicit casts\iref{expr.static.cast}. A conversion to \keyword{void} does not invoke any conversion function\iref{expr.static.cast}. +as standard conversions for the purposes of overload resolution\iref{over.best.ics,over.ics.ref} and therefore initialization\iref{dcl.init} and explicit casts\iref{expr.static.cast}. A conversion to \keyword{void} does not invoke any conversion function\iref{expr.static.cast}. Even though never directly called to perform a conversion, such conversion functions can be declared and can potentially be reached through a call to a virtual conversion function in a base class. @@ -3147,7 +3147,7 @@ as if it were the sole member of a non-union class. \begin{note} A union object and its non-static data members are -pointer-interconvertible~(\ref{basic.compound}, \ref{expr.static.cast}). +pointer-interconvertible\iref{basic.compound,expr.static.cast}. As a consequence, all non-static data members of a union object have the same address. \end{note} @@ -3633,7 +3633,7 @@ The order of derivation is not significant except as specified by the semantics of initialization by constructor\iref{class.base.init}, cleanup\iref{class.dtor}, and storage -layout~(\ref{class.mem}, \ref{class.access.spec}). +layout\iref{class.mem,class.access.spec}. \end{note} \pnum @@ -4151,7 +4151,7 @@ An abstract class can be used only as a base class of some other class; no objects of an abstract class can be created except as subobjects of a class -derived from it~(\ref{basic.def}, \ref{class.mem}). +derived from it\iref{basic.def,class.mem}. \end{note} \indextext{definition!pure virtual function}% A pure virtual function need be defined only if called with, or as if @@ -4189,8 +4189,8 @@ a function being defined\iref{dcl.fct} or called\iref{expr.call}, except as specified in \ref{dcl.type.simple}. Further, an abstract class type cannot be used as -the type of an explicit type conversion~(\ref{expr.static.cast}, -\ref{expr.reinterpret.cast}, \ref{expr.const.cast}), +the type of an explicit type conversion\iref{expr.static.cast, +expr.reinterpret.cast,expr.const.cast}, because the resulting prvalue would be of abstract class type\iref{basic.lval}. However, pointers and references to abstract class types can appear in such contexts. @@ -4443,8 +4443,7 @@ \pnum Member declarations can be labeled by an -\grammarterm{access-specifier} -(\ref{class.derived}): +\grammarterm{access-specifier}\iref{class.derived}: \begin{ncsimplebnf} access-specifier \terminal{:} \opt{member-specification} @@ -4606,7 +4605,7 @@ A member of a private base class can be inaccessible as inherited, but accessible directly. Because of the rules on pointer conversions\iref{conv.ptr} and -explicit casts~(\ref{expr.type.conv}, \ref{expr.static.cast}, \ref{expr.cast}), +explicit casts\iref{expr.type.conv,expr.static.cast,expr.cast}, a conversion from a pointer to a derived class to a pointer to an inaccessible base class can be ill-formed if an implicit conversion is used, but well-formed if an explicit cast is used. @@ -4712,7 +4711,7 @@ \pnum If a base class is accessible, one can implicitly convert a pointer to -a derived class to a pointer to that base class~(\ref{conv.ptr}, \ref{conv.mem}). +a derived class to a pointer to that base class\iref{conv.ptr,conv.mem}. \begin{note} It follows that members and friends of a class @@ -4910,8 +4909,8 @@ \begin{note} A friend declaration can be the -\grammarterm{declaration} in a \grammarterm{template-declaration} -(\ref{temp.pre}, \ref{temp.friend}). +\grammarterm{declaration} in +a \grammarterm{template-declaration}\iref{temp.pre,temp.friend}. \end{note} If the type specifier in a \keyword{friend} declaration designates a (possibly @@ -5037,8 +5036,7 @@ \indextext{local class!friend}% \indextext{friend!local class and}% \begin{note} -A friend declaration never binds any names -(\ref{dcl.meaning}, \ref{dcl.type.elab}). +A friend declaration never binds any names\iref{dcl.meaning,dcl.type.elab}. \end{note} \begin{example} \begin{codeblock} diff --git a/source/compatibility.tex b/source/compatibility.tex index 9b07e9ba52..a5b7bac5ee 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -1516,8 +1516,7 @@ \diffref{temp.param} \change -Repurpose \keyword{export} for modules -(\ref{module}, \ref{cpp.module}, \ref{cpp.import}). +Repurpose \keyword{export} for modules\iref{module,cpp.module,cpp.import}. \rationale No implementation consensus for the \CppIII{} meaning of \keyword{export}. \effect diff --git a/source/concepts.tex b/source/concepts.tex index 439f541970..ac641ec5ce 100644 --- a/source/concepts.tex +++ b/source/concepts.tex @@ -38,7 +38,7 @@ invocations of the library function templates \tcode{std::move}, \tcode{std::forward}, and -\tcode{std::declval}~(\ref{forward}, \ref{declval}). +\tcode{std::declval}\iref{forward,declval}. \end{itemize} \begin{example} The operands of the expression \tcode{a = std::move(b)} are @@ -854,8 +854,7 @@ The exposition-only \exposconcept{boolean-testable} concept specifies the requirements on expressions that are convertible to \tcode{bool} and -for which the logical operators~% -(\ref{expr.log.and}, \ref{expr.log.or}, \ref{expr.unary.op}) +for which the logical operators\iref{expr.log.and,expr.log.or,expr.unary.op} have the conventional semantics. \begin{itemdecl} diff --git a/source/containers.tex b/source/containers.tex index 8bbfcebd33..c3342af987 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -6217,7 +6217,7 @@ \indextext{requirements!container}% The conditions for an aggregate\iref{dcl.init.aggr} shall be met. Class \tcode{array} relies on the implicitly-declared special -member functions~(\ref{class.default.ctor}, \ref{class.dtor}, and \ref{class.copy.ctor}) to +member functions\iref{class.default.ctor,class.dtor,class.copy.ctor} to conform to the container requirements table in~\ref{container.requirements}. In addition to the requirements specified in the container requirements table, the implicit move constructor and move assignment operator for \tcode{array} diff --git a/source/declarations.tex b/source/declarations.tex index 4989015973..5cbc237f24 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -192,8 +192,8 @@ is declared to be a \grammarterm{typedef-name}, synonymous with its associated type\iref{dcl.typedef}. \begin{note} -Such a \grammarterm{declarator-id} is an \grammarterm{identifier} -(\ref{class.conv.fct}). +Such a \grammarterm{declarator-id} is +an \grammarterm{identifier}\iref{class.conv.fct}. \end{note} If the \grammarterm{decl-specifier-seq} contains no \keyword{typedef} specifier, the @@ -501,7 +501,7 @@ The \keyword{mutable} specifier on a class data member nullifies a \keyword{const} specifier applied to the containing class object and permits modification of the mutable class member even though the rest of -the object is const~(\ref{basic.type.qualifier}, \ref{dcl.type.cv}). +the object is const\iref{basic.type.qualifier,dcl.type.cv}. \end{note} \rSec2[dcl.fct.spec]{Function specifiers}% @@ -992,8 +992,8 @@ \pnum \indextext{specifier!\idxcode{inline}}% \indextext{inline function}% -A function declaration~(\ref{dcl.fct}, \ref{class.mfct}, -\ref{class.friend}) with an \keyword{inline} specifier declares an +A function declaration\iref{dcl.fct,class.mfct,class.friend} +with an \keyword{inline} specifier declares an \defnadj{inline}{function}. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. @@ -1050,7 +1050,7 @@ \begin{note} A constexpr function\iref{dcl.constexpr} is implicitly inline. In the global module, a function defined within a class definition -is implicitly inline~(\ref{class.mfct}, \ref{class.friend}). +is implicitly inline\iref{class.mfct,class.friend}. \end{note} \rSec2[dcl.type]{Type specifiers}% @@ -1198,8 +1198,7 @@ \pnum \indextext{const object!undefined change to}% -Any attempt to modify~(\ref{expr.ass}, -\ref{expr.post.incr}, \ref{expr.pre.incr}) a +Any attempt to modify\iref{expr.ass,expr.post.incr,expr.pre.incr} a const object\iref{basic.type.qualifier} during its lifetime\iref{basic.life} results in undefined behavior. \begin{example} @@ -1506,7 +1505,7 @@ \grammarterm{simple-type-specifier} introduces its \grammarterm{type-name}\iref{dcl.type.simple}. If the \grammarterm{identifier} or \grammarterm{simple-template-id} resolves to a -\grammarterm{typedef-name} (\ref{dcl.typedef}, \ref{temp.names}), +\grammarterm{typedef-name}\iref{dcl.typedef,temp.names}, the \grammarterm{elaborated-type-specifier} is ill-formed. \begin{note} This implies that, within a class template with a template @@ -1561,8 +1560,8 @@ \item otherwise, if $E$ is an unparenthesized \grammarterm{id-expression} naming a non-type \grammarterm{template-parameter}\iref{temp.param}, \tcode{decltype($E$)} is the type of the \grammarterm{template-parameter} -after performing any necessary type deduction -(\ref{dcl.spec.auto}, \ref{dcl.type.class.deduct}); +after performing any necessary +type deduction\iref{dcl.spec.auto,dcl.type.class.deduct}; \item otherwise, if $E$ is an unparenthesized \grammarterm{id-expression} or an unparenthesized @@ -2142,7 +2141,7 @@ \pnum In all contexts, a \grammarterm{declarator} is interpreted as given below. Where an \grammarterm{abstract-declarator} can be used (or omitted) -in place of a \grammarterm{declarator} (\ref{dcl.fct}, \ref{except.pre}), +in place of a \grammarterm{declarator}\iref{dcl.fct,except.pre}, it is as if a unique identifier were included in the appropriate place\iref{dcl.name}. The preceding specifiers indicate @@ -2506,8 +2505,8 @@ \grammarterm{explicit-instantiation}\iref{temp.explicit}. \begin{note} An \grammarterm{unqualified-id} that is not an \grammarterm{identifier} -is used to declare certain functions -(\ref{class.conv.fct}, \ref{class.dtor}, \ref{over.oper}, \ref{over.literal}). +is used to declare +certain functions\iref{class.conv.fct,class.dtor,over.oper,over.literal}. \end{note} The optional \grammarterm{attribute-specifier-seq} following a \grammarterm{declarator-id} appertains to the entity that is declared. @@ -2871,7 +2870,7 @@ The optional \grammarterm{attribute-specifier-seq} appertains to the reference type. Cv-qualified references are ill-formed except when the cv-qualifiers are introduced through the use of a -\grammarterm{typedef-name}~(\ref{dcl.typedef}, \ref{temp.param}) or +\grammarterm{typedef-name}\iref{dcl.typedef,temp.param} or \grammarterm{decltype-specifier}\iref{dcl.type.decltype}, in which case the cv-qualifiers are ignored. \begin{example} @@ -2998,7 +2997,7 @@ \pnum \indextext{reference collapsing}% -If a \grammarterm{typedef-name}~(\ref{dcl.typedef}, \ref{temp.param}) +If a \grammarterm{typedef-name}\iref{dcl.typedef,temp.param} or a \grammarterm{decltype-specifier}\iref{dcl.type.decltype} denotes a type \tcode{TR} that is a reference to a type \tcode{T}, an attempt to create the type ``lvalue reference to \cv{}~\tcode{TR}'' creates the type ``lvalue reference to \tcode{T}'', while an attempt to create @@ -3236,8 +3235,8 @@ parameter\iref{dcl.fct}. An array bound may also be omitted when an object (but not a non-static data member) of array type is initialized -and the declarator is followed by an initializer -(\ref{dcl.init}, \ref{class.mem}, \ref{expr.type.conv}, \ref{expr.new}). +and the declarator is followed by +an initializer\iref{dcl.init,class.mem,expr.type.conv,expr.new}. \indextext{array size!default}% In these cases, the array bound is calculated from the number of initial elements (say, \tcode{N}) @@ -3626,7 +3625,7 @@ \pnum A function type with a \grammarterm{cv-qualifier-seq} or a \grammarterm{ref-qualifier} (including a type named by -\grammarterm{typedef-name}~(\ref{dcl.typedef}, \ref{temp.param})) +\grammarterm{typedef-name}\iref{dcl.typedef,temp.param}) shall appear only as: \begin{itemize} \item the function type for a non-static member function, @@ -4588,8 +4587,8 @@ \tcode{X}. The form \tcode{()} -is permitted in certain other initialization contexts~(\ref{expr.new}, -\ref{expr.type.conv}, \ref{class.base.init}). +is permitted in certain other initialization contexts\iref{expr.new, +expr.type.conv,class.base.init}. \end{note} \item @@ -5589,8 +5588,7 @@ user-defined conversions are considered using the rules for copy-initialization of an object of type ``\cvqual{cv1} \tcode{T1}'' by -user-defined conversion -(\ref{dcl.init}, \ref{over.match.copy}, \ref{over.match.conv}); +user-defined conversion\iref{dcl.init,over.match.copy,over.match.conv}; the program is ill-formed if the corresponding non-reference copy-initialization would be ill-formed. The result of the call to the conversion function, as described for the non-reference @@ -5686,7 +5684,7 @@ \item as a \grammarterm{for-range-initializer}\iref{stmt.iter} \item as a function argument\iref{expr.call} \item as a subscript\iref{expr.sub} -\item as an argument to a constructor invocation~(\ref{dcl.init}, \ref{expr.type.conv}) +\item as an argument to a constructor invocation\iref{dcl.init,expr.type.conv} \item as an initializer for a non-static data member\iref{class.mem} \item in a \grammarterm{mem-initializer}\iref{class.base.init} \item on the right-hand side of an assignment\iref{expr.ass} @@ -5783,7 +5781,7 @@ \item Otherwise, if \tcode{T} is a class type, constructors are considered. The applicable constructors are enumerated and -the best one is chosen through overload resolution~(\ref{over.match}, \ref{over.match.list}). If a narrowing +the best one is chosen through overload resolution\iref{over.match,over.match.list}. If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed. @@ -6243,7 +6241,7 @@ \pnum An explicitly-defaulted function that is not defined as deleted may be declared \keyword{constexpr} or \keyword{consteval} only -if it is constexpr-compatible (\ref{special}, \ref{class.compare.default}). +if it is constexpr-compatible\iref{special,class.compare.default}. A function explicitly defaulted on its first declaration is implicitly inline\iref{dcl.inline}, and is implicitly constexpr\iref{dcl.constexpr} if it is constexpr-compatible. @@ -6280,8 +6278,7 @@ Explicitly-defaulted functions and implicitly-declared functions are collectively called \defn{defaulted} functions, and the implementation shall provide implicit definitions -for them~(\ref{class.ctor}, -\ref{class.dtor}, \ref{class.copy.ctor}, \ref{class.copy.assign}), +for them\iref{class.ctor,class.dtor,class.copy.ctor,class.copy.assign}, including possibly defining them as deleted. A defaulted prospective destructor\iref{class.dtor} that is not a destructor is defined as deleted. @@ -7481,8 +7478,8 @@ \begin{note} A \grammarterm{using-directive} makes the names in the nominated namespace usable in the scope in which the -\grammarterm{using-directive} appears after the \grammarterm{using-directive} -(\ref{basic.lookup.unqual}, \ref{namespace.qual}). +\grammarterm{using-directive} appears after +the \grammarterm{using-directive}\iref{basic.lookup.unqual,namespace.qual}. During unqualified name lookup, the names appear as if they were declared in the nearest enclosing namespace which contains both the \grammarterm{using-directive} and the nominated @@ -7787,7 +7784,7 @@ \end{note} If a constructor or assignment operator brought from a base class into a derived class has the signature of a copy/move constructor or assignment operator -for the derived class~(\ref{class.copy.ctor}, \ref{class.copy.assign}), +for the derived class\iref{class.copy.ctor,class.copy.assign}, the \grammarterm{using-declaration} does not by itself suppress the implicit declaration of the derived class member; the member from the base class is hidden or overridden @@ -7842,8 +7839,8 @@ does not name declarations added to the namespace after it. Thus, additional overloads added after the \grammarterm{using-declaration} are ignored, but default function arguments\iref{dcl.fct.default}, default template -arguments\iref{temp.param}, and template specializations~(\ref{temp.spec.partial}, -\ref{temp.expl.spec}) are considered. +arguments\iref{temp.param}, and +template specializations\iref{temp.spec.partial,temp.expl.spec} are considered. \end{note} \begin{example} \begin{codeblock} @@ -7997,7 +7994,7 @@ Constructors that are named by a \grammarterm{using-declaration} are treated as though they were constructors of the derived class when looking up the constructors of the derived class\iref{class.qual} -or forming a set of overload candidates~(\ref{over.match.ctor}, \ref{over.match.copy}, \ref{over.match.list}). +or forming a set of overload candidates\iref{over.match.ctor,over.match.copy,over.match.list}. \begin{note} If such a constructor is selected to perform the initialization of an object of class type, all subobjects other than the base class @@ -8439,9 +8436,9 @@ \pnum Each \grammarterm{attribute-specifier-seq} is said to \defn{appertain} to some entity or -statement, identified by the syntactic context where it appears -(\ref{stmt.stmt}, \ref{dcl.dcl}, -\ref{dcl.decl}). If an \grammarterm{attribute-specifier-seq} that appertains to some +statement, identified by the syntactic context +where it appears\iref{stmt.stmt,dcl.dcl,dcl.decl}. +If an \grammarterm{attribute-specifier-seq} that appertains to some entity or statement contains an \grammarterm{attribute} or \grammarterm{alignment-specifier} that is not allowed to apply to that entity or statement, the program is ill-formed. If an \grammarterm{attribute-specifier-seq} @@ -8930,7 +8927,7 @@ whose return type is a nodiscard type, or \item an explicit type - conversion~(\ref{expr.type.conv}, \ref{expr.static.cast}, \ref{expr.cast}) + conversion\iref{expr.type.conv,expr.static.cast,expr.cast} that constructs an object through a constructor declared \tcode{nodiscard} in a reachable declaration, or that initializes an object of a nodiscard type. diff --git a/source/exceptions.tex b/source/exceptions.tex index 6482b538ac..a436edfc57 100644 --- a/source/exceptions.tex +++ b/source/exceptions.tex @@ -257,7 +257,7 @@ \pnum Throwing an exception -copy-initializes~(\ref{dcl.init}, \ref{class.copy.ctor}) a temporary object, +copy-initializes\iref{dcl.init,class.copy.ctor} a temporary object, called the \defnx{exception object}{exception handling!exception object}. If the type of the exception object would be @@ -868,7 +868,7 @@ to the exception specification of the constructor, because an exception thrown from such a destructor would call the function \tcode{std::terminate} -rather than escape the constructor~(\ref{except.throw}, \ref{except.terminate}). +rather than escape the constructor\iref{except.throw,except.terminate}. \end{note} \pnum @@ -939,7 +939,7 @@ An exception specification is considered to be \defnx{needed}{needed!exception specification} when: \begin{itemize} \item in an expression, the function is selected by -overload resolution~(\ref{over.match}, \ref{over.over}); +overload resolution\iref{over.match,over.over}; \item the function is odr-used\iref{term.odr.use} or, if it appears in an unevaluated operand, would be odr-used if the expression were @@ -1042,18 +1042,18 @@ \item% for a parallel algorithm whose \tcode{ExecutionPolicy} specifies such -behavior~(\ref{execpol.seq}, \ref{execpol.par}, \ref{execpol.parunseq}), +behavior\iref{execpol.seq,execpol.par,execpol.parunseq}, when execution of an element access function\iref{algorithms.parallel.defns} of the parallel algorithm exits via an exception\iref{algorithms.parallel.exceptions}, or \item% when the destructor or the move assignment operator is invoked on an object -of type \tcode{std::thread} that refers to a joinable thread -(\ref{thread.thread.destr}, \ref{thread.thread.assign}), or +of type \tcode{std::thread} that refers to +a joinable thread\iref{thread.thread.destr,thread.thread.assign}, or \item% when a call to a \tcode{wait()}, \tcode{wait_until()}, or \tcode{wait_for()} -function on a condition variable~(\ref{thread.condition.condvar}, \ref{thread.condition.condvarany}) +function on a condition variable\iref{thread.condition.condvar,thread.condition.condvarany} fails to meet a postcondition. \end{itemize} @@ -1094,7 +1094,7 @@ As a consequence, an exception is considered uncaught during any stack unwinding resulting from it being thrown. \end{note} -If an exception is rethrown~(\ref{expr.throw}, \ref{propagation}), +If an exception is rethrown\iref{expr.throw,propagation}, it is considered uncaught from the point of rethrow until the rethrown exception is caught. The function \tcode{std::uncaught_exceptions}\iref{uncaught.exceptions} diff --git a/source/expressions.tex b/source/expressions.tex index 08d450de78..30fe24187e 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -189,9 +189,9 @@ \item the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type\iref{expr.call}, -\item a cast to an rvalue reference to object type -(\ref{expr.type.conv}, \ref{expr.dynamic.cast}, \ref{expr.static.cast} -\ref{expr.reinterpret.cast}, \ref{expr.const.cast}, \ref{expr.cast}), +\item a cast to an rvalue reference to +object type\iref{expr.type.conv,expr.dynamic.cast,expr.static.cast, +expr.reinterpret.cast,expr.const.cast,expr.cast}, \item a subscripting operation with an xvalue array operand\iref{expr.sub}, @@ -292,7 +292,7 @@ \begin{note} A program that attempts to modify an object through a nonmodifiable lvalue or through an rvalue -is ill-formed~(\ref{expr.ass}, \ref{expr.post.incr}, \ref{expr.pre.incr}). +is ill-formed\iref{expr.ass,expr.post.incr,expr.pre.incr}. \end{note} \pnum @@ -329,7 +329,7 @@ \pnum \indextext{expression!reference}% If an expression initially has the type ``reference to -\tcode{T}''~(\ref{dcl.ref}, \ref{dcl.init.ref}), the type is adjusted to +\tcode{T}''\iref{dcl.ref,dcl.init.ref}, the type is adjusted to \tcode{T} prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression. @@ -428,13 +428,13 @@ \pnum \label{term.unevaluated.operand}% In some contexts, \defnx{unevaluated operands}{unevaluated operand} -appear~(\ref{expr.prim.req}, -\ref{expr.typeid}, -\ref{expr.sizeof}, -\ref{expr.unary.noexcept}, -\ref{dcl.type.decltype}, -\ref{temp.pre}, -\ref{temp.concept}). +appear\iref{expr.prim.req, +expr.typeid, +expr.sizeof, +expr.unary.noexcept, +dcl.type.decltype, +temp.pre, +temp.concept}. An unevaluated operand is not evaluated. \begin{note} In an unevaluated operand, a non-static class member can be @@ -1057,7 +1057,7 @@ The rule for conversion of pointers to members (from pointer to member of base to pointer to member of derived) appears inverted compared to the rule for pointers to objects (from pointer to derived to pointer to -base)~(\ref{conv.ptr}, \ref{class.derived}). This inversion is +base)\iref{conv.ptr,class.derived}. This inversion is necessary to ensure type safety. Note that a pointer to member is not an object pointer or a function pointer and the rules for conversions @@ -1364,7 +1364,7 @@ \pnum For an \grammarterm{id-expression} that denotes an overload set, overload resolution is performed -to select a unique function~(\ref{over.match}, \ref{over.over}). +to select a unique function\iref{over.match,over.over}. \begin{note} A program cannot refer to a function with a trailing \grammarterm{requires-clause} @@ -1434,10 +1434,9 @@ the \grammarterm{template-id} or \grammarterm{type-name} of $U$, if any. \end{itemize} \begin{note} -Other constructs that contain names to look up can have several component names -(\ref{expr.prim.id.qual}, \ref{dcl.type.simple}, \ref{dcl.type.elab}, -\ref{dcl.mptr}, \ref{namespace.udecl}, \ref{temp.param}, \ref{temp.names}, -\ref{temp.res}). +Other constructs that contain names to look up can have several +component names\iref{expr.prim.id.qual,dcl.type.simple,dcl.type.elab, +dcl.mptr,namespace.udecl,temp.param,temp.names,temp.res}. \end{note} The \defnadj{terminal}{name} of a construct is the component name of that construct that appears lexically last. @@ -1646,7 +1645,7 @@ as the right operand of a class member access\iref{expr.ref} that forms the \grammarterm{postfix-expression} of a function call\iref{expr.call}. \begin{note} -Such a call ends the lifetime of the object (\ref{expr.call}, \ref{basic.life}). +Such a call ends the lifetime of the object\iref{expr.call,basic.life}. \end{note} \pnum @@ -2233,7 +2232,7 @@ \pnum The \grammarterm{identifier} in a \grammarterm{simple-capture} -shall denote a local entity (\ref{basic.lookup.unqual}, \ref{basic.pre}). +shall denote a local entity\iref{basic.lookup.unqual,basic.pre}. The \grammarterm{simple-capture}{s} \keyword{this} and \tcode{* \keyword{this}} denote the local entity \tcode{*\keyword{this}}. An entity that is designated by a @@ -3114,7 +3113,7 @@ \pnum For a call to a non-static member function, the postfix expression shall be an -implicit~(\ref{class.mfct.non.static}, \ref{class.static}) or explicit +implicit\iref{class.mfct.non.static,class.static} or explicit class member access\iref{expr.ref} whose \grammarterm{id-expression} is a function member name, or a pointer-to-member expression\iref{expr.mptr.oper} selecting a function member; the call is as a member of @@ -3163,7 +3162,7 @@ the function call destroys the object of scalar type denoted by the object expression -of the class member access (\ref{expr.ref}, \ref{basic.life}). +of the class member access\iref{expr.ref,basic.life}. \pnum Calling a function through an @@ -3184,7 +3183,7 @@ \indextext{function parameter|see{parameter}}% \indextext{initialization!parameter}% When a function is called, each parameter\iref{dcl.fct} is -initialized~(\ref{dcl.init}, \ref{class.copy.ctor}) with +initialized\iref{dcl.init,class.copy.ctor} with its corresponding argument. If the function is an explicit object member function and there is an implied object argument\iref{over.call.func}, @@ -3302,7 +3301,7 @@ cast away the constness in order to modify the argument's value. Where a parameter is of \keyword{const} reference type a temporary object is introduced if -needed~(\ref{dcl.type}, \ref{lex.literal}, \ref{lex.string}, \ref{dcl.array}, \ref{class.temporary}). +needed\iref{dcl.type,lex.literal,lex.string,dcl.array,class.temporary}. In addition, it is possible to modify the values of non-constant objects through pointer parameters. \end{note} @@ -4883,7 +4882,7 @@ A \keyword{sizeof} expression is an integral constant expression\iref{expr.const}. The type \tcode{std::size_t} is defined in the standard header -\libheader{cstddef}~(\ref{cstddef.syn}, \ref{support.types.layout}). +\libheader{cstddef}\iref{cstddef.syn,support.types.layout}. \end{note} \rSec3[expr.alignof]{Alignof} @@ -4902,7 +4901,7 @@ An \keyword{alignof} expression is an integral constant expression\iref{expr.const}. The type \tcode{std::size_t} is defined in the standard header -\libheader{cstddef}~(\ref{cstddef.syn}, \ref{support.types.layout}). +\libheader{cstddef}\iref{cstddef.syn,support.types.layout}. \end{note} \pnum @@ -5092,7 +5091,7 @@ the allocated object is an array with \tcode{n} elements, where \tcode{n} is determined from the number of initial elements supplied in -the \grammarterm{new-initializer}~(\ref{dcl.init.aggr}, \ref{dcl.init.string}). +the \grammarterm{new-initializer}\iref{dcl.init.aggr,dcl.init.string}. \pnum \indextext{\idxcode{new}}% @@ -5195,7 +5194,7 @@ \begin{note} An implementation is required to provide default definitions for the global allocation -functions~(\ref{basic.stc.dynamic}, \ref{new.delete.single}, \ref{new.delete.array}). +functions\iref{basic.stc.dynamic,new.delete.single,new.delete.array}. A \Cpp{} program can provide alternative definitions of these functions\iref{replacement.functions} and/or class-specific versions\iref{class.free}. @@ -5218,7 +5217,7 @@ \pnum An implementation is allowed to omit a call to a replaceable global allocation -function~(\ref{new.delete.single}, \ref{new.delete.array}). When it does so, +function\iref{new.delete.single,new.delete.array}. When it does so, the storage is instead provided by the implementation or provided by extending the allocation of another \grammarterm{new-expression}. @@ -5391,8 +5390,8 @@ it indicates failure to allocate storage by throwing a \indextext{\idxcode{bad_alloc}}% \indexlibraryglobal{bad_alloc}% -\tcode{std::bad_alloc} exception~(\ref{basic.stc.dynamic.allocation}, -\ref{except}, \ref{bad.alloc}); +\tcode{std::bad_alloc} +exception\iref{basic.stc.dynamic.allocation,except,bad.alloc}; it returns a non-null pointer otherwise. If the allocation function has a non-throwing exception specification, it returns null to indicate failure to allocate storage @@ -5678,7 +5677,7 @@ \begin{note} \indextext{\idxcode{operator delete}}% An implementation provides default definitions of the global -deallocation functions (\ref{new.delete.single}, \ref{new.delete.array}). +deallocation functions\iref{new.delete.single,new.delete.array}. A \Cpp{} program can provide alternative definitions of these functions\iref{replacement.functions}, and/or class-specific versions\iref{class.free}. @@ -5793,12 +5792,12 @@ the first argument was not the result of a prior call to a replaceable allocation function or the second or third argument was not the corresponding argument in said call, -the behavior is undefined~(\ref{new.delete.single}, \ref{new.delete.array}). +the behavior is undefined\iref{new.delete.single,new.delete.array}. \end{note} \pnum Access and ambiguity control are done for both the deallocation function -and the destructor~(\ref{class.dtor}, \ref{class.free}). +and the destructor\iref{class.dtor,class.free}. \rSec2[expr.cast]{Explicit type conversion (cast notation)}% \indextext{expression!cast|(} @@ -6820,7 +6819,7 @@ Otherwise, the result is a prvalue. If the second and third operands do not have the same type, and either has (possibly cv-qualified) class type, overload resolution is used to determine the conversions (if any) -to be applied to the operands~(\ref{over.match.oper}, \ref{over.built}). +to be applied to the operands\iref{over.match.oper,over.built}. If the overload resolution fails, the program is ill-formed. Otherwise, the conversions thus determined are applied, and the converted operands are used in place of the original operands for the remainder of this @@ -7076,7 +7075,7 @@ \item an assignment to an object of class type, in which case the initializer list is passed as the argument to the assignment operator function selected by -overload resolution~(\ref{over.ass}, \ref{over.match}). +overload resolution\iref{over.ass,over.match}. \end{itemize} \begin{example} \begin{codeblock} @@ -7300,7 +7299,7 @@ a reference to \keyword{this} or to a variable with automatic storage duration defined outside that \grammarterm{lambda-expression}, where -the reference would be an odr-use~(\ref{term.odr.use}, \ref{expr.prim.lambda}); +the reference would be an odr-use\iref{term.odr.use,expr.prim.lambda}; \begin{example} \begin{codeblock} void g() { @@ -7339,8 +7338,7 @@ a \keyword{reinterpret_cast}\iref{expr.reinterpret.cast}; \item -a modification of an object~(\ref{expr.ass}, \ref{expr.post.incr}, -\ref{expr.pre.incr}) +a modification of an object\iref{expr.ass,expr.post.incr,expr.pre.incr} unless it is applied to a non-volatile lvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of $E$; @@ -7353,8 +7351,7 @@ \item a \grammarterm{new-expression}\iref{expr.new}, unless the selected allocation function is -a replaceable global allocation function~(\ref{new.delete.single}, -\ref{new.delete.array}) and +a replaceable global allocation function\iref{new.delete.single,new.delete.array} and the allocated storage is deallocated within the evaluation of $E$; \item diff --git a/source/future.tex b/source/future.tex index d9da8342e2..17bd08d0ea 100644 --- a/source/future.tex +++ b/source/future.tex @@ -61,7 +61,7 @@ \rSec1[depr.array.comp]{Array comparisons} \pnum -Equality and relational comparisons (\ref{expr.eq}, \ref{expr.rel}) +Equality and relational comparisons\iref{expr.eq,expr.rel} between two operands of array type are deprecated. \begin{note} @@ -565,7 +565,8 @@ The function frees the dynamically allocated array object only if \tcode{(strmode \& allocated) != 0} and -\tcode{(strmode \& frozen) == 0}.~(\ref{depr.strstreambuf.virtuals} describes how a dynamically allocated array object is freed.) +\tcode{(strmode \& frozen) == 0}. +(\ref{depr.strstreambuf.virtuals} describes how a dynamically allocated array object is freed.) \end{itemdescr} \rSec3[depr.strstreambuf.members]{Member functions} diff --git a/source/grammar.tex b/source/grammar.tex index affc8ca89b..8501d39453 100644 --- a/source/grammar.tex +++ b/source/grammar.tex @@ -9,7 +9,7 @@ It is not an exact statement of the language. In particular, the grammar described here accepts a superset of valid \Cpp{} constructs. -Disambiguation rules~(\ref{stmt.ambig}, \ref{dcl.spec}, \ref{class.member.lookup}) +Disambiguation rules\iref{stmt.ambig,dcl.spec,class.member.lookup} are applied to distinguish expressions from declarations. Further, access control, ambiguity, and type rules are used to weed out syntactically valid but meaningless constructs. diff --git a/source/iostreams.tex b/source/iostreams.tex index 09ff08579a..e7fa8f0516 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -135,7 +135,7 @@ \rSec2[iostreams.threadsafety]{Thread safety} \pnum -Concurrent access to a stream object~(\ref{string.streams}, \ref{file.streams}), stream buffer +Concurrent access to a stream object\iref{string.streams,file.streams}, stream buffer object\iref{stream.buffers}, or C Library stream\iref{c.files} by multiple threads may result in a data race\iref{intro.multithread} unless otherwise specified\iref{iostream.objects}. \begin{note} @@ -3593,8 +3593,7 @@ Influences stream buffering in a way that is defined separately for each class derived from \tcode{basic_streambuf} -in this Clause~(\ref{stringbuf.virtuals}, -\ref{filebuf.virtuals}). +in this Clause\iref{stringbuf.virtuals,filebuf.virtuals}. \pnum \default @@ -3617,8 +3616,7 @@ the controlled sequences in a way that is defined separately for each class derived from \tcode{basic_streambuf} -in this Clause~(\ref{stringbuf.virtuals}, -\ref{filebuf.virtuals}). +in this Clause\iref{stringbuf.virtuals,filebuf.virtuals}. \pnum \default @@ -3640,8 +3638,7 @@ the controlled sequences in a way that is defined separately for each class derived from \tcode{basic_streambuf} -in this Clause~(\ref{stringbuf}, -\ref{filebuf}). +in this Clause\iref{stringbuf,filebuf}. \pnum \default @@ -4030,8 +4027,7 @@ \begin{footnote} That is, for each class derived from a specialization of \tcode{basic_streambuf} -in this Clause~(\ref{stringbuf}, -\ref{filebuf}), +in this Clause\iref{stringbuf,filebuf}, a specification of how consuming a character effects the associated output sequence is given. There is no requirement on a program-defined class. \end{footnote} @@ -8451,7 +8447,7 @@ Initializes the base class with \tcode{basic_istream(addressof(sb))}\iref{istream} and \tcode{sb} with -\tcode{basic_stringbuf(s, which | ios_base::in)}\linebreak(\ref{stringbuf.cons}). % avoid Overfull +\tcode{basic_stringbuf(s, which | ios_base::in)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} \indexlibraryctor{basic_istringstream}% @@ -8498,7 +8494,7 @@ Initializes the base class with \tcode{basic_istream(addressof(sb))}\iref{istream} and \tcode{sb} with -\tcode{basic_stringbuf(s, which | ios_base::in, a)}\linebreak(\ref{stringbuf.cons}). % avoid Overfull +\tcode{basic_stringbuf(s, which | ios_base::in, a)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} \indexlibraryctor{basic_istringstream}% @@ -8767,7 +8763,7 @@ Initializes the base class with \tcode{basic_ostream(addressof(sb))}\iref{ostream} and \tcode{sb} with -\tcode{basic_stringbuf(s, which | ios_base::out)}\linebreak(\ref{stringbuf.cons}). % avoid Overfull +\tcode{basic_stringbuf(s, which | ios_base::out)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} \indexlibraryctor{basic_ostringstream}% @@ -8781,7 +8777,7 @@ Initializes the base class with \tcode{basic_ostream(addressof(sb))}\iref{ostream} and \tcode{sb} with -\tcode{basic_stringbuf(which | ios_base::out, a)}\linebreak(\ref{stringbuf.cons}). % avoid Overfull +\tcode{basic_stringbuf(which | ios_base::out, a)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} \indexlibraryctor{basic_ostringstream}% @@ -8814,7 +8810,7 @@ Initializes the base class with \tcode{basic_ostream(addressof(sb))}\iref{ostream} and \tcode{sb} with -\tcode{basic_stringbuf(s, which | ios_base::out, a)}\linebreak(\ref{stringbuf.cons}). % avoid Overfull +\tcode{basic_stringbuf(s, which | ios_base::out, a)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} \indexlibraryctor{basic_ostringstream}% @@ -8835,7 +8831,7 @@ Initializes the base class with \tcode{basic_ostream(addressof(sb))}\iref{ostream} and \tcode{sb} with -\tcode{basic_stringbuf(s, which | ios_base::out)}\linebreak(\ref{stringbuf.cons}). % avoid Overfull +\tcode{basic_stringbuf(s, which | ios_base::out)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} \indexlibraryctor{basic_ostringstream}% diff --git a/source/iterators.tex b/source/iterators.tex index c2fe9a94da..14e44f0150 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -1554,8 +1554,8 @@ an iterator. Most algorithms will require additional operations to compare iterators with sentinels\iref{iterator.concept.sentinel}, to read\iref{iterator.concept.input} or write\iref{iterator.concept.output} values, or -to provide a richer set of iterator movements (\ref{iterator.concept.forward}, -\ref{iterator.concept.bidir}, \ref{iterator.concept.random.access}). +to provide a richer set of iterator movements\iref{iterator.concept.forward, +iterator.concept.bidir,iterator.concept.random.access}. \begin{codeblock} template @@ -1954,8 +1954,8 @@ set of requirements specifies operations for dereferencing and incrementing an iterator. Most algorithms will require additional operations to read\iref{input.iterators} or write\iref{output.iterators} values, or -to provide a richer set of iterator movements~(\ref{forward.iterators}, -\ref{bidirectional.iterators}, \ref{random.access.iterators}). +to provide a richer set of iterator movements\iref{forward.iterators, +bidirectional.iterators,random.access.iterators}. \pnum A type \tcode{X} meets the \defnoldconcept{Iterator} requirements if: diff --git a/source/lex.tex b/source/lex.tex index c6afecf493..77e09e142a 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -159,7 +159,7 @@ whether the sources for module units and header units on which the current translation unit has an interface -dependency (\ref{module.unit}, \ref{module.import}) +dependency\iref{module.unit,module.import} are required to be available. \begin{note} Source files, translation @@ -343,7 +343,7 @@ other than a multicharacter or non-encodable character literal or in a \grammarterm{string-literal} are encoded as a sequence of one or more code units, as determined -by the \grammarterm{encoding-prefix} (\ref{lex.ccon}, \ref{lex.string}); +by the \grammarterm{encoding-prefix}\iref{lex.ccon,lex.string}; this is termed the respective \defnadj{literal}{encoding}. The \defnadj{ordinary literal}{encoding} is the encoding applied to an ordinary character or string literal. diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 0685cc3c32..870871efcd 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -46,8 +46,9 @@ \pnum The language support library\iref{support} provides components that are -required by certain parts of the \Cpp{} language, such as memory allocation~(\ref{expr.new}, -\ref{expr.delete}) and exception processing\iref{except}. +required by certain parts of the \Cpp{} language, +such as memory allocation\iref{expr.new,expr.delete} and +exception processing\iref{except}. \pnum The concepts library\iref{concepts} describes library components that \Cpp{} @@ -864,7 +865,7 @@ and \ref{depr} do not describe copy/move constructors, assignment operators, or (non-virtual) destructors with the same apparent semantics as those that can be generated -by default~(\ref{class.copy.ctor}, \ref{class.copy.assign}, \ref{class.dtor}). +by default\iref{class.copy.ctor,class.copy.assign,class.dtor}. \indextext{constructor!copy}% \indextext{operator!assignment}% \indextext{destructor}% @@ -2680,7 +2681,7 @@ \pnum A \Cpp{} program may provide the definition for any of the following dynamic memory allocation function signatures declared in header -\tcode{}~(\ref{basic.stc.dynamic}, \ref{new.syn}): +\tcode{}\iref{basic.stc.dynamic,new.syn}: \indextext{\idxcode{new}!\idxcode{operator}!replaceable}% \indexlibrarymember{new}{operator}% @@ -2722,7 +2723,7 @@ \pnum The program's definitions are used instead of the default versions supplied by the implementation\iref{new.delete}. -Such replacement occurs prior to program startup~(\ref{basic.def.odr}, \ref{basic.start}). +Such replacement occurs prior to program startup\iref{basic.def.odr,basic.start}. \indextext{startup!program}% The program's declarations shall not be specified as \keyword{inline}. @@ -2788,7 +2789,7 @@ \required paragraph. \item -For handler functions~(\ref{new.handler}, \ref{terminate.handler}), +For handler functions\iref{new.handler,terminate.handler}, if the installed handler function does not implement the semantics of the applicable \required paragraph. @@ -2796,8 +2797,8 @@ For types used as template arguments when instantiating a template component, if the operations on the type do not implement the semantics of the applicable \emph{Requirements} -subclause~(\ref{allocator.requirements}, \ref{container.requirements}, \ref{iterator.requirements}, -\ref{algorithms.requirements}, \ref{numeric.requirements}). +subclause\iref{allocator.requirements,container.requirements,iterator.requirements, +algorithms.requirements,numeric.requirements}. Operations on such types can report a failure by throwing an exception unless otherwise specified. \item @@ -3177,7 +3178,7 @@ types. \begin{note} There is an implicit exception to this rule for types that are -described as synonyms~(\ref{dcl.typedef}, \ref{namespace.udecl}), such as +described as synonyms\iref{dcl.typedef,namespace.udecl}, such as \tcode{size_t}\iref{support.types} and \tcode{streamoff}\iref{stream.types}. \end{note} @@ -3241,8 +3242,8 @@ \end{footnote} Implementations should report errors by throwing exceptions of or derived -from the standard exception classes~(\ref{bad.alloc}, -\ref{support.exception}, \ref{std.exceptions}). +from the standard +exception classes\iref{bad.alloc,support.exception,std.exceptions}. \pnum An implementation may strengthen the diff --git a/source/limits.tex b/source/limits.tex index 4a9d97c2e5..e3b86f6ca1 100644 --- a/source/limits.tex +++ b/source/limits.tex @@ -37,7 +37,7 @@ or macro name\iref{cpp.replace} [1\,024]. \item% Number of -characters in an external identifier (\ref{lex.name}, \ref{basic.link}) [1\,024]. +characters in an external identifier\iref{lex.name,basic.link} [1\,024]. \item% External identifiers\iref{basic.link} in one translation unit [65\,536]. \item% diff --git a/source/locales.tex b/source/locales.tex index 982f09962a..e0533f7d71 100644 --- a/source/locales.tex +++ b/source/locales.tex @@ -725,7 +725,7 @@ \begin{example} A vector of strings \tcode{v} can be collated according to collation rules in locale \tcode{loc} -simply by~(\ref{alg.sort}, \ref{vector}): +simply by\iref{alg.sort,vector}: \begin{codeblock} std::sort(v.begin(), v.end(), loc); @@ -2044,7 +2044,7 @@ Extractor and inserter members of the standard iostreams use \tcode{num_get<>} and \tcode{num_put<>} member functions for formatting and parsing -numeric values~(\ref{istream.formatted.reqmts}, \ref{ostream.formatted.reqmts}). +numeric values\iref{istream.formatted.reqmts,ostream.formatted.reqmts}. \rSec3[locale.num.get]{Class template \tcode{num_get}} diff --git a/source/macros.tex b/source/macros.tex index af55ae9fae..08826b05c4 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -352,8 +352,19 @@ \newcommand{\xref}{\textsc{See also:}\space} \newcommand{\xrefc}[1]{\xref{} ISO C #1} -%% Inline parenthesized reference -\newcommand{\iref}[1]{\nolinebreak[3] (\ref{#1})} +%% Inline comma-separated parenthesized references +\ExplSyntaxOn +\NewDocumentCommand \iref { m } { + \clist_set:Nx \l_tmpa_clist { #1 } + \nolinebreak[3] ~ ( + \clist_map_inline:Nn \l_tmpa_clist { + \clist_put_right:Nn \g_tmpa_clist { \ref{##1} } + } + \clist_use:Nn \g_tmpa_clist { ,~ } + ) + \clist_clear:N \g_tmpa_clist +} +\ExplSyntaxOff %% Inline non-parenthesized table reference (override memoir's \tref) \renewcommand{\tref}[1]{\hyperref[tab:#1]{\tablerefname \nolinebreak[3] \ref*{tab:#1}}} diff --git a/source/modules.tex b/source/modules.tex index 0f0249c09f..cfd4928bb7 100644 --- a/source/modules.tex +++ b/source/modules.tex @@ -149,7 +149,7 @@ \item Otherwise, if the declaration \begin{itemize} \item is a replaceable global allocation or deallocation -function (\ref{new.delete.single}, \ref{new.delete.array}), or +function\iref{new.delete.single,new.delete.array}, or \item is a \grammarterm{namespace-definition} with external linkage, or \item appears within a \grammarterm{linkage-specification}, \end{itemize} @@ -810,7 +810,7 @@ \item where definitions for inline functions and templates -must appear~(\ref{basic.def.odr}, \ref{dcl.inline}, \ref{temp.pre}), +must appear\iref{basic.def.odr,dcl.inline,temp.pre}, \item the instantiation contexts of templates @@ -858,7 +858,7 @@ \pnum During the implicit definition of -a defaulted function (\ref{special}, \ref{class.compare.default}), +a defaulted function\iref{special,class.compare.default}, the instantiation context is the union of the instantiation context from the definition of the class and the instantiation context of the program construct that diff --git a/source/overloading.tex b/source/overloading.tex index fb83380ea9..516ef0ed39 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -239,8 +239,7 @@ is allowed in an implicit conversion sequence, special rules apply when selecting -the best user-defined conversion~(\ref{over.match.best}, -\ref{over.best.ics}). +the best user-defined conversion\iref{over.match.best,over.best.ics}. \begin{example} \begin{codeblock} class T { @@ -285,8 +284,7 @@ \pnum In each case where a candidate is a function template, candidate function template specializations -are generated using template argument deduction~(\ref{temp.over}, -\ref{temp.deduct}). +are generated using template argument deduction\iref{temp.over,temp.deduct}. If a constructor template or conversion function template has an \grammarterm{explicit-specifier} whose \grammarterm{constant-expression} is value-dependent\iref{temp.dep}, @@ -318,7 +316,7 @@ \pnum A -defaulted move special member function~(\ref{class.copy.ctor}, \ref{class.copy.assign}) +defaulted move special member function\iref{class.copy.ctor,class.copy.assign} that is defined as deleted is excluded from the set of candidate functions in all contexts. A constructor inherited from class type \tcode{C}\iref{class.inhctor.init} @@ -694,8 +692,7 @@ the set of non-member candidates is empty; otherwise, it includes the result of unqualified lookup for \tcode{\keyword{operator}@} -in the rewritten function call -(\ref{basic.lookup.unqual}, \ref{basic.lookup.argdep}), +in the rewritten function call\iref{basic.lookup.unqual,basic.lookup.argdep}, ignoring all member functions. However, if no operand has a class type, only those non-member functions in the lookup set that have a first parameter of type @@ -1121,7 +1118,7 @@ In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed. \begin{note} -This differs from other situations~(\ref{over.match.ctor}, \ref{over.match.copy}), +This differs from other situations\iref{over.match.ctor,over.match.copy}, where only converting constructors are considered for copy-initialization. This restriction only applies if this initialization is part of the final result of overload @@ -1857,7 +1854,7 @@ sequence of conversions is an implicit conversion as defined in \ref{conv}, which means it is governed by the rules for initialization of an object or reference by a single -expression~(\ref{dcl.init}, \ref{dcl.init.ref}). +expression\iref{dcl.init,dcl.init.ref}. \pnum Implicit conversion sequences are concerned only with the type, @@ -2830,8 +2827,7 @@ The target can be \begin{itemize} \item -an object or reference being initialized~(\ref{dcl.init}, \ref{dcl.init.ref}, -\ref{dcl.init.list}), +an object or reference being initialized\iref{dcl.init,dcl.init.ref,dcl.init.list}, \item the left side of an assignment\iref{expr.ass}, \item @@ -2841,8 +2837,7 @@ \item the return value of a function, operator function, or conversion\iref{stmt.return}, \item -an explicit type conversion~(\ref{expr.type.conv}, \ref{expr.static.cast}, -\ref{expr.cast}), or +an explicit type conversion\iref{expr.type.conv,expr.static.cast,expr.cast}, or \item a non-type \grammarterm{template-parameter}\iref{temp.arg.nontype}. @@ -2866,8 +2861,8 @@ \end{note} \pnum -The specialization, if any, generated by template argument deduction -(\ref{temp.over}, \ref{temp.deduct.funcaddr}, \ref{temp.arg.explicit}) +The specialization, if any, generated by template argument +deduction\iref{temp.over,temp.deduct.funcaddr,temp.arg.explicit} for each function template named is added to the set of selected functions considered. @@ -3849,7 +3844,7 @@ template double operator "" _\u03C0(); // OK, UCN for lowercase pi float operator ""_e(const char*); // OK float operator ""E(const char*); // ill-formed, no diagnostic required: - // reserved literal suffix~(\ref{usrlit.suffix}, \ref{lex.ext}) + // reserved literal suffix\iref{usrlit.suffix,lex.ext} double operator""_Bq(long double); // OK, does not use the reserved \grammarterm{identifier} \tcode{_Bq}\iref{lex.name} double operator"" _Bq(long double); // ill-formed, no diagnostic required: // uses the reserved \grammarterm{identifier} \tcode{_Bq}\iref{lex.name} diff --git a/source/preprocessor.tex b/source/preprocessor.tex index 465b3420bd..7528bd6c83 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -1229,7 +1229,7 @@ If the substitution of \mname{VA_ARGS} as neither an operand of \tcode{\#} nor \tcode{\#\#} consists of no preprocessing tokens, the argument consists of -a single placemarker preprocessing token~(\ref{cpp.concat}, \ref{cpp.rescan}). +a single placemarker preprocessing token\iref{cpp.concat,cpp.rescan}. Otherwise, the argument consists of the results of the expansion of the contained \grammarterm{pp-tokens} as the replacement list of the current function-like macro diff --git a/source/regex.tex b/source/regex.tex index 9800293c79..5ee8aa28ed 100644 --- a/source/regex.tex +++ b/source/regex.tex @@ -2104,8 +2104,8 @@ \indextext{requirements!container}% \indextext{requirements!sequence}% The class template \tcode{match_results} meets the requirements of an -allocator-aware container and of a sequence container -(\ref{container.requirements.general}, \ref{sequence.reqmts}) +allocator-aware container and of +a sequence container\iref{container.requirements.general,sequence.reqmts} except that only copy assignment, move assignment, and diff --git a/source/statements.tex b/source/statements.tex index e384cbd5c1..65b4534ee1 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -832,7 +832,7 @@ \pnum The destructor for the result object -is potentially invoked~(\ref{class.dtor}, \ref{except.ctor}). +is potentially invoked\iref{class.dtor,except.ctor}. \begin{example} \begin{codeblock} class A { diff --git a/source/support.tex b/source/support.tex index ac603a4846..40ceef1aae 100644 --- a/source/support.tex +++ b/source/support.tex @@ -3225,7 +3225,7 @@ \remarks The message may be a null-terminated multibyte string\iref{multibyte.strings}, suitable for conversion and display as a -\tcode{wstring}~(\ref{string.classes}, \ref{locale.codecvt}). +\tcode{wstring}\iref{string.classes,locale.codecvt}. \end{itemdescr} \rSec2[bad.cast]{Class \tcode{bad_cast}} @@ -3635,7 +3635,7 @@ \remarks The message may be a null-terminated multibyte string\iref{multibyte.strings}, suitable for conversion and display as a -\tcode{wstring}~(\ref{string.classes}, \ref{locale.codecvt}). +\tcode{wstring}\iref{string.classes,locale.codecvt}. The return value remains valid until the exception object from which it is obtained is destroyed or a non-\keyword{const} member function of the exception object is called. @@ -4277,7 +4277,8 @@ \pnum The \tcode{partial_ordering} type is typically used as the result type of a three-way comparison operator\iref{expr.spaceship} -that (a) admits all of the six two-way comparison operators (\ref{expr.rel}, \ref{expr.eq}), +that (a) admits all of the six +two-way comparison operators\iref{expr.rel,expr.eq}, (b) does not imply substitutability, and (c) permits two values to be incomparable. \begin{footnote} @@ -4394,7 +4395,8 @@ \pnum The \tcode{weak_ordering} type is typically used as the result type of a three-way comparison operator\iref{expr.spaceship} -that (a) admits all of the six two-way comparison operators (\ref{expr.rel}, \ref{expr.eq}), +that (a) admits all of the six +two-way comparison operators\iref{expr.rel,expr.eq}, and (b) does not imply substitutability. \indexlibraryglobal{weak_ordering}% @@ -4518,7 +4520,8 @@ \pnum The \tcode{strong_ordering} type is typically used as the result type of a three-way comparison operator\iref{expr.spaceship} -that (a) admits all of the six two-way comparison operators (\ref{expr.rel}, \ref{expr.eq}), +that (a) admits all of the six +two-way comparison operators\iref{expr.rel,expr.eq}, and (b) does imply substitutability. \indexlibraryglobal{strong_ordering}% @@ -5869,7 +5872,7 @@ \item initialization of a variable with static storage duration -requiring dynamic initialization~(\ref{basic.start.dynamic}, \ref{stmt.dcl}) +requiring dynamic initialization\iref{basic.start.dynamic,stmt.dcl} \begin{footnote} Such initialization can occur because it is the first odr-use\iref{term.odr.use} of that variable. \end{footnote} diff --git a/source/templates.tex b/source/templates.tex index a831fc7687..dce8fc693d 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -3180,7 +3180,7 @@ \pnum A partial specialization may be declared in any scope in which the corresponding primary template -may be defined~(\ref{dcl.meaning}, \ref{class.mem}, \ref{temp.mem}). +may be defined\iref{dcl.meaning,class.mem,temp.mem}. \begin{example} \begin{codeblock} template struct A { @@ -3490,7 +3490,7 @@ If a member template of a class template is partially specialized, the member template partial specializations are member templates of the enclosing class template; -if the enclosing class template is instantiated~(\ref{temp.inst}, \ref{temp.explicit}), +if the enclosing class template is instantiated\iref{temp.inst,temp.explicit}, a declaration for every member template partial specialization is also instantiated as part of creating the members of the class template specialization. @@ -3790,7 +3790,7 @@ when a placement operator delete that is a function template specialization -is selected to match a placement operator new~(\ref{basic.stc.dynamic.deallocation}, \ref{expr.new}); +is selected to match a placement operator new\iref{basic.stc.dynamic.deallocation,expr.new}; \item when a friend function declaration\iref{temp.friend}, an explicit instantiation\iref{temp.explicit} or an explicit specialization\iref{temp.expl.spec} refers to @@ -4201,8 +4201,8 @@ \begin{note} Some dependent names are also looked up during parsing to determine that they are dependent or to interpret following \tcode{<} tokens. -Uses of other names might be type-dependent or value-dependent -(\ref{temp.dep.expr}, \ref{temp.dep.constexpr}). +Uses of other names might be type-dependent or +value-dependent\iref{temp.dep.expr,temp.dep.constexpr}. A \grammarterm{using-declarator} is never dependent in a specialization and is therefore replaced during lookup for that specialization\iref{basic.lookup}. \end{note} @@ -4528,8 +4528,9 @@ class template itself. Otherwise, it is a \grammarterm{type-name} equivalent to the \grammarterm{template-name} -followed by the template argument list~(\ref{temp.decls.general}, -\ref{temp.arg.general}) of the class template +followed by +the template argument list\iref{temp.decls.general,temp.arg.general} +of the class template enclosed in \tcode{<>}. \pnum @@ -4639,8 +4640,7 @@ the \grammarterm{template-parameter-list}). \begin{note} The scope of a class template, -including its non-dependent base classes -(\ref{temp.dep.type}, \ref{class.member.lookup}), +including its non-dependent base classes\iref{temp.dep.type,class.member.lookup}, is searched before its template parameter scope. \end{note} \begin{example} @@ -6237,7 +6237,7 @@ the translation unit containing the explicit instantiation, provided that the associated constraints, if any, of that member are satisfied by the template arguments of the explicit -instantiation~(\ref{temp.constr.decl}, \ref{temp.constr.constr}), +instantiation\iref{temp.constr.decl,temp.constr.constr}, except as described below. \begin{note} In addition, it will typically be an explicit instantiation of certain @@ -6356,7 +6356,7 @@ \pnum An explicit specialization may be declared in any scope in which the corresponding primary template -may be defined~(\ref{dcl.meaning}, \ref{class.mem}, \ref{temp.mem}). +may be defined\iref{dcl.meaning,class.mem,temp.mem}. \pnum An explicit specialization does not introduce a name\iref{basic.scope.scope}. @@ -6799,7 +6799,7 @@ \pnum Template arguments shall not be specified when referring to a specialization of -a constructor template~(\ref{class.ctor}, \ref{class.qual}). +a constructor template\iref{class.ctor,class.qual}. \pnum A template argument list may be specified when referring to a specialization @@ -8619,7 +8619,7 @@ for explicit instantiations\iref{temp.explicit}, explicit specializations\iref{temp.expl.spec}, and certain friend declarations\iref{temp.friend}. This is also done to determine whether a deallocation function template specialization matches a placement -\tcode{operator new}~(\ref{basic.stc.dynamic.deallocation}, \ref{expr.new}). +\tcode{operator new}\iref{basic.stc.dynamic.deallocation,expr.new}. In all these cases, \tcode{P} is the type of the function template being considered as a potential match and \tcode{A} is either the function type from the declaration diff --git a/source/threads.tex b/source/threads.tex index 4476674e95..5f8da57d2f 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -7244,8 +7244,7 @@ \begin{itemize} \item If \tcode{launch::async} is set in \tcode{policy}, calls -\tcode{invoke(auto(std::forward(f)), auto(std::for\-ward(args))...)} -(\ref{func.require}, \ref{thread.thread.constr}) +\tcode{invoke(auto(std::forward(f)), auto(std::for\-ward(args))...)}\iref{func.require,thread.thread.constr} as if in a new thread of execution represented by a \tcode{thread} object with the values produced by \tcode{auto} being materialized\iref{conv.rval} in the thread that called \tcode{async}. diff --git a/source/utilities.tex b/source/utilities.tex index 69c0c4ad75..a18164278f 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -16163,8 +16163,8 @@ \pnum A \defnx{function object type}{function object!type} is an object type\iref{term.object.type} that can be the type of the -\grammarterm{postfix-expression} in a function call -(\ref{expr.call}, \ref{over.match.call}). +\grammarterm{postfix-expression} +in a function call\iref{expr.call,over.match.call}. \begin{footnote} Such a type is a function pointer or a class type which has a member \tcode{operator()} or a class type @@ -16751,7 +16751,7 @@ \pnum The library provides basic function object classes for all of the arithmetic -operators in the language~(\ref{expr.mul}, \ref{expr.add}). +operators in the language\iref{expr.mul,expr.add}. \rSec3[arithmetic.operations.plus]{Class template \tcode{plus}} @@ -17012,7 +17012,7 @@ \pnum The library provides basic function object classes for all of the comparison -operators in the language~(\ref{expr.rel}, \ref{expr.eq}). +operators in the language\iref{expr.rel,expr.eq}. \pnum For templates \tcode{less}, \tcode{greater}, \tcode{less_equal}, and @@ -17546,7 +17546,7 @@ \pnum The library provides basic function object classes for all of the logical -operators in the language~(\ref{expr.log.and}, \ref{expr.log.or}, \ref{expr.unary.op}). +operators in the language\iref{expr.log.and,expr.log.or,expr.unary.op}. \rSec3[logical.operations.and]{Class template \tcode{logical_and}} @@ -17681,8 +17681,7 @@ \pnum The library provides basic function object classes for all of the bitwise -operators in the language~(\ref{expr.bit.and}, \ref{expr.or}, -\ref{expr.xor}, \ref{expr.unary.op}). +operators in the language\iref{expr.bit.and,expr.or,expr.xor,expr.unary.op}. \rSec3[bitwise.operations.and]{Class template \tcode{bit_and}} @@ -20148,7 +20147,7 @@ \pnum For the purpose of defining the templates in this subclause, a function call expression \tcode{declval()} for any type \tcode{T} -is considered to be a trivial~(\ref{term.trivial.type}, \ref{special}) function call +is considered to be a trivial\iref{term.trivial.type,special} function call that is not an odr-use\iref{term.odr.use} of \tcode{declval} in the context of the corresponding definition notwithstanding the restrictions of~\ref{declval}. @@ -20408,7 +20407,7 @@ \tcode{is_constructible_v} is \tcode{true} and the variable definition for \tcode{is_constructible}, as defined below, is known to call - no operation that is not trivial~(\ref{term.trivial.type}, \ref{special}). & + no operation that is not trivial\iref{term.trivial.type,special}. & \tcode{T} and all types in the template parameter pack \tcode{Args} shall be complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep @@ -20442,8 +20441,8 @@ \tcode{template}\br \tcode{struct is_trivially_assignable;} & \tcode{is_assignable_v} is \tcode{true} and the assignment, as defined by - \tcode{is_assignable}, is known to call no operation that is not trivial - ~(\ref{term.trivial.type}, \ref{special}). & + \tcode{is_assignable}, is known to call no operation that is not + trivial\iref{term.trivial.type,special}. & \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep @@ -20878,7 +20877,7 @@ \pnum For the purpose of defining the templates in this subclause, a function call expression \tcode{declval()} for any type \tcode{T} -is considered to be a trivial~(\ref{term.trivial.type}, \ref{special}) function call +is considered to be a trivial\iref{term.trivial.type,special} function call that is not an odr-use\iref{term.odr.use} of \tcode{declval} in the context of the corresponding definition notwithstanding the restrictions of~\ref{declval}. From b652db7a7f93b4dacef96ec8071f2d3cc73f83e1 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 15 Dec 2021 22:53:11 +0100 Subject: [PATCH 155/182] [check] Check for "(\ref", recommend \iref --- tools/check-source.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/check-source.sh b/tools/check-source.sh index de4caf3c7d..9a90e8b4db 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -85,6 +85,10 @@ grep -n 'ucode{[^}]*[^0-9a-f}][^}]*}' $texfiles | grep -n 'unicode{[^}]*[^0-9a-f}][^}]*}' $texfiles | fail 'use lowercase hex digits inside \\unicode' || failed=1 +# Use \iref instead of "(\ref", except for subclause ranges +grep -n '.(\\ref' $texfiles | grep -v -- "--" | + fail 'use \\iref instead of (\\ref' || failed=1 + # Use \xrefc instead of "ISO C x.y.z" grep -n "^ISO C [0-9]*\." $texfiles | fail 'use \\xrefc instead' || failed=1 From 2cd31adb2033b4ae82339ef270bc058128cbd199 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 23 Feb 2022 22:38:13 +0100 Subject: [PATCH 156/182] [bit] Move into [utilities] --- source/numerics.tex | 415 ------------------------------------------ source/utilities.tex | 417 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 416 insertions(+), 416 deletions(-) diff --git a/source/numerics.tex b/source/numerics.tex index 735d2a3238..811f7d9d90 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -20,7 +20,6 @@ \ref{numeric.requirements} & Requirements & \\ \rowsep \ref{cfenv} & Floating-point environment & \tcode{} \\ \rowsep \ref{complex.numbers} & Complex numbers & \tcode{} \\ \rowsep -\ref{bit} & Bit manipulation & \tcode{} \\ \rowsep \ref{rand} & Random number generation & \tcode{} \\ \rowsep \ref{numarray} & Numeric arrays & \tcode{} \\ \rowsep \ref{c.math} & Mathematical functions for floating-point types & @@ -1274,420 +1273,6 @@ \end{itemdescr} -\rSec1[bit]{Bit manipulation} - -\rSec2[bit.general]{General} - -\pnum -The header \libheaderdef{bit} provides components to access, -manipulate and process both individual bits and bit sequences. - -\rSec2[bit.syn]{Header \tcode{} synopsis} - -\begin{codeblock} -namespace std { - // \ref{bit.cast}, \tcode{bit_cast} - template - constexpr To bit_cast(const From& from) noexcept; - - // \ref{bit.byteswap}, \tcode{byteswap} - template - constexpr T byteswap(T value) noexcept; - - // \ref{bit.pow.two}, integral powers of 2 - template - constexpr bool has_single_bit(T x) noexcept; - template - constexpr T bit_ceil(T x); - template - constexpr T bit_floor(T x) noexcept; - template - constexpr T bit_width(T x) noexcept; - - // \ref{bit.rotate}, rotating - template - [[nodiscard]] constexpr T rotl(T x, int s) noexcept; - template - [[nodiscard]] constexpr T rotr(T x, int s) noexcept; - - // \ref{bit.count}, counting - template - constexpr int countl_zero(T x) noexcept; - template - constexpr int countl_one(T x) noexcept; - template - constexpr int countr_zero(T x) noexcept; - template - constexpr int countr_one(T x) noexcept; - template - constexpr int popcount(T x) noexcept; - - // \ref{bit.endian}, endian - enum class endian { - little = @\seebelow@, - big = @\seebelow@, - native = @\seebelow@ - }; -} -\end{codeblock} - -\rSec2[bit.cast]{Function template \tcode{bit_cast}} - -\indexlibraryglobal{bit_cast}% -\begin{itemdecl} -template - constexpr To bit_cast(const From& from) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\begin{itemize} -\item \tcode{sizeof(To) == sizeof(From)} is \tcode{true}; -\item \tcode{is_trivially_copyable_v} is \tcode{true}; and -\item \tcode{is_trivially_copyable_v} is \tcode{true}. -\end{itemize} - -\pnum -\returns -An object of type \tcode{To}. -Implicitly creates objects nested within the result\iref{intro.object}. -Each bit of the value representation of the result -is equal to the corresponding bit in the object representation -of \tcode{from}. Padding bits of the result are unspecified. -For the result and each object created within it, -if there is no value of the object's type corresponding to the -value representation produced, the behavior is undefined. -If there are multiple such values, which value is produced is unspecified. -A bit in the value representation of the result is indeterminate if -it does not correspond to a bit in the value representation of \tcode{from} or -corresponds to a bit of an object that is not within its lifetime or -has an indeterminate value\iref{basic.indet}. -For each bit in the value representation of the result that is indeterminate, -the smallest object containing that bit has an indeterminate value; -the behavior is undefined unless that object is -of unsigned ordinary character type or \tcode{std::byte} type. -The result does not otherwise contain any indeterminate values. - -\pnum -\remarks -This function is \keyword{constexpr} if and only if -\tcode{To}, \tcode{From}, and the types of all subobjects -of \tcode{To} and \tcode{From} are types \tcode{T} such that: -\begin{itemize} -\item \tcode{is_union_v} is \tcode{false}; -\item \tcode{is_pointer_v} is \tcode{false}; -\item \tcode{is_member_pointer_v} is \tcode{false}; -\item \tcode{is_volatile_v} is \tcode{false}; and -\item \tcode{T} has no non-static data members of reference type. -\end{itemize} -\end{itemdescr} - -\rSec2[bit.byteswap]{\tcode{byteswap}} - -\indexlibraryglobal{byteswap}% -\begin{itemdecl} -template - constexpr T byteswap(T value) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} models \libconcept{integral}. - -\pnum -\mandates -\tcode{T} does not have padding bits\iref{basic.types.general}. - -\pnum -Let the sequence $R$ comprise -the bytes of the object representation of \tcode{value} in reverse order. - -\pnum -\returns -An object \tcode{v} of type \tcode{T} -such that each byte in the object representation of \tcode{v} is equal to -the byte in the corresponding position in $R$. -\end{itemdescr} - -\rSec2[bit.pow.two]{Integral powers of 2} - -\indexlibraryglobal{has_single_bit}% -\begin{itemdecl} -template - constexpr bool has_single_bit(T x) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -\tcode{true} if \tcode{x} is an integral power of two; -\tcode{false} otherwise. - -\end{itemdescr} - -\indexlibraryglobal{bit_ceil}% -\begin{itemdecl} -template - constexpr T bit_ceil(T x); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let $N$ be the smallest power of 2 greater than or equal to \tcode{x}. - -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\expects -$N$ is representable as a value of type \tcode{T}. - -\pnum -\returns -$N$. - -\pnum -\throws -Nothing. - -\pnum -\remarks -A function call expression -that violates the precondition in the \expects element -is not a core constant expression\iref{expr.const}. -\end{itemdescr} - -\indexlibraryglobal{bit_floor}% -\begin{itemdecl} -template - constexpr T bit_floor(T x) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -If \tcode{x == 0}, \tcode{0}; -otherwise the maximal value \tcode{y} -such that \tcode{has_single_bit(y)} is \tcode{true} and \tcode{y <= x}. - -\end{itemdescr} - -\indexlibraryglobal{bit_width}% -\begin{itemdecl} -template - constexpr T bit_width(T x) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -If \tcode{x == 0}, \tcode{0}; -otherwise one plus the base-2 logarithm of \tcode{x}, -with any fractional part discarded. - -\end{itemdescr} - -\rSec2[bit.rotate]{Rotating} - -\pnum -In the following descriptions, -let \tcode{N} denote \tcode{numeric_limits::digits}. - -\begin{itemdecl} -template - [[nodiscard]] constexpr T rotl(T x, int s) noexcept; -\end{itemdecl} - -\indexlibraryglobal{rotl}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -Let \tcode{r} be \tcode{s \% N}. - -\pnum -\returns -If \tcode{r} is \tcode{0}, \tcode{x}; -if \tcode{r} is positive, \tcode{(x << r) | (x >> (N - r))}; -if \tcode{r} is negative, \tcode{rotr(x, -r)}. -\end{itemdescr} - -\begin{itemdecl} -template - [[nodiscard]] constexpr T rotr(T x, int s) noexcept; -\end{itemdecl} - -\indexlibraryglobal{rotr}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -Let \tcode{r} be \tcode{s \% N}. - -\pnum -\returns -If \tcode{r} is \tcode{0}, \tcode{x}; -if \tcode{r} is positive, \tcode{(x >> r) | (x << (N - r))}; -if \tcode{r} is negative, \tcode{rotl(x, -r)}. -\end{itemdescr} - -\rSec2[bit.count]{Counting} - -\pnum -In the following descriptions, -let \tcode{N} denote \tcode{numeric_limits::digits}. - -\begin{itemdecl} -template - constexpr int countl_zero(T x) noexcept; -\end{itemdecl} - -\indexlibraryglobal{countl_zero}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -The number of consecutive \tcode{0} bits in the value of \tcode{x}, -starting from the most significant bit. -\begin{note} -Returns \tcode{N} if \tcode{x == 0}. -\end{note} -\end{itemdescr} - -\begin{itemdecl} -template - constexpr int countl_one(T x) noexcept; -\end{itemdecl} - -\indexlibraryglobal{countl_one}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -The number of consecutive \tcode{1} bits in the value of \tcode{x}, -starting from the most significant bit. -\begin{note} -Returns \tcode{N} if \tcode{x == numeric_limits::max()}. -\end{note} -\end{itemdescr} - -\begin{itemdecl} -template - constexpr int countr_zero(T x) noexcept; -\end{itemdecl} - -\indexlibraryglobal{countr_zero}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -The number of consecutive \tcode{0} bits in the value of \tcode{x}, -starting from the least significant bit. -\begin{note} -Returns \tcode{N} if \tcode{x == 0}. -\end{note} -\end{itemdescr} - -\begin{itemdecl} -template - constexpr int countr_one(T x) noexcept; -\end{itemdecl} - -\indexlibraryglobal{countr_one}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -The number of consecutive \tcode{1} bits in the value of \tcode{x}, -starting from the least significant bit. -\begin{note} -Returns \tcode{N} if \tcode{x == numeric_limits::max()}. -\end{note} -\end{itemdescr} - -\begin{itemdecl} -template - constexpr int popcount(T x) noexcept; -\end{itemdecl} - -\indexlibraryglobal{popcount}% -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an unsigned integer type\iref{basic.fundamental}. - -\pnum -\returns -The number of \tcode{1} bits in the value of \tcode{x}. -\end{itemdescr} - -\rSec2[bit.endian]{Endian} - -\pnum -Two common methods of byte ordering in multibyte scalar types are big-endian -and little-endian in the execution environment. Big-endian is a format for -storage of binary data in which the most significant byte is placed first, -with the rest in descending order. Little-endian is a format for storage of -binary data in which the least significant byte is placed first, with the rest -in ascending order. This subclause describes the endianness of the scalar types -of the execution environment. - -\indexlibraryglobal{endian}% -\indexlibrarymember{little}{endian}% -\indexlibrarymember{big}{endian}% -\indexlibrarymember{native}{endian}% -\begin{itemdecl} -enum class endian { - little = @\seebelow@, - big = @\seebelow@, - native = @\seebelow@ -}; -\end{itemdecl} - -\begin{itemdescr} -\pnum -If all scalar types have size 1 byte, then all of \tcode{endian::little}, -\tcode{endian::big}, and \tcode{endian::native} have the same value. -Otherwise, \tcode{endian::little} is not equal to \tcode{endian::big}. -If all scalar types are big-endian, \tcode{endian::native} is -equal to \tcode{endian::big}. -If all scalar types are little-endian, \tcode{endian::native} is -equal to \tcode{endian::little}. -Otherwise, \tcode{endian::native} is not equal -to either \tcode{endian::big} or \tcode{endian::little}. -\end{itemdescr} - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/source/utilities.tex b/source/utilities.tex index a18164278f..c18b5faa36 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -28,7 +28,8 @@ \ref{type.index} & Type indexes & \tcode{} \\ \rowsep \ref{execpol} & Execution policies & \tcode{} \\ \rowsep \ref{charconv} & Primitive numeric conversions & \tcode{} \\ \rowsep -\ref{format} & Formatting & \tcode{} \\ +\ref{format} & Formatting & \tcode{} \\ \rowsep +\ref{bit} & Bit manipulation & \tcode{} \\ \end{libsumtab} \rSec1[utility]{Utility components} @@ -24856,3 +24857,417 @@ \ensures \tcode{strcmp(what(), what_arg) == 0}. \end{itemdescr} + +\rSec1[bit]{Bit manipulation} + +\rSec2[bit.general]{General} + +\pnum +The header \libheaderdef{bit} provides components to access, +manipulate and process both individual bits and bit sequences. + +\rSec2[bit.syn]{Header \tcode{} synopsis} + +\begin{codeblock} +namespace std { + // \ref{bit.cast}, \tcode{bit_cast} + template + constexpr To bit_cast(const From& from) noexcept; + + // \ref{bit.byteswap}, \tcode{byteswap} + template + constexpr T byteswap(T value) noexcept; + + // \ref{bit.pow.two}, integral powers of 2 + template + constexpr bool has_single_bit(T x) noexcept; + template + constexpr T bit_ceil(T x); + template + constexpr T bit_floor(T x) noexcept; + template + constexpr T bit_width(T x) noexcept; + + // \ref{bit.rotate}, rotating + template + [[nodiscard]] constexpr T rotl(T x, int s) noexcept; + template + [[nodiscard]] constexpr T rotr(T x, int s) noexcept; + + // \ref{bit.count}, counting + template + constexpr int countl_zero(T x) noexcept; + template + constexpr int countl_one(T x) noexcept; + template + constexpr int countr_zero(T x) noexcept; + template + constexpr int countr_one(T x) noexcept; + template + constexpr int popcount(T x) noexcept; + + // \ref{bit.endian}, endian + enum class endian { + little = @\seebelow@, + big = @\seebelow@, + native = @\seebelow@ + }; +} +\end{codeblock} + +\rSec2[bit.cast]{Function template \tcode{bit_cast}} + +\indexlibraryglobal{bit_cast}% +\begin{itemdecl} +template + constexpr To bit_cast(const From& from) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item \tcode{sizeof(To) == sizeof(From)} is \tcode{true}; +\item \tcode{is_trivially_copyable_v} is \tcode{true}; and +\item \tcode{is_trivially_copyable_v} is \tcode{true}. +\end{itemize} + +\pnum +\returns +An object of type \tcode{To}. +Implicitly creates objects nested within the result\iref{intro.object}. +Each bit of the value representation of the result +is equal to the corresponding bit in the object representation +of \tcode{from}. Padding bits of the result are unspecified. +For the result and each object created within it, +if there is no value of the object's type corresponding to the +value representation produced, the behavior is undefined. +If there are multiple such values, which value is produced is unspecified. +A bit in the value representation of the result is indeterminate if +it does not correspond to a bit in the value representation of \tcode{from} or +corresponds to a bit of an object that is not within its lifetime or +has an indeterminate value\iref{basic.indet}. +For each bit in the value representation of the result that is indeterminate, +the smallest object containing that bit has an indeterminate value; +the behavior is undefined unless that object is +of unsigned ordinary character type or \tcode{std::byte} type. +The result does not otherwise contain any indeterminate values. + +\pnum +\remarks +This function is \keyword{constexpr} if and only if +\tcode{To}, \tcode{From}, and the types of all subobjects +of \tcode{To} and \tcode{From} are types \tcode{T} such that: +\begin{itemize} +\item \tcode{is_union_v} is \tcode{false}; +\item \tcode{is_pointer_v} is \tcode{false}; +\item \tcode{is_member_pointer_v} is \tcode{false}; +\item \tcode{is_volatile_v} is \tcode{false}; and +\item \tcode{T} has no non-static data members of reference type. +\end{itemize} +\end{itemdescr} + +\rSec2[bit.byteswap]{\tcode{byteswap}} + +\indexlibraryglobal{byteswap}% +\begin{itemdecl} +template + constexpr T byteswap(T value) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} models \libconcept{integral}. + +\pnum +\mandates +\tcode{T} does not have padding bits\iref{basic.types.general}. + +\pnum +Let the sequence $R$ comprise +the bytes of the object representation of \tcode{value} in reverse order. + +\pnum +\returns +An object \tcode{v} of type \tcode{T} +such that each byte in the object representation of \tcode{v} is equal to +the byte in the corresponding position in $R$. +\end{itemdescr} + +\rSec2[bit.pow.two]{Integral powers of 2} + +\indexlibraryglobal{has_single_bit}% +\begin{itemdecl} +template + constexpr bool has_single_bit(T x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +\tcode{true} if \tcode{x} is an integral power of two; +\tcode{false} otherwise. + +\end{itemdescr} + +\indexlibraryglobal{bit_ceil}% +\begin{itemdecl} +template + constexpr T bit_ceil(T x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $N$ be the smallest power of 2 greater than or equal to \tcode{x}. + +\pnum +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +\expects +$N$ is representable as a value of type \tcode{T}. + +\pnum +\returns +$N$. + +\pnum +\throws +Nothing. + +\pnum +\remarks +A function call expression +that violates the precondition in the \expects element +is not a core constant expression\iref{expr.const}. +\end{itemdescr} + +\indexlibraryglobal{bit_floor}% +\begin{itemdecl} +template + constexpr T bit_floor(T x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +If \tcode{x == 0}, \tcode{0}; +otherwise the maximal value \tcode{y} +such that \tcode{has_single_bit(y)} is \tcode{true} and \tcode{y <= x}. + +\end{itemdescr} + +\indexlibraryglobal{bit_width}% +\begin{itemdecl} +template + constexpr T bit_width(T x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +If \tcode{x == 0}, \tcode{0}; +otherwise one plus the base-2 logarithm of \tcode{x}, +with any fractional part discarded. + +\end{itemdescr} + +\rSec2[bit.rotate]{Rotating} + +\pnum +In the following descriptions, +let \tcode{N} denote \tcode{numeric_limits::digits}. + +\begin{itemdecl} +template + [[nodiscard]] constexpr T rotl(T x, int s) noexcept; +\end{itemdecl} + +\indexlibraryglobal{rotl}% +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +Let \tcode{r} be \tcode{s \% N}. + +\pnum +\returns +If \tcode{r} is \tcode{0}, \tcode{x}; +if \tcode{r} is positive, \tcode{(x << r) | (x >> (N - r))}; +if \tcode{r} is negative, \tcode{rotr(x, -r)}. +\end{itemdescr} + +\begin{itemdecl} +template + [[nodiscard]] constexpr T rotr(T x, int s) noexcept; +\end{itemdecl} + +\indexlibraryglobal{rotr}% +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +Let \tcode{r} be \tcode{s \% N}. + +\pnum +\returns +If \tcode{r} is \tcode{0}, \tcode{x}; +if \tcode{r} is positive, \tcode{(x >> r) | (x << (N - r))}; +if \tcode{r} is negative, \tcode{rotl(x, -r)}. +\end{itemdescr} + +\rSec2[bit.count]{Counting} + +\pnum +In the following descriptions, +let \tcode{N} denote \tcode{numeric_limits::digits}. + +\begin{itemdecl} +template + constexpr int countl_zero(T x) noexcept; +\end{itemdecl} + +\indexlibraryglobal{countl_zero}% +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +The number of consecutive \tcode{0} bits in the value of \tcode{x}, +starting from the most significant bit. +\begin{note} +Returns \tcode{N} if \tcode{x == 0}. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr int countl_one(T x) noexcept; +\end{itemdecl} + +\indexlibraryglobal{countl_one}% +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +The number of consecutive \tcode{1} bits in the value of \tcode{x}, +starting from the most significant bit. +\begin{note} +Returns \tcode{N} if \tcode{x == numeric_limits::max()}. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr int countr_zero(T x) noexcept; +\end{itemdecl} + +\indexlibraryglobal{countr_zero}% +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +The number of consecutive \tcode{0} bits in the value of \tcode{x}, +starting from the least significant bit. +\begin{note} +Returns \tcode{N} if \tcode{x == 0}. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr int countr_one(T x) noexcept; +\end{itemdecl} + +\indexlibraryglobal{countr_one}% +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +The number of consecutive \tcode{1} bits in the value of \tcode{x}, +starting from the least significant bit. +\begin{note} +Returns \tcode{N} if \tcode{x == numeric_limits::max()}. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr int popcount(T x) noexcept; +\end{itemdecl} + +\indexlibraryglobal{popcount}% +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +The number of \tcode{1} bits in the value of \tcode{x}. +\end{itemdescr} + +\rSec2[bit.endian]{Endian} + +\pnum +Two common methods of byte ordering in multibyte scalar types are big-endian +and little-endian in the execution environment. Big-endian is a format for +storage of binary data in which the most significant byte is placed first, +with the rest in descending order. Little-endian is a format for storage of +binary data in which the least significant byte is placed first, with the rest +in ascending order. This subclause describes the endianness of the scalar types +of the execution environment. + +\indexlibraryglobal{endian}% +\indexlibrarymember{little}{endian}% +\indexlibrarymember{big}{endian}% +\indexlibrarymember{native}{endian}% +\begin{itemdecl} +enum class endian { + little = @\seebelow@, + big = @\seebelow@, + native = @\seebelow@ +}; +\end{itemdecl} + +\begin{itemdescr} +\pnum +If all scalar types have size 1 byte, then all of \tcode{endian::little}, +\tcode{endian::big}, and \tcode{endian::native} have the same value. +Otherwise, \tcode{endian::little} is not equal to \tcode{endian::big}. +If all scalar types are big-endian, \tcode{endian::native} is +equal to \tcode{endian::big}. +If all scalar types are little-endian, \tcode{endian::native} is +equal to \tcode{endian::little}. +Otherwise, \tcode{endian::native} is not equal +to either \tcode{endian::big} or \tcode{endian::little}. +\end{itemdescr} From e3532fd233355f93558f6a53d14b72e16a1f1ed2 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 23 Feb 2022 22:44:52 +0100 Subject: [PATCH 157/182] [memory] Create new clause and move [memory], [smartptr], [mem.res], and [allocator.adaptor] from [utilities] into the new clause. --- source/lib-intro.tex | 5 + source/memory.tex | 6754 +++++++++++++++++++++++++++++++++++++++++ source/std.tex | 1 + source/utilities.tex | 6739 ---------------------------------------- tools/check-source.sh | 2 +- 5 files changed, 6761 insertions(+), 6740 deletions(-) create mode 100644 source/memory.tex diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 870871efcd..d0973ce552 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -29,6 +29,7 @@ \ref{support} & Language support library \\ \ref{concepts} & Concepts library \\ \ref{diagnostics} & Diagnostics library \\ +\ref{mem} & Memory management library \\ \ref{utilities} & General utilities library \\ \ref{strings} & Strings library \\ \ref{containers} & Containers library \\ @@ -59,6 +60,10 @@ The diagnostics library\iref{diagnostics} provides a consistent framework for reporting errors in a \Cpp{} program, including predefined exception classes. +\pnum +The memory management library\iref{mem} provides components for +memory management, including smart pointers and scoped allocators. + \pnum The general utilities library\iref{utilities} includes components used by other library elements, such as a predefined storage allocator for dynamic diff --git a/source/memory.tex b/source/memory.tex new file mode 100644 index 0000000000..668bdf2667 --- /dev/null +++ b/source/memory.tex @@ -0,0 +1,6754 @@ +%!TEX root = std.tex +\rSec0[mem]{Memory management library} + +\rSec1[mem.general]{General} + +\pnum +This Clause describes components for memory management. + +\pnum +The following subclauses describe general memory management facilities, +smart pointers, memory resources, and scoped allocators, +as summarized in \tref{mem.summary}. + +\begin{libsumtab}{Memory management library summary}{mem.summary} +\ref{memory} & Memory & \tcode{}, \tcode{} \\ \rowsep +\ref{smartptr} & Smart pointers & \tcode{} \\ \rowsep +\ref{mem.res} & Memory resources & \tcode{} \\ \rowsep +\ref{allocator.adaptor} & Scoped allocators & \tcode{} \\ +\end{libsumtab} + +\rSec1[memory]{Memory} + +\rSec2[memory.general]{In general} + +\pnum +Subclause~\ref{memory} describes the contents of the header +\libheaderref{memory} and some +of the contents of the header \libheaderref{cstdlib}. + +\rSec2[memory.syn]{Header \tcode{} synopsis} + +\pnum +The header \libheaderdef{memory} defines several types and function templates that +describe properties of pointers and pointer-like types, manage memory +for containers and other template types, destroy objects, and +construct objects in +uninitialized memory +buffers~(\ref{pointer.traits}--\ref{specialized.addressof} and \ref{specialized.algorithms}). +The header also defines the templates +\tcode{unique_ptr}, \tcode{shared_ptr}, \tcode{weak_ptr}, +\tcode{out_ptr_t}, \tcode{inout_ptr_t}, and various function +templates that operate on objects of these types\iref{smartptr}. + +\pnum +Let \tcode{\exposid{POINTER_OF}(T)} denote a type that is +\begin{itemize} +\item +\tcode{T::pointer} if the \grammarterm{qualified-id} \tcode{T::pointer} +is valid and denotes a type, +\item +otherwise, \tcode{T::element_type*} +if the \grammarterm{qualified-id} \tcode{T::element_type} +is valid and denotes a type, +\item +otherwise, \tcode{pointer_traits::element_type*}. +\end{itemize} + +\pnum +Let \tcode{\exposid{POINTER_OF_OR}(T, U)} denote a type that is: +\begin{itemize} +\item +\tcode{\exposid{POINTER_OF}(T)} +if \tcode{\exposid{POINTER_OF}(T)} is valid and denotes a type, +\item +otherwise, \tcode{U}. +\end{itemize} + +\begin{codeblock} +#include // see \ref{compare.syn} + +namespace std { + // \ref{pointer.traits}, pointer traits + template struct pointer_traits; + template struct pointer_traits; + + // \ref{pointer.conversion}, pointer conversion + template + constexpr T* to_address(T* p) noexcept; + template + constexpr auto to_address(const Ptr& p) noexcept; + + // \ref{ptr.align}, pointer alignment + void* align(size_t alignment, size_t size, void*& ptr, size_t& space); + template + [[nodiscard]] constexpr T* assume_aligned(T* ptr); + + // \ref{allocator.tag}, allocator argument tag + struct allocator_arg_t { explicit allocator_arg_t() = default; }; + inline constexpr allocator_arg_t allocator_arg{}; + + // \ref{allocator.uses}, \tcode{uses_allocator} + template struct uses_allocator; + + // \ref{allocator.uses.trait}, \tcode{uses_allocator} + template + inline constexpr bool @\libglobal{uses_allocator_v}@ = uses_allocator::value; + + // \ref{allocator.uses.construction}, uses-allocator construction + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + Args&&... args) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, + Tuple1&& x, Tuple2&& y) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + U&& u, V&& v) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + pair& pr) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + const pair& pr) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + pair&& pr) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + const pair&& pr) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept; + template + constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args); + template + constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, + Args&&... args); + + // \ref{allocator.traits}, allocator traits + template struct allocator_traits; + + template + struct allocation_result { + Pointer ptr; + size_t count; + }; + + template + [[nodiscard] constexpr allocation_result::pointer> + allocate_at_least(Allocator& a, size_t n); + + // \ref{default.allocator}, the default allocator + template class allocator; + template + constexpr bool operator==(const allocator&, const allocator&) noexcept; + + // \ref{specialized.addressof}, addressof + template + constexpr T* addressof(T& r) noexcept; + template + const T* addressof(const T&&) = delete; + + // \ref{specialized.algorithms}, specialized algorithms + // \ref{special.mem.concepts}, special memory concepts + template + concept @\exposconcept{nothrow-input-iterator}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-forward-iterator}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-sentinel-for}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-input-range}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-forward-range}@ = @\seebelow@; // \expos + + template + void uninitialized_default_construct(NoThrowForwardIterator first, + NoThrowForwardIterator last); + template + void uninitialized_default_construct(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, + NoThrowForwardIterator last); + template + NoThrowForwardIterator + uninitialized_default_construct_n(NoThrowForwardIterator first, Size n); + template + NoThrowForwardIterator + uninitialized_default_construct_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, Size n); + + namespace ranges { + template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> + requires @\libconcept{default_initializable}@> + I uninitialized_default_construct(I first, S last); + template<@\exposconcept{nothrow-forward-range}@ R> + requires @\libconcept{default_initializable}@> + borrowed_iterator_t uninitialized_default_construct(R&& r); + + template<@\exposconcept{nothrow-forward-iterator}@ I> + requires @\libconcept{default_initializable}@> + I uninitialized_default_construct_n(I first, iter_difference_t n); + } + + template + void uninitialized_value_construct(NoThrowForwardIterator first, + NoThrowForwardIterator last); + template + void uninitialized_value_construct(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, + NoThrowForwardIterator last); + template + NoThrowForwardIterator + uninitialized_value_construct_n(NoThrowForwardIterator first, Size n); + template + NoThrowForwardIterator + uninitialized_value_construct_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, Size n); + + namespace ranges { + template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> + requires @\libconcept{default_initializable}@> + I uninitialized_value_construct(I first, S last); + template<@\exposconcept{nothrow-forward-range}@ R> + requires @\libconcept{default_initializable}@> + borrowed_iterator_t uninitialized_value_construct(R&& r); + + template<@\exposconcept{nothrow-forward-iterator}@ I> + requires @\libconcept{default_initializable}@> + I uninitialized_value_construct_n(I first, iter_difference_t n); + } + + template + NoThrowForwardIterator uninitialized_copy(InputIterator first, InputIterator last, + NoThrowForwardIterator result); + template + NoThrowForwardIterator uninitialized_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator first, ForwardIterator last, + NoThrowForwardIterator result); + template + NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n, + NoThrowForwardIterator result); + template + NoThrowForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator first, Size n, + NoThrowForwardIterator result); + + namespace ranges { + template + using uninitialized_copy_result = in_out_result; + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S1, + @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S2> + requires @\libconcept{constructible_from}@, iter_reference_t> + uninitialized_copy_result + uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast); + template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> + requires @\libconcept{constructible_from}@, range_reference_t> + uninitialized_copy_result, borrowed_iterator_t> + uninitialized_copy(IR&& in_range, OR&& out_range); + + template + using uninitialized_copy_n_result = in_out_result; + template<@\libconcept{input_iterator}@ I, @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S> + requires @\libconcept{constructible_from}@, iter_reference_t> + uninitialized_copy_n_result + uninitialized_copy_n(I ifirst, iter_difference_t n, O ofirst, S olast); + } + + template + NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last, + NoThrowForwardIterator result); + template + NoThrowForwardIterator uninitialized_move(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator first, ForwardIterator last, + NoThrowForwardIterator result); + template + pair + uninitialized_move_n(InputIterator first, Size n, NoThrowForwardIterator result); + template + pair + uninitialized_move_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator first, Size n, NoThrowForwardIterator result); + + namespace ranges { + template + using uninitialized_move_result = in_out_result; + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S1, + @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S2> + requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> + uninitialized_move_result + uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast); + template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> + requires @\libconcept{constructible_from}@, range_rvalue_reference_t> + uninitialized_move_result, borrowed_iterator_t> + uninitialized_move(IR&& in_range, OR&& out_range); + + template + using uninitialized_move_n_result = in_out_result; + template<@\libconcept{input_iterator}@ I, + @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S> + requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> + uninitialized_move_n_result + uninitialized_move_n(I ifirst, iter_difference_t n, O ofirst, S olast); + } + + template + void uninitialized_fill(NoThrowForwardIterator first, NoThrowForwardIterator last, + const T& x); + template + void uninitialized_fill(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, NoThrowForwardIterator last, + const T& x); + template + NoThrowForwardIterator + uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); + template + NoThrowForwardIterator + uninitialized_fill_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, Size n, const T& x); + + namespace ranges { + template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S, class T> + requires @\libconcept{constructible_from}@, const T&> + I uninitialized_fill(I first, S last, const T& x); + template<@\exposconcept{nothrow-forward-range}@ R, class T> + requires @\libconcept{constructible_from}@, const T&> + borrowed_iterator_t uninitialized_fill(R&& r, const T& x); + + template<@\exposconcept{nothrow-forward-iterator}@ I, class T> + requires @\libconcept{constructible_from}@, const T&> + I uninitialized_fill_n(I first, iter_difference_t n, const T& x); + } + + // \ref{specialized.construct}, \tcode{construct_at} + template + constexpr T* construct_at(T* location, Args&&... args); + + namespace ranges { + template + constexpr T* construct_at(T* location, Args&&... args); + } + + // \ref{specialized.destroy}, \tcode{destroy} + template + constexpr void destroy_at(T* location); + template + constexpr void destroy(NoThrowForwardIterator first, NoThrowForwardIterator last); + template + void destroy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, NoThrowForwardIterator last); + template + constexpr NoThrowForwardIterator destroy_n(NoThrowForwardIterator first, Size n); + template + NoThrowForwardIterator destroy_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator first, Size n); + + namespace ranges { + template<@\libconcept{destructible}@ T> + constexpr void destroy_at(T* location) noexcept; + + template<@\exposconcept{nothrow-input-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> + requires @\libconcept{destructible}@> + constexpr I destroy(I first, S last) noexcept; + template<@\exposconcept{nothrow-input-range}@ R> + requires @\libconcept{destructible}@> + constexpr borrowed_iterator_t destroy(R&& r) noexcept; + + template<@\exposconcept{nothrow-input-iterator}@ I> + requires @\libconcept{destructible}@> + constexpr I destroy_n(I first, iter_difference_t n) noexcept; + } + + // \ref{unique.ptr}, class template \tcode{unique_ptr} + template struct default_delete; + template struct default_delete; + template> class unique_ptr; + template class unique_ptr; + + template + constexpr unique_ptr make_unique(Args&&... args); // \tcode{T} is not array + template + constexpr unique_ptr make_unique(size_t n); // \tcode{T} is \tcode{U[]} + template + @\unspecnc@ make_unique(Args&&...) = delete; // \tcode{T} is \tcode{U[N]} + + template + constexpr unique_ptr make_unique_for_overwrite(); // \tcode{T} is not array + template + constexpr unique_ptr make_unique_for_overwrite(size_t n); // \tcode{T} is \tcode{U[]} + template + @\unspecnc@ make_unique_for_overwrite(Args&&...) = delete; // \tcode{T} is \tcode{U[N]} + + template + constexpr void swap(unique_ptr& x, unique_ptr& y) noexcept; + + template + constexpr bool operator==(const unique_ptr& x, const unique_ptr& y); + template + bool operator<(const unique_ptr& x, const unique_ptr& y); + template + bool operator>(const unique_ptr& x, const unique_ptr& y); + template + bool operator<=(const unique_ptr& x, const unique_ptr& y); + template + bool operator>=(const unique_ptr& x, const unique_ptr& y); + template + requires @\libconcept{three_way_comparable_with}@::pointer, + typename unique_ptr::pointer> + compare_three_way_result_t::pointer, + typename unique_ptr::pointer> + operator<=>(const unique_ptr& x, const unique_ptr& y); + + template + constexpr bool operator==(const unique_ptr& x, nullptr_t) noexcept; + template + constexpr bool operator<(const unique_ptr& x, nullptr_t); + template + constexpr bool operator<(nullptr_t, const unique_ptr& y); + template + constexpr bool operator>(const unique_ptr& x, nullptr_t); + template + constexpr bool operator>(nullptr_t, const unique_ptr& y); + template + constexpr bool operator<=(const unique_ptr& x, nullptr_t); + template + constexpr bool operator<=(nullptr_t, const unique_ptr& y); + template + constexpr bool operator>=(const unique_ptr& x, nullptr_t); + template + constexpr bool operator>=(nullptr_t, const unique_ptr& y); + template + requires @\libconcept{three_way_comparable}@::pointer> + constexpr compare_three_way_result_t::pointer> + operator<=>(const unique_ptr& x, nullptr_t); + + template + basic_ostream& operator<<(basic_ostream& os, const unique_ptr& p); + + // \ref{util.smartptr.weak.bad}, class \tcode{bad_weak_ptr} + class bad_weak_ptr; + + // \ref{util.smartptr.shared}, class template \tcode{shared_ptr} + template class shared_ptr; + + // \ref{util.smartptr.shared.create}, \tcode{shared_ptr} creation + template + shared_ptr make_shared(Args&&... args); // \tcode{T} is not array + template + shared_ptr allocate_shared(const A& a, Args&&... args); // \tcode{T} is not array + + template + shared_ptr make_shared(size_t N); // \tcode{T} is \tcode{U[]} + template + shared_ptr allocate_shared(const A& a, size_t N); // \tcode{T} is \tcode{U[]} + + template + shared_ptr make_shared(); // \tcode{T} is \tcode{U[N]} + template + shared_ptr allocate_shared(const A& a); // \tcode{T} is \tcode{U[N]} + + template + shared_ptr make_shared(size_t N, const remove_extent_t& u); // \tcode{T} is \tcode{U[]} + template + shared_ptr allocate_shared(const A& a, size_t N, + const remove_extent_t& u); // \tcode{T} is \tcode{U[]} + + template + shared_ptr make_shared(const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} + template + shared_ptr allocate_shared(const A& a, const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} + + template + shared_ptr make_shared_for_overwrite(); // \tcode{T} is not \tcode{U[]} + template + shared_ptr allocate_shared_for_overwrite(const A& a); // \tcode{T} is not \tcode{U[]} + + template + shared_ptr make_shared_for_overwrite(size_t N); // \tcode{T} is \tcode{U[]} + template + shared_ptr allocate_shared_for_overwrite(const A& a, size_t N); // \tcode{T} is \tcode{U[]} + + // \ref{util.smartptr.shared.cmp}, \tcode{shared_ptr} comparisons + template + bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept; + template + strong_ordering operator<=>(const shared_ptr& a, const shared_ptr& b) noexcept; + + template + bool operator==(const shared_ptr& x, nullptr_t) noexcept; + template + strong_ordering operator<=>(const shared_ptr& x, nullptr_t) noexcept; + + // \ref{util.smartptr.shared.spec}, \tcode{shared_ptr} specialized algorithms + template + void swap(shared_ptr& a, shared_ptr& b) noexcept; + + // \ref{util.smartptr.shared.cast}, \tcode{shared_ptr} casts + template + shared_ptr static_pointer_cast(const shared_ptr& r) noexcept; + template + shared_ptr static_pointer_cast(shared_ptr&& r) noexcept; + template + shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept; + template + shared_ptr dynamic_pointer_cast(shared_ptr&& r) noexcept; + template + shared_ptr const_pointer_cast(const shared_ptr& r) noexcept; + template + shared_ptr const_pointer_cast(shared_ptr&& r) noexcept; + template + shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept; + template + shared_ptr reinterpret_pointer_cast(shared_ptr&& r) noexcept; + + // \ref{util.smartptr.getdeleter}, \tcode{shared_ptr} \tcode{get_deleter} + template + D* get_deleter(const shared_ptr& p) noexcept; + + // \ref{util.smartptr.shared.io}, \tcode{shared_ptr} I/O + template + basic_ostream& operator<<(basic_ostream& os, const shared_ptr& p); + + // \ref{util.smartptr.weak}, class template \tcode{weak_ptr} + template class weak_ptr; + + // \ref{util.smartptr.weak.spec}, \tcode{weak_ptr} specialized algorithms + template void swap(weak_ptr& a, weak_ptr& b) noexcept; + + // \ref{util.smartptr.ownerless}, class template \tcode{owner_less} + template struct owner_less; + + // \ref{util.smartptr.enab}, class template \tcode{enable_shared_from_this} + template class enable_shared_from_this; + + // \ref{util.smartptr.hash}, hash support + template struct hash; + template struct hash>; + template struct hash>; + + // \ref{util.smartptr.atomic}, atomic smart pointers + template struct atomic; + template struct atomic>; + template struct atomic>; + + // \ref{out.ptr.t}, class template \tcode{out_ptr_t} + template + class out_ptr_t; + + // \ref{out.ptr}, function template \tcode{out_ptr} + template + auto out_ptr(Smart& s, Args&&... args); + + // \ref{inout.ptr.t}, class template \tcode{inout_ptr_t} + template + class inout_ptr_t; + + // \ref{inout.ptr}, function template \tcode{inout_ptr} + template + auto inout_ptr(Smart& s, Args&&... args); +} +\end{codeblock} + +\rSec2[pointer.traits]{Pointer traits} + +\rSec3[pointer.traits.general]{General} + +\pnum +The class template \tcode{pointer_traits} supplies a uniform interface to certain +attributes of pointer-like types. + +\indexlibraryglobal{pointer_traits}% +\begin{codeblock} +namespace std { + template struct pointer_traits { + using pointer = Ptr; + using element_type = @\seebelow@; + using difference_type = @\seebelow@; + + template using rebind = @\seebelow@; + + static pointer pointer_to(@\seebelow@ r); + }; + + template struct pointer_traits { + using pointer = T*; + using element_type = T; + using difference_type = ptrdiff_t; + + template using rebind = U*; + + static constexpr pointer pointer_to(@\seebelow@ r) noexcept; + }; +} +\end{codeblock} + +\rSec3[pointer.traits.types]{Member types} + +\indexlibrarymember{element_type}{pointer_traits}% +\begin{itemdecl} +using element_type = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Ptr::element_type} if +the \grammarterm{qualified-id} \tcode{Ptr::element_type} is valid and denotes a +type\iref{temp.deduct}; otherwise, \tcode{T} if +\tcode{Ptr} is a class template instantiation of the form \tcode{SomePointer}, +where \tcode{Args} is zero or more type arguments; otherwise, the specialization is +ill-formed. +\end{itemdescr} + +\indexlibrarymember{difference_type}{pointer_traits}% +\begin{itemdecl} +using difference_type = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Ptr::difference_type} if +the \grammarterm{qualified-id} \tcode{Ptr::difference_type} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{ptrdiff_t}. +\end{itemdescr} + +\indexlibrarymember{rebind}{pointer_traits}% +\begin{itemdecl} +template using rebind = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\templalias \tcode{Ptr::rebind} if +the \grammarterm{qualified-id} \tcode{Ptr::rebind} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{SomePointer} if +\tcode{Ptr} is a class template instantiation of the form \tcode{SomePointer}, +where \tcode{Args} is zero or more type arguments; otherwise, the instantiation of +\tcode{rebind} is ill-formed. +\end{itemdescr} + +\rSec3[pointer.traits.functions]{Member functions} + +\indexlibrarymember{pointer_to}{pointer_traits}% +\begin{itemdecl} +static pointer pointer_traits::pointer_to(@\seebelow@ r); +static constexpr pointer pointer_traits::pointer_to(@\seebelow@ r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +For the first member function, +\tcode{Ptr::pointer_to(r)} is well-formed. + +\pnum +\expects +For the first member function, +\tcode{Ptr::pointer_to(r)} returns a pointer to \tcode{r} +through which indirection is valid. + +\pnum +\returns +The first member function returns \tcode{Ptr::pointer_to(r)}. +The second member function returns \tcode{addressof(r)}. + +\pnum +\remarks +If \tcode{element_type} is \cv{}~\keyword{void}, the type of +\tcode{r} is unspecified; otherwise, it is \tcode{element_type\&}. +\end{itemdescr} + +\rSec3[pointer.traits.optmem]{Optional members} + +\pnum +Specializations of \tcode{pointer_traits} may define the member declared +in this subclause to customize the behavior of the standard library. + +\indexlibrarymember{to_address}{pointer_traits}% +\begin{itemdecl} +static element_type* to_address(pointer p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A pointer of type \tcode{element_type*} that references +the same location as the argument \tcode{p}. + +\pnum +\begin{note} +This function is intended to be the inverse of \tcode{pointer_to}. +If defined, it customizes the behavior of +the non-member function +\tcode{to_address}\iref{pointer.conversion}. +\end{note} +\end{itemdescr} + +\rSec2[pointer.conversion]{Pointer conversion} + +\indexlibraryglobal{to_address}% +\begin{itemdecl} +template constexpr T* to_address(T* p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is not a function type. + +\pnum +\returns +\tcode{p}. +\end{itemdescr} + +\indexlibraryglobal{to_address}% +\begin{itemdecl} +template constexpr auto to_address(const Ptr& p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{pointer_traits::to_address(p)} if that expression is well-formed +(see \ref{pointer.traits.optmem}), +otherwise \tcode{to_address(p.operator->())}. +\end{itemdescr} + +\rSec2[ptr.align]{Pointer alignment} + +\indexlibraryglobal{align}% +\begin{itemdecl} +void* align(size_t alignment, size_t size, void*& ptr, size_t& space); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\begin{itemize} +\item +\tcode{alignment} is a power of two + +\item +\tcode{ptr} represents the address of contiguous storage of at least +\tcode{space} bytes +\end{itemize} + +\pnum +\effects +If it is possible to fit \tcode{size} bytes +of storage aligned by \tcode{alignment} into the buffer pointed to by +\tcode{ptr} with length \tcode{space}, the function updates +\tcode{ptr} to represent the first possible address of such storage +and decreases \tcode{space} by the number of bytes used for alignment. +Otherwise, the function does nothing. + +\pnum +\returns +A null pointer if the requested aligned buffer +would not fit into the available space, otherwise the adjusted value +of \tcode{ptr}. + +\pnum +\begin{note} +The function updates its \tcode{ptr} +and \tcode{space} arguments so that it can be called repeatedly +with possibly different \tcode{alignment} and \tcode{size} +arguments for the same buffer. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{assume_aligned}% +\begin{itemdecl} +template + [[nodiscard]] constexpr T* assume_aligned(T* ptr); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{N} is a power of two. + +\pnum +\expects +\tcode{ptr} points to an object \tcode{X} of +a type similar\iref{conv.qual} to \tcode{T}, +where \tcode{X} has alignment \tcode{N}\iref{basic.align}. + +\pnum +\returns +\tcode{ptr}. + +\pnum +\throws +Nothing. + +\pnum +\begin{note} +The alignment assumption on an object \tcode{X} +expressed by a call to \tcode{assume_aligned} +might result in generation of more efficient code. +It is up to the program to ensure that the assumption actually holds. +The call does not cause the implementation to verify or enforce this. +An implementation might only make the assumption +for those operations on \tcode{X} that access \tcode{X} +through the pointer returned by \tcode{assume_aligned}. +\end{note} +\end{itemdescr} + +\rSec2[allocator.tag]{Allocator argument tag} + +\indexlibraryglobal{allocator_arg_t}% +\indexlibraryglobal{allocator_arg}% +\begin{itemdecl} +namespace std { + struct allocator_arg_t { explicit allocator_arg_t() = default; }; + inline constexpr allocator_arg_t allocator_arg{}; +} +\end{itemdecl} + +\pnum +The \tcode{allocator_arg_t} struct is an empty class type used as a unique type to +disambiguate constructor and function overloading. Specifically, several types (see +\tcode{tuple}~\ref{tuple}) have constructors with \tcode{allocator_arg_t} as the first +argument, immediately followed by an argument of a type that meets the +\oldconcept{Allocator} requirements (\tref{cpp17.allocator}). + +\rSec2[allocator.uses]{\tcode{uses_allocator}} + +\rSec3[allocator.uses.trait]{\tcode{uses_allocator} trait} + +\indexlibraryglobal{uses_allocator}% +\begin{itemdecl} +template struct uses_allocator; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\remarks +Automatically detects whether \tcode{T} has a nested \tcode{allocator_type} that +is convertible from \tcode{Alloc}. Meets the \oldconcept{BinaryTypeTrait} +requirements\iref{meta.rqmts}. The implementation shall provide a definition that is +derived from \tcode{true_type} if the \grammarterm{qualified-id} \tcode{T::allocator_type} +is valid and denotes a type\iref{temp.deduct} and +\tcode{is_convertible_v != false}, otherwise it shall be +derived from \tcode{false_type}. A program may specialize this template to derive from +\tcode{true_type} for a program-defined type \tcode{T} that does not have a nested +\tcode{allocator_type} but nonetheless can be constructed with an allocator where +either: +\begin{itemize} +\item the first argument of a constructor has type \tcode{allocator_arg_t} and the +second argument has type \tcode{Alloc} or + +\item the last argument of a constructor has type \tcode{Alloc}. +\end{itemize} +\end{itemdescr} + +\rSec3[allocator.uses.construction]{Uses-allocator construction} + +\pnum +\defnx{Uses-allocator construction}{uses-allocator construction} +with allocator \tcode{alloc} and constructor arguments \tcode{args...} +refers to the construction of an object of type \tcode{T} +such that \tcode{alloc} is passed to the constructor of \tcode{T} +if \tcode{T} uses an allocator type compatible with \tcode{alloc}. +When applied to the construction of an object of type \tcode{T}, +it is equivalent to initializing it with the value of the expression +\tcode{make_obj_using_allocator(alloc, args...)}, described below. + +\pnum +The following utility functions support +three conventions for passing \tcode{alloc} to a constructor: +\begin{itemize} +\item + If \tcode{T} does not use an allocator compatible with \tcode{alloc}, + then \tcode{alloc} is ignored. +\item + Otherwise, if \tcode{T} has a constructor invocable as + \tcode{T(allocator_arg, alloc, args...)} (leading-allocator convention), + then uses-allocator construction chooses this constructor form. +\item + Otherwise, if \tcode{T} has a constructor invocable as + \tcode{T(args..., alloc)} (trailing-allocator convention), + then uses-allocator construction chooses this constructor form. +\end{itemize} + +\pnum +The \tcode{uses_allocator_construction_args} function template +takes an allocator and argument list and +produces (as a tuple) a new argument list matching one of the above conventions. +Additionally, overloads are provided +that treat specializations of \tcode{pair} +such that uses-allocator construction is applied individually +to the \tcode{first} and \tcode{second} data members. +The \tcode{make_obj_using_allocator} and +\tcode{uninitialized_construct_using_allocator} function templates +apply the modified constructor arguments +to construct an object of type \tcode{T} +as a return value or in-place, respectively. +\begin{note} +For \tcode{uses_allocator_construction_args} and +\tcode{make_obj_using_allocator}, type \tcode{T} +is not deduced and must therefore be specified explicitly by the caller. +\end{note} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + Args&&... args) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is not a specialization of \tcode{pair}. + +\pnum +\returns +A \tcode{tuple} value determined as follows: +\begin{itemize} +\item + If \tcode{uses_allocator_v} is \tcode{false} and + \tcode{is_constructible_v} is \tcode{true}, + return \tcode{forward_as_tuple(std::forward(args)...)}. +\item + Otherwise, if \tcode{uses_allocator_v} is \tcode{true} and + \tcode{is_constructible_v} + is \tcode{true}, + return +\begin{codeblock} +tuple( + allocator_arg, alloc, std::forward(args)...) +\end{codeblock} +\item + Otherwise, if \tcode{uses_allocator_v} is \tcode{true} and + \tcode{is_constructible_v} is \tcode{true}, + return \tcode{forward_as_tuple(std::forward(args)..., alloc)}. +\item + Otherwise, the program is ill-formed. +\end{itemize} +\begin{note} +This definition prevents a silent failure +to pass the allocator to a constructor of a type for which +\tcode{uses_allocator_v} is \tcode{true}. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, + Tuple1&& x, Tuple2&& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a specialization of \tcode{pair}. + +\pnum +\effects +For \tcode{T} specified as \tcode{pair}, equivalent to: +\begin{codeblock} +return make_tuple( + piecewise_construct, + apply([&alloc](auto&&... args1) { + return uses_allocator_construction_args( + alloc, std::forward(args1)...); + }, std::forward(x)), + apply([&alloc](auto&&... args2) { + return uses_allocator_construction_args( + alloc, std::forward(args2)...); + }, std::forward(y))); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a specialization of \tcode{pair}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return uses_allocator_construction_args(alloc, piecewise_construct, + tuple<>{}, tuple<>{}); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + U&& u, V&& v) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a specialization of \tcode{pair}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return uses_allocator_construction_args(alloc, piecewise_construct, + forward_as_tuple(std::forward(u)), + forward_as_tuple(std::forward(v))); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + pair& pr) noexcept; +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + const pair& pr) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a specialization of \tcode{pair}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return uses_allocator_construction_args(alloc, piecewise_construct, + forward_as_tuple(pr.first), + forward_as_tuple(pr.second)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + pair&& pr) noexcept; +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + const pair&& pr) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a specialization of \tcode{pair}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return uses_allocator_construction_args(alloc, piecewise_construct, + forward_as_tuple(get<0>(std::move(pr))), + forward_as_tuple(get<1>(std::move(pr)))); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{uses_allocator_construction_args}% +\begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \exposid{FUN} be the function template: +\begin{codeblock} +template + void @\exposid{FUN}@(const pair&); +\end{codeblock} + +\pnum +\constraints +\tcode{T} is a specialization of \tcode{pair}, and +the expression \tcode{\exposid{FUN}(u)} is not well-formed +when considered as an unevaluated operand. + +\pnum +Let \exposid{pair-constructor} be an exposition-only class defined as follows: + +\begin{codeblock} +class @\exposid{pair-constructor}@ { + using @\exposid{pair-type}@ = remove_cv_t; // \expos + + constexpr auto @\exposid{do-construct}@(const @\exposid{pair-type}@& p) const { // \expos + return make_obj_using_allocator<@\exposid{pair-type}@>(@\exposid{alloc_}@, p); + } + constexpr auto @\exposid{do-construct}@(@\exposid{pair-type}@&& p) const { // \expos + return make_obj_using_allocator<@\exposid{pair-type}@>(@\exposid{alloc_}@, std::move(p)); + } + + const Alloc& @\exposid{alloc_}@; // \expos + U& @\exposid{u_}@; // \expos + +public: + constexpr operator @\exposid{pair-type}@() const { + return @\exposid{do-construct}@(std::forward(@\exposid{u_}@)); + } +}; +\end{codeblock} + +\pnum +\returns +\tcode{make_tuple(pc)}, +where \tcode{pc} is a \exposid{pair-constructor} object +whose \exposid{alloc_} member is initialized with \tcode{alloc} and +whose \exposid{u_} member is initialized with \tcode{u}. +\end{itemdescr} + +\indexlibraryglobal{make_obj_using_allocator}% +\begin{itemdecl} +template + constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return make_from_tuple(uses_allocator_construction_args( + alloc, std::forward(args)...)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{uninitialized_construct_using_allocator}% +\begin{itemdecl} +template + constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return apply([&](U&&... xs) { + return construct_at(p, std::forward(xs)...); + }, uses_allocator_construction_args(alloc, std::forward(args)...)); +\end{codeblock} +\end{itemdescr} + +\rSec2[allocator.traits]{Allocator traits} + +\rSec3[allocator.traits.general]{General} + +\pnum +The class template \tcode{allocator_traits} supplies a uniform interface to all +allocator types. +An allocator cannot be a non-class type, however, even if \tcode{allocator_traits} +supplies the entire required interface. +\begin{note} +Thus, it is always possible to create +a derived class from an allocator. +\end{note} + +\indexlibraryglobal{allocator_traits}% +\begin{codeblock} +namespace std { + template struct allocator_traits { + using allocator_type = Alloc; + + using value_type = typename Alloc::value_type; + + using pointer = @\seebelow@; + using const_pointer = @\seebelow@; + using void_pointer = @\seebelow@; + using const_void_pointer = @\seebelow@; + + using difference_type = @\seebelow@; + using size_type = @\seebelow@; + + using propagate_on_container_copy_assignment = @\seebelow@; + using propagate_on_container_move_assignment = @\seebelow@; + using propagate_on_container_swap = @\seebelow@; + using is_always_equal = @\seebelow@; + + template using rebind_alloc = @\seebelow@; + template using rebind_traits = allocator_traits>; + + [[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n); + [[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n, + const_void_pointer hint); + + static constexpr void deallocate(Alloc& a, pointer p, size_type n); + + template + static constexpr void construct(Alloc& a, T* p, Args&&... args); + + template + static constexpr void destroy(Alloc& a, T* p); + + static constexpr size_type max_size(const Alloc& a) noexcept; + + static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs); + }; +} +\end{codeblock} + +\rSec3[allocator.traits.types]{Member types} + +\indexlibrarymember{pointer}{allocator_traits}% +\begin{itemdecl} +using pointer = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::pointer} if +the \grammarterm{qualified-id} \tcode{Alloc::pointer} is valid and denotes a +type\iref{temp.deduct}; otherwise, \tcode{value_type*}. +\end{itemdescr} + +\indexlibrarymember{const_pointer}{allocator_traits}% +\begin{itemdecl} +using const_pointer = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::const_pointer} if +the \grammarterm{qualified-id} \tcode{Alloc::const_pointer} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{pointer_traits::rebind<\brk{}const value_type>}. +\end{itemdescr} + +\indexlibrarymember{void_pointer}{allocator_traits}% +\begin{itemdecl} +using void_pointer = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::void_pointer} if +the \grammarterm{qualified-id} \tcode{Alloc::void_pointer} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{pointer_traits::rebind<\brk{}void>}. +\end{itemdescr} + +\indexlibrarymember{const_void_pointer}{allocator_traits}% +\begin{itemdecl} +using const_void_pointer = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::const_void_pointer} if +the \grammarterm{qualified-id} \tcode{Alloc::const_void_pointer} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{pointer_traits::\brk{}rebind}. +\end{itemdescr} + +\indexlibrarymember{difference_type}{allocator_traits}% +\begin{itemdecl} +using difference_type = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::difference_type} if +the \grammarterm{qualified-id} \tcode{Alloc::difference_type} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{pointer_traits::dif\-ference_type}. +\end{itemdescr} + +\indexlibrarymember{size_type}{allocator_traits}% +\begin{itemdecl} +using size_type = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::size_type} if +the \grammarterm{qualified-id} \tcode{Alloc::size_type} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{make_unsigned_t}. +\end{itemdescr} + +\indexlibrarymember{propagate_on_container_copy_assignment}{allocator_traits}% +\begin{itemdecl} +using propagate_on_container_copy_assignment = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::propagate_on_container_copy_assignment} if +the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_copy_assignment} is valid and denotes a +type\iref{temp.deduct}; otherwise +\tcode{false_type}. +\end{itemdescr} + +\indexlibrarymember{propagate_on_container_move_assignment}{allocator_traits}% +\begin{itemdecl} +using propagate_on_container_move_assignment = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::propagate_on_container_move_assignment} if +the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_move_assignment} is valid and denotes a +type\iref{temp.deduct}; otherwise +\tcode{false_type}. +\end{itemdescr} + +\indexlibrarymember{propagate_on_container_swap}{allocator_traits}% +\begin{itemdecl} +using propagate_on_container_swap = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::propagate_on_container_swap} if +the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_swap} is valid and denotes a +type\iref{temp.deduct}; otherwise +\tcode{false_type}. +\end{itemdescr} + +\indexlibrarymember{is_always_equal}{allocator_traits}% +\begin{itemdecl} +using is_always_equal = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{Alloc::is_always_equal} if +the \grammarterm{qualified-id} \tcode{Alloc::is_always_equal} +is valid and denotes a type\iref{temp.deduct}; +otherwise \tcode{is_empty::type}. +\end{itemdescr} + +\indexlibrarymember{rebind_alloc}{allocator_traits}% +\begin{itemdecl} +template using rebind_alloc = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\templalias \tcode{Alloc::rebind::other} if +the \grammarterm{qualified-id} \tcode{Alloc::rebind::other} is valid and denotes a +type\iref{temp.deduct}; otherwise, +\tcode{Alloc} if \tcode{Alloc} is a class template instantiation +of the form \tcode{Alloc}, where \tcode{Args} is zero or more type arguments; +otherwise, the instantiation of \tcode{rebind_alloc} is ill-formed. +\end{itemdescr} + +\rSec3[allocator.traits.members]{Static member functions} + +\indexlibrarymember{allocate}{allocator_traits}% +\begin{itemdecl} +[[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{a.allocate(n)}. +\end{itemdescr} + +\indexlibrarymember{allocate}{allocator_traits}% +\begin{itemdecl} +[[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{a.allocate(n, hint)} if that expression is well-formed; otherwise, \tcode{a.allocate(n)}. +\end{itemdescr} + +\indexlibrarymember{deallocate}{allocator_traits}% +\begin{itemdecl} +static constexpr void deallocate(Alloc& a, pointer p, size_type n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{a.deallocate(p, n)}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibrarymember{construct}{allocator_traits}% +\begin{itemdecl} +template + static constexpr void construct(Alloc& a, T* p, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{a.construct(p, std::forward(args)...)} +if that call is well-formed; +otherwise, invokes \tcode{construct_at(p, std::forward(args)...)}. +\end{itemdescr} + +\indexlibrarymember{destroy}{allocator_traits}% +\begin{itemdecl} +template + static constexpr void destroy(Alloc& a, T* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{a.destroy(p)} if that call is well-formed; otherwise, invokes +\tcode{destroy_at(p)}. +\end{itemdescr} + +\indexlibrarymember{max_size}{allocator_traits}% +\begin{itemdecl} +static constexpr size_type max_size(const Alloc& a) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{a.max_size()} if that expression is well-formed; otherwise, +\tcode{numeric_limits::\brk{}max()/sizeof(value_type)}. +\end{itemdescr} + +\indexlibrarymember{select_on_container_copy_construction}{allocator_traits}% +\begin{itemdecl} +static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{rhs.select_on_container_copy_construction()} if that expression is +well-formed; otherwise, \tcode{rhs}. +\end{itemdescr} + +\rSec3[allocator.traits.other]{Other} + +\pnum +The class template \tcode{allocation_result} has +the template parameters, data members, and special members specified above. +It has no base classes or members other than those specified. + +\begin{itemdecl} +template +[[nodiscard]] constexpr allocation_result::pointer> + allocate_at_least(Allocator& a, size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{a.allocate_at_least(n)} if that expression is well-formed; +otherwise, \tcode{\{a.allocate(n), n\}}. +\end{itemdescr} + +\rSec2[default.allocator]{The default allocator} + +\rSec3[default.allocator.general]{General} + +\pnum +All specializations of the default allocator meet the +allocator completeness requirements\iref{allocator.requirements.completeness}. + +\indexlibraryglobal{allocator}% +\indexlibrarymember{value_type}{allocator}% +\indexlibrarymember{size_type}{allocator}% +\indexlibrarymember{difference_type}{allocator}% +\indexlibrarymember{propagate_on_container_move_assignment}{allocator}% +\indexlibrarymember{operator=}{allocator}% +\begin{codeblock} +namespace std { + template class allocator { + public: + using value_type = T; + using size_type = size_t; + using difference_type = ptrdiff_t; + using propagate_on_container_move_assignment = true_type; + + constexpr allocator() noexcept; + constexpr allocator(const allocator&) noexcept; + template constexpr allocator(const allocator&) noexcept; + constexpr ~allocator(); + constexpr allocator& operator=(const allocator&) = default; + + [[nodiscard]] constexpr T* allocate(size_t n); + [[nodiscard]] constexpr allocation_result allocate_at_least(size_t n); + constexpr void deallocate(T* p, size_t n); + }; +} +\end{codeblock} + +\pnum +\tcode{allocator_traits>::is_always_equal::value} +is \tcode{true} for any \tcode{T}. + +\rSec3[allocator.members]{Members} + +\pnum +Except for the destructor, member functions of the default allocator shall not introduce +data races\iref{intro.multithread} as a result of concurrent calls to those member +functions from different threads. Calls to these functions that allocate or deallocate a +particular unit of storage shall occur in a single total order, and each such +deallocation call shall happen before the next allocation (if any) in this order. + +\indexlibrarymember{allocate}{allocator}% +\begin{itemdecl} +[[nodiscard]] constexpr T* allocate(size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is not an incomplete type\iref{term.incomplete.type}. + +\pnum +\returns +A pointer to the initial element of an array of \tcode{n} \tcode{T}. + +\pnum +\throws +\tcode{bad_array_new_length} if +\tcode{numeric_limits::max() / sizeof(T) < n}, or +\tcode{bad_alloc} if the storage cannot be obtained. + +\pnum +\remarks +The storage for the array +is obtained by calling \tcode{::operator new}\iref{new.delete}, +but it is unspecified when or how often this +function is called. +This function starts the lifetime of the array object, +but not that of any of the array elements. +\end{itemdescr} + +\indexlibrarymember{allocate_at_least}{allocator}% +\begin{itemdecl} +[[nodiscard]] constexpr allocation_result allocate_at_least(size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is not an incomplete type\iref{term.incomplete.type}. + +\pnum +\returns +\tcode{allocation_result\{ptr, count\}}, +where \tcode{ptr} is a pointer to +the initial element of an array of \tcode{count} \tcode{T} and +$\tcode{count} \geq \tcode{n}$. + +\pnum +\throws +\tcode{bad_array_new_length} +if $\tcode{numeric_limits::max() / sizeof(T)} < \tcode{n}$, +or \tcode{bad_alloc} if the storage cannot be obtained. + +\pnum +\remarks +The storage for the array is obtained by calling \tcode{::operator new}, +but it is unspecified when or how often this function is called. +This function starts the lifetime of the array object, +but not that of any of the array elements. +\end{itemdescr} + +\indexlibrarymember{deallocate}{allocator}% +\begin{itemdecl} +constexpr void deallocate(T* p, size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\begin{itemize} +\item +If \tcode{p} is memory that was obtained by a call to \tcode{allocate_at_least}, +let \tcode{ret} be the value returned and +\tcode{req} be the value passed as the first argument to that call. +\tcode{p} is equal to \tcode{ret.ptr} and +\tcode{n} is a value such that $\tcode{req} \leq \tcode{n} \leq \tcode{ret.count}$. +\item +Otherwise, \tcode{p} is a pointer value obtained from \tcode{allocate}. +\tcode{n} equals the value passed as the first argument +to the invocation of \tcode{allocate} which returned \tcode{p}. +\end{itemize} + +\pnum +\effects +Deallocates the storage referenced by \tcode{p}. + +\pnum +\remarks +Uses +\tcode{::operator delete}\iref{new.delete}, +but it is unspecified +when this function is called. +\end{itemdescr} + +\rSec3[allocator.globals]{Operators} + +\indexlibrarymember{operator==}{allocator}% +\begin{itemdecl} +template + constexpr bool operator==(const allocator&, const allocator&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true}. +\end{itemdescr} + +\rSec2[specialized.addressof]{\tcode{addressof}} + +\indexlibraryglobal{addressof}% +\begin{itemdecl} +template constexpr T* addressof(T& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The actual address of the object or function referenced by \tcode{r}, even in the +presence of an overloaded \tcode{operator\&}. + +\pnum +\remarks +An expression \tcode{addressof(E)} +is a constant subexpression\iref{defns.const.subexpr} +if \tcode{E} is an lvalue constant subexpression. +\end{itemdescr} + +\rSec2[c.malloc]{C library memory allocation} + +\pnum +\begin{note} +The header \libheaderref{cstdlib} +declares the functions described in this subclause. +\end{note} + +\indexlibraryglobal{aligned_alloc}% +\indexlibraryglobal{calloc}% +\indexlibraryglobal{malloc}% +\indexlibraryglobal{realloc}% +\begin{itemdecl} +void* aligned_alloc(size_t alignment, size_t size); +void* calloc(size_t nmemb, size_t size); +void* malloc(size_t size); +void* realloc(void* ptr, size_t size); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +These functions have the semantics specified in the C standard library. + +\pnum +\remarks +These functions do not attempt to allocate +storage by calling \tcode{::operator new()}\iref{new.delete}. +\indexlibrarymember{new}{operator}% + +\pnum +These functions implicitly create objects\iref{intro.object} +in the returned region of storage and +return a pointer to a suitable created object. +In the case of \tcode{calloc} and \tcode{realloc}, +the objects are created before the storage is zeroed or copied, respectively. +\end{itemdescr} + +\indexlibraryglobal{free}% +\begin{itemdecl} +void free(void* ptr); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +This function has the semantics specified in the C standard library. + +\pnum +\remarks +This function does not attempt to +deallocate storage by calling +\tcode{::operator delete()}\indexlibrarymember{delete}{operator}. +\end{itemdescr} + +\xrefc{7.22.3} + +\rSec1[smartptr]{Smart pointers} + +\rSec2[unique.ptr]{Unique-ownership pointers} + +\rSec3[unique.ptr.general]{General} + +\pnum +A \defn{unique pointer} is an object that owns another object and +manages that other object through a pointer. More precisely, a unique pointer +is an object \textit{u} that stores a pointer to a second object \textit{p} and +will dispose of \textit{p} when \textit{u} is itself destroyed (e.g., when +leaving block scope\iref{stmt.dcl}). In this context, \textit{u} is said +to \defn{own} \tcode{p}. + +\pnum +The mechanism by which \textit{u} disposes of \textit{p} is known as +\textit{p}'s associated \defn{deleter}, a function object whose correct +invocation results in \textit{p}'s appropriate disposition (typically its deletion). + +\pnum +Let the notation \textit{u.p} denote the pointer stored by \textit{u}, and +let \textit{u.d} denote the associated deleter. Upon request, \textit{u} can +\defn{reset} (replace) \textit{u.p} and \textit{u.d} with another pointer and +deleter, but properly disposes of its owned object via the associated +deleter before such replacement is considered completed. + +\pnum +Each object of a type \tcode{U} instantiated from the \tcode{unique_ptr} template +specified in \ref{unique.ptr} has the strict ownership semantics, specified above, +of a unique pointer. In partial satisfaction of these semantics, each such \tcode{U} +is \oldconcept{MoveConstructible} and \oldconcept{MoveAssignable}, but is not +\oldconcept{CopyConstructible} nor \oldconcept{CopyAssignable}. +The template parameter \tcode{T} of \tcode{unique_ptr} may be an incomplete type. + +\pnum +\begin{note} +The uses +of \tcode{unique_ptr} include providing exception safety for +dynamically allocated memory, passing ownership of dynamically allocated +memory to a function, and returning dynamically allocated memory from a +function. +\end{note} + +\rSec3[unique.ptr.dltr]{Default deleters} + +\rSec4[unique.ptr.dltr.general]{In general} + +\pnum +The class template \tcode{default_delete} serves as the default deleter (destruction policy) +for the class template \tcode{unique_ptr}. + +\pnum +The template parameter \tcode{T} of \tcode{default_delete} may be +an incomplete type. + +\rSec4[unique.ptr.dltr.dflt]{\tcode{default_delete}} + +\begin{codeblock} +namespace std { + template struct default_delete { + constexpr default_delete() noexcept = default; + template constexpr default_delete(const default_delete&) noexcept; + constexpr void operator()(T*) const; + }; +} +\end{codeblock} + +\indexlibraryctor{default_delete}% +\begin{itemdecl} +template constexpr default_delete(const default_delete& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{U*} is implicitly convertible to \tcode{T*}. + +\pnum +\effects +Constructs a \tcode{default_delete} object +from another \tcode{default_delete} object. +\end{itemdescr} + +\indexlibrarymember{operator()}{default_delete}% +\begin{itemdecl} +constexpr void operator()(T* ptr) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is a complete type. + +\pnum +\effects +Calls \keyword{delete} on \tcode{ptr}. +\end{itemdescr} + +\rSec4[unique.ptr.dltr.dflt1]{\tcode{default_delete}} + +\begin{codeblock} +namespace std { + template struct default_delete { + constexpr default_delete() noexcept = default; + template constexpr default_delete(const default_delete&) noexcept; + template constexpr void operator()(U* ptr) const; + }; +} +\end{codeblock} + +\indexlibraryctor{default_delete} +\begin{itemdecl} +template constexpr default_delete(const default_delete& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{U(*)[]} is convertible to \tcode{T(*)[]}. + +\pnum +\effects +Constructs a \tcode{default_delete} object from another \tcode{default_delete} object. +\end{itemdescr} + +\indexlibrarymember{operator()}{default_delete}% +\begin{itemdecl} +template constexpr void operator()(U* ptr) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{U(*)[]} is convertible to \tcode{T(*)[]}. + +\pnum +\mandates +\tcode{U} is a complete type. + +\pnum +\effects +Calls \tcode{delete[]} on \tcode{ptr}. +\end{itemdescr} + +\rSec3[unique.ptr.single]{\tcode{unique_ptr} for single objects} + +\rSec4[unique.ptr.single.general]{General} + +\indexlibraryglobal{unique_ptr}% +\begin{codeblock} +namespace std { + template> class unique_ptr { + public: + using pointer = @\seebelow@; + using element_type = T; + using deleter_type = D; + + // \ref{unique.ptr.single.ctor}, constructors + constexpr unique_ptr() noexcept; + constexpr explicit unique_ptr(type_identity_t p) noexcept; + constexpr unique_ptr(type_identity_t p, @\seebelow@ d1) noexcept; + constexpr unique_ptr(type_identity_t p, @\seebelow@ d2) noexcept; + constexpr unique_ptr(unique_ptr&& u) noexcept; + constexpr unique_ptr(nullptr_t) noexcept; + template + constexpr unique_ptr(unique_ptr&& u) noexcept; + + // \ref{unique.ptr.single.dtor}, destructor + constexpr ~unique_ptr(); + + // \ref{unique.ptr.single.asgn}, assignment + constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; + template + constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; + constexpr unique_ptr& operator=(nullptr_t) noexcept; + + // \ref{unique.ptr.single.observers}, observers + constexpr add_lvalue_reference_t operator*() const noexcept(@\seebelow@); + constexpr pointer operator->() const noexcept; + constexpr pointer get() const noexcept; + constexpr deleter_type& get_deleter() noexcept; + constexpr const deleter_type& get_deleter() const noexcept; + constexpr explicit operator bool() const noexcept; + + // \ref{unique.ptr.single.modifiers}, modifiers + constexpr pointer release() noexcept; + constexpr void reset(pointer p = pointer()) noexcept; + constexpr void swap(unique_ptr& u) noexcept; + + // disable copy from lvalue + unique_ptr(const unique_ptr&) = delete; + unique_ptr& operator=(const unique_ptr&) = delete; + }; +} +\end{codeblock} + +\pnum +The default type for the template parameter \tcode{D} is +\tcode{default_delete}. A client-supplied template argument +\tcode{D} shall be a function +object type\iref{function.objects}, lvalue reference to function, or +lvalue reference to function object type +for which, given +a value \tcode{d} of type \tcode{D} and a value +\tcode{ptr} of type \tcode{unique_ptr::pointer}, the expression +\tcode{d(ptr)} is valid and has the effect of disposing of the +pointer as appropriate for that deleter. + +\pnum +If the deleter's type \tcode{D} is not a reference type, \tcode{D} shall meet +the \oldconcept{Destructible} requirements (\tref{cpp17.destructible}). + +\pnum +If the \grammarterm{qualified-id} \tcode{remove_reference_t::pointer} is valid and denotes a +type\iref{temp.deduct}, then \tcode{unique_ptr::pointer} shall be a synonym for \tcode{remove_reference_t::pointer}. Otherwise +\tcode{unique_ptr::pointer} shall be a synonym for \tcode{element_type*}. The type \tcode{unique_ptr::pointer} shall +meet the \oldconcept{NullablePointer} requirements (\tref{cpp17.nullablepointer}). + +\pnum +\begin{example} +Given an allocator type \tcode{X} (\tref{cpp17.allocator}) and +letting \tcode{A} be a synonym for \tcode{allocator_traits}, the types \tcode{A::pointer}, +\tcode{A::const_pointer}, \tcode{A::void_pointer}, and \tcode{A::const_void_pointer} +may be used as \tcode{unique_ptr::pointer}. +\end{example} + +\rSec4[unique.ptr.single.ctor]{Constructors} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +constexpr unique_ptr() noexcept; +constexpr unique_ptr(nullptr_t) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_pointer_v} is \tcode{false} and +\tcode{is_default_constructible_v} is \tcode{true}. + +\pnum +\expects +\tcode{D} meets the \oldconcept{DefaultConstructible} requirements (\tref{cpp17.defaultconstructible}), +and that construction does not throw an exception. + +\pnum +\effects +Constructs a \tcode{unique_ptr} object that owns +nothing, value-initializing the stored pointer and the stored deleter. + +\pnum +\ensures +\tcode{get() == nullptr}. \tcode{get_deleter()} +returns a reference to the stored deleter. +\end{itemdescr} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +constexpr explicit unique_ptr(type_identity_t p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_pointer_v} is \tcode{false} and +\tcode{is_default_constructible_v} is \tcode{true}. + +\pnum +\expects +\tcode{D} meets the \oldconcept{DefaultConstructible} requirements (\tref{cpp17.defaultconstructible}), +and that construction does not throw an exception. + +\pnum +\effects +Constructs a \tcode{unique_ptr} which owns +\tcode{p}, initializing the stored pointer with \tcode{p} and +value-initializing the stored deleter. + +\pnum +\ensures +\tcode{get() == p}. \tcode{get_deleter()} +returns a reference to the stored deleter. +\end{itemdescr} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +constexpr unique_ptr(type_identity_t p, const D& d) noexcept; +constexpr unique_ptr(type_identity_t p, remove_reference_t&& d) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\expects +For the first constructor, if \tcode{D} is not a reference type, +\tcode{D} meets the \oldconcept{CopyConstructible} requirements and +such construction does not exit via an exception. +For the second constructor, if \tcode{D} is not a reference type, +\tcode{D} meets the \oldconcept{MoveConstructible} requirements and +such construction does not exit via an exception. + +\pnum +\effects +Constructs a \tcode{unique_ptr} object which owns \tcode{p}, initializing +the stored pointer with \tcode{p} and initializing the deleter +from \tcode{std::forward(d)}. + +\pnum +\ensures +\tcode{get() == p}. +\tcode{get_deleter()} returns a reference to the stored +deleter. If \tcode{D} is a reference type then \tcode{get_deleter()} +returns a reference to the lvalue \tcode{d}. + +\pnum +\remarks +If \tcode{D} is a reference type, +the second constructor is defined as deleted. + +\pnum +\begin{example} +\begin{codeblock} +D d; +unique_ptr p1(new int, D()); // \tcode{D} must be \oldconcept{MoveConstructible} +unique_ptr p2(new int, d); // \tcode{D} must be \oldconcept{CopyConstructible} +unique_ptr p3(new int, d); // \tcode{p3} holds a reference to \tcode{d} +unique_ptr p4(new int, D()); // error: rvalue deleter object combined + // with reference deleter type +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +constexpr unique_ptr(unique_ptr&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_move_constructible_v} is \tcode{true}. + +\pnum +\expects +If \tcode{D} is not a reference type, +\tcode{D} meets the \oldconcept{MoveConstructible} +requirements (\tref{cpp17.moveconstructible}). +Construction +of the deleter from an rvalue of type \tcode{D} does not +throw an exception. + +\pnum +\effects +Constructs a \tcode{unique_ptr} from +\tcode{u}. If \tcode{D} is a reference type, this +deleter is copy constructed from \tcode{u}'s deleter; otherwise, this +deleter is move constructed from \tcode{u}'s deleter. +\begin{note} +The +construction of the deleter can be implemented with \tcode{std::forward}. +\end{note} + +\pnum +\ensures +\tcode{get()} yields the value \tcode{u.get()} +yielded before the construction. \tcode{u.get() == nullptr}. +\tcode{get_deleter()} returns a reference +to the stored deleter that was constructed from +\tcode{u.get_deleter()}. If \tcode{D} is a reference type then +\tcode{get_deleter()} and \tcode{u.get_deleter()} both reference +the same lvalue deleter. +\end{itemdescr} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +template constexpr unique_ptr(unique_ptr&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{pointer}, +\item \tcode{U} is not an array type, and +\item either \tcode{D} is a reference type and \tcode{E} is the same type as \tcode{D}, or +\tcode{D} is not a reference type and \tcode{E} is implicitly convertible to \tcode{D}. +\end{itemize} + +\pnum +\expects +If \tcode{E} is not a reference type, +construction of the deleter from an rvalue of type \tcode{E} +is well-formed and does not throw an exception. +Otherwise, \tcode{E} is a reference type and +construction of the deleter from an lvalue of type \tcode{E} +is well-formed and does not throw an exception. + +\pnum +\effects +Constructs a \tcode{unique_ptr} from \tcode{u}. +If \tcode{E} is a reference type, this deleter is copy constructed from +\tcode{u}'s deleter; otherwise, this deleter is move constructed from \tcode{u}'s +deleter. +\begin{note} +The deleter constructor can be implemented with +\tcode{std::forward}. +\end{note} + +\pnum +\ensures +\tcode{get()} yields the value \tcode{u.get()} +yielded before the construction. \tcode{u.get() == nullptr}. +\tcode{get_deleter()} returns a reference +to the stored deleter that was constructed from +\tcode{u.get_deleter()}. +\end{itemdescr} + +\rSec4[unique.ptr.single.dtor]{Destructor} + +\indexlibrarydtor{unique_ptr}% +\begin{itemdecl} +constexpr ~unique_ptr(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{if (get()) get_deleter()(get());} +\begin{note} +The use of \tcode{default_delete} requires \tcode{T} to be a complete type. +\end{note} + +\pnum +\remarks +The behavior is undefined +if the evaluation of \tcode{get_deleter()(get())} throws an exception. +\end{itemdescr} + +\rSec4[unique.ptr.single.asgn]{Assignment} + +\indexlibrarymember{operator=}{unique_ptr}% +\begin{itemdecl} +constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_move_assignable_v} is \tcode{true}. + +\pnum +\expects +If \tcode{D} is not a reference type, \tcode{D} meets the +\oldconcept{MoveAssignable} requirements (\tref{cpp17.moveassignable}) and assignment +of the deleter from an rvalue of type \tcode{D} does not throw an exception. +Otherwise, \tcode{D} is a reference type; +\tcode{remove_reference_t} meets the \oldconcept{CopyAssignable} +requirements and assignment of the deleter from an +lvalue of type \tcode{D} does not throw an exception. + +\pnum +\effects +Calls \tcode{reset(u.release())} followed by +\tcode{get_deleter() = std::forward(u.get_dele\-ter())}. + +\pnum +\ensures +If \tcode{this != addressof(u)}, +\tcode{u.get() == nullptr}, +otherwise \tcode{u.get()} is unchanged. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{operator=}{unique_ptr}% +\begin{itemdecl} +template constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{pointer}, and +\item \tcode{U} is not an array type, and +\item \tcode{is_assignable_v} is \tcode{true}. +\end{itemize} + +\pnum +\expects +If \tcode{E} is not a reference type, +assignment of the deleter from an rvalue of type \tcode{E} +is well-formed and does not throw an exception. +Otherwise, \tcode{E} is a reference type and +assignment of the deleter from an lvalue of type \tcode{E} +is well-formed and does not throw an exception. + +\pnum +\effects +Calls \tcode{reset(u.release())} followed by +\tcode{get_deleter() = std::forward(u.get_dele\-ter())}. + +\pnum +\ensures +\tcode{u.get() == nullptr}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{operator=}{unique_ptr}% +\begin{itemdecl} +constexpr unique_ptr& operator=(nullptr_t) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +As if by \tcode{reset()}. + +\pnum +\ensures +\tcode{get() == nullptr}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\rSec4[unique.ptr.single.observers]{Observers} + +\indexlibrarymember{operator*}{unique_ptr}% +\begin{itemdecl} +constexpr add_lvalue_reference_t operator*() const noexcept(noexcept(*declval())); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{get() != nullptr}. + +\pnum +\returns +\tcode{*get()}. + +\end{itemdescr} + +\indexlibrarymember{operator->}{unique_ptr}% +\begin{itemdecl} +constexpr pointer operator->() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{get() != nullptr}. + +\pnum +\returns +\tcode{get()}. + +\pnum +\begin{note} +The use of this function typically requires that \tcode{T} be a complete type. +\end{note} +\end{itemdescr} + +\indexlibrarymember{get}{unique_ptr}% +\begin{itemdecl} +constexpr pointer get() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The stored pointer. +\end{itemdescr} + +\indexlibrarymember{get_deleter}{unique_ptr}% +\begin{itemdecl} +constexpr deleter_type& get_deleter() noexcept; +constexpr const deleter_type& get_deleter() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A reference to the stored deleter. +\end{itemdescr} + +\indexlibrarymember{operator bool}{unique_ptr}% +\begin{itemdecl} +constexpr explicit operator bool() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{get() != nullptr}. +\end{itemdescr} + +\rSec4[unique.ptr.single.modifiers]{Modifiers} + +\indexlibrarymember{release}{unique_ptr}% +\begin{itemdecl} +constexpr pointer release() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{get() == nullptr}. + +\pnum +\returns +The value \tcode{get()} had at the start of +the call to \tcode{release}. +\end{itemdescr} + +\indexlibrarymember{reset}{unique_ptr}% +\begin{itemdecl} +constexpr void reset(pointer p = pointer()) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Assigns \tcode{p} to the stored pointer, and then, +with the old value of the stored pointer, \tcode{old_p}, +evaluates \tcode{if (old_p) get_deleter()(old_p);} +\begin{note} +The order of these operations is significant +because the call to \tcode{get_deleter()} might destroy \tcode{*this}. +\end{note} + +\pnum +\ensures +\tcode{get() == p}. +\begin{note} +The postcondition does not hold if the call to \tcode{get_deleter()} +destroys \tcode{*this} since \tcode{this->get()} is no longer a valid expression. +\end{note} + +\pnum +\remarks +The behavior is undefined +if the evaluation of \tcode{get_deleter()(old_p)} throws an exception. +\end{itemdescr} + +\indexlibrarymember{swap}{unique_ptr}% +\begin{itemdecl} +constexpr void swap(unique_ptr& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{get_deleter()} is swappable\iref{swappable.requirements} and +does not throw an exception under \tcode{swap}. + +\pnum +\effects +Invokes \tcode{swap} on the stored pointers and on the stored +deleters of \tcode{*this} and \tcode{u}. +\end{itemdescr} + +\rSec3[unique.ptr.runtime]{\tcode{unique_ptr} for array objects with a runtime length} + +\rSec4[unique.ptr.runtime.general]{General} + +\indexlibraryglobal{unique_ptr}% +\begin{codeblock} +namespace std { + template class unique_ptr { + public: + using pointer = @\seebelow@; + using element_type = T; + using deleter_type = D; + + // \ref{unique.ptr.runtime.ctor}, constructors + constexpr unique_ptr() noexcept; + template constexpr explicit unique_ptr(U p) noexcept; + template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; + template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; + constexpr unique_ptr(unique_ptr&& u) noexcept; + template + constexpr unique_ptr(unique_ptr&& u) noexcept; + constexpr unique_ptr(nullptr_t) noexcept; + + // destructor + constexpr ~unique_ptr(); + + // assignment + constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; + template + constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; + constexpr unique_ptr& operator=(nullptr_t) noexcept; + + // \ref{unique.ptr.runtime.observers}, observers + constexpr T& operator[](size_t i) const; + constexpr pointer get() const noexcept; + constexpr deleter_type& get_deleter() noexcept; + constexpr const deleter_type& get_deleter() const noexcept; + constexpr explicit operator bool() const noexcept; + + // \ref{unique.ptr.runtime.modifiers}, modifiers + constexpr pointer release() noexcept; + template constexpr void reset(U p) noexcept; + constexpr void reset(nullptr_t = nullptr) noexcept; + constexpr void swap(unique_ptr& u) noexcept; + + // disable copy from lvalue + unique_ptr(const unique_ptr&) = delete; + unique_ptr& operator=(const unique_ptr&) = delete; + }; +} +\end{codeblock} + +\pnum +A specialization for array types is provided with a slightly altered +interface. + +\begin{itemize} +\item Conversions between different types of +\tcode{unique_ptr} +that would be disallowed for the corresponding pointer-to-array types, +and conversions to or from the non-array forms of +\tcode{unique_ptr}, produce an ill-formed program. + +\item Pointers to types derived from \tcode{T} are +rejected by the constructors, and by \tcode{reset}. + +\item The observers \tcode{operator*} and +\tcode{operator->} are not provided. + +\item The indexing observer \tcode{operator[]} is provided. + +\item The default deleter will call \tcode{delete[]}. +\end{itemize} + +\pnum +Descriptions are provided below only for members that +differ from the primary template. + +\pnum +The template argument \tcode{T} shall be a complete type. + +\rSec4[unique.ptr.runtime.ctor]{Constructors} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +template constexpr explicit unique_ptr(U p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +This constructor behaves the same as +the constructor in the primary template that +takes a single parameter of type \tcode{pointer}. + +\pnum +\constraints +\begin{itemize} +\item \tcode{U} is the same type as \tcode{pointer}, or +\item \tcode{pointer} is the same type as \tcode{element_type*}, +\tcode{U} is a pointer type \tcode{V*}, and +\tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}. +\end{itemize} +\end{itemdescr} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; +template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +These constructors behave the same as +the constructors in the primary template that +take a parameter of type \tcode{pointer} and a second parameter. + +\pnum +\constraints +\begin{itemize} +\item \tcode{U} is the same type as \tcode{pointer}, +\item \tcode{U} is \tcode{nullptr_t}, or +\item \tcode{pointer} is the same type as \tcode{element_type*}, + \tcode{U} is a pointer type \tcode{V*}, and + \tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}. +\end{itemize} +\end{itemdescr} + +\indexlibraryctor{unique_ptr}% +\begin{itemdecl} +template constexpr unique_ptr(unique_ptr&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +This constructor behaves the same as in the primary template. + +\pnum +\constraints +Where \tcode{UP} is \tcode{unique_ptr}: +\begin{itemize} +\item \tcode{U} is an array type, and +\item \tcode{pointer} is the same type as \tcode{element_type*}, and +\item \tcode{UP::pointer} is the same type as \tcode{UP::element_type*}, and +\item \tcode{UP::element_type(*)[]} is convertible to \tcode{element_type(*)[]}, and +\item either \tcode{D} is a reference type and \tcode{E} is the same type as \tcode{D}, + or \tcode{D} is not a reference type and \tcode{E} is implicitly convertible to \tcode{D}. +\end{itemize} + +\begin{note} +This replaces the \constraints specification of the primary template. +\end{note} +\end{itemdescr} + +\rSec4[unique.ptr.runtime.asgn]{Assignment} + +\indexlibrarymember{operator=}{unique_ptr}% +\begin{itemdecl} +template constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +This operator behaves the same as in the primary template. + +\pnum +\constraints +Where \tcode{UP} is \tcode{unique_ptr}: +\begin{itemize} +\item \tcode{U} is an array type, and +\item \tcode{pointer} is the same type as \tcode{element_type*}, and +\item \tcode{UP::pointer} is the same type as \tcode{UP::element_type*}, and +\item \tcode{UP::element_type(*)[]} is convertible to \tcode{element_type(*)[]}, and +\item \tcode{is_assignable_v} is \tcode{true}. +\end{itemize} + +\begin{note} +This replaces the \constraints specification of the primary template. +\end{note} +\end{itemdescr} + +\rSec4[unique.ptr.runtime.observers]{Observers} + +\indexlibrarymember{operator[]}{unique_ptr}% +\begin{itemdecl} +constexpr T& operator[](size_t i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +$\tcode{i} <$ the +number of elements in the array to which +the stored pointer points. + +\pnum +\returns +\tcode{get()[i]}. +\end{itemdescr} + +\rSec4[unique.ptr.runtime.modifiers]{Modifiers} + +\indexlibrarymember{reset}{unique_ptr}% +\begin{itemdecl} +constexpr void reset(nullptr_t p = nullptr) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{reset(pointer())}. +\end{itemdescr} + +\indexlibrarymember{reset}{unique_ptr}% +\begin{itemdecl} +constexpr template void reset(U p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +This function behaves the same as +the \tcode{reset} member of the primary template. + +\pnum +\constraints +\begin{itemize} +\item \tcode{U} is the same type as \tcode{pointer}, or +\item \tcode{pointer} is the same type as \tcode{element_type*}, + \tcode{U} is a pointer type \tcode{V*}, and + \tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}. +\end{itemize} +\end{itemdescr} + +\rSec3[unique.ptr.create]{Creation} + +\indexlibraryglobal{make_unique}% +\begin{itemdecl} +template constexpr unique_ptr make_unique(Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is not an array type. + +\pnum +\returns +\tcode{unique_ptr(new T(std::forward(args)...))}. + +\end{itemdescr} + +\indexlibraryglobal{make_unique}% +\begin{itemdecl} +template constexpr unique_ptr make_unique(size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an array of unknown bound. + +\pnum +\returns +\tcode{unique_ptr(new remove_extent_t[n]())}. + +\end{itemdescr} + +\indexlibraryglobal{make_unique}% +\begin{itemdecl} +template @\unspec@ make_unique(Args&&...) = delete; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an array of known bound. + +\end{itemdescr} + +\indexlibraryglobal{make_unique}% +\begin{itemdecl} +template constexpr unique_ptr make_unique_for_overwrite(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is not an array type. + +\pnum +\returns +\tcode{unique_ptr(new T)}. +\end{itemdescr} + +\indexlibraryglobal{make_unique}% +\begin{itemdecl} +template constexpr unique_ptr make_unique_for_overwrite(size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an array of unknown bound. + +\pnum +\returns +\tcode{unique_ptr(new remove_extent_t[n])}. +\end{itemdescr} + +\indexlibraryglobal{make_unique}% +\begin{itemdecl} +template @\unspec@ make_unique_for_overwrite(Args&&...) = delete; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an array of known bound. +\end{itemdescr} + +\rSec3[unique.ptr.special]{Specialized algorithms} + +\indexlibrary{\idxcode{swap(unique_ptr\&, unique_ptr\&)}}% +\begin{itemdecl} +template constexpr void swap(unique_ptr& x, unique_ptr& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_swappable_v} is \tcode{true}. + +\pnum +\effects +Calls \tcode{x.swap(y)}. +\end{itemdescr} + +\indexlibrarymember{operator==}{unique_ptr}% +\begin{itemdecl} +template + constexpr bool operator==(const unique_ptr& x, const unique_ptr& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.get() == y.get()}. +\end{itemdescr} + +\indexlibrarymember{operator<}{unique_ptr}% +\begin{itemdecl} +template + bool operator<(const unique_ptr& x, const unique_ptr& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{CT} denote +\begin{codeblock} +common_type_t::pointer, + typename unique_ptr::pointer> +\end{codeblock} + +\pnum +\mandates +\begin{itemize} +\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{CT} and +\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{CT}. +\end{itemize} + +\pnum +\expects +The specialization +\tcode{less} is a function object type\iref{function.objects} that +induces a strict weak ordering\iref{alg.sorting} on the pointer values. + +\pnum +\returns +\tcode{less()(x.get(), y.get())}. +\end{itemdescr} + +\indexlibrarymember{operator>}{unique_ptr}% +\begin{itemdecl} +template + bool operator>(const unique_ptr& x, const unique_ptr& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{y < x}. +\end{itemdescr} + +\indexlibrarymember{operator<=}{unique_ptr}% +\begin{itemdecl} +template + bool operator<=(const unique_ptr& x, const unique_ptr& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!(y < x)}. +\end{itemdescr} + +\indexlibrarymember{operator>=}{unique_ptr}% +\begin{itemdecl} +template + bool operator>=(const unique_ptr& x, const unique_ptr& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!(x < y)}. +\end{itemdescr} + +\indexlibrarymember{operator<=>}{unique_ptr}% +\begin{itemdecl} +template + requires @\libconcept{three_way_comparable_with}@::pointer, + typename unique_ptr::pointer> + compare_three_way_result_t::pointer, + typename unique_ptr::pointer> + operator<=>(const unique_ptr& x, const unique_ptr& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{compare_three_way()(x.get(), y.get())}. +\end{itemdescr} + +\indexlibrarymember{operator==}{unique_ptr}% +\begin{itemdecl} +template + constexpr bool operator==(const unique_ptr& x, nullptr_t) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!x}. +\end{itemdescr} + +\indexlibrarymember{operator<}{unique_ptr}% +\begin{itemdecl} +template + constexpr bool operator<(const unique_ptr& x, nullptr_t); +template + constexpr bool operator<(nullptr_t, const unique_ptr& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The specialization \tcode{less::pointer>} is +a function object type\iref{function.objects} that induces a strict weak +ordering\iref{alg.sorting} on the pointer values. + +\pnum +\returns +The first function template returns +\begin{codeblock} +less::pointer>()(x.get(), nullptr) +\end{codeblock} +The second function template returns +\begin{codeblock} +less::pointer>()(nullptr, x.get()) +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator>}{unique_ptr}% +\begin{itemdecl} +template + constexpr bool operator>(const unique_ptr& x, nullptr_t); +template + constexpr bool operator>(nullptr_t, const unique_ptr& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The first function template returns \tcode{nullptr < x}. +The second function template returns \tcode{x < nullptr}. +\end{itemdescr} + +\indexlibrarymember{operator<=}{unique_ptr}% +\begin{itemdecl} +template + constexpr bool operator<=(const unique_ptr& x, nullptr_t); +template + constexpr bool operator<=(nullptr_t, const unique_ptr& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The first function template returns \tcode{!(nullptr < x)}. +The second function template returns \tcode{!(x < nullptr)}. +\end{itemdescr} + +\indexlibrarymember{operator>=}{unique_ptr}% +\begin{itemdecl} +template + constexpr bool operator>=(const unique_ptr& x, nullptr_t); +template + constexpr bool operator>=(nullptr_t, const unique_ptr& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The first function template returns \tcode{!(x < nullptr)}. +The second function template returns \tcode{!(nullptr < x)}. +\end{itemdescr} + +\indexlibrarymember{operator<=>}{unique_ptr}% +\begin{itemdecl} +template + requires @\libconcept{three_way_comparable}@::pointer> + constexpr compare_three_way_result_t::pointer> + operator<=>(const unique_ptr& x, nullptr_t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +compare_three_way()(x.get(), static_cast::pointer>(nullptr)). +\end{codeblock} +\end{itemdescr} + +\rSec3[unique.ptr.io]{I/O} + +\indexlibrarymember{operator<<}{unique_ptr}% +\begin{itemdecl} +template + basic_ostream& operator<<(basic_ostream& os, const unique_ptr& p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{os << p.get()} is a valid expression. + +\pnum +\effects +Equivalent to: \tcode{os << p.get();} + +\pnum +\returns +\tcode{os}. +\end{itemdescr} + +\rSec2[util.sharedptr]{Shared-ownership pointers} + +\rSec3[util.smartptr.weak.bad]{Class \tcode{bad_weak_ptr}}% +\indextext{smart pointers|(}% + +\indexlibraryglobal{bad_weak_ptr}% +\begin{codeblock} +namespace std { + class bad_weak_ptr : public exception { + public: + // see \ref{exception} for the specification of the special member functions + const char* what() const noexcept override; + }; +} +\end{codeblock} + +\pnum +An exception of type \tcode{bad_weak_ptr} is thrown by the \tcode{shared_ptr} +constructor taking a \tcode{weak_ptr}. + +\indexlibrarymember{what}{bad_weak_ptr}% +\begin{itemdecl} +const char* what() const noexcept override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An \impldef{return value of \tcode{bad_weak_ptr::what}} \ntbs{}. +\end{itemdescr} + +\rSec3[util.smartptr.shared]{Class template \tcode{shared_ptr}} + +\rSec4[util.smartptr.shared.general]{General} + +\pnum +\indexlibraryglobal{shared_ptr}% +The \tcode{shared_ptr} class template stores a pointer, usually obtained +via \keyword{new}. \tcode{shared_ptr} implements semantics of shared ownership; +the last remaining owner of the pointer is responsible for destroying +the object, or otherwise releasing the resources associated with the stored pointer. A +\tcode{shared_ptr} is said to be empty if it does not own a pointer. + +\begin{codeblock} +namespace std { + template class shared_ptr { + public: + using element_type = remove_extent_t; + using weak_type = weak_ptr; + + // \ref{util.smartptr.shared.const}, constructors + constexpr shared_ptr() noexcept; + constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { } + template + explicit shared_ptr(Y* p); + template + shared_ptr(Y* p, D d); + template + shared_ptr(Y* p, D d, A a); + template + shared_ptr(nullptr_t p, D d); + template + shared_ptr(nullptr_t p, D d, A a); + template + shared_ptr(const shared_ptr& r, element_type* p) noexcept; + template + shared_ptr(shared_ptr&& r, element_type* p) noexcept; + shared_ptr(const shared_ptr& r) noexcept; + template + shared_ptr(const shared_ptr& r) noexcept; + shared_ptr(shared_ptr&& r) noexcept; + template + shared_ptr(shared_ptr&& r) noexcept; + template + explicit shared_ptr(const weak_ptr& r); + template + shared_ptr(unique_ptr&& r); + + // \ref{util.smartptr.shared.dest}, destructor + ~shared_ptr(); + + // \ref{util.smartptr.shared.assign}, assignment + shared_ptr& operator=(const shared_ptr& r) noexcept; + template + shared_ptr& operator=(const shared_ptr& r) noexcept; + shared_ptr& operator=(shared_ptr&& r) noexcept; + template + shared_ptr& operator=(shared_ptr&& r) noexcept; + template + shared_ptr& operator=(unique_ptr&& r); + + // \ref{util.smartptr.shared.mod}, modifiers + void swap(shared_ptr& r) noexcept; + void reset() noexcept; + template + void reset(Y* p); + template + void reset(Y* p, D d); + template + void reset(Y* p, D d, A a); + + // \ref{util.smartptr.shared.obs}, observers + element_type* get() const noexcept; + T& operator*() const noexcept; + T* operator->() const noexcept; + element_type& operator[](ptrdiff_t i) const; + long use_count() const noexcept; + explicit operator bool() const noexcept; + template + bool owner_before(const shared_ptr& b) const noexcept; + template + bool owner_before(const weak_ptr& b) const noexcept; + }; + + template + shared_ptr(weak_ptr) -> shared_ptr; + template + shared_ptr(unique_ptr) -> shared_ptr; +} +\end{codeblock} + +\pnum +Specializations of \tcode{shared_ptr} shall be \oldconcept{CopyConstructible}, +\oldconcept{CopyAssignable}, and \oldconcept{\-Less\-Than\-Comparable}, allowing their use in standard +containers. Specializations of \tcode{shared_ptr} shall be +contextually convertible to \tcode{bool}, +allowing their use in boolean expressions and declarations in conditions. + +\pnum +The template parameter \tcode{T} of \tcode{shared_ptr} +may be an incomplete type. +\begin{note} +\tcode{T} can be a function type. +\end{note} + +\pnum +\begin{example} +\begin{codeblock} +if (shared_ptr px = dynamic_pointer_cast(py)) { + // do something with \tcode{px} +} +\end{codeblock} +\end{example} + +\pnum +For purposes of determining the presence of a data race, member functions shall +access and modify only the \tcode{shared_ptr} and \tcode{weak_ptr} objects +themselves and not objects they refer to. Changes in \tcode{use_count()} do not +reflect modifications that can introduce data races. + +\pnum +For the purposes of subclause \ref{smartptr}, +a pointer type \tcode{Y*} is said to be +\defnx{compatible with}{compatible with!\idxcode{shared_ptr}} +a pointer type \tcode{T*} when either +\tcode{Y*} is convertible to \tcode{T*} or +\tcode{Y} is \tcode{U[N]} and \tcode{T} is \cv{}~\tcode{U[]}. + +\rSec4[util.smartptr.shared.const]{Constructors} + +\pnum +In the constructor definitions below, +enables \tcode{shared_from_this} with \tcode{p}, +for a pointer \tcode{p} of type \tcode{Y*}, +means that if \tcode{Y} has an unambiguous and accessible base class +that is a specialization of \tcode{enable_shared_from_this}\iref{util.smartptr.enab}, +then \tcode{remove_cv_t*} shall be implicitly convertible to \tcode{T*} and +the constructor evaluates the statement: +\begin{codeblock} +if (p != nullptr && p->weak_this.expired()) + p->weak_this = shared_ptr>(*this, const_cast*>(p)); +\end{codeblock} +The assignment to the \tcode{weak_this} member is not atomic and +conflicts with any potentially concurrent access to the same object\iref{intro.multithread}. + +\indexlibraryctor{shared_ptr}% +\begin{itemdecl} +constexpr shared_ptr() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{use_count() == 0 \&\& get() == nullptr}. +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\begin{itemdecl} +template explicit shared_ptr(Y* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +When \tcode{T} is an array type, +the expression \tcode{delete[] p} is well-formed and either +\tcode{T} is \tcode{U[N]} and \tcode{Y(*)[N]} is convertible to \tcode{T*}, or +\tcode{T} is \tcode{U[]} and \tcode{Y(*)[]} is convertible to \tcode{T*}. +When \tcode{T} is not an array type, +the expression \tcode{delete p} is well-formed and +\tcode{Y*} is convertible to \tcode{T*}. + +\pnum +\mandates +\tcode{Y} is a complete type. + +\pnum +\expects +The expression +\tcode{delete[] p}, when \tcode{T} is an array type, or +\tcode{delete p}, when \tcode{T} is not an array type, +has well-defined behavior, and +does not throw exceptions. + +\pnum +\effects +When \tcode{T} is not an array type, +constructs a \tcode{shared_ptr} object +that owns the pointer \tcode{p}. +Otherwise, constructs a \tcode{shared_ptr} +that owns \tcode{p} and a deleter of an +unspecified type that calls \tcode{delete[] p}. +When \tcode{T} is not an array type, +enables \tcode{shared_from_this} with \tcode{p}. +If an exception is thrown, \tcode{delete p} is called +when \tcode{T} is not an array type, \tcode{delete[] p} otherwise. + +\pnum +\ensures +\tcode{use_count() == 1 \&\& get() == p}. + +\pnum +\throws +\tcode{bad_alloc}, or an \impldef{exception type when \tcode{shared_ptr} +constructor fails} exception when a resource other than memory cannot be obtained. +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\begin{itemdecl} +template shared_ptr(Y* p, D d); +template shared_ptr(Y* p, D d, A a); +template shared_ptr(nullptr_t p, D d); +template shared_ptr(nullptr_t p, D d, A a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_move_constructible_v} is \tcode{true}, and +\tcode{d(p)} is a well-formed expression. +For the first two overloads: + +\begin{itemize} +\item +If \tcode{T} is an array type, then either +\tcode{T} is \tcode{U[N]} and \tcode{Y(*)[N]} is convertible to \tcode{T*}, or +\tcode{T} is \tcode{U[]} and \tcode{Y(*)[]} is convertible to \tcode{T*}. + +\item +If \tcode{T} is not an array type, then \tcode{Y*} is convertible to \tcode{T*}. +\end{itemize} + +\pnum +\expects +Construction of \tcode{d} and a deleter of type \tcode{D} +initialized with \tcode{std::move(d)} do not throw exceptions. +The expression \tcode{d(p)} +has well-defined behavior and does not throw exceptions. +\tcode{A} meets the \oldconcept{Allocator} requirements (\tref{cpp17.allocator}). + +\pnum +\effects +Constructs a \tcode{shared_ptr} object that owns the +object \tcode{p} and the deleter \tcode{d}. +When \tcode{T} is not an array type, +the first and second constructors enable \tcode{shared_from_this} with \tcode{p}. +The second and fourth constructors shall use a copy of \tcode{a} to +allocate memory for internal use. +If an exception is thrown, \tcode{d(p)} is called. + +\pnum +\ensures +\tcode{use_count() == 1 \&\& get() == p}. + +\pnum +\throws +\tcode{bad_alloc}, or an \impldef{exception type when \tcode{shared_ptr} +constructor fails} exception +when a resource other than memory cannot be obtained. +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\begin{itemdecl} +template shared_ptr(const shared_ptr& r, element_type* p) noexcept; +template shared_ptr(shared_ptr&& r, element_type* p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{shared_ptr} instance that +stores \tcode{p} and shares ownership with +the initial value of \tcode{r}. + +\pnum +\ensures +\tcode{get() == p}. +For the second overload, +\tcode{r} is empty and \tcode{r.get() == nullptr}. + +\pnum +\begin{note} +Use of this constructor leads to a dangling pointer +unless \tcode{p} remains valid +at least until the ownership group of \tcode{r} is destroyed. +\end{note} + +\pnum +\begin{note} +This constructor allows creation of an empty +\tcode{shared_ptr} instance with a non-null stored pointer. +\end{note} +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\begin{itemdecl} +shared_ptr(const shared_ptr& r) noexcept; +template shared_ptr(const shared_ptr& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the second constructor, \tcode{Y*} is compatible with \tcode{T*}. + +\pnum +\effects +If \tcode{r} is empty, constructs +an empty \tcode{shared_ptr} object; otherwise, constructs +a \tcode{shared_ptr} object that shares ownership with \tcode{r}. + +\pnum +\ensures +\tcode{get() == r.get() \&\& use_count() == r.use_count()}. +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\begin{itemdecl} +shared_ptr(shared_ptr&& r) noexcept; +template shared_ptr(shared_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the second constructor, \tcode{Y*} is compatible with \tcode{T*}. + +\pnum +\effects +Move constructs a \tcode{shared_ptr} instance from \tcode{r}. + +\pnum +\ensures +\tcode{*this} contains the old value of +\tcode{r}. \tcode{r} is empty, and \tcode{r.get() == nullptr}. +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\indexlibraryglobal{weak_ptr}% +\begin{itemdecl} +template explicit shared_ptr(const weak_ptr& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{Y*} is compatible with \tcode{T*}. + +\pnum +\effects +Constructs a \tcode{shared_ptr} object that shares ownership with +\tcode{r} and stores a copy of the pointer stored in \tcode{r}. +If an exception is thrown, the constructor has no effect. + +\pnum +\ensures +\tcode{use_count() == r.use_count()}. + +\pnum +\throws +\tcode{bad_weak_ptr} when \tcode{r.expired()}. +\end{itemdescr} + +\indexlibraryctor{shared_ptr}% +\indexlibraryglobal{unique_ptr}% +\begin{itemdecl} +template shared_ptr(unique_ptr&& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{Y*} is compatible with \tcode{T*} and +\tcode{unique_ptr::pointer} is convertible to \tcode{element_type*}. + +\pnum +\effects +If \tcode{r.get() == nullptr}, equivalent to \tcode{shared_ptr()}. +Otherwise, if \tcode{D} is not a reference type, +equivalent to \tcode{shared_ptr(r.release(), std::move(r.get_deleter()))}. +Otherwise, equivalent to \tcode{shared_ptr(r.release(), ref(r.get_deleter()))}. +If an exception is thrown, the constructor has no effect. +\end{itemdescr} + +\rSec4[util.smartptr.shared.dest]{Destructor} + +\indexlibrarydtor{shared_ptr}% +\begin{itemdecl} +~shared_ptr(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item If \tcode{*this} is empty or shares ownership with another +\tcode{shared_ptr} instance (\tcode{use_count() > 1}), there are no side effects. + +\item +Otherwise, if \tcode{*this} owns an object +\tcode{p} and a deleter \tcode{d}, \tcode{d(p)} is called. + +\item Otherwise, \tcode{*this} owns a pointer \tcode{p}, +and \tcode{delete p} is called. +\end{itemize} +\end{itemdescr} + +\pnum +\begin{note} +Since the destruction of \tcode{*this} +decreases the number of instances that share ownership with \tcode{*this} +by one, +after \tcode{*this} has been destroyed +all \tcode{shared_ptr} instances that shared ownership with +\tcode{*this} will report a \tcode{use_count()} that is one less +than its previous value. +\end{note} + +\rSec4[util.smartptr.shared.assign]{Assignment} + +\indexlibrarymember{operator=}{shared_ptr}% +\begin{itemdecl} +shared_ptr& operator=(const shared_ptr& r) noexcept; +template shared_ptr& operator=(const shared_ptr& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr(r).swap(*this)}. + +\pnum +\returns +\tcode{*this}. + +\pnum +\begin{note} +The use count updates caused by the temporary object +construction and destruction are not observable side +effects, so the implementation can meet the effects (and the +implied guarantees) via different means, without creating a +temporary. In particular, in the example: +\begin{codeblock} +shared_ptr p(new int); +shared_ptr q(p); +p = p; +q = p; +\end{codeblock} +both assignments can be no-ops. +\end{note} +\end{itemdescr} + +\indexlibrarymember{operator=}{shared_ptr}% +\begin{itemdecl} +shared_ptr& operator=(shared_ptr&& r) noexcept; +template shared_ptr& operator=(shared_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr(std::move(r)).swap(*this)}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{operator=}{shared_ptr}% +\begin{itemdecl} +template shared_ptr& operator=(unique_ptr&& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr(std::move(r)).swap(*this)}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\rSec4[util.smartptr.shared.mod]{Modifiers} + +\indexlibrarymember{swap}{shared_ptr}% +\begin{itemdecl} +void swap(shared_ptr& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} + +\pnum +\effects +Exchanges the contents of \tcode{*this} and \tcode{r}. +\end{itemdescr} + +\indexlibrarymember{reset}{shared_ptr}% +\begin{itemdecl} +void reset() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr().swap(*this)}. +\end{itemdescr} + +\indexlibrarymember{reset}{shared_ptr}% +\begin{itemdecl} +template void reset(Y* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr(p).swap(*this)}. +\end{itemdescr} + +\indexlibrarymember{reset}{shared_ptr}% +\begin{itemdecl} +template void reset(Y* p, D d); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr(p, d).swap(*this)}. +\end{itemdescr} + +\indexlibrarymember{reset}{shared_ptr}% +\begin{itemdecl} +template void reset(Y* p, D d, A a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{shared_ptr(p, d, a).swap(*this)}. +\end{itemdescr} + +\rSec4[util.smartptr.shared.obs]{Observers} +\indexlibrarymember{get}{shared_ptr}% +\begin{itemdecl} +element_type* get() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The stored pointer. +\end{itemdescr} + +\indexlibrarymember{operator*}{shared_ptr}% +\begin{itemdecl} +T& operator*() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{get() != 0}. + +\pnum +\returns +\tcode{*get()}. + +\pnum +\remarks +When \tcode{T} is an array type or \cv{}~\keyword{void}, +it is unspecified whether this +member function is declared. If it is declared, it is unspecified what its +return type is, except that the declaration (although not necessarily the +definition) of the function shall be well-formed. +\end{itemdescr} + +\indexlibrarymember{operator->}{shared_ptr}% +\begin{itemdecl} +T* operator->() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{get() != 0}. + +\pnum +\returns +\tcode{get()}. + +\pnum +\remarks +When \tcode{T} is an array type, +it is unspecified whether this member function is declared. +If it is declared, it is unspecified what its return type is, +except that the declaration (although not necessarily the definition) +of the function shall be well-formed. +\end{itemdescr} + +\indexlibrarymember{operator[]}{shared_ptr}% +\begin{itemdecl} +element_type& operator[](ptrdiff_t i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{get() != 0 \&\& i >= 0}. +If \tcode{T} is \tcode{U[N]}, \tcode{i < N}. + +\pnum +\returns +\tcode{get()[i]}. + +\pnum +\throws +Nothing. + +\pnum +\remarks +When \tcode{T} is not an array type, +it is unspecified whether this member function is declared. +If it is declared, it is unspecified what its return type is, +except that the declaration (although not necessarily the definition) +of the function shall be well-formed. +\end{itemdescr} + +\indexlibrarymember{use_count}{shared_ptr}% +\begin{itemdecl} +long use_count() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\sync +None. + +\pnum +\returns +The number of \tcode{shared_ptr} objects, \tcode{*this} included, +that share ownership with \tcode{*this}, or \tcode{0} when \tcode{*this} is +empty. + +\pnum +\begin{note} +\tcode{get() == nullptr} +does not imply a specific return value of \tcode{use_count()}. +\end{note} + +\pnum +\begin{note} +\tcode{weak_ptr::lock()} +can affect the return value of \tcode{use_count()}. +\end{note} + +\pnum +\begin{note} +When multiple threads +might affect the return value of \tcode{use_count()}, +the result is approximate. +In particular, \tcode{use_count() == 1} does not imply that accesses through +a previously destroyed \tcode{shared_ptr} have in any sense completed. +\end{note} +\end{itemdescr} + +\indexlibrarymember{operator bool}{shared_ptr}% +\begin{itemdecl} +explicit operator bool() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{get() != 0}. +\end{itemdescr} + +\indexlibrarymember{owner_before}{shared_ptr}% +\begin{itemdecl} +template bool owner_before(const shared_ptr& b) const noexcept; +template bool owner_before(const weak_ptr& b) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An unspecified value such that +\begin{itemize} +\item \tcode{x.owner_before(y)} defines a strict weak ordering as defined in~\ref{alg.sorting}; + +\item under the equivalence relation defined by \tcode{owner_before}, +\tcode{!a.owner_before(b) \&\& !b.owner_before(a)}, two \tcode{shared_ptr} or +\tcode{weak_ptr} instances are equivalent if and only if they share ownership or +are both empty. +\end{itemize} + +\end{itemdescr} + +\rSec4[util.smartptr.shared.create]{Creation} + +\pnum +The common requirements that apply to all +\tcode{make_shared}, +\tcode{allocate_shared}, +\tcode{make_shared_for_overwrite}, and +\tcode{allocate_shared_for_overwrite} overloads, +unless specified otherwise, are described below. + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared(@\placeholdernc{args}@); +template + shared_ptr allocate_shared(const A& a, @\placeholdernc{args}@); +template + shared_ptr make_shared_for_overwrite(@\placeholdernc{args}@); +template + shared_ptr allocate_shared_for_overwrite(const A& a, @\placeholdernc{args}@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{A} meets the \oldconcept{Allocator} requirements (\tref{cpp17.allocator}). + +\pnum +\effects +Allocates memory for an object of type \tcode{T} +(or \tcode{U[N]} when \tcode{T} is \tcode{U[]}, +where \tcode{N} is determined from \placeholder{args} as specified by the concrete overload). +The object is initialized from \placeholder{args} as specified by the concrete overload. +The \tcode{allocate_shared} and \tcode{allocate_shared_for_overwrite} templates +use a copy of \tcode{a} +(rebound for an unspecified \tcode{value_type}) to allocate memory. +If an exception is thrown, the functions have no effect. + +\pnum +\ensures +\tcode{r.get() != 0 \&\& r.use_count() == 1}, +where \tcode{r} is the return value. + +\pnum +\returns +A \tcode{shared_ptr} instance that stores and owns the address of +the newly constructed object. + +\pnum +\throws +\tcode{bad_alloc}, or +an exception thrown from \tcode{allocate} or from the initialization of the object. + +\pnum +\remarks +\begin{itemize} +\item + Implementations should perform no more than one memory allocation. + \begin{note} + This provides efficiency equivalent to an intrusive smart pointer. + \end{note} +\item + When an object of an array type \tcode{U} is specified to have + an initial value of \tcode{u} (of the same type), + this shall be interpreted to mean that + each array element of the object has as its initial value + the corresponding element from \tcode{u}. +\item + When an object of an array type is specified to have + a default initial value, + this shall be interpreted to mean that each array element of the object + has a default initial value. +\item + When a (sub)object of a non-array type \tcode{U} is specified to have + an initial value of \tcode{v}, or \tcode{U(l...)}, + where \tcode{l...} is a list of constructor arguments, + \tcode{make_shared} shall initialize this (sub)object + via the expression \tcode{::new(pv) U(v)} or \tcode{::new(pv) U(l...)} respectively, + where \tcode{pv} has type \tcode{void*} and points to storage + suitable to hold an object of type \tcode{U}. +\item + When a (sub)object of a non-array type \tcode{U} is specified to have + an initial value of \tcode{v}, or \tcode{U(l...)}, + where \tcode{l...} is a list of constructor arguments, + \tcode{allocate_shared} shall initialize this (sub)object + via the expression + \begin{itemize} + \item \tcode{allocator_traits::construct(a2, pv, v)} or + \item \tcode{allocator_traits::construct(a2, pv, l...)} + \end{itemize} + respectively, + where \tcode{pv} points to storage + suitable to hold an object of type \tcode{U} and + \tcode{a2} of type \tcode{A2} is a rebound copy of + the allocator \tcode{a} passed to \tcode{allocate_shared} + such that its \tcode{value_type} is \tcode{remove_cv_t}. +\item + When a (sub)object of non-array type \tcode{U} is specified to have + a default initial value, + \tcode{make_shared} shall initialize this (sub)object + via the expression \tcode{::new(pv) U()}, + where \tcode{pv} has type \tcode{void*} and points to storage + suitable to hold an object of type \tcode{U}. +\item + When a (sub)object of non-array type \tcode{U} is specified to have + a default initial value, + \tcode{allocate_shared} shall initialize this (sub)object + via the expression \tcode{allocator_traits::construct(a2, pv)}, + where \tcode{pv} points to storage + suitable to hold an object of type \tcode{U} and + \tcode{a2} of type \tcode{A2} is a rebound copy of + the allocator \tcode{a} passed to \tcode{allocate_shared} + such that its \tcode{value_type} is \tcode{remove_cv_t}. +\item + When a (sub)object of non-array type \tcode{U} is initialized by + \tcode{make_shared_for_overwrite} or\linebreak % avoid Overfull + \tcode{allocate_shared_for_overwrite}, + it is initialized via the expression \tcode{::new(pv) U}, + where \tcode{pv} has type \tcode{void*} and + points to storage suitable to hold an object of type \tcode{U}. +\item + Array elements are initialized in ascending order of their addresses. +\item + When the lifetime of the object managed by the return value ends, or + when the initialization of an array element throws an exception, + the initialized elements are destroyed in the reverse order + of their original construction. +\item + When a (sub)object of non-array type \tcode{U} + that was initialized by \tcode{make_shared} is to be destroyed, + it is destroyed via the expression \tcode{pv->\~{}U()} where + \tcode{pv} points to that object of type \tcode{U}. +\item + When a (sub)object of non-array type \tcode{U} + that was initialized by \tcode{allocate_shared} is to be destroyed, + it is destroyed via the expression + \tcode{allocator_traits::destroy(a2, pv)} where + \tcode{pv} points to that object of type \tcode{remove_cv_t} and + \tcode{a2} of type \tcode{A2} is a rebound copy of + the allocator \tcode{a} passed to \tcode{allocate_shared} + such that its \tcode{value_type} is \tcode{remove_cv_t}. +\end{itemize} +\begin{note} +These functions will typically allocate more memory than \tcode{sizeof(T)} to +allow for internal bookkeeping structures such as reference counts. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared(Args&&... args); // \tcode{T} is not array +template + shared_ptr allocate_shared(const A& a, Args&&... args); // \tcode{T} is not array +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is not an array type. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{T} +with an initial value \tcode{T(forward(args)...)}. + +\pnum +\remarks +The \tcode{shared_ptr} constructors called by these functions +enable \tcode{shared_from_this} +with the address of the newly constructed object of type \tcode{T}. + +\pnum +\begin{example} +\begin{codeblock} +shared_ptr p = make_shared(); // \tcode{shared_ptr} to \tcode{int()} +shared_ptr> q = make_shared>(16, 1); + // \tcode{shared_ptr} to vector of \tcode{16} elements with value \tcode{1} +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template shared_ptr + make_shared(size_t N); // \tcode{T} is \tcode{U[]} +template + shared_ptr allocate_shared(const A& a, size_t N); // \tcode{T} is \tcode{U[]} +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is of the form \tcode{U[]}. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{U[N]} +with a default initial value, +where \tcode{U} is \tcode{remove_extent_t}. + +\pnum +\begin{example} +\begin{codeblock} +shared_ptr p = make_shared(1024); + // \tcode{shared_ptr} to a value-initialized \tcode{double[1024]} +shared_ptr q = make_shared(6); + // \tcode{shared_ptr} to a value-initialized \tcode{double[6][2][2]} +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared(); // \tcode{T} is \tcode{U[N]} +template + shared_ptr allocate_shared(const A& a); // \tcode{T} is \tcode{U[N]} +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is of the form \tcode{U[N]}. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{T} +with a default initial value. + +\pnum +\begin{example} +\begin{codeblock} +shared_ptr p = make_shared(); + // \tcode{shared_ptr} to a value-initialized \tcode{double[1024]} +shared_ptr q = make_shared(); + // \tcode{shared_ptr} to a value-initialized \tcode{double[6][2][2]} +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared(size_t N, + const remove_extent_t& u); // \tcode{T} is \tcode{U[]} +template + shared_ptr allocate_shared(const A& a, size_t N, + const remove_extent_t& u); // \tcode{T} is \tcode{U[]} +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is of the form \tcode{U[]}. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{U[N]}, +where \tcode{U} is \tcode{remove_extent_t} and +each array element has an initial value of \tcode{u}. + +\pnum +\begin{example} +\begin{codeblock} +shared_ptr p = make_shared(1024, 1.0); + // \tcode{shared_ptr} to a \tcode{double[1024]}, where each element is \tcode{1.0} +shared_ptr q = make_shared(6, {1.0, 0.0}); + // \tcode{shared_ptr} to a \tcode{double[6][2]}, where each \tcode{double[2]} element is \tcode{\{1.0, 0.0\}} +shared_ptr[]> r = make_shared[]>(4, {1, 2}); + // \tcode{shared_ptr} to a \tcode{vector[4]}, where each vector has contents \tcode{\{1, 2\}} +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared(const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} +template + shared_ptr allocate_shared(const A& a, + const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is of the form \tcode{U[N]}. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{T}, +where each array element of type \tcode{remove_extent_t} +has an initial value of \tcode{u}. + +\pnum +\begin{example} +\begin{codeblock} +shared_ptr p = make_shared(1.0); + // \tcode{shared_ptr} to a \tcode{double[1024]}, where each element is \tcode{1.0} +shared_ptr q = make_shared({1.0, 0.0}); + // \tcode{shared_ptr} to a \tcode{double[6][2]}, where each double[2] element is \tcode{\{1.0, 0.0\}} +shared_ptr[4]> r = make_shared[4]>({1, 2}); + // \tcode{shared_ptr} to a \tcode{vector[4]}, where each vector has contents \tcode{\{1, 2\}} +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared_for_overwrite(); +template + shared_ptr allocate_shared_for_overwrite(const A& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is not an array of unknown bound. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{T}. + +\pnum +\begin{example} +\begin{codeblock} +struct X { double data[1024]; }; +shared_ptr p = make_shared_for_overwrite(); + // \tcode{shared_ptr} to a default-initialized \tcode{X}, where each element in \tcode{X::data} has an indeterminate value + +shared_ptr q = make_shared_for_overwrite(); + // \tcode{shared_ptr} to a default-initialized \tcode{double[1024]}, where each element has an indeterminate value +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{make_shared}% +\indexlibraryglobal{allocate_shared}% +\begin{itemdecl} +template + shared_ptr make_shared_for_overwrite(size_t N); +template + shared_ptr allocate_shared_for_overwrite(const A& a, size_t N); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is an array of unknown bound. + +\pnum +\returns +A \tcode{shared_ptr} to an object of type \tcode{U[N]}, +where \tcode{U} is \tcode{remove_extent_t}. + +\pnum +\begin{example} +\begin{codeblock} +shared_ptr p = make_shared_for_overwrite(1024); + // \tcode{shared_ptr} to a default-initialized \tcode{double[1024]}, where each element has an indeterminate value +\end{codeblock} +\end{example} +\end{itemdescr} + +\rSec4[util.smartptr.shared.cmp]{Comparison} + +\indexlibrarymember{operator==}{shared_ptr}% +\begin{itemdecl} +template + bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{a.get() == b.get()}. +\end{itemdescr} + +\indexlibrarymember{operator==}{shared_ptr}% +\begin{itemdecl} +template + bool operator==(const shared_ptr& a, nullptr_t) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!a}. +\end{itemdescr} + +\indexlibrarymember{operator<=>}{shared_ptr}% +\begin{itemdecl} +template + strong_ordering operator<=>(const shared_ptr& a, const shared_ptr& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{compare_three_way()(a.get(), b.get())}. + +\pnum +\begin{note} +Defining a comparison operator function allows \tcode{shared_ptr} objects +to be used as keys in associative containers. +\end{note} +\end{itemdescr} + +\indexlibrarymember{operator<=>}{shared_ptr}% +\begin{itemdecl} +template + strong_ordering operator<=>(const shared_ptr& a, nullptr_t) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +compare_three_way()(a.get(), static_cast::element_type*>(nullptr). +\end{codeblock} +\end{itemdescr} + +\rSec4[util.smartptr.shared.spec]{Specialized algorithms} + +\indexlibrarymember{swap}{shared_ptr}% +\begin{itemdecl} +template + void swap(shared_ptr& a, shared_ptr& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{a.swap(b)}. +\end{itemdescr} + +\rSec4[util.smartptr.shared.cast]{Casts} + +\indexlibrarymember{static_pointer_cast}{shared_ptr}% +\begin{itemdecl} +template + shared_ptr static_pointer_cast(const shared_ptr& r) noexcept; +template + shared_ptr static_pointer_cast(shared_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{static_cast((U*)nullptr)} is well-formed. + +\pnum +\returns +\begin{codeblock} +shared_ptr(@\placeholder{R}@, static_cast::element_type*>(r.get())) +\end{codeblock} +where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and +\tcode{std::move(r)} for the second. + +\pnum +\begin{note} +The seemingly equivalent expression +\tcode{shared_ptr(static_cast(r.get()))} +will eventually result in undefined behavior, attempting to delete the +same object twice. +\end{note} +\end{itemdescr} + +\indexlibrarymember{dynamic_pointer_cast}{shared_ptr}% +\begin{itemdecl} +template + shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept; +template + shared_ptr dynamic_pointer_cast(shared_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{dynamic_cast((U*)nullptr)} is well-formed. +The expression \tcode{dynamic_cast::element_type*>(r.get())} is well-formed. + +\pnum +\expects +The expression \tcode{dynamic_cast::element_type*>(r.get())} has well-defined behavior. + +\pnum +\returns +\begin{itemize} +\item When \tcode{dynamic_cast::element_type*>(r.get())} + returns a non-null value \tcode{p}, + \tcode{shared_ptr(\placeholder{R}, p)}, + where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and + \tcode{std::move(r)} for the second. +\item Otherwise, \tcode{shared_ptr()}. +\end{itemize} + +\pnum +\begin{note} +The seemingly equivalent expression +\tcode{shared_ptr(dynamic_cast(r.get()))} will eventually result in +undefined behavior, attempting to delete the same object twice. +\end{note} +\end{itemdescr} + +\indexlibrarymember{const_pointer_cast}{shared_ptr}% +\begin{itemdecl} +template + shared_ptr const_pointer_cast(const shared_ptr& r) noexcept; +template + shared_ptr const_pointer_cast(shared_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{const_cast((U*)nullptr)} is well-formed. + +\pnum +\returns +\begin{codeblock} +shared_ptr(@\placeholder{R}@, const_cast::element_type*>(r.get())) +\end{codeblock} +where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and +\tcode{std::move(r)} for the second. + +\pnum +\begin{note} +The seemingly equivalent expression +\tcode{shared_ptr(const_cast(r.get()))} will eventually result in +undefined behavior, attempting to delete the same object twice. +\end{note} +\end{itemdescr} + +\indexlibrarymember{reinterpret_pointer_cast}{shared_ptr}% +\begin{itemdecl} +template + shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept; +template + shared_ptr reinterpret_pointer_cast(shared_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{reinterpret_cast((U*)nullptr)} is well-formed. + +\pnum +\returns +\begin{codeblock} +shared_ptr(@\placeholder{R}@, reinterpret_cast::element_type*>(r.get())) +\end{codeblock} +where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and +\tcode{std::move(r)} for the second. + +\pnum +\begin{note} +The seemingly equivalent expression +\tcode{shared_ptr(reinterpret_cast(r.get()))} will eventually result in +undefined behavior, attempting to delete the same object twice. +\end{note} +\end{itemdescr} + +\rSec4[util.smartptr.getdeleter]{\tcode{get_deleter}} + +\indexlibrarymember{get_deleter}{shared_ptr}% +\begin{itemdecl} +template + D* get_deleter(const shared_ptr& p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \tcode{p} owns a deleter \tcode{d} of type cv-unqualified +\tcode{D}, returns \tcode{addressof(d)}; otherwise returns \keyword{nullptr}. +The returned +pointer remains valid as long as there exists a \tcode{shared_ptr} instance +that owns \tcode{d}. +\begin{note} +It is unspecified whether the pointer +remains valid longer than that. This can happen if the implementation doesn't destroy +the deleter until all \tcode{weak_ptr} instances that share ownership with +\tcode{p} have been destroyed. +\end{note} +\end{itemdescr} + +\rSec4[util.smartptr.shared.io]{I/O} + +\indexlibrarymember{operator<<}{shared_ptr}% +\begin{itemdecl} +template + basic_ostream& operator<<(basic_ostream& os, const shared_ptr& p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +As if by: \tcode{os <{}< p.get();} + +\pnum +\returns +\tcode{os}. +\end{itemdescr} + +\rSec3[util.smartptr.weak]{Class template \tcode{weak_ptr}} + +\rSec4[util.smartptr.weak.general]{General} + +\pnum +\indexlibraryglobal{weak_ptr}% +The \tcode{weak_ptr} class template stores a weak reference to an object +that is already managed by a \tcode{shared_ptr}. To access the object, a +\tcode{weak_ptr} can be converted to a \tcode{shared_ptr} using the member +function \tcode{lock}. + +\begin{codeblock} +namespace std { + template class weak_ptr { + public: + using element_type = remove_extent_t; + + // \ref{util.smartptr.weak.const}, constructors + constexpr weak_ptr() noexcept; + template + weak_ptr(const shared_ptr& r) noexcept; + weak_ptr(const weak_ptr& r) noexcept; + template + weak_ptr(const weak_ptr& r) noexcept; + weak_ptr(weak_ptr&& r) noexcept; + template + weak_ptr(weak_ptr&& r) noexcept; + + // \ref{util.smartptr.weak.dest}, destructor + ~weak_ptr(); + + // \ref{util.smartptr.weak.assign}, assignment + weak_ptr& operator=(const weak_ptr& r) noexcept; + template + weak_ptr& operator=(const weak_ptr& r) noexcept; + template + weak_ptr& operator=(const shared_ptr& r) noexcept; + weak_ptr& operator=(weak_ptr&& r) noexcept; + template + weak_ptr& operator=(weak_ptr&& r) noexcept; + + // \ref{util.smartptr.weak.mod}, modifiers + void swap(weak_ptr& r) noexcept; + void reset() noexcept; + + // \ref{util.smartptr.weak.obs}, observers + long use_count() const noexcept; + bool expired() const noexcept; + shared_ptr lock() const noexcept; + template + bool owner_before(const shared_ptr& b) const noexcept; + template + bool owner_before(const weak_ptr& b) const noexcept; + }; + + template + weak_ptr(shared_ptr) -> weak_ptr; +} +\end{codeblock} + +\pnum +Specializations of \tcode{weak_ptr} shall be \oldconcept{CopyConstructible} and +\oldconcept{CopyAssignable}, allowing their use in standard +containers. The template parameter \tcode{T} of \tcode{weak_ptr} may be an +incomplete type. + +\rSec4[util.smartptr.weak.const]{Constructors} + +\indexlibraryctor{weak_ptr}% +\begin{itemdecl} +constexpr weak_ptr() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{weak_ptr} object that stores a null pointer value. + +\pnum +\ensures +\tcode{use_count() == 0}. +\end{itemdescr} + +\indexlibraryctor{weak_ptr}% +\begin{itemdecl} +weak_ptr(const weak_ptr& r) noexcept; +template weak_ptr(const weak_ptr& r) noexcept; +template weak_ptr(const shared_ptr& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the second and third constructors, \tcode{Y*} is compatible with \tcode{T*}. + +\pnum +\effects +If \tcode{r} is empty, constructs +an empty \tcode{weak_ptr} object that stores a null pointer value; +otherwise, constructs +a \tcode{weak_ptr} object that shares ownership +with \tcode{r} and stores a copy of the pointer stored in \tcode{r}. + +\pnum +\ensures +\tcode{use_count() == r.use_count()}. +\end{itemdescr} + +\indexlibraryctor{weak_ptr}% +\begin{itemdecl} +weak_ptr(weak_ptr&& r) noexcept; +template weak_ptr(weak_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the second constructor, \tcode{Y*} is compatible with \tcode{T*}. + +\pnum +\effects +Move constructs a \tcode{weak_ptr} instance from \tcode{r}. + +\pnum +\ensures +\tcode{*this} contains the old value of \tcode{r}. +\tcode{r} is empty, stores a null pointer value, and \tcode{r.use_count() == 0}. +\end{itemdescr} + +\rSec4[util.smartptr.weak.dest]{Destructor} + +\indexlibrarydtor{weak_ptr}% +\begin{itemdecl} +~weak_ptr(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Destroys this \tcode{weak_ptr} object but has no +effect on the object its stored pointer points to. +\end{itemdescr} + +\rSec4[util.smartptr.weak.assign]{Assignment} + +\indexlibrarymember{operator=}{weak_ptr}% +\begin{itemdecl} +weak_ptr& operator=(const weak_ptr& r) noexcept; +template weak_ptr& operator=(const weak_ptr& r) noexcept; +template weak_ptr& operator=(const shared_ptr& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{weak_ptr(r).swap(*this)}. + +\pnum +\returns +\tcode{*this}. + +\pnum +\remarks +The implementation may meet the effects (and the +implied guarantees) via different means, without creating a temporary object. +\end{itemdescr} + +\indexlibrarymember{operator=}{weak_ptr}% +\begin{itemdecl} +weak_ptr& operator=(weak_ptr&& r) noexcept; +template weak_ptr& operator=(weak_ptr&& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{weak_ptr(std::move(r)).swap(*this)}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\rSec4[util.smartptr.weak.mod]{Modifiers} +\indexlibrarymember{swap}{weak_ptr}% +\begin{itemdecl} +void swap(weak_ptr& r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Exchanges the contents of \tcode{*this} and \tcode{r}. +\end{itemdescr} + +\indexlibrarymember{reset}{weak_ptr}% +\begin{itemdecl} +void reset() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{weak_ptr().swap(*this)}. +\end{itemdescr} + +\rSec4[util.smartptr.weak.obs]{Observers} +\indexlibrarymember{use_count}{weak_ptr}% +\begin{itemdecl} +long use_count() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{0} if \tcode{*this} is empty; +otherwise, the number of \tcode{shared_ptr} instances +that share ownership with \tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{expired}{weak_ptr}% +\begin{itemdecl} +bool expired() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{use_count() == 0}. +\end{itemdescr} + +\indexlibrarymember{lock}{weak_ptr}% +\begin{itemdecl} +shared_ptr lock() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{expired() ?\ shared_ptr() :\ shared_ptr(*this)}, executed atomically. +\end{itemdescr} + +\indexlibrarymember{owner_before}{weak_ptr}% +\begin{itemdecl} +template bool owner_before(const shared_ptr& b) const noexcept; +template bool owner_before(const weak_ptr& b) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An unspecified value such that +\begin{itemize} +\item \tcode{x.owner_before(y)} defines a strict weak ordering as defined in~\ref{alg.sorting}; + +\item under the equivalence relation defined by \tcode{owner_before}, +\tcode{!a.owner_before(b) \&\& !b.owner_before(a)}, two \tcode{shared_ptr} or +\tcode{weak_ptr} instances are equivalent if and only if they share ownership or are +both empty. +\end{itemize} +\end{itemdescr} + + +\rSec4[util.smartptr.weak.spec]{Specialized algorithms} + +\indexlibrarymember{swap}{weak_ptr}% +\begin{itemdecl} +template + void swap(weak_ptr& a, weak_ptr& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{a.swap(b)}. +\end{itemdescr} + +\rSec3[util.smartptr.ownerless]{Class template \tcode{owner_less}} + +\pnum +The class template \tcode{owner_less} allows ownership-based mixed comparisons of shared +and weak pointers. + +\indexlibraryglobal{owner_less}% +\begin{codeblock} +namespace std { + template struct owner_less; + + template struct owner_less> { + bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; + bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; + }; + + template struct owner_less> { + bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; + bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; + }; + + template<> struct owner_less { + template + bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; + template + bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + template + bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; + template + bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; + + using is_transparent = @\unspec@; + }; +} +\end{codeblock} + +\indexlibrarymember{operator()}{owner_less}% +\pnum +\tcode{operator()(x, y)} returns \tcode{x.owner_before(y)}. +\begin{note} +Note that +\begin{itemize} +\item \tcode{operator()} defines a strict weak ordering as defined in~\ref{alg.sorting}; + +\item +two \tcode{shared_ptr} or \tcode{weak_ptr} instances are equivalent +under the equivalence relation defined by \tcode{operator()}, +\tcode{!operator()(a, b) \&\& !operator()(b, a)}, +if and only if they share ownership or are both empty. +\end{itemize} +\end{note} + +\rSec3[util.smartptr.enab]{Class template \tcode{enable_shared_from_this}} + +\pnum +\indexlibraryglobal{enable_shared_from_this}% +A class \tcode{T} can inherit from \tcode{enable_shared_from_this} +to inherit the \tcode{shared_from_this} member functions that obtain +a \tcode{shared_ptr} instance pointing to \tcode{*this}. + +\pnum +\begin{example} +\begin{codeblock} +struct X: public enable_shared_from_this { }; + +int main() { + shared_ptr p(new X); + shared_ptr q = p->shared_from_this(); + assert(p == q); + assert(!p.owner_before(q) && !q.owner_before(p)); // p and q share ownership +} +\end{codeblock} +\end{example} + +\begin{codeblock} +namespace std { + template class enable_shared_from_this { + protected: + constexpr enable_shared_from_this() noexcept; + enable_shared_from_this(const enable_shared_from_this&) noexcept; + enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; + ~enable_shared_from_this(); + + public: + shared_ptr shared_from_this(); + shared_ptr shared_from_this() const; + weak_ptr weak_from_this() noexcept; + weak_ptr weak_from_this() const noexcept; + + private: + mutable weak_ptr weak_this; // \expos + }; +} +\end{codeblock} + +\pnum +The template parameter \tcode{T} of \tcode{enable_shared_from_this} +may be an incomplete type. + +\indexlibraryctor{enable_shared_from_this}% +\begin{itemdecl} +constexpr enable_shared_from_this() noexcept; +enable_shared_from_this(const enable_shared_from_this&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Value-initializes \tcode{weak_this}. +\end{itemdescr} + +\indexlibrarymember{operator=}{enable_shared_from_this}% +\begin{itemdecl} +enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{*this}. + +\pnum +\begin{note} +\tcode{weak_this} is not changed. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{shared_ptr}% +\indexlibrarymember{shared_from_this}{enable_shared_from_this}% +\begin{itemdecl} +shared_ptr shared_from_this(); +shared_ptr shared_from_this() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{shared_ptr(weak_this)}. +\end{itemdescr} + +\indexlibraryglobal{weak_ptr}% +\indexlibrarymember{weak_from_this}{enable_shared_from_this}% +\begin{itemdecl} +weak_ptr weak_from_this() noexcept; +weak_ptr weak_from_this() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{weak_this}. +\end{itemdescr} + +\rSec2[util.smartptr.hash]{Smart pointer hash support} + +\indexlibrarymember{hash}{unique_ptr}% +\begin{itemdecl} +template struct hash>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Letting \tcode{UP} be \tcode{unique_ptr}, +the specialization \tcode{hash} is enabled\iref{unord.hash} +if and only if \tcode{hash} is enabled. +When enabled, for an object \tcode{p} of type \tcode{UP}, +\tcode{hash()(p)} evaluates to +the same value as \tcode{hash()(p.get())}. +The member functions are not guaranteed to be \keyword{noexcept}. +\end{itemdescr} + +\indexlibrarymember{hash}{shared_ptr}% +\begin{itemdecl} +template struct hash>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +For an object \tcode{p} of type \tcode{shared_ptr}, +\tcode{hash>()(p)} evaluates to +the same value as \tcode{hash::element_type*>()(p.get())}. +\end{itemdescr}% +\indextext{smart pointers|)} + +\rSec2[smartptr.adapt]{Smart pointer adaptors} + +\rSec3[out.ptr.t]{Class template \tcode{out_ptr_t}} + +\pnum +\tcode{out_ptr_t} is a class template used to adapt types +such as smart pointers\iref{smartptr} +for functions that use output pointer parameters. + +\pnum +\begin{example} +\begin{codeblock} +#include +#include + +int fopen_s(std::FILE** f, const char* name, const char* mode); + +struct fclose_deleter { + void operator()(std::FILE* f) const noexcept { + std::fclose(f); + } +}; + +int main(int, char*[]) { + constexpr const char* file_name = "ow.o"; + std::unique_ptr file_ptr; + int err = fopen_s(std::out_ptr(file_ptr), file_name, "r+b"); + if (err != 0) + return 1; + // \tcode{*file_ptr} is valid + return 0; +} +\end{codeblock} +\tcode{unique_ptr} can be used with \tcode{out_ptr} +to be passed into an output pointer-style function, +without needing to hold onto an intermediate pointer value and +manually delete it on error or failure. +\end{example} + +\indexlibraryglobal{out_ptr_t}% +\begin{codeblock} +namespace std { + template + class out_ptr_t { + public: + explicit out_ptr_t(Smart&, Args...); + out_ptr_t(const out_ptr_t&) = delete; + + ~out_ptr_t(); + + operator Pointer*() const noexcept; + operator void**() const noexcept; + + private: + Smart& s; // \expos + tuple a; // \expos + Pointer p; // \expos + }; +} +\end{codeblock} + +\pnum +\tcode{Pointer} shall meet the \oldconcept{NullablePointer} requirements. +If \tcode{Smart} is a specialization of \tcode{shared_ptr} and +\tcode{sizeof...(Args) == 0}, +the program is ill-formed. +\begin{note} +It is typically a user error to reset a \tcode{shared_ptr} +without specifying a deleter, +as \tcode{shared_ptr} will replace a custom deleter upon usage of \tcode{reset}, +as specified in \ref{util.smartptr.shared.mod}. +\end{note} + +\pnum +Program-defined specializations of \tcode{out_ptr_t} +that depend on at least one program-defined type +need not meet the requirements for the primary template. + +\pnum +Evaluations of the conversion functions +on the same object may conflict\iref{intro.races}. + +\indexlibraryctor{out_ptr_t}% +\begin{itemdecl} +explicit out_ptr_t(Smart& smart, Args... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{s} with \tcode{smart}, +\tcode{a} with \tcode{std::forward(args)...}, and +value-initializes \tcode{p}. + +\pnum +\begin{note} +The constructor is not \tcode{noexcept} +to allow for a variety of non-terminating and safe implementation strategies. +For example, an implementation can allocate +a \tcode{shared_ptr}'s internal node in the constructor and +let implementation-defined exceptions escape safely. +The destructor can then move the allocated control block in directly and +avoid any other exceptions. +\end{note} +\end{itemdescr} + +\indexlibrarydtor{out_ptr_t}% +\begin{itemdecl} +~out_ptr_t(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{SP} be +\tcode{\exposid{POINTER_OF_OR}(Smart, Pointer)}\iref{memory.general}. + +\pnum +\effects +Equivalent to: +\begin{itemize} +\item +% pretend to \item that there is real text here, but undo the vertical spacing +\mbox{}\vspace{-\baselineskip}\vspace{-\parskip} +\begin{codeblock} +if (p) { + apply([&](auto&&... args) { + s.reset(static_cast(p), std::forward(args)...); }, std::move(a)); +} +\end{codeblock} +if the expression +\tcode{s.reset(static_cast(p), std::forward(args)...)} +is well-\linebreak formed; +\item +otherwise, +\begin{codeblock} +if (p) { + apply([&](auto&&... args) { + s = Smart(static_cast(p), std::forward(args)...); }, std::move(a)); +} +\end{codeblock} +if \tcode{is_constructible_v} is \tcode{true}; +\item +otherwise, the program is ill-formed. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +operator Pointer*() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{operator void**()} has not been called on \tcode{*this}. + +\pnum +\returns +\tcode{addressof(const_cast(p))}. +\end{itemdescr} + +\begin{itemdecl} +operator void**() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_same_v} is \tcode{false}. + +\pnum +\mandates +\tcode{is_pointer_v} is \tcode{true}. + +\pnum +\expects +\tcode{operator Pointer*()} has not been called on \tcode{*this}. + +\pnum +\returns +A pointer value \tcode{v} such that: +\begin{itemize} +\item +the initial value \tcode{*v} is equivalent to \tcode{static_cast(p)} and +\item +any modification of \tcode{*v} +that is not followed by a subsequent modification of \tcode{*this} +affects the value of \tcode{p} during the destruction of \tcode{*this}, +such that \tcode{static_cast(p) == *v}. +\end{itemize} + +\pnum +\remarks +Accessing \tcode{*v} outside the lifetime of \tcode{*this} +has undefined behavior. + +\pnum +\begin{note} +\tcode{reinterpret_cast(static_cast(*this))} +can be a viable implementation strategy for some implementations. +\end{note} +\end{itemdescr} + +\rSec3[out.ptr]{Function template \tcode{out_ptr}} + +\indexlibraryglobal{out_ptr}% +\begin{itemdecl} +template + auto out_ptr(Smart& s, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{P} be \tcode{Pointer} +if \tcode{is_void_v} is \tcode{false}, +otherwise \tcode{\exposid{POINTER_OF}(Smart)}. + +\pnum +\returns +\tcode{out_ptr_t(s, std::forward(args)...)} +\end{itemdescr} + +\rSec3[inout.ptr.t]{Class template \tcode{inout_ptr_t}} + +\pnum +\tcode{inout_ptr_t} is a class template used to adapt types +such as smart pointers\iref{smartptr} +for functions that use output pointer parameters +whose dereferenced values may first be deleted +before being set to another allocated value. + +\pnum +\begin{example} +\begin{codeblock} +#include + +struct star_fish* star_fish_alloc(); +int star_fish_populate(struct star_fish** ps, const char* description); + +struct star_fish_deleter { + void operator() (struct star_fish* c) const noexcept; +}; + +using star_fish_ptr = std::unique_ptr; + +int main(int, char*[]) { + star_fish_ptr peach(star_fish_alloc()); + // ... + // used, need to re-make + int err = star_fish_populate(std::inout_ptr(peach), "caring clown-fish liker"); + return err; +} +\end{codeblock} +A \tcode{unique_ptr} can be used with \tcode{inout_ptr} +to be passed into an output pointer-style function. +The original value will be properly deleted +according to the function it is used with and +a new value reset in its place. +\end{example} + +\indexlibraryglobal{inout_ptr_t}% +\begin{codeblock} +namespace std { + template + class inout_ptr_t { + public: + explicit inout_ptr_t(Smart&, Args...); + inout_ptr_t(const inout_ptr_t&) = delete; + + ~inout_ptr_t(); + + operator Pointer*() const noexcept; + operator void**() const noexcept; + + private: + Smart& s; // \expos + tuple a; // \expos + Pointer p; // \expos + }; +} +\end{codeblock} + +\pnum +\tcode{Pointer} shall meet the \oldconcept{NullablePointer} requirements. +If \tcode{Smart} is a specialization of \tcode{shared_ptr}, +the program is ill-formed. +\begin{note} +It is impossible to properly acquire unique ownership of the managed resource +from a \tcode{shared_ptr} given its shared ownership model. +\end{note} + +\pnum +Program-defined specializations of \tcode{inout_ptr_t} +that depend on at least one program-defined type +need not meet the requirements for the primary template. + +\pnum +Evaluations of the conversion functions on the same object +may conflict\iref{intro.races}. + +\indexlibraryctor{inout_ptr_t}% +\begin{itemdecl} +explicit inout_ptr_t(Smart& smart, Args... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{s} with \tcode{smart}, +\tcode{a} with \tcode{std::forward(args)...}, and +\tcode{p} to either +\begin{itemize} +\item \tcode{smart} if \tcode{is_pointer_v} is \tcode{true}, +\item otherwise, \tcode{smart.get()}. +\end{itemize} + +\pnum +\remarks +An implementation can call \tcode{s.release()}. + +\pnum +\begin{note} +The constructor is not \tcode{noexcept} +to allow for a variety of non-terminating and safe implementation strategies. +For example, an intrusive pointer implementation with a control block +can allocate in the constructor and safely fail with an exception. +\end{note} +\end{itemdescr} + +\indexlibrarydtor{inout_ptr_t}% +\begin{itemdecl} +~inout_ptr_t(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{SP} be +\tcode{\exposid{POINTER_OF_OR}(Smart, Pointer)}\iref{memory.general}. + +\pnum +Let \exposid{release-statement} be \tcode{s.release();} +if an implementation does not call \tcode{s.release()} in the constructor. +Otherwise, it is empty. + +\pnum +\effects +Equivalent to: +\begin{itemize} +\item +% pretend to \item that there is real text here, but undo the vertical spacing +\mbox{}\vspace{-\baselineskip}\vspace{-\parskip} +\begin{codeblock} +if (p) { + apply([&](auto&&... args) { + s = Smart( static_cast(p), std::forward(args)...); }, std::move(a)); +} +\end{codeblock} +if \tcode{is_pointer_v} is \tcode{true}; +\item +otherwise, +\begin{codeblock} +if (p) { + apply([&](auto&&... args) { + @\exposid{release-statement}@; + s.reset(static_cast(p), std::forward(args)...); }, std::move(a)); +} +\end{codeblock} +if the expression +\tcode{s.reset(static_cast(p), std::forward(args)...)} +is well-\newline formed; +\item +otherwise, +\begin{codeblock} +if (p) { + apply([&](auto&&... args) { + @\exposid{release-statement}@; + s = Smart(static_cast(p), std::forward(args)...); }, std::move(a)); +} +\end{codeblock} +if \tcode{is_constructible_v} is \tcode{true}; +\item +otherwise, the program is ill-formed. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +operator Pointer*() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{operator void**()} has not been called on \tcode{*this}. + +\pnum +\returns +\tcode{addressof(const_cast(p))}. +\end{itemdescr} + +\begin{itemdecl} +operator void**() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_same_v} is \tcode{false}. + +\pnum +\mandates +\tcode{is_pointer_v} is \tcode{true}. + +\pnum +\expects +\tcode{operator Pointer*()} has not been called on \tcode{*this}. + +\pnum +\returns +A pointer value \tcode{v} such that: +\begin{itemize} +\item +the initial value \tcode{*v} is equivalent to \tcode{static_cast(p)} and +\item +any modification of \tcode{*v} +that is not followed by subsequent modification of \tcode{*this} +affects the value of \tcode{p} during the destruction of \tcode{*this}, +such that \tcode{static_cast(p) == *v}. +\end{itemize} + +\pnum +\remarks +Accessing \tcode{*v} outside the lifetime of \tcode{*this} +has undefined behavior. + +\pnum +\begin{note} +\tcode{reinterpret_cast(static_cast(*this))} +can be a viable implementation strategy for some implementations. +\end{note} +\end{itemdescr} + +\rSec3[inout.ptr]{Function template \tcode{inout_ptr}} + +\indexlibraryglobal{inout_ptr}% +\begin{itemdecl} +template + auto inout_ptr(Smart& s, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{P} be \tcode{Pointer} if \tcode{is_void_v} is \tcode{false}, +otherwise \tcode{\exposid{POINTER_OF}(Smart)}. + +\pnum +\returns +\tcode{inout_ptr_t(s, std::forward(args)...)}. +\end{itemdescr} + +\rSec1[mem.res]{Memory resources} + +\rSec2[mem.res.syn]{Header \tcode{} synopsis} + +\indexheader{memory_resource}% +\begin{codeblock} +namespace std::pmr { + // \ref{mem.res.class}, class \tcode{memory_resource} + class memory_resource; + + bool operator==(const memory_resource& a, const memory_resource& b) noexcept; + + // \ref{mem.poly.allocator.class}, class template \tcode{polymorphic_allocator} + template class polymorphic_allocator; + + template + bool operator==(const polymorphic_allocator& a, + const polymorphic_allocator& b) noexcept; + + // \ref{mem.res.global}, global memory resources + memory_resource* new_delete_resource() noexcept; + memory_resource* null_memory_resource() noexcept; + memory_resource* set_default_resource(memory_resource* r) noexcept; + memory_resource* get_default_resource() noexcept; + + // \ref{mem.res.pool}, pool resource classes + struct pool_options; + class synchronized_pool_resource; + class unsynchronized_pool_resource; + class monotonic_buffer_resource; +} +\end{codeblock} + +\rSec2[mem.res.class]{Class \tcode{memory_resource}} + +\rSec3[mem.res.class.general]{General} + +\pnum +The \tcode{memory_resource} class is an abstract interface to an unbounded set of classes encapsulating memory resources. + +\indexlibraryglobal{memory_resource}% +\indexlibrarymember{operator=}{memory_resource}% +\begin{codeblock} +namespace std::pmr { + class memory_resource { + static constexpr size_t max_align = alignof(max_align_t); // \expos + + public: + memory_resource() = default; + memory_resource(const memory_resource&) = default; + virtual ~memory_resource(); + + memory_resource& operator=(const memory_resource&) = default; + + [[nodiscard]] void* allocate(size_t bytes, size_t alignment = max_align); + void deallocate(void* p, size_t bytes, size_t alignment = max_align); + + bool is_equal(const memory_resource& other) const noexcept; + + private: + virtual void* do_allocate(size_t bytes, size_t alignment) = 0; + virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0; + + virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; + }; +} +\end{codeblock} + + +\rSec3[mem.res.public]{Public member functions} + +\indexlibrarydtor{memory_resource}% +\begin{itemdecl} +~memory_resource(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Destroys this \tcode{memory_resource}. +\end{itemdescr} + +\indexlibrarymember{allocate}{memory_resource}% +\begin{itemdecl} +[[nodiscard]] void* allocate(size_t bytes, size_t alignment = max_align); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Allocates storage by calling \tcode{do_allocate(bytes, alignment)} and +implicitly creates objects within the allocated region of storage. + +\pnum +\returns +A pointer to a suitable created object\iref{intro.object} +in the allocated region of storage. + +\pnum +\throws +What and when the call to \tcode{do_allocate} throws. +\end{itemdescr} + +\indexlibrarymember{deallocate}{memory_resource}% +\begin{itemdecl} +void deallocate(void* p, size_t bytes, size_t alignment = max_align); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{do_deallocate(p, bytes, alignment)}. +\end{itemdescr} + +\indexlibrarymember{is_equal}{memory_resource}% +\begin{itemdecl} +bool is_equal(const memory_resource& other) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return do_is_equal(other);} +\end{itemdescr} + + +\rSec3[mem.res.private]{Private virtual member functions} + +\indexlibrarymember{do_allocate}{memory_resource}% +\begin{itemdecl} +virtual void* do_allocate(size_t bytes, size_t alignment) = 0; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{alignment} is a power of two. + +\pnum +\returns +A derived class shall implement this function to +return a pointer to allocated storage\iref{basic.stc.dynamic.allocation} +with a size of at least \tcode{bytes}, +aligned to the specified \tcode{alignment}. + +\pnum +\throws +A derived class implementation shall throw an appropriate exception if it is unable to allocate memory with the requested size and alignment. +\end{itemdescr} + +\indexlibrarymember{do_deallocate}{memory_resource}% +\begin{itemdecl} +virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{p} was returned from a prior call to \tcode{allocate(bytes, alignment)} +on a memory resource equal to \tcode{*this}, +and the storage at \tcode{p} has not yet been deallocated. + +\pnum +\effects +A derived class shall implement this function to dispose of allocated storage. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibrarymember{do_is_equal}{memory_resource}% +\begin{itemdecl} +virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A derived class shall implement this function to return \tcode{true} if memory allocated from \keyword{this} can be deallocated from \tcode{other} and vice-versa, +otherwise \tcode{false}. +\begin{note} +It is possible that the most-derived type of \tcode{other} does not match the type of \keyword{this}. +For a derived class \tcode{D}, an implementation of this function +can immediately return \tcode{false} +if \tcode{dynamic_cast(\&other) == nullptr}. +\end{note} +\end{itemdescr} + +\rSec3[mem.res.eq]{Equality} + +\indexlibrarymember{operator==}{memory_resource}% +\begin{itemdecl} +bool operator==(const memory_resource& a, const memory_resource& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\&a == \&b || a.is_equal(b)}. +\end{itemdescr} + +\rSec2[mem.poly.allocator.class]{Class template \tcode{polymorphic_allocator}} + +\rSec3[mem.poly.allocator.class.general]{General} + +\pnum +A specialization of class template \tcode{pmr::polymorphic_allocator} +meets the \oldconcept{Allocator} requirements (\tref{cpp17.allocator}). +Constructed with different memory resources, +different instances of the same specialization of \tcode{pmr::polymorphic_allocator} +can exhibit entirely different allocation behavior. +This runtime polymorphism allows objects that use \tcode{polymorphic_allocator} +to behave as if they used different allocator types at run time +even though they use the same static allocator type. + +\pnum +All specializations of class template \tcode{pmr::polymorphic_allocator} +meet the allocator completeness requirements\iref{allocator.requirements.completeness}. + +\indexlibraryglobal{polymorphic_allocator}% +\indexlibrarymember{value_type}{polymorphic_allocator}% +\begin{codeblock} +namespace std::pmr { + template class polymorphic_allocator { + memory_resource* memory_rsrc; // \expos + + public: + using value_type = Tp; + + // \ref{mem.poly.allocator.ctor}, constructors + polymorphic_allocator() noexcept; + polymorphic_allocator(memory_resource* r); + + polymorphic_allocator(const polymorphic_allocator& other) = default; + + template + polymorphic_allocator(const polymorphic_allocator& other) noexcept; + + polymorphic_allocator& operator=(const polymorphic_allocator&) = delete; + + // \ref{mem.poly.allocator.mem}, member functions + [[nodiscard]] Tp* allocate(size_t n); + void deallocate(Tp* p, size_t n); + + [[nodiscard]] void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t)); + void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t)); + template [[nodiscard]] T* allocate_object(size_t n = 1); + template void deallocate_object(T* p, size_t n = 1); + template [[nodiscard]] T* new_object(CtorArgs&&... ctor_args); + template void delete_object(T* p); + + template + void construct(T* p, Args&&... args); + + polymorphic_allocator select_on_container_copy_construction() const; + + memory_resource* resource() const; + }; +} +\end{codeblock} + +\rSec3[mem.poly.allocator.ctor]{Constructors} + +\indexlibraryctor{polymorphic_allocator}% +\begin{itemdecl} +polymorphic_allocator() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Sets \tcode{memory_rsrc} to \tcode{get_default_resource()}. +\end{itemdescr} + +\indexlibraryctor{polymorphic_allocator}% +\begin{itemdecl} +polymorphic_allocator(memory_resource* r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{r} is non-null. + +\pnum +\effects +Sets \tcode{memory_rsrc} to \tcode{r}. + +\pnum +\throws +Nothing. + +\pnum +\begin{note} +This constructor provides an implicit conversion from \tcode{memory_resource*}. +\end{note} +\end{itemdescr} + +\indexlibraryctor{polymorphic_allocator}% +\begin{itemdecl} +template polymorphic_allocator(const polymorphic_allocator& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Sets \tcode{memory_rsrc} to \tcode{other.resource()}. +\end{itemdescr} + + +\rSec3[mem.poly.allocator.mem]{Member functions} + +\indexlibrarymember{allocate}{polymorphic_allocator}% +\begin{itemdecl} +[[nodiscard]] Tp* allocate(size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{numeric_limits::max() / sizeof(Tp) < n}, +throws \tcode{bad_array_new_length}. +Otherwise equivalent to: +\begin{codeblock} +return static_cast(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp))); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{deallocate}{polymorphic_allocator}% +\begin{itemdecl} +void deallocate(Tp* p, size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{p} was allocated from a memory resource \tcode{x}, +equal to \tcode{*memory_rsrc}, +using \tcode{x.allocate(n * sizeof(Tp), alignof(Tp))}. + +\pnum +\effects +Equivalent to \tcode{memory_rsrc->deallocate(p, n * sizeof(Tp), alignof(Tp))}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibrarymember{allocate_bytes}{polymorphic_allocator}% +\begin{itemdecl} +[[nodiscard]] void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return memory_rsrc->allocate(nbytes, alignment);} + +\pnum +\begin{note} +The return type is \tcode{void*} (rather than, e.g., \tcode{byte*}) +to support conversion to an arbitrary pointer type \tcode{U*} +by \tcode{static_cast}, thus facilitating construction of a \tcode{U} +object in the allocated memory. +\end{note} +\end{itemdescr} + +\indexlibrarymember{deallocate_bytes}{polymorphic_allocator}% +\begin{itemdecl} +void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{memory_rsrc->deallocate(p, nbytes, alignment)}. +\end{itemdescr} + +\indexlibrarymember{allocate_object}{polymorphic_allocator}% +\begin{itemdecl} +template + [[nodiscard]] T* allocate_object(size_t n = 1); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Allocates memory suitable for holding +an array of \tcode{n} objects of type \tcode{T}, as follows: +\begin{itemize} +\item + if \tcode{numeric_limits::max() / sizeof(T) < n}, + throws \tcode{bad_array_new_length}, +\item + otherwise equivalent to: +\begin{codeblock} +return static_cast(allocate_bytes(n*sizeof(T), alignof(T))); +\end{codeblock} +\end{itemize} + +\pnum +\begin{note} +\tcode{T} is not deduced and must therefore be provided as a template argument. +\end{note} +\end{itemdescr} + +\indexlibrarymember{deallocate_object}{polymorphic_allocator}% +\begin{itemdecl} +template + void deallocate_object(T* p, size_t n = 1); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{deallocate_bytes(p, n*sizeof(T), alignof(T))}. +\end{itemdescr} + +\indexlibrarymember{new_object}{polymorphic_allocator}% +\begin{itemdecl} +template + [[nodiscard]] T* new_object(CtorArgs&&... ctor_args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Allocates and constructs an object of type \tcode{T}, as follows.\newline +Equivalent to: +\begin{codeblock} +T* p = allocate_object(); +try { + construct(p, std::forward(ctor_args)...); +} catch (...) { + deallocate_object(p); + throw; +} +return p; +\end{codeblock} + +\pnum +\begin{note} +\tcode{T} is not deduced and must therefore be provided as a template argument. +\end{note} +\end{itemdescr} + +\indexlibrarymember{new_object}{polymorphic_allocator}% +\begin{itemdecl} +template + void delete_object(T* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +allocator_traits::destroy(*this, p); +deallocate_object(p); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{construct}{polymorphic_allocator}% +\begin{itemdecl} +template + void construct(T* p, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +Uses-allocator construction of \tcode{T} +with allocator \tcode{*this} (see~\ref{allocator.uses.construction}) +and constructor arguments \tcode{std::forward(args)...} is well-formed. + +\pnum +\effects +Construct a \tcode{T} object in the storage +whose address is represented by \tcode{p} +by uses-allocator construction with allocator \tcode{*this} +and constructor arguments \tcode{std::forward(args)...}. + +\pnum +\throws +Nothing unless the constructor for \tcode{T} throws. +\end{itemdescr} + +\indexlibrarymember{select_on_container_copy_construction}{polymorphic_allocator}% +\begin{itemdecl} +polymorphic_allocator select_on_container_copy_construction() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{polymorphic_allocator()}. + +\pnum +\begin{note} +The memory resource is not propagated. +\end{note} +\end{itemdescr} + +\indexlibrarymember{resource}{polymorphic_allocator}% +\begin{itemdecl} +memory_resource* resource() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{memory_rsrc}. +\end{itemdescr} + +\rSec3[mem.poly.allocator.eq]{Equality} + +\indexlibrarymember{operator==}{polymorphic_allocator}% +\begin{itemdecl} +template + bool operator==(const polymorphic_allocator& a, + const polymorphic_allocator& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{*a.resource() == *b.resource()}. +\end{itemdescr} + +\rSec2[mem.res.global]{Access to program-wide \tcode{memory_resource} objects} + +\indexlibraryglobal{new_delete_resource}% +\begin{itemdecl} +memory_resource* new_delete_resource() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A pointer to a static-duration object of a type derived from \tcode{memory_resource} +that can serve as a resource for allocating memory +using \tcode{::operator new} and \tcode{::operator delete}. +The same value is returned every time this function is called. +For a return value \tcode{p} and a memory resource \tcode{r}, +\tcode{p->is_equal(r)} returns \tcode{\&r == p}. +\end{itemdescr} + +\indexlibraryglobal{null_memory_resource}% +\begin{itemdecl} +memory_resource* null_memory_resource() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A pointer to a static-duration object of a type derived from \tcode{memory_resource} +for which \tcode{allocate()} always throws \tcode{bad_alloc} and +for which \tcode{deallocate()} has no effect. +The same value is returned every time this function is called. +For a return value \tcode{p} and a memory resource \tcode{r}, +\tcode{p->is_equal(r)} returns \tcode{\&r == p}. +\end{itemdescr} + +\pnum +The \defn{default memory resource pointer} is a pointer to a memory resource +that is used by certain facilities when an explicit memory resource +is not supplied through the interface. +Its initial value is the return value of \tcode{new_delete_resource()}. + +\indexlibraryglobal{set_default_resource}% +\begin{itemdecl} +memory_resource* set_default_resource(memory_resource* r) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{r} is non-null, +sets the value of the default memory resource pointer to \tcode{r}, +otherwise sets the default memory resource pointer to \tcode{new_delete_resource()}. + +\pnum +\returns +The previous value of the default memory resource pointer. + +\pnum +\remarks +Calling the \tcode{set_default_resource} and +\tcode{get_default_resource} functions shall not incur a data race. +A call to the \tcode{set_default_resource} function +shall synchronize with subsequent calls to +the \tcode{set_default_resource} and \tcode{get_default_resource} functions. +\end{itemdescr} + +\indexlibraryglobal{get_default_resource}% +\begin{itemdecl} +memory_resource* get_default_resource() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The current value of the default memory resource pointer. +\end{itemdescr} + +\rSec2[mem.res.pool]{Pool resource classes} + +\rSec3[mem.res.pool.overview]{Classes \tcode{synchronized_pool_resource} and \tcode{unsynchronized_pool_resource}} + +\pnum +The \tcode{synchronized_pool_resource} and +\tcode{unsynchronized_pool_resource} classes +(collectively called \defn{pool resource classes}) +are general-purpose memory resources having the following qualities: +\begin{itemize} +\item +Each resource frees its allocated memory on destruction, +even if \tcode{deallocate} has not been called for some of the allocated blocks. +\item +A pool resource consists of a collection of \defn{pools}, +serving requests for different block sizes. +Each individual pool manages a collection of \defn{chunks} +that are in turn divided into blocks of uniform size, +returned via calls to \tcode{do_allocate}. +Each call to \tcode{do_allocate(size, alignment)} is dispatched +to the pool serving the smallest blocks accommodating at least \tcode{size} bytes. +\item +When a particular pool is exhausted, +allocating a block from that pool results in the allocation +of an additional chunk of memory from the \defn{upstream allocator} +(supplied at construction), thus replenishing the pool. +With each successive replenishment, +the chunk size obtained increases geometrically. +\begin{note} +By allocating memory in chunks, +the pooling strategy increases the chance that consecutive allocations +will be close together in memory. +\end{note} +\item +Allocation requests that exceed the largest block size of any pool +are fulfilled directly from the upstream allocator. +\item +A \tcode{pool_options} struct may be passed to the pool resource constructors +to tune the largest block size and the maximum chunk size. +\end{itemize} + +\pnum +A \tcode{synchronized_pool_resource} may be accessed from multiple threads +without external synchronization +and may have thread-specific pools to reduce synchronization costs. +An \tcode{unsynchronized_pool_resource} class may not be accessed +from multiple threads simultaneously +and thus avoids the cost of synchronization entirely +in single-threaded applications. + +\indexlibraryglobal{pool_options}% +\indexlibraryglobal{synchronized_pool_resource}% +\indexlibraryglobal{unsynchronized_pool_resource}% +\begin{codeblock} +namespace std::pmr { + struct pool_options { + size_t max_blocks_per_chunk = 0; + size_t largest_required_pool_block = 0; + }; + + class synchronized_pool_resource : public memory_resource { + public: + synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); + + synchronized_pool_resource() + : synchronized_pool_resource(pool_options(), get_default_resource()) {} + explicit synchronized_pool_resource(memory_resource* upstream) + : synchronized_pool_resource(pool_options(), upstream) {} + explicit synchronized_pool_resource(const pool_options& opts) + : synchronized_pool_resource(opts, get_default_resource()) {} + + synchronized_pool_resource(const synchronized_pool_resource&) = delete; + virtual ~synchronized_pool_resource(); + + synchronized_pool_resource& operator=(const synchronized_pool_resource&) = delete; + + void release(); + memory_resource* upstream_resource() const; + pool_options options() const; + + protected: + void* do_allocate(size_t bytes, size_t alignment) override; + void do_deallocate(void* p, size_t bytes, size_t alignment) override; + + bool do_is_equal(const memory_resource& other) const noexcept override; + }; + + class unsynchronized_pool_resource : public memory_resource { + public: + unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream); + + unsynchronized_pool_resource() + : unsynchronized_pool_resource(pool_options(), get_default_resource()) {} + explicit unsynchronized_pool_resource(memory_resource* upstream) + : unsynchronized_pool_resource(pool_options(), upstream) {} + explicit unsynchronized_pool_resource(const pool_options& opts) + : unsynchronized_pool_resource(opts, get_default_resource()) {} + + unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete; + virtual ~unsynchronized_pool_resource(); + + unsynchronized_pool_resource& operator=(const unsynchronized_pool_resource&) = delete; + + void release(); + memory_resource* upstream_resource() const; + pool_options options() const; + + protected: + void* do_allocate(size_t bytes, size_t alignment) override; + void do_deallocate(void* p, size_t bytes, size_t alignment) override; + + bool do_is_equal(const memory_resource& other) const noexcept override; + }; +} +\end{codeblock} + +\rSec3[mem.res.pool.options]{\tcode{pool_options} data members} + +\pnum +The members of \tcode{pool_options} +comprise a set of constructor options for pool resources. +The effect of each option on the pool resource behavior is described below: + +\indexlibrarymember{pool_options}{max_blocks_per_chunk}% +\begin{itemdecl} +size_t max_blocks_per_chunk; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The maximum number of blocks that will be allocated at once +from the upstream memory resource\iref{mem.res.monotonic.buffer} +to replenish a pool. +If the value of \tcode{max_blocks_per_chunk} is zero or +is greater than an \impldef{largest supported value to configure the maximum number of blocks to replenish a pool} +limit, that limit is used instead. +The implementation +may choose to use a smaller value than is specified in this field and +may use different values for different pools. +\end{itemdescr} + +\indexlibrarymember{pool_options}{largest_required_pool_block}% +\begin{itemdecl} +size_t largest_required_pool_block; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The largest allocation size that is required to be fulfilled +using the pooling mechanism. +Attempts to allocate a single block larger than this threshold +will be allocated directly from the upstream memory resource. +If \tcode{largest_required_pool_block} is zero or +is greater than an \impldef{largest supported value to configure the largest allocation satisfied directly by a pool} +limit, that limit is used instead. +The implementation may choose a pass-through threshold +larger than specified in this field. +\end{itemdescr} + +\rSec3[mem.res.pool.ctor]{Constructors and destructors} + +\indexlibraryctor{synchronized_pool_resource}% +\indexlibraryctor{unsynchronized_pool_resource}% +\begin{itemdecl} +synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); +unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{upstream} is the address of a valid memory resource. + +\pnum +\effects +Constructs a pool resource object that will obtain memory from \tcode{upstream} +whenever the pool resource is unable to satisfy a memory request +from its own internal data structures. +The resulting object will hold a copy of \tcode{upstream}, +but will not own the resource to which \tcode{upstream} points. +\begin{note} +The intention is that calls to \tcode{upstream->allocate()} +will be substantially fewer than calls to \tcode{this->allocate()} +in most cases. +\end{note} +The behavior of the pooling mechanism is tuned +according to the value of the \tcode{opts} argument. + +\pnum +\throws +Nothing unless \tcode{upstream->allocate()} throws. +It is unspecified if, or under what conditions, +this constructor calls \tcode{upstream->allocate()}. +\end{itemdescr} + +\indexlibrarydtor{synchronized_pool_resource}% +\indexlibrarydtor{unsynchronized_pool_resource}% +\begin{itemdecl} +virtual ~synchronized_pool_resource(); +virtual ~unsynchronized_pool_resource(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{release()}. +\end{itemdescr} + +\rSec3[mem.res.pool.mem]{Members} + +\indexlibrarymember{release}{synchronized_pool_resource}% +\indexlibrarymember{release}{unsynchronized_pool_resource}% +\begin{itemdecl} +void release(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{upstream_resource()->deallocate()} as necessary +to release all allocated memory. +\begin{note} +The memory is released back to \tcode{upstream_resource()} +even if \tcode{deallocate} has not been called +for some of the allocated blocks. +\end{note} +\end{itemdescr} + +\indexlibrarymember{upstream_resource}{synchronized_pool_resource}% +\indexlibrarymember{upstream_resource}{unsynchronized_pool_resource}% +\begin{itemdecl} +memory_resource* upstream_resource() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The value of the \tcode{upstream} argument +provided to the constructor of this object. +\end{itemdescr} + +\indexlibrarymember{options}{synchronized_pool_resource}% +\indexlibrarymember{options}{unsynchronized_pool_resource}% +\begin{itemdecl} +pool_options options() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The options that control the pooling behavior of this resource. +The values in the returned struct may differ +from those supplied to the pool resource constructor in that +values of zero will be replaced with \impldef{default configuration of a pool} +defaults, and sizes may be rounded to unspecified granularity. +\end{itemdescr} + +\indexlibrarymember{do_allocate}{synchronized_pool_resource}% +\indexlibrarymember{do_allocate}{unsynchronized_pool_resource}% +\begin{itemdecl} +void* do_allocate(size_t bytes, size_t alignment) override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If the pool selected for a block of size \tcode{bytes} +is unable to satisfy the memory request from its own internal data structures, +it will call \tcode{upstream_resource()->allocate()} to obtain more memory. +If \tcode{bytes} is larger than that which the largest pool can handle, +then memory will be allocated using \tcode{upstream_resource()->allocate()}. + +\pnum +\returns +A pointer to allocated storage\iref{basic.stc.dynamic.allocation} +with a size of at least \tcode{bytes}. +The size and alignment of the allocated memory shall meet the requirements +for a class derived from \tcode{memory_resource}\iref{mem.res.class}. + +\pnum +\throws +Nothing unless \tcode{upstream_resource()->allocate()} throws. +\end{itemdescr} + +\indexlibrarymember{do_deallocate}{synchronized_pool_resource}% +\indexlibrarymember{do_deallocate}{unsynchronized_pool_resource}% +\begin{itemdecl} +void do_deallocate(void* p, size_t bytes, size_t alignment) override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Returns the memory at \tcode{p} to the pool. +It is unspecified if, or under what circumstances, +this operation will result in a call to \tcode{upstream_resource()->deallocate()}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibrarymember{do_is_equal}{synchronized_pool_resource}% +\indexlibrarymember{do_is_equal}{unsynchronized_pool_resource}% +\begin{itemdecl} +bool do_is_equal(const memory_resource& other) const noexcept override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{this == \&other}. +\end{itemdescr} + +\rSec2[mem.res.monotonic.buffer]{Class \tcode{monotonic_buffer_resource}} + +\rSec3[mem.res.monotonic.buffer.general]{General} + +\pnum +A \tcode{monotonic_buffer_resource} is a special-purpose memory resource +intended for very fast memory allocations in situations +where memory is used to build up a few objects +and then is released all at once when the memory resource object is destroyed. + +\indexlibraryglobal{monotonic_buffer_resource}% +\begin{codeblock} +namespace std::pmr { + class monotonic_buffer_resource : public memory_resource { + memory_resource* upstream_rsrc; // \expos + void* current_buffer; // \expos + size_t next_buffer_size; // \expos + + public: + explicit monotonic_buffer_resource(memory_resource* upstream); + monotonic_buffer_resource(size_t initial_size, memory_resource* upstream); + monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream); + + monotonic_buffer_resource() + : monotonic_buffer_resource(get_default_resource()) {} + explicit monotonic_buffer_resource(size_t initial_size) + : monotonic_buffer_resource(initial_size, get_default_resource()) {} + monotonic_buffer_resource(void* buffer, size_t buffer_size) + : monotonic_buffer_resource(buffer, buffer_size, get_default_resource()) {} + + monotonic_buffer_resource(const monotonic_buffer_resource&) = delete; + + virtual ~monotonic_buffer_resource(); + + monotonic_buffer_resource& operator=(const monotonic_buffer_resource&) = delete; + + void release(); + memory_resource* upstream_resource() const; + + protected: + void* do_allocate(size_t bytes, size_t alignment) override; + void do_deallocate(void* p, size_t bytes, size_t alignment) override; + + bool do_is_equal(const memory_resource& other) const noexcept override; + }; +} +\end{codeblock} + +\rSec3[mem.res.monotonic.buffer.ctor]{Constructors and destructor} + +\indexlibraryctor{monotonic_buffer_resource}% +\begin{itemdecl} +explicit monotonic_buffer_resource(memory_resource* upstream); +monotonic_buffer_resource(size_t initial_size, memory_resource* upstream); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{upstream} is the address of a valid memory resource. +\tcode{initial_size}, if specified, is greater than zero. + +\pnum +\effects +Sets \tcode{upstream_rsrc} to \tcode{upstream} and +\tcode{current_buffer} to \keyword{nullptr}. +If \tcode{initial_size} is specified, +sets \tcode{next_buffer_size} to at least \tcode{initial_size}; +otherwise sets \tcode{next_buffer_size} to an +\impldef{default \tcode{next_buffer_size} for a \tcode{monotonic_buffer_resource}} size. +\end{itemdescr} + +\indexlibraryctor{monotonic_buffer_resource}% +\begin{itemdecl} +monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{upstream} is the address of a valid memory resource. +\tcode{buffer_size} is no larger than the number of bytes in \tcode{buffer}. + +\pnum +\effects +Sets \tcode{upstream_rsrc} to \tcode{upstream}, +\tcode{current_buffer} to \tcode{buffer}, and +\tcode{next_buffer_size} to \tcode{buffer_size} (but not less than 1), +then increases \tcode{next_buffer_size} +by an \impldef{growth factor for \tcode{monotonic_buffer_resource}} growth factor (which need not be integral). +\end{itemdescr} + +\indexlibrarydtor{monotonic_buffer_resource}% +\begin{itemdecl} +~monotonic_buffer_resource(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{release()}. +\end{itemdescr} + + +\rSec3[mem.res.monotonic.buffer.mem]{Members} + +\indexlibrarymember{release}{monotonic_buffer_resource}% +\begin{itemdecl} +void release(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{upstream_rsrc->deallocate()} as necessary +to release all allocated memory. +Resets \tcode{current_buffer} and \tcode{next_buffer_size} +to their initial values at construction. + +\pnum +\begin{note} +The memory is released back to \tcode{upstream_rsrc} +even if some blocks that were allocated from \keyword{this} +have not been deallocated from \keyword{this}. +\end{note} +\end{itemdescr} + +\indexlibrarymember{upstream_resource}{monotonic_buffer_resource}% +\begin{itemdecl} +memory_resource* upstream_resource() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The value of \tcode{upstream_rsrc}. +\end{itemdescr} + +\indexlibrarymember{do_allocate}{monotonic_buffer_resource}% +\begin{itemdecl} +void* do_allocate(size_t bytes, size_t alignment) override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If the unused space in \tcode{current_buffer} +can fit a block with the specified \tcode{bytes} and \tcode{alignment}, +then allocate the return block from \tcode{current_buffer}; +otherwise set \tcode{current_buffer} to \tcode{upstream_rsrc->allocate(n, m)}, +where \tcode{n} is not less than \tcode{max(bytes, next_buffer_size)} and +\tcode{m} is not less than \tcode{alignment}, +and increase \tcode{next_buffer_size} +by an \impldef{growth factor for \tcode{monotonic_buffer_resource}} growth factor (which need not be integral), +then allocate the return block from the newly-allocated \tcode{current_buffer}. + +\pnum +\returns +A pointer to allocated storage\iref{basic.stc.dynamic.allocation} +with a size of at least \tcode{bytes}. +The size and alignment of the allocated memory shall meet the requirements +for a class derived from \tcode{memory_resource}\iref{mem.res.class}. + +\pnum +\throws +Nothing unless \tcode{upstream_rsrc->allocate()} throws. +\end{itemdescr} + +\indexlibrarymember{do_deallocate}{monotonic_buffer_resource}% +\begin{itemdecl} +void do_deallocate(void* p, size_t bytes, size_t alignment) override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +None. + +\pnum +\throws +Nothing. + +\pnum +\remarks +Memory used by this resource increases monotonically until its destruction. +\end{itemdescr} + +\indexlibrarymember{do_is_equal}{monotonic_buffer_resource}% +\begin{itemdecl} +bool do_is_equal(const memory_resource& other) const noexcept override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{this == \&other}. +\end{itemdescr} + + +\rSec1[allocator.adaptor]{Class template \tcode{scoped_allocator_adaptor}} + +\rSec2[allocator.adaptor.syn]{Header \tcode{} synopsis} + +\indexheader{scoped_allocator}% +\begin{codeblock} +namespace std { + // class template \tcode{scoped allocator adaptor} + template + class scoped_allocator_adaptor; + + // \ref{scoped.adaptor.operators}, scoped allocator operators + template + bool operator==(const scoped_allocator_adaptor& a, + const scoped_allocator_adaptor& b) noexcept; +} +\end{codeblock} + +\pnum +The class template \tcode{scoped_allocator_adaptor} is an allocator template that +specifies an allocator resource (the outer allocator) to be used by a container (as any +other allocator does) and also specifies an inner allocator resource to be passed to the +constructor of every element within the container. This adaptor is instantiated with one +outer and zero or more inner allocator types. If instantiated with only one allocator +type, the inner allocator becomes the \tcode{scoped_allocator_adaptor} itself, thus +using the same allocator resource for the container and every element within the +container and, if the elements themselves are containers, each of their elements +recursively. If instantiated with more than one allocator, the first allocator is the +outer allocator for use by the container, the second allocator is passed to the +constructors of the container's elements, and, if the elements themselves are +containers, the third allocator is passed to the elements' elements, and so on. If +containers are nested to a depth greater than the number of allocators, the last +allocator is used repeatedly, as in the single-allocator case, for any remaining +recursions. +\begin{note} +The \tcode{scoped_allocator_adaptor} is derived from the outer +allocator type so it can be substituted for the outer allocator type in most +expressions. +\end{note} + +\indexlibraryglobal{scoped_allocator_adaptor}% +\indexlibrarymember{outer_allocator_type}{scoped_allocator_adaptor}% +\indexlibrarymember{value_type}{scoped_allocator_adaptor}% +\indexlibrarymember{size_type}{scoped_allocator_adaptor}% +\indexlibrarymember{difference_type}{scoped_allocator_adaptor}% +\indexlibrarymember{pointer}{scoped_allocator_adaptor}% +\indexlibrarymember{const_pointer}{scoped_allocator_adaptor}% +\indexlibrarymember{void_pointer}{scoped_allocator_adaptor}% +\indexlibrarymember{const_void_pointer}{scoped_allocator_adaptor}% +\begin{codeblock} +namespace std { + template + class scoped_allocator_adaptor : public OuterAlloc { + private: + using OuterTraits = allocator_traits; // \expos + scoped_allocator_adaptor inner; // \expos + + public: + using outer_allocator_type = OuterAlloc; + using inner_allocator_type = @\seebelow@; + + using value_type = typename OuterTraits::value_type; + using size_type = typename OuterTraits::size_type; + using difference_type = typename OuterTraits::difference_type; + using pointer = typename OuterTraits::pointer; + using const_pointer = typename OuterTraits::const_pointer; + using void_pointer = typename OuterTraits::void_pointer; + using const_void_pointer = typename OuterTraits::const_void_pointer; + + using propagate_on_container_copy_assignment = @\seebelow@; + using propagate_on_container_move_assignment = @\seebelow@; + using propagate_on_container_swap = @\seebelow@; + using is_always_equal = @\seebelow@; + + template struct rebind { + using other = scoped_allocator_adaptor< + OuterTraits::template rebind_alloc, InnerAllocs...>; + }; + + scoped_allocator_adaptor(); + template + scoped_allocator_adaptor(OuterA2&& outerAlloc, + const InnerAllocs&... innerAllocs) noexcept; + + scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept; + scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; + + template + scoped_allocator_adaptor( + const scoped_allocator_adaptor& other) noexcept; + template + scoped_allocator_adaptor( + scoped_allocator_adaptor&& other) noexcept; + + scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default; + scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default; + + ~scoped_allocator_adaptor(); + + inner_allocator_type& inner_allocator() noexcept; + const inner_allocator_type& inner_allocator() const noexcept; + outer_allocator_type& outer_allocator() noexcept; + const outer_allocator_type& outer_allocator() const noexcept; + + [[nodiscard]] pointer allocate(size_type n); + [[nodiscard]] pointer allocate(size_type n, const_void_pointer hint); + void deallocate(pointer p, size_type n); + size_type max_size() const; + + template + void construct(T* p, Args&&... args); + + template + void destroy(T* p); + + scoped_allocator_adaptor select_on_container_copy_construction() const; + }; + + template + scoped_allocator_adaptor(OuterAlloc, InnerAllocs...) + -> scoped_allocator_adaptor; +} +\end{codeblock} + +\rSec2[allocator.adaptor.types]{Member types} + +\indexlibrarymember{inner_allocator_type}{scoped_allocator_adaptor}% +\begin{itemdecl} +using inner_allocator_type = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{scoped_allocator_adaptor} if \tcode{sizeof...(InnerAllocs)} is +zero; otherwise,\\ \tcode{scoped_allocator_adaptor}. +\end{itemdescr} + +\indexlibrarymember{propagate_on_container_copy_assignment}{scoped_allocator_adaptor}% +\begin{itemdecl} +using propagate_on_container_copy_assignment = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{true_type} if +\tcode{allocator_traits::propagate_on_container_copy_assignment::value} is +\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and +\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. +\end{itemdescr} + +\indexlibrarymember{propagate_on_container_move_assignment}{scoped_allocator_adaptor}% +\begin{itemdecl} +using propagate_on_container_move_assignment = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{true_type} if +\tcode{allocator_traits::propagate_on_container_move_assignment::value} is +\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and +\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. +\end{itemdescr} + +\indexlibrarymember{propagate_on_container_swap}{scoped_allocator_adaptor}% +\begin{itemdecl} +using propagate_on_container_swap = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{true_type} if +\tcode{allocator_traits::propagate_on_container_swap::value} is +\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and +\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. +\end{itemdescr} + +\indexlibrarymember{is_always_equal}{scoped_allocator_adaptor}% +\begin{itemdecl} +using is_always_equal = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ctype \tcode{true_type} if +\tcode{allocator_traits::is_always_equal::value} is +\tcode{true} for every \tcode{A} in the set of \tcode{OuterAlloc} and +\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. +\end{itemdescr} + +\rSec2[allocator.adaptor.cnstr]{Constructors} + +\indexlibraryctor{scoped_allocator_adaptor}% +\begin{itemdecl} +scoped_allocator_adaptor(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Value-initializes the \tcode{OuterAlloc} base class and the \tcode{inner} allocator +object. +\end{itemdescr} + +\indexlibraryctor{scoped_allocator_adaptor}% +\begin{itemdecl} +template + scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +Initializes the \tcode{OuterAlloc} base class with +\tcode{std::forward(outerAlloc)} and \tcode{inner} with \tcode{innerAllocs...} +(hence recursively initializing each allocator within the adaptor with the corresponding +allocator from the argument list). +\end{itemdescr} + +\indexlibraryctor{scoped_allocator_adaptor}% +\begin{itemdecl} +scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes each allocator within the adaptor with the corresponding allocator +from \tcode{other}. +\end{itemdescr} + +\indexlibraryctor{scoped_allocator_adaptor}% +\begin{itemdecl} +scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Move constructs each allocator within the adaptor with the corresponding allocator +from \tcode{other}. +\end{itemdescr} + +\indexlibraryctor{scoped_allocator_adaptor}% +\begin{itemdecl} +template + scoped_allocator_adaptor( + const scoped_allocator_adaptor& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +Initializes each allocator within the adaptor with the corresponding allocator +from \tcode{other}. +\end{itemdescr} + +\indexlibraryctor{scoped_allocator_adaptor}% +\begin{itemdecl} +template + scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +Initializes each allocator within the adaptor with the corresponding allocator rvalue +from \tcode{other}. +\end{itemdescr} + +\rSec2[allocator.adaptor.members]{Members} + +\pnum +In the \tcode{construct} member functions, +\tcode{\placeholdernc{OUTERMOST}(x)} is +\tcode{\placeholdernc{OUTERMOST}(x.outer_allocator())} if +the expression \tcode{x.outer_allocator()} is +valid~\iref{temp.deduct} and +\tcode{x} otherwise; +\tcode{\placeholdernc{OUTERMOST_ALLOC_TRAITS}(x)} is +\tcode{allocator_traits>}. +\begin{note} +\tcode{\placeholdernc{OUTERMOST}(x)} and +\tcode{\placeholdernc{OUTERMOST_ALL\-OC_TRAITS}(x)} are recursive operations. It +is incumbent upon the definition of \tcode{outer_allocator()} to ensure that the +recursion terminates. It will terminate for all instantiations of +\tcode{scoped_allocator_adaptor}. +\end{note} + +\indexlibrarymember{inner_allocator}{scoped_allocator_adaptor}% +\begin{itemdecl} +inner_allocator_type& inner_allocator() noexcept; +const inner_allocator_type& inner_allocator() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{*this} if \tcode{sizeof...(InnerAllocs)} is zero; otherwise, +\tcode{inner}. +\end{itemdescr} + +\indexlibrarymember{outer_allocator}{scoped_allocator_adaptor}% +\begin{itemdecl} +outer_allocator_type& outer_allocator() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{static_cast(*this)}. +\end{itemdescr} + +\indexlibrarymember{outer_allocator}{scoped_allocator_adaptor}% +\begin{itemdecl} +const outer_allocator_type& outer_allocator() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{static_cast(*this)}. +\end{itemdescr} + +\indexlibrarymember{allocate}{scoped_allocator_adaptor}% +\begin{itemdecl} +[[nodiscard]] pointer allocate(size_type n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{allocator_traits::allocate(outer_allocator(), n)}. +\end{itemdescr} + +\indexlibrarymember{allocate}{scoped_allocator_adaptor}% +\begin{itemdecl} +[[nodiscard]] pointer allocate(size_type n, const_void_pointer hint); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{allocator_traits::allocate(outer_allocator(), n, hint)}. +\end{itemdescr} + +\indexlibrarymember{deallocate}{scoped_allocator_adaptor}% +\begin{itemdecl} +void deallocate(pointer p, size_type n) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +As if by: +\tcode{allocator_traits::deallocate(outer_allocator(), p, n);} +\end{itemdescr} + +\indexlibrarymember{max_size}{scoped_allocator_adaptor}% +\begin{itemdecl} +size_type max_size() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{allocator_traits::max_size(outer_allocator())}. +\end{itemdescr} + +\indexlibrarymember{construct}{scoped_allocator_adaptor}% +\begin{itemdecl} +template + void construct(T* p, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +apply([p, this](auto&&... newargs) { + @\placeholdernc{OUTERMOST_ALLOC_TRAITS}@(*this)::construct( + @\placeholdernc{OUTERMOST}@(*this), p, + std::forward(newargs)...); + }, + uses_allocator_construction_args(inner_allocator(), + std::forward(args)...)); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{destroy}{scoped_allocator_adaptor}% +\begin{itemdecl} +template + void destroy(T* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{\placeholdernc{OUTERMOST_ALLOC_TRAITS}(*this)::destroy(\placeholdernc{OUTERMOST}(*this), p)}. +\end{itemdescr} + +\indexlibrarymember{select_on_container_copy_construction}{scoped_allocator_adaptor}% +\begin{itemdecl} +scoped_allocator_adaptor select_on_container_copy_construction() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A new \tcode{scoped_allocator_adaptor} object +where each allocator \tcode{a1} within the adaptor +is initialized with +\tcode{allocator_traits::select_on_container_copy_construction(a2)}, +where \tcode{A1} is the type of \tcode{a1} and +\tcode{a2} is the corresponding allocator in \tcode{*this}. +\end{itemdescr} + +\rSec2[scoped.adaptor.operators]{Operators} + +\indexlibrarymember{operator==}{scoped_allocator_adaptor}% +\begin{itemdecl} +template + bool operator==(const scoped_allocator_adaptor& a, + const scoped_allocator_adaptor& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \tcode{sizeof...(InnerAllocs)} is zero, +\begin{codeblock} +a.outer_allocator() == b.outer_allocator() +\end{codeblock} +otherwise +\begin{codeblock} +a.outer_allocator() == b.outer_allocator() && a.inner_allocator() == b.inner_allocator() +\end{codeblock} +\end{itemdescr} diff --git a/source/std.tex b/source/std.tex index 552d663558..dc5385f897 100644 --- a/source/std.tex +++ b/source/std.tex @@ -119,6 +119,7 @@ \include{support} \include{concepts} \include{diagnostics} +\include{memory} \include{utilities} \include{strings} \include{containers} diff --git a/source/utilities.tex b/source/utilities.tex index c18b5faa36..e8693c39d5 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -18,10 +18,6 @@ \ref{any} & Storage for any type & \tcode{} \\ \rowsep \ref{expected} & Expected objects & \tcode{} \\ \rowsep \ref{bitset} & Fixed-size sequences of bits & \tcode{} \\ \rowsep -\ref{memory} & Memory & \tcode{}, \tcode{} \\ \rowsep -\ref{smartptr} & Smart pointers & \tcode{} \\ \rowsep -\ref{mem.res} & Memory resources & \tcode{} \\ \rowsep -\ref{allocator.adaptor} & Scoped allocators & \tcode{} \\ \rowsep \ref{function.objects} & Function objects & \tcode{} \\ \rowsep \ref{meta} & Type traits & \tcode{} \\ \rowsep \ref{ratio} & Compile-time rational arithmetic & \tcode{} \\ \rowsep @@ -9422,6741 +9418,6 @@ (see~\ref{ostream.formatted}). \end{itemdescr} -\rSec1[memory]{Memory} - -\rSec2[memory.general]{In general} - -\pnum -Subclause~\ref{memory} describes the contents of the header -\libheaderref{memory} and some -of the contents of the header \libheaderref{cstdlib}. - -\rSec2[memory.syn]{Header \tcode{} synopsis} - -\pnum -The header \libheaderdef{memory} defines several types and function templates that -describe properties of pointers and pointer-like types, manage memory -for containers and other template types, destroy objects, and -construct objects in -uninitialized memory -buffers~(\ref{pointer.traits}--\ref{specialized.addressof} and \ref{specialized.algorithms}). -The header also defines the templates -\tcode{unique_ptr}, \tcode{shared_ptr}, \tcode{weak_ptr}, -\tcode{out_ptr_t}, \tcode{inout_ptr_t}, and various function -templates that operate on objects of these types\iref{smartptr}. - -\pnum -Let \tcode{\exposid{POINTER_OF}(T)} denote a type that is -\begin{itemize} -\item -\tcode{T::pointer} if the \grammarterm{qualified-id} \tcode{T::pointer} -is valid and denotes a type, -\item -otherwise, \tcode{T::element_type*} -if the \grammarterm{qualified-id} \tcode{T::element_type} -is valid and denotes a type, -\item -otherwise, \tcode{pointer_traits::element_type*}. -\end{itemize} - -\pnum -Let \tcode{\exposid{POINTER_OF_OR}(T, U)} denote a type that is: -\begin{itemize} -\item -\tcode{\exposid{POINTER_OF}(T)} -if \tcode{\exposid{POINTER_OF}(T)} is valid and denotes a type, -\item -otherwise, \tcode{U}. -\end{itemize} - -\begin{codeblock} -#include // see \ref{compare.syn} - -namespace std { - // \ref{pointer.traits}, pointer traits - template struct pointer_traits; - template struct pointer_traits; - - // \ref{pointer.conversion}, pointer conversion - template - constexpr T* to_address(T* p) noexcept; - template - constexpr auto to_address(const Ptr& p) noexcept; - - // \ref{ptr.align}, pointer alignment - void* align(size_t alignment, size_t size, void*& ptr, size_t& space); - template - [[nodiscard]] constexpr T* assume_aligned(T* ptr); - - // \ref{allocator.tag}, allocator argument tag - struct allocator_arg_t { explicit allocator_arg_t() = default; }; - inline constexpr allocator_arg_t allocator_arg{}; - - // \ref{allocator.uses}, \tcode{uses_allocator} - template struct uses_allocator; - - // \ref{allocator.uses.trait}, \tcode{uses_allocator} - template - inline constexpr bool @\libglobal{uses_allocator_v}@ = uses_allocator::value; - - // \ref{allocator.uses.construction}, uses-allocator construction - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - Args&&... args) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, - Tuple1&& x, Tuple2&& y) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - U&& u, V&& v) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - pair& pr) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - const pair& pr) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - pair&& pr) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - const pair&& pr) noexcept; - template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept; - template - constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args); - template - constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, - Args&&... args); - - // \ref{allocator.traits}, allocator traits - template struct allocator_traits; - - template - struct allocation_result { - Pointer ptr; - size_t count; - }; - - template - [[nodiscard] constexpr allocation_result::pointer> - allocate_at_least(Allocator& a, size_t n); - - // \ref{default.allocator}, the default allocator - template class allocator; - template - constexpr bool operator==(const allocator&, const allocator&) noexcept; - - // \ref{specialized.addressof}, addressof - template - constexpr T* addressof(T& r) noexcept; - template - const T* addressof(const T&&) = delete; - - // \ref{specialized.algorithms}, specialized algorithms - // \ref{special.mem.concepts}, special memory concepts - template - concept @\exposconcept{nothrow-input-iterator}@ = @\seebelow@; // \expos - template - concept @\exposconcept{nothrow-forward-iterator}@ = @\seebelow@; // \expos - template - concept @\exposconcept{nothrow-sentinel-for}@ = @\seebelow@; // \expos - template - concept @\exposconcept{nothrow-input-range}@ = @\seebelow@; // \expos - template - concept @\exposconcept{nothrow-forward-range}@ = @\seebelow@; // \expos - - template - void uninitialized_default_construct(NoThrowForwardIterator first, - NoThrowForwardIterator last); - template - void uninitialized_default_construct(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, - NoThrowForwardIterator last); - template - NoThrowForwardIterator - uninitialized_default_construct_n(NoThrowForwardIterator first, Size n); - template - NoThrowForwardIterator - uninitialized_default_construct_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, Size n); - - namespace ranges { - template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> - requires @\libconcept{default_initializable}@> - I uninitialized_default_construct(I first, S last); - template<@\exposconcept{nothrow-forward-range}@ R> - requires @\libconcept{default_initializable}@> - borrowed_iterator_t uninitialized_default_construct(R&& r); - - template<@\exposconcept{nothrow-forward-iterator}@ I> - requires @\libconcept{default_initializable}@> - I uninitialized_default_construct_n(I first, iter_difference_t n); - } - - template - void uninitialized_value_construct(NoThrowForwardIterator first, - NoThrowForwardIterator last); - template - void uninitialized_value_construct(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, - NoThrowForwardIterator last); - template - NoThrowForwardIterator - uninitialized_value_construct_n(NoThrowForwardIterator first, Size n); - template - NoThrowForwardIterator - uninitialized_value_construct_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, Size n); - - namespace ranges { - template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> - requires @\libconcept{default_initializable}@> - I uninitialized_value_construct(I first, S last); - template<@\exposconcept{nothrow-forward-range}@ R> - requires @\libconcept{default_initializable}@> - borrowed_iterator_t uninitialized_value_construct(R&& r); - - template<@\exposconcept{nothrow-forward-iterator}@ I> - requires @\libconcept{default_initializable}@> - I uninitialized_value_construct_n(I first, iter_difference_t n); - } - - template - NoThrowForwardIterator uninitialized_copy(InputIterator first, InputIterator last, - NoThrowForwardIterator result); - template - NoThrowForwardIterator uninitialized_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - ForwardIterator first, ForwardIterator last, - NoThrowForwardIterator result); - template - NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n, - NoThrowForwardIterator result); - template - NoThrowForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - ForwardIterator first, Size n, - NoThrowForwardIterator result); - - namespace ranges { - template - using uninitialized_copy_result = in_out_result; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S1, - @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S2> - requires @\libconcept{constructible_from}@, iter_reference_t> - uninitialized_copy_result - uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast); - template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> - requires @\libconcept{constructible_from}@, range_reference_t> - uninitialized_copy_result, borrowed_iterator_t> - uninitialized_copy(IR&& in_range, OR&& out_range); - - template - using uninitialized_copy_n_result = in_out_result; - template<@\libconcept{input_iterator}@ I, @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S> - requires @\libconcept{constructible_from}@, iter_reference_t> - uninitialized_copy_n_result - uninitialized_copy_n(I ifirst, iter_difference_t n, O ofirst, S olast); - } - - template - NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last, - NoThrowForwardIterator result); - template - NoThrowForwardIterator uninitialized_move(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - ForwardIterator first, ForwardIterator last, - NoThrowForwardIterator result); - template - pair - uninitialized_move_n(InputIterator first, Size n, NoThrowForwardIterator result); - template - pair - uninitialized_move_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - ForwardIterator first, Size n, NoThrowForwardIterator result); - - namespace ranges { - template - using uninitialized_move_result = in_out_result; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S1, - @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S2> - requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> - uninitialized_move_result - uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast); - template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> - requires @\libconcept{constructible_from}@, range_rvalue_reference_t> - uninitialized_move_result, borrowed_iterator_t> - uninitialized_move(IR&& in_range, OR&& out_range); - - template - using uninitialized_move_n_result = in_out_result; - template<@\libconcept{input_iterator}@ I, - @\exposconcept{nothrow-forward-iterator}@ O, @\exposconcept{nothrow-sentinel-for}@ S> - requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> - uninitialized_move_n_result - uninitialized_move_n(I ifirst, iter_difference_t n, O ofirst, S olast); - } - - template - void uninitialized_fill(NoThrowForwardIterator first, NoThrowForwardIterator last, - const T& x); - template - void uninitialized_fill(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, NoThrowForwardIterator last, - const T& x); - template - NoThrowForwardIterator - uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); - template - NoThrowForwardIterator - uninitialized_fill_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, Size n, const T& x); - - namespace ranges { - template<@\exposconcept{nothrow-forward-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S, class T> - requires @\libconcept{constructible_from}@, const T&> - I uninitialized_fill(I first, S last, const T& x); - template<@\exposconcept{nothrow-forward-range}@ R, class T> - requires @\libconcept{constructible_from}@, const T&> - borrowed_iterator_t uninitialized_fill(R&& r, const T& x); - - template<@\exposconcept{nothrow-forward-iterator}@ I, class T> - requires @\libconcept{constructible_from}@, const T&> - I uninitialized_fill_n(I first, iter_difference_t n, const T& x); - } - - // \ref{specialized.construct}, \tcode{construct_at} - template - constexpr T* construct_at(T* location, Args&&... args); - - namespace ranges { - template - constexpr T* construct_at(T* location, Args&&... args); - } - - // \ref{specialized.destroy}, \tcode{destroy} - template - constexpr void destroy_at(T* location); - template - constexpr void destroy(NoThrowForwardIterator first, NoThrowForwardIterator last); - template - void destroy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, NoThrowForwardIterator last); - template - constexpr NoThrowForwardIterator destroy_n(NoThrowForwardIterator first, Size n); - template - NoThrowForwardIterator destroy_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, Size n); - - namespace ranges { - template<@\libconcept{destructible}@ T> - constexpr void destroy_at(T* location) noexcept; - - template<@\exposconcept{nothrow-input-iterator}@ I, @\exposconcept{nothrow-sentinel-for}@ S> - requires @\libconcept{destructible}@> - constexpr I destroy(I first, S last) noexcept; - template<@\exposconcept{nothrow-input-range}@ R> - requires @\libconcept{destructible}@> - constexpr borrowed_iterator_t destroy(R&& r) noexcept; - - template<@\exposconcept{nothrow-input-iterator}@ I> - requires @\libconcept{destructible}@> - constexpr I destroy_n(I first, iter_difference_t n) noexcept; - } - - // \ref{unique.ptr}, class template \tcode{unique_ptr} - template struct default_delete; - template struct default_delete; - template> class unique_ptr; - template class unique_ptr; - - template - constexpr unique_ptr make_unique(Args&&... args); // \tcode{T} is not array - template - constexpr unique_ptr make_unique(size_t n); // \tcode{T} is \tcode{U[]} - template - @\unspecnc@ make_unique(Args&&...) = delete; // \tcode{T} is \tcode{U[N]} - - template - constexpr unique_ptr make_unique_for_overwrite(); // \tcode{T} is not array - template - constexpr unique_ptr make_unique_for_overwrite(size_t n); // \tcode{T} is \tcode{U[]} - template - @\unspecnc@ make_unique_for_overwrite(Args&&...) = delete; // \tcode{T} is \tcode{U[N]} - - template - constexpr void swap(unique_ptr& x, unique_ptr& y) noexcept; - - template - constexpr bool operator==(const unique_ptr& x, const unique_ptr& y); - template - bool operator<(const unique_ptr& x, const unique_ptr& y); - template - bool operator>(const unique_ptr& x, const unique_ptr& y); - template - bool operator<=(const unique_ptr& x, const unique_ptr& y); - template - bool operator>=(const unique_ptr& x, const unique_ptr& y); - template - requires @\libconcept{three_way_comparable_with}@::pointer, - typename unique_ptr::pointer> - compare_three_way_result_t::pointer, - typename unique_ptr::pointer> - operator<=>(const unique_ptr& x, const unique_ptr& y); - - template - constexpr bool operator==(const unique_ptr& x, nullptr_t) noexcept; - template - constexpr bool operator<(const unique_ptr& x, nullptr_t); - template - constexpr bool operator<(nullptr_t, const unique_ptr& y); - template - constexpr bool operator>(const unique_ptr& x, nullptr_t); - template - constexpr bool operator>(nullptr_t, const unique_ptr& y); - template - constexpr bool operator<=(const unique_ptr& x, nullptr_t); - template - constexpr bool operator<=(nullptr_t, const unique_ptr& y); - template - constexpr bool operator>=(const unique_ptr& x, nullptr_t); - template - constexpr bool operator>=(nullptr_t, const unique_ptr& y); - template - requires @\libconcept{three_way_comparable}@::pointer> - constexpr compare_three_way_result_t::pointer> - operator<=>(const unique_ptr& x, nullptr_t); - - template - basic_ostream& operator<<(basic_ostream& os, const unique_ptr& p); - - // \ref{util.smartptr.weak.bad}, class \tcode{bad_weak_ptr} - class bad_weak_ptr; - - // \ref{util.smartptr.shared}, class template \tcode{shared_ptr} - template class shared_ptr; - - // \ref{util.smartptr.shared.create}, \tcode{shared_ptr} creation - template - shared_ptr make_shared(Args&&... args); // \tcode{T} is not array - template - shared_ptr allocate_shared(const A& a, Args&&... args); // \tcode{T} is not array - - template - shared_ptr make_shared(size_t N); // \tcode{T} is \tcode{U[]} - template - shared_ptr allocate_shared(const A& a, size_t N); // \tcode{T} is \tcode{U[]} - - template - shared_ptr make_shared(); // \tcode{T} is \tcode{U[N]} - template - shared_ptr allocate_shared(const A& a); // \tcode{T} is \tcode{U[N]} - - template - shared_ptr make_shared(size_t N, const remove_extent_t& u); // \tcode{T} is \tcode{U[]} - template - shared_ptr allocate_shared(const A& a, size_t N, - const remove_extent_t& u); // \tcode{T} is \tcode{U[]} - - template - shared_ptr make_shared(const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} - template - shared_ptr allocate_shared(const A& a, const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} - - template - shared_ptr make_shared_for_overwrite(); // \tcode{T} is not \tcode{U[]} - template - shared_ptr allocate_shared_for_overwrite(const A& a); // \tcode{T} is not \tcode{U[]} - - template - shared_ptr make_shared_for_overwrite(size_t N); // \tcode{T} is \tcode{U[]} - template - shared_ptr allocate_shared_for_overwrite(const A& a, size_t N); // \tcode{T} is \tcode{U[]} - - // \ref{util.smartptr.shared.cmp}, \tcode{shared_ptr} comparisons - template - bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept; - template - strong_ordering operator<=>(const shared_ptr& a, const shared_ptr& b) noexcept; - - template - bool operator==(const shared_ptr& x, nullptr_t) noexcept; - template - strong_ordering operator<=>(const shared_ptr& x, nullptr_t) noexcept; - - // \ref{util.smartptr.shared.spec}, \tcode{shared_ptr} specialized algorithms - template - void swap(shared_ptr& a, shared_ptr& b) noexcept; - - // \ref{util.smartptr.shared.cast}, \tcode{shared_ptr} casts - template - shared_ptr static_pointer_cast(const shared_ptr& r) noexcept; - template - shared_ptr static_pointer_cast(shared_ptr&& r) noexcept; - template - shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept; - template - shared_ptr dynamic_pointer_cast(shared_ptr&& r) noexcept; - template - shared_ptr const_pointer_cast(const shared_ptr& r) noexcept; - template - shared_ptr const_pointer_cast(shared_ptr&& r) noexcept; - template - shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept; - template - shared_ptr reinterpret_pointer_cast(shared_ptr&& r) noexcept; - - // \ref{util.smartptr.getdeleter}, \tcode{shared_ptr} \tcode{get_deleter} - template - D* get_deleter(const shared_ptr& p) noexcept; - - // \ref{util.smartptr.shared.io}, \tcode{shared_ptr} I/O - template - basic_ostream& operator<<(basic_ostream& os, const shared_ptr& p); - - // \ref{util.smartptr.weak}, class template \tcode{weak_ptr} - template class weak_ptr; - - // \ref{util.smartptr.weak.spec}, \tcode{weak_ptr} specialized algorithms - template void swap(weak_ptr& a, weak_ptr& b) noexcept; - - // \ref{util.smartptr.ownerless}, class template \tcode{owner_less} - template struct owner_less; - - // \ref{util.smartptr.enab}, class template \tcode{enable_shared_from_this} - template class enable_shared_from_this; - - // \ref{util.smartptr.hash}, hash support - template struct hash; - template struct hash>; - template struct hash>; - - // \ref{util.smartptr.atomic}, atomic smart pointers - template struct atomic; - template struct atomic>; - template struct atomic>; - - // \ref{out.ptr.t}, class template \tcode{out_ptr_t} - template - class out_ptr_t; - - // \ref{out.ptr}, function template \tcode{out_ptr} - template - auto out_ptr(Smart& s, Args&&... args); - - // \ref{inout.ptr.t}, class template \tcode{inout_ptr_t} - template - class inout_ptr_t; - - // \ref{inout.ptr}, function template \tcode{inout_ptr} - template - auto inout_ptr(Smart& s, Args&&... args); -} -\end{codeblock} - -\rSec2[pointer.traits]{Pointer traits} - -\rSec3[pointer.traits.general]{General} - -\pnum -The class template \tcode{pointer_traits} supplies a uniform interface to certain -attributes of pointer-like types. - -\indexlibraryglobal{pointer_traits}% -\begin{codeblock} -namespace std { - template struct pointer_traits { - using pointer = Ptr; - using element_type = @\seebelow@; - using difference_type = @\seebelow@; - - template using rebind = @\seebelow@; - - static pointer pointer_to(@\seebelow@ r); - }; - - template struct pointer_traits { - using pointer = T*; - using element_type = T; - using difference_type = ptrdiff_t; - - template using rebind = U*; - - static constexpr pointer pointer_to(@\seebelow@ r) noexcept; - }; -} -\end{codeblock} - -\rSec3[pointer.traits.types]{Member types} - -\indexlibrarymember{element_type}{pointer_traits}% -\begin{itemdecl} -using element_type = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{Ptr::element_type} if -the \grammarterm{qualified-id} \tcode{Ptr::element_type} is valid and denotes a -type\iref{temp.deduct}; otherwise, \tcode{T} if -\tcode{Ptr} is a class template instantiation of the form \tcode{SomePointer}, -where \tcode{Args} is zero or more type arguments; otherwise, the specialization is -ill-formed. -\end{itemdescr} - -\indexlibrarymember{difference_type}{pointer_traits}% -\begin{itemdecl} -using difference_type = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{Ptr::difference_type} if -the \grammarterm{qualified-id} \tcode{Ptr::difference_type} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{ptrdiff_t}. -\end{itemdescr} - -\indexlibrarymember{rebind}{pointer_traits}% -\begin{itemdecl} -template using rebind = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\templalias \tcode{Ptr::rebind} if -the \grammarterm{qualified-id} \tcode{Ptr::rebind} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{SomePointer} if -\tcode{Ptr} is a class template instantiation of the form \tcode{SomePointer}, -where \tcode{Args} is zero or more type arguments; otherwise, the instantiation of -\tcode{rebind} is ill-formed. -\end{itemdescr} - -\rSec3[pointer.traits.functions]{Member functions} - -\indexlibrarymember{pointer_to}{pointer_traits}% -\begin{itemdecl} -static pointer pointer_traits::pointer_to(@\seebelow@ r); -static constexpr pointer pointer_traits::pointer_to(@\seebelow@ r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -For the first member function, -\tcode{Ptr::pointer_to(r)} is well-formed. - -\pnum -\expects -For the first member function, -\tcode{Ptr::pointer_to(r)} returns a pointer to \tcode{r} -through which indirection is valid. - -\pnum -\returns -The first member function returns \tcode{Ptr::pointer_to(r)}. -The second member function returns \tcode{addressof(r)}. - -\pnum -\remarks -If \tcode{element_type} is \cv{}~\keyword{void}, the type of -\tcode{r} is unspecified; otherwise, it is \tcode{element_type\&}. -\end{itemdescr} - -\rSec3[pointer.traits.optmem]{Optional members} - -\pnum -Specializations of \tcode{pointer_traits} may define the member declared -in this subclause to customize the behavior of the standard library. - -\indexlibrarymember{to_address}{pointer_traits}% -\begin{itemdecl} -static element_type* to_address(pointer p) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A pointer of type \tcode{element_type*} that references -the same location as the argument \tcode{p}. - -\pnum -\begin{note} -This function is intended to be the inverse of \tcode{pointer_to}. -If defined, it customizes the behavior of -the non-member function -\tcode{to_address}\iref{pointer.conversion}. -\end{note} -\end{itemdescr} - -\rSec2[pointer.conversion]{Pointer conversion} - -\indexlibraryglobal{to_address}% -\begin{itemdecl} -template constexpr T* to_address(T* p) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{T} is not a function type. - -\pnum -\returns -\tcode{p}. -\end{itemdescr} - -\indexlibraryglobal{to_address}% -\begin{itemdecl} -template constexpr auto to_address(const Ptr& p) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{pointer_traits::to_address(p)} if that expression is well-formed -(see \ref{pointer.traits.optmem}), -otherwise \tcode{to_address(p.operator->())}. -\end{itemdescr} - -\rSec2[ptr.align]{Pointer alignment} - -\indexlibraryglobal{align}% -\begin{itemdecl} -void* align(size_t alignment, size_t size, void*& ptr, size_t& space); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\begin{itemize} -\item -\tcode{alignment} is a power of two - -\item -\tcode{ptr} represents the address of contiguous storage of at least -\tcode{space} bytes -\end{itemize} - -\pnum -\effects -If it is possible to fit \tcode{size} bytes -of storage aligned by \tcode{alignment} into the buffer pointed to by -\tcode{ptr} with length \tcode{space}, the function updates -\tcode{ptr} to represent the first possible address of such storage -and decreases \tcode{space} by the number of bytes used for alignment. -Otherwise, the function does nothing. - -\pnum -\returns -A null pointer if the requested aligned buffer -would not fit into the available space, otherwise the adjusted value -of \tcode{ptr}. - -\pnum -\begin{note} -The function updates its \tcode{ptr} -and \tcode{space} arguments so that it can be called repeatedly -with possibly different \tcode{alignment} and \tcode{size} -arguments for the same buffer. -\end{note} -\end{itemdescr} - -\indexlibraryglobal{assume_aligned}% -\begin{itemdecl} -template - [[nodiscard]] constexpr T* assume_aligned(T* ptr); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{N} is a power of two. - -\pnum -\expects -\tcode{ptr} points to an object \tcode{X} of -a type similar\iref{conv.qual} to \tcode{T}, -where \tcode{X} has alignment \tcode{N}\iref{basic.align}. - -\pnum -\returns -\tcode{ptr}. - -\pnum -\throws -Nothing. - -\pnum -\begin{note} -The alignment assumption on an object \tcode{X} -expressed by a call to \tcode{assume_aligned} -might result in generation of more efficient code. -It is up to the program to ensure that the assumption actually holds. -The call does not cause the implementation to verify or enforce this. -An implementation might only make the assumption -for those operations on \tcode{X} that access \tcode{X} -through the pointer returned by \tcode{assume_aligned}. -\end{note} -\end{itemdescr} - -\rSec2[allocator.tag]{Allocator argument tag} - -\indexlibraryglobal{allocator_arg_t}% -\indexlibraryglobal{allocator_arg}% -\begin{itemdecl} -namespace std { - struct allocator_arg_t { explicit allocator_arg_t() = default; }; - inline constexpr allocator_arg_t allocator_arg{}; -} -\end{itemdecl} - -\pnum -The \tcode{allocator_arg_t} struct is an empty class type used as a unique type to -disambiguate constructor and function overloading. Specifically, several types (see -\tcode{tuple}~\ref{tuple}) have constructors with \tcode{allocator_arg_t} as the first -argument, immediately followed by an argument of a type that meets the -\oldconcept{Allocator} requirements (\tref{cpp17.allocator}). - -\rSec2[allocator.uses]{\tcode{uses_allocator}} - -\rSec3[allocator.uses.trait]{\tcode{uses_allocator} trait} - -\indexlibraryglobal{uses_allocator}% -\begin{itemdecl} -template struct uses_allocator; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\remarks -Automatically detects whether \tcode{T} has a nested \tcode{allocator_type} that -is convertible from \tcode{Alloc}. Meets the \oldconcept{BinaryTypeTrait} -requirements\iref{meta.rqmts}. The implementation shall provide a definition that is -derived from \tcode{true_type} if the \grammarterm{qualified-id} \tcode{T::allocator_type} -is valid and denotes a type\iref{temp.deduct} and -\tcode{is_convertible_v != false}, otherwise it shall be -derived from \tcode{false_type}. A program may specialize this template to derive from -\tcode{true_type} for a program-defined type \tcode{T} that does not have a nested -\tcode{allocator_type} but nonetheless can be constructed with an allocator where -either: -\begin{itemize} -\item the first argument of a constructor has type \tcode{allocator_arg_t} and the -second argument has type \tcode{Alloc} or - -\item the last argument of a constructor has type \tcode{Alloc}. -\end{itemize} -\end{itemdescr} - -\rSec3[allocator.uses.construction]{Uses-allocator construction} - -\pnum -\defnx{Uses-allocator construction}{uses-allocator construction} -with allocator \tcode{alloc} and constructor arguments \tcode{args...} -refers to the construction of an object of type \tcode{T} -such that \tcode{alloc} is passed to the constructor of \tcode{T} -if \tcode{T} uses an allocator type compatible with \tcode{alloc}. -When applied to the construction of an object of type \tcode{T}, -it is equivalent to initializing it with the value of the expression -\tcode{make_obj_using_allocator(alloc, args...)}, described below. - -\pnum -The following utility functions support -three conventions for passing \tcode{alloc} to a constructor: -\begin{itemize} -\item - If \tcode{T} does not use an allocator compatible with \tcode{alloc}, - then \tcode{alloc} is ignored. -\item - Otherwise, if \tcode{T} has a constructor invocable as - \tcode{T(allocator_arg, alloc, args...)} (leading-allocator convention), - then uses-allocator construction chooses this constructor form. -\item - Otherwise, if \tcode{T} has a constructor invocable as - \tcode{T(args..., alloc)} (trailing-allocator convention), - then uses-allocator construction chooses this constructor form. -\end{itemize} - -\pnum -The \tcode{uses_allocator_construction_args} function template -takes an allocator and argument list and -produces (as a tuple) a new argument list matching one of the above conventions. -Additionally, overloads are provided -that treat specializations of \tcode{pair} -such that uses-allocator construction is applied individually -to the \tcode{first} and \tcode{second} data members. -The \tcode{make_obj_using_allocator} and -\tcode{uninitialized_construct_using_allocator} function templates -apply the modified constructor arguments -to construct an object of type \tcode{T} -as a return value or in-place, respectively. -\begin{note} -For \tcode{uses_allocator_construction_args} and -\tcode{make_obj_using_allocator}, type \tcode{T} -is not deduced and must therefore be specified explicitly by the caller. -\end{note} - -\indexlibraryglobal{uses_allocator_construction_args}% -\begin{itemdecl} -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - Args&&... args) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is not a specialization of \tcode{pair}. - -\pnum -\returns -A \tcode{tuple} value determined as follows: -\begin{itemize} -\item - If \tcode{uses_allocator_v} is \tcode{false} and - \tcode{is_constructible_v} is \tcode{true}, - return \tcode{forward_as_tuple(std::forward(args)...)}. -\item - Otherwise, if \tcode{uses_allocator_v} is \tcode{true} and - \tcode{is_constructible_v} - is \tcode{true}, - return -\begin{codeblock} -tuple( - allocator_arg, alloc, std::forward(args)...) -\end{codeblock} -\item - Otherwise, if \tcode{uses_allocator_v} is \tcode{true} and - \tcode{is_constructible_v} is \tcode{true}, - return \tcode{forward_as_tuple(std::forward(args)..., alloc)}. -\item - Otherwise, the program is ill-formed. -\end{itemize} -\begin{note} -This definition prevents a silent failure -to pass the allocator to a constructor of a type for which -\tcode{uses_allocator_v} is \tcode{true}. -\end{note} -\end{itemdescr} - -\indexlibraryglobal{uses_allocator_construction_args}% -\begin{itemdecl} -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, - Tuple1&& x, Tuple2&& y) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is a specialization of \tcode{pair}. - -\pnum -\effects -For \tcode{T} specified as \tcode{pair}, equivalent to: -\begin{codeblock} -return make_tuple( - piecewise_construct, - apply([&alloc](auto&&... args1) { - return uses_allocator_construction_args( - alloc, std::forward(args1)...); - }, std::forward(x)), - apply([&alloc](auto&&... args2) { - return uses_allocator_construction_args( - alloc, std::forward(args2)...); - }, std::forward(y))); -\end{codeblock} -\end{itemdescr} - -\indexlibraryglobal{uses_allocator_construction_args}% -\begin{itemdecl} -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is a specialization of \tcode{pair}. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -return uses_allocator_construction_args(alloc, piecewise_construct, - tuple<>{}, tuple<>{}); -\end{codeblock} -\end{itemdescr} - -\indexlibraryglobal{uses_allocator_construction_args}% -\begin{itemdecl} -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - U&& u, V&& v) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is a specialization of \tcode{pair}. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -return uses_allocator_construction_args(alloc, piecewise_construct, - forward_as_tuple(std::forward(u)), - forward_as_tuple(std::forward(v))); -\end{codeblock} -\end{itemdescr} - -\indexlibraryglobal{uses_allocator_construction_args}% -\begin{itemdecl} -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - pair& pr) noexcept; -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - const pair& pr) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is a specialization of \tcode{pair}. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -return uses_allocator_construction_args(alloc, piecewise_construct, - forward_as_tuple(pr.first), - forward_as_tuple(pr.second)); -\end{codeblock} -\end{itemdescr} - -\indexlibraryglobal{uses_allocator_construction_args}% -\begin{itemdecl} -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - pair&& pr) noexcept; -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, - const pair&& pr) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is a specialization of \tcode{pair}. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -return uses_allocator_construction_args(alloc, piecewise_construct, - forward_as_tuple(get<0>(std::move(pr))), - forward_as_tuple(get<1>(std::move(pr)))); -\end{codeblock} -\end{itemdescr} - -\indexlibraryglobal{uses_allocator_construction_args}% -\begin{itemdecl} -template - constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \exposid{FUN} be the function template: -\begin{codeblock} -template - void @\exposid{FUN}@(const pair&); -\end{codeblock} - -\pnum -\constraints -\tcode{T} is a specialization of \tcode{pair}, and -the expression \tcode{\exposid{FUN}(u)} is not well-formed -when considered as an unevaluated operand. - -\pnum -Let \exposid{pair-constructor} be an exposition-only class defined as follows: - -\begin{codeblock} -class @\exposid{pair-constructor}@ { - using @\exposid{pair-type}@ = remove_cv_t; // \expos - - constexpr auto @\exposid{do-construct}@(const @\exposid{pair-type}@& p) const { // \expos - return make_obj_using_allocator<@\exposid{pair-type}@>(@\exposid{alloc_}@, p); - } - constexpr auto @\exposid{do-construct}@(@\exposid{pair-type}@&& p) const { // \expos - return make_obj_using_allocator<@\exposid{pair-type}@>(@\exposid{alloc_}@, std::move(p)); - } - - const Alloc& @\exposid{alloc_}@; // \expos - U& @\exposid{u_}@; // \expos - -public: - constexpr operator @\exposid{pair-type}@() const { - return @\exposid{do-construct}@(std::forward(@\exposid{u_}@)); - } -}; -\end{codeblock} - -\pnum -\returns -\tcode{make_tuple(pc)}, -where \tcode{pc} is a \exposid{pair-constructor} object -whose \exposid{alloc_} member is initialized with \tcode{alloc} and -whose \exposid{u_} member is initialized with \tcode{u}. -\end{itemdescr} - -\indexlibraryglobal{make_obj_using_allocator}% -\begin{itemdecl} -template - constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -return make_from_tuple(uses_allocator_construction_args( - alloc, std::forward(args)...)); -\end{codeblock} -\end{itemdescr} - -\indexlibraryglobal{uninitialized_construct_using_allocator}% -\begin{itemdecl} -template - constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -return apply([&](U&&... xs) { - return construct_at(p, std::forward(xs)...); - }, uses_allocator_construction_args(alloc, std::forward(args)...)); -\end{codeblock} -\end{itemdescr} - -\rSec2[allocator.traits]{Allocator traits} - -\rSec3[allocator.traits.general]{General} - -\pnum -The class template \tcode{allocator_traits} supplies a uniform interface to all -allocator types. -An allocator cannot be a non-class type, however, even if \tcode{allocator_traits} -supplies the entire required interface. -\begin{note} -Thus, it is always possible to create -a derived class from an allocator. -\end{note} - -\indexlibraryglobal{allocator_traits}% -\begin{codeblock} -namespace std { - template struct allocator_traits { - using allocator_type = Alloc; - - using value_type = typename Alloc::value_type; - - using pointer = @\seebelow@; - using const_pointer = @\seebelow@; - using void_pointer = @\seebelow@; - using const_void_pointer = @\seebelow@; - - using difference_type = @\seebelow@; - using size_type = @\seebelow@; - - using propagate_on_container_copy_assignment = @\seebelow@; - using propagate_on_container_move_assignment = @\seebelow@; - using propagate_on_container_swap = @\seebelow@; - using is_always_equal = @\seebelow@; - - template using rebind_alloc = @\seebelow@; - template using rebind_traits = allocator_traits>; - - [[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n); - [[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n, - const_void_pointer hint); - - static constexpr void deallocate(Alloc& a, pointer p, size_type n); - - template - static constexpr void construct(Alloc& a, T* p, Args&&... args); - - template - static constexpr void destroy(Alloc& a, T* p); - - static constexpr size_type max_size(const Alloc& a) noexcept; - - static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs); - }; -} -\end{codeblock} - -\rSec3[allocator.traits.types]{Member types} - -\indexlibrarymember{pointer}{allocator_traits}% -\begin{itemdecl} -using pointer = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{Alloc::pointer} if -the \grammarterm{qualified-id} \tcode{Alloc::pointer} is valid and denotes a -type\iref{temp.deduct}; otherwise, \tcode{value_type*}. -\end{itemdescr} - -\indexlibrarymember{const_pointer}{allocator_traits}% -\begin{itemdecl} -using const_pointer = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{Alloc::const_pointer} if -the \grammarterm{qualified-id} \tcode{Alloc::const_pointer} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{pointer_traits::rebind<\brk{}const value_type>}. -\end{itemdescr} - -\indexlibrarymember{void_pointer}{allocator_traits}% -\begin{itemdecl} -using void_pointer = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{Alloc::void_pointer} if -the \grammarterm{qualified-id} \tcode{Alloc::void_pointer} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{pointer_traits::rebind<\brk{}void>}. -\end{itemdescr} - -\indexlibrarymember{const_void_pointer}{allocator_traits}% -\begin{itemdecl} -using const_void_pointer = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{Alloc::const_void_pointer} if -the \grammarterm{qualified-id} \tcode{Alloc::const_void_pointer} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{pointer_traits::\brk{}rebind}. -\end{itemdescr} - -\indexlibrarymember{difference_type}{allocator_traits}% -\begin{itemdecl} -using difference_type = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{Alloc::difference_type} if -the \grammarterm{qualified-id} \tcode{Alloc::difference_type} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{pointer_traits::dif\-ference_type}. -\end{itemdescr} - -\indexlibrarymember{size_type}{allocator_traits}% -\begin{itemdecl} -using size_type = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{Alloc::size_type} if -the \grammarterm{qualified-id} \tcode{Alloc::size_type} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{make_unsigned_t}. -\end{itemdescr} - -\indexlibrarymember{propagate_on_container_copy_assignment}{allocator_traits}% -\begin{itemdecl} -using propagate_on_container_copy_assignment = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{Alloc::propagate_on_container_copy_assignment} if -the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_copy_assignment} is valid and denotes a -type\iref{temp.deduct}; otherwise -\tcode{false_type}. -\end{itemdescr} - -\indexlibrarymember{propagate_on_container_move_assignment}{allocator_traits}% -\begin{itemdecl} -using propagate_on_container_move_assignment = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{Alloc::propagate_on_container_move_assignment} if -the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_move_assignment} is valid and denotes a -type\iref{temp.deduct}; otherwise -\tcode{false_type}. -\end{itemdescr} - -\indexlibrarymember{propagate_on_container_swap}{allocator_traits}% -\begin{itemdecl} -using propagate_on_container_swap = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{Alloc::propagate_on_container_swap} if -the \grammarterm{qualified-id} \tcode{Alloc::propagate_on_container_swap} is valid and denotes a -type\iref{temp.deduct}; otherwise -\tcode{false_type}. -\end{itemdescr} - -\indexlibrarymember{is_always_equal}{allocator_traits}% -\begin{itemdecl} -using is_always_equal = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{Alloc::is_always_equal} if -the \grammarterm{qualified-id} \tcode{Alloc::is_always_equal} -is valid and denotes a type\iref{temp.deduct}; -otherwise \tcode{is_empty::type}. -\end{itemdescr} - -\indexlibrarymember{rebind_alloc}{allocator_traits}% -\begin{itemdecl} -template using rebind_alloc = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\templalias \tcode{Alloc::rebind::other} if -the \grammarterm{qualified-id} \tcode{Alloc::rebind::other} is valid and denotes a -type\iref{temp.deduct}; otherwise, -\tcode{Alloc} if \tcode{Alloc} is a class template instantiation -of the form \tcode{Alloc}, where \tcode{Args} is zero or more type arguments; -otherwise, the instantiation of \tcode{rebind_alloc} is ill-formed. -\end{itemdescr} - -\rSec3[allocator.traits.members]{Static member functions} - -\indexlibrarymember{allocate}{allocator_traits}% -\begin{itemdecl} -[[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{a.allocate(n)}. -\end{itemdescr} - -\indexlibrarymember{allocate}{allocator_traits}% -\begin{itemdecl} -[[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{a.allocate(n, hint)} if that expression is well-formed; otherwise, \tcode{a.allocate(n)}. -\end{itemdescr} - -\indexlibrarymember{deallocate}{allocator_traits}% -\begin{itemdecl} -static constexpr void deallocate(Alloc& a, pointer p, size_type n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls \tcode{a.deallocate(p, n)}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{construct}{allocator_traits}% -\begin{itemdecl} -template - static constexpr void construct(Alloc& a, T* p, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls \tcode{a.construct(p, std::forward(args)...)} -if that call is well-formed; -otherwise, invokes \tcode{construct_at(p, std::forward(args)...)}. -\end{itemdescr} - -\indexlibrarymember{destroy}{allocator_traits}% -\begin{itemdecl} -template - static constexpr void destroy(Alloc& a, T* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls \tcode{a.destroy(p)} if that call is well-formed; otherwise, invokes -\tcode{destroy_at(p)}. -\end{itemdescr} - -\indexlibrarymember{max_size}{allocator_traits}% -\begin{itemdecl} -static constexpr size_type max_size(const Alloc& a) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{a.max_size()} if that expression is well-formed; otherwise, -\tcode{numeric_limits::\brk{}max()/sizeof(value_type)}. -\end{itemdescr} - -\indexlibrarymember{select_on_container_copy_construction}{allocator_traits}% -\begin{itemdecl} -static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{rhs.select_on_container_copy_construction()} if that expression is -well-formed; otherwise, \tcode{rhs}. -\end{itemdescr} - -\rSec3[allocator.traits.other]{Other} - -\pnum -The class template \tcode{allocation_result} has -the template parameters, data members, and special members specified above. -It has no base classes or members other than those specified. - -\begin{itemdecl} -template -[[nodiscard]] constexpr allocation_result::pointer> - allocate_at_least(Allocator& a, size_t n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{a.allocate_at_least(n)} if that expression is well-formed; -otherwise, \tcode{\{a.allocate(n), n\}}. -\end{itemdescr} - -\rSec2[default.allocator]{The default allocator} - -\rSec3[default.allocator.general]{General} - -\pnum -All specializations of the default allocator meet the -allocator completeness requirements\iref{allocator.requirements.completeness}. - -\indexlibraryglobal{allocator}% -\indexlibrarymember{value_type}{allocator}% -\indexlibrarymember{size_type}{allocator}% -\indexlibrarymember{difference_type}{allocator}% -\indexlibrarymember{propagate_on_container_move_assignment}{allocator}% -\indexlibrarymember{operator=}{allocator}% -\begin{codeblock} -namespace std { - template class allocator { - public: - using value_type = T; - using size_type = size_t; - using difference_type = ptrdiff_t; - using propagate_on_container_move_assignment = true_type; - - constexpr allocator() noexcept; - constexpr allocator(const allocator&) noexcept; - template constexpr allocator(const allocator&) noexcept; - constexpr ~allocator(); - constexpr allocator& operator=(const allocator&) = default; - - [[nodiscard]] constexpr T* allocate(size_t n); - [[nodiscard]] constexpr allocation_result allocate_at_least(size_t n); - constexpr void deallocate(T* p, size_t n); - }; -} -\end{codeblock} - -\pnum -\tcode{allocator_traits>::is_always_equal::value} -is \tcode{true} for any \tcode{T}. - -\rSec3[allocator.members]{Members} - -\pnum -Except for the destructor, member functions of the default allocator shall not introduce -data races\iref{intro.multithread} as a result of concurrent calls to those member -functions from different threads. Calls to these functions that allocate or deallocate a -particular unit of storage shall occur in a single total order, and each such -deallocation call shall happen before the next allocation (if any) in this order. - -\indexlibrarymember{allocate}{allocator}% -\begin{itemdecl} -[[nodiscard]] constexpr T* allocate(size_t n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{T} is not an incomplete type\iref{term.incomplete.type}. - -\pnum -\returns -A pointer to the initial element of an array of \tcode{n} \tcode{T}. - -\pnum -\throws -\tcode{bad_array_new_length} if -\tcode{numeric_limits::max() / sizeof(T) < n}, or -\tcode{bad_alloc} if the storage cannot be obtained. - -\pnum -\remarks -The storage for the array -is obtained by calling \tcode{::operator new}\iref{new.delete}, -but it is unspecified when or how often this -function is called. -This function starts the lifetime of the array object, -but not that of any of the array elements. -\end{itemdescr} - -\indexlibrarymember{allocate_at_least}{allocator}% -\begin{itemdecl} -[[nodiscard]] constexpr allocation_result allocate_at_least(size_t n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{T} is not an incomplete type\iref{term.incomplete.type}. - -\pnum -\returns -\tcode{allocation_result\{ptr, count\}}, -where \tcode{ptr} is a pointer to -the initial element of an array of \tcode{count} \tcode{T} and -$\tcode{count} \geq \tcode{n}$. - -\pnum -\throws -\tcode{bad_array_new_length} -if $\tcode{numeric_limits::max() / sizeof(T)} < \tcode{n}$, -or \tcode{bad_alloc} if the storage cannot be obtained. - -\pnum -\remarks -The storage for the array is obtained by calling \tcode{::operator new}, -but it is unspecified when or how often this function is called. -This function starts the lifetime of the array object, -but not that of any of the array elements. -\end{itemdescr} - -\indexlibrarymember{deallocate}{allocator}% -\begin{itemdecl} -constexpr void deallocate(T* p, size_t n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\begin{itemize} -\item -If \tcode{p} is memory that was obtained by a call to \tcode{allocate_at_least}, -let \tcode{ret} be the value returned and -\tcode{req} be the value passed as the first argument to that call. -\tcode{p} is equal to \tcode{ret.ptr} and -\tcode{n} is a value such that $\tcode{req} \leq \tcode{n} \leq \tcode{ret.count}$. -\item -Otherwise, \tcode{p} is a pointer value obtained from \tcode{allocate}. -\tcode{n} equals the value passed as the first argument -to the invocation of \tcode{allocate} which returned \tcode{p}. -\end{itemize} - -\pnum -\effects -Deallocates the storage referenced by \tcode{p}. - -\pnum -\remarks -Uses -\tcode{::operator delete}\iref{new.delete}, -but it is unspecified -when this function is called. -\end{itemdescr} - -\rSec3[allocator.globals]{Operators} - -\indexlibrarymember{operator==}{allocator}% -\begin{itemdecl} -template - constexpr bool operator==(const allocator&, const allocator&) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true}. -\end{itemdescr} - -\rSec2[specialized.addressof]{\tcode{addressof}} - -\indexlibraryglobal{addressof}% -\begin{itemdecl} -template constexpr T* addressof(T& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The actual address of the object or function referenced by \tcode{r}, even in the -presence of an overloaded \tcode{operator\&}. - -\pnum -\remarks -An expression \tcode{addressof(E)} -is a constant subexpression\iref{defns.const.subexpr} -if \tcode{E} is an lvalue constant subexpression. -\end{itemdescr} - -\rSec2[c.malloc]{C library memory allocation} - -\pnum -\begin{note} -The header \libheaderref{cstdlib} -declares the functions described in this subclause. -\end{note} - -\indexlibraryglobal{aligned_alloc}% -\indexlibraryglobal{calloc}% -\indexlibraryglobal{malloc}% -\indexlibraryglobal{realloc}% -\begin{itemdecl} -void* aligned_alloc(size_t alignment, size_t size); -void* calloc(size_t nmemb, size_t size); -void* malloc(size_t size); -void* realloc(void* ptr, size_t size); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -These functions have the semantics specified in the C standard library. - -\pnum -\remarks -These functions do not attempt to allocate -storage by calling \tcode{::operator new()}\iref{new.delete}. -\indexlibrarymember{new}{operator}% - -\pnum -These functions implicitly create objects\iref{intro.object} -in the returned region of storage and -return a pointer to a suitable created object. -In the case of \tcode{calloc} and \tcode{realloc}, -the objects are created before the storage is zeroed or copied, respectively. -\end{itemdescr} - -\indexlibraryglobal{free}% -\begin{itemdecl} -void free(void* ptr); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -This function has the semantics specified in the C standard library. - -\pnum -\remarks -This function does not attempt to -deallocate storage by calling -\tcode{::operator delete()}\indexlibrarymember{delete}{operator}. -\end{itemdescr} - -\xrefc{7.22.3} - -\rSec1[smartptr]{Smart pointers} - -\rSec2[unique.ptr]{Unique-ownership pointers} - -\rSec3[unique.ptr.general]{General} - -\pnum -A \defn{unique pointer} is an object that owns another object and -manages that other object through a pointer. More precisely, a unique pointer -is an object \textit{u} that stores a pointer to a second object \textit{p} and -will dispose of \textit{p} when \textit{u} is itself destroyed (e.g., when -leaving block scope\iref{stmt.dcl}). In this context, \textit{u} is said -to \defn{own} \tcode{p}. - -\pnum -The mechanism by which \textit{u} disposes of \textit{p} is known as -\textit{p}'s associated \defn{deleter}, a function object whose correct -invocation results in \textit{p}'s appropriate disposition (typically its deletion). - -\pnum -Let the notation \textit{u.p} denote the pointer stored by \textit{u}, and -let \textit{u.d} denote the associated deleter. Upon request, \textit{u} can -\defn{reset} (replace) \textit{u.p} and \textit{u.d} with another pointer and -deleter, but properly disposes of its owned object via the associated -deleter before such replacement is considered completed. - -\pnum -Each object of a type \tcode{U} instantiated from the \tcode{unique_ptr} template -specified in \ref{unique.ptr} has the strict ownership semantics, specified above, -of a unique pointer. In partial satisfaction of these semantics, each such \tcode{U} -is \oldconcept{MoveConstructible} and \oldconcept{MoveAssignable}, but is not -\oldconcept{CopyConstructible} nor \oldconcept{CopyAssignable}. -The template parameter \tcode{T} of \tcode{unique_ptr} may be an incomplete type. - -\pnum -\begin{note} -The uses -of \tcode{unique_ptr} include providing exception safety for -dynamically allocated memory, passing ownership of dynamically allocated -memory to a function, and returning dynamically allocated memory from a -function. -\end{note} - -\rSec3[unique.ptr.dltr]{Default deleters} - -\rSec4[unique.ptr.dltr.general]{In general} - -\pnum -The class template \tcode{default_delete} serves as the default deleter (destruction policy) -for the class template \tcode{unique_ptr}. - -\pnum -The template parameter \tcode{T} of \tcode{default_delete} may be -an incomplete type. - -\rSec4[unique.ptr.dltr.dflt]{\tcode{default_delete}} - -\begin{codeblock} -namespace std { - template struct default_delete { - constexpr default_delete() noexcept = default; - template constexpr default_delete(const default_delete&) noexcept; - constexpr void operator()(T*) const; - }; -} -\end{codeblock} - -\indexlibraryctor{default_delete}% -\begin{itemdecl} -template constexpr default_delete(const default_delete& other) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{U*} is implicitly convertible to \tcode{T*}. - -\pnum -\effects -Constructs a \tcode{default_delete} object -from another \tcode{default_delete} object. -\end{itemdescr} - -\indexlibrarymember{operator()}{default_delete}% -\begin{itemdecl} -constexpr void operator()(T* ptr) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{T} is a complete type. - -\pnum -\effects -Calls \keyword{delete} on \tcode{ptr}. -\end{itemdescr} - -\rSec4[unique.ptr.dltr.dflt1]{\tcode{default_delete}} - -\begin{codeblock} -namespace std { - template struct default_delete { - constexpr default_delete() noexcept = default; - template constexpr default_delete(const default_delete&) noexcept; - template constexpr void operator()(U* ptr) const; - }; -} -\end{codeblock} - -\indexlibraryctor{default_delete} -\begin{itemdecl} -template constexpr default_delete(const default_delete& other) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{U(*)[]} is convertible to \tcode{T(*)[]}. - -\pnum -\effects -Constructs a \tcode{default_delete} object from another \tcode{default_delete} object. -\end{itemdescr} - -\indexlibrarymember{operator()}{default_delete}% -\begin{itemdecl} -template constexpr void operator()(U* ptr) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{U(*)[]} is convertible to \tcode{T(*)[]}. - -\pnum -\mandates -\tcode{U} is a complete type. - -\pnum -\effects -Calls \tcode{delete[]} on \tcode{ptr}. -\end{itemdescr} - -\rSec3[unique.ptr.single]{\tcode{unique_ptr} for single objects} - -\rSec4[unique.ptr.single.general]{General} - -\indexlibraryglobal{unique_ptr}% -\begin{codeblock} -namespace std { - template> class unique_ptr { - public: - using pointer = @\seebelow@; - using element_type = T; - using deleter_type = D; - - // \ref{unique.ptr.single.ctor}, constructors - constexpr unique_ptr() noexcept; - constexpr explicit unique_ptr(type_identity_t p) noexcept; - constexpr unique_ptr(type_identity_t p, @\seebelow@ d1) noexcept; - constexpr unique_ptr(type_identity_t p, @\seebelow@ d2) noexcept; - constexpr unique_ptr(unique_ptr&& u) noexcept; - constexpr unique_ptr(nullptr_t) noexcept; - template - constexpr unique_ptr(unique_ptr&& u) noexcept; - - // \ref{unique.ptr.single.dtor}, destructor - constexpr ~unique_ptr(); - - // \ref{unique.ptr.single.asgn}, assignment - constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; - template - constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; - constexpr unique_ptr& operator=(nullptr_t) noexcept; - - // \ref{unique.ptr.single.observers}, observers - constexpr add_lvalue_reference_t operator*() const noexcept(@\seebelow@); - constexpr pointer operator->() const noexcept; - constexpr pointer get() const noexcept; - constexpr deleter_type& get_deleter() noexcept; - constexpr const deleter_type& get_deleter() const noexcept; - constexpr explicit operator bool() const noexcept; - - // \ref{unique.ptr.single.modifiers}, modifiers - constexpr pointer release() noexcept; - constexpr void reset(pointer p = pointer()) noexcept; - constexpr void swap(unique_ptr& u) noexcept; - - // disable copy from lvalue - unique_ptr(const unique_ptr&) = delete; - unique_ptr& operator=(const unique_ptr&) = delete; - }; -} -\end{codeblock} - -\pnum -The default type for the template parameter \tcode{D} is -\tcode{default_delete}. A client-supplied template argument -\tcode{D} shall be a function -object type\iref{function.objects}, lvalue reference to function, or -lvalue reference to function object type -for which, given -a value \tcode{d} of type \tcode{D} and a value -\tcode{ptr} of type \tcode{unique_ptr::pointer}, the expression -\tcode{d(ptr)} is valid and has the effect of disposing of the -pointer as appropriate for that deleter. - -\pnum -If the deleter's type \tcode{D} is not a reference type, \tcode{D} shall meet -the \oldconcept{Destructible} requirements (\tref{cpp17.destructible}). - -\pnum -If the \grammarterm{qualified-id} \tcode{remove_reference_t::pointer} is valid and denotes a -type\iref{temp.deduct}, then \tcode{unique_ptr::pointer} shall be a synonym for \tcode{remove_reference_t::pointer}. Otherwise -\tcode{unique_ptr::pointer} shall be a synonym for \tcode{element_type*}. The type \tcode{unique_ptr::pointer} shall -meet the \oldconcept{NullablePointer} requirements (\tref{cpp17.nullablepointer}). - -\pnum -\begin{example} -Given an allocator type \tcode{X} (\tref{cpp17.allocator}) and -letting \tcode{A} be a synonym for \tcode{allocator_traits}, the types \tcode{A::pointer}, -\tcode{A::const_pointer}, \tcode{A::void_pointer}, and \tcode{A::const_void_pointer} -may be used as \tcode{unique_ptr::pointer}. -\end{example} - -\rSec4[unique.ptr.single.ctor]{Constructors} - -\indexlibraryctor{unique_ptr}% -\begin{itemdecl} -constexpr unique_ptr() noexcept; -constexpr unique_ptr(nullptr_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_pointer_v} is \tcode{false} and -\tcode{is_default_constructible_v} is \tcode{true}. - -\pnum -\expects -\tcode{D} meets the \oldconcept{DefaultConstructible} requirements (\tref{cpp17.defaultconstructible}), -and that construction does not throw an exception. - -\pnum -\effects -Constructs a \tcode{unique_ptr} object that owns -nothing, value-initializing the stored pointer and the stored deleter. - -\pnum -\ensures -\tcode{get() == nullptr}. \tcode{get_deleter()} -returns a reference to the stored deleter. -\end{itemdescr} - -\indexlibraryctor{unique_ptr}% -\begin{itemdecl} -constexpr explicit unique_ptr(type_identity_t p) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_pointer_v} is \tcode{false} and -\tcode{is_default_constructible_v} is \tcode{true}. - -\pnum -\expects -\tcode{D} meets the \oldconcept{DefaultConstructible} requirements (\tref{cpp17.defaultconstructible}), -and that construction does not throw an exception. - -\pnum -\effects -Constructs a \tcode{unique_ptr} which owns -\tcode{p}, initializing the stored pointer with \tcode{p} and -value-initializing the stored deleter. - -\pnum -\ensures -\tcode{get() == p}. \tcode{get_deleter()} -returns a reference to the stored deleter. -\end{itemdescr} - -\indexlibraryctor{unique_ptr}% -\begin{itemdecl} -constexpr unique_ptr(type_identity_t p, const D& d) noexcept; -constexpr unique_ptr(type_identity_t p, remove_reference_t&& d) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. - -\pnum -\expects -For the first constructor, if \tcode{D} is not a reference type, -\tcode{D} meets the \oldconcept{CopyConstructible} requirements and -such construction does not exit via an exception. -For the second constructor, if \tcode{D} is not a reference type, -\tcode{D} meets the \oldconcept{MoveConstructible} requirements and -such construction does not exit via an exception. - -\pnum -\effects -Constructs a \tcode{unique_ptr} object which owns \tcode{p}, initializing -the stored pointer with \tcode{p} and initializing the deleter -from \tcode{std::forward(d)}. - -\pnum -\ensures -\tcode{get() == p}. -\tcode{get_deleter()} returns a reference to the stored -deleter. If \tcode{D} is a reference type then \tcode{get_deleter()} -returns a reference to the lvalue \tcode{d}. - -\pnum -\remarks -If \tcode{D} is a reference type, -the second constructor is defined as deleted. - -\pnum -\begin{example} -\begin{codeblock} -D d; -unique_ptr p1(new int, D()); // \tcode{D} must be \oldconcept{MoveConstructible} -unique_ptr p2(new int, d); // \tcode{D} must be \oldconcept{CopyConstructible} -unique_ptr p3(new int, d); // \tcode{p3} holds a reference to \tcode{d} -unique_ptr p4(new int, D()); // error: rvalue deleter object combined - // with reference deleter type -\end{codeblock} -\end{example} -\end{itemdescr} - -\indexlibraryctor{unique_ptr}% -\begin{itemdecl} -constexpr unique_ptr(unique_ptr&& u) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_move_constructible_v} is \tcode{true}. - -\pnum -\expects -If \tcode{D} is not a reference type, -\tcode{D} meets the \oldconcept{MoveConstructible} -requirements (\tref{cpp17.moveconstructible}). -Construction -of the deleter from an rvalue of type \tcode{D} does not -throw an exception. - -\pnum -\effects -Constructs a \tcode{unique_ptr} from -\tcode{u}. If \tcode{D} is a reference type, this -deleter is copy constructed from \tcode{u}'s deleter; otherwise, this -deleter is move constructed from \tcode{u}'s deleter. -\begin{note} -The -construction of the deleter can be implemented with \tcode{std::forward}. -\end{note} - -\pnum -\ensures -\tcode{get()} yields the value \tcode{u.get()} -yielded before the construction. \tcode{u.get() == nullptr}. -\tcode{get_deleter()} returns a reference -to the stored deleter that was constructed from -\tcode{u.get_deleter()}. If \tcode{D} is a reference type then -\tcode{get_deleter()} and \tcode{u.get_deleter()} both reference -the same lvalue deleter. -\end{itemdescr} - -\indexlibraryctor{unique_ptr}% -\begin{itemdecl} -template constexpr unique_ptr(unique_ptr&& u) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\begin{itemize} -\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{pointer}, -\item \tcode{U} is not an array type, and -\item either \tcode{D} is a reference type and \tcode{E} is the same type as \tcode{D}, or -\tcode{D} is not a reference type and \tcode{E} is implicitly convertible to \tcode{D}. -\end{itemize} - -\pnum -\expects -If \tcode{E} is not a reference type, -construction of the deleter from an rvalue of type \tcode{E} -is well-formed and does not throw an exception. -Otherwise, \tcode{E} is a reference type and -construction of the deleter from an lvalue of type \tcode{E} -is well-formed and does not throw an exception. - -\pnum -\effects -Constructs a \tcode{unique_ptr} from \tcode{u}. -If \tcode{E} is a reference type, this deleter is copy constructed from -\tcode{u}'s deleter; otherwise, this deleter is move constructed from \tcode{u}'s -deleter. -\begin{note} -The deleter constructor can be implemented with -\tcode{std::forward}. -\end{note} - -\pnum -\ensures -\tcode{get()} yields the value \tcode{u.get()} -yielded before the construction. \tcode{u.get() == nullptr}. -\tcode{get_deleter()} returns a reference -to the stored deleter that was constructed from -\tcode{u.get_deleter()}. -\end{itemdescr} - -\rSec4[unique.ptr.single.dtor]{Destructor} - -\indexlibrarydtor{unique_ptr}% -\begin{itemdecl} -constexpr ~unique_ptr(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\tcode{if (get()) get_deleter()(get());} -\begin{note} -The use of \tcode{default_delete} requires \tcode{T} to be a complete type. -\end{note} - -\pnum -\remarks -The behavior is undefined -if the evaluation of \tcode{get_deleter()(get())} throws an exception. -\end{itemdescr} - -\rSec4[unique.ptr.single.asgn]{Assignment} - -\indexlibrarymember{operator=}{unique_ptr}% -\begin{itemdecl} -constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_move_assignable_v} is \tcode{true}. - -\pnum -\expects -If \tcode{D} is not a reference type, \tcode{D} meets the -\oldconcept{MoveAssignable} requirements (\tref{cpp17.moveassignable}) and assignment -of the deleter from an rvalue of type \tcode{D} does not throw an exception. -Otherwise, \tcode{D} is a reference type; -\tcode{remove_reference_t} meets the \oldconcept{CopyAssignable} -requirements and assignment of the deleter from an -lvalue of type \tcode{D} does not throw an exception. - -\pnum -\effects -Calls \tcode{reset(u.release())} followed by -\tcode{get_deleter() = std::forward(u.get_dele\-ter())}. - -\pnum -\ensures -If \tcode{this != addressof(u)}, -\tcode{u.get() == nullptr}, -otherwise \tcode{u.get()} is unchanged. - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{operator=}{unique_ptr}% -\begin{itemdecl} -template constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\begin{itemize} -\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{pointer}, and -\item \tcode{U} is not an array type, and -\item \tcode{is_assignable_v} is \tcode{true}. -\end{itemize} - -\pnum -\expects -If \tcode{E} is not a reference type, -assignment of the deleter from an rvalue of type \tcode{E} -is well-formed and does not throw an exception. -Otherwise, \tcode{E} is a reference type and -assignment of the deleter from an lvalue of type \tcode{E} -is well-formed and does not throw an exception. - -\pnum -\effects -Calls \tcode{reset(u.release())} followed by -\tcode{get_deleter() = std::forward(u.get_dele\-ter())}. - -\pnum -\ensures -\tcode{u.get() == nullptr}. - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{operator=}{unique_ptr}% -\begin{itemdecl} -constexpr unique_ptr& operator=(nullptr_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by \tcode{reset()}. - -\pnum -\ensures -\tcode{get() == nullptr}. - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\rSec4[unique.ptr.single.observers]{Observers} - -\indexlibrarymember{operator*}{unique_ptr}% -\begin{itemdecl} -constexpr add_lvalue_reference_t operator*() const noexcept(noexcept(*declval())); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{get() != nullptr}. - -\pnum -\returns -\tcode{*get()}. - -\end{itemdescr} - -\indexlibrarymember{operator->}{unique_ptr}% -\begin{itemdecl} -constexpr pointer operator->() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{get() != nullptr}. - -\pnum -\returns -\tcode{get()}. - -\pnum -\begin{note} -The use of this function typically requires that \tcode{T} be a complete type. -\end{note} -\end{itemdescr} - -\indexlibrarymember{get}{unique_ptr}% -\begin{itemdecl} -constexpr pointer get() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The stored pointer. -\end{itemdescr} - -\indexlibrarymember{get_deleter}{unique_ptr}% -\begin{itemdecl} -constexpr deleter_type& get_deleter() noexcept; -constexpr const deleter_type& get_deleter() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A reference to the stored deleter. -\end{itemdescr} - -\indexlibrarymember{operator bool}{unique_ptr}% -\begin{itemdecl} -constexpr explicit operator bool() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{get() != nullptr}. -\end{itemdescr} - -\rSec4[unique.ptr.single.modifiers]{Modifiers} - -\indexlibrarymember{release}{unique_ptr}% -\begin{itemdecl} -constexpr pointer release() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{get() == nullptr}. - -\pnum -\returns -The value \tcode{get()} had at the start of -the call to \tcode{release}. -\end{itemdescr} - -\indexlibrarymember{reset}{unique_ptr}% -\begin{itemdecl} -constexpr void reset(pointer p = pointer()) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Assigns \tcode{p} to the stored pointer, and then, -with the old value of the stored pointer, \tcode{old_p}, -evaluates \tcode{if (old_p) get_deleter()(old_p);} -\begin{note} -The order of these operations is significant -because the call to \tcode{get_deleter()} might destroy \tcode{*this}. -\end{note} - -\pnum -\ensures -\tcode{get() == p}. -\begin{note} -The postcondition does not hold if the call to \tcode{get_deleter()} -destroys \tcode{*this} since \tcode{this->get()} is no longer a valid expression. -\end{note} - -\pnum -\remarks -The behavior is undefined -if the evaluation of \tcode{get_deleter()(old_p)} throws an exception. -\end{itemdescr} - -\indexlibrarymember{swap}{unique_ptr}% -\begin{itemdecl} -constexpr void swap(unique_ptr& u) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{get_deleter()} is swappable\iref{swappable.requirements} and -does not throw an exception under \tcode{swap}. - -\pnum -\effects -Invokes \tcode{swap} on the stored pointers and on the stored -deleters of \tcode{*this} and \tcode{u}. -\end{itemdescr} - -\rSec3[unique.ptr.runtime]{\tcode{unique_ptr} for array objects with a runtime length} - -\rSec4[unique.ptr.runtime.general]{General} - -\indexlibraryglobal{unique_ptr}% -\begin{codeblock} -namespace std { - template class unique_ptr { - public: - using pointer = @\seebelow@; - using element_type = T; - using deleter_type = D; - - // \ref{unique.ptr.runtime.ctor}, constructors - constexpr unique_ptr() noexcept; - template constexpr explicit unique_ptr(U p) noexcept; - template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; - template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; - constexpr unique_ptr(unique_ptr&& u) noexcept; - template - constexpr unique_ptr(unique_ptr&& u) noexcept; - constexpr unique_ptr(nullptr_t) noexcept; - - // destructor - constexpr ~unique_ptr(); - - // assignment - constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; - template - constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; - constexpr unique_ptr& operator=(nullptr_t) noexcept; - - // \ref{unique.ptr.runtime.observers}, observers - constexpr T& operator[](size_t i) const; - constexpr pointer get() const noexcept; - constexpr deleter_type& get_deleter() noexcept; - constexpr const deleter_type& get_deleter() const noexcept; - constexpr explicit operator bool() const noexcept; - - // \ref{unique.ptr.runtime.modifiers}, modifiers - constexpr pointer release() noexcept; - template constexpr void reset(U p) noexcept; - constexpr void reset(nullptr_t = nullptr) noexcept; - constexpr void swap(unique_ptr& u) noexcept; - - // disable copy from lvalue - unique_ptr(const unique_ptr&) = delete; - unique_ptr& operator=(const unique_ptr&) = delete; - }; -} -\end{codeblock} - -\pnum -A specialization for array types is provided with a slightly altered -interface. - -\begin{itemize} -\item Conversions between different types of -\tcode{unique_ptr} -that would be disallowed for the corresponding pointer-to-array types, -and conversions to or from the non-array forms of -\tcode{unique_ptr}, produce an ill-formed program. - -\item Pointers to types derived from \tcode{T} are -rejected by the constructors, and by \tcode{reset}. - -\item The observers \tcode{operator*} and -\tcode{operator->} are not provided. - -\item The indexing observer \tcode{operator[]} is provided. - -\item The default deleter will call \tcode{delete[]}. -\end{itemize} - -\pnum -Descriptions are provided below only for members that -differ from the primary template. - -\pnum -The template argument \tcode{T} shall be a complete type. - -\rSec4[unique.ptr.runtime.ctor]{Constructors} - -\indexlibraryctor{unique_ptr}% -\begin{itemdecl} -template constexpr explicit unique_ptr(U p) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -This constructor behaves the same as -the constructor in the primary template that -takes a single parameter of type \tcode{pointer}. - -\pnum -\constraints -\begin{itemize} -\item \tcode{U} is the same type as \tcode{pointer}, or -\item \tcode{pointer} is the same type as \tcode{element_type*}, -\tcode{U} is a pointer type \tcode{V*}, and -\tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}. -\end{itemize} -\end{itemdescr} - -\indexlibraryctor{unique_ptr}% -\begin{itemdecl} -template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; -template constexpr unique_ptr(U p, @\seebelow@ d) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -These constructors behave the same as -the constructors in the primary template that -take a parameter of type \tcode{pointer} and a second parameter. - -\pnum -\constraints -\begin{itemize} -\item \tcode{U} is the same type as \tcode{pointer}, -\item \tcode{U} is \tcode{nullptr_t}, or -\item \tcode{pointer} is the same type as \tcode{element_type*}, - \tcode{U} is a pointer type \tcode{V*}, and - \tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}. -\end{itemize} -\end{itemdescr} - -\indexlibraryctor{unique_ptr}% -\begin{itemdecl} -template constexpr unique_ptr(unique_ptr&& u) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -This constructor behaves the same as in the primary template. - -\pnum -\constraints -Where \tcode{UP} is \tcode{unique_ptr}: -\begin{itemize} -\item \tcode{U} is an array type, and -\item \tcode{pointer} is the same type as \tcode{element_type*}, and -\item \tcode{UP::pointer} is the same type as \tcode{UP::element_type*}, and -\item \tcode{UP::element_type(*)[]} is convertible to \tcode{element_type(*)[]}, and -\item either \tcode{D} is a reference type and \tcode{E} is the same type as \tcode{D}, - or \tcode{D} is not a reference type and \tcode{E} is implicitly convertible to \tcode{D}. -\end{itemize} - -\begin{note} -This replaces the \constraints specification of the primary template. -\end{note} -\end{itemdescr} - -\rSec4[unique.ptr.runtime.asgn]{Assignment} - -\indexlibrarymember{operator=}{unique_ptr}% -\begin{itemdecl} -template constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -This operator behaves the same as in the primary template. - -\pnum -\constraints -Where \tcode{UP} is \tcode{unique_ptr}: -\begin{itemize} -\item \tcode{U} is an array type, and -\item \tcode{pointer} is the same type as \tcode{element_type*}, and -\item \tcode{UP::pointer} is the same type as \tcode{UP::element_type*}, and -\item \tcode{UP::element_type(*)[]} is convertible to \tcode{element_type(*)[]}, and -\item \tcode{is_assignable_v} is \tcode{true}. -\end{itemize} - -\begin{note} -This replaces the \constraints specification of the primary template. -\end{note} -\end{itemdescr} - -\rSec4[unique.ptr.runtime.observers]{Observers} - -\indexlibrarymember{operator[]}{unique_ptr}% -\begin{itemdecl} -constexpr T& operator[](size_t i) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -$\tcode{i} <$ the -number of elements in the array to which -the stored pointer points. - -\pnum -\returns -\tcode{get()[i]}. -\end{itemdescr} - -\rSec4[unique.ptr.runtime.modifiers]{Modifiers} - -\indexlibrarymember{reset}{unique_ptr}% -\begin{itemdecl} -constexpr void reset(nullptr_t p = nullptr) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{reset(pointer())}. -\end{itemdescr} - -\indexlibrarymember{reset}{unique_ptr}% -\begin{itemdecl} -constexpr template void reset(U p) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -This function behaves the same as -the \tcode{reset} member of the primary template. - -\pnum -\constraints -\begin{itemize} -\item \tcode{U} is the same type as \tcode{pointer}, or -\item \tcode{pointer} is the same type as \tcode{element_type*}, - \tcode{U} is a pointer type \tcode{V*}, and - \tcode{V(*)[]} is convertible to \tcode{element_type(*)[]}. -\end{itemize} -\end{itemdescr} - -\rSec3[unique.ptr.create]{Creation} - -\indexlibraryglobal{make_unique}% -\begin{itemdecl} -template constexpr unique_ptr make_unique(Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is not an array type. - -\pnum -\returns -\tcode{unique_ptr(new T(std::forward(args)...))}. - -\end{itemdescr} - -\indexlibraryglobal{make_unique}% -\begin{itemdecl} -template constexpr unique_ptr make_unique(size_t n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an array of unknown bound. - -\pnum -\returns -\tcode{unique_ptr(new remove_extent_t[n]())}. - -\end{itemdescr} - -\indexlibraryglobal{make_unique}% -\begin{itemdecl} -template @\unspec@ make_unique(Args&&...) = delete; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an array of known bound. - -\end{itemdescr} - -\indexlibraryglobal{make_unique}% -\begin{itemdecl} -template constexpr unique_ptr make_unique_for_overwrite(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is not an array type. - -\pnum -\returns -\tcode{unique_ptr(new T)}. -\end{itemdescr} - -\indexlibraryglobal{make_unique}% -\begin{itemdecl} -template constexpr unique_ptr make_unique_for_overwrite(size_t n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an array of unknown bound. - -\pnum -\returns -\tcode{unique_ptr(new remove_extent_t[n])}. -\end{itemdescr} - -\indexlibraryglobal{make_unique}% -\begin{itemdecl} -template @\unspec@ make_unique_for_overwrite(Args&&...) = delete; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an array of known bound. -\end{itemdescr} - -\rSec3[unique.ptr.special]{Specialized algorithms} - -\indexlibrary{\idxcode{swap(unique_ptr\&, unique_ptr\&)}}% -\begin{itemdecl} -template constexpr void swap(unique_ptr& x, unique_ptr& y) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_swappable_v} is \tcode{true}. - -\pnum -\effects -Calls \tcode{x.swap(y)}. -\end{itemdescr} - -\indexlibrarymember{operator==}{unique_ptr}% -\begin{itemdecl} -template - constexpr bool operator==(const unique_ptr& x, const unique_ptr& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x.get() == y.get()}. -\end{itemdescr} - -\indexlibrarymember{operator<}{unique_ptr}% -\begin{itemdecl} -template - bool operator<(const unique_ptr& x, const unique_ptr& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{CT} denote -\begin{codeblock} -common_type_t::pointer, - typename unique_ptr::pointer> -\end{codeblock} - -\pnum -\mandates -\begin{itemize} -\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{CT} and -\item \tcode{unique_ptr::pointer} is implicitly convertible to \tcode{CT}. -\end{itemize} - -\pnum -\expects -The specialization -\tcode{less} is a function object type\iref{function.objects} that -induces a strict weak ordering\iref{alg.sorting} on the pointer values. - -\pnum -\returns -\tcode{less()(x.get(), y.get())}. -\end{itemdescr} - -\indexlibrarymember{operator>}{unique_ptr}% -\begin{itemdecl} -template - bool operator>(const unique_ptr& x, const unique_ptr& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{y < x}. -\end{itemdescr} - -\indexlibrarymember{operator<=}{unique_ptr}% -\begin{itemdecl} -template - bool operator<=(const unique_ptr& x, const unique_ptr& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{!(y < x)}. -\end{itemdescr} - -\indexlibrarymember{operator>=}{unique_ptr}% -\begin{itemdecl} -template - bool operator>=(const unique_ptr& x, const unique_ptr& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{!(x < y)}. -\end{itemdescr} - -\indexlibrarymember{operator<=>}{unique_ptr}% -\begin{itemdecl} -template - requires @\libconcept{three_way_comparable_with}@::pointer, - typename unique_ptr::pointer> - compare_three_way_result_t::pointer, - typename unique_ptr::pointer> - operator<=>(const unique_ptr& x, const unique_ptr& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{compare_three_way()(x.get(), y.get())}. -\end{itemdescr} - -\indexlibrarymember{operator==}{unique_ptr}% -\begin{itemdecl} -template - constexpr bool operator==(const unique_ptr& x, nullptr_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{!x}. -\end{itemdescr} - -\indexlibrarymember{operator<}{unique_ptr}% -\begin{itemdecl} -template - constexpr bool operator<(const unique_ptr& x, nullptr_t); -template - constexpr bool operator<(nullptr_t, const unique_ptr& x); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The specialization \tcode{less::pointer>} is -a function object type\iref{function.objects} that induces a strict weak -ordering\iref{alg.sorting} on the pointer values. - -\pnum -\returns -The first function template returns -\begin{codeblock} -less::pointer>()(x.get(), nullptr) -\end{codeblock} -The second function template returns -\begin{codeblock} -less::pointer>()(nullptr, x.get()) -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{operator>}{unique_ptr}% -\begin{itemdecl} -template - constexpr bool operator>(const unique_ptr& x, nullptr_t); -template - constexpr bool operator>(nullptr_t, const unique_ptr& x); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The first function template returns \tcode{nullptr < x}. -The second function template returns \tcode{x < nullptr}. -\end{itemdescr} - -\indexlibrarymember{operator<=}{unique_ptr}% -\begin{itemdecl} -template - constexpr bool operator<=(const unique_ptr& x, nullptr_t); -template - constexpr bool operator<=(nullptr_t, const unique_ptr& x); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The first function template returns \tcode{!(nullptr < x)}. -The second function template returns \tcode{!(x < nullptr)}. -\end{itemdescr} - -\indexlibrarymember{operator>=}{unique_ptr}% -\begin{itemdecl} -template - constexpr bool operator>=(const unique_ptr& x, nullptr_t); -template - constexpr bool operator>=(nullptr_t, const unique_ptr& x); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The first function template returns \tcode{!(x < nullptr)}. -The second function template returns \tcode{!(nullptr < x)}. -\end{itemdescr} - -\indexlibrarymember{operator<=>}{unique_ptr}% -\begin{itemdecl} -template - requires @\libconcept{three_way_comparable}@::pointer> - constexpr compare_three_way_result_t::pointer> - operator<=>(const unique_ptr& x, nullptr_t); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\begin{codeblock} -compare_three_way()(x.get(), static_cast::pointer>(nullptr)). -\end{codeblock} -\end{itemdescr} - -\rSec3[unique.ptr.io]{I/O} - -\indexlibrarymember{operator<<}{unique_ptr}% -\begin{itemdecl} -template - basic_ostream& operator<<(basic_ostream& os, const unique_ptr& p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{os << p.get()} is a valid expression. - -\pnum -\effects -Equivalent to: \tcode{os << p.get();} - -\pnum -\returns -\tcode{os}. -\end{itemdescr} - -\rSec2[util.sharedptr]{Shared-ownership pointers} - -\rSec3[util.smartptr.weak.bad]{Class \tcode{bad_weak_ptr}}% -\indextext{smart pointers|(}% - -\indexlibraryglobal{bad_weak_ptr}% -\begin{codeblock} -namespace std { - class bad_weak_ptr : public exception { - public: - // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; - }; -} -\end{codeblock} - -\pnum -An exception of type \tcode{bad_weak_ptr} is thrown by the \tcode{shared_ptr} -constructor taking a \tcode{weak_ptr}. - -\indexlibrarymember{what}{bad_weak_ptr}% -\begin{itemdecl} -const char* what() const noexcept override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -An \impldef{return value of \tcode{bad_weak_ptr::what}} \ntbs{}. -\end{itemdescr} - -\rSec3[util.smartptr.shared]{Class template \tcode{shared_ptr}} - -\rSec4[util.smartptr.shared.general]{General} - -\pnum -\indexlibraryglobal{shared_ptr}% -The \tcode{shared_ptr} class template stores a pointer, usually obtained -via \keyword{new}. \tcode{shared_ptr} implements semantics of shared ownership; -the last remaining owner of the pointer is responsible for destroying -the object, or otherwise releasing the resources associated with the stored pointer. A -\tcode{shared_ptr} is said to be empty if it does not own a pointer. - -\begin{codeblock} -namespace std { - template class shared_ptr { - public: - using element_type = remove_extent_t; - using weak_type = weak_ptr; - - // \ref{util.smartptr.shared.const}, constructors - constexpr shared_ptr() noexcept; - constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { } - template - explicit shared_ptr(Y* p); - template - shared_ptr(Y* p, D d); - template - shared_ptr(Y* p, D d, A a); - template - shared_ptr(nullptr_t p, D d); - template - shared_ptr(nullptr_t p, D d, A a); - template - shared_ptr(const shared_ptr& r, element_type* p) noexcept; - template - shared_ptr(shared_ptr&& r, element_type* p) noexcept; - shared_ptr(const shared_ptr& r) noexcept; - template - shared_ptr(const shared_ptr& r) noexcept; - shared_ptr(shared_ptr&& r) noexcept; - template - shared_ptr(shared_ptr&& r) noexcept; - template - explicit shared_ptr(const weak_ptr& r); - template - shared_ptr(unique_ptr&& r); - - // \ref{util.smartptr.shared.dest}, destructor - ~shared_ptr(); - - // \ref{util.smartptr.shared.assign}, assignment - shared_ptr& operator=(const shared_ptr& r) noexcept; - template - shared_ptr& operator=(const shared_ptr& r) noexcept; - shared_ptr& operator=(shared_ptr&& r) noexcept; - template - shared_ptr& operator=(shared_ptr&& r) noexcept; - template - shared_ptr& operator=(unique_ptr&& r); - - // \ref{util.smartptr.shared.mod}, modifiers - void swap(shared_ptr& r) noexcept; - void reset() noexcept; - template - void reset(Y* p); - template - void reset(Y* p, D d); - template - void reset(Y* p, D d, A a); - - // \ref{util.smartptr.shared.obs}, observers - element_type* get() const noexcept; - T& operator*() const noexcept; - T* operator->() const noexcept; - element_type& operator[](ptrdiff_t i) const; - long use_count() const noexcept; - explicit operator bool() const noexcept; - template - bool owner_before(const shared_ptr& b) const noexcept; - template - bool owner_before(const weak_ptr& b) const noexcept; - }; - - template - shared_ptr(weak_ptr) -> shared_ptr; - template - shared_ptr(unique_ptr) -> shared_ptr; -} -\end{codeblock} - -\pnum -Specializations of \tcode{shared_ptr} shall be \oldconcept{CopyConstructible}, -\oldconcept{CopyAssignable}, and \oldconcept{\-Less\-Than\-Comparable}, allowing their use in standard -containers. Specializations of \tcode{shared_ptr} shall be -contextually convertible to \tcode{bool}, -allowing their use in boolean expressions and declarations in conditions. - -\pnum -The template parameter \tcode{T} of \tcode{shared_ptr} -may be an incomplete type. -\begin{note} -\tcode{T} can be a function type. -\end{note} - -\pnum -\begin{example} -\begin{codeblock} -if (shared_ptr px = dynamic_pointer_cast(py)) { - // do something with \tcode{px} -} -\end{codeblock} -\end{example} - -\pnum -For purposes of determining the presence of a data race, member functions shall -access and modify only the \tcode{shared_ptr} and \tcode{weak_ptr} objects -themselves and not objects they refer to. Changes in \tcode{use_count()} do not -reflect modifications that can introduce data races. - -\pnum -For the purposes of subclause \ref{smartptr}, -a pointer type \tcode{Y*} is said to be -\defnx{compatible with}{compatible with!\idxcode{shared_ptr}} -a pointer type \tcode{T*} when either -\tcode{Y*} is convertible to \tcode{T*} or -\tcode{Y} is \tcode{U[N]} and \tcode{T} is \cv{}~\tcode{U[]}. - -\rSec4[util.smartptr.shared.const]{Constructors} - -\pnum -In the constructor definitions below, -enables \tcode{shared_from_this} with \tcode{p}, -for a pointer \tcode{p} of type \tcode{Y*}, -means that if \tcode{Y} has an unambiguous and accessible base class -that is a specialization of \tcode{enable_shared_from_this}\iref{util.smartptr.enab}, -then \tcode{remove_cv_t*} shall be implicitly convertible to \tcode{T*} and -the constructor evaluates the statement: -\begin{codeblock} -if (p != nullptr && p->weak_this.expired()) - p->weak_this = shared_ptr>(*this, const_cast*>(p)); -\end{codeblock} -The assignment to the \tcode{weak_this} member is not atomic and -conflicts with any potentially concurrent access to the same object\iref{intro.multithread}. - -\indexlibraryctor{shared_ptr}% -\begin{itemdecl} -constexpr shared_ptr() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{use_count() == 0 \&\& get() == nullptr}. -\end{itemdescr} - -\indexlibraryctor{shared_ptr}% -\begin{itemdecl} -template explicit shared_ptr(Y* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -When \tcode{T} is an array type, -the expression \tcode{delete[] p} is well-formed and either -\tcode{T} is \tcode{U[N]} and \tcode{Y(*)[N]} is convertible to \tcode{T*}, or -\tcode{T} is \tcode{U[]} and \tcode{Y(*)[]} is convertible to \tcode{T*}. -When \tcode{T} is not an array type, -the expression \tcode{delete p} is well-formed and -\tcode{Y*} is convertible to \tcode{T*}. - -\pnum -\mandates -\tcode{Y} is a complete type. - -\pnum -\expects -The expression -\tcode{delete[] p}, when \tcode{T} is an array type, or -\tcode{delete p}, when \tcode{T} is not an array type, -has well-defined behavior, and -does not throw exceptions. - -\pnum -\effects -When \tcode{T} is not an array type, -constructs a \tcode{shared_ptr} object -that owns the pointer \tcode{p}. -Otherwise, constructs a \tcode{shared_ptr} -that owns \tcode{p} and a deleter of an -unspecified type that calls \tcode{delete[] p}. -When \tcode{T} is not an array type, -enables \tcode{shared_from_this} with \tcode{p}. -If an exception is thrown, \tcode{delete p} is called -when \tcode{T} is not an array type, \tcode{delete[] p} otherwise. - -\pnum -\ensures -\tcode{use_count() == 1 \&\& get() == p}. - -\pnum -\throws -\tcode{bad_alloc}, or an \impldef{exception type when \tcode{shared_ptr} -constructor fails} exception when a resource other than memory cannot be obtained. -\end{itemdescr} - -\indexlibraryctor{shared_ptr}% -\begin{itemdecl} -template shared_ptr(Y* p, D d); -template shared_ptr(Y* p, D d, A a); -template shared_ptr(nullptr_t p, D d); -template shared_ptr(nullptr_t p, D d, A a); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_move_constructible_v} is \tcode{true}, and -\tcode{d(p)} is a well-formed expression. -For the first two overloads: - -\begin{itemize} -\item -If \tcode{T} is an array type, then either -\tcode{T} is \tcode{U[N]} and \tcode{Y(*)[N]} is convertible to \tcode{T*}, or -\tcode{T} is \tcode{U[]} and \tcode{Y(*)[]} is convertible to \tcode{T*}. - -\item -If \tcode{T} is not an array type, then \tcode{Y*} is convertible to \tcode{T*}. -\end{itemize} - -\pnum -\expects -Construction of \tcode{d} and a deleter of type \tcode{D} -initialized with \tcode{std::move(d)} do not throw exceptions. -The expression \tcode{d(p)} -has well-defined behavior and does not throw exceptions. -\tcode{A} meets the \oldconcept{Allocator} requirements (\tref{cpp17.allocator}). - -\pnum -\effects -Constructs a \tcode{shared_ptr} object that owns the -object \tcode{p} and the deleter \tcode{d}. -When \tcode{T} is not an array type, -the first and second constructors enable \tcode{shared_from_this} with \tcode{p}. -The second and fourth constructors shall use a copy of \tcode{a} to -allocate memory for internal use. -If an exception is thrown, \tcode{d(p)} is called. - -\pnum -\ensures -\tcode{use_count() == 1 \&\& get() == p}. - -\pnum -\throws -\tcode{bad_alloc}, or an \impldef{exception type when \tcode{shared_ptr} -constructor fails} exception -when a resource other than memory cannot be obtained. -\end{itemdescr} - -\indexlibraryctor{shared_ptr}% -\begin{itemdecl} -template shared_ptr(const shared_ptr& r, element_type* p) noexcept; -template shared_ptr(shared_ptr&& r, element_type* p) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs a \tcode{shared_ptr} instance that -stores \tcode{p} and shares ownership with -the initial value of \tcode{r}. - -\pnum -\ensures -\tcode{get() == p}. -For the second overload, -\tcode{r} is empty and \tcode{r.get() == nullptr}. - -\pnum -\begin{note} -Use of this constructor leads to a dangling pointer -unless \tcode{p} remains valid -at least until the ownership group of \tcode{r} is destroyed. -\end{note} - -\pnum -\begin{note} -This constructor allows creation of an empty -\tcode{shared_ptr} instance with a non-null stored pointer. -\end{note} -\end{itemdescr} - -\indexlibraryctor{shared_ptr}% -\begin{itemdecl} -shared_ptr(const shared_ptr& r) noexcept; -template shared_ptr(const shared_ptr& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the second constructor, \tcode{Y*} is compatible with \tcode{T*}. - -\pnum -\effects -If \tcode{r} is empty, constructs -an empty \tcode{shared_ptr} object; otherwise, constructs -a \tcode{shared_ptr} object that shares ownership with \tcode{r}. - -\pnum -\ensures -\tcode{get() == r.get() \&\& use_count() == r.use_count()}. -\end{itemdescr} - -\indexlibraryctor{shared_ptr}% -\begin{itemdecl} -shared_ptr(shared_ptr&& r) noexcept; -template shared_ptr(shared_ptr&& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the second constructor, \tcode{Y*} is compatible with \tcode{T*}. - -\pnum -\effects -Move constructs a \tcode{shared_ptr} instance from \tcode{r}. - -\pnum -\ensures -\tcode{*this} contains the old value of -\tcode{r}. \tcode{r} is empty, and \tcode{r.get() == nullptr}. -\end{itemdescr} - -\indexlibraryctor{shared_ptr}% -\indexlibraryglobal{weak_ptr}% -\begin{itemdecl} -template explicit shared_ptr(const weak_ptr& r); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{Y*} is compatible with \tcode{T*}. - -\pnum -\effects -Constructs a \tcode{shared_ptr} object that shares ownership with -\tcode{r} and stores a copy of the pointer stored in \tcode{r}. -If an exception is thrown, the constructor has no effect. - -\pnum -\ensures -\tcode{use_count() == r.use_count()}. - -\pnum -\throws -\tcode{bad_weak_ptr} when \tcode{r.expired()}. -\end{itemdescr} - -\indexlibraryctor{shared_ptr}% -\indexlibraryglobal{unique_ptr}% -\begin{itemdecl} -template shared_ptr(unique_ptr&& r); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{Y*} is compatible with \tcode{T*} and -\tcode{unique_ptr::pointer} is convertible to \tcode{element_type*}. - -\pnum -\effects -If \tcode{r.get() == nullptr}, equivalent to \tcode{shared_ptr()}. -Otherwise, if \tcode{D} is not a reference type, -equivalent to \tcode{shared_ptr(r.release(), std::move(r.get_deleter()))}. -Otherwise, equivalent to \tcode{shared_ptr(r.release(), ref(r.get_deleter()))}. -If an exception is thrown, the constructor has no effect. -\end{itemdescr} - -\rSec4[util.smartptr.shared.dest]{Destructor} - -\indexlibrarydtor{shared_ptr}% -\begin{itemdecl} -~shared_ptr(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -\begin{itemize} -\item If \tcode{*this} is empty or shares ownership with another -\tcode{shared_ptr} instance (\tcode{use_count() > 1}), there are no side effects. - -\item -Otherwise, if \tcode{*this} owns an object -\tcode{p} and a deleter \tcode{d}, \tcode{d(p)} is called. - -\item Otherwise, \tcode{*this} owns a pointer \tcode{p}, -and \tcode{delete p} is called. -\end{itemize} -\end{itemdescr} - -\pnum -\begin{note} -Since the destruction of \tcode{*this} -decreases the number of instances that share ownership with \tcode{*this} -by one, -after \tcode{*this} has been destroyed -all \tcode{shared_ptr} instances that shared ownership with -\tcode{*this} will report a \tcode{use_count()} that is one less -than its previous value. -\end{note} - -\rSec4[util.smartptr.shared.assign]{Assignment} - -\indexlibrarymember{operator=}{shared_ptr}% -\begin{itemdecl} -shared_ptr& operator=(const shared_ptr& r) noexcept; -template shared_ptr& operator=(const shared_ptr& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{shared_ptr(r).swap(*this)}. - -\pnum -\returns -\tcode{*this}. - -\pnum -\begin{note} -The use count updates caused by the temporary object -construction and destruction are not observable side -effects, so the implementation can meet the effects (and the -implied guarantees) via different means, without creating a -temporary. In particular, in the example: -\begin{codeblock} -shared_ptr p(new int); -shared_ptr q(p); -p = p; -q = p; -\end{codeblock} -both assignments can be no-ops. -\end{note} -\end{itemdescr} - -\indexlibrarymember{operator=}{shared_ptr}% -\begin{itemdecl} -shared_ptr& operator=(shared_ptr&& r) noexcept; -template shared_ptr& operator=(shared_ptr&& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{shared_ptr(std::move(r)).swap(*this)}. - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{operator=}{shared_ptr}% -\begin{itemdecl} -template shared_ptr& operator=(unique_ptr&& r); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{shared_ptr(std::move(r)).swap(*this)}. - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\rSec4[util.smartptr.shared.mod]{Modifiers} - -\indexlibrarymember{swap}{shared_ptr}% -\begin{itemdecl} -void swap(shared_ptr& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} - -\pnum -\effects -Exchanges the contents of \tcode{*this} and \tcode{r}. -\end{itemdescr} - -\indexlibrarymember{reset}{shared_ptr}% -\begin{itemdecl} -void reset() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{shared_ptr().swap(*this)}. -\end{itemdescr} - -\indexlibrarymember{reset}{shared_ptr}% -\begin{itemdecl} -template void reset(Y* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{shared_ptr(p).swap(*this)}. -\end{itemdescr} - -\indexlibrarymember{reset}{shared_ptr}% -\begin{itemdecl} -template void reset(Y* p, D d); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{shared_ptr(p, d).swap(*this)}. -\end{itemdescr} - -\indexlibrarymember{reset}{shared_ptr}% -\begin{itemdecl} -template void reset(Y* p, D d, A a); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{shared_ptr(p, d, a).swap(*this)}. -\end{itemdescr} - -\rSec4[util.smartptr.shared.obs]{Observers} -\indexlibrarymember{get}{shared_ptr}% -\begin{itemdecl} -element_type* get() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The stored pointer. -\end{itemdescr} - -\indexlibrarymember{operator*}{shared_ptr}% -\begin{itemdecl} -T& operator*() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{get() != 0}. - -\pnum -\returns -\tcode{*get()}. - -\pnum -\remarks -When \tcode{T} is an array type or \cv{}~\keyword{void}, -it is unspecified whether this -member function is declared. If it is declared, it is unspecified what its -return type is, except that the declaration (although not necessarily the -definition) of the function shall be well-formed. -\end{itemdescr} - -\indexlibrarymember{operator->}{shared_ptr}% -\begin{itemdecl} -T* operator->() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{get() != 0}. - -\pnum -\returns -\tcode{get()}. - -\pnum -\remarks -When \tcode{T} is an array type, -it is unspecified whether this member function is declared. -If it is declared, it is unspecified what its return type is, -except that the declaration (although not necessarily the definition) -of the function shall be well-formed. -\end{itemdescr} - -\indexlibrarymember{operator[]}{shared_ptr}% -\begin{itemdecl} -element_type& operator[](ptrdiff_t i) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{get() != 0 \&\& i >= 0}. -If \tcode{T} is \tcode{U[N]}, \tcode{i < N}. - -\pnum -\returns -\tcode{get()[i]}. - -\pnum -\throws -Nothing. - -\pnum -\remarks -When \tcode{T} is not an array type, -it is unspecified whether this member function is declared. -If it is declared, it is unspecified what its return type is, -except that the declaration (although not necessarily the definition) -of the function shall be well-formed. -\end{itemdescr} - -\indexlibrarymember{use_count}{shared_ptr}% -\begin{itemdecl} -long use_count() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\sync -None. - -\pnum -\returns -The number of \tcode{shared_ptr} objects, \tcode{*this} included, -that share ownership with \tcode{*this}, or \tcode{0} when \tcode{*this} is -empty. - -\pnum -\begin{note} -\tcode{get() == nullptr} -does not imply a specific return value of \tcode{use_count()}. -\end{note} - -\pnum -\begin{note} -\tcode{weak_ptr::lock()} -can affect the return value of \tcode{use_count()}. -\end{note} - -\pnum -\begin{note} -When multiple threads -might affect the return value of \tcode{use_count()}, -the result is approximate. -In particular, \tcode{use_count() == 1} does not imply that accesses through -a previously destroyed \tcode{shared_ptr} have in any sense completed. -\end{note} -\end{itemdescr} - -\indexlibrarymember{operator bool}{shared_ptr}% -\begin{itemdecl} -explicit operator bool() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{get() != 0}. -\end{itemdescr} - -\indexlibrarymember{owner_before}{shared_ptr}% -\begin{itemdecl} -template bool owner_before(const shared_ptr& b) const noexcept; -template bool owner_before(const weak_ptr& b) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -An unspecified value such that -\begin{itemize} -\item \tcode{x.owner_before(y)} defines a strict weak ordering as defined in~\ref{alg.sorting}; - -\item under the equivalence relation defined by \tcode{owner_before}, -\tcode{!a.owner_before(b) \&\& !b.owner_before(a)}, two \tcode{shared_ptr} or -\tcode{weak_ptr} instances are equivalent if and only if they share ownership or -are both empty. -\end{itemize} - -\end{itemdescr} - -\rSec4[util.smartptr.shared.create]{Creation} - -\pnum -The common requirements that apply to all -\tcode{make_shared}, -\tcode{allocate_shared}, -\tcode{make_shared_for_overwrite}, and -\tcode{allocate_shared_for_overwrite} overloads, -unless specified otherwise, are described below. - -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% -\begin{itemdecl} -template - shared_ptr make_shared(@\placeholdernc{args}@); -template - shared_ptr allocate_shared(const A& a, @\placeholdernc{args}@); -template - shared_ptr make_shared_for_overwrite(@\placeholdernc{args}@); -template - shared_ptr allocate_shared_for_overwrite(const A& a, @\placeholdernc{args}@); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{A} meets the \oldconcept{Allocator} requirements (\tref{cpp17.allocator}). - -\pnum -\effects -Allocates memory for an object of type \tcode{T} -(or \tcode{U[N]} when \tcode{T} is \tcode{U[]}, -where \tcode{N} is determined from \placeholder{args} as specified by the concrete overload). -The object is initialized from \placeholder{args} as specified by the concrete overload. -The \tcode{allocate_shared} and \tcode{allocate_shared_for_overwrite} templates -use a copy of \tcode{a} -(rebound for an unspecified \tcode{value_type}) to allocate memory. -If an exception is thrown, the functions have no effect. - -\pnum -\ensures -\tcode{r.get() != 0 \&\& r.use_count() == 1}, -where \tcode{r} is the return value. - -\pnum -\returns -A \tcode{shared_ptr} instance that stores and owns the address of -the newly constructed object. - -\pnum -\throws -\tcode{bad_alloc}, or -an exception thrown from \tcode{allocate} or from the initialization of the object. - -\pnum -\remarks -\begin{itemize} -\item - Implementations should perform no more than one memory allocation. - \begin{note} - This provides efficiency equivalent to an intrusive smart pointer. - \end{note} -\item - When an object of an array type \tcode{U} is specified to have - an initial value of \tcode{u} (of the same type), - this shall be interpreted to mean that - each array element of the object has as its initial value - the corresponding element from \tcode{u}. -\item - When an object of an array type is specified to have - a default initial value, - this shall be interpreted to mean that each array element of the object - has a default initial value. -\item - When a (sub)object of a non-array type \tcode{U} is specified to have - an initial value of \tcode{v}, or \tcode{U(l...)}, - where \tcode{l...} is a list of constructor arguments, - \tcode{make_shared} shall initialize this (sub)object - via the expression \tcode{::new(pv) U(v)} or \tcode{::new(pv) U(l...)} respectively, - where \tcode{pv} has type \tcode{void*} and points to storage - suitable to hold an object of type \tcode{U}. -\item - When a (sub)object of a non-array type \tcode{U} is specified to have - an initial value of \tcode{v}, or \tcode{U(l...)}, - where \tcode{l...} is a list of constructor arguments, - \tcode{allocate_shared} shall initialize this (sub)object - via the expression - \begin{itemize} - \item \tcode{allocator_traits::construct(a2, pv, v)} or - \item \tcode{allocator_traits::construct(a2, pv, l...)} - \end{itemize} - respectively, - where \tcode{pv} points to storage - suitable to hold an object of type \tcode{U} and - \tcode{a2} of type \tcode{A2} is a rebound copy of - the allocator \tcode{a} passed to \tcode{allocate_shared} - such that its \tcode{value_type} is \tcode{remove_cv_t}. -\item - When a (sub)object of non-array type \tcode{U} is specified to have - a default initial value, - \tcode{make_shared} shall initialize this (sub)object - via the expression \tcode{::new(pv) U()}, - where \tcode{pv} has type \tcode{void*} and points to storage - suitable to hold an object of type \tcode{U}. -\item - When a (sub)object of non-array type \tcode{U} is specified to have - a default initial value, - \tcode{allocate_shared} shall initialize this (sub)object - via the expression \tcode{allocator_traits::construct(a2, pv)}, - where \tcode{pv} points to storage - suitable to hold an object of type \tcode{U} and - \tcode{a2} of type \tcode{A2} is a rebound copy of - the allocator \tcode{a} passed to \tcode{allocate_shared} - such that its \tcode{value_type} is \tcode{remove_cv_t}. -\item - When a (sub)object of non-array type \tcode{U} is initialized by - \tcode{make_shared_for_overwrite} or\linebreak % avoid Overfull - \tcode{allocate_shared_for_overwrite}, - it is initialized via the expression \tcode{::new(pv) U}, - where \tcode{pv} has type \tcode{void*} and - points to storage suitable to hold an object of type \tcode{U}. -\item - Array elements are initialized in ascending order of their addresses. -\item - When the lifetime of the object managed by the return value ends, or - when the initialization of an array element throws an exception, - the initialized elements are destroyed in the reverse order - of their original construction. -\item - When a (sub)object of non-array type \tcode{U} - that was initialized by \tcode{make_shared} is to be destroyed, - it is destroyed via the expression \tcode{pv->\~{}U()} where - \tcode{pv} points to that object of type \tcode{U}. -\item - When a (sub)object of non-array type \tcode{U} - that was initialized by \tcode{allocate_shared} is to be destroyed, - it is destroyed via the expression - \tcode{allocator_traits::destroy(a2, pv)} where - \tcode{pv} points to that object of type \tcode{remove_cv_t} and - \tcode{a2} of type \tcode{A2} is a rebound copy of - the allocator \tcode{a} passed to \tcode{allocate_shared} - such that its \tcode{value_type} is \tcode{remove_cv_t}. -\end{itemize} -\begin{note} -These functions will typically allocate more memory than \tcode{sizeof(T)} to -allow for internal bookkeeping structures such as reference counts. -\end{note} -\end{itemdescr} - -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% -\begin{itemdecl} -template - shared_ptr make_shared(Args&&... args); // \tcode{T} is not array -template - shared_ptr allocate_shared(const A& a, Args&&... args); // \tcode{T} is not array -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is not an array type. - -\pnum -\returns -A \tcode{shared_ptr} to an object of type \tcode{T} -with an initial value \tcode{T(forward(args)...)}. - -\pnum -\remarks -The \tcode{shared_ptr} constructors called by these functions -enable \tcode{shared_from_this} -with the address of the newly constructed object of type \tcode{T}. - -\pnum -\begin{example} -\begin{codeblock} -shared_ptr p = make_shared(); // \tcode{shared_ptr} to \tcode{int()} -shared_ptr> q = make_shared>(16, 1); - // \tcode{shared_ptr} to vector of \tcode{16} elements with value \tcode{1} -\end{codeblock} -\end{example} -\end{itemdescr} - -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% -\begin{itemdecl} -template shared_ptr - make_shared(size_t N); // \tcode{T} is \tcode{U[]} -template - shared_ptr allocate_shared(const A& a, size_t N); // \tcode{T} is \tcode{U[]} -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is of the form \tcode{U[]}. - -\pnum -\returns -A \tcode{shared_ptr} to an object of type \tcode{U[N]} -with a default initial value, -where \tcode{U} is \tcode{remove_extent_t}. - -\pnum -\begin{example} -\begin{codeblock} -shared_ptr p = make_shared(1024); - // \tcode{shared_ptr} to a value-initialized \tcode{double[1024]} -shared_ptr q = make_shared(6); - // \tcode{shared_ptr} to a value-initialized \tcode{double[6][2][2]} -\end{codeblock} -\end{example} -\end{itemdescr} - -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% -\begin{itemdecl} -template - shared_ptr make_shared(); // \tcode{T} is \tcode{U[N]} -template - shared_ptr allocate_shared(const A& a); // \tcode{T} is \tcode{U[N]} -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is of the form \tcode{U[N]}. - -\pnum -\returns -A \tcode{shared_ptr} to an object of type \tcode{T} -with a default initial value. - -\pnum -\begin{example} -\begin{codeblock} -shared_ptr p = make_shared(); - // \tcode{shared_ptr} to a value-initialized \tcode{double[1024]} -shared_ptr q = make_shared(); - // \tcode{shared_ptr} to a value-initialized \tcode{double[6][2][2]} -\end{codeblock} -\end{example} -\end{itemdescr} - -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% -\begin{itemdecl} -template - shared_ptr make_shared(size_t N, - const remove_extent_t& u); // \tcode{T} is \tcode{U[]} -template - shared_ptr allocate_shared(const A& a, size_t N, - const remove_extent_t& u); // \tcode{T} is \tcode{U[]} -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is of the form \tcode{U[]}. - -\pnum -\returns -A \tcode{shared_ptr} to an object of type \tcode{U[N]}, -where \tcode{U} is \tcode{remove_extent_t} and -each array element has an initial value of \tcode{u}. - -\pnum -\begin{example} -\begin{codeblock} -shared_ptr p = make_shared(1024, 1.0); - // \tcode{shared_ptr} to a \tcode{double[1024]}, where each element is \tcode{1.0} -shared_ptr q = make_shared(6, {1.0, 0.0}); - // \tcode{shared_ptr} to a \tcode{double[6][2]}, where each \tcode{double[2]} element is \tcode{\{1.0, 0.0\}} -shared_ptr[]> r = make_shared[]>(4, {1, 2}); - // \tcode{shared_ptr} to a \tcode{vector[4]}, where each vector has contents \tcode{\{1, 2\}} -\end{codeblock} -\end{example} -\end{itemdescr} - -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% -\begin{itemdecl} -template - shared_ptr make_shared(const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} -template - shared_ptr allocate_shared(const A& a, - const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is of the form \tcode{U[N]}. - -\pnum -\returns -A \tcode{shared_ptr} to an object of type \tcode{T}, -where each array element of type \tcode{remove_extent_t} -has an initial value of \tcode{u}. - -\pnum -\begin{example} -\begin{codeblock} -shared_ptr p = make_shared(1.0); - // \tcode{shared_ptr} to a \tcode{double[1024]}, where each element is \tcode{1.0} -shared_ptr q = make_shared({1.0, 0.0}); - // \tcode{shared_ptr} to a \tcode{double[6][2]}, where each double[2] element is \tcode{\{1.0, 0.0\}} -shared_ptr[4]> r = make_shared[4]>({1, 2}); - // \tcode{shared_ptr} to a \tcode{vector[4]}, where each vector has contents \tcode{\{1, 2\}} -\end{codeblock} -\end{example} -\end{itemdescr} - -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% -\begin{itemdecl} -template - shared_ptr make_shared_for_overwrite(); -template - shared_ptr allocate_shared_for_overwrite(const A& a); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is not an array of unknown bound. - -\pnum -\returns -A \tcode{shared_ptr} to an object of type \tcode{T}. - -\pnum -\begin{example} -\begin{codeblock} -struct X { double data[1024]; }; -shared_ptr p = make_shared_for_overwrite(); - // \tcode{shared_ptr} to a default-initialized \tcode{X}, where each element in \tcode{X::data} has an indeterminate value - -shared_ptr q = make_shared_for_overwrite(); - // \tcode{shared_ptr} to a default-initialized \tcode{double[1024]}, where each element has an indeterminate value -\end{codeblock} -\end{example} -\end{itemdescr} - -\indexlibraryglobal{make_shared}% -\indexlibraryglobal{allocate_shared}% -\begin{itemdecl} -template - shared_ptr make_shared_for_overwrite(size_t N); -template - shared_ptr allocate_shared_for_overwrite(const A& a, size_t N); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{T} is an array of unknown bound. - -\pnum -\returns -A \tcode{shared_ptr} to an object of type \tcode{U[N]}, -where \tcode{U} is \tcode{remove_extent_t}. - -\pnum -\begin{example} -\begin{codeblock} -shared_ptr p = make_shared_for_overwrite(1024); - // \tcode{shared_ptr} to a default-initialized \tcode{double[1024]}, where each element has an indeterminate value -\end{codeblock} -\end{example} -\end{itemdescr} - -\rSec4[util.smartptr.shared.cmp]{Comparison} - -\indexlibrarymember{operator==}{shared_ptr}% -\begin{itemdecl} -template - bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{a.get() == b.get()}. -\end{itemdescr} - -\indexlibrarymember{operator==}{shared_ptr}% -\begin{itemdecl} -template - bool operator==(const shared_ptr& a, nullptr_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{!a}. -\end{itemdescr} - -\indexlibrarymember{operator<=>}{shared_ptr}% -\begin{itemdecl} -template - strong_ordering operator<=>(const shared_ptr& a, const shared_ptr& b) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{compare_three_way()(a.get(), b.get())}. - -\pnum -\begin{note} -Defining a comparison operator function allows \tcode{shared_ptr} objects -to be used as keys in associative containers. -\end{note} -\end{itemdescr} - -\indexlibrarymember{operator<=>}{shared_ptr}% -\begin{itemdecl} -template - strong_ordering operator<=>(const shared_ptr& a, nullptr_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\begin{codeblock} -compare_three_way()(a.get(), static_cast::element_type*>(nullptr). -\end{codeblock} -\end{itemdescr} - -\rSec4[util.smartptr.shared.spec]{Specialized algorithms} - -\indexlibrarymember{swap}{shared_ptr}% -\begin{itemdecl} -template - void swap(shared_ptr& a, shared_ptr& b) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{a.swap(b)}. -\end{itemdescr} - -\rSec4[util.smartptr.shared.cast]{Casts} - -\indexlibrarymember{static_pointer_cast}{shared_ptr}% -\begin{itemdecl} -template - shared_ptr static_pointer_cast(const shared_ptr& r) noexcept; -template - shared_ptr static_pointer_cast(shared_ptr&& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -The expression \tcode{static_cast((U*)nullptr)} is well-formed. - -\pnum -\returns -\begin{codeblock} -shared_ptr(@\placeholder{R}@, static_cast::element_type*>(r.get())) -\end{codeblock} -where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and -\tcode{std::move(r)} for the second. - -\pnum -\begin{note} -The seemingly equivalent expression -\tcode{shared_ptr(static_cast(r.get()))} -will eventually result in undefined behavior, attempting to delete the -same object twice. -\end{note} -\end{itemdescr} - -\indexlibrarymember{dynamic_pointer_cast}{shared_ptr}% -\begin{itemdecl} -template - shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept; -template - shared_ptr dynamic_pointer_cast(shared_ptr&& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -The expression \tcode{dynamic_cast((U*)nullptr)} is well-formed. -The expression \tcode{dynamic_cast::element_type*>(r.get())} is well-formed. - -\pnum -\expects -The expression \tcode{dynamic_cast::element_type*>(r.get())} has well-defined behavior. - -\pnum -\returns -\begin{itemize} -\item When \tcode{dynamic_cast::element_type*>(r.get())} - returns a non-null value \tcode{p}, - \tcode{shared_ptr(\placeholder{R}, p)}, - where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and - \tcode{std::move(r)} for the second. -\item Otherwise, \tcode{shared_ptr()}. -\end{itemize} - -\pnum -\begin{note} -The seemingly equivalent expression -\tcode{shared_ptr(dynamic_cast(r.get()))} will eventually result in -undefined behavior, attempting to delete the same object twice. -\end{note} -\end{itemdescr} - -\indexlibrarymember{const_pointer_cast}{shared_ptr}% -\begin{itemdecl} -template - shared_ptr const_pointer_cast(const shared_ptr& r) noexcept; -template - shared_ptr const_pointer_cast(shared_ptr&& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -The expression \tcode{const_cast((U*)nullptr)} is well-formed. - -\pnum -\returns -\begin{codeblock} -shared_ptr(@\placeholder{R}@, const_cast::element_type*>(r.get())) -\end{codeblock} -where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and -\tcode{std::move(r)} for the second. - -\pnum -\begin{note} -The seemingly equivalent expression -\tcode{shared_ptr(const_cast(r.get()))} will eventually result in -undefined behavior, attempting to delete the same object twice. -\end{note} -\end{itemdescr} - -\indexlibrarymember{reinterpret_pointer_cast}{shared_ptr}% -\begin{itemdecl} -template - shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept; -template - shared_ptr reinterpret_pointer_cast(shared_ptr&& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -The expression \tcode{reinterpret_cast((U*)nullptr)} is well-formed. - -\pnum -\returns -\begin{codeblock} -shared_ptr(@\placeholder{R}@, reinterpret_cast::element_type*>(r.get())) -\end{codeblock} -where \tcode{\placeholder{R}} is \tcode{r} for the first overload, and -\tcode{std::move(r)} for the second. - -\pnum -\begin{note} -The seemingly equivalent expression -\tcode{shared_ptr(reinterpret_cast(r.get()))} will eventually result in -undefined behavior, attempting to delete the same object twice. -\end{note} -\end{itemdescr} - -\rSec4[util.smartptr.getdeleter]{\tcode{get_deleter}} - -\indexlibrarymember{get_deleter}{shared_ptr}% -\begin{itemdecl} -template - D* get_deleter(const shared_ptr& p) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -If \tcode{p} owns a deleter \tcode{d} of type cv-unqualified -\tcode{D}, returns \tcode{addressof(d)}; otherwise returns \keyword{nullptr}. -The returned -pointer remains valid as long as there exists a \tcode{shared_ptr} instance -that owns \tcode{d}. -\begin{note} -It is unspecified whether the pointer -remains valid longer than that. This can happen if the implementation doesn't destroy -the deleter until all \tcode{weak_ptr} instances that share ownership with -\tcode{p} have been destroyed. -\end{note} -\end{itemdescr} - -\rSec4[util.smartptr.shared.io]{I/O} - -\indexlibrarymember{operator<<}{shared_ptr}% -\begin{itemdecl} -template - basic_ostream& operator<<(basic_ostream& os, const shared_ptr& p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by: \tcode{os <{}< p.get();} - -\pnum -\returns -\tcode{os}. -\end{itemdescr} - -\rSec3[util.smartptr.weak]{Class template \tcode{weak_ptr}} - -\rSec4[util.smartptr.weak.general]{General} - -\pnum -\indexlibraryglobal{weak_ptr}% -The \tcode{weak_ptr} class template stores a weak reference to an object -that is already managed by a \tcode{shared_ptr}. To access the object, a -\tcode{weak_ptr} can be converted to a \tcode{shared_ptr} using the member -function \tcode{lock}. - -\begin{codeblock} -namespace std { - template class weak_ptr { - public: - using element_type = remove_extent_t; - - // \ref{util.smartptr.weak.const}, constructors - constexpr weak_ptr() noexcept; - template - weak_ptr(const shared_ptr& r) noexcept; - weak_ptr(const weak_ptr& r) noexcept; - template - weak_ptr(const weak_ptr& r) noexcept; - weak_ptr(weak_ptr&& r) noexcept; - template - weak_ptr(weak_ptr&& r) noexcept; - - // \ref{util.smartptr.weak.dest}, destructor - ~weak_ptr(); - - // \ref{util.smartptr.weak.assign}, assignment - weak_ptr& operator=(const weak_ptr& r) noexcept; - template - weak_ptr& operator=(const weak_ptr& r) noexcept; - template - weak_ptr& operator=(const shared_ptr& r) noexcept; - weak_ptr& operator=(weak_ptr&& r) noexcept; - template - weak_ptr& operator=(weak_ptr&& r) noexcept; - - // \ref{util.smartptr.weak.mod}, modifiers - void swap(weak_ptr& r) noexcept; - void reset() noexcept; - - // \ref{util.smartptr.weak.obs}, observers - long use_count() const noexcept; - bool expired() const noexcept; - shared_ptr lock() const noexcept; - template - bool owner_before(const shared_ptr& b) const noexcept; - template - bool owner_before(const weak_ptr& b) const noexcept; - }; - - template - weak_ptr(shared_ptr) -> weak_ptr; -} -\end{codeblock} - -\pnum -Specializations of \tcode{weak_ptr} shall be \oldconcept{CopyConstructible} and -\oldconcept{CopyAssignable}, allowing their use in standard -containers. The template parameter \tcode{T} of \tcode{weak_ptr} may be an -incomplete type. - -\rSec4[util.smartptr.weak.const]{Constructors} - -\indexlibraryctor{weak_ptr}% -\begin{itemdecl} -constexpr weak_ptr() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs an empty \tcode{weak_ptr} object that stores a null pointer value. - -\pnum -\ensures -\tcode{use_count() == 0}. -\end{itemdescr} - -\indexlibraryctor{weak_ptr}% -\begin{itemdecl} -weak_ptr(const weak_ptr& r) noexcept; -template weak_ptr(const weak_ptr& r) noexcept; -template weak_ptr(const shared_ptr& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the second and third constructors, \tcode{Y*} is compatible with \tcode{T*}. - -\pnum -\effects -If \tcode{r} is empty, constructs -an empty \tcode{weak_ptr} object that stores a null pointer value; -otherwise, constructs -a \tcode{weak_ptr} object that shares ownership -with \tcode{r} and stores a copy of the pointer stored in \tcode{r}. - -\pnum -\ensures -\tcode{use_count() == r.use_count()}. -\end{itemdescr} - -\indexlibraryctor{weak_ptr}% -\begin{itemdecl} -weak_ptr(weak_ptr&& r) noexcept; -template weak_ptr(weak_ptr&& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the second constructor, \tcode{Y*} is compatible with \tcode{T*}. - -\pnum -\effects -Move constructs a \tcode{weak_ptr} instance from \tcode{r}. - -\pnum -\ensures -\tcode{*this} contains the old value of \tcode{r}. -\tcode{r} is empty, stores a null pointer value, and \tcode{r.use_count() == 0}. -\end{itemdescr} - -\rSec4[util.smartptr.weak.dest]{Destructor} - -\indexlibrarydtor{weak_ptr}% -\begin{itemdecl} -~weak_ptr(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Destroys this \tcode{weak_ptr} object but has no -effect on the object its stored pointer points to. -\end{itemdescr} - -\rSec4[util.smartptr.weak.assign]{Assignment} - -\indexlibrarymember{operator=}{weak_ptr}% -\begin{itemdecl} -weak_ptr& operator=(const weak_ptr& r) noexcept; -template weak_ptr& operator=(const weak_ptr& r) noexcept; -template weak_ptr& operator=(const shared_ptr& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{weak_ptr(r).swap(*this)}. - -\pnum -\returns -\tcode{*this}. - -\pnum -\remarks -The implementation may meet the effects (and the -implied guarantees) via different means, without creating a temporary object. -\end{itemdescr} - -\indexlibrarymember{operator=}{weak_ptr}% -\begin{itemdecl} -weak_ptr& operator=(weak_ptr&& r) noexcept; -template weak_ptr& operator=(weak_ptr&& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{weak_ptr(std::move(r)).swap(*this)}. - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\rSec4[util.smartptr.weak.mod]{Modifiers} -\indexlibrarymember{swap}{weak_ptr}% -\begin{itemdecl} -void swap(weak_ptr& r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Exchanges the contents of \tcode{*this} and \tcode{r}. -\end{itemdescr} - -\indexlibrarymember{reset}{weak_ptr}% -\begin{itemdecl} -void reset() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{weak_ptr().swap(*this)}. -\end{itemdescr} - -\rSec4[util.smartptr.weak.obs]{Observers} -\indexlibrarymember{use_count}{weak_ptr}% -\begin{itemdecl} -long use_count() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{0} if \tcode{*this} is empty; -otherwise, the number of \tcode{shared_ptr} instances -that share ownership with \tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{expired}{weak_ptr}% -\begin{itemdecl} -bool expired() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{use_count() == 0}. -\end{itemdescr} - -\indexlibrarymember{lock}{weak_ptr}% -\begin{itemdecl} -shared_ptr lock() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{expired() ?\ shared_ptr() :\ shared_ptr(*this)}, executed atomically. -\end{itemdescr} - -\indexlibrarymember{owner_before}{weak_ptr}% -\begin{itemdecl} -template bool owner_before(const shared_ptr& b) const noexcept; -template bool owner_before(const weak_ptr& b) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -An unspecified value such that -\begin{itemize} -\item \tcode{x.owner_before(y)} defines a strict weak ordering as defined in~\ref{alg.sorting}; - -\item under the equivalence relation defined by \tcode{owner_before}, -\tcode{!a.owner_before(b) \&\& !b.owner_before(a)}, two \tcode{shared_ptr} or -\tcode{weak_ptr} instances are equivalent if and only if they share ownership or are -both empty. -\end{itemize} -\end{itemdescr} - - -\rSec4[util.smartptr.weak.spec]{Specialized algorithms} - -\indexlibrarymember{swap}{weak_ptr}% -\begin{itemdecl} -template - void swap(weak_ptr& a, weak_ptr& b) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{a.swap(b)}. -\end{itemdescr} - -\rSec3[util.smartptr.ownerless]{Class template \tcode{owner_less}} - -\pnum -The class template \tcode{owner_less} allows ownership-based mixed comparisons of shared -and weak pointers. - -\indexlibraryglobal{owner_less}% -\begin{codeblock} -namespace std { - template struct owner_less; - - template struct owner_less> { - bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; - bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; - bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; - }; - - template struct owner_less> { - bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; - bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; - bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; - }; - - template<> struct owner_less { - template - bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; - template - bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; - template - bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; - template - bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; - - using is_transparent = @\unspec@; - }; -} -\end{codeblock} - -\indexlibrarymember{operator()}{owner_less}% -\pnum -\tcode{operator()(x, y)} returns \tcode{x.owner_before(y)}. -\begin{note} -Note that -\begin{itemize} -\item \tcode{operator()} defines a strict weak ordering as defined in~\ref{alg.sorting}; - -\item -two \tcode{shared_ptr} or \tcode{weak_ptr} instances are equivalent -under the equivalence relation defined by \tcode{operator()}, -\tcode{!operator()(a, b) \&\& !operator()(b, a)}, -if and only if they share ownership or are both empty. -\end{itemize} -\end{note} - -\rSec3[util.smartptr.enab]{Class template \tcode{enable_shared_from_this}} - -\pnum -\indexlibraryglobal{enable_shared_from_this}% -A class \tcode{T} can inherit from \tcode{enable_shared_from_this} -to inherit the \tcode{shared_from_this} member functions that obtain -a \tcode{shared_ptr} instance pointing to \tcode{*this}. - -\pnum -\begin{example} -\begin{codeblock} -struct X: public enable_shared_from_this { }; - -int main() { - shared_ptr p(new X); - shared_ptr q = p->shared_from_this(); - assert(p == q); - assert(!p.owner_before(q) && !q.owner_before(p)); // p and q share ownership -} -\end{codeblock} -\end{example} - -\begin{codeblock} -namespace std { - template class enable_shared_from_this { - protected: - constexpr enable_shared_from_this() noexcept; - enable_shared_from_this(const enable_shared_from_this&) noexcept; - enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; - ~enable_shared_from_this(); - - public: - shared_ptr shared_from_this(); - shared_ptr shared_from_this() const; - weak_ptr weak_from_this() noexcept; - weak_ptr weak_from_this() const noexcept; - - private: - mutable weak_ptr weak_this; // \expos - }; -} -\end{codeblock} - -\pnum -The template parameter \tcode{T} of \tcode{enable_shared_from_this} -may be an incomplete type. - -\indexlibraryctor{enable_shared_from_this}% -\begin{itemdecl} -constexpr enable_shared_from_this() noexcept; -enable_shared_from_this(const enable_shared_from_this&) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Value-initializes \tcode{weak_this}. -\end{itemdescr} - -\indexlibrarymember{operator=}{enable_shared_from_this}% -\begin{itemdecl} -enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{*this}. - -\pnum -\begin{note} -\tcode{weak_this} is not changed. -\end{note} -\end{itemdescr} - -\indexlibraryglobal{shared_ptr}% -\indexlibrarymember{shared_from_this}{enable_shared_from_this}% -\begin{itemdecl} -shared_ptr shared_from_this(); -shared_ptr shared_from_this() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{shared_ptr(weak_this)}. -\end{itemdescr} - -\indexlibraryglobal{weak_ptr}% -\indexlibrarymember{weak_from_this}{enable_shared_from_this}% -\begin{itemdecl} -weak_ptr weak_from_this() noexcept; -weak_ptr weak_from_this() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{weak_this}. -\end{itemdescr} - -\rSec2[util.smartptr.hash]{Smart pointer hash support} - -\indexlibrarymember{hash}{unique_ptr}% -\begin{itemdecl} -template struct hash>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -Letting \tcode{UP} be \tcode{unique_ptr}, -the specialization \tcode{hash} is enabled\iref{unord.hash} -if and only if \tcode{hash} is enabled. -When enabled, for an object \tcode{p} of type \tcode{UP}, -\tcode{hash()(p)} evaluates to -the same value as \tcode{hash()(p.get())}. -The member functions are not guaranteed to be \keyword{noexcept}. -\end{itemdescr} - -\indexlibrarymember{hash}{shared_ptr}% -\begin{itemdecl} -template struct hash>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -For an object \tcode{p} of type \tcode{shared_ptr}, -\tcode{hash>()(p)} evaluates to -the same value as \tcode{hash::element_type*>()(p.get())}. -\end{itemdescr}% -\indextext{smart pointers|)} - -\rSec2[smartptr.adapt]{Smart pointer adaptors} - -\rSec3[out.ptr.t]{Class template \tcode{out_ptr_t}} - -\pnum -\tcode{out_ptr_t} is a class template used to adapt types -such as smart pointers\iref{smartptr} -for functions that use output pointer parameters. - -\pnum -\begin{example} -\begin{codeblock} -#include -#include - -int fopen_s(std::FILE** f, const char* name, const char* mode); - -struct fclose_deleter { - void operator()(std::FILE* f) const noexcept { - std::fclose(f); - } -}; - -int main(int, char*[]) { - constexpr const char* file_name = "ow.o"; - std::unique_ptr file_ptr; - int err = fopen_s(std::out_ptr(file_ptr), file_name, "r+b"); - if (err != 0) - return 1; - // \tcode{*file_ptr} is valid - return 0; -} -\end{codeblock} -\tcode{unique_ptr} can be used with \tcode{out_ptr} -to be passed into an output pointer-style function, -without needing to hold onto an intermediate pointer value and -manually delete it on error or failure. -\end{example} - -\indexlibraryglobal{out_ptr_t}% -\begin{codeblock} -namespace std { - template - class out_ptr_t { - public: - explicit out_ptr_t(Smart&, Args...); - out_ptr_t(const out_ptr_t&) = delete; - - ~out_ptr_t(); - - operator Pointer*() const noexcept; - operator void**() const noexcept; - - private: - Smart& s; // \expos - tuple a; // \expos - Pointer p; // \expos - }; -} -\end{codeblock} - -\pnum -\tcode{Pointer} shall meet the \oldconcept{NullablePointer} requirements. -If \tcode{Smart} is a specialization of \tcode{shared_ptr} and -\tcode{sizeof...(Args) == 0}, -the program is ill-formed. -\begin{note} -It is typically a user error to reset a \tcode{shared_ptr} -without specifying a deleter, -as \tcode{shared_ptr} will replace a custom deleter upon usage of \tcode{reset}, -as specified in \ref{util.smartptr.shared.mod}. -\end{note} - -\pnum -Program-defined specializations of \tcode{out_ptr_t} -that depend on at least one program-defined type -need not meet the requirements for the primary template. - -\pnum -Evaluations of the conversion functions -on the same object may conflict\iref{intro.races}. - -\indexlibraryctor{out_ptr_t}% -\begin{itemdecl} -explicit out_ptr_t(Smart& smart, Args... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{s} with \tcode{smart}, -\tcode{a} with \tcode{std::forward(args)...}, and -value-initializes \tcode{p}. - -\pnum -\begin{note} -The constructor is not \tcode{noexcept} -to allow for a variety of non-terminating and safe implementation strategies. -For example, an implementation can allocate -a \tcode{shared_ptr}'s internal node in the constructor and -let implementation-defined exceptions escape safely. -The destructor can then move the allocated control block in directly and -avoid any other exceptions. -\end{note} -\end{itemdescr} - -\indexlibrarydtor{out_ptr_t}% -\begin{itemdecl} -~out_ptr_t(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{SP} be -\tcode{\exposid{POINTER_OF_OR}(Smart, Pointer)}\iref{memory.general}. - -\pnum -\effects -Equivalent to: -\begin{itemize} -\item -% pretend to \item that there is real text here, but undo the vertical spacing -\mbox{}\vspace{-\baselineskip}\vspace{-\parskip} -\begin{codeblock} -if (p) { - apply([&](auto&&... args) { - s.reset(static_cast(p), std::forward(args)...); }, std::move(a)); -} -\end{codeblock} -if the expression -\tcode{s.reset(static_cast(p), std::forward(args)...)} -is well-\linebreak formed; -\item -otherwise, -\begin{codeblock} -if (p) { - apply([&](auto&&... args) { - s = Smart(static_cast(p), std::forward(args)...); }, std::move(a)); -} -\end{codeblock} -if \tcode{is_constructible_v} is \tcode{true}; -\item -otherwise, the program is ill-formed. -\end{itemize} -\end{itemdescr} - -\begin{itemdecl} -operator Pointer*() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{operator void**()} has not been called on \tcode{*this}. - -\pnum -\returns -\tcode{addressof(const_cast(p))}. -\end{itemdescr} - -\begin{itemdecl} -operator void**() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_same_v} is \tcode{false}. - -\pnum -\mandates -\tcode{is_pointer_v} is \tcode{true}. - -\pnum -\expects -\tcode{operator Pointer*()} has not been called on \tcode{*this}. - -\pnum -\returns -A pointer value \tcode{v} such that: -\begin{itemize} -\item -the initial value \tcode{*v} is equivalent to \tcode{static_cast(p)} and -\item -any modification of \tcode{*v} -that is not followed by a subsequent modification of \tcode{*this} -affects the value of \tcode{p} during the destruction of \tcode{*this}, -such that \tcode{static_cast(p) == *v}. -\end{itemize} - -\pnum -\remarks -Accessing \tcode{*v} outside the lifetime of \tcode{*this} -has undefined behavior. - -\pnum -\begin{note} -\tcode{reinterpret_cast(static_cast(*this))} -can be a viable implementation strategy for some implementations. -\end{note} -\end{itemdescr} - -\rSec3[out.ptr]{Function template \tcode{out_ptr}} - -\indexlibraryglobal{out_ptr}% -\begin{itemdecl} -template - auto out_ptr(Smart& s, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{P} be \tcode{Pointer} -if \tcode{is_void_v} is \tcode{false}, -otherwise \tcode{\exposid{POINTER_OF}(Smart)}. - -\pnum -\returns -\tcode{out_ptr_t(s, std::forward(args)...)} -\end{itemdescr} - -\rSec3[inout.ptr.t]{Class template \tcode{inout_ptr_t}} - -\pnum -\tcode{inout_ptr_t} is a class template used to adapt types -such as smart pointers\iref{smartptr} -for functions that use output pointer parameters -whose dereferenced values may first be deleted -before being set to another allocated value. - -\pnum -\begin{example} -\begin{codeblock} -#include - -struct star_fish* star_fish_alloc(); -int star_fish_populate(struct star_fish** ps, const char* description); - -struct star_fish_deleter { - void operator() (struct star_fish* c) const noexcept; -}; - -using star_fish_ptr = std::unique_ptr; - -int main(int, char*[]) { - star_fish_ptr peach(star_fish_alloc()); - // ... - // used, need to re-make - int err = star_fish_populate(std::inout_ptr(peach), "caring clown-fish liker"); - return err; -} -\end{codeblock} -A \tcode{unique_ptr} can be used with \tcode{inout_ptr} -to be passed into an output pointer-style function. -The original value will be properly deleted -according to the function it is used with and -a new value reset in its place. -\end{example} - -\indexlibraryglobal{inout_ptr_t}% -\begin{codeblock} -namespace std { - template - class inout_ptr_t { - public: - explicit inout_ptr_t(Smart&, Args...); - inout_ptr_t(const inout_ptr_t&) = delete; - - ~inout_ptr_t(); - - operator Pointer*() const noexcept; - operator void**() const noexcept; - - private: - Smart& s; // \expos - tuple a; // \expos - Pointer p; // \expos - }; -} -\end{codeblock} - -\pnum -\tcode{Pointer} shall meet the \oldconcept{NullablePointer} requirements. -If \tcode{Smart} is a specialization of \tcode{shared_ptr}, -the program is ill-formed. -\begin{note} -It is impossible to properly acquire unique ownership of the managed resource -from a \tcode{shared_ptr} given its shared ownership model. -\end{note} - -\pnum -Program-defined specializations of \tcode{inout_ptr_t} -that depend on at least one program-defined type -need not meet the requirements for the primary template. - -\pnum -Evaluations of the conversion functions on the same object -may conflict\iref{intro.races}. - -\indexlibraryctor{inout_ptr_t}% -\begin{itemdecl} -explicit inout_ptr_t(Smart& smart, Args... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{s} with \tcode{smart}, -\tcode{a} with \tcode{std::forward(args)...}, and -\tcode{p} to either -\begin{itemize} -\item \tcode{smart} if \tcode{is_pointer_v} is \tcode{true}, -\item otherwise, \tcode{smart.get()}. -\end{itemize} - -\pnum -\remarks -An implementation can call \tcode{s.release()}. - -\pnum -\begin{note} -The constructor is not \tcode{noexcept} -to allow for a variety of non-terminating and safe implementation strategies. -For example, an intrusive pointer implementation with a control block -can allocate in the constructor and safely fail with an exception. -\end{note} -\end{itemdescr} - -\indexlibrarydtor{inout_ptr_t}% -\begin{itemdecl} -~inout_ptr_t(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{SP} be -\tcode{\exposid{POINTER_OF_OR}(Smart, Pointer)}\iref{memory.general}. - -\pnum -Let \exposid{release-statement} be \tcode{s.release();} -if an implementation does not call \tcode{s.release()} in the constructor. -Otherwise, it is empty. - -\pnum -\effects -Equivalent to: -\begin{itemize} -\item -% pretend to \item that there is real text here, but undo the vertical spacing -\mbox{}\vspace{-\baselineskip}\vspace{-\parskip} -\begin{codeblock} -if (p) { - apply([&](auto&&... args) { - s = Smart( static_cast(p), std::forward(args)...); }, std::move(a)); -} -\end{codeblock} -if \tcode{is_pointer_v} is \tcode{true}; -\item -otherwise, -\begin{codeblock} -if (p) { - apply([&](auto&&... args) { - @\exposid{release-statement}@; - s.reset(static_cast(p), std::forward(args)...); }, std::move(a)); -} -\end{codeblock} -if the expression -\tcode{s.reset(static_cast(p), std::forward(args)...)} -is well-\newline formed; -\item -otherwise, -\begin{codeblock} -if (p) { - apply([&](auto&&... args) { - @\exposid{release-statement}@; - s = Smart(static_cast(p), std::forward(args)...); }, std::move(a)); -} -\end{codeblock} -if \tcode{is_constructible_v} is \tcode{true}; -\item -otherwise, the program is ill-formed. -\end{itemize} -\end{itemdescr} - -\begin{itemdecl} -operator Pointer*() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{operator void**()} has not been called on \tcode{*this}. - -\pnum -\returns -\tcode{addressof(const_cast(p))}. -\end{itemdescr} - -\begin{itemdecl} -operator void**() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_same_v} is \tcode{false}. - -\pnum -\mandates -\tcode{is_pointer_v} is \tcode{true}. - -\pnum -\expects -\tcode{operator Pointer*()} has not been called on \tcode{*this}. - -\pnum -\returns -A pointer value \tcode{v} such that: -\begin{itemize} -\item -the initial value \tcode{*v} is equivalent to \tcode{static_cast(p)} and -\item -any modification of \tcode{*v} -that is not followed by subsequent modification of \tcode{*this} -affects the value of \tcode{p} during the destruction of \tcode{*this}, -such that \tcode{static_cast(p) == *v}. -\end{itemize} - -\pnum -\remarks -Accessing \tcode{*v} outside the lifetime of \tcode{*this} -has undefined behavior. - -\pnum -\begin{note} -\tcode{reinterpret_cast(static_cast(*this))} -can be a viable implementation strategy for some implementations. -\end{note} -\end{itemdescr} - -\rSec3[inout.ptr]{Function template \tcode{inout_ptr}} - -\indexlibraryglobal{inout_ptr}% -\begin{itemdecl} -template - auto inout_ptr(Smart& s, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{P} be \tcode{Pointer} if \tcode{is_void_v} is \tcode{false}, -otherwise \tcode{\exposid{POINTER_OF}(Smart)}. - -\pnum -\returns -\tcode{inout_ptr_t(s, std::forward(args)...)}. -\end{itemdescr} - -\rSec1[mem.res]{Memory resources} - -\rSec2[mem.res.syn]{Header \tcode{} synopsis} - -\indexheader{memory_resource}% -\begin{codeblock} -namespace std::pmr { - // \ref{mem.res.class}, class \tcode{memory_resource} - class memory_resource; - - bool operator==(const memory_resource& a, const memory_resource& b) noexcept; - - // \ref{mem.poly.allocator.class}, class template \tcode{polymorphic_allocator} - template class polymorphic_allocator; - - template - bool operator==(const polymorphic_allocator& a, - const polymorphic_allocator& b) noexcept; - - // \ref{mem.res.global}, global memory resources - memory_resource* new_delete_resource() noexcept; - memory_resource* null_memory_resource() noexcept; - memory_resource* set_default_resource(memory_resource* r) noexcept; - memory_resource* get_default_resource() noexcept; - - // \ref{mem.res.pool}, pool resource classes - struct pool_options; - class synchronized_pool_resource; - class unsynchronized_pool_resource; - class monotonic_buffer_resource; -} -\end{codeblock} - -\rSec2[mem.res.class]{Class \tcode{memory_resource}} - -\rSec3[mem.res.class.general]{General} - -\pnum -The \tcode{memory_resource} class is an abstract interface to an unbounded set of classes encapsulating memory resources. - -\indexlibraryglobal{memory_resource}% -\indexlibrarymember{operator=}{memory_resource}% -\begin{codeblock} -namespace std::pmr { - class memory_resource { - static constexpr size_t max_align = alignof(max_align_t); // \expos - - public: - memory_resource() = default; - memory_resource(const memory_resource&) = default; - virtual ~memory_resource(); - - memory_resource& operator=(const memory_resource&) = default; - - [[nodiscard]] void* allocate(size_t bytes, size_t alignment = max_align); - void deallocate(void* p, size_t bytes, size_t alignment = max_align); - - bool is_equal(const memory_resource& other) const noexcept; - - private: - virtual void* do_allocate(size_t bytes, size_t alignment) = 0; - virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0; - - virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; - }; -} -\end{codeblock} - - -\rSec3[mem.res.public]{Public member functions} - -\indexlibrarydtor{memory_resource}% -\begin{itemdecl} -~memory_resource(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Destroys this \tcode{memory_resource}. -\end{itemdescr} - -\indexlibrarymember{allocate}{memory_resource}% -\begin{itemdecl} -[[nodiscard]] void* allocate(size_t bytes, size_t alignment = max_align); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Allocates storage by calling \tcode{do_allocate(bytes, alignment)} and -implicitly creates objects within the allocated region of storage. - -\pnum -\returns -A pointer to a suitable created object\iref{intro.object} -in the allocated region of storage. - -\pnum -\throws -What and when the call to \tcode{do_allocate} throws. -\end{itemdescr} - -\indexlibrarymember{deallocate}{memory_resource}% -\begin{itemdecl} -void deallocate(void* p, size_t bytes, size_t alignment = max_align); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{do_deallocate(p, bytes, alignment)}. -\end{itemdescr} - -\indexlibrarymember{is_equal}{memory_resource}% -\begin{itemdecl} -bool is_equal(const memory_resource& other) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return do_is_equal(other);} -\end{itemdescr} - - -\rSec3[mem.res.private]{Private virtual member functions} - -\indexlibrarymember{do_allocate}{memory_resource}% -\begin{itemdecl} -virtual void* do_allocate(size_t bytes, size_t alignment) = 0; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{alignment} is a power of two. - -\pnum -\returns -A derived class shall implement this function to -return a pointer to allocated storage\iref{basic.stc.dynamic.allocation} -with a size of at least \tcode{bytes}, -aligned to the specified \tcode{alignment}. - -\pnum -\throws -A derived class implementation shall throw an appropriate exception if it is unable to allocate memory with the requested size and alignment. -\end{itemdescr} - -\indexlibrarymember{do_deallocate}{memory_resource}% -\begin{itemdecl} -virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} was returned from a prior call to \tcode{allocate(bytes, alignment)} -on a memory resource equal to \tcode{*this}, -and the storage at \tcode{p} has not yet been deallocated. - -\pnum -\effects -A derived class shall implement this function to dispose of allocated storage. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{do_is_equal}{memory_resource}% -\begin{itemdecl} -virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A derived class shall implement this function to return \tcode{true} if memory allocated from \keyword{this} can be deallocated from \tcode{other} and vice-versa, -otherwise \tcode{false}. -\begin{note} -It is possible that the most-derived type of \tcode{other} does not match the type of \keyword{this}. -For a derived class \tcode{D}, an implementation of this function -can immediately return \tcode{false} -if \tcode{dynamic_cast(\&other) == nullptr}. -\end{note} -\end{itemdescr} - -\rSec3[mem.res.eq]{Equality} - -\indexlibrarymember{operator==}{memory_resource}% -\begin{itemdecl} -bool operator==(const memory_resource& a, const memory_resource& b) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{\&a == \&b || a.is_equal(b)}. -\end{itemdescr} - -\rSec2[mem.poly.allocator.class]{Class template \tcode{polymorphic_allocator}} - -\rSec3[mem.poly.allocator.class.general]{General} - -\pnum -A specialization of class template \tcode{pmr::polymorphic_allocator} -meets the \oldconcept{Allocator} requirements (\tref{cpp17.allocator}). -Constructed with different memory resources, -different instances of the same specialization of \tcode{pmr::polymorphic_allocator} -can exhibit entirely different allocation behavior. -This runtime polymorphism allows objects that use \tcode{polymorphic_allocator} -to behave as if they used different allocator types at run time -even though they use the same static allocator type. - -\pnum -All specializations of class template \tcode{pmr::polymorphic_allocator} -meet the allocator completeness requirements\iref{allocator.requirements.completeness}. - -\indexlibraryglobal{polymorphic_allocator}% -\indexlibrarymember{value_type}{polymorphic_allocator}% -\begin{codeblock} -namespace std::pmr { - template class polymorphic_allocator { - memory_resource* memory_rsrc; // \expos - - public: - using value_type = Tp; - - // \ref{mem.poly.allocator.ctor}, constructors - polymorphic_allocator() noexcept; - polymorphic_allocator(memory_resource* r); - - polymorphic_allocator(const polymorphic_allocator& other) = default; - - template - polymorphic_allocator(const polymorphic_allocator& other) noexcept; - - polymorphic_allocator& operator=(const polymorphic_allocator&) = delete; - - // \ref{mem.poly.allocator.mem}, member functions - [[nodiscard]] Tp* allocate(size_t n); - void deallocate(Tp* p, size_t n); - - [[nodiscard]] void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t)); - void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t)); - template [[nodiscard]] T* allocate_object(size_t n = 1); - template void deallocate_object(T* p, size_t n = 1); - template [[nodiscard]] T* new_object(CtorArgs&&... ctor_args); - template void delete_object(T* p); - - template - void construct(T* p, Args&&... args); - - polymorphic_allocator select_on_container_copy_construction() const; - - memory_resource* resource() const; - }; -} -\end{codeblock} - -\rSec3[mem.poly.allocator.ctor]{Constructors} - -\indexlibraryctor{polymorphic_allocator}% -\begin{itemdecl} -polymorphic_allocator() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Sets \tcode{memory_rsrc} to \tcode{get_default_resource()}. -\end{itemdescr} - -\indexlibraryctor{polymorphic_allocator}% -\begin{itemdecl} -polymorphic_allocator(memory_resource* r); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{r} is non-null. - -\pnum -\effects -Sets \tcode{memory_rsrc} to \tcode{r}. - -\pnum -\throws -Nothing. - -\pnum -\begin{note} -This constructor provides an implicit conversion from \tcode{memory_resource*}. -\end{note} -\end{itemdescr} - -\indexlibraryctor{polymorphic_allocator}% -\begin{itemdecl} -template polymorphic_allocator(const polymorphic_allocator& other) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Sets \tcode{memory_rsrc} to \tcode{other.resource()}. -\end{itemdescr} - - -\rSec3[mem.poly.allocator.mem]{Member functions} - -\indexlibrarymember{allocate}{polymorphic_allocator}% -\begin{itemdecl} -[[nodiscard]] Tp* allocate(size_t n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If \tcode{numeric_limits::max() / sizeof(Tp) < n}, -throws \tcode{bad_array_new_length}. -Otherwise equivalent to: -\begin{codeblock} -return static_cast(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp))); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{deallocate}{polymorphic_allocator}% -\begin{itemdecl} -void deallocate(Tp* p, size_t n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} was allocated from a memory resource \tcode{x}, -equal to \tcode{*memory_rsrc}, -using \tcode{x.allocate(n * sizeof(Tp), alignof(Tp))}. - -\pnum -\effects -Equivalent to \tcode{memory_rsrc->deallocate(p, n * sizeof(Tp), alignof(Tp))}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{allocate_bytes}{polymorphic_allocator}% -\begin{itemdecl} -[[nodiscard]] void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return memory_rsrc->allocate(nbytes, alignment);} - -\pnum -\begin{note} -The return type is \tcode{void*} (rather than, e.g., \tcode{byte*}) -to support conversion to an arbitrary pointer type \tcode{U*} -by \tcode{static_cast}, thus facilitating construction of a \tcode{U} -object in the allocated memory. -\end{note} -\end{itemdescr} - -\indexlibrarymember{deallocate_bytes}{polymorphic_allocator}% -\begin{itemdecl} -void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t)); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{memory_rsrc->deallocate(p, nbytes, alignment)}. -\end{itemdescr} - -\indexlibrarymember{allocate_object}{polymorphic_allocator}% -\begin{itemdecl} -template - [[nodiscard]] T* allocate_object(size_t n = 1); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Allocates memory suitable for holding -an array of \tcode{n} objects of type \tcode{T}, as follows: -\begin{itemize} -\item - if \tcode{numeric_limits::max() / sizeof(T) < n}, - throws \tcode{bad_array_new_length}, -\item - otherwise equivalent to: -\begin{codeblock} -return static_cast(allocate_bytes(n*sizeof(T), alignof(T))); -\end{codeblock} -\end{itemize} - -\pnum -\begin{note} -\tcode{T} is not deduced and must therefore be provided as a template argument. -\end{note} -\end{itemdescr} - -\indexlibrarymember{deallocate_object}{polymorphic_allocator}% -\begin{itemdecl} -template - void deallocate_object(T* p, size_t n = 1); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{deallocate_bytes(p, n*sizeof(T), alignof(T))}. -\end{itemdescr} - -\indexlibrarymember{new_object}{polymorphic_allocator}% -\begin{itemdecl} -template - [[nodiscard]] T* new_object(CtorArgs&&... ctor_args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Allocates and constructs an object of type \tcode{T}, as follows.\newline -Equivalent to: -\begin{codeblock} -T* p = allocate_object(); -try { - construct(p, std::forward(ctor_args)...); -} catch (...) { - deallocate_object(p); - throw; -} -return p; -\end{codeblock} - -\pnum -\begin{note} -\tcode{T} is not deduced and must therefore be provided as a template argument. -\end{note} -\end{itemdescr} - -\indexlibrarymember{new_object}{polymorphic_allocator}% -\begin{itemdecl} -template - void delete_object(T* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -allocator_traits::destroy(*this, p); -deallocate_object(p); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{construct}{polymorphic_allocator}% -\begin{itemdecl} -template - void construct(T* p, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -Uses-allocator construction of \tcode{T} -with allocator \tcode{*this} (see~\ref{allocator.uses.construction}) -and constructor arguments \tcode{std::forward(args)...} is well-formed. - -\pnum -\effects -Construct a \tcode{T} object in the storage -whose address is represented by \tcode{p} -by uses-allocator construction with allocator \tcode{*this} -and constructor arguments \tcode{std::forward(args)...}. - -\pnum -\throws -Nothing unless the constructor for \tcode{T} throws. -\end{itemdescr} - -\indexlibrarymember{select_on_container_copy_construction}{polymorphic_allocator}% -\begin{itemdecl} -polymorphic_allocator select_on_container_copy_construction() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{polymorphic_allocator()}. - -\pnum -\begin{note} -The memory resource is not propagated. -\end{note} -\end{itemdescr} - -\indexlibrarymember{resource}{polymorphic_allocator}% -\begin{itemdecl} -memory_resource* resource() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{memory_rsrc}. -\end{itemdescr} - -\rSec3[mem.poly.allocator.eq]{Equality} - -\indexlibrarymember{operator==}{polymorphic_allocator}% -\begin{itemdecl} -template - bool operator==(const polymorphic_allocator& a, - const polymorphic_allocator& b) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{*a.resource() == *b.resource()}. -\end{itemdescr} - -\rSec2[mem.res.global]{Access to program-wide \tcode{memory_resource} objects} - -\indexlibraryglobal{new_delete_resource}% -\begin{itemdecl} -memory_resource* new_delete_resource() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A pointer to a static-duration object of a type derived from \tcode{memory_resource} -that can serve as a resource for allocating memory -using \tcode{::operator new} and \tcode{::operator delete}. -The same value is returned every time this function is called. -For a return value \tcode{p} and a memory resource \tcode{r}, -\tcode{p->is_equal(r)} returns \tcode{\&r == p}. -\end{itemdescr} - -\indexlibraryglobal{null_memory_resource}% -\begin{itemdecl} -memory_resource* null_memory_resource() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A pointer to a static-duration object of a type derived from \tcode{memory_resource} -for which \tcode{allocate()} always throws \tcode{bad_alloc} and -for which \tcode{deallocate()} has no effect. -The same value is returned every time this function is called. -For a return value \tcode{p} and a memory resource \tcode{r}, -\tcode{p->is_equal(r)} returns \tcode{\&r == p}. -\end{itemdescr} - -\pnum -The \defn{default memory resource pointer} is a pointer to a memory resource -that is used by certain facilities when an explicit memory resource -is not supplied through the interface. -Its initial value is the return value of \tcode{new_delete_resource()}. - -\indexlibraryglobal{set_default_resource}% -\begin{itemdecl} -memory_resource* set_default_resource(memory_resource* r) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If \tcode{r} is non-null, -sets the value of the default memory resource pointer to \tcode{r}, -otherwise sets the default memory resource pointer to \tcode{new_delete_resource()}. - -\pnum -\returns -The previous value of the default memory resource pointer. - -\pnum -\remarks -Calling the \tcode{set_default_resource} and -\tcode{get_default_resource} functions shall not incur a data race. -A call to the \tcode{set_default_resource} function -shall synchronize with subsequent calls to -the \tcode{set_default_resource} and \tcode{get_default_resource} functions. -\end{itemdescr} - -\indexlibraryglobal{get_default_resource}% -\begin{itemdecl} -memory_resource* get_default_resource() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The current value of the default memory resource pointer. -\end{itemdescr} - -\rSec2[mem.res.pool]{Pool resource classes} - -\rSec3[mem.res.pool.overview]{Classes \tcode{synchronized_pool_resource} and \tcode{unsynchronized_pool_resource}} - -\pnum -The \tcode{synchronized_pool_resource} and -\tcode{unsynchronized_pool_resource} classes -(collectively called \defn{pool resource classes}) -are general-purpose memory resources having the following qualities: -\begin{itemize} -\item -Each resource frees its allocated memory on destruction, -even if \tcode{deallocate} has not been called for some of the allocated blocks. -\item -A pool resource consists of a collection of \defn{pools}, -serving requests for different block sizes. -Each individual pool manages a collection of \defn{chunks} -that are in turn divided into blocks of uniform size, -returned via calls to \tcode{do_allocate}. -Each call to \tcode{do_allocate(size, alignment)} is dispatched -to the pool serving the smallest blocks accommodating at least \tcode{size} bytes. -\item -When a particular pool is exhausted, -allocating a block from that pool results in the allocation -of an additional chunk of memory from the \defn{upstream allocator} -(supplied at construction), thus replenishing the pool. -With each successive replenishment, -the chunk size obtained increases geometrically. -\begin{note} -By allocating memory in chunks, -the pooling strategy increases the chance that consecutive allocations -will be close together in memory. -\end{note} -\item -Allocation requests that exceed the largest block size of any pool -are fulfilled directly from the upstream allocator. -\item -A \tcode{pool_options} struct may be passed to the pool resource constructors -to tune the largest block size and the maximum chunk size. -\end{itemize} - -\pnum -A \tcode{synchronized_pool_resource} may be accessed from multiple threads -without external synchronization -and may have thread-specific pools to reduce synchronization costs. -An \tcode{unsynchronized_pool_resource} class may not be accessed -from multiple threads simultaneously -and thus avoids the cost of synchronization entirely -in single-threaded applications. - -\indexlibraryglobal{pool_options}% -\indexlibraryglobal{synchronized_pool_resource}% -\indexlibraryglobal{unsynchronized_pool_resource}% -\begin{codeblock} -namespace std::pmr { - struct pool_options { - size_t max_blocks_per_chunk = 0; - size_t largest_required_pool_block = 0; - }; - - class synchronized_pool_resource : public memory_resource { - public: - synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); - - synchronized_pool_resource() - : synchronized_pool_resource(pool_options(), get_default_resource()) {} - explicit synchronized_pool_resource(memory_resource* upstream) - : synchronized_pool_resource(pool_options(), upstream) {} - explicit synchronized_pool_resource(const pool_options& opts) - : synchronized_pool_resource(opts, get_default_resource()) {} - - synchronized_pool_resource(const synchronized_pool_resource&) = delete; - virtual ~synchronized_pool_resource(); - - synchronized_pool_resource& operator=(const synchronized_pool_resource&) = delete; - - void release(); - memory_resource* upstream_resource() const; - pool_options options() const; - - protected: - void* do_allocate(size_t bytes, size_t alignment) override; - void do_deallocate(void* p, size_t bytes, size_t alignment) override; - - bool do_is_equal(const memory_resource& other) const noexcept override; - }; - - class unsynchronized_pool_resource : public memory_resource { - public: - unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream); - - unsynchronized_pool_resource() - : unsynchronized_pool_resource(pool_options(), get_default_resource()) {} - explicit unsynchronized_pool_resource(memory_resource* upstream) - : unsynchronized_pool_resource(pool_options(), upstream) {} - explicit unsynchronized_pool_resource(const pool_options& opts) - : unsynchronized_pool_resource(opts, get_default_resource()) {} - - unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete; - virtual ~unsynchronized_pool_resource(); - - unsynchronized_pool_resource& operator=(const unsynchronized_pool_resource&) = delete; - - void release(); - memory_resource* upstream_resource() const; - pool_options options() const; - - protected: - void* do_allocate(size_t bytes, size_t alignment) override; - void do_deallocate(void* p, size_t bytes, size_t alignment) override; - - bool do_is_equal(const memory_resource& other) const noexcept override; - }; -} -\end{codeblock} - -\rSec3[mem.res.pool.options]{\tcode{pool_options} data members} - -\pnum -The members of \tcode{pool_options} -comprise a set of constructor options for pool resources. -The effect of each option on the pool resource behavior is described below: - -\indexlibrarymember{pool_options}{max_blocks_per_chunk}% -\begin{itemdecl} -size_t max_blocks_per_chunk; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The maximum number of blocks that will be allocated at once -from the upstream memory resource\iref{mem.res.monotonic.buffer} -to replenish a pool. -If the value of \tcode{max_blocks_per_chunk} is zero or -is greater than an \impldef{largest supported value to configure the maximum number of blocks to replenish a pool} -limit, that limit is used instead. -The implementation -may choose to use a smaller value than is specified in this field and -may use different values for different pools. -\end{itemdescr} - -\indexlibrarymember{pool_options}{largest_required_pool_block}% -\begin{itemdecl} -size_t largest_required_pool_block; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The largest allocation size that is required to be fulfilled -using the pooling mechanism. -Attempts to allocate a single block larger than this threshold -will be allocated directly from the upstream memory resource. -If \tcode{largest_required_pool_block} is zero or -is greater than an \impldef{largest supported value to configure the largest allocation satisfied directly by a pool} -limit, that limit is used instead. -The implementation may choose a pass-through threshold -larger than specified in this field. -\end{itemdescr} - -\rSec3[mem.res.pool.ctor]{Constructors and destructors} - -\indexlibraryctor{synchronized_pool_resource}% -\indexlibraryctor{unsynchronized_pool_resource}% -\begin{itemdecl} -synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); -unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{upstream} is the address of a valid memory resource. - -\pnum -\effects -Constructs a pool resource object that will obtain memory from \tcode{upstream} -whenever the pool resource is unable to satisfy a memory request -from its own internal data structures. -The resulting object will hold a copy of \tcode{upstream}, -but will not own the resource to which \tcode{upstream} points. -\begin{note} -The intention is that calls to \tcode{upstream->allocate()} -will be substantially fewer than calls to \tcode{this->allocate()} -in most cases. -\end{note} -The behavior of the pooling mechanism is tuned -according to the value of the \tcode{opts} argument. - -\pnum -\throws -Nothing unless \tcode{upstream->allocate()} throws. -It is unspecified if, or under what conditions, -this constructor calls \tcode{upstream->allocate()}. -\end{itemdescr} - -\indexlibrarydtor{synchronized_pool_resource}% -\indexlibrarydtor{unsynchronized_pool_resource}% -\begin{itemdecl} -virtual ~synchronized_pool_resource(); -virtual ~unsynchronized_pool_resource(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls \tcode{release()}. -\end{itemdescr} - -\rSec3[mem.res.pool.mem]{Members} - -\indexlibrarymember{release}{synchronized_pool_resource}% -\indexlibrarymember{release}{unsynchronized_pool_resource}% -\begin{itemdecl} -void release(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls \tcode{upstream_resource()->deallocate()} as necessary -to release all allocated memory. -\begin{note} -The memory is released back to \tcode{upstream_resource()} -even if \tcode{deallocate} has not been called -for some of the allocated blocks. -\end{note} -\end{itemdescr} - -\indexlibrarymember{upstream_resource}{synchronized_pool_resource}% -\indexlibrarymember{upstream_resource}{unsynchronized_pool_resource}% -\begin{itemdecl} -memory_resource* upstream_resource() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The value of the \tcode{upstream} argument -provided to the constructor of this object. -\end{itemdescr} - -\indexlibrarymember{options}{synchronized_pool_resource}% -\indexlibrarymember{options}{unsynchronized_pool_resource}% -\begin{itemdecl} -pool_options options() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The options that control the pooling behavior of this resource. -The values in the returned struct may differ -from those supplied to the pool resource constructor in that -values of zero will be replaced with \impldef{default configuration of a pool} -defaults, and sizes may be rounded to unspecified granularity. -\end{itemdescr} - -\indexlibrarymember{do_allocate}{synchronized_pool_resource}% -\indexlibrarymember{do_allocate}{unsynchronized_pool_resource}% -\begin{itemdecl} -void* do_allocate(size_t bytes, size_t alignment) override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If the pool selected for a block of size \tcode{bytes} -is unable to satisfy the memory request from its own internal data structures, -it will call \tcode{upstream_resource()->allocate()} to obtain more memory. -If \tcode{bytes} is larger than that which the largest pool can handle, -then memory will be allocated using \tcode{upstream_resource()->allocate()}. - -\pnum -\returns -A pointer to allocated storage\iref{basic.stc.dynamic.allocation} -with a size of at least \tcode{bytes}. -The size and alignment of the allocated memory shall meet the requirements -for a class derived from \tcode{memory_resource}\iref{mem.res.class}. - -\pnum -\throws -Nothing unless \tcode{upstream_resource()->allocate()} throws. -\end{itemdescr} - -\indexlibrarymember{do_deallocate}{synchronized_pool_resource}% -\indexlibrarymember{do_deallocate}{unsynchronized_pool_resource}% -\begin{itemdecl} -void do_deallocate(void* p, size_t bytes, size_t alignment) override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Returns the memory at \tcode{p} to the pool. -It is unspecified if, or under what circumstances, -this operation will result in a call to \tcode{upstream_resource()->deallocate()}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{do_is_equal}{synchronized_pool_resource}% -\indexlibrarymember{do_is_equal}{unsynchronized_pool_resource}% -\begin{itemdecl} -bool do_is_equal(const memory_resource& other) const noexcept override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{this == \&other}. -\end{itemdescr} - -\rSec2[mem.res.monotonic.buffer]{Class \tcode{monotonic_buffer_resource}} - -\rSec3[mem.res.monotonic.buffer.general]{General} - -\pnum -A \tcode{monotonic_buffer_resource} is a special-purpose memory resource -intended for very fast memory allocations in situations -where memory is used to build up a few objects -and then is released all at once when the memory resource object is destroyed. - -\indexlibraryglobal{monotonic_buffer_resource}% -\begin{codeblock} -namespace std::pmr { - class monotonic_buffer_resource : public memory_resource { - memory_resource* upstream_rsrc; // \expos - void* current_buffer; // \expos - size_t next_buffer_size; // \expos - - public: - explicit monotonic_buffer_resource(memory_resource* upstream); - monotonic_buffer_resource(size_t initial_size, memory_resource* upstream); - monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream); - - monotonic_buffer_resource() - : monotonic_buffer_resource(get_default_resource()) {} - explicit monotonic_buffer_resource(size_t initial_size) - : monotonic_buffer_resource(initial_size, get_default_resource()) {} - monotonic_buffer_resource(void* buffer, size_t buffer_size) - : monotonic_buffer_resource(buffer, buffer_size, get_default_resource()) {} - - monotonic_buffer_resource(const monotonic_buffer_resource&) = delete; - - virtual ~monotonic_buffer_resource(); - - monotonic_buffer_resource& operator=(const monotonic_buffer_resource&) = delete; - - void release(); - memory_resource* upstream_resource() const; - - protected: - void* do_allocate(size_t bytes, size_t alignment) override; - void do_deallocate(void* p, size_t bytes, size_t alignment) override; - - bool do_is_equal(const memory_resource& other) const noexcept override; - }; -} -\end{codeblock} - -\rSec3[mem.res.monotonic.buffer.ctor]{Constructors and destructor} - -\indexlibraryctor{monotonic_buffer_resource}% -\begin{itemdecl} -explicit monotonic_buffer_resource(memory_resource* upstream); -monotonic_buffer_resource(size_t initial_size, memory_resource* upstream); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{upstream} is the address of a valid memory resource. -\tcode{initial_size}, if specified, is greater than zero. - -\pnum -\effects -Sets \tcode{upstream_rsrc} to \tcode{upstream} and -\tcode{current_buffer} to \keyword{nullptr}. -If \tcode{initial_size} is specified, -sets \tcode{next_buffer_size} to at least \tcode{initial_size}; -otherwise sets \tcode{next_buffer_size} to an -\impldef{default \tcode{next_buffer_size} for a \tcode{monotonic_buffer_resource}} size. -\end{itemdescr} - -\indexlibraryctor{monotonic_buffer_resource}% -\begin{itemdecl} -monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{upstream} is the address of a valid memory resource. -\tcode{buffer_size} is no larger than the number of bytes in \tcode{buffer}. - -\pnum -\effects -Sets \tcode{upstream_rsrc} to \tcode{upstream}, -\tcode{current_buffer} to \tcode{buffer}, and -\tcode{next_buffer_size} to \tcode{buffer_size} (but not less than 1), -then increases \tcode{next_buffer_size} -by an \impldef{growth factor for \tcode{monotonic_buffer_resource}} growth factor (which need not be integral). -\end{itemdescr} - -\indexlibrarydtor{monotonic_buffer_resource}% -\begin{itemdecl} -~monotonic_buffer_resource(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls \tcode{release()}. -\end{itemdescr} - - -\rSec3[mem.res.monotonic.buffer.mem]{Members} - -\indexlibrarymember{release}{monotonic_buffer_resource}% -\begin{itemdecl} -void release(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls \tcode{upstream_rsrc->deallocate()} as necessary -to release all allocated memory. -Resets \tcode{current_buffer} and \tcode{next_buffer_size} -to their initial values at construction. - -\pnum -\begin{note} -The memory is released back to \tcode{upstream_rsrc} -even if some blocks that were allocated from \keyword{this} -have not been deallocated from \keyword{this}. -\end{note} -\end{itemdescr} - -\indexlibrarymember{upstream_resource}{monotonic_buffer_resource}% -\begin{itemdecl} -memory_resource* upstream_resource() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The value of \tcode{upstream_rsrc}. -\end{itemdescr} - -\indexlibrarymember{do_allocate}{monotonic_buffer_resource}% -\begin{itemdecl} -void* do_allocate(size_t bytes, size_t alignment) override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If the unused space in \tcode{current_buffer} -can fit a block with the specified \tcode{bytes} and \tcode{alignment}, -then allocate the return block from \tcode{current_buffer}; -otherwise set \tcode{current_buffer} to \tcode{upstream_rsrc->allocate(n, m)}, -where \tcode{n} is not less than \tcode{max(bytes, next_buffer_size)} and -\tcode{m} is not less than \tcode{alignment}, -and increase \tcode{next_buffer_size} -by an \impldef{growth factor for \tcode{monotonic_buffer_resource}} growth factor (which need not be integral), -then allocate the return block from the newly-allocated \tcode{current_buffer}. - -\pnum -\returns -A pointer to allocated storage\iref{basic.stc.dynamic.allocation} -with a size of at least \tcode{bytes}. -The size and alignment of the allocated memory shall meet the requirements -for a class derived from \tcode{memory_resource}\iref{mem.res.class}. - -\pnum -\throws -Nothing unless \tcode{upstream_rsrc->allocate()} throws. -\end{itemdescr} - -\indexlibrarymember{do_deallocate}{monotonic_buffer_resource}% -\begin{itemdecl} -void do_deallocate(void* p, size_t bytes, size_t alignment) override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -None. - -\pnum -\throws -Nothing. - -\pnum -\remarks -Memory used by this resource increases monotonically until its destruction. -\end{itemdescr} - -\indexlibrarymember{do_is_equal}{monotonic_buffer_resource}% -\begin{itemdecl} -bool do_is_equal(const memory_resource& other) const noexcept override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{this == \&other}. -\end{itemdescr} - - -\rSec1[allocator.adaptor]{Class template \tcode{scoped_allocator_adaptor}} - -\rSec2[allocator.adaptor.syn]{Header \tcode{} synopsis} - -\indexheader{scoped_allocator}% -\begin{codeblock} -namespace std { - // class template \tcode{scoped allocator adaptor} - template - class scoped_allocator_adaptor; - - // \ref{scoped.adaptor.operators}, scoped allocator operators - template - bool operator==(const scoped_allocator_adaptor& a, - const scoped_allocator_adaptor& b) noexcept; -} -\end{codeblock} - -\pnum -The class template \tcode{scoped_allocator_adaptor} is an allocator template that -specifies an allocator resource (the outer allocator) to be used by a container (as any -other allocator does) and also specifies an inner allocator resource to be passed to the -constructor of every element within the container. This adaptor is instantiated with one -outer and zero or more inner allocator types. If instantiated with only one allocator -type, the inner allocator becomes the \tcode{scoped_allocator_adaptor} itself, thus -using the same allocator resource for the container and every element within the -container and, if the elements themselves are containers, each of their elements -recursively. If instantiated with more than one allocator, the first allocator is the -outer allocator for use by the container, the second allocator is passed to the -constructors of the container's elements, and, if the elements themselves are -containers, the third allocator is passed to the elements' elements, and so on. If -containers are nested to a depth greater than the number of allocators, the last -allocator is used repeatedly, as in the single-allocator case, for any remaining -recursions. -\begin{note} -The \tcode{scoped_allocator_adaptor} is derived from the outer -allocator type so it can be substituted for the outer allocator type in most -expressions. -\end{note} - -\indexlibraryglobal{scoped_allocator_adaptor}% -\indexlibrarymember{outer_allocator_type}{scoped_allocator_adaptor}% -\indexlibrarymember{value_type}{scoped_allocator_adaptor}% -\indexlibrarymember{size_type}{scoped_allocator_adaptor}% -\indexlibrarymember{difference_type}{scoped_allocator_adaptor}% -\indexlibrarymember{pointer}{scoped_allocator_adaptor}% -\indexlibrarymember{const_pointer}{scoped_allocator_adaptor}% -\indexlibrarymember{void_pointer}{scoped_allocator_adaptor}% -\indexlibrarymember{const_void_pointer}{scoped_allocator_adaptor}% -\begin{codeblock} -namespace std { - template - class scoped_allocator_adaptor : public OuterAlloc { - private: - using OuterTraits = allocator_traits; // \expos - scoped_allocator_adaptor inner; // \expos - - public: - using outer_allocator_type = OuterAlloc; - using inner_allocator_type = @\seebelow@; - - using value_type = typename OuterTraits::value_type; - using size_type = typename OuterTraits::size_type; - using difference_type = typename OuterTraits::difference_type; - using pointer = typename OuterTraits::pointer; - using const_pointer = typename OuterTraits::const_pointer; - using void_pointer = typename OuterTraits::void_pointer; - using const_void_pointer = typename OuterTraits::const_void_pointer; - - using propagate_on_container_copy_assignment = @\seebelow@; - using propagate_on_container_move_assignment = @\seebelow@; - using propagate_on_container_swap = @\seebelow@; - using is_always_equal = @\seebelow@; - - template struct rebind { - using other = scoped_allocator_adaptor< - OuterTraits::template rebind_alloc, InnerAllocs...>; - }; - - scoped_allocator_adaptor(); - template - scoped_allocator_adaptor(OuterA2&& outerAlloc, - const InnerAllocs&... innerAllocs) noexcept; - - scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept; - scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; - - template - scoped_allocator_adaptor( - const scoped_allocator_adaptor& other) noexcept; - template - scoped_allocator_adaptor( - scoped_allocator_adaptor&& other) noexcept; - - scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default; - scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default; - - ~scoped_allocator_adaptor(); - - inner_allocator_type& inner_allocator() noexcept; - const inner_allocator_type& inner_allocator() const noexcept; - outer_allocator_type& outer_allocator() noexcept; - const outer_allocator_type& outer_allocator() const noexcept; - - [[nodiscard]] pointer allocate(size_type n); - [[nodiscard]] pointer allocate(size_type n, const_void_pointer hint); - void deallocate(pointer p, size_type n); - size_type max_size() const; - - template - void construct(T* p, Args&&... args); - - template - void destroy(T* p); - - scoped_allocator_adaptor select_on_container_copy_construction() const; - }; - - template - scoped_allocator_adaptor(OuterAlloc, InnerAllocs...) - -> scoped_allocator_adaptor; -} -\end{codeblock} - -\rSec2[allocator.adaptor.types]{Member types} - -\indexlibrarymember{inner_allocator_type}{scoped_allocator_adaptor}% -\begin{itemdecl} -using inner_allocator_type = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{scoped_allocator_adaptor} if \tcode{sizeof...(InnerAllocs)} is -zero; otherwise,\\ \tcode{scoped_allocator_adaptor}. -\end{itemdescr} - -\indexlibrarymember{propagate_on_container_copy_assignment}{scoped_allocator_adaptor}% -\begin{itemdecl} -using propagate_on_container_copy_assignment = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{true_type} if -\tcode{allocator_traits::propagate_on_container_copy_assignment::value} is -\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and -\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. -\end{itemdescr} - -\indexlibrarymember{propagate_on_container_move_assignment}{scoped_allocator_adaptor}% -\begin{itemdecl} -using propagate_on_container_move_assignment = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{true_type} if -\tcode{allocator_traits::propagate_on_container_move_assignment::value} is -\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and -\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. -\end{itemdescr} - -\indexlibrarymember{propagate_on_container_swap}{scoped_allocator_adaptor}% -\begin{itemdecl} -using propagate_on_container_swap = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{true_type} if -\tcode{allocator_traits::propagate_on_container_swap::value} is -\tcode{true} for any \tcode{A} in the set of \tcode{OuterAlloc} and -\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. -\end{itemdescr} - -\indexlibrarymember{is_always_equal}{scoped_allocator_adaptor}% -\begin{itemdecl} -using is_always_equal = @\seebelow@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ctype \tcode{true_type} if -\tcode{allocator_traits::is_always_equal::value} is -\tcode{true} for every \tcode{A} in the set of \tcode{OuterAlloc} and -\tcode{InnerAllocs...}; otherwise, \tcode{false_type}. -\end{itemdescr} - -\rSec2[allocator.adaptor.cnstr]{Constructors} - -\indexlibraryctor{scoped_allocator_adaptor}% -\begin{itemdecl} -scoped_allocator_adaptor(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Value-initializes the \tcode{OuterAlloc} base class and the \tcode{inner} allocator -object. -\end{itemdescr} - -\indexlibraryctor{scoped_allocator_adaptor}% -\begin{itemdecl} -template - scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. - -\pnum -\effects -Initializes the \tcode{OuterAlloc} base class with -\tcode{std::forward(outerAlloc)} and \tcode{inner} with \tcode{innerAllocs...} -(hence recursively initializing each allocator within the adaptor with the corresponding -allocator from the argument list). -\end{itemdescr} - -\indexlibraryctor{scoped_allocator_adaptor}% -\begin{itemdecl} -scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes each allocator within the adaptor with the corresponding allocator -from \tcode{other}. -\end{itemdescr} - -\indexlibraryctor{scoped_allocator_adaptor}% -\begin{itemdecl} -scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Move constructs each allocator within the adaptor with the corresponding allocator -from \tcode{other}. -\end{itemdescr} - -\indexlibraryctor{scoped_allocator_adaptor}% -\begin{itemdecl} -template - scoped_allocator_adaptor( - const scoped_allocator_adaptor& other) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. - -\pnum -\effects -Initializes each allocator within the adaptor with the corresponding allocator -from \tcode{other}. -\end{itemdescr} - -\indexlibraryctor{scoped_allocator_adaptor}% -\begin{itemdecl} -template - scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. - -\pnum -\effects -Initializes each allocator within the adaptor with the corresponding allocator rvalue -from \tcode{other}. -\end{itemdescr} - -\rSec2[allocator.adaptor.members]{Members} - -\pnum -In the \tcode{construct} member functions, -\tcode{\placeholdernc{OUTERMOST}(x)} is -\tcode{\placeholdernc{OUTERMOST}(x.outer_allocator())} if -the expression \tcode{x.outer_allocator()} is -valid~\iref{temp.deduct} and -\tcode{x} otherwise; -\tcode{\placeholdernc{OUTERMOST_ALLOC_TRAITS}(x)} is -\tcode{allocator_traits>}. -\begin{note} -\tcode{\placeholdernc{OUTERMOST}(x)} and -\tcode{\placeholdernc{OUTERMOST_ALL\-OC_TRAITS}(x)} are recursive operations. It -is incumbent upon the definition of \tcode{outer_allocator()} to ensure that the -recursion terminates. It will terminate for all instantiations of -\tcode{scoped_allocator_adaptor}. -\end{note} - -\indexlibrarymember{inner_allocator}{scoped_allocator_adaptor}% -\begin{itemdecl} -inner_allocator_type& inner_allocator() noexcept; -const inner_allocator_type& inner_allocator() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{*this} if \tcode{sizeof...(InnerAllocs)} is zero; otherwise, -\tcode{inner}. -\end{itemdescr} - -\indexlibrarymember{outer_allocator}{scoped_allocator_adaptor}% -\begin{itemdecl} -outer_allocator_type& outer_allocator() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{static_cast(*this)}. -\end{itemdescr} - -\indexlibrarymember{outer_allocator}{scoped_allocator_adaptor}% -\begin{itemdecl} -const outer_allocator_type& outer_allocator() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{static_cast(*this)}. -\end{itemdescr} - -\indexlibrarymember{allocate}{scoped_allocator_adaptor}% -\begin{itemdecl} -[[nodiscard]] pointer allocate(size_type n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{allocator_traits::allocate(outer_allocator(), n)}. -\end{itemdescr} - -\indexlibrarymember{allocate}{scoped_allocator_adaptor}% -\begin{itemdecl} -[[nodiscard]] pointer allocate(size_type n, const_void_pointer hint); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{allocator_traits::allocate(outer_allocator(), n, hint)}. -\end{itemdescr} - -\indexlibrarymember{deallocate}{scoped_allocator_adaptor}% -\begin{itemdecl} -void deallocate(pointer p, size_type n) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by: -\tcode{allocator_traits::deallocate(outer_allocator(), p, n);} -\end{itemdescr} - -\indexlibrarymember{max_size}{scoped_allocator_adaptor}% -\begin{itemdecl} -size_type max_size() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{allocator_traits::max_size(outer_allocator())}. -\end{itemdescr} - -\indexlibrarymember{construct}{scoped_allocator_adaptor}% -\begin{itemdecl} -template - void construct(T* p, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -apply([p, this](auto&&... newargs) { - @\placeholdernc{OUTERMOST_ALLOC_TRAITS}@(*this)::construct( - @\placeholdernc{OUTERMOST}@(*this), p, - std::forward(newargs)...); - }, - uses_allocator_construction_args(inner_allocator(), - std::forward(args)...)); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{destroy}{scoped_allocator_adaptor}% -\begin{itemdecl} -template - void destroy(T* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls \tcode{\placeholdernc{OUTERMOST_ALLOC_TRAITS}(*this)::destroy(\placeholdernc{OUTERMOST}(*this), p)}. -\end{itemdescr} - -\indexlibrarymember{select_on_container_copy_construction}{scoped_allocator_adaptor}% -\begin{itemdecl} -scoped_allocator_adaptor select_on_container_copy_construction() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A new \tcode{scoped_allocator_adaptor} object -where each allocator \tcode{a1} within the adaptor -is initialized with -\tcode{allocator_traits::select_on_container_copy_construction(a2)}, -where \tcode{A1} is the type of \tcode{a1} and -\tcode{a2} is the corresponding allocator in \tcode{*this}. -\end{itemdescr} - -\rSec2[scoped.adaptor.operators]{Operators} - -\indexlibrarymember{operator==}{scoped_allocator_adaptor}% -\begin{itemdecl} -template - bool operator==(const scoped_allocator_adaptor& a, - const scoped_allocator_adaptor& b) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -If \tcode{sizeof...(InnerAllocs)} is zero, -\begin{codeblock} -a.outer_allocator() == b.outer_allocator() -\end{codeblock} -otherwise -\begin{codeblock} -a.outer_allocator() == b.outer_allocator() && a.inner_allocator() == b.inner_allocator() -\end{codeblock} -\end{itemdescr} - \rSec1[function.objects]{Function objects} \rSec2[function.objects.general]{General} diff --git a/tools/check-source.sh b/tools/check-source.sh index 9a90e8b4db..6a8b21ecd7 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -6,7 +6,7 @@ failed=0 # Ignore files where rules may be violated within macro definitions. texfiles=$(ls *.tex | grep -v macros.tex | grep -v layout.tex | grep -v tables.tex) -texlibdesc="support.tex concepts.tex diagnostics.tex utilities.tex strings.tex containers.tex iterators.tex ranges.tex algorithms.tex numerics.tex time.tex locales.tex iostreams.tex regex.tex atomics.tex threads.tex" +texlibdesc="support.tex concepts.tex diagnostics.tex memory.tex utilities.tex strings.tex containers.tex iterators.tex ranges.tex algorithms.tex numerics.tex time.tex locales.tex iostreams.tex regex.tex atomics.tex threads.tex" texlib="lib-intro.tex $texlibdesc" # Filter that reformats the error message as a "workflow command", From cb7b98d46c4603ccc485fe826fb4363cb2c039bf Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 23 Feb 2022 22:48:10 +0100 Subject: [PATCH 158/182] [comparisons.three.way,func.search] Add namespace around class definition --- source/utilities.tex | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/source/utilities.tex b/source/utilities.tex index e8693c39d5..52a1a16d73 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -10549,12 +10549,14 @@ \indexlibraryglobal{compare_three_way}% \begin{codeblock} -struct compare_three_way { - template - constexpr auto operator()(T&& t, U&& u) const; +namespace std { + struct compare_three_way { + template + constexpr auto operator()(T&& t, U&& u) const; - using is_transparent = @\unspec@; -}; + using is_transparent = @\unspec@; + }; +} \end{codeblock} \begin{itemdecl} @@ -12387,7 +12389,8 @@ \indexlibraryglobal{default_searcher}% \begin{codeblock} -template> +namespace std { + template> class default_searcher { public: constexpr default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last, @@ -12402,6 +12405,7 @@ ForwardIterator1 pat_last_; // \expos BinaryPredicate pred_; // \expos }; +} \end{codeblock} \indexlibraryctor{default_searcher}% @@ -12446,9 +12450,10 @@ \indexlibraryglobal{boyer_moore_searcher}% \begin{codeblock} -template::value_type>, - class BinaryPredicate = equal_to<>> +namespace std { + template::value_type>, + class BinaryPredicate = equal_to<>> class boyer_moore_searcher { public: boyer_moore_searcher(RandomAccessIterator1 pat_first, @@ -12466,6 +12471,7 @@ Hash hash_; // \expos BinaryPredicate pred_; // \expos }; +} \end{codeblock} \indexlibraryctor{boyer_moore_searcher}% @@ -12545,9 +12551,10 @@ \indexlibraryglobal{boyer_moore_horspool_searcher}% \begin{codeblock} -template::value_type>, - class BinaryPredicate = equal_to<>> +namespace std { + template::value_type>, + class BinaryPredicate = equal_to<>> class boyer_moore_horspool_searcher { public: boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, @@ -12565,6 +12572,7 @@ Hash hash_; // \expos BinaryPredicate pred_; // \expos }; +} \end{codeblock} \indexlibraryctor{boyer_moore_horspool_searcher}% From 1daeb8e44b659c5cdf7133df68def1264c8b5774 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 23 Feb 2022 22:54:01 +0100 Subject: [PATCH 159/182] Move [string.view] to before [string.classes] --- source/strings.tex | 6225 ++++++++++++++++++++++---------------------- 1 file changed, 3112 insertions(+), 3113 deletions(-) diff --git a/source/strings.tex b/source/strings.tex index 783a688896..46d10379b4 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -19,8 +19,8 @@ \begin{libsumtab}[x{2.1in}]{Strings library summary}{strings.summary} \ref{char.traits} & Character traits & \tcode{} \\ -\ref{string.classes} & String classes & \\ \rowsep \ref{string.view} & String view classes & \tcode{} \\ \rowsep +\ref{string.classes} & String classes & \\ \rowsep \ref{c.strings} & Null-terminated sequence utilities & \tcode{}, \tcode{}, \tcode{}, \tcode{}, \tcode{}, \tcode{} \\ @@ -515,2224 +515,1983 @@ returns \tcode{WEOF}. -\rSec1[string.classes]{String classes} +\rSec1[string.view]{String view classes} -\rSec2[string.classes.general]{General} +\rSec2[string.view.general]{General} \pnum -The header \tcode{} 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}, -\tcode{basic_string}, -\tcode{basic_string}, -\tcode{basic_string}, -and -\tcode{basic_string<\brk{}wchar_t>}, respectively. +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}. -\rSec2[string.syn]{Header \tcode{} synopsis} -\indexheader{string}% +\pnum +\begin{note} +The library provides implicit conversions from \tcode{const charT*} and \tcode{std::basic_string} to \tcode{std::basic_string_view} so that user code can accept just \tcode{std::basic_string_view} 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} in order to interoperate with these functions. +\end{note} + +\rSec2[string.view.synop]{Header \tcode{} synopsis} +\indexheader{string_view}% \begin{codeblock} #include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} namespace std { - // \ref{char.traits}, character traits - template struct char_traits; - template<> struct char_traits; - template<> struct char_traits; - template<> struct char_traits; - template<> struct char_traits; - template<> struct char_traits; - - // \ref{basic.string}, \tcode{basic_string} - template, class Allocator = allocator> - class basic_string; - - template - constexpr basic_string - operator+(const basic_string& lhs, - const basic_string& rhs); - template - constexpr basic_string - operator+(basic_string&& lhs, - const basic_string& rhs); - template - constexpr basic_string - operator+(const basic_string& lhs, - basic_string&& rhs); - template - constexpr basic_string - operator+(basic_string&& lhs, - basic_string&& rhs); - template - constexpr basic_string - operator+(const charT* lhs, - const basic_string& rhs); - template - constexpr basic_string - operator+(const charT* lhs, - basic_string&& rhs); - template - constexpr basic_string - operator+(charT lhs, - const basic_string& rhs); - template - constexpr basic_string - operator+(charT lhs, - basic_string&& rhs); - template - constexpr basic_string - operator+(const basic_string& lhs, - const charT* rhs); - template - constexpr basic_string - operator+(basic_string&& lhs, - const charT* rhs); - template - constexpr basic_string - operator+(const basic_string& lhs, - charT rhs); - template - constexpr basic_string - operator+(basic_string&& lhs, - charT rhs); + // \ref{string.view.template}, class template \tcode{basic_string_view} + template> + class basic_string_view; - template - constexpr bool - operator==(const basic_string& lhs, - const basic_string& rhs) noexcept; - template - constexpr bool operator==(const basic_string& lhs, - const charT* rhs); + template + inline constexpr bool ranges::enable_view> = true; + template + inline constexpr bool ranges::enable_borrowed_range> = true; - template - constexpr @\seebelow@ operator<=>(const basic_string& lhs, - @\itcorr@ const basic_string& rhs) noexcept; - template - constexpr @\seebelow@ operator<=>(const basic_string& lhs, - @\itcorr@ const charT* rhs); + // \ref{string.view.comparison}, non-member comparison functions + template + constexpr bool operator==(basic_string_view x, + basic_string_view y) noexcept; + template + constexpr @\seebelow@ operator<=>(basic_string_view x, + @\itcorr@ basic_string_view y) noexcept; - // \ref{string.special}, swap - template - constexpr void - swap(basic_string& lhs, - basic_string& rhs) - noexcept(noexcept(lhs.swap(rhs))); + // see \ref{string.view.comparison}, sufficient additional overloads of comparison functions - // \ref{string.io}, inserters and extractors - template - basic_istream& - operator>>(basic_istream& is, - basic_string& str); - template + // \ref{string.view.io}, inserters and extractors + template basic_ostream& operator<<(basic_ostream& os, - const basic_string& str); - template - basic_istream& - getline(basic_istream& is, - basic_string& str, - charT delim); - template - basic_istream& - getline(basic_istream&& is, - basic_string& str, - charT delim); - template - basic_istream& - getline(basic_istream& is, - basic_string& str); - template - basic_istream& - getline(basic_istream&& is, - basic_string& str); - - // \ref{string.erasure}, erasure - template - constexpr typename basic_string::size_type - erase(basic_string& c, const U& value); - template - constexpr typename basic_string::size_type - erase_if(basic_string& c, Predicate pred); - - // \tcode{basic_string} \grammarterm{typedef-name}s - using @\libglobal{string}@ = basic_string; - using @\libglobal{u8string}@ = basic_string; - using @\libglobal{u16string}@ = basic_string; - using @\libglobal{u32string}@ = basic_string; - using @\libglobal{wstring}@ = basic_string; - - // \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); - string to_string(int val); - string to_string(unsigned val); - string to_string(long val); - string to_string(unsigned long val); - string to_string(long long val); - 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); - wstring to_wstring(int val); - wstring to_wstring(unsigned val); - wstring to_wstring(long val); - wstring to_wstring(unsigned long val); - wstring to_wstring(long long val); - 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> - using basic_string = std::basic_string>; + basic_string_view str); - using string = basic_string; - using u8string = basic_string; - using u16string = basic_string; - using u32string = basic_string; - using wstring = basic_string; - } + // \tcode{basic_string_view} \grammarterm{typedef-name}s + using string_view = basic_string_view; + using u8string_view = basic_string_view; + using u16string_view = basic_string_view; + using u32string_view = basic_string_view; + using wstring_view = basic_string_view; - // \ref{basic.string.hash}, hash support + // \ref{string.view.hash}, hash support template struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; 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); + 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} -\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.requirements.general}. +The function templates defined in \ref{utility.swap} and \ref{iterator.range} +are available when \tcode{} is included. -\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}. +\rSec2[string.view.template]{Class template \tcode{basic_string_view}} +\rSec3[string.view.template.general]{General} -\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}% +\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 Allocator = allocator> - class basic_string { + template> + class basic_string_view { public: // types using traits_type = traits; using value_type = charT; - using allocator_type = Allocator; - using size_type = typename allocator_traits::size_type; - using difference_type = typename allocator_traits::difference_type; - using pointer = typename allocator_traits::pointer; - using const_pointer = typename allocator_traits::const_pointer; + using pointer = value_type*; + using const_pointer = const value_type*; 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; - using const_reverse_iterator = std::reverse_iterator; + 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; + 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.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()); - template - constexpr basic_string(const T& t, size_type pos, size_type n, - const Allocator& a = Allocator()); - template - 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 - constexpr basic_string(InputIterator begin, InputIterator end, - const Allocator& a = Allocator()); - template<@\exposconcept{container-compatible-range}@ R> - constexpr basic_string(from_range_t, R&& rg, const Allocator& a = Allocator()); - constexpr basic_string(initializer_list, 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::propagate_on_container_move_assignment::value || - allocator_traits::is_always_equal::value); - template - 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); + // \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 + constexpr basic_string_view(It begin, End end); + template + constexpr basic_string_view(R&& r); - // \ref{string.iterators}, iterators - constexpr iterator begin() noexcept; + // \ref{string.view.iterators}, iterator support constexpr const_iterator begin() const noexcept; - constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; - - constexpr reverse_iterator rbegin() noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const 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 + // \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 void resize(size_type n, charT c); - constexpr void resize(size_type n); - template 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; [[nodiscard]] constexpr bool empty() const noexcept; - // \ref{string.access}, element access + // \ref{string.view.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 charT& front() const; - constexpr charT& front(); - constexpr const charT& back() const; - constexpr charT& back(); + constexpr const_reference at(size_type pos) const; + constexpr const_reference front() const; + constexpr const_reference back() const; + constexpr const_pointer data() const noexcept; - // \ref{string.modifiers}, modifiers - constexpr basic_string& operator+=(const basic_string& str); - template - 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); - constexpr basic_string& append(const basic_string& str); - constexpr basic_string& append(const basic_string& str, size_type pos, size_type n = npos); - template - constexpr basic_string& append(const T& t); - template - 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(size_type n, charT c); - template - constexpr basic_string& append(InputIterator first, InputIterator last); - template<@\exposconcept{container-compatible-range}@ R> - constexpr basic_string& append_range(R&& rg); - constexpr basic_string& append(initializer_list); + // \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; - constexpr void push_back(charT c); + // \ref{string.view.ops}, string operations + constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; - constexpr basic_string& assign(const basic_string& str); - constexpr basic_string& assign(basic_string&& str) - noexcept(allocator_traits::propagate_on_container_move_assignment::value || - allocator_traits::is_always_equal::value); - constexpr basic_string& assign(const basic_string& str, size_type pos, size_type n = npos); - template - constexpr basic_string& assign(const T& t); - template - 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(size_type n, charT c); - template - constexpr basic_string& assign(InputIterator first, InputIterator last); - template<@\exposconcept{container-compatible-range}@ R> - constexpr basic_string& assign_range(R&& rg); - constexpr basic_string& assign(initializer_list); + constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; - 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 - constexpr basic_string& insert(size_type pos, const T& t); - template - 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 - constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last); - template<@\exposconcept{container-compatible-range}@ R> - constexpr iterator insert_range(const_iterator p, R&& rg); - constexpr iterator insert(const_iterator p, initializer_list); + constexpr int compare(basic_string_view s) const noexcept; + constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const; + constexpr int compare(size_type pos1, size_type n1, basic_string_view s, + size_type pos2, size_type n2) 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 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 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 void pop_back(); + constexpr bool contains(basic_string_view x) const noexcept; + constexpr bool contains(charT x) const noexcept; + constexpr bool contains(const charT* x) const; - 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 - constexpr basic_string& replace(size_type pos1, size_type n1, const T& t); - template - 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 - 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 - constexpr basic_string& replace(const_iterator i1, const_iterator i2, - InputIterator j1, InputIterator j2); - template<@\exposconcept{container-compatible-range}@ 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); - - constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; - - constexpr void swap(basic_string& str) - noexcept(allocator_traits::propagate_on_container_swap::value || - allocator_traits::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() const noexcept; - constexpr allocator_type get_allocator() const noexcept; - - template - 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; + // \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 find(charT c, size_type pos = 0) const noexcept; - template - 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(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 rfind(charT c, size_type pos = npos) const noexcept; - template - 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(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_first_of(charT c, size_type pos = 0) const noexcept; - template - 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(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_last_of(charT c, size_type pos = npos) const noexcept; - - template - 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(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; - template - 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, + 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(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 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 basic_string substr(size_type pos = 0, size_type n = npos) const; - - template - constexpr int compare(const T& t) const noexcept(@\seebelow@); - template - constexpr int compare(size_type pos1, size_type n1, const T& t) const; - template - 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 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; + private: + const_pointer data_; // \expos + size_type size_; // \expos }; - template::value_type>> - basic_string(InputIterator, InputIterator, Allocator = Allocator()) - -> basic_string::value_type, - char_traits::value_type>, - Allocator>; - - template>> - basic_string(from_range_t, R&&, Allocator = Allocator()) - -> basic_string, char_traits>, - Allocator>; - - template> - explicit basic_string(basic_string_view, const Allocator& = Allocator()) - -> basic_string; - - template> - basic_string(basic_string_view, - typename @\seebelow@::size_type, typename @\seebelow@::size_type, - const Allocator& = Allocator()) - -> basic_string; + // \ref{string.view.deduct}, deduction guides + template + basic_string_view(It, End) -> basic_string_view>; + template + basic_string_view(R&&) -> basic_string_view>; } \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 -In every specialization \tcode{basic_string}, -the type \tcode{allocator_traits::value_type} shall name the same type -as \tcode{charT}. Every object of type -\tcode{basic_string} 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.requirements.general}. -In every specialization \tcode{basic_string}, -the type \tcode{traits} shall meet -the character traits requirements\iref{char.traits}. -\begin{note} -Every specialization \tcode{basic_string} is -an allocator-aware container, -but does not use the allocator's \tcode{construct} and \tcode{destroy} -member functions\iref{container.requirements.general}. -\end{note} +In every specialization \tcode{basic_string_view}, 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}. +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: +For a \tcode{basic_string_view str}, +any operation that invalidates a pointer +in the range \range{str.data()}{\brk{}str.data() + str.size()} +invalidates pointers, iterators, and references +returned from \tcode{str}'s member functions. -\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} +\pnum +The complexity of \tcode{basic_string_view} member functions is \bigoh{1} +unless otherwise specified. -\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} +\pnum +\tcode{basic_string_view} is +a trivially copyable type\iref{term.trivially.copyable.type}. -\rSec3[string.cons]{Constructors and assignment operators} +\rSec3[string.view.cons]{Construction and assignment} -\indexlibraryctor{basic_string}% +\indexlibraryctor{basic_string_view}% \begin{itemdecl} -constexpr explicit basic_string(const Allocator& a) noexcept; +constexpr basic_string_view() noexcept; \end{itemdecl} \begin{itemdescr} - \pnum \ensures -\tcode{size()} is equal to \tcode{0}. +\tcode{size_ == 0} and \tcode{data_ == nullptr}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibraryctor{basic_string_view}% \begin{itemdecl} -constexpr basic_string(const basic_string& str); -constexpr basic_string(basic_string&& str) noexcept; +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 an object whose -value is that of \tcode{str} prior to this call. +Constructs a \tcode{basic_string_view}, initializing \tcode{data_} with \tcode{str} +and initializing \tcode{size_} with \tcode{traits::length(str)}. \pnum -\remarks -In the second form, \tcode{str} is left in a valid but unspecified state. +\complexity +\bigoh{\tcode{traits::length(str)}}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibraryctor{basic_string_view}% \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_view(const charT* str, size_type len); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\range{str}{str + len} is a valid range. + \pnum \effects -Let \tcode{n} be \tcode{npos} for the first overload. Equivalent to: -\begin{codeblock} -basic_string(basic_string_view(str).substr(pos, n), a) -\end{codeblock} +Constructs a \tcode{basic_string_view}, initializing \tcode{data_} with \tcode{str} +and initializing \tcode{size_} with \tcode{len}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibraryctor{basic_string_view}% \begin{itemdecl} -template - constexpr basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); +template + constexpr basic_string_view(It begin, End end); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_convertible_v>} -is \tcode{true}. +\begin{itemize} +\item \tcode{It} satisfies \libconcept{contiguous_iterator}. +\item \tcode{End} satisfies \tcode{\libconcept{sized_sentinel_for}}. +\item \tcode{is_same_v, charT>} is \tcode{true}. +\item \tcode{is_convertible_v} 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}}. +\end{itemize} \pnum \effects -Creates a variable, \tcode{sv}, -as if by \tcode{basic_string_view sv = t;} -and then behaves the same as: -\begin{codeblock} -basic_string(sv.substr(pos, n), a); -\end{codeblock} +Initializes \tcode{data_} with \tcode{to_address(begin)} and +initializes \tcode{size_} with \tcode{end - begin}. + +\pnum +\throws +When and what \tcode{end - begin} throws. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibraryctor{basic_string_view}% \begin{itemdecl} -template - constexpr explicit basic_string(const T& t, const Allocator& a = Allocator()); +template + constexpr basic_string_view(R&& r); \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{d} be an lvalue of type \tcode{remove_cvref_t}. + \pnum \constraints \begin{itemize} \item -\tcode{is_convertible_v>} is -\tcode{true} and +\tcode{remove_cvref_t} is not the same type as \tcode{basic_string_view}, \item -\tcode{is_convertible_v} is -\tcode{false}. +\tcode{R} models +\tcode{ranges::\libconcept{contiguous_range}} and \tcode{ranges::\libconcept{sized_range}}, +\item +\tcode{is_same_v, charT>} is \tcode{true}, +\item +\tcode{is_convertible_v} is \tcode{false}, +\item +\tcode{d.operator ::std::basic_string_view()} +is not a valid expression, and +\item +if the \grammarterm{qualified-id} \tcode{remove_reference_t::traits_type} +is valid and denotes a type, +\tcode{is_same_v::traits_type, traits>} is \tcode{true}. \end{itemize} \pnum \effects -Creates a variable, \tcode{sv}, as if by -\tcode{basic_string_view 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}. +Initializes \tcode{data_} with \tcode{ranges::data(r)} and +\tcode{size_} with \tcode{ranges::size(r)}. \pnum -\ensures -\tcode{size()} is equal to \tcode{n}, and -\tcode{traits::compare(data(), s, n)} is equal to \tcode{0}. +\throws +Any exception thrown by \tcode{ranges::data(r)} and \tcode{ranges::size(r)}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\rSec3[string.view.iterators]{Iterator support} + +\indexlibrarymember{const_iterator}{basic_string_view}% \begin{itemdecl} -constexpr basic_string(const charT* s, const Allocator& a = Allocator()); +using const_iterator = @\impdefx{type of \tcode{basic_string_view::const_iterator}}@; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{Allocator} is a type -that qualifies as an allocator\iref{container.requirements.general}. -\begin{note} -This affects class template argument deduction. -\end{note} +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 -\effects -Equivalent to: \tcode{basic_string(s, traits::length(s), a)}. +All requirements on container iterators\iref{container.requirements} apply to \tcode{basic_string_view::const_iterator} as well. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibrarymember{begin}{basic_string_view}% +\indexlibrarymember{cbegin}{basic_string_view}% \begin{itemdecl} -constexpr basic_string(size_type n, charT c, const Allocator& a = Allocator()); +constexpr const_iterator begin() const noexcept; +constexpr const_iterator cbegin() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{Allocator} is a type -that qualifies as an allocator\iref{container.requirements.general}. -\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}. +\returns +An iterator such that +\begin{itemize} +\item if \tcode{!empty()}, \tcode{addressof(*begin()) == data_}, +\item otherwise, an unspecified value such that \range{begin()}{end()} is a valid range. +\end{itemize} \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibrarymember{end}{basic_string_view}% +\indexlibrarymember{cend}{basic_string_view}% \begin{itemdecl} -template - constexpr basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator()); +constexpr const_iterator end() const noexcept; +constexpr const_iterator cend() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{InputIterator} is a type that qualifies as an input -iterator\iref{container.requirements.general}. - -\pnum -\effects -Constructs a string from the values in the range \range{begin}{end}, -as specified in \ref{sequence.reqmts}. +\returns +\tcode{begin() + size()}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibrarymember{rbegin}{basic_string_view}% +\indexlibrarymember{crbegin}{basic_string_view}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - constexpr basic_string(from_range_t, R&& rg, const Allocator& = Allocator()); +constexpr const_reverse_iterator rbegin() const noexcept; +constexpr const_reverse_iterator crbegin() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Constructs a string from the values in the range \tcode{rg}, -as specified in \ref{sequence.reqmts}. +\returns +\tcode{const_reverse_iterator(end())}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\indexlibrarymember{rend}{basic_string_view}% +\indexlibrarymember{crend}{basic_string_view}% \begin{itemdecl} -constexpr basic_string(initializer_list il, const Allocator& a = Allocator()); +constexpr const_reverse_iterator rend() const noexcept; +constexpr const_reverse_iterator crend() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{basic_string(il.begin(), il.end(), a)}. +\returns +\tcode{const_reverse_iterator(begin())}. \end{itemdescr} -\indexlibraryctor{basic_string}% +\rSec3[string.view.capacity]{Capacity} + +\indexlibrarymember{size}{basic_string_view}% +\indexlibrarymember{length}{basic_string_view}% \begin{itemdecl} -constexpr basic_string(const basic_string& str, const Allocator& alloc); -constexpr basic_string(basic_string&& str, const Allocator& alloc); +constexpr size_type size() const noexcept; +constexpr size_type length() const noexcept; \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()}. +\returns +\tcode{size_}. \end{itemdescr} + +\indexlibrarymember{max_size}{basic_string_view}% \begin{itemdecl} -template::value_type>> - basic_string(InputIterator, InputIterator, Allocator = Allocator()) - -> basic_string::value_type, - char_traits::value_type>, - Allocator>; +constexpr size_type max_size() const noexcept; \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.requirements.general}. +\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} -template> - explicit basic_string(basic_string_view, const Allocator& = Allocator()) - -> basic_string; - -template> - basic_string(basic_string_view, - typename @\seebelow@::size_type, typename @\seebelow@::size_type, - const Allocator& = Allocator()) - -> basic_string; +[[nodiscard]] constexpr bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{Allocator} is a type that qualifies as -an allocator\iref{container.requirements.general}. +\returns +\tcode{size_ == 0}. \end{itemdescr} -\indexlibrarymember{operator=}{basic_string}% +\rSec3[string.view.access]{Element access} + +\indexlibrarymember{operator[]}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator=(const basic_string& str); +constexpr const_reference operator[](size_type pos) const; \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}. +\expects +\tcode{pos < size()}. \pnum \returns -\tcode{*this}. +\tcode{data_[pos]}. + +\pnum +\throws +Nothing. + +\pnum +\begin{note} +Unlike \tcode{basic_string::operator[]}, +\tcode{basic_string_view::operator[](size())} has undefined behavior instead of returning \tcode{charT()}. +\end{note} \end{itemdescr} -\indexlibrarymember{operator=}{basic_string}% +\indexlibrarymember{at}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator=(basic_string&& str) - noexcept(allocator_traits::propagate_on_container_move_assignment::value || - allocator_traits::is_always_equal::value); +constexpr const_reference at(size_type pos) const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Move assigns as a sequence container\iref{container.requirements}, -except that iterators, pointers and references may be invalidated. +\returns +\tcode{data_[pos]}. \pnum -\returns -\tcode{*this}. +\throws +\tcode{out_of_range} if \tcode{pos >= size()}. \end{itemdescr} -\indexlibrarymember{operator=}{basic_string}% +\indexlibrarymember{front}{basic_string_view}% \begin{itemdecl} -template - constexpr basic_string& operator=(const T& t); +constexpr const_reference front() const; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item \tcode{is_convertible_v>} -is \tcode{true} and -\item \tcode{is_convertible_v} -is \tcode{false}. -\end{itemize} +\expects +\tcode{!empty()}. \pnum -\effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return assign(sv); -\end{codeblock} +\returns +\tcode{data_[0]}. + +\pnum +\throws +Nothing. \end{itemdescr} -\indexlibrarymember{operator=}{basic_string}% +\indexlibrarymember{back}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator=(const charT* s); +constexpr const_reference back() const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\tcode{return *this = basic_string_view(s);} +\expects +\tcode{!empty()}. + +\pnum +\returns +\tcode{data_[size() - 1]}. + +\pnum +\throws +Nothing. \end{itemdescr} -\indexlibrarymember{operator=}{basic_string}% +\indexlibrarymember{data}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator=(charT c); +constexpr const_pointer data() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return *this = basic_string_view(addressof(c), 1); -\end{codeblock} +\returns +\tcode{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} -\indexlibrarymember{operator=}{basic_string}% +\rSec3[string.view.modifiers]{Modifiers} + +\indexlibrarymember{remove_prefix}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator=(initializer_list il); +constexpr void remove_prefix(size_type n); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{n <= size()}. + \pnum \effects -Equivalent to: -\begin{codeblock} -return *this = basic_string_view(il.begin(), il.size()); -\end{codeblock} +Equivalent to: \tcode{data_ += n; size_ -= n;} \end{itemdescr} -\rSec3[string.iterators]{Iterator support} - -\indexlibrarymember{begin}{basic_string}% -\indexlibrarymember{cbegin}{basic_string}% +\indexlibrarymember{remove_suffix}{basic_string_view}% \begin{itemdecl} -constexpr iterator begin() noexcept; -constexpr const_iterator begin() const noexcept; -constexpr const_iterator cbegin() const noexcept; +constexpr void remove_suffix(size_type n); \end{itemdecl} \begin{itemdescr} \pnum -\returns -An iterator referring to the first character in the string. +\expects +\tcode{n <= size()}. + +\pnum +\effects +Equivalent to: \tcode{size_ -= n;} \end{itemdescr} -\indexlibrarymember{end}{basic_string}% -\indexlibrarymember{cend}{basic_string}% +\indexlibrarymember{swap}{basic_string_view}% \begin{itemdecl} -constexpr iterator end() noexcept; -constexpr const_iterator end() const noexcept; -constexpr const_iterator cend() const noexcept; +constexpr void swap(basic_string_view& s) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -An iterator which is the past-the-end value. +\effects +Exchanges the values of \tcode{*this} and \tcode{s}. \end{itemdescr} -\indexlibrarymember{rbegin}{basic_string}% -\indexlibrarymember{crbegin}{basic_string}% +\rSec3[string.view.ops]{String operations} + +\indexlibrarymember{copy}{basic_string_view}% \begin{itemdecl} -constexpr reverse_iterator rbegin() noexcept; -constexpr const_reverse_iterator rbegin() const noexcept; -constexpr const_reverse_iterator crbegin() const noexcept; +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 -An iterator which is semantically equivalent to -\tcode{reverse_iterator(end())}. +\tcode{rlen}. + +\pnum +\throws +\tcode{out_of_range} if \tcode{pos > size()}. + +\pnum +\complexity +\bigoh{\tcode{rlen}}. \end{itemdescr} -\indexlibrarymember{rend}{basic_string}% -\indexlibrarymember{crend}{basic_string}% +\indexlibrarymember{substr}{basic_string_view}% \begin{itemdecl} -constexpr reverse_iterator rend() noexcept; -constexpr const_reverse_iterator rend() const noexcept; -constexpr const_reverse_iterator crend() const noexcept; +constexpr basic_string_view substr(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 -An iterator which is semantically equivalent to -\tcode{reverse_iterator(begin())}. -\end{itemdescr} +\tcode{basic_string_view(data() + pos, rlen)}. -\rSec3[string.capacity]{Capacity} +\pnum +\throws +\tcode{out_of_range} if \tcode{pos > size()}. +\end{itemdescr} -\indexlibrarymember{size}{basic_string}% -\indexlibrarymember{length}{basic_string}% +\indexlibrarymember{compare}{basic_string_view}% \begin{itemdecl} -constexpr size_type size() const noexcept; -constexpr size_type length() const noexcept; +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 -A count of the number of char-like objects currently in the string. +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 -Constant time. +\bigoh{\tcode{rlen}}. \end{itemdescr} -\indexlibrarymember{max_size}{basic_string}% +\indexlibrarymember{compare}{basic_string_view}% \begin{itemdecl} -constexpr size_type max_size() const noexcept; +constexpr int compare(size_type pos1, size_type n1, basic_string_view str) const; \end{itemdecl} \begin{itemdescr} \pnum -\returns -The largest possible number of char-like objects that can be stored in a -\tcode{basic_string}. +\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 -\complexity -Constant time. +\effects +Equivalent to: \tcode{return substr(pos1, n1).compare(str.substr(pos2, n2));} \end{itemdescr} -\indexlibrarymember{resize}{basic_string}% +\indexlibrarymember{compare}{basic_string_view}% \begin{itemdecl} -constexpr void resize(size_type n, charT c); +constexpr int compare(const charT* s) const; \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} +Equivalent to: \tcode{return compare(basic_string_view(s));} \end{itemdescr} -\indexlibrarymember{resize}{basic_string}% +\indexlibrarymember{compare}{basic_string_view}% \begin{itemdecl} -constexpr void resize(size_type n); +constexpr int compare(size_type pos1, size_type n1, const charT* s) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to \tcode{resize(n, charT())}. +Equivalent to: \tcode{return substr(pos1, n1).compare(basic_string_view(s));} \end{itemdescr} -\indexlibrarymember{resize_and_overwrite}{basic_string}% +\indexlibrarymember{compare}{basic_string_view}% \begin{itemdecl} -template constexpr void resize_and_overwrite(size_type n, Operation op); +constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const; \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 \tcode{charT*}, -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 -$OP$ be the expression \tcode{std::move(op)(p, n)}. -\item -\tcode{r} = $OP$. -\end{itemize} - -\pnum -\mandates -$OP$ has an integer-like type\iref{iterator.concept.winc}. - -\pnum -\expects -\begin{itemize} -\item -$OP$ does not throw an exception or modify \tcode{p} or \tcode{n}. -\item -$\tcode{r} \geq 0$. -\item -$\tcode{r} \leq \tcode{n}$. -\item -After evaluating $OP$ -there are no indeterminate values in the range \range{p}{p + r}. -\end{itemize} - \pnum \effects -Evaluates $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 $OP$. +Equivalent to: \tcode{return substr(pos1, n1).compare(basic_string_view(s, n2));} \end{itemdescr} -\indexlibrarymember{capacity}{basic_string}% +\indexlibrarymember{starts_with}{basic_string_view}% \begin{itemdecl} -constexpr size_type capacity() const noexcept; +constexpr bool starts_with(basic_string_view x) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -The size of the allocated storage in the string. - -\pnum -\complexity -Constant time. +\effects +Equivalent to: \tcode{return substr(0, x.size()) == x;} \end{itemdescr} -\indexlibrarymember{reserve}{basic_string}% +\indexlibrarymember{starts_with}{basic_string_view}% \begin{itemdecl} -constexpr void reserve(size_type res_arg); +constexpr bool starts_with(charT x) const noexcept; \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. -After -\tcode{reserve()}, -\tcode{capacity()} -is greater or equal to the argument of -\tcode{reserve} -if reallocation happens; and -equal to the previous value of -\tcode{capacity()} -otherwise. -Reallocation happens at this point if and only if -the current capacity is less than the argument of \tcode{reserve()}. - -\pnum -\throws -\tcode{length_error} -if -\tcode{res_arg > max_size()} or any exceptions thrown by -\tcode{allocator_traits} \tcode{::allocate}. +Equivalent to: \tcode{return !empty() \&\& traits::eq(front(), x);} \end{itemdescr} -\indexlibrarymember{shrink_to_fit}{basic_string}% +\indexlibrarymember{starts_with}{basic_string_view}% \begin{itemdecl} -constexpr void shrink_to_fit(); +constexpr bool starts_with(const charT* x) const; \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. +Equivalent to: \tcode{return starts_with(basic_string_view(x));} +\end{itemdescr} -\pnum -\complexity -If the size is not equal to the old capacity, -linear in the size of the sequence; -otherwise constant. +\indexlibrarymember{ends_with}{basic_string_view}% +\begin{itemdecl} +constexpr bool ends_with(basic_string_view x) const noexcept; +\end{itemdecl} +\begin{itemdescr} \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} +\effects +Equivalent to: +\begin{codeblock} +return size() >= x.size() && compare(size() - x.size(), npos, x) == 0; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{clear}{basic_string}% +\indexlibrarymember{ends_with}{basic_string_view}% \begin{itemdecl} -constexpr void clear() noexcept; +constexpr bool ends_with(charT x) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{erase(begin(), end());} +Equivalent to: \tcode{return !empty() \&\& traits::eq(back(), x);} \end{itemdescr} -\indexlibrarymember{empty}{basic_string}% +\indexlibrarymember{ends_with}{basic_string_view}% \begin{itemdecl} -[[nodiscard]] constexpr bool empty() const noexcept; +constexpr bool ends_with(const charT* x) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return size() == 0;} +Equivalent to: \tcode{return ends_with(basic_string_view(x));} \end{itemdescr} -\rSec3[string.access]{Element access} - -\indexlibrarymember{operator[]}{basic_string}% +\indexlibrarymember{contains}{basic_string_view}% \begin{itemdecl} -constexpr const_reference operator[](size_type pos) const; -constexpr reference operator[](size_type pos); +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 -\expects -\tcode{pos <= size()}. +\effects +Equivalent to: \tcode{return find(x) != npos;} +\end{itemdescr} -\pnum -\returns -\tcode{*(begin() + pos)} if \tcode{pos < size()}. Otherwise, -returns a reference to an object of type \tcode{charT} with value -\tcode{charT()}, where modifying the object to any value other than -\tcode{charT()} leads to undefined behavior. +\rSec3[string.view.find]{Searching} \pnum -\throws -Nothing. +Member functions in this subclause have complexity \bigoh{\tcode{size() * str.size()}} at worst, +although implementations should do better. \pnum -\complexity -Constant time. -\end{itemdescr} +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);} -\indexlibrarymember{at}{basic_string}% +\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 const_reference at(size_type pos) const; -constexpr reference at(size_type pos); +constexpr size_type find(basic_string_view str, size_type pos = 0) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{operator[](pos)}. +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(at(xpos + I), str.at(I))} for all elements \tcode{I} of the string referenced by \tcode{str}. +\end{itemize} \pnum -\throws -\tcode{out_of_range} -if -\tcode{pos >= size()}. +\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{front}{basic_string}% +\indexlibrarymember{rfind}{basic_string_view}% \begin{itemdecl} -constexpr const charT& front() const; -constexpr charT& front(); +constexpr size_type rfind(basic_string_view str, size_type pos = npos) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +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(at(xpos + I), str.at(I))} for all elements \tcode{I} of the string referenced by \tcode{str}. +\end{itemize} \pnum \effects -Equivalent to: \tcode{return operator[](0);} +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{back}{basic_string}% +\indexlibrarymember{find_first_of}{basic_string_view}% \begin{itemdecl} -constexpr const charT& back() const; -constexpr charT& back(); +constexpr size_type find_first_of(basic_string_view str, size_type pos = 0) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +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(at(xpos), str.at(I))} for some element \tcode{I} of the string referenced by \tcode{str}. +\end{itemize} \pnum \effects -Equivalent to: \tcode{return operator[](size() - 1);} -\end{itemdescr} - -\rSec3[string.modifiers]{Modifiers} +Determines \tcode{xpos}. -\rSec4[string.op.append]{\tcode{basic_string::operator+=}} +\pnum +\returns +\tcode{xpos} if the function can determine such a value for \tcode{xpos}. +Otherwise, returns \tcode{npos}. +\end{itemdescr} -\indexlibrarymember{operator+=}{basic_string}% +\indexlibrarymember{find_last_of}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator+=(const basic_string& str); +constexpr size_type find_last_of(basic_string_view str, size_type pos = npos) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return append(str);} +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(at(xpos), str.at(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{operator+=}{basic_string}% +\indexlibrarymember{find_first_not_of}{basic_string_view}% \begin{itemdecl} -template - constexpr basic_string& operator+=(const T& t); +constexpr size_type find_first_not_of(basic_string_view str, size_type pos = 0) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints +Let \tcode{xpos} be the lowest position, if possible, such that the following conditions hold: \begin{itemize} \item -\tcode{is_convertible_v>} is -\tcode{true} and +\tcode{pos <= xpos} \item -\tcode{is_convertible_v} is -\tcode{false}. +\tcode{xpos < size()} +\item +\tcode{traits::eq(at(xpos), str.at(I))} for no element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum \effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return append(sv); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{operator+=}{basic_string}% -\begin{itemdecl} -constexpr basic_string& operator+=(const charT* s); -\end{itemdecl} +Determines \tcode{xpos}. -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return append(s);} +\returns +\tcode{xpos} if the function can determine such a value for \tcode{xpos}. Otherwise, returns \tcode{npos}. \end{itemdescr} -\indexlibrarymember{operator+=}{basic_string}% +\indexlibrarymember{find_last_not_of}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& operator+=(charT c); +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(at(xpos), str.at(I))} for no element \tcode{I} of the string referenced by \tcode{str}. +\end{itemize} + \pnum \effects -Equivalent to: \tcode{return append(size_type\{1\}, c);} +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{operator+=}{basic_string}% +\rSec2[string.view.deduct]{Deduction guides} + \begin{itemdecl} -constexpr basic_string& operator+=(initializer_list il); +template + basic_string_view(It, End) -> basic_string_view>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return append(il);} +\constraints +\begin{itemize} +\item \tcode{It} satisfies \libconcept{contiguous_iterator}. +\item \tcode{End} satisfies \tcode{\libconcept{sized_sentinel_for}}. +\end{itemize} \end{itemdescr} - -\rSec4[string.append]{\tcode{basic_string::append}} - -\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -constexpr basic_string& append(const basic_string& str); +template + basic_string_view(R&&) -> basic_string_view>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return append(str.data(), str.size());} +\constraints +\tcode{R} satisfies \tcode{ranges::\libconcept{contiguous_range}}. \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} +\rSec2[string.view.comparison]{Non-member comparison functions} -\begin{itemdescr} \pnum -\effects -Equivalent to: +Let \tcode{S} be \tcode{basic_string_view}, and \tcode{sv} be an instance of \tcode{S}. +Implementations shall provide sufficient additional overloads marked \keyword{constexpr} and \keyword{noexcept} +so that an object \tcode{t} with an implicit conversion to \tcode{S} can be compared according to \tref{string.view.comparison.overloads}. +\begin{libtab2}{Additional \tcode{basic_string_view} comparison overloads}{string.view.comparison.overloads}{cc}{Expression}{Equivalent to} +\tcode{t == sv} & \tcode{S(t) == sv} \\ +\tcode{sv == t} & \tcode{sv == S(t)} \\ +\tcode{t != sv} & \tcode{S(t) != sv} \\ +\tcode{sv != t} & \tcode{sv != S(t)} \\ +\tcode{t < sv} & \tcode{S(t) < sv} \\ +\tcode{sv < t} & \tcode{sv < S(t)} \\ +\tcode{t > sv} & \tcode{S(t) > sv} \\ +\tcode{sv > t} & \tcode{sv > S(t)} \\ +\tcode{t <= sv} & \tcode{S(t) <= sv} \\ +\tcode{sv <= t} & \tcode{sv <= S(t)} \\ +\tcode{t >= sv} & \tcode{S(t) >= sv} \\ +\tcode{sv >= t} & \tcode{sv >= S(t)} \\ +\tcode{t <=> sv} & \tcode{S(t) <=> sv} \\ +\tcode{sv <=> t} & \tcode{sv <=> S(t)} \\ +\end{libtab2} +\begin{example} +A sample conforming implementation for \tcode{operator==} would be: \begin{codeblock} -return append(basic_string_view(str).substr(pos, n)); +template + constexpr bool operator==(basic_string_view lhs, + basic_string_view rhs) noexcept { + return lhs.compare(rhs) == 0; + } +template + constexpr bool operator==(basic_string_view lhs, + type_identity_t> rhs) noexcept { + return lhs.compare(rhs) == 0; + } \end{codeblock} -\end{itemdescr} +\end{example} -\indexlibrarymember{append}{basic_string}% +\indexlibrarymember{operator==}{basic_string_view}% \begin{itemdecl} -template - constexpr basic_string& append(const T& t); +template + constexpr bool operator==(basic_string_view lhs, + basic_string_view rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} - -\pnum -\effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return append(sv.data(), sv.size()); -\end{codeblock} +\returns +\tcode{lhs.compare(rhs) == 0}. \end{itemdescr} -\indexlibrarymember{append}{basic_string}% +\indexlibrarymember{operator<=>}{basic_string_view}% \begin{itemdecl} -template - constexpr basic_string& append(const T& t, size_type pos, size_type n = npos); +template + constexpr @\seebelow@ operator<=>(basic_string_view lhs, + @\itcorr@ basic_string_view rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} +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 -\effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return append(sv.substr(pos, n)); -\end{codeblock} +\mandates +\tcode{R} denotes a comparison category type\iref{cmp.categories}. + +\pnum +\returns +\tcode{static_cast(lhs.compare(rhs) <=> 0)}. \end{itemdescr} -\indexlibrarymember{append}{basic_string}% +\rSec2[string.view.io]{Inserters and extractors} + +\indexlibrarymember{operator<<}{basic_string_view}% \begin{itemdecl} -constexpr basic_string& append(const charT* s, size_type n); +template + basic_ostream& + operator<<(basic_ostream& os, basic_string_view str); \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. +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{*this}. +\tcode{os} \end{itemdescr} -\indexlibrarymember{append}{basic_string}% +\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} -constexpr basic_string& append(const charT* s); +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return append(s, traits::length(s));} +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} -\indexlibrarymember{append}{basic_string}% +\rSec2[string.view.literals]{Suffix for \tcode{basic_string_view} literals} + +\indexlibrarymember{operator""""sv}{string_view}% \begin{itemdecl} -constexpr basic_string& append(size_type n, charT c); +constexpr string_view operator""sv(const char* str, size_t len) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\effects -Appends \tcode{n} copies of \tcode{c} to the string. - \pnum \returns -\tcode{*this}. +\tcode{string_view\{str, len\}}. \end{itemdescr} -\indexlibrarymember{append}{basic_string}% +\indexlibrarymember{operator""""sv}{u8string_view}% \begin{itemdecl} -template - constexpr basic_string& append(InputIterator first, InputIterator last); +constexpr u8string_view operator""sv(const char8_t* str, size_t len) noexcept; \end{itemdecl} - \begin{itemdescr} \pnum -\constraints -\tcode{InputIterator} is a type that qualifies as an input -iterator\iref{container.requirements.general}. - -\pnum -\effects -Equivalent to: \tcode{return append(basic_string(first, last, get_allocator()));} +\returns +\tcode{u8string_view\{str, len\}}. \end{itemdescr} -\indexlibrarymember{append_range}{basic_string}% +\indexlibrarymember{operator""""sv}{u16string_view}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - constexpr basic_string& append_range(R&& rg); +constexpr u16string_view operator""sv(const char16_t* str, size_t len) noexcept; \end{itemdecl} - \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return append(basic_string(from_range, std::forward(rg), get_allocator()));} +\returns +\tcode{u16string_view\{str, len\}}. \end{itemdescr} -\indexlibrarymember{append}{basic_string}% +\indexlibrarymember{operator""""sv}{u32string_view}% \begin{itemdecl} -constexpr basic_string& append(initializer_list il); +constexpr u32string_view operator""sv(const char32_t* str, size_t len) noexcept; \end{itemdecl} - \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return append(il.begin(), il.size());} +\returns +\tcode{u32string_view\{str, len\}}. \end{itemdescr} -\indexlibrarymember{push_back}{basic_string}% +\indexlibrarymember{operator""""sv}{wstring_view}% \begin{itemdecl} -constexpr void push_back(charT c); +constexpr wstring_view operator""sv(const wchar_t* str, size_t len) noexcept; \end{itemdecl} - \begin{itemdescr} \pnum -\effects -Equivalent to -\tcode{append(size_type\{1\}, c)}. +\returns +\tcode{wstring_view\{str, len\}}. \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} +\rSec1[string.classes]{String classes} -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -constexpr basic_string& assign(basic_string&& str) - noexcept(allocator_traits::propagate_on_container_move_assignment::value || - allocator_traits::is_always_equal::value); -\end{itemdecl} +\rSec2[string.classes.general]{General} -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return *this = std::move(str);} -\end{itemdescr} - +The header \tcode{} 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}, +\tcode{basic_string}, +\tcode{basic_string}, +\tcode{basic_string}, +and +\tcode{basic_string<\brk{}wchar_t>}, respectively. -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -constexpr basic_string& assign(const basic_string& str, size_type pos, size_type n = npos); -\end{itemdecl} +\rSec2[string.syn]{Header \tcode{} synopsis} +\indexheader{string}% -\begin{itemdescr} -\pnum -\effects -Equivalent to: \begin{codeblock} -return assign(basic_string_view(str).substr(pos, n)); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -template - constexpr basic_string& assign(const T& t); -\end{itemdecl} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} -\begin{itemdescr} -\pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} +namespace std { + // \ref{char.traits}, character traits + template struct char_traits; + template<> struct char_traits; + template<> struct char_traits; + template<> struct char_traits; + template<> struct char_traits; + template<> struct char_traits; -\pnum -\effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return assign(sv.data(), sv.size()); -\end{codeblock} -\end{itemdescr} + // \ref{basic.string}, \tcode{basic_string} + template, class Allocator = allocator> + class basic_string; -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -template - constexpr basic_string& assign(const T& t, size_type pos, size_type n = npos); -\end{itemdecl} + template + constexpr basic_string + operator+(const basic_string& lhs, + const basic_string& rhs); + template + constexpr basic_string + operator+(basic_string&& lhs, + const basic_string& rhs); + template + constexpr basic_string + operator+(const basic_string& lhs, + basic_string&& rhs); + template + constexpr basic_string + operator+(basic_string&& lhs, + basic_string&& rhs); + template + constexpr basic_string + operator+(const charT* lhs, + const basic_string& rhs); + template + constexpr basic_string + operator+(const charT* lhs, + basic_string&& rhs); + template + constexpr basic_string + operator+(charT lhs, + const basic_string& rhs); + template + constexpr basic_string + operator+(charT lhs, + basic_string&& rhs); + template + constexpr basic_string + operator+(const basic_string& lhs, + const charT* rhs); + template + constexpr basic_string + operator+(basic_string&& lhs, + const charT* rhs); + template + constexpr basic_string + operator+(const basic_string& lhs, + charT rhs); + template + constexpr basic_string + operator+(basic_string&& lhs, + charT rhs); -\begin{itemdescr} -\pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} + template + constexpr bool + operator==(const basic_string& lhs, + const basic_string& rhs) noexcept; + template + constexpr bool operator==(const basic_string& lhs, + const charT* rhs); -\pnum -\effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return assign(sv.substr(pos, n)); -\end{codeblock} -\end{itemdescr} + template + constexpr @\seebelow@ operator<=>(const basic_string& lhs, + @\itcorr@ const basic_string& rhs) noexcept; + template + constexpr @\seebelow@ operator<=>(const basic_string& lhs, + @\itcorr@ const charT* rhs); -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -constexpr basic_string& assign(const charT* s, size_type n); -\end{itemdecl} + // \ref{string.special}, swap + template + constexpr void + swap(basic_string& lhs, + basic_string& rhs) + noexcept(noexcept(lhs.swap(rhs))); -\begin{itemdescr} -\pnum -\expects -\range{s}{s + n} is a valid range. + // \ref{string.io}, inserters and extractors + template + basic_istream& + operator>>(basic_istream& is, + basic_string& str); + template + basic_ostream& + operator<<(basic_ostream& os, + const basic_string& str); + template + basic_istream& + getline(basic_istream& is, + basic_string& str, + charT delim); + template + basic_istream& + getline(basic_istream&& is, + basic_string& str, + charT delim); + template + basic_istream& + getline(basic_istream& is, + basic_string& str); + template + basic_istream& + getline(basic_istream&& is, + basic_string& str); -\pnum -\effects -Replaces the string controlled by \tcode{*this} with -a copy of the range \range{s}{s + n}. + // \ref{string.erasure}, erasure + template + constexpr typename basic_string::size_type + erase(basic_string& c, const U& value); + template + constexpr typename basic_string::size_type + erase_if(basic_string& c, Predicate pred); -\pnum -\returns -\tcode{*this}. -\end{itemdescr} + // \tcode{basic_string} \grammarterm{typedef-name}s + using @\libglobal{string}@ = basic_string; + using @\libglobal{u8string}@ = basic_string; + using @\libglobal{u16string}@ = basic_string; + using @\libglobal{u32string}@ = basic_string; + using @\libglobal{wstring}@ = basic_string; -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -constexpr basic_string& assign(const charT* s); -\end{itemdecl} + // \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); + string to_string(int val); + string to_string(unsigned val); + string to_string(long val); + string to_string(unsigned long val); + string to_string(long long val); + string to_string(unsigned long long val); + string to_string(float val); + string to_string(double val); + string to_string(long double val); -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return assign(s, traits::length(s));} -\end{itemdescr} + 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); + wstring to_wstring(int val); + wstring to_wstring(unsigned val); + wstring to_wstring(long val); + wstring to_wstring(unsigned long val); + wstring to_wstring(long long val); + wstring to_wstring(unsigned long long val); + wstring to_wstring(float val); + wstring to_wstring(double val); + wstring to_wstring(long double val); -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -constexpr basic_string& assign(initializer_list il); -\end{itemdecl} + namespace pmr { + template> + using basic_string = std::basic_string>; -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return assign(il.begin(), il.size());} -\end{itemdescr} + using string = basic_string; + using u8string = basic_string; + using u16string = basic_string; + using u32string = basic_string; + using wstring = basic_string; + } -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -constexpr basic_string& assign(size_type n, charT c); -\end{itemdecl} + // \ref{basic.string.hash}, hash support + template struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -clear(); -resize(n, c); -return *this; + 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} -\end{itemdescr} - -\indexlibrarymember{assign}{basic_string}% -\begin{itemdecl} -template - 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.requirements.general}. -\pnum -\effects -Equivalent to: \tcode{return assign(basic_string(first, last, get_allocator()));} -\end{itemdescr} +\rSec2[basic.string]{Class template \tcode{basic_string}} -\indexlibrarymember{assign_range}{basic_string}% -\begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - constexpr basic_string& assign_range(R&& rg); -\end{itemdecl} +\rSec3[basic.string.general]{General} -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return assign(basic_string(from_range, std::forward(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} +\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}. -\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} +A specialization of \tcode{basic_string} is a contiguous container\iref{container.requirements.general}. -\begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return insert(pos1, basic_string_view(str), pos2, n); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{insert}{basic_string}% -\begin{itemdecl} -template - constexpr basic_string& insert(size_type pos, const T& t); -\end{itemdecl} +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}. -\begin{itemdescr} -\pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} -\pnum -\effects -Equivalent to: +\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} -basic_string_view sv = t; -return insert(pos, sv.data(), sv.size()); -\end{codeblock} -\end{itemdescr} +namespace std { + template, + class Allocator = allocator> + class basic_string { + public: + // types + using traits_type = traits; + using value_type = charT; + using allocator_type = Allocator; + using size_type = typename allocator_traits::size_type; + using difference_type = typename allocator_traits::difference_type; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; -\indexlibrarymember{insert}{basic_string}% -\begin{itemdecl} -template - constexpr basic_string& insert(size_type pos1, const T& t, - size_type pos2, size_type n = npos); -\end{itemdecl} + 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; + using const_reverse_iterator = std::reverse_iterator; + static constexpr size_type npos = size_type(-1); -\begin{itemdescr} -\pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} - -\pnum -\effects -Equivalent to: -\begin{codeblock} -basic_string_view 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::allocate}. -\end{itemize} -\end{itemdescr} + // \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()); + template + constexpr basic_string(const T& t, size_type pos, size_type n, + const Allocator& a = Allocator()); + template + 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 + constexpr basic_string(InputIterator begin, InputIterator end, + const Allocator& a = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string(from_range_t, R&& rg, const Allocator& a = Allocator()); + constexpr basic_string(initializer_list, const Allocator& = Allocator()); + constexpr basic_string(const basic_string&, const Allocator&); + constexpr basic_string(basic_string&&, const Allocator&); + constexpr ~basic_string(); -\indexlibrarymember{insert}{basic_string}% -\begin{itemdecl} -constexpr basic_string& insert(size_type pos, const charT* s); -\end{itemdecl} + constexpr basic_string& operator=(const basic_string& str); + constexpr basic_string& operator=(basic_string&& str) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); + template + 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); -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return insert(pos, s, traits::length(s));} -\end{itemdescr} + // \ref{string.iterators}, iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; -\indexlibrarymember{insert}{basic_string}% -\begin{itemdecl} -constexpr basic_string& insert(size_type pos, size_type n, charT c); -\end{itemdecl} + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; -\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. + 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; -\pnum -\returns -\tcode{*this} + // \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 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; + [[nodiscard]] constexpr bool empty() const noexcept; -\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::allocate}. -\end{itemize} -\end{itemdescr} + // \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); -\indexlibrarymember{insert}{basic_string}% -\begin{itemdecl} -constexpr iterator insert(const_iterator p, charT c); -\end{itemdecl} + constexpr const charT& front() const; + constexpr charT& front(); + constexpr const charT& back() const; + constexpr charT& back(); -\begin{itemdescr} -\pnum -\expects -\tcode{p} is a valid iterator on -\tcode{*this}. + // \ref{string.modifiers}, modifiers + constexpr basic_string& operator+=(const basic_string& str); + template + 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); + constexpr basic_string& append(const basic_string& str); + constexpr basic_string& append(const basic_string& str, size_type pos, size_type n = npos); + template + constexpr basic_string& append(const T& t); + template + 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(size_type n, charT c); + template + constexpr basic_string& append(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& append_range(R&& rg); + constexpr basic_string& append(initializer_list); -\pnum -\effects -Inserts a copy of \tcode{c} at the position \tcode{p}. + constexpr void push_back(charT c); -\pnum -\returns -An iterator which refers to the inserted character. -\end{itemdescr} + constexpr basic_string& assign(const basic_string& str); + constexpr basic_string& assign(basic_string&& str) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); + constexpr basic_string& assign(const basic_string& str, size_type pos, size_type n = npos); + template + constexpr basic_string& assign(const T& t); + template + 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(size_type n, charT c); + template + constexpr basic_string& assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& assign_range(R&& rg); + constexpr basic_string& assign(initializer_list); -\indexlibrarymember{insert}{basic_string}% -\begin{itemdecl} -constexpr iterator insert(const_iterator p, size_type n, charT c); -\end{itemdecl} + 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 + constexpr basic_string& insert(size_type pos, const T& t); + template + 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 + constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator p, R&& rg); + constexpr iterator insert(const_iterator p, initializer_list); -\begin{itemdescr} -\pnum -\expects -\tcode{p} is a valid iterator on -\tcode{*this}. + 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); -\pnum -\effects -Inserts \tcode{n} copies of \tcode{c} at the position \tcode{p}. + constexpr void pop_back(); -\pnum -\returns -An iterator which refers to the first inserted character, or -\tcode{p} if \tcode{n == 0}. -\end{itemdescr} + 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 + constexpr basic_string& replace(size_type pos1, size_type n1, const T& t); + template + 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 + 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 + constexpr basic_string& replace(const_iterator i1, const_iterator i2, + InputIterator j1, InputIterator j2); + template<@\exposconcept{container-compatible-range}@ 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); -\indexlibrarymember{insert}{basic_string}% -\begin{itemdecl} -template - constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last); -\end{itemdecl} + constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; -\begin{itemdescr} -\pnum -\constraints -\tcode{InputIterator} is a type that qualifies as an input -iterator\iref{container.requirements.general}. + constexpr void swap(basic_string& str) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); -\pnum -\expects -\tcode{p} is a valid iterator on -\tcode{*this}. + // \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() const noexcept; + constexpr allocator_type get_allocator() const noexcept; -\pnum -\effects -Equivalent to -\tcode{insert(p - begin(), basic_string(first, last, get_allocator()))}. + template + 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 + 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; -\pnum -\returns -An iterator which refers to the first inserted character, or -\tcode{p} if \tcode{first == last}. -\end{itemdescr} + template + 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 + 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; -\indexlibrarymember{insert_range}{basic_string}% -\begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - constexpr iterator insert_range(const_iterator p, R&& rg); -\end{itemdecl} + template + 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 + 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; -\begin{itemdescr} -\pnum -\expects -\tcode{p} is a valid iterator on \tcode{*this}. + constexpr basic_string substr(size_type pos = 0, size_type n = npos) const; -\pnum -\effects -Equivalent to -\tcode{insert(p - begin(), basic_string(from_range, std::forward(rg), get_allocator()))}. + template + constexpr int compare(const T& t) const noexcept(@\seebelow@); + template + constexpr int compare(size_type pos1, size_type n1, const T& t) const; + template + 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; -\pnum -\returns -An iterator which refers to the first inserted character, or -\tcode{p} if \tcode{rg} is empty. -\end{itemdescr} + 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; -\indexlibrarymember{insert}{basic_string}% -\begin{itemdecl} -constexpr iterator insert(const_iterator p, initializer_list il); -\end{itemdecl} + constexpr bool contains(basic_string_view x) const noexcept; + constexpr bool contains(charT x) const noexcept; + constexpr bool contains(const charT* x) const; + }; -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return insert(p, il.begin(), il.end());} -\end{itemdescr} + template::value_type>> + basic_string(InputIterator, InputIterator, Allocator = Allocator()) + -> basic_string::value_type, + char_traits::value_type>, + Allocator>; -\rSec4[string.erase]{\tcode{basic_string::erase}} + template>> + basic_string(from_range_t, R&&, Allocator = Allocator()) + -> basic_string, char_traits>, + Allocator>; -\indexlibrarymember{erase}{basic_string}% -\begin{itemdecl} -constexpr basic_string& erase(size_type pos = 0, size_type n = npos); -\end{itemdecl} + template> + explicit basic_string(basic_string_view, const Allocator& = Allocator()) + -> basic_string; -\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}. + template> + basic_string(basic_string_view, + typename @\seebelow@::size_type, typename @\seebelow@::size_type, + const Allocator& = Allocator()) + -> basic_string; +} +\end{codeblock} \pnum -\returns -\tcode{*this}. +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 -\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} +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. -\begin{itemdescr} -\pnum -\expects -\tcode{p} is a valid dereferenceable iterator on \tcode{*this}. +\rSec3[string.require]{General requirements} \pnum -\effects -Removes the character referred to by \tcode{p}. +If any operation would cause \tcode{size()} to +exceed \tcode{max_size()}, that operation throws an +exception object of type \tcode{length_error}. \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. +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 -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{erase}{basic_string}% -\begin{itemdecl} -constexpr iterator erase(const_iterator first, const_iterator last); -\end{itemdecl} +In every specialization \tcode{basic_string}, +the type \tcode{allocator_traits::value_type} shall name the same type +as \tcode{charT}. Every object of type +\tcode{basic_string} 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.requirements.general}. +In every specialization \tcode{basic_string}, +the type \tcode{traits} shall meet +the character traits requirements\iref{char.traits}. +\begin{note} +Every specialization \tcode{basic_string} is +an allocator-aware container, +but does not use the allocator's \tcode{construct} and \tcode{destroy} +member functions\iref{container.requirements.general}. +\end{note} +\begin{note} +The program is ill-formed if \tcode{traits::char_type} +is not the same type as \tcode{charT}. +\end{note} -\begin{itemdescr} \pnum -\expects -\tcode{first} and \tcode{last} are valid iterators on -\tcode{*this}. \range{first}{last} is a valid range. +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: -\pnum -\effects -Removes the characters in the range -\tcode{[first, last)}. +\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} -\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. +\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} -\pnum -\throws -Nothing. -\end{itemdescr} +\rSec3[string.cons]{Constructors and assignment operators} -\indexlibrarymember{pop_back}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} -constexpr void pop_back(); +constexpr explicit basic_string(const Allocator& a) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{!empty()}. - -\pnum -\effects -Equivalent to \tcode{erase(end() - 1)}. \pnum -\throws -Nothing. +\ensures +\tcode{size()} is equal to \tcode{0}. \end{itemdescr} -\rSec4[string.replace]{\tcode{basic_string::replace}} - -\indexlibrarymember{replace}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str); +constexpr basic_string(const basic_string& str); +constexpr basic_string(basic_string&& str) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return replace(pos1, n1, str.data(), str.size());} +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} -\indexlibrarymember{replace}{basic_string}% +\indexlibraryctor{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); +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()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: +Let \tcode{n} be \tcode{npos} for the first overload. Equivalent to: \begin{codeblock} -return replace(pos1, n1, basic_string_view(str).substr(pos2, n2)); +basic_string(basic_string_view(str).substr(pos, n), a) \end{codeblock} \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} template - constexpr basic_string& replace(size_type pos1, size_type n1, const T& t); + constexpr basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} +\tcode{is_convertible_v>} +is \tcode{true}. \pnum \effects -Equivalent to: +Creates a variable, \tcode{sv}, +as if by \tcode{basic_string_view sv = t;} +and then behaves the same as: \begin{codeblock} -basic_string_view sv = t; -return replace(pos1, n1, sv.data(), sv.size()); +basic_string(sv.substr(pos, n), a); \end{codeblock} \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} template - constexpr basic_string& replace(size_type pos1, size_type n1, const T& t, - size_type pos2, size_type n2 = npos); + constexpr explicit basic_string(const T& t, const Allocator& a = Allocator()); \end{itemdecl} \begin{itemdescr} @@ -2749,187 +2508,257 @@ \pnum \effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return replace(pos1, n1, sv.substr(pos2, n2)); -\end{codeblock} +Creates a variable, \tcode{sv}, as if by +\tcode{basic_string_view sv = t;} and +then behaves the same as \tcode{basic_string(sv.data(), sv.size(), a)}. \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(size_type pos1, size_type n1, const charT* s, size_type n2); +constexpr basic_string(const charT* s, size_type n, const Allocator& a = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \expects -\range{s}{s + n2} is a valid range. +\range{s}{s + n} 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}. +Constructs an object whose initial value is the range \range{s}{s + n}. \pnum -\returns -\tcode{*this}. +\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 -\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::allocate}. -\end{itemize} +\constraints +\tcode{Allocator} is a type +that qualifies as an allocator\iref{container.requirements.general}. +\begin{note} +This affects class template argument deduction. +\end{note} + +\pnum +\effects +Equivalent to: \tcode{basic_string(s, traits::length(s), a)}. \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(size_type pos, size_type n, const charT* s); +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.requirements.general}. +\begin{note} +This affects class template argument deduction. +\end{note} + \pnum \effects -Equivalent to: \tcode{return replace(pos, n, s, traits::length(s));} +Constructs an object whose value consists of \tcode{n} copies of \tcode{c}. \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(size_type pos1, size_type n1, size_type n2, charT c); +template + 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.requirements.general}. + \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}. +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}@ R> + constexpr basic_string(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} +\begin{itemdescr} \pnum -\returns -\tcode{*this}. +\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 il, const Allocator& a = Allocator()); +\end{itemdecl} +\begin{itemdescr} \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::allocate.} -\end{itemize} +\effects +Equivalent to \tcode{basic_string(il.begin(), il.end(), a)}. \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibraryctor{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str); +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 -Equivalent to: \tcode{return replace(i1, i2, basic_string_view(str));} +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} -\indexlibrarymember{replace}{basic_string}% \begin{itemdecl} -template - constexpr basic_string& replace(const_iterator i1, const_iterator i2, const T& t); +template::value_type>> + basic_string(InputIterator, InputIterator, Allocator = Allocator()) + -> basic_string::value_type, + char_traits::value_type>, + Allocator>; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} +\tcode{InputIterator} is a type that qualifies as an input iterator, +and \tcode{Allocator} is a type that qualifies as an allocator\iref{container.requirements.general}. +\end{itemdescr} -\pnum -\expects -\range{begin()}{i1} and \range{i1}{i2} are valid ranges. +\begin{itemdecl} +template> + explicit basic_string(basic_string_view, const Allocator& = Allocator()) + -> basic_string; + +template> + basic_string(basic_string_view, + typename @\seebelow@::size_type, typename @\seebelow@::size_type, + const Allocator& = Allocator()) + -> basic_string; +\end{itemdecl} +\begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -basic_string_view sv = t; -return replace(i1 - begin(), i2 - i1, sv.data(), sv.size()); -\end{codeblock} +\constraints +\tcode{Allocator} is a type that qualifies as +an allocator\iref{container.requirements.general}. \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{operator=}{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s, size_type n); +constexpr basic_string& operator=(const basic_string& str); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return replace(i1, i2, basic_string_view(s, n));} +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{replace}{basic_string}% +\indexlibrarymember{operator=}{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s); +constexpr basic_string& operator=(basic_string&& str) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return replace(i1, i2, basic_string_view(s));} +Move assigns as a sequence container\iref{container.requirements}, +except that iterators, pointers and references may be invalidated. + +\pnum +\returns +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{operator=}{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(const_iterator i1, const_iterator i2, size_type n, charT c); +template + constexpr basic_string& operator=(const T& t); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\range{begin()}{i1} and \range{i1}{i2} are valid ranges. +\constraints +\begin{itemize} +\item \tcode{is_convertible_v>} +is \tcode{true} and +\item \tcode{is_convertible_v} +is \tcode{false}. +\end{itemize} \pnum \effects -Equivalent to: \tcode{return replace(i1 - begin(), i2 - i1, n, c);} +Equivalent to: +\begin{codeblock} +basic_string_view sv = t; +return assign(sv); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\indexlibrarymember{operator=}{basic_string}% \begin{itemdecl} -template - constexpr basic_string& replace(const_iterator i1, const_iterator i2, - InputIterator j1, InputIterator j2); +constexpr basic_string& operator=(const charT* s); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{InputIterator} is a type that qualifies as an input -iterator\iref{container.requirements.general}. +\effects +Equivalent to: +\tcode{return *this = basic_string_view(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 replace(i1, i2, basic_string(j1, j2, get_allocator()));} +Equivalent to: +\begin{codeblock} +return *this = basic_string_view(addressof(c), 1); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{replace_with_range}{basic_string}% +\indexlibrarymember{operator=}{basic_string}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); +constexpr basic_string& operator=(initializer_list il); \end{itemdecl} \begin{itemdescr} @@ -2937,428 +2766,467 @@ \effects Equivalent to: \begin{codeblock} -return replace(i1, i2, basic_string(from_range, std::forward(rg), get_allocator())); +return *this = basic_string_view(il.begin(), il.size()); \end{codeblock} \end{itemdescr} -\indexlibrarymember{replace}{basic_string}% +\rSec3[string.iterators]{Iterator support} + +\indexlibrarymember{begin}{basic_string}% +\indexlibrarymember{cbegin}{basic_string}% \begin{itemdecl} -constexpr basic_string& replace(const_iterator i1, const_iterator i2, initializer_list il); +constexpr iterator begin() noexcept; +constexpr const_iterator begin() const noexcept; +constexpr const_iterator cbegin() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return replace(i1, i2, il.begin(), il.size());} +\returns +An iterator referring to the first character in the string. \end{itemdescr} -\rSec4[string.copy]{\tcode{basic_string::copy}} - -\indexlibrarymember{copy}{basic_string}% +\indexlibrarymember{end}{basic_string}% +\indexlibrarymember{cend}{basic_string}% \begin{itemdecl} -constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; +constexpr iterator end() noexcept; +constexpr const_iterator end() const noexcept; +constexpr const_iterator cend() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\tcode{return basic_string_view(*this).copy(s, n, pos);} -\begin{note} -This does not terminate \tcode{s} with a null object. -\end{note} +\returns +An iterator which is the past-the-end value. \end{itemdescr} -\rSec4[string.swap]{\tcode{basic_string::swap}} - -\indexlibrarymember{swap}{basic_string}% +\indexlibrarymember{rbegin}{basic_string}% +\indexlibrarymember{crbegin}{basic_string}% \begin{itemdecl} -constexpr void swap(basic_string& s) - noexcept(allocator_traits::propagate_on_container_swap::value || - allocator_traits::is_always_equal::value); +constexpr reverse_iterator rbegin() noexcept; +constexpr const_reverse_iterator rbegin() const noexcept; +constexpr const_reverse_iterator crbegin() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{allocator_traits::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}. +\returns +An iterator which is semantically equivalent to +\tcode{reverse_iterator(end())}. +\end{itemdescr} -\pnum -\throws -Nothing. +\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 -\complexity -Constant time. +\returns +An iterator which is semantically equivalent to +\tcode{reverse_iterator(begin())}. \end{itemdescr} -\rSec3[string.ops]{String operations} - -\rSec4[string.accessors]{Accessors} +\rSec3[string.capacity]{Capacity} -\indexlibrarymember{c_str}{basic_string}% -\indexlibrarymember{data}{basic_string}% +\indexlibrarymember{size}{basic_string}% +\indexlibrarymember{length}{basic_string}% \begin{itemdecl} -constexpr const charT* c_str() const noexcept; -constexpr const charT* data() const noexcept; +constexpr size_type size() const noexcept; +constexpr size_type length() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -A pointer \tcode{p} such that \tcode{p + i == addressof(operator[](i))} for each -\tcode{i} in \crange{0}{size()}. +A count of the number of char-like objects currently in the string. \pnum \complexity Constant time. - -\pnum -\remarks -The program shall not modify any of the values stored in the character array; otherwise, the behavior is undefined. \end{itemdescr} -\indexlibrarymember{data}{basic_string}% +\indexlibrarymember{max_size}{basic_string}% \begin{itemdecl} -constexpr charT* data() noexcept; +constexpr size_type max_size() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -A pointer \tcode{p} such that \tcode{p + i == addressof(operator[](i))} for each -\tcode{i} in \crange{0}{size()}. +The largest possible number of char-like objects that can be stored in a +\tcode{basic_string}. \pnum \complexity Constant time. - -\pnum -\remarks -The program shall not modify the value stored at \tcode{p + size()} -to any value other than \tcode{charT()}; otherwise, the behavior is undefined. \end{itemdescr} -\indexlibrarymember{operator basic_string_view}{basic_string}% +\indexlibrarymember{resize}{basic_string}% \begin{itemdecl} -constexpr operator basic_string_view() const noexcept; +constexpr void resize(size_type n, charT c); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return basic_string_view(data(), size());} +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{get_allocator}{basic_string}% +\indexlibrarymember{resize}{basic_string}% \begin{itemdecl} -constexpr allocator_type get_allocator() const noexcept; +constexpr void resize(size_type n); \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. +\effects +Equivalent to \tcode{resize(n, charT())}. \end{itemdescr} -\rSec4[string.find]{Searching} +\indexlibrarymember{resize_and_overwrite}{basic_string}% +\begin{itemdecl} +template constexpr void resize_and_overwrite(size_type n, Operation op); +\end{itemdecl} +\begin{itemdescr} \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}. - +Let \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(str), pos);} - +\tcode{o = size()} before the call to \tcode{resize_and_overwrite}. \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(s), pos);} - +\tcode{k} be \tcode{min(o, n)}. \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(s, n), pos);} +\tcode{p} be a \tcode{charT*}, +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 +$OP$ be the expression \tcode{std::move(op)(p, n)}. +\item +\tcode{r} = $OP$. +\end{itemize} +\pnum +\mandates +$OP$ has an integer-like type\iref{iterator.concept.winc}. + +\pnum +\expects +\begin{itemize} \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(addressof(c), 1), pos); -\end{codeblock} +$OP$ does not throw an exception or modify \tcode{p} or \tcode{n}. +\item +$\tcode{r} \geq 0$. +\item +$\tcode{r} \leq \tcode{n}$. +\item +After evaluating $OP$ +there are no indeterminate values in the range \range{p}{p + r}. \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}% +\pnum +\effects +Evaluates $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 $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. +After +\tcode{reserve()}, +\tcode{capacity()} +is greater or equal to the argument of +\tcode{reserve} +if reallocation happens; and +equal to the previous value of +\tcode{capacity()} +otherwise. +Reallocation happens at this point if and only if +the current capacity is less than the argument of \tcode{reserve()}. + +\pnum +\throws +\tcode{length_error} +if +\tcode{res_arg > max_size()} or any exceptions thrown by +\tcode{allocator_traits} \tcode{::allocate}. +\end{itemdescr} + +\indexlibrarymember{shrink_to_fit}{basic_string}% \begin{itemdecl} -template - constexpr size_type find(const T& t, size_type pos = 0) const noexcept(@\seebelow@); -template - constexpr size_type rfind(const T& t, size_type pos = npos) const noexcept(@\seebelow@); -template - constexpr size_type find_first_of(const T& t, size_type pos = 0) const noexcept(@\seebelow@); -template - constexpr size_type find_last_of(const T& t, size_type pos = npos) const noexcept(@\seebelow@); -template - constexpr size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept(@\seebelow@); -template - constexpr size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept(@\seebelow@); +constexpr void shrink_to_fit(); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} +\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 -\effects -Let \placeholder{G} be the name of the function. -Equivalent to: -\begin{codeblock} -basic_string_view s = *this, sv = t; -return s.@\placeholder{G}@(sv, pos); -\end{codeblock} +\complexity +If the size is not equal to the old capacity, +linear in the size of the sequence; +otherwise constant. \pnum \remarks -The exception specification is equivalent to -\tcode{is_nothrow_convertible_v>}. +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} -\rSec4[string.substr]{\tcode{basic_string::substr}} - -\indexlibrarymember{substr}{basic_string}% +\indexlibrarymember{clear}{basic_string}% \begin{itemdecl} -constexpr basic_string substr(size_type pos = 0, size_type n = npos) const; +constexpr void clear() noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Determines the effective length \tcode{rlen} of the string to copy as the smaller of \tcode{n} and -\tcode{size() - pos}. +Equivalent to: \tcode{erase(begin(), end());} +\end{itemdescr} -\pnum -\returns -\tcode{basic_string(data()+pos, rlen)}. +\indexlibrarymember{empty}{basic_string}% +\begin{itemdecl} +[[nodiscard]] constexpr bool empty() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -\tcode{out_of_range} -if -\tcode{pos > size()}. +\effects +Equivalent to: +\tcode{return size() == 0;} \end{itemdescr} -\rSec4[string.compare]{\tcode{basic_string::compare}} +\rSec3[string.access]{Element access} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{operator[]}{basic_string}% \begin{itemdecl} -template - constexpr int compare(const T& t) const noexcept(@\seebelow@); +constexpr const_reference operator[](size_type pos) const; +constexpr reference operator[](size_type pos); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} +\expects +\tcode{pos <= size()}. \pnum -\effects -Equivalent to: \tcode{return basic_string_view(*this).compare(t);} +\returns +\tcode{*(begin() + pos)} if \tcode{pos < size()}. Otherwise, +returns a reference to an object of type \tcode{charT} with value +\tcode{charT()}, where modifying the object to any value other than +\tcode{charT()} leads to undefined behavior. \pnum -\remarks -The exception specification is equivalent to -\tcode{is_nothrow_convertible_v>}. +\throws +Nothing. + +\pnum +\complexity +Constant time. \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{at}{basic_string}% \begin{itemdecl} -template - constexpr int compare(size_type pos1, size_type n1, const T& t) const; +constexpr const_reference at(size_type pos) const; +constexpr reference at(size_type pos); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} +\returns +\tcode{operator[](pos)}. \pnum -\effects -Equivalent to: -\begin{codeblock} -return basic_string_view(*this).substr(pos1, n1).compare(t); -\end{codeblock} +\throws +\tcode{out_of_range} +if +\tcode{pos >= size()}. \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{front}{basic_string}% \begin{itemdecl} -template - constexpr int compare(size_type pos1, size_type n1, const T& t, - size_type pos2, size_type n2 = npos) const; +constexpr const charT& front() const; +constexpr charT& front(); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item -\tcode{is_convertible_v>} is -\tcode{true} and -\item -\tcode{is_convertible_v} is -\tcode{false}. -\end{itemize} +\expects +\tcode{!empty()}. \pnum \effects -Equivalent to: -\begin{codeblock} -basic_string_view s = *this, sv = t; -return s.substr(pos1, n1).compare(sv.substr(pos2, n2)); -\end{codeblock} +Equivalent to: \tcode{return operator[](0);} \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{back}{basic_string}% \begin{itemdecl} -constexpr int compare(const basic_string& str) const noexcept; +constexpr const charT& back() const; +constexpr charT& back(); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{!empty()}. + \pnum \effects -Equivalent to: -\tcode{return compare(basic_string_view(str));} +Equivalent to: \tcode{return operator[](size() - 1);} \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\rSec3[string.modifiers]{Modifiers} + +\rSec4[string.op.append]{\tcode{basic_string::operator+=}} + +\indexlibrarymember{operator+=}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos1, size_type n1, const basic_string& str) const; +constexpr basic_string& operator+=(const basic_string& str); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return compare(pos1, n1, basic_string_view(str));} +Equivalent to: \tcode{return append(str);} + + \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{operator+=}{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; +template + constexpr basic_string& operator+=(const T& t); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} + \pnum \effects Equivalent to: \begin{codeblock} -return compare(pos1, n1, basic_string_view(str), pos2, n2); +basic_string_view sv = t; +return append(sv); \end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{operator+=}{basic_string}% \begin{itemdecl} -constexpr int compare(const charT* s) const; +constexpr basic_string& operator+=(const charT* s); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return compare(basic_string_view(s));} +Equivalent to: \tcode{return append(s);} \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{operator+=}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos, size_type n1, const charT* s) const; +constexpr basic_string& operator+=(charT c); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return compare(pos, n1, basic_string_view(s));} +Equivalent to: \tcode{return append(size_type\{1\}, c);} \end{itemdescr} -\indexlibrarymember{compare}{basic_string}% +\indexlibrarymember{operator+=}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos, size_type n1, const charT* s, size_type n2) const; +constexpr basic_string& operator+=(initializer_list il); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return compare(pos, n1, basic_string_view(s, n2));} +Equivalent to: \tcode{return append(il);} \end{itemdescr} -\rSec4[string.starts.with]{\tcode{basic_string::starts_with}} -\indexlibrarymember{starts_with}{basic_string}% +\rSec4[string.append]{\tcode{basic_string::append}} + +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -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 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} @@ -3366,457 +3234,360 @@ \effects Equivalent to: \begin{codeblock} -return basic_string_view(data(), size()).starts_with(x); +return append(basic_string_view(str).substr(pos, n)); \end{codeblock} \end{itemdescr} -\rSec4[string.ends.with]{\tcode{basic_string::ends_with}} - -\indexlibrarymember{ends_with}{basic_string}% +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -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; +template + constexpr basic_string& append(const T& t); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} + \pnum \effects Equivalent to: \begin{codeblock} -return basic_string_view(data(), size()).ends_with(x); +basic_string_view sv = t; +return append(sv.data(), sv.size()); \end{codeblock} \end{itemdescr} -\rSec4[string.contains]{\tcode{basic_string::contains}} - -\indexlibrarymember{contains}{basic_string}% +\indexlibrarymember{append}{basic_string}% \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; +template + 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>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} + \pnum \effects Equivalent to: \begin{codeblock} -return basic_string_view(data(), size()).contains(x); +basic_string_view sv = t; +return append(sv.substr(pos, n)); \end{codeblock} \end{itemdescr} -\rSec2[string.nonmembers]{Non-member functions} - -\indexlibraryglobal{basic_string} - -\rSec3[string.op.plus]{\tcode{operator+}} - -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(const basic_string& lhs, - const basic_string& rhs); -template - constexpr basic_string - operator+(const basic_string& lhs, const charT* rhs); +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 -Equivalent to: -\begin{codeblock} -basic_string r = lhs; -r.append(rhs); -return r; -\end{codeblock} +Appends a copy of the range \range{s}{s + n} to the string. + +\pnum +\returns +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(basic_string&& lhs, - const basic_string& rhs); -template - constexpr basic_string - operator+(basic_string&& lhs, const charT* rhs); +constexpr basic_string& append(const charT* s); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -lhs.append(rhs); -return std::move(lhs); -\end{codeblock} +Equivalent to: \tcode{return append(s, traits::length(s));} \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(basic_string&& lhs, - basic_string&& rhs); +constexpr basic_string& append(size_type n, charT c); \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} +Appends \tcode{n} copies of \tcode{c} to the string. + +\pnum +\returns +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(const basic_string& lhs, - basic_string&& rhs); -template - constexpr basic_string - operator+(const charT* lhs, basic_string&& rhs); +template + 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.requirements.general}. + \pnum \effects -Equivalent to: -\begin{codeblock} -rhs.insert(0, lhs); -return std::move(rhs); -\end{codeblock} +Equivalent to: \tcode{return append(basic_string(first, last, get_allocator()));} \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{append_range}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(const charT* lhs, const basic_string& rhs); +template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& append_range(R&& rg); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -basic_string r = rhs; -r.insert(0, lhs); -return r; -\end{codeblock} +Equivalent to: \tcode{return append(basic_string(from_range, std::forward(rg), get_allocator()));} \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{append}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(charT lhs, const basic_string& rhs); +constexpr basic_string& append(initializer_list il); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -basic_string r = rhs; -r.insert(r.begin(), lhs); -return r; -\end{codeblock} +Equivalent to: \tcode{return append(il.begin(), il.size());} \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{push_back}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(charT lhs, basic_string&& rhs); +constexpr void push_back(charT c); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -rhs.insert(rhs.begin(), lhs); -return std::move(rhs); -\end{codeblock} +Equivalent to +\tcode{append(size_type\{1\}, c)}. \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% +\rSec4[string.assign]{\tcode{basic_string::assign}} + +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(const basic_string& lhs, charT rhs); +constexpr basic_string& assign(const basic_string& str); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -basic_string r = lhs; -r.push_back(rhs); -return r; -\end{codeblock} +Equivalent to: \tcode{return *this = str;} \end{itemdescr} -\indexlibrarymember{operator+}{basic_string}% +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -template - constexpr basic_string - operator+(basic_string&& lhs, charT rhs); +constexpr basic_string& assign(basic_string&& str) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -lhs.push_back(rhs); -return std::move(lhs); -\end{codeblock} +Equivalent to: \tcode{return *this = std::move(str);} \end{itemdescr} -\rSec3[string.cmp]{Non-member comparison operator functions} -\begin{itemdecl} -template - constexpr bool - operator==(const basic_string& lhs, - const basic_string& rhs) noexcept; -template - constexpr bool operator==(const basic_string& lhs, - const charT* rhs); -template - constexpr @\seebelow@ operator<=>(const basic_string& lhs, - @\itcorr@ const basic_string& rhs) noexcept; -template - constexpr @\seebelow@ operator<=>(const basic_string& lhs, - @\itcorr@ const charT* rhs); +\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 -Let \tcode{\placeholder{op}} be the operator. Equivalent to: \begin{codeblock} -return basic_string_view(lhs) @\placeholder{op}@ basic_string_view(rhs); +return assign(basic_string_view(str).substr(pos, n)); \end{codeblock} \end{itemdescr} -\rSec3[string.special]{\tcode{swap}} - -\indexlibrarymember{swap}{basic_string}% +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -template - constexpr void - swap(basic_string& lhs, - basic_string& rhs) - noexcept(noexcept(lhs.swap(rhs))); +template + constexpr basic_string& assign(const T& t); \end{itemdecl} -\begin{itemdescr} +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} + \pnum \effects -Equivalent to \tcode{lhs.swap(rhs)}. +Equivalent to: +\begin{codeblock} +basic_string_view sv = t; +return assign(sv.data(), sv.size()); +\end{codeblock} \end{itemdescr} -\rSec3[string.io]{Inserters and extractors} - -\indexlibrarymember{operator>>}{basic_string}% +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -template - basic_istream& - operator>>(basic_istream& is, basic_string& str); +template + constexpr basic_string& assign(const T& t, size_type pos, size_type n = npos); \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: +\constraints \begin{itemize} \item -\textit{n} -characters are stored; -\item -end-of-file occurs on the input sequence; +\tcode{is_convertible_v>} is +\tcode{true} and \item -\tcode{isspace(c, is.getloc())} -is \tcode{true} for the next available input character -\textit{c}. +\tcode{is_convertible_v} is +\tcode{false}. \end{itemize} \pnum -After the last character (if any) is extracted, -\tcode{is.width(0)} -is called and the -\tcode{sentry} -object is destroyed. +\effects +Equivalent to: +\begin{codeblock} +basic_string_view 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 -If the function extracts no characters, it calls -\tcode{is.setstate(ios_base::failbit)}, -which may throw -\tcode{ios_base::fail\-ure}\iref{iostate.flags}. +\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{is}. +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{operator<<}{basic_string}% +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -template - basic_ostream& - operator<<(basic_ostream& os, - const basic_string& str); +constexpr basic_string& assign(const charT* s); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return os << basic_string_view(str);} +Equivalent to: \tcode{return assign(s, traits::length(s));} \end{itemdescr} -\indexlibrarymember{getline}{basic_string}% +\indexlibrarymember{assign}{basic_string}% \begin{itemdecl} -template - basic_istream& - getline(basic_istream& is, - basic_string& str, - charT delim); -template - basic_istream& - getline(basic_istream&& is, - basic_string& str, - charT delim); +constexpr basic_string& assign(initializer_list il); \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 -(in which case, the -\tcode{getline} -function calls -\tcode{is.setstate(\brk{}ios_base::eofbit)}). -\item -\tcode{traits::eq(c, delim)} -for the next available input character -\textit{c} -(in which case, -\textit{c} -is extracted but not appended)\iref{iostate.flags} -\item -\tcode{str.max_size()} -characters are stored -(in which case, -the function calls -\tcode{is.setstate(ios_base::fail\-bit))}\iref{iostate.flags} -\end{itemize} +Equivalent to: \tcode{return assign(il.begin(), il.size());} +\end{itemdescr} + +\indexlibrarymember{assign}{basic_string}% +\begin{itemdecl} +constexpr basic_string& assign(size_type n, charT c); +\end{itemdecl} +\begin{itemdescr} \pnum -The conditions are tested in the order shown. -In any case, -after the last character is extracted, the -\tcode{sentry} -object is destroyed. +\effects +Equivalent to: +\begin{codeblock} +clear(); +resize(n, c); +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{assign}{basic_string}% +\begin{itemdecl} +template + constexpr basic_string& assign(InputIterator first, InputIterator last); +\end{itemdecl} +\begin{itemdescr} \pnum -If the function extracts no characters, it calls -\tcode{is.setstate(ios_base::fail\-bit)} -which may throw -\tcode{ios_base::fail\-ure}\iref{iostate.flags}. +\constraints +\tcode{InputIterator} is a type that qualifies as an input +iterator\iref{container.requirements.general}. \pnum -\returns -\tcode{is}. +\effects +Equivalent to: \tcode{return assign(basic_string(first, last, get_allocator()));} \end{itemdescr} -\indexlibrarymember{getline}{basic_string}% +\indexlibrarymember{assign_range}{basic_string}% \begin{itemdecl} -template - basic_istream& - getline(basic_istream& is, - basic_string& str); -template - basic_istream& - getline(basic_istream&& is, - basic_string& str); +template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& assign_range(R&& rg); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{getline(is, str, is.widen('\textbackslash n'))}. +\effects +Equivalent to: \tcode{return assign(basic_string(from_range, std::forward(rg), get_allocator()));} \end{itemdescr} -\rSec3[string.erasure]{Erasure} +\rSec4[string.insert]{\tcode{basic_string::insert}} -\indexlibrarymember{erase}{basic_string}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -template - constexpr typename basic_string::size_type - erase(basic_string& c, const U& value); +constexpr basic_string& insert(size_type pos, const basic_string& str); \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} +Equivalent to: \tcode{return insert(pos, str.data(), str.size());} \end{itemdescr} -\indexlibrarymember{erase_if}{basic_string}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -template - constexpr typename basic_string::size_type - erase_if(basic_string& c, Predicate pred); +constexpr basic_string& insert(size_type pos1, const basic_string& str, + size_type pos2, size_type n = npos); \end{itemdecl} \begin{itemdescr} @@ -3824,1107 +3595,1201 @@ \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; +return insert(pos1, basic_string_view(str), pos2, n); \end{codeblock} \end{itemdescr} -\rSec2[string.conversions]{Numeric conversions} - -\indexlibraryglobal{stoi}% -\indexlibraryglobal{stol}% -\indexlibraryglobal{stoul}% -\indexlibraryglobal{stoll}% -\indexlibraryglobal{stoull}% +\indexlibrarymember{insert}{basic_string}% \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); +template + constexpr basic_string& insert(size_type pos, const T& t); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} + \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}. +Equivalent to: +\begin{codeblock} +basic_string_view sv = t; +return insert(pos, sv.data(), sv.size()); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{insert}{basic_string}% +\begin{itemdecl} +template + constexpr basic_string& insert(size_type pos1, const T& t, + size_type pos2, size_type n = npos); +\end{itemdecl} +\begin{itemdescr} \pnum -\returns -The converted result. +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} \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. +\effects +Equivalent to: +\begin{codeblock} +basic_string_view sv = t; +return insert(pos1, sv.substr(pos2, n)); +\end{codeblock} \end{itemdescr} -\indexlibraryglobal{stof}% -\indexlibraryglobal{stod}% -\indexlibraryglobal{stold}% +\indexlibrarymember{insert}{basic_string}% \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); +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 -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}. +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 -The converted result. +\tcode{*this}. \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. +\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::allocate}. +\end{itemize} \end{itemdescr} -\indexlibraryglobal{to_string}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -string to_string(int val); -string to_string(unsigned val); -string to_string(long val); -string to_string(unsigned long val); -string to_string(long long val); -string to_string(unsigned long long val); -string to_string(float val); -string to_string(double val); -string to_string(long double val); +constexpr basic_string& insert(size_type pos, const charT* s); \end{itemdecl} \begin{itemdescr} \pnum -\returns -Each function returns a \tcode{string} object holding the character -representation of the value of its argument that would be generated by calling -\tcode{sprintf(buf, fmt, val)} with a format specifier of -\tcode{"\%d"}, -\tcode{"\%u"}, -\tcode{"\%ld"}, -\tcode{"\%lu"}, -\tcode{"\%lld"}, \tcode{"\%llu"}, -\tcode{"\%f"}, -\tcode{"\%f"}, -or \tcode{"\%Lf"}, respectively, where \tcode{buf} designates an internal -character buffer of sufficient size. +\effects +Equivalent to: \tcode{return insert(pos, s, traits::length(s));} \end{itemdescr} -\indexlibraryglobal{stoi}% -\indexlibraryglobal{stol}% -\indexlibraryglobal{stoul}% -\indexlibraryglobal{stoll}% -\indexlibraryglobal{stoull}% +\indexlibrarymember{insert}{basic_string}% \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); +constexpr basic_string& insert(size_type pos, size_type n, charT c); \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}. +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 -The converted result. +\tcode{*this} \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. +\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::allocate}. +\end{itemize} \end{itemdescr} -\indexlibraryglobal{stof}% -\indexlibraryglobal{stod}% -\indexlibraryglobal{stold}% +\indexlibrarymember{insert}{basic_string}% \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); +constexpr iterator insert(const_iterator p, charT c); \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}. +\expects +\tcode{p} is a valid iterator on +\tcode{*this}. \pnum -\returns -The converted result. +\effects +Inserts a copy of \tcode{c} at the position \tcode{p}. \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}. +\returns +An iterator which refers to the inserted character. \end{itemdescr} -\indexlibraryglobal{to_wstring}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -wstring to_wstring(int val); -wstring to_wstring(unsigned val); -wstring to_wstring(long val); -wstring to_wstring(unsigned long val); -wstring to_wstring(long long val); -wstring to_wstring(unsigned long long val); -wstring to_wstring(float val); -wstring to_wstring(double val); -wstring to_wstring(long double val); +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 -Each function returns a \tcode{wstring} object holding the character -representation of the value of its argument that would be generated by calling -\tcode{swprintf(buf, buffsz, fmt, val)} with a format specifier of -\tcode{L"\%d"}, -\tcode{L"\%u"}, -\tcode{L"\%ld"}, -\tcode{L"\%lu"}, -\tcode{L"\%lld"}, -\tcode{L"\%llu"}, -\tcode{L"\%f"}, -\tcode{L"\%f"}, -or \tcode{L"\%Lf"}, respectively, where \tcode{buf} designates an -internal character buffer of sufficient size \tcode{buffsz}. +An iterator which refers to the first inserted character, or +\tcode{p} if \tcode{n == 0}. \end{itemdescr} -\rSec2[basic.string.hash]{Hash support} - -\indexlibrarymember{hash}{string}% -\indexlibrarymember{hash}{u16string}% -\indexlibrarymember{hash}{u32string}% -\indexlibrarymember{hash}{wstring}% -\indexlibrarymember{hash}{pmr::string}% -\indexlibrarymember{hash}{pmr::u16string}% -\indexlibrarymember{hash}{pmr::u32string}% -\indexlibrarymember{hash}{pmr::wstring}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; +template + constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last); \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) == hash()(SV(s))}. -\end{itemdescr} +\constraints +\tcode{InputIterator} is a type that qualifies as an input +iterator\iref{container.requirements.general}. -\rSec2[basic.string.literals]{Suffix for \tcode{basic_string} literals} +\pnum +\expects +\tcode{p} is a valid iterator on +\tcode{*this}. -\indexlibrarymember{operator""""s}{string}% -\begin{itemdecl} -constexpr string operator""s(const char* str, size_t len); -\end{itemdecl} +\pnum +\effects +Equivalent to +\tcode{insert(p - begin(), basic_string(first, last, get_allocator()))}. -\begin{itemdescr} \pnum \returns -\tcode{string\{str, len\}}. +An iterator which refers to the first inserted character, or +\tcode{p} if \tcode{first == last}. \end{itemdescr} -\indexlibrarymember{operator""""s}{u8string}% +\indexlibrarymember{insert_range}{basic_string}% \begin{itemdecl} -constexpr u8string operator""s(const char8_t* str, size_t len); +template<@\exposconcept{container-compatible-range}@ 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(rg), get_allocator()))}. + \pnum \returns -\tcode{u8string\{str, len\}}. +An iterator which refers to the first inserted character, or +\tcode{p} if \tcode{rg} is empty. \end{itemdescr} -\indexlibrarymember{operator""""s}{u16string}% +\indexlibrarymember{insert}{basic_string}% \begin{itemdecl} -constexpr u16string operator""s(const char16_t* str, size_t len); +constexpr iterator insert(const_iterator p, initializer_list il); \end{itemdecl} + \begin{itemdescr} \pnum -\returns -\tcode{u16string\{str, len\}}. +\effects +Equivalent to: \tcode{return insert(p, il.begin(), il.end());} \end{itemdescr} -\indexlibrarymember{operator""""s}{u32string}% +\rSec4[string.erase]{\tcode{basic_string::erase}} + +\indexlibrarymember{erase}{basic_string}% \begin{itemdecl} -constexpr u32string operator""s(const char32_t* str, size_t len); +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{u32string\{str, len\}}. +\tcode{*this}. + +\pnum +\throws +\tcode{out_of_range} +if \tcode{pos} +\tcode{> size()}. \end{itemdescr} -\indexlibrarymember{operator""""s}{wstring}% +\indexlibrarymember{erase}{basic_string}% \begin{itemdecl} -constexpr wstring operator""s(const wchar_t* str, size_t len); +constexpr iterator erase(const_iterator p); \end{itemdecl} + \begin{itemdescr} \pnum -\returns -\tcode{wstring\{str, len\}}. -\end{itemdescr} +\expects +\tcode{p} is a valid dereferenceable iterator on \tcode{*this}. \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[string.view]{String view classes} - -\rSec2[string.view.general]{General} +\effects +Removes the character referred to by \tcode{p}. \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}. +\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 -\begin{note} -The library provides implicit conversions from \tcode{const charT*} and \tcode{std::basic_string} to \tcode{std::basic_string_view} so that user code can accept just \tcode{std::basic_string_view} 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} in order to interoperate with these functions. -\end{note} - -\rSec2[string.view.synop]{Header \tcode{} synopsis} - -\indexheader{string_view}% -\begin{codeblock} -#include // see \ref{compare.syn} - -namespace std { - // \ref{string.view.template}, class template \tcode{basic_string_view} - template> - class basic_string_view; - - template - inline constexpr bool ranges::enable_view> = true; - template - inline constexpr bool ranges::enable_borrowed_range> = true; - - // \ref{string.view.comparison}, non-member comparison functions - template - constexpr bool operator==(basic_string_view x, - basic_string_view y) noexcept; - template - constexpr @\seebelow@ operator<=>(basic_string_view x, - @\itcorr@ basic_string_view y) noexcept; - - // see \ref{string.view.comparison}, sufficient additional overloads of comparison functions - - // \ref{string.view.io}, inserters and extractors - template - basic_ostream& - operator<<(basic_ostream& os, - basic_string_view str); - - // \tcode{basic_string_view} \grammarterm{typedef-name}s - using string_view = basic_string_view; - using u8string_view = basic_string_view; - using u16string_view = basic_string_view; - using u32string_view = basic_string_view; - using wstring_view = basic_string_view; - - // \ref{string.view.hash}, hash support - template struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; - template<> struct hash; +\throws +Nothing. +\end{itemdescr} - 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} +\indexlibrarymember{erase}{basic_string}% +\begin{itemdecl} +constexpr iterator erase(const_iterator first, const_iterator last); +\end{itemdecl} +\begin{itemdescr} \pnum -The function templates defined in \ref{utility.swap} and \ref{iterator.range} -are available when \tcode{} is included. - -\rSec2[string.view.template]{Class template \tcode{basic_string_view}} - -\rSec3[string.view.template.general]{General} +\expects +\tcode{first} and \tcode{last} are valid iterators on +\tcode{*this}. \range{first}{last} is a valid range. -\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 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; - using reverse_iterator = const_reverse_iterator; - using size_type = size_t; - using difference_type = ptrdiff_t; - static constexpr size_type npos = size_type(-1); +\pnum +\effects +Removes the characters in the range +\tcode{[first, last)}. - // \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 - constexpr basic_string_view(It begin, End end); - template - constexpr basic_string_view(R&& r); +\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. - // \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; +\pnum +\throws +Nothing. +\end{itemdescr} - // \ref{string.view.capacity}, capacity - constexpr size_type size() const noexcept; - constexpr size_type length() const noexcept; - constexpr size_type max_size() const noexcept; - [[nodiscard]] constexpr bool empty() const noexcept; +\indexlibrarymember{pop_back}{basic_string}% +\begin{itemdecl} +constexpr void pop_back(); +\end{itemdecl} - // \ref{string.view.access}, element access - constexpr const_reference operator[](size_type pos) const; - constexpr const_reference at(size_type pos) const; - constexpr const_reference front() const; - constexpr const_reference back() const; - constexpr const_pointer data() const noexcept; +\begin{itemdescr} +\pnum +\expects +\tcode{!empty()}. - // \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; +\pnum +\effects +Equivalent to \tcode{erase(end() - 1)}. - // \ref{string.view.ops}, string operations - constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; +\pnum +\throws +Nothing. +\end{itemdescr} - constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; +\rSec4[string.replace]{\tcode{basic_string::replace}} - constexpr int compare(basic_string_view s) const noexcept; - constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const; - constexpr int compare(size_type pos1, size_type n1, basic_string_view s, - size_type pos2, size_type n2) 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; +\indexlibrarymember{replace}{basic_string}% +\begin{itemdecl} +constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str); +\end{itemdecl} - 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; +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return replace(pos1, n1, str.data(), str.size());} +\end{itemdescr} - constexpr bool contains(basic_string_view x) const noexcept; - constexpr bool contains(charT x) const noexcept; - constexpr bool contains(const charT* x) const; +\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} - // \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; +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return replace(pos1, n1, basic_string_view(str).substr(pos2, n2)); +\end{codeblock} +\end{itemdescr} - 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; +\indexlibrarymember{replace}{basic_string}% +\begin{itemdecl} +template + constexpr basic_string& replace(size_type pos1, size_type n1, const T& t); +\end{itemdecl} - private: - const_pointer data_; // \expos - size_type size_; // \expos - }; +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} - // \ref{string.view.deduct}, deduction guides - template - basic_string_view(It, End) -> basic_string_view>; - template - basic_string_view(R&&) -> basic_string_view>; -} +\pnum +\effects +Equivalent to: +\begin{codeblock} +basic_string_view sv = t; +return replace(pos1, n1, sv.data(), sv.size()); \end{codeblock} +\end{itemdescr} +\indexlibrarymember{replace}{basic_string}% +\begin{itemdecl} +template + 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 -In every specialization \tcode{basic_string_view}, 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} +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} \pnum -For a \tcode{basic_string_view str}, -any operation that invalidates a pointer -in the range \range{str.data()}{\brk{}str.data() + str.size()} -invalidates pointers, iterators, and references -returned from \tcode{str}'s member functions. +\effects +Equivalent to: +\begin{codeblock} +basic_string_view 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 -The complexity of \tcode{basic_string_view} member functions is \bigoh{1} -unless otherwise specified. +\expects +\range{s}{s + n2} is a valid range. \pnum -\tcode{basic_string_view} is -a trivially copyable type\iref{term.trivially.copyable.type}. +\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}. -\rSec3[string.view.cons]{Construction and assignment} +\pnum +\returns +\tcode{*this}. -\indexlibraryctor{basic_string_view}% +\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::allocate}. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{replace}{basic_string}% \begin{itemdecl} -constexpr basic_string_view() noexcept; +constexpr basic_string& replace(size_type pos, size_type n, const charT* s); \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{size_ == 0} and \tcode{data_ == nullptr}. +\effects +Equivalent to: \tcode{return replace(pos, n, s, traits::length(s));} \end{itemdescr} -\indexlibraryctor{basic_string_view}% +\indexlibrarymember{replace}{basic_string}% \begin{itemdecl} -constexpr basic_string_view(const charT* str); +constexpr basic_string& replace(size_type pos1, size_type n1, size_type n2, charT c); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\range{str}{str + traits::length(str)} is a valid range. +\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 -\effects -Constructs a \tcode{basic_string_view}, initializing \tcode{data_} with \tcode{str} -and initializing \tcode{size_} with \tcode{traits::length(str)}. +\returns +\tcode{*this}. \pnum -\complexity -\bigoh{\tcode{traits::length(str)}}. +\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::allocate.} +\end{itemize} \end{itemdescr} -\indexlibraryctor{basic_string_view}% +\indexlibrarymember{replace}{basic_string}% \begin{itemdecl} -constexpr basic_string_view(const charT* str, size_type len); +constexpr basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str); \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\range{str}{str + len} is a valid range. - \pnum \effects -Constructs a \tcode{basic_string_view}, initializing \tcode{data_} with \tcode{str} -and initializing \tcode{size_} with \tcode{len}. +Equivalent to: \tcode{return replace(i1, i2, basic_string_view(str));} \end{itemdescr} -\indexlibraryctor{basic_string_view}% +\indexlibrarymember{replace}{basic_string}% \begin{itemdecl} -template - constexpr basic_string_view(It begin, End end); +template + constexpr basic_string& replace(const_iterator i1, const_iterator i2, const T& t); \end{itemdecl} \begin{itemdescr} \pnum \constraints \begin{itemize} -\item \tcode{It} satisfies \libconcept{contiguous_iterator}. -\item \tcode{End} satisfies \tcode{\libconcept{sized_sentinel_for}}. -\item \tcode{is_same_v, charT>} is \tcode{true}. -\item \tcode{is_convertible_v} is \tcode{false}. +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} 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}}. -\end{itemize} +\range{begin()}{i1} and \range{i1}{i2} are valid ranges. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +basic_string_view 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(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(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 -\effects -Initializes \tcode{data_} with \tcode{to_address(begin)} and -initializes \tcode{size_} with \tcode{end - begin}. +\expects +\range{begin()}{i1} and \range{i1}{i2} are valid ranges. \pnum -\throws -When and what \tcode{end - begin} throws. +\effects +Equivalent to: \tcode{return replace(i1 - begin(), i2 - i1, n, c);} \end{itemdescr} -\indexlibraryctor{basic_string_view}% +\indexlibrarymember{replace}{basic_string}% \begin{itemdecl} -template - constexpr basic_string_view(R&& r); +template + constexpr basic_string& replace(const_iterator i1, const_iterator i2, + InputIterator j1, InputIterator j2); \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{d} be an lvalue of type \tcode{remove_cvref_t}. - \pnum \constraints -\begin{itemize} -\item -\tcode{remove_cvref_t} 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, charT>} is \tcode{true}, -\item -\tcode{is_convertible_v} is \tcode{false}, -\item -\tcode{d.operator ::std::basic_string_view()} -is not a valid expression, and -\item -if the \grammarterm{qualified-id} \tcode{remove_reference_t::traits_type} -is valid and denotes a type, -\tcode{is_same_v::traits_type, traits>} is \tcode{true}. -\end{itemize} +\tcode{InputIterator} is a type that qualifies as an input +iterator\iref{container.requirements.general}. \pnum \effects -Initializes \tcode{data_} with \tcode{ranges::data(r)} and -\tcode{size_} with \tcode{ranges::size(r)}. - -\pnum -\throws -Any exception thrown by \tcode{ranges::data(r)} and \tcode{ranges::size(r)}. +Equivalent to: \tcode{return replace(i1, i2, basic_string(j1, j2, get_allocator()));} \end{itemdescr} -\rSec3[string.view.iterators]{Iterator support} - -\indexlibrarymember{const_iterator}{basic_string_view}% +\indexlibrarymember{replace_with_range}{basic_string}% \begin{itemdecl} -using const_iterator = @\impdefx{type of \tcode{basic_string_view::const_iterator}}@; +template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); \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. +\effects +Equivalent to: +\begin{codeblock} +return replace(i1, i2, basic_string(from_range, std::forward(rg), get_allocator())); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{begin}{basic_string_view}% -\indexlibrarymember{cbegin}{basic_string_view}% +\indexlibrarymember{replace}{basic_string}% \begin{itemdecl} -constexpr const_iterator begin() const noexcept; -constexpr const_iterator cbegin() const noexcept; +constexpr basic_string& replace(const_iterator i1, const_iterator i2, initializer_list il); \end{itemdecl} \begin{itemdescr} \pnum -\returns -An iterator such that -\begin{itemize} -\item if \tcode{!empty()}, \tcode{addressof(*begin()) == data_}, -\item otherwise, an unspecified value such that \range{begin()}{end()} is a valid range. -\end{itemize} +\effects +Equivalent to: \tcode{return replace(i1, i2, il.begin(), il.size());} \end{itemdescr} -\indexlibrarymember{end}{basic_string_view}% -\indexlibrarymember{cend}{basic_string_view}% +\rSec4[string.copy]{\tcode{basic_string::copy}} + +\indexlibrarymember{copy}{basic_string}% \begin{itemdecl} -constexpr const_iterator end() const noexcept; -constexpr const_iterator cend() const noexcept; +constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{begin() + size()}. +\effects +Equivalent to: +\tcode{return basic_string_view(*this).copy(s, n, pos);} +\begin{note} +This does not terminate \tcode{s} with a null object. +\end{note} \end{itemdescr} -\indexlibrarymember{rbegin}{basic_string_view}% -\indexlibrarymember{crbegin}{basic_string_view}% +\rSec4[string.swap]{\tcode{basic_string::swap}} + +\indexlibrarymember{swap}{basic_string}% \begin{itemdecl} -constexpr const_reverse_iterator rbegin() const noexcept; -constexpr const_reverse_iterator crbegin() const noexcept; +constexpr void swap(basic_string& s) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{const_reverse_iterator(end())}. +\expects +\tcode{allocator_traits::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} -\indexlibrarymember{rend}{basic_string_view}% -\indexlibrarymember{crend}{basic_string_view}% +\rSec3[string.ops]{String operations} + +\rSec4[string.accessors]{Accessors} + +\indexlibrarymember{c_str}{basic_string}% +\indexlibrarymember{data}{basic_string}% \begin{itemdecl} -constexpr const_reverse_iterator rend() const noexcept; -constexpr const_reverse_iterator crend() const noexcept; +constexpr const charT* c_str() const noexcept; +constexpr const charT* data() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{const_reverse_iterator(begin())}. -\end{itemdescr} +A pointer \tcode{p} such that \tcode{p + i == addressof(operator[](i))} for each +\tcode{i} in \crange{0}{size()}. -\rSec3[string.view.capacity]{Capacity} +\pnum +\complexity +Constant time. -\indexlibrarymember{size}{basic_string_view}% -\indexlibrarymember{length}{basic_string_view}% +\pnum +\remarks +The program shall not modify any of the values stored in the character array; otherwise, the behavior is undefined. +\end{itemdescr} + +\indexlibrarymember{data}{basic_string}% \begin{itemdecl} -constexpr size_type size() const noexcept; -constexpr size_type length() const noexcept; +constexpr charT* data() noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{size_}. -\end{itemdescr} +A pointer \tcode{p} such that \tcode{p + i == addressof(operator[](i))} for each +\tcode{i} in \crange{0}{size()}. + +\pnum +\complexity +Constant time. +\pnum +\remarks +The program shall not modify the value stored at \tcode{p + size()} +to any value other than \tcode{charT()}; otherwise, the behavior is undefined. +\end{itemdescr} -\indexlibrarymember{max_size}{basic_string_view}% +\indexlibrarymember{operator basic_string_view}{basic_string}% \begin{itemdecl} -constexpr size_type max_size() const noexcept; +constexpr operator basic_string_view() 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}. +\effects +Equivalent to: +\tcode{return basic_string_view(data(), size());} \end{itemdescr} -\indexlibrarymember{empty}{basic_string_view}% +\indexlibrarymember{get_allocator}{basic_string}% \begin{itemdecl} -[[nodiscard]] constexpr bool empty() const noexcept; +constexpr allocator_type get_allocator() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{size_ == 0}. +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} -\rSec3[string.view.access]{Element access} +\rSec4[string.find]{Searching} -\indexlibrarymember{operator[]}{basic_string_view}% +\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(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(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(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(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} -constexpr const_reference operator[](size_type pos) const; +template + constexpr size_type find(const T& t, size_type pos = 0) const noexcept(@\seebelow@); +template + constexpr size_type rfind(const T& t, size_type pos = npos) const noexcept(@\seebelow@); +template + constexpr size_type find_first_of(const T& t, size_type pos = 0) const noexcept(@\seebelow@); +template + constexpr size_type find_last_of(const T& t, size_type pos = npos) const noexcept(@\seebelow@); +template + constexpr size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept(@\seebelow@); +template + constexpr size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{pos < size()}. - -\pnum -\returns -\tcode{data_[pos]}. +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} \pnum -\throws -Nothing. +\effects +Let \placeholder{G} be the name of the function. +Equivalent to: +\begin{codeblock} +basic_string_view s = *this, sv = t; +return s.@\placeholder{G}@(sv, pos); +\end{codeblock} \pnum -\begin{note} -Unlike \tcode{basic_string::operator[]}, -\tcode{basic_string_view::operator[](size())} has undefined behavior instead of returning \tcode{charT()}. -\end{note} +\remarks +The exception specification is equivalent to +\tcode{is_nothrow_convertible_v>}. \end{itemdescr} -\indexlibrarymember{at}{basic_string_view}% +\rSec4[string.substr]{\tcode{basic_string::substr}} + +\indexlibrarymember{substr}{basic_string}% \begin{itemdecl} -constexpr const_reference at(size_type pos) const; +constexpr basic_string substr(size_type pos = 0, size_type n = npos) const; \end{itemdecl} \begin{itemdescr} +\pnum +\effects +Determines the effective length \tcode{rlen} of the string to copy as the smaller of \tcode{n} and +\tcode{size() - pos}. + \pnum \returns -\tcode{data_[pos]}. +\tcode{basic_string(data()+pos, rlen)}. \pnum \throws -\tcode{out_of_range} if \tcode{pos >= size()}. +\tcode{out_of_range} +if +\tcode{pos > size()}. \end{itemdescr} -\indexlibrarymember{front}{basic_string_view}% +\rSec4[string.compare]{\tcode{basic_string::compare}} + +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr const_reference front() const; +template + constexpr int compare(const T& t) const noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} \pnum -\returns -\tcode{data_[0]}. +\effects +Equivalent to: \tcode{return basic_string_view(*this).compare(t);} \pnum -\throws -Nothing. +\remarks +The exception specification is equivalent to +\tcode{is_nothrow_convertible_v>}. \end{itemdescr} -\indexlibrarymember{back}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr const_reference back() const; +template + constexpr int compare(size_type pos1, size_type n1, const T& t) const; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. - -\pnum -\returns -\tcode{data_[size() - 1]}. +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} \pnum -\throws -Nothing. +\effects +Equivalent to: +\begin{codeblock} +return basic_string_view(*this).substr(pos1, n1).compare(t); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{data}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr const_pointer data() const noexcept; +template + 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 -\returns -\tcode{data_}. +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v>} is +\tcode{true} and +\item +\tcode{is_convertible_v} is +\tcode{false}. +\end{itemize} \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} +\effects +Equivalent to: +\begin{codeblock} +basic_string_view s = *this, sv = t; +return s.substr(pos1, n1).compare(sv.substr(pos2, n2)); +\end{codeblock} \end{itemdescr} -\rSec3[string.view.modifiers]{Modifiers} - -\indexlibrarymember{remove_prefix}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr void remove_prefix(size_type n); +constexpr int compare(const basic_string& str) const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{n <= size()}. - \pnum \effects -Equivalent to: \tcode{data_ += n; size_ -= n;} +Equivalent to: +\tcode{return compare(basic_string_view(str));} \end{itemdescr} -\indexlibrarymember{remove_suffix}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr void remove_suffix(size_type n); +constexpr int compare(size_type pos1, size_type n1, const basic_string& str) const; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{n <= size()}. - \pnum \effects -Equivalent to: \tcode{size_ -= n;} +Equivalent to: +\tcode{return compare(pos1, n1, basic_string_view(str));} \end{itemdescr} -\indexlibrarymember{swap}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr void swap(basic_string_view& s) noexcept; +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 -Exchanges the values of \tcode{*this} and \tcode{s}. +Equivalent to: +\begin{codeblock} +return compare(pos1, n1, basic_string_view(str), pos2, n2); +\end{codeblock} \end{itemdescr} -\rSec3[string.view.ops]{String operations} - -\indexlibrarymember{copy}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; +constexpr int compare(const charT* s) 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}}. +Equivalent to: +\tcode{return compare(basic_string_view(s));} \end{itemdescr} -\indexlibrarymember{substr}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; +constexpr int compare(size_type pos, size_type n1, const charT* s) 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()}. +Equivalent to: \tcode{return compare(pos, n1, basic_string_view(s));} \end{itemdescr} -\indexlibrarymember{compare}{basic_string_view}% +\indexlibrarymember{compare}{basic_string}% \begin{itemdecl} -constexpr int compare(basic_string_view str) const noexcept; +constexpr int compare(size_type pos, size_type n1, const charT* s, size_type n2) const; \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)}. +Equivalent to: \tcode{return compare(pos, n1, basic_string_view(s, n2));} +\end{itemdescr} -\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} +\rSec4[string.starts.with]{\tcode{basic_string::starts_with}} + +\indexlibrarymember{starts_with}{basic_string}% +\begin{itemdecl} +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; +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -\bigoh{\tcode{rlen}}. +\effects +Equivalent to: +\begin{codeblock} +return basic_string_view(data(), size()).starts_with(x); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string_view}% +\rSec4[string.ends.with]{\tcode{basic_string::ends_with}} + +\indexlibrarymember{ends_with}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos1, size_type n1, basic_string_view str) 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; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return substr(pos1, n1).compare(str);} +Equivalent to: +\begin{codeblock} +return basic_string_view(data(), size()).ends_with(x); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string_view}% +\rSec4[string.contains]{\tcode{basic_string::contains}} + +\indexlibrarymember{contains}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos1, size_type n1, basic_string_view str, - size_type pos2, size_type n2) const; +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 substr(pos1, n1).compare(str.substr(pos2, n2));} +Equivalent to: +\begin{codeblock} +return basic_string_view(data(), size()).contains(x); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string_view}% +\rSec2[string.nonmembers]{Non-member functions} + +\indexlibraryglobal{basic_string} + +\rSec3[string.op.plus]{\tcode{operator+}} + +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr int compare(const charT* s) const; +template + constexpr basic_string + operator+(const basic_string& lhs, + const basic_string& rhs); +template + constexpr basic_string + operator+(const basic_string& lhs, const charT* rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return compare(basic_string_view(s));} +Equivalent to: +\begin{codeblock} +basic_string r = lhs; +r.append(rhs); +return r; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos1, size_type n1, const charT* s) const; +template + constexpr basic_string + operator+(basic_string&& lhs, + const basic_string& rhs); +template + constexpr basic_string + operator+(basic_string&& lhs, const charT* rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return substr(pos1, n1).compare(basic_string_view(s));} +Equivalent to: +\begin{codeblock} +lhs.append(rhs); +return std::move(lhs); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{compare}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const; +template + constexpr basic_string + operator+(basic_string&& lhs, + basic_string&& rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return substr(pos1, n1).compare(basic_string_view(s, n2));} +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{starts_with}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr bool starts_with(basic_string_view x) const noexcept; +template + constexpr basic_string + operator+(const basic_string& lhs, + basic_string&& rhs); +template + constexpr basic_string + operator+(const charT* lhs, basic_string&& rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return substr(0, x.size()) == x;} +Equivalent to: +\begin{codeblock} +rhs.insert(0, lhs); +return std::move(rhs); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{starts_with}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr bool starts_with(charT x) const noexcept; +template + constexpr basic_string + operator+(const charT* lhs, const basic_string& rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !empty() \&\& traits::eq(front(), x);} +Equivalent to: +\begin{codeblock} +basic_string r = rhs; +r.insert(0, lhs); +return r; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{starts_with}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr bool starts_with(const charT* x) const; +template + constexpr basic_string + operator+(charT lhs, const basic_string& rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return starts_with(basic_string_view(x));} +Equivalent to: +\begin{codeblock} +basic_string r = rhs; +r.insert(r.begin(), lhs); +return r; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{ends_with}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr bool ends_with(basic_string_view x) const noexcept; +template + constexpr basic_string + operator+(charT lhs, basic_string&& rhs); \end{itemdecl} \begin{itemdescr} @@ -4932,448 +4797,582 @@ \effects Equivalent to: \begin{codeblock} -return size() >= x.size() && compare(size() - x.size(), npos, x) == 0; +rhs.insert(rhs.begin(), lhs); +return std::move(rhs); \end{codeblock} \end{itemdescr} -\indexlibrarymember{ends_with}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr bool ends_with(charT x) const noexcept; +template + constexpr basic_string + operator+(const basic_string& lhs, charT rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !empty() \&\& traits::eq(back(), x);} +Equivalent to: +\begin{codeblock} +basic_string r = lhs; +r.push_back(rhs); +return r; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{ends_with}{basic_string_view}% +\indexlibrarymember{operator+}{basic_string}% \begin{itemdecl} -constexpr bool ends_with(const charT* x) const; +template + constexpr basic_string + operator+(basic_string&& lhs, charT rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return ends_with(basic_string_view(x));} +Equivalent to: +\begin{codeblock} +lhs.push_back(rhs); +return std::move(lhs); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{contains}{basic_string_view}% +\rSec3[string.cmp]{Non-member comparison operator functions} \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} +template + constexpr bool + operator==(const basic_string& lhs, + const basic_string& rhs) noexcept; +template + constexpr bool operator==(const basic_string& lhs, + const charT* rhs); +template + constexpr @\seebelow@ operator<=>(const basic_string& lhs, + @\itcorr@ const basic_string& rhs) noexcept; +template + constexpr @\seebelow@ operator<=>(const basic_string& lhs, + @\itcorr@ const charT* rhs); +\end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return find(x) != npos;} +Let \tcode{\placeholder{op}} be the operator. +Equivalent to: +\begin{codeblock} +return basic_string_view(lhs) @\placeholder{op}@ basic_string_view(rhs); +\end{codeblock} \end{itemdescr} -\rSec3[string.view.find]{Searching} +\rSec3[string.special]{\tcode{swap}} -\pnum -Member functions in this subclause have complexity \bigoh{\tcode{size() * str.size()}} at worst, -although implementations should do better. +\indexlibrarymember{swap}{basic_string}% +\begin{itemdecl} +template + constexpr void + swap(basic_string& lhs, + basic_string& rhs) + noexcept(noexcept(lhs.swap(rhs))); +\end{itemdecl} +\begin{itemdescr} \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);} +\effects +Equivalent to \tcode{lhs.swap(rhs)}. +\end{itemdescr} -\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} +\rSec3[string.io]{Inserters and extractors} -\indexlibrarymember{find}{basic_string_view}% +\indexlibrarymember{operator>>}{basic_string}% \begin{itemdecl} -constexpr size_type find(basic_string_view str, size_type pos = 0) const noexcept; +template + basic_istream& + operator>>(basic_istream& is, basic_string& str); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{xpos} be the lowest position, if possible, such that the following conditions hold: +\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 -\tcode{pos <= xpos} +\textit{n} +characters are stored; \item -\tcode{xpos + str.size() <= size()} +end-of-file occurs on the input sequence; \item -\tcode{traits::eq(at(xpos + I), str.at(I))} for all elements \tcode{I} of the string referenced by \tcode{str}. +\tcode{isspace(c, is.getloc())} +is \tcode{true} for the next available input character +\textit{c}. \end{itemize} \pnum -\effects -Determines \tcode{xpos}. +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, it calls +\tcode{is.setstate(ios_base::failbit)}, +which may throw +\tcode{ios_base::fail\-ure}\iref{iostate.flags}. \pnum \returns -\tcode{xpos} if the function can determine such a value for \tcode{xpos}. -Otherwise, returns \tcode{npos}. +\tcode{is}. \end{itemdescr} -\indexlibrarymember{rfind}{basic_string_view}% +\indexlibrarymember{operator<<}{basic_string}% \begin{itemdecl} -constexpr size_type rfind(basic_string_view str, size_type pos = npos) const noexcept; +template + basic_ostream& + operator<<(basic_ostream& os, + const basic_string& str); \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(at(xpos + I), str.at(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}. +Equivalent to: \tcode{return os << basic_string_view(str);} \end{itemdescr} -\indexlibrarymember{find_first_of}{basic_string_view}% +\indexlibrarymember{getline}{basic_string}% \begin{itemdecl} -constexpr size_type find_first_of(basic_string_view str, size_type pos = 0) const noexcept; +template + basic_istream& + getline(basic_istream& is, + basic_string& str, + charT delim); +template + basic_istream& + getline(basic_istream&& is, + basic_string& str, + charT delim); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{xpos} be the lowest position, if possible, such that the following conditions hold: +\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 -\tcode{pos <= xpos} +end-of-file occurs on the input sequence +(in which case, the +\tcode{getline} +function calls +\tcode{is.setstate(\brk{}ios_base::eofbit)}). \item -\tcode{xpos < size()} +\tcode{traits::eq(c, delim)} +for the next available input character +\textit{c} +(in which case, +\textit{c} +is extracted but not appended)\iref{iostate.flags} \item -\tcode{traits::eq(at(xpos), str.at(I))} for some element \tcode{I} of the string referenced by \tcode{str}. +\tcode{str.max_size()} +characters are stored +(in which case, +the function calls +\tcode{is.setstate(ios_base::fail\-bit))}\iref{iostate.flags} \end{itemize} \pnum -\effects -Determines \tcode{xpos}. +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, it calls +\tcode{is.setstate(ios_base::fail\-bit)} +which may throw +\tcode{ios_base::fail\-ure}\iref{iostate.flags}. \pnum \returns -\tcode{xpos} if the function can determine such a value for \tcode{xpos}. -Otherwise, returns \tcode{npos}. +\tcode{is}. \end{itemdescr} -\indexlibrarymember{find_last_of}{basic_string_view}% +\indexlibrarymember{getline}{basic_string}% \begin{itemdecl} -constexpr size_type find_last_of(basic_string_view str, size_type pos = npos) const noexcept; +template + basic_istream& + getline(basic_istream& is, + basic_string& str); +template + basic_istream& + getline(basic_istream&& is, + basic_string& str); \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(at(xpos), str.at(I))} for some element \tcode{I} of the string referenced by \tcode{str}. -\end{itemize} +\returns +\tcode{getline(is, str, is.widen('\textbackslash n'))}. +\end{itemdescr} -\pnum -\effects -Determines \tcode{xpos}. +\rSec3[string.erasure]{Erasure} +\indexlibrarymember{erase}{basic_string}% +\begin{itemdecl} +template + constexpr typename basic_string::size_type + erase(basic_string& c, const U& value); +\end{itemdecl} + +\begin{itemdescr} \pnum -\returns -\tcode{xpos} if the function can determine such a value for \tcode{xpos}. -Otherwise, returns \tcode{npos}. +\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{find_first_not_of}{basic_string_view}% +\indexlibrarymember{erase_if}{basic_string}% \begin{itemdecl} -constexpr size_type find_first_not_of(basic_string_view str, size_type pos = 0) const noexcept; +template + constexpr typename basic_string::size_type + erase_if(basic_string& c, Predicate pred); \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(at(xpos), str.at(I))} for no element \tcode{I} of the string referenced by \tcode{str}. -\end{itemize} +\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 -Determines \tcode{xpos}. +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 -\tcode{xpos} if the function can determine such a value for \tcode{xpos}. Otherwise, returns \tcode{npos}. +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} -\indexlibrarymember{find_last_not_of}{basic_string_view}% +\indexlibraryglobal{stof}% +\indexlibraryglobal{stod}% +\indexlibraryglobal{stold}% \begin{itemdecl} -constexpr size_type find_last_not_of(basic_string_view str, size_type pos = npos) const noexcept; +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 -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(at(xpos), str.at(I))} for no element \tcode{I} of the string referenced by \tcode{str}. -\end{itemize} - \pnum \effects -Determines \tcode{xpos}. +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 -\tcode{xpos} if the function can determine such a value for \tcode{xpos}. -Otherwise, returns \tcode{npos}. -\end{itemdescr} +The converted result. -\rSec2[string.view.deduct]{Deduction guides} +\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} -template - basic_string_view(It, End) -> basic_string_view>; +string to_string(int val); +string to_string(unsigned val); +string to_string(long val); +string to_string(unsigned long val); +string to_string(long long val); +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 -\constraints -\begin{itemize} -\item \tcode{It} satisfies \libconcept{contiguous_iterator}. -\item \tcode{End} satisfies \tcode{\libconcept{sized_sentinel_for}}. -\end{itemize} +\returns +Each function returns a \tcode{string} object holding the character +representation of the value of its argument that would be generated by calling +\tcode{sprintf(buf, fmt, val)} with a format specifier of +\tcode{"\%d"}, +\tcode{"\%u"}, +\tcode{"\%ld"}, +\tcode{"\%lu"}, +\tcode{"\%lld"}, \tcode{"\%llu"}, +\tcode{"\%f"}, +\tcode{"\%f"}, +or \tcode{"\%Lf"}, respectively, where \tcode{buf} designates an internal +character buffer of sufficient size. \end{itemdescr} +\indexlibraryglobal{stoi}% +\indexlibraryglobal{stol}% +\indexlibraryglobal{stoul}% +\indexlibraryglobal{stoll}% +\indexlibraryglobal{stoull}% \begin{itemdecl} -template - basic_string_view(R&&) -> basic_string_view>; +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 -\constraints -\tcode{R} satisfies \tcode{ranges::\libconcept{contiguous_range}}. -\end{itemdescr} - -\rSec2[string.view.comparison]{Non-member comparison functions} +\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 -Let \tcode{S} be \tcode{basic_string_view}, and \tcode{sv} be an instance of \tcode{S}. -Implementations shall provide sufficient additional overloads marked \keyword{constexpr} and \keyword{noexcept} -so that an object \tcode{t} with an implicit conversion to \tcode{S} can be compared according to \tref{string.view.comparison.overloads}. -\begin{libtab2}{Additional \tcode{basic_string_view} comparison overloads}{string.view.comparison.overloads}{cc}{Expression}{Equivalent to} -\tcode{t == sv} & \tcode{S(t) == sv} \\ -\tcode{sv == t} & \tcode{sv == S(t)} \\ -\tcode{t != sv} & \tcode{S(t) != sv} \\ -\tcode{sv != t} & \tcode{sv != S(t)} \\ -\tcode{t < sv} & \tcode{S(t) < sv} \\ -\tcode{sv < t} & \tcode{sv < S(t)} \\ -\tcode{t > sv} & \tcode{S(t) > sv} \\ -\tcode{sv > t} & \tcode{sv > S(t)} \\ -\tcode{t <= sv} & \tcode{S(t) <= sv} \\ -\tcode{sv <= t} & \tcode{sv <= S(t)} \\ -\tcode{t >= sv} & \tcode{S(t) >= sv} \\ -\tcode{sv >= t} & \tcode{sv >= S(t)} \\ -\tcode{t <=> sv} & \tcode{S(t) <=> sv} \\ -\tcode{sv <=> t} & \tcode{sv <=> S(t)} \\ -\end{libtab2} -\begin{example} -A sample conforming implementation for \tcode{operator==} would be: -\begin{codeblock} -template - constexpr bool operator==(basic_string_view lhs, - basic_string_view rhs) noexcept { - return lhs.compare(rhs) == 0; - } -template - constexpr bool operator==(basic_string_view lhs, - type_identity_t> rhs) noexcept { - return lhs.compare(rhs) == 0; - } -\end{codeblock} -\end{example} - -\indexlibrarymember{operator==}{basic_string_view}% -\begin{itemdecl} -template - constexpr bool operator==(basic_string_view lhs, - basic_string_view rhs) noexcept; -\end{itemdecl} +\returns +The converted result. -\begin{itemdescr} \pnum -\returns -\tcode{lhs.compare(rhs) == 0}. +\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} -\indexlibrarymember{operator<=>}{basic_string_view}% +\indexlibraryglobal{stof}% +\indexlibraryglobal{stod}% +\indexlibraryglobal{stold}% \begin{itemdecl} -template - constexpr @\seebelow@ operator<=>(basic_string_view lhs, - @\itcorr@ basic_string_view rhs) noexcept; +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 -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}. +\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 -\mandates -\tcode{R} denotes a comparison category type\iref{cmp.categories}. +\returns +The converted result. \pnum -\returns -\tcode{static_cast(lhs.compare(rhs) <=> 0)}. +\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} -\rSec2[string.view.io]{Inserters and extractors} - -\indexlibrarymember{operator<<}{basic_string_view}% +\indexlibraryglobal{to_wstring}% \begin{itemdecl} -template - basic_ostream& - operator<<(basic_ostream& os, basic_string_view str); +wstring to_wstring(int val); +wstring to_wstring(unsigned val); +wstring to_wstring(long val); +wstring to_wstring(unsigned long val); +wstring to_wstring(long long val); +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 -\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} +Each function returns a \tcode{wstring} object holding the character +representation of the value of its argument that would be generated by calling +\tcode{swprintf(buf, buffsz, fmt, val)} with a format specifier of +\tcode{L"\%d"}, +\tcode{L"\%u"}, +\tcode{L"\%ld"}, +\tcode{L"\%lu"}, +\tcode{L"\%lld"}, +\tcode{L"\%llu"}, +\tcode{L"\%f"}, +\tcode{L"\%f"}, +or \tcode{L"\%Lf"}, respectively, where \tcode{buf} designates an +internal character buffer of sufficient size \tcode{buffsz}. \end{itemdescr} -\rSec2[string.view.hash]{Hash support} +\rSec2[basic.string.hash]{Hash support} -\indexlibrarymember{hash}{string_view}% -\indexlibrarymember{hash}{u8string_view}% -\indexlibrarymember{hash}{u16string_view}% -\indexlibrarymember{hash}{u32string_view}% -\indexlibrarymember{hash}{wstring_view}% +\indexlibrarymember{hash}{string}% +\indexlibrarymember{hash}{u16string}% +\indexlibrarymember{hash}{u32string}% +\indexlibrarymember{hash}{wstring}% +\indexlibrarymember{hash}{pmr::string}% +\indexlibrarymember{hash}{pmr::u16string}% +\indexlibrarymember{hash}{pmr::u32string}% +\indexlibrarymember{hash}{pmr::wstring}% \begin{itemdecl} -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; -template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; +template<> struct hash; \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} +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) == hash()(SV(s))}. \end{itemdescr} -\rSec2[string.view.literals]{Suffix for \tcode{basic_string_view} literals} +\rSec2[basic.string.literals]{Suffix for \tcode{basic_string} literals} -\indexlibrarymember{operator""""sv}{string_view}% +\indexlibrarymember{operator""""s}{string}% \begin{itemdecl} -constexpr string_view operator""sv(const char* str, size_t len) noexcept; +constexpr string operator""s(const char* str, size_t len); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{string_view\{str, len\}}. +\tcode{string\{str, len\}}. \end{itemdescr} -\indexlibrarymember{operator""""sv}{u8string_view}% +\indexlibrarymember{operator""""s}{u8string}% \begin{itemdecl} -constexpr u8string_view operator""sv(const char8_t* str, size_t len) noexcept; +constexpr u8string operator""s(const char8_t* str, size_t len); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{u8string_view\{str, len\}}. +\tcode{u8string\{str, len\}}. \end{itemdescr} -\indexlibrarymember{operator""""sv}{u16string_view}% +\indexlibrarymember{operator""""s}{u16string}% \begin{itemdecl} -constexpr u16string_view operator""sv(const char16_t* str, size_t len) noexcept; +constexpr u16string operator""s(const char16_t* str, size_t len); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{u16string_view\{str, len\}}. +\tcode{u16string\{str, len\}}. \end{itemdescr} -\indexlibrarymember{operator""""sv}{u32string_view}% +\indexlibrarymember{operator""""s}{u32string}% \begin{itemdecl} -constexpr u32string_view operator""sv(const char32_t* str, size_t len) noexcept; +constexpr u32string operator""s(const char32_t* str, size_t len); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{u32string_view\{str, len\}}. +\tcode{u32string\{str, len\}}. \end{itemdescr} -\indexlibrarymember{operator""""sv}{wstring_view}% +\indexlibrarymember{operator""""s}{wstring}% \begin{itemdecl} -constexpr wstring_view operator""sv(const wchar_t* str, size_t len) noexcept; +constexpr wstring operator""s(const wchar_t* str, size_t len); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{wstring_view\{str, len\}}. +\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} From 724e83e4d0cd82737952711d31505872188269ab Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 23 Feb 2022 23:01:35 +0100 Subject: [PATCH 160/182] [meta] Create new clause and move [intseq], [meta], and [ratio] from [utilities] into the new clause. --- source/lib-intro.tex | 8 +- source/meta.tex | 2630 +++++++++++++++++++++++++++++++++++++++++ source/std.tex | 1 + source/utilities.tex | 2618 ---------------------------------------- tools/check-source.sh | 2 +- 5 files changed, 2639 insertions(+), 2620 deletions(-) create mode 100644 source/meta.tex diff --git a/source/lib-intro.tex b/source/lib-intro.tex index d0973ce552..6405c26b63 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -30,6 +30,7 @@ \ref{concepts} & Concepts library \\ \ref{diagnostics} & Diagnostics library \\ \ref{mem} & Memory management library \\ +\ref{meta} & Metaprogramming library \\ \ref{utilities} & General utilities library \\ \ref{strings} & Strings library \\ \ref{containers} & Containers library \\ @@ -64,6 +65,11 @@ The memory management library\iref{mem} provides components for memory management, including smart pointers and scoped allocators. +\pnum +The metaprogramming library\iref{meta} describes facilities +for use in templates and during constant evaluation, +including type traits, integer sequences, and rational arithmetic. + \pnum The general utilities library\iref{utilities} includes components used by other library elements, such as a predefined storage allocator for dynamic @@ -1337,7 +1343,7 @@ \ref{support.coroutine} & Coroutines support & \tcode{} \\ \rowsep \ref{support.runtime} & Other runtime support & \tcode{} \\ \rowsep \ref{concepts} & Concepts library & \tcode{} \\ \rowsep -\ref{meta} & Type traits & \tcode{} \\ \rowsep +\ref{type.traits} & Type traits & \tcode{} \\ \rowsep \ref{bit} & Bit manipulation & \tcode{} \\ \rowsep \ref{atomics} & Atomics & \tcode{} \\ \end{libsumtab} diff --git a/source/meta.tex b/source/meta.tex new file mode 100644 index 0000000000..bd138d5e90 --- /dev/null +++ b/source/meta.tex @@ -0,0 +1,2630 @@ +%!TEX root = std.tex +\rSec0[meta]{Metaprogramming library} + +\rSec1[meta.general]{General} + +\pnum +This Clause describes metaprogramming facilities. +These facilities are summarized in \tref{meta.summary}. + +\begin{libsumtab}{Metaprogramming library summary}{meta.summary} +\ref{intseq} & Integer sequences & \tcode{} \\ \rowsep +\ref{type.traits} & Type traits & \tcode{} \\ \rowsep +\ref{ratio} & Rational arithmetic & \tcode{} \\ +\end{libsumtab} + +\rSec1[intseq]{Compile-time integer sequences} + +\rSec2[intseq.general]{In general} + +\pnum +The library provides a class template that can represent an integer sequence. +When used as an argument to a function template the template parameter pack defining the +sequence can be deduced and used in a pack expansion. +\begin{note} +The \tcode{index_sequence} alias template is provided for the common case of +an integer sequence of type \tcode{size_t}; see also \ref{tuple.apply}. +\end{note} + +\rSec2[intseq.intseq]{Class template \tcode{integer_sequence}} + +\indexlibraryglobal{integer_sequence}% +\indexlibrarymember{value_type}{integer_sequence}% +\begin{codeblock} +namespace std { + template struct integer_sequence { + using value_type = T; + static constexpr size_t size() noexcept { return sizeof...(I); } + }; +} +\end{codeblock} + +\pnum +\mandates +\tcode{T} is an integer type. + +\rSec2[intseq.make]{Alias template \tcode{make_integer_sequence}} + +\indexlibraryglobal{make_integer_sequence}% +\begin{itemdecl} +template + using make_integer_sequence = integer_sequence; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +$\tcode{N} \geq 0$. + +\pnum +The alias template +\tcode{make_integer_sequence} denotes a specialization of +\tcode{integer_sequence} with \tcode{N} non-type template arguments. +The type \tcode{make_integer_sequence} is an alias for the type +\tcode{integer_sequence}. +\begin{note} +\tcode{make_integer_sequence} is an alias for the type +\tcode{integer_sequence}. +\end{note} +\end{itemdescr} + +\rSec1[type.traits]{Metaprogramming and type traits} + +\rSec2[type.traits.general]{General} + +\pnum +Subclause \ref{meta} describes components used by \Cpp{} programs, particularly in +templates, to support the widest possible range of types, optimise +template code usage, detect type related user errors, and perform +type inference and transformation at compile time. It includes type +classification traits, type property inspection traits, and type +transformations. The type classification traits describe a complete taxonomy +of all possible \Cpp{} types, and state where in that taxonomy a given +type belongs. The type property inspection traits allow important +characteristics of types or of combinations of types to be inspected. The +type transformations allow certain properties of types to be manipulated. + +\pnum +\indextext{signal-safe!type traits}% +All functions specified in \ref{meta} are signal-safe\iref{support.signal}. + +\rSec2[meta.rqmts]{Requirements} + +\pnum +A \defnoldconcept{UnaryTypeTrait} describes a property +of a type. It shall be a class template that takes one template type +argument and, optionally, additional arguments that help define the +property being described. It shall be \oldconcept{DefaultConstructible}, +\oldconcept{CopyConstructible}, +and publicly and unambiguously derived, directly or indirectly, from +its \defn{base characteristic}, which is +a specialization of the template +\tcode{integral_constant}\iref{meta.help}, with +the arguments to the template \tcode{integral_constant} determined by the +requirements for the particular property being described. +The member names of the base characteristic shall not be hidden and shall be +unambiguously available in the \oldconcept{UnaryTypeTrait}. + +\pnum +A \defnoldconcept{BinaryTypeTrait} describes a +relationship between two types. It shall be a class template that +takes two template type arguments and, optionally, additional +arguments that help define the relationship being described. It shall +be \oldconcept{DefaultConstructible}, \oldconcept{CopyConstructible}, +and publicly and unambiguously derived, directly or +indirectly, from +its \term{base characteristic}, which is a specialization +of the template +\tcode{integral_constant}\iref{meta.help}, with +the arguments to the template \tcode{integral_constant} determined by the +requirements for the particular relationship being described. +The member names of the base characteristic shall not be hidden and shall be +unambiguously available in the \oldconcept{BinaryTypeTrait}. + +\pnum +A \defnoldconcept{TransformationTrait} +modifies a property +of a type. It shall be a class template that takes one +template type argument and, optionally, additional arguments that help +define the modification. It shall define a publicly accessible nested type +named \tcode{type}, which shall be a synonym for the modified type. + +\pnum +Unless otherwise specified, +the behavior of a program that adds specializations +for any of the templates specified in \ref{meta} +is undefined. + +\pnum +Unless otherwise specified, an incomplete type may be used +to instantiate a template specified in \ref{meta}. +The behavior of a program is undefined if: +\begin{itemize} +\item + an instantiation of a template specified in \ref{meta} + directly or indirectly depends on + an incompletely-defined object type \tcode{T}, and +\item + that instantiation could yield a different result + were \tcode{T} hypothetically completed. +\end{itemize} + +\rSec2[meta.type.synop]{Header \tcode{} synopsis} + +\indexheader{type_traits}% +% FIXME: Many index entries missing. +\begin{codeblock} +namespace std { + // \ref{meta.help}, helper class + template struct integral_constant; + + template + using bool_constant = integral_constant; + using true_type = bool_constant; + using false_type = bool_constant; + + // \ref{meta.unary.cat}, primary type categories + template struct is_void; + template struct is_null_pointer; + template struct is_integral; + template struct is_floating_point; + template struct is_array; + template struct is_pointer; + template struct is_lvalue_reference; + template struct is_rvalue_reference; + template struct is_member_object_pointer; + template struct is_member_function_pointer; + template struct is_enum; + template struct is_union; + template struct is_class; + template struct is_function; + + // \ref{meta.unary.comp}, composite type categories + template struct is_reference; + template struct is_arithmetic; + template struct is_fundamental; + template struct is_object; + template struct is_scalar; + template struct is_compound; + template struct is_member_pointer; + + // \ref{meta.unary.prop}, type properties + template struct is_const; + template struct is_volatile; + template struct is_trivial; + template struct is_trivially_copyable; + template struct is_standard_layout; + template struct is_empty; + template struct is_polymorphic; + template struct is_abstract; + template struct is_final; + template struct is_aggregate; + + template struct is_signed; + template struct is_unsigned; + template struct is_bounded_array; + template struct is_unbounded_array; + template struct is_scoped_enum; + + template struct is_constructible; + template struct is_default_constructible; + template struct is_copy_constructible; + template struct is_move_constructible; + + template struct is_assignable; + template struct is_copy_assignable; + template struct is_move_assignable; + + template struct is_swappable_with; + template struct is_swappable; + + template struct is_destructible; + + template struct is_trivially_constructible; + template struct is_trivially_default_constructible; + template struct is_trivially_copy_constructible; + template struct is_trivially_move_constructible; + + template struct is_trivially_assignable; + template struct is_trivially_copy_assignable; + template struct is_trivially_move_assignable; + template struct is_trivially_destructible; + + template struct is_nothrow_constructible; + template struct is_nothrow_default_constructible; + template struct is_nothrow_copy_constructible; + template struct is_nothrow_move_constructible; + + template struct is_nothrow_assignable; + template struct is_nothrow_copy_assignable; + template struct is_nothrow_move_assignable; + + template struct is_nothrow_swappable_with; + template struct is_nothrow_swappable; + + template struct is_nothrow_destructible; + + template struct has_virtual_destructor; + + template struct has_unique_object_representations; + + template struct reference_constructs_from_temporary; + template struct reference_converts_from_temporary; + + // \ref{meta.unary.prop.query}, type property queries + template struct alignment_of; + template struct rank; + template struct extent; + + // \ref{meta.rel}, type relations + template struct is_same; + template struct is_base_of; + template struct is_convertible; + template struct is_nothrow_convertible; + template struct is_layout_compatible; + template struct is_pointer_interconvertible_base_of; + + template struct is_invocable; + template struct is_invocable_r; + + template struct is_nothrow_invocable; + template struct is_nothrow_invocable_r; + + // \ref{meta.trans.cv}, const-volatile modifications + template struct remove_const; + template struct remove_volatile; + template struct remove_cv; + template struct add_const; + template struct add_volatile; + template struct add_cv; + + template + using @\libglobal{remove_const_t}@ = typename remove_const::type; + template + using @\libglobal{remove_volatile_t}@ = typename remove_volatile::type; + template + using @\libglobal{remove_cv_t}@ = typename remove_cv::type; + template + using @\libglobal{add_const_t}@ = typename add_const::type; + template + using @\libglobal{add_volatile_t}@ = typename add_volatile::type; + template + using @\libglobal{add_cv_t}@ = typename add_cv::type; + + // \ref{meta.trans.ref}, reference modifications + template struct remove_reference; + template struct add_lvalue_reference; + template struct add_rvalue_reference; + + template + using @\libglobal{remove_reference_t}@ = typename remove_reference::type; + template + using @\libglobal{add_lvalue_reference_t}@ = typename add_lvalue_reference::type; + template + using @\libglobal{add_rvalue_reference_t}@ = typename add_rvalue_reference::type; + + // \ref{meta.trans.sign}, sign modifications + template struct make_signed; + template struct make_unsigned; + + template + using @\libglobal{make_signed_t}@ = typename make_signed::type; + template + using @\libglobal{make_unsigned_t}@ = typename make_unsigned::type; + + // \ref{meta.trans.arr}, array modifications + template struct remove_extent; + template struct remove_all_extents; + + template + using @\libglobal{remove_extent_t}@ = typename remove_extent::type; + template + using @\libglobal{remove_all_extents_t}@ = typename remove_all_extents::type; + + // \ref{meta.trans.ptr}, pointer modifications + template struct remove_pointer; + template struct add_pointer; + + template + using @\libglobal{remove_pointer_t}@ = typename remove_pointer::type; + template + using @\libglobal{add_pointer_t}@ = typename add_pointer::type; + + // \ref{meta.trans.other}, other transformations + template struct type_identity; + template struct remove_cvref; + template struct decay; + template struct enable_if; + template struct conditional; + template struct common_type; + template class TQual, template class UQual> + struct basic_common_reference { }; + template struct common_reference; + template struct underlying_type; + template struct invoke_result; + template struct unwrap_reference; + template struct unwrap_ref_decay; + + template + using @\libglobal{type_identity_t}@ = typename type_identity::type; + template + using @\libglobal{remove_cvref_t}@ = typename remove_cvref::type; + template + using @\libglobal{decay_t}@ = typename decay::type; + template + using @\libglobal{enable_if_t}@ = typename enable_if::type; + template + using @\libglobal{conditional_t}@ = typename conditional::type; + template + using @\libglobal{common_type_t}@ = typename common_type::type; + template + using @\libglobal{common_reference_t}@ = typename common_reference::type; + template + using @\libglobal{underlying_type_t}@ = typename underlying_type::type; + template + using @\libglobal{invoke_result_t}@ = typename invoke_result::type; + template + using unwrap_reference_t = typename unwrap_reference::type; + template + using unwrap_ref_decay_t = typename unwrap_ref_decay::type; + template + using @\libglobal{void_t}@ = void; + + // \ref{meta.logical}, logical operator traits + template struct conjunction; + template struct disjunction; + template struct negation; + + // \ref{meta.unary.cat}, primary type categories + template + inline constexpr bool @\libglobal{is_void_v}@ = is_void::value; + template + inline constexpr bool @\libglobal{is_null_pointer_v}@ = is_null_pointer::value; + template + inline constexpr bool @\libglobal{is_integral_v}@ = is_integral::value; + template + inline constexpr bool @\libglobal{is_floating_point_v}@ = is_floating_point::value; + template + inline constexpr bool @\libglobal{is_array_v}@ = is_array::value; + template + inline constexpr bool @\libglobal{is_pointer_v}@ = is_pointer::value; + template + inline constexpr bool @\libglobal{is_lvalue_reference_v}@ = is_lvalue_reference::value; + template + inline constexpr bool @\libglobal{is_rvalue_reference_v}@ = is_rvalue_reference::value; + template + inline constexpr bool @\libglobal{is_member_object_pointer_v}@ = is_member_object_pointer::value; + template + inline constexpr bool @\libglobal{is_member_function_pointer_v}@ = is_member_function_pointer::value; + template + inline constexpr bool @\libglobal{is_enum_v}@ = is_enum::value; + template + inline constexpr bool @\libglobal{is_union_v}@ = is_union::value; + template + inline constexpr bool @\libglobal{is_class_v}@ = is_class::value; + template + inline constexpr bool @\libglobal{is_function_v}@ = is_function::value; + + // \ref{meta.unary.comp}, composite type categories + template + inline constexpr bool @\libglobal{is_reference_v}@ = is_reference::value; + template + inline constexpr bool @\libglobal{is_arithmetic_v}@ = is_arithmetic::value; + template + inline constexpr bool @\libglobal{is_fundamental_v}@ = is_fundamental::value; + template + inline constexpr bool @\libglobal{is_object_v}@ = is_object::value; + template + inline constexpr bool @\libglobal{is_scalar_v}@ = is_scalar::value; + template + inline constexpr bool @\libglobal{is_compound_v}@ = is_compound::value; + template + inline constexpr bool @\libglobal{is_member_pointer_v}@ = is_member_pointer::value; + + // \ref{meta.unary.prop}, type properties + template + inline constexpr bool @\libglobal{is_const_v}@ = is_const::value; + template + inline constexpr bool @\libglobal{is_volatile_v}@ = is_volatile::value; + template + inline constexpr bool @\libglobal{is_trivial_v}@ = is_trivial::value; + template + inline constexpr bool @\libglobal{is_trivially_copyable_v}@ = is_trivially_copyable::value; + template + inline constexpr bool @\libglobal{is_standard_layout_v}@ = is_standard_layout::value; + template + inline constexpr bool @\libglobal{is_empty_v}@ = is_empty::value; + template + inline constexpr bool @\libglobal{is_polymorphic_v}@ = is_polymorphic::value; + template + inline constexpr bool @\libglobal{is_abstract_v}@ = is_abstract::value; + template + inline constexpr bool @\libglobal{is_final_v}@ = is_final::value; + template + inline constexpr bool @\libglobal{is_aggregate_v}@ = is_aggregate::value; + template + inline constexpr bool @\libglobal{is_signed_v}@ = is_signed::value; + template + inline constexpr bool @\libglobal{is_unsigned_v}@ = is_unsigned::value; + template + inline constexpr bool @\libglobal{is_bounded_array_v}@ = is_bounded_array::value; + template + inline constexpr bool @\libglobal{is_unbounded_array_v}@ = is_unbounded_array::value; + template + inline constexpr bool @\libglobal{is_scoped_enum_v}@ = is_scoped_enum::value; + template + inline constexpr bool @\libglobal{is_constructible_v}@ = is_constructible::value; + template + inline constexpr bool @\libglobal{is_default_constructible_v}@ = is_default_constructible::value; + template + inline constexpr bool @\libglobal{is_copy_constructible_v}@ = is_copy_constructible::value; + template + inline constexpr bool @\libglobal{is_move_constructible_v}@ = is_move_constructible::value; + template + inline constexpr bool @\libglobal{is_assignable_v}@ = is_assignable::value; + template + inline constexpr bool @\libglobal{is_copy_assignable_v}@ = is_copy_assignable::value; + template + inline constexpr bool @\libglobal{is_move_assignable_v}@ = is_move_assignable::value; + template + inline constexpr bool @\libglobal{is_swappable_with_v}@ = is_swappable_with::value; + template + inline constexpr bool @\libglobal{is_swappable_v}@ = is_swappable::value; + template + inline constexpr bool @\libglobal{is_destructible_v}@ = is_destructible::value; + template + inline constexpr bool is_trivially_constructible_v + = is_trivially_constructible::value; + template + inline constexpr bool is_trivially_default_constructible_v + = is_trivially_default_constructible::value; + template + inline constexpr bool is_trivially_copy_constructible_v + = is_trivially_copy_constructible::value; + template + inline constexpr bool is_trivially_move_constructible_v + = is_trivially_move_constructible::value; + template + inline constexpr bool @\libglobal{is_trivially_assignable_v}@ = is_trivially_assignable::value; + template + inline constexpr bool is_trivially_copy_assignable_v + = is_trivially_copy_assignable::value; + template + inline constexpr bool is_trivially_move_assignable_v + = is_trivially_move_assignable::value; + template + inline constexpr bool @\libglobal{is_trivially_destructible_v}@ = is_trivially_destructible::value; + template + inline constexpr bool is_nothrow_constructible_v + = is_nothrow_constructible::value; + template + inline constexpr bool is_nothrow_default_constructible_v + = is_nothrow_default_constructible::value; + template + inline constexpr bool is_nothrow_copy_constructible_v + = is_nothrow_copy_constructible::value; + template + inline constexpr bool is_nothrow_move_constructible_v + = is_nothrow_move_constructible::value; + template + inline constexpr bool @\libglobal{is_nothrow_assignable_v}@ = is_nothrow_assignable::value; + template + inline constexpr bool @\libglobal{is_nothrow_copy_assignable_v}@ = is_nothrow_copy_assignable::value; + template + inline constexpr bool @\libglobal{is_nothrow_move_assignable_v}@ = is_nothrow_move_assignable::value; + template + inline constexpr bool @\libglobal{is_nothrow_swappable_with_v}@ = is_nothrow_swappable_with::value; + template + inline constexpr bool @\libglobal{is_nothrow_swappable_v}@ = is_nothrow_swappable::value; + template + inline constexpr bool @\libglobal{is_nothrow_destructible_v}@ = is_nothrow_destructible::value; + template + inline constexpr bool @\libglobal{has_virtual_destructor_v}@ = has_virtual_destructor::value; + template + inline constexpr bool has_unique_object_representations_v + = has_unique_object_representations::value; + template + inline constexpr bool @\libglobal{reference_constructs_from_temporary_v}@ + = reference_constructs_from_temporary::value; + template + inline constexpr bool @\libglobal{reference_converts_from_temporary_v}@ + = reference_converts_from_temporary::value; + + // \ref{meta.unary.prop.query}, type property queries + template + inline constexpr size_t @\libglobal{alignment_of_v}@ = alignment_of::value; + template + inline constexpr size_t @\libglobal{rank_v}@ = rank::value; + template + inline constexpr size_t @\libglobal{extent_v}@ = extent::value; + + // \ref{meta.rel}, type relations + template + inline constexpr bool @\libglobal{is_same_v}@ = is_same::value; + template + inline constexpr bool @\libglobal{is_base_of_v}@ = is_base_of::value; + template + inline constexpr bool @\libglobal{is_convertible_v}@ = is_convertible::value; + template + inline constexpr bool @\libglobal{is_nothrow_convertible_v}@ = is_nothrow_convertible::value; + template + inline constexpr bool @\libglobal{is_layout_compatible_v}@ = is_layout_compatible::value; + template + inline constexpr bool is_pointer_interconvertible_base_of_v + = is_pointer_interconvertible_base_of::value; + template + inline constexpr bool @\libglobal{is_invocable_v}@ = is_invocable::value; + template + inline constexpr bool @\libglobal{is_invocable_r_v}@ = is_invocable_r::value; + template + inline constexpr bool @\libglobal{is_nothrow_invocable_v}@ = is_nothrow_invocable::value; + template + inline constexpr bool is_nothrow_invocable_r_v + = is_nothrow_invocable_r::value; + + // \ref{meta.logical}, logical operator traits + template + inline constexpr bool @\libglobal{conjunction_v}@ = conjunction::value; + template + inline constexpr bool @\libglobal{disjunction_v}@ = disjunction::value; + template + inline constexpr bool @\libglobal{negation_v}@ = negation::value; + + // \ref{meta.member}, member relationships + template + constexpr bool is_pointer_interconvertible_with_class(M S::*m) noexcept; + template + constexpr bool is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept; + + // \ref{meta.const.eval}, constant evaluation context + constexpr bool is_constant_evaluated() noexcept; +} +\end{codeblock} + +\rSec2[meta.help]{Helper classes} + +\indexlibrarymember{value_type}{integral_constant}% +\begin{codeblock} +namespace std { + template struct integral_constant { + static constexpr T value = v; + + using value_type = T; + using type = integral_constant; + + constexpr operator value_type() const noexcept { return value; } + constexpr value_type operator()() const noexcept { return value; } + }; +} +\end{codeblock} + +\indexlibraryglobal{integral_constant}% +\indexlibraryglobal{bool_constant}% +\indexlibraryglobal{true_type}% +\indexlibraryglobal{false_type}% +\pnum +The class template \tcode{integral_constant}, +alias template \tcode{bool_constant}, and +its associated \grammarterm{typedef-name}{s} +\tcode{true_type} and \tcode{false_type} +are used as base classes to define +the interface for various type traits. + +\rSec2[meta.unary]{Unary type traits} + +\rSec3[meta.unary.general]{General} + +\pnum +Subclause \ref{meta.unary} contains templates that may be used to query the +properties of a type at compile time. + +\pnum +Each of these templates shall be a +\oldconcept{UnaryTypeTrait}\iref{meta.rqmts} +with a base characteristic of +\tcode{true_type} if the corresponding condition is \tcode{true}, otherwise +\tcode{false_type}. + +\rSec3[meta.unary.cat]{Primary type categories} + +\pnum +The primary type categories correspond to the descriptions given in +subclause~\ref{basic.types} of the \Cpp{} standard. + +\pnum +For any given type \tcode{T}, the result of applying one of these templates to +\tcode{T} and to \cv{}~\tcode{T} shall yield the same result. + +\pnum +\begin{note} +For any given type \tcode{T}, exactly one of the primary type categories +has a \tcode{value} member that evaluates to \tcode{true}. +\end{note} + +\begin{libreqtab3e}{Primary type category predicates}{meta.unary.cat} +\\ \topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\\capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep +\endhead +\indexlibraryglobal{is_void}% +\tcode{template}\br + \tcode{struct is_void;} & +\tcode{T} is \keyword{void} & \\ \rowsep +\indexlibraryglobal{is_null_pointer}% +\tcode{template}\br + \tcode{struct is_null_pointer;} & +\tcode{T} is \tcode{nullptr_t}\iref{basic.fundamental} & \\ \rowsep +\indexlibraryglobal{is_integral}% +\tcode{template}\br + \tcode{struct is_integral;} & +\tcode{T} is an integral type\iref{basic.fundamental} & \\ \rowsep +\indexlibraryglobal{is_floating_point}% +\tcode{template}\br + \tcode{struct is_floating_point;} & +\tcode{T} is a floating-point type\iref{basic.fundamental} & \\ \rowsep +\indexlibraryglobal{is_array}% +\tcode{template}\br + \tcode{struct is_array;} & +\tcode{T} is an array type\iref{basic.compound} of known or unknown extent & +Class template \tcode{array}\iref{array} +is not an array type. \\ \rowsep +\indexlibraryglobal{is_pointer}% +\tcode{template}\br + \tcode{struct is_pointer;} & +\tcode{T} is a pointer type\iref{basic.compound} & +Includes pointers to functions +but not pointers to non-static members. \\ \rowsep +\indexlibraryglobal{is_lvalue_reference}% +\tcode{template}\br + \tcode{struct is_lvalue_reference;} & + \tcode{T} is an lvalue reference type\iref{dcl.ref} & \\ \rowsep +\indexlibraryglobal{is_rvalue_reference}% +\tcode{template}\br + \tcode{struct is_rvalue_reference;} & + \tcode{T} is an rvalue reference type\iref{dcl.ref} & \\ \rowsep +\indexlibraryglobal{is_member_object_pointer}% +\tcode{template}\br + \tcode{struct is_member_object_pointer;}& + \tcode{T} is a pointer to data member & \\ \rowsep +\indexlibraryglobal{is_member_function_pointer}% +\tcode{template}\br + \tcode{struct is_member_function_pointer;}& +\tcode{T} is a pointer to member function & \\ \rowsep +\indexlibraryglobal{is_enum}% +\tcode{template}\br + \tcode{struct is_enum;} & +\tcode{T} is an enumeration type\iref{basic.compound} & \\ \rowsep +\indexlibraryglobal{is_union}% +\tcode{template}\br + \tcode{struct is_union;} & +\tcode{T} is a union type\iref{basic.compound} & \\ \rowsep +\indexlibraryglobal{is_class}% +\tcode{template}\br + \tcode{struct is_class;} & +\tcode{T} is a non-union class type\iref{basic.compound} & \\ \rowsep +\indexlibraryglobal{is_function}% +\tcode{template}\br + \tcode{struct is_function;} & +\tcode{T} is a function type\iref{basic.compound} & \\ +\end{libreqtab3e} + +\rSec3[meta.unary.comp]{Composite type traits} + +\pnum +These templates provide convenient compositions of the primary type +categories, corresponding to the descriptions given in subclause~\ref{basic.types}. + +\pnum +For any given type \tcode{T}, the result of applying one of these templates to +\tcode{T} and to \cv{}~\tcode{T} shall yield the same result. + +\begin{libreqtab3b}{Composite type category predicates}{meta.unary.comp} +\\ \topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep +\endhead +\indexlibraryglobal{is_reference}% +\tcode{template}\br + \tcode{struct is_reference;} & + \tcode{T} is an lvalue reference or an rvalue reference & \\ \rowsep +\indexlibraryglobal{is_arithmetic}% +\tcode{template}\br + \tcode{struct is_arithmetic;} & + \tcode{T} is an arithmetic type\iref{basic.fundamental} & \\ \rowsep +\indexlibraryglobal{is_fundamental}% +\tcode{template}\br + \tcode{struct is_fundamental;} & + \tcode{T} is a fundamental type\iref{basic.fundamental} & \\ \rowsep +\indexlibraryglobal{is_object}% +\tcode{template}\br + \tcode{struct is_object;} & + \tcode{T} is an object type\iref{term.object.type} & \\ \rowsep +\indexlibraryglobal{is_scalar}% +\tcode{template}\br + \tcode{struct is_scalar;} & + \tcode{T} is a scalar type\iref{term.scalar.type} & \\ \rowsep +\indexlibraryglobal{is_compound}% +\tcode{template}\br + \tcode{struct is_compound;} & + \tcode{T} is a compound type\iref{basic.compound} & \\ \rowsep +\indexlibraryglobal{is_member_pointer}% +\tcode{template}\br + \tcode{struct is_member_pointer;} & + \tcode{T} is a pointer-to-member type\iref{basic.compound} & \\ +\end{libreqtab3b} + +\rSec3[meta.unary.prop]{Type properties} + +\pnum +These templates provide access to some of the more important +properties of types. + +\pnum +It is unspecified whether the library defines any full or partial +specializations of any of these templates. + +\pnum +For all of the class templates \tcode{X} declared in this subclause, +instantiating that template with a template-argument that is a class +template specialization may result in the implicit instantiation of +the template argument if and only if the semantics of \tcode{X} require that +the argument is a complete type. + +\pnum +For the purpose of defining the templates in this subclause, +a function call expression \tcode{declval()} for any type \tcode{T} +is considered to be a trivial\iref{term.trivial.type,special} function call +that is not an odr-use\iref{term.odr.use} of \tcode{declval} +in the context of the corresponding definition +notwithstanding the restrictions of~\ref{declval}. + +\pnum +For the purpose of defining the templates in this subclause, +let \tcode{\placeholdernc{VAL}} for some type \tcode{T} be +an expression defined as follows: +\begin{itemize} +\item +If \tcode{T} is a reference or function type, +\tcode{\placeholdernc{VAL}} is an expression +with the same type and value category as \tcode{declval()}. +\item +Otherwise, \tcode{\placeholdernc{VAL}} is a prvalue +that initially has type \tcode{T}. +\begin{note} +If \tcode{T} is cv-qualified, +the cv-qualification is subject to adjustment\iref{expr.type}. +\end{note} +\end{itemize} + +\begin{libreqtab3b}{Type property predicates}{meta.unary.prop} +\\ \topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Preconditions} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Preconditions} \\ \capsep +\endhead + +\indexlibraryglobal{is_const}% +\tcode{template}\br + \tcode{struct is_const;} & + \tcode{T} is const-qualified\iref{basic.type.qualifier} & \\ \rowsep + +\indexlibraryglobal{is_volatile}% +\tcode{template}\br + \tcode{struct is_volatile;} & + \tcode{T} is volatile-qualified\iref{basic.type.qualifier} & \\ \rowsep + + +\indexlibraryglobal{is_trivial}% +\tcode{template}\br + \tcode{struct is_trivial;} & + \tcode{T} is a trivial type\iref{term.trivial.type} & + \tcode{remove_all_extents_t} shall be a complete + type or \cv{}~\keyword{void}. \\ \rowsep + +\indexlibraryglobal{is_trivially_copyable}% +\tcode{template}\br + \tcode{struct is_trivially_copyable;} & + \tcode{T} is a trivially copyable type\iref{term.trivially.copyable.type} & + \tcode{remove_all_extents_t} shall be a complete type or + \cv{}~\keyword{void}. \\ \rowsep + +\indexlibraryglobal{is_standard_layout}% +\tcode{template}\br + \tcode{struct is_standard_layout;} & + \tcode{T} is a standard-layout type\iref{term.standard.layout.type} & + \tcode{remove_all_extents_t} shall be a complete + type or \cv{}~\keyword{void}. \\ \rowsep + +\indexlibrary{\idxcode{is_empty}!class}% +\tcode{template}\br + \tcode{struct is_empty;} & + \tcode{T} is a class type, but not a union type, with no non-static data + members other than subobjects of zero size, no virtual member functions, + no virtual base classes, and no base class \tcode{B} for + which \tcode{is_empty_v} is \tcode{false}. & + If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep + +\indexlibraryglobal{is_polymorphic}% +\tcode{template}\br + \tcode{struct is_polymorphic;} & + \tcode{T} is a polymorphic class\iref{class.virtual} & + If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep + +\indexlibraryglobal{is_abstract}% +\tcode{template}\br + \tcode{struct is_abstract;} & + \tcode{T} is an abstract class\iref{class.abstract} & + If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep + +\indexlibraryglobal{is_final}% +\tcode{template}\br + \tcode{struct is_final;} & + \tcode{T} is a class type marked with the \grammarterm{class-virt-specifier} + \tcode{final}\iref{class.pre}. +\begin{tailnote} +A union is a class type that + can be marked with \tcode{final}. +\end{tailnote} +& + If \tcode{T} is a class type, \tcode{T} shall be a complete type. \\ \rowsep + +\indexlibraryglobal{is_aggregate}% +\tcode{template}\br + \tcode{struct is_aggregate;} & + \tcode{T} is an aggregate type\iref{dcl.init.aggr} & + \tcode{remove_all_extents_t} shall be a complete type or \cv~\keyword{void}. \\ \rowsep + +\indexlibrary{\idxcode{is_signed}!class}% +\tcode{template}\br + \tcode{struct is_signed;} & + If \tcode{is_arithmetic_v} is \tcode{true}, the same result as + \tcode{T(-1) < T(0)}; + otherwise, \tcode{false} & \\ \rowsep + +\indexlibraryglobal{is_unsigned}% +\tcode{template}\br + \tcode{struct is_unsigned;} & + If \tcode{is_arithmetic_v} is \tcode{true}, the same result as + \tcode{T(0) < T(-1)}; + otherwise, \tcode{false} & \\ \rowsep + +\indexlibraryglobal{is_bounded_array}% +\tcode{template}\br + \tcode{struct is_bounded_array;} & + \tcode{T} is an array type of known bound\iref{dcl.array} + & \\ \rowsep + +\indexlibraryglobal{is_unbounded_array}% +\tcode{template}\br + \tcode{struct is_unbounded_array;} & + \tcode{T} is an array type of unknown bound\iref{dcl.array} + & \\ \rowsep + +\indexlibraryglobal{is_scoped_enum}% +\tcode{template}\br + \tcode{struct is_scoped_enum;} & + \tcode{T} is a scoped enumeration\iref{dcl.enum} + & \\ \rowsep + +\indexlibraryglobal{is_constructible}% +\tcode{template}\br + \tcode{struct is_constructible;} & + For a function type \tcode{T} or + for a \cv{}~\keyword{void} type \tcode{T}, + \tcode{is_constructible_v} is \tcode{false}, + otherwise \seebelow & + \tcode{T} and all types in the template parameter pack \tcode{Args} + shall be complete types, \cv{}~\keyword{void}, + or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_default_constructible}% +\tcode{template}\br + \tcode{struct is_default_constructible;} & + \tcode{is_constructible_v} is \tcode{true}. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, + or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_copy_constructible}% +\tcode{template}\br + \tcode{struct is_copy_constructible;} & + For a referenceable type \tcode{T}\iref{defns.referenceable}, the same result as + \tcode{is_constructible_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, + or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_move_constructible}% +\tcode{template}\br + \tcode{struct is_move_constructible;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_constructible_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, + or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_assignable}% +\tcode{template}\br + \tcode{struct is_assignable;} & + The expression \tcode{declval() =} \tcode{declval()} is well-formed + when treated as an unevaluated + operand\iref{term.unevaluated.operand}. Access checking is performed as if in a context + unrelated to \tcode{T} and \tcode{U}. Only the validity of the immediate context + of the assignment expression is considered. +\begin{tailnote} +The compilation of the + expression can result in side effects such as the instantiation of class template + specializations and function template specializations, the generation of + implicitly-defined functions, and so on. Such side effects are not in the ``immediate + context'' and can result in the program being ill-formed. +\end{tailnote} +& + \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, + or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_copy_assignable}% +\tcode{template}\br + \tcode{struct is_copy_assignable;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_assignable_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, + or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_move_assignable}% +\tcode{template}\br + \tcode{struct is_move_assignable;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_assignable_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, + or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_swappable_with}% +\tcode{template}\br + \tcode{struct is_swappable_with;} & + The expressions \tcode{swap(declval(), declval())} and + \tcode{swap(declval(), declval())} are each well-formed + when treated as an unevaluated operand\iref{term.unevaluated.operand} + in an overload-resolution context + for swappable values\iref{swappable.requirements}. + Access checking is performed as if in a context + unrelated to \tcode{T} and \tcode{U}. + Only the validity of the immediate context + of the \tcode{swap} expressions is considered. + \begin{tailnote} + The compilation of the expressions can result in side effects + such as the instantiation of class template specializations and + function template specializations, + the generation of implicitly-defined functions, and so on. + Such side effects are not in the ``immediate context'' and + can result in the program being ill-formed. + \end{tailnote} +& + \tcode{T} and \tcode{U} shall be complete types, + \cv{}~\keyword{void}, or + arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_swappable}% +\tcode{template}\br + \tcode{struct is_swappable;} & + For a referenceable type \tcode{T}, + the same result as \tcode{is_swappable_with_v}, + otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or + an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_destructible}% +\tcode{template}\br + \tcode{struct is_destructible;} & + Either \tcode{T} is a reference type, + or \tcode{T} is a complete object type + for which the expression + \tcode{declval().\~U()} + is well-formed + when treated as an unevaluated operand\iref{term.unevaluated.operand}, + where \tcode{U} is + \tcode{remove_all_extents_t}. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, + or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_constructible}% +\tcode{template}\br + \keyword{struct}\br + \tcode{is_trivially_constructible;} & + \tcode{is_constructible_v} is \tcode{true} and the variable + definition for \tcode{is_constructible}, as defined below, is known to call + no operation that is not trivial\iref{term.trivial.type,special}. & + \tcode{T} and all types in the template parameter pack \tcode{Args} shall be complete types, + \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_default_constructible}% +\tcode{template}\br + \tcode{struct is_trivially_default_constructible;} & + \tcode{is_trivially_constructible_v} is \tcode{true}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_copy_constructible}% +\tcode{template}\br + \tcode{struct is_trivially_copy_constructible;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_trivially_constructible_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_move_constructible}% +\tcode{template}\br + \tcode{struct is_trivially_move_constructible;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_trivially_constructible_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_assignable}% +\tcode{template}\br + \tcode{struct is_trivially_assignable;} & + \tcode{is_assignable_v} is \tcode{true} and the assignment, as defined by + \tcode{is_assignable}, is known to call no operation that is not + trivial\iref{term.trivial.type,special}. & + \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, + or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_copy_assignable}% +\tcode{template}\br + \tcode{struct is_trivially_copy_assignable;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_trivially_assignable_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_move_assignable}% +\tcode{template}\br + \tcode{struct is_trivially_move_assignable;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_trivially_assignable_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_trivially_destructible}% +\tcode{template}\br + \tcode{struct is_trivially_destructible;} & + \tcode{is_destructible_v} is \tcode{true} and + \tcode{remove_all_extents_t} is either a non-class type or + a class type with a trivial destructor. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_constructible}% +\tcode{template}\br + \tcode{struct is_nothrow_constructible;} & + \tcode{is_constructible_v} is \tcode{true} + and the + variable definition for \tcode{is_constructible}, as defined below, is known not to + throw any exceptions\iref{expr.unary.noexcept}. + & + \tcode{T} and all types in the template parameter pack \tcode{Args} + shall be complete types, \cv{}~\keyword{void}, + or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_default_constructible}% +\tcode{template}\br + \tcode{struct is_nothrow_default_constructible;} & + \tcode{is_nothrow_constructible_v} is \tcode{true}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_copy_constructible}% +\tcode{template}\br + \tcode{struct is_nothrow_copy_constructible;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_nothrow_constructible_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_move_constructible}% +\tcode{template}\br + \tcode{struct is_nothrow_move_constructible;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_nothrow_constructible_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_assignable}% +\tcode{template}\br + \tcode{struct is_nothrow_assignable;} & + \tcode{is_assignable_v} is \tcode{true} and the assignment is known not to + throw any exceptions\iref{expr.unary.noexcept}. & + \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, + or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_copy_assignable}% +\tcode{template}\br + \tcode{struct is_nothrow_copy_assignable;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_nothrow_assignable_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_move_assignable}% +\tcode{template}\br + \tcode{struct is_nothrow_move_assignable;} & + For a referenceable type \tcode{T}, the same result as + \tcode{is_nothrow_assignable_v}, otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_swappable_with}% +\tcode{template}\br + \tcode{struct is_nothrow_swappable_with;} & + \tcode{is_swappable_with_v} is \tcode{true} and + each \tcode{swap} expression of the definition of + \tcode{is_swappable_with} is known not to throw + any exceptions\iref{expr.unary.noexcept}. & + \tcode{T} and \tcode{U} shall be complete types, + \cv{}~\keyword{void}, or + arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_swappable}% +\tcode{template}\br + \tcode{struct is_nothrow_swappable;} & + For a referenceable type \tcode{T}, + the same result as \tcode{is_nothrow_swappable_with_v}, + otherwise \tcode{false}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or + an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_destructible}% +\tcode{template}\br + \tcode{struct is_nothrow_destructible;} & + \tcode{is_destructible_v} is \tcode{true} and the indicated destructor is known + not to throw any exceptions\iref{expr.unary.noexcept}. & + \tcode{T} shall be a complete type, + \cv{}~\keyword{void}, or an array of unknown + bound. \\ \rowsep + +\indexlibraryglobal{has_virtual_destructor}% +\tcode{template}\br + \tcode{struct has_virtual_destructor;} & + \tcode{T} has a virtual destructor\iref{class.dtor} & + If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep + +\indexlibraryglobal{has_unique_object_representations}% +\tcode{template}\br + \tcode{struct has_unique_object_representations;} & + For an array type \tcode{T}, the same result as + \tcode{has_unique_object_representations_v>}, + otherwise \seebelow. & + \tcode{T} shall be a complete type, \cv{}~\keyword{void}, or + an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{reference_constructs_from_temporary}% +\tcode{template}\br + \tcode{struct reference_constructs_from_temporary;} & + \tcode{conjunction_v, is_constructible>} + is \tcode{true}, and + the initialization \tcode{T t(\exposidnc{VAL});} binds \tcode{t} to + a temporary object whose lifetime is extended\iref{class.temporary}. & + \tcode{T} and \tcode{U} shall be + complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{reference_converts_from_temporary}% +\tcode{template}\br + \tcode{struct reference_converts_from_temporary;} & + \tcode{conjunction_v, is_convertible>} is \tcode{true}, + and the initialization \tcode{T t = \exposidnc{VAL};} binds \tcode{t} to + a temporary object whose lifetime is extended\iref{class.temporary}. & + \tcode{T} and \tcode{U} shall be + complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep + +\end{libreqtab3b} + +\pnum +\begin{example} +\begin{codeblock} +is_const_v // \tcode{true} +is_const_v // \tcode{false} +is_const_v // \tcode{false} +is_const_v // \tcode{false} +is_const_v // \tcode{true} +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblock} +remove_const_t // \tcode{volatile int} +remove_const_t // \tcode{const int*} +remove_const_t // \tcode{const int\&} +remove_const_t // \tcode{int[3]} +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblock} +// Given: +struct P final { }; +union U1 { }; +union U2 final { }; + +// the following assertions hold: +static_assert(!is_final_v); +static_assert(is_final_v

); +static_assert(!is_final_v); +static_assert(is_final_v); +\end{codeblock} +\end{example} + +\indexlibraryglobal{is_constructible}% +\pnum +The predicate condition for a template specialization +\tcode{is_constructible} shall be satisfied if and only if the +following variable definition would be well-formed for some invented variable \tcode{t}: + +\begin{codeblock} +T t(declval()...); +\end{codeblock} + +\begin{note} +These tokens are never interpreted as a function declaration. +\end{note} +Access checking is performed as if in a context unrelated to \tcode{T} +and any of the \tcode{Args}. Only the validity of the immediate context of the +variable initialization is considered. +\begin{note} +The evaluation of the +initialization can result in side effects such as the instantiation of class +template specializations and function template specializations, the generation +of implicitly-defined functions, and so on. Such side effects are not in the +``immediate context'' and can result in the program being ill-formed. +\end{note} + +\indexlibraryglobal{has_unique_object_representations}% +\pnum +The predicate condition for a template specialization +\tcode{has_unique_object_representations} +shall be satisfied if and only if: +\begin{itemize} +\item \tcode{T} is trivially copyable, and +\item any two objects of type \tcode{T} with the same value +have the same object representation, where +two objects of array or non-union class type are considered to have the same value +if their respective sequences of direct subobjects have the same values, and +two objects of union type are considered to have the same value +if they have the same active member and the corresponding members have the same value. +\end{itemize} +The set of scalar types for which this condition holds is +\impldef{which scalar types have unique object representations}. +\begin{note} +If a type has padding bits, the condition does not hold; +otherwise, the condition holds true for integral types. +\end{note} + +\rSec2[meta.unary.prop.query]{Type property queries} + +\pnum +This subclause contains templates that may be used to query +properties of types at compile time. + +\begin{libreqtab2a}{Type property queries}{meta.unary.prop.query} +\\ \topline +\lhdr{Template} & \rhdr{Value} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Value} \\ \capsep +\endhead + +\indexlibraryglobal{alignment_of}% +\tcode{template\br + struct alignment_of;} & + \tcode{alignof(T)}.\br + \mandates + \tcode{alignof(T)} is a valid expression\iref{expr.alignof} \\ \rowsep + +\indexlibraryglobal{rank}% +\tcode{template\br + struct rank;} & + If \tcode{T} names an array type, an integer value representing + the number of dimensions of \tcode{T}; otherwise, 0. \\ \rowsep + +\indexlibraryglobal{extent}% +\tcode{template\br + struct extent;} & + If \tcode{T} is not an array type, or if it has rank less + than or equal to \tcode{I}, or if \tcode{I} is 0 and \tcode{T} + has type ``array of unknown bound of \tcode{U}'', then + 0; otherwise, the bound\iref{dcl.array} of the $\tcode{I}^\text{th}$ dimension of +\tcode{T}, where indexing of \tcode{I} is zero-based \\ +\end{libreqtab2a} + +\pnum +Each of these templates shall be a \oldconcept{UnaryTypeTrait}\iref{meta.rqmts} with a +base characteristic of \tcode{integral_constant}. + +\pnum +\begin{example} +\begin{codeblock} +// the following assertions hold: +assert(rank_v == 0); +assert(rank_v == 1); +assert(rank_v == 2); +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblock} +// the following assertions hold: +assert(extent_v == 0); +assert(extent_v == 2); +assert(extent_v == 2); +assert(extent_v == 0); +assert((extent_v) == 0); +assert((extent_v) == 0); +assert((extent_v) == 4); +assert((extent_v) == 4); +\end{codeblock} +\end{example} + +\rSec2[meta.rel]{Relationships between types} + +\pnum +This subclause contains templates that may be used to query +relationships between types at compile time. + +\pnum +Each of these templates shall be a +\oldconcept{BinaryTypeTrait}\iref{meta.rqmts} +with a base characteristic of +\tcode{true_type} if the corresponding condition is true, otherwise +\tcode{false_type}. + +\begin{libreqtab3f}{Type relationship predicates}{meta.rel} +\\ \topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep +\endhead +\tcode{template}\br + \tcode{struct is_same;} & + \tcode{T} and \tcode{U} name the same type with the same cv-qualifications & \\ \rowsep + +\indexlibraryglobal{is_base_of}% +\tcode{template}\br + \tcode{struct is_base_of;} & + \tcode{Base} is a base class of \tcode{Derived}\iref{class.derived} + without regard to cv-qualifiers + or \tcode{Base} and \tcode{Derived} are not unions and + name the same class type + without regard to cv-qualifiers & + If \tcode{Base} and + \tcode{Derived} are non-union class types and are +not possibly cv-qualified versions of the same type, + \tcode{Derived} shall be a complete + type. + \begin{tailnote} +Base classes that are private, protected, or ambiguous + are, nonetheless, base classes. +\end{tailnote} +\\ \rowsep + +\indexlibraryglobal{is_convertible}% +\tcode{template}\br + \tcode{struct is_convertible;} & + \seebelow & + \tcode{From} and \tcode{To} shall be complete types, + \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_convertible}% +\tcode{template}\br + \tcode{struct is_nothrow_convertible;} & + \tcode{is_convertible_v} is \tcode{true} and + the conversion, as defined by \tcode{is_convertible}, + is known not to throw any exceptions\iref{expr.unary.noexcept} & + \tcode{From} and \tcode{To} shall be complete types, + \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_layout_compatible}% +\tcode{template}\br + \tcode{struct is_layout_compatible;} & + \tcode{T} and \tcode{U} are layout-compatible\iref{term.layout.compatible.type} & + \tcode{T} and \tcode{U} shall be complete types, + \cv{}~\keyword{void}, + or arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_pointer_interconvertible_base_of}% +\tcode{template}\br + \tcode{struct is_pointer_interconvertible_base_of;} & + \tcode{Derived} is unambiguously derived from \tcode{Base} + without regard to cv-qualifiers, + and each object of type \tcode{Derived} + is pointer-interconvertible\iref{basic.compound} with + its \tcode{Base} subobject, + or \tcode{Base} and \tcode{Derived} are not unions + and name the same class type + without regard to cv-qualifiers. & + If \tcode{Base} and \tcode{Derived} are non-union class types + and are not (possibly cv-qualified versions of) the same type, + \tcode{Derived} shall be a complete type. \\ \rowsep + +\indexlibraryglobal{is_invocable}% +\tcode{template}\br + \tcode{struct is_invocable;} & + The expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} + is well-formed when treated as an unevaluated operand\iref{term.unevaluated.operand} & + \tcode{Fn} and all types in the template parameter pack \tcode{ArgTypes} + shall be complete types, \cv{}~\keyword{void}, or + arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_invocable_r}% +\tcode{template}\br + \tcode{struct is_invocable_r;} & + The expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} + is well-formed when treated as an unevaluated operand & + \tcode{Fn}, \tcode{R}, and all types in the template parameter pack \tcode{ArgTypes} + shall be complete types, \cv{}~\keyword{void}, or + arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_invocable}% +\tcode{template}\br + \tcode{struct is_nothrow_invocable;} & + \tcode{is_invocable_v<}\br\tcode{Fn, ArgTypes...>} is \tcode{true} and + the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} + is known not to throw any exceptions\iref{expr.unary.noexcept} & + \tcode{Fn} and all types in the template parameter pack \tcode{ArgTypes} + shall be complete types, \cv{}~\keyword{void}, or + arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_invocable_r}% +\tcode{template}\br + \tcode{struct is_nothrow_invocable_r;} & + \tcode{is_invocable_r_v<}\br\tcode{R, Fn, ArgTypes...>} is \tcode{true} and + the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} + is known not to throw any exceptions\iref{expr.unary.noexcept} & + \tcode{Fn}, \tcode{R}, and all types in the template parameter pack \tcode{ArgTypes} + shall be complete types, \cv{}~\keyword{void}, or + arrays of unknown bound. \\ +\end{libreqtab3f} + +\pnum +For the purpose of defining the templates in this subclause, +a function call expression \tcode{declval()} for any type \tcode{T} +is considered to be a trivial\iref{term.trivial.type,special} function call +that is not an odr-use\iref{term.odr.use} of \tcode{declval} +in the context of the corresponding definition +notwithstanding the restrictions of~\ref{declval}. + +\pnum +\begin{example} +\begin{codeblock} +struct B {}; +struct B1 : B {}; +struct B2 : B {}; +struct D : private B1, private B2 {}; + +is_base_of_v // \tcode{true} +is_base_of_v // \tcode{true} +is_base_of_v // \tcode{true} +is_base_of_v // \tcode{true} +is_base_of_v // \tcode{false} +is_base_of_v // \tcode{false} +is_base_of_v // \tcode{false} +is_base_of_v // \tcode{false} +\end{codeblock} +\end{example} + +\indexlibraryglobal{is_convertible}% +\pnum +The predicate condition for a template specialization \tcode{is_convertible} +shall be satisfied if and only if the return expression in the following code would be +well-formed, including any implicit conversions to the return type of the function: + +\begin{codeblock} +To test() { + return declval(); +} +\end{codeblock} + +\begin{note} +This requirement gives well-defined results for reference types, +array types, function types, and \cv{}~\keyword{void}. +\end{note} +Access checking is performed +in a context unrelated to \tcode{To} and \tcode{From}. Only the validity of +the immediate context of the \grammarterm{expression} of the \tcode{return} statement\iref{stmt.return} +(including initialization of the returned object or reference) is considered. +\begin{note} +The +initialization can result in side effects such as the +instantiation of class template specializations and function template +specializations, the generation of implicitly-defined functions, and so on. Such +side effects are not in the ``immediate context'' and can result in the program +being ill-formed. +\end{note} + +\rSec2[meta.trans]{Transformations between types} + +\rSec3[meta.trans.general]{General} +\pnum +Subclause \ref{meta.trans} contains templates that may be used to transform one +type to another following some predefined rule. + +\pnum +Each of the templates in \ref{meta.trans} shall be a +\oldconcept{TransformationTrait}\iref{meta.rqmts}. + +\rSec3[meta.trans.cv]{Const-volatile modifications} + +\begin{libreqtab2a}{Const-volatile modifications}{meta.trans.cv} +\\ \topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endhead + +\indexlibraryglobal{remove_const}% +\tcode{template\br + struct remove_const;} & + The member typedef \tcode{type} names + the same type as \tcode{T} + except that any top-level const-qualifier has been removed. + \begin{tailexample} +\tcode{remove_const_t} evaluates + to \tcode{volatile int}, whereas \tcode{remove_const_t} evaluates to + \tcode{const int*}. +\end{tailexample} +\\ \rowsep + +\indexlibraryglobal{remove_volatile}% +\tcode{template\br + struct remove_volatile;} & + The member typedef \tcode{type} names + the same type as \tcode{T} + except that any top-level volatile-qualifier has been removed. + \begin{tailexample} +\tcode{remove_volatile_t} + evaluates to \tcode{const int}, + whereas \tcode{remove_volatile_t} evaluates to \tcode{volatile int*}. + \end{tailexample} +\\ \rowsep + +\indexlibraryglobal{remove_cv}% +\tcode{template\br + struct remove_cv;} & + The member typedef \tcode{type} shall be the same as \tcode{T} + except that any top-level cv-qualifier has been removed. + \begin{tailexample} +\tcode{remove_cv_t} + evaluates to \tcode{int}, whereas \tcode{remove_cv_t} + evaluates to \tcode{const volatile int*}. +\end{tailexample} +\\ \rowsep + +\indexlibraryglobal{add_const}% +\tcode{template\br + struct add_const;} & + If \tcode{T} is a reference, function, or top-level const-qualified + type, then \tcode{type} names + the same type as \tcode{T}, otherwise + \tcode{T const}. \\ \rowsep + +\indexlibraryglobal{add_volatile}% +\tcode{template\br + struct add_volatile;} & + If \tcode{T} is a reference, function, or top-level volatile-qualified + type, then \tcode{type} names + the same type as \tcode{T}, otherwise + \tcode{T volatile}. \\ \rowsep + +\indexlibraryglobal{add_cv}% +\tcode{template\br + struct add_cv;} & + The member typedef \tcode{type} names + the same type as + \tcode{add_const_t>}. \\ +\end{libreqtab2a} + +\rSec3[meta.trans.ref]{Reference modifications} + +\begin{libreqtab2a}{Reference modifications}{meta.trans.ref} +\\ \topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endhead + +\indexlibraryglobal{remove_reference}% +\tcode{template\br + struct remove_reference;} & + If \tcode{T} has type ``reference to \tcode{T1}'' then the + member typedef \tcode{type} names \tcode{T1}; + otherwise, \tcode{type} names \tcode{T}.\\ \rowsep + +\indexlibraryglobal{add_lvalue_reference}% +\tcode{template\br + struct add_lvalue_reference;} & + If \tcode{T} names a referenceable type\iref{defns.referenceable} then + the member typedef \tcode{type} names \tcode{T\&}; + otherwise, \tcode{type} names \tcode{T}. + \begin{tailnote} + This rule reflects the semantics of reference collapsing\iref{dcl.ref}. + \end{tailnote} +\\ \rowsep + +\indexlibraryglobal{add_rvalue_reference}% +\tcode{template}\br + \tcode{struct add_rvalue_reference;} & + If \tcode{T} names a referenceable type then + the member typedef \tcode{type} names \tcode{T\&\&}; + otherwise, \tcode{type} names \tcode{T}. + \begin{tailnote} +This rule reflects the semantics of reference collapsing\iref{dcl.ref}. + For example, when a type \tcode{T} names a type \tcode{T1\&}, the type + \tcode{add_rvalue_reference_t} is not an rvalue reference. + \end{tailnote} +\\ +\end{libreqtab2a} + +\rSec3[meta.trans.sign]{Sign modifications} +\begin{libreqtab2a}{Sign modifications}{meta.trans.sign} +\\ \topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endhead + +\indexlibraryglobal{make_signed}% +\tcode{template}\br + \tcode{struct make_signed;} & + If \tcode{T} names a (possibly cv-qualified) signed integer + type\iref{basic.fundamental} then the member typedef + \tcode{type} names the type \tcode{T}; otherwise, + if \tcode{T} names a (possibly cv-qualified) unsigned integer + type then \tcode{type} names the corresponding + signed integer type, with the same cv-qualifiers as \tcode{T}; + otherwise, \tcode{type} names the signed integer type with smallest + rank\iref{conv.rank} for which + \tcode{sizeof(T) == sizeof(type)}, with the same + cv-qualifiers as \tcode{T}.\br + \mandates \tcode{T} is an integral or enumeration type + other than \cv~\tcode{bool}.\\ \rowsep + +\indexlibraryglobal{make_unsigned}% +\tcode{template}\br + \tcode{struct make_unsigned;} & + If \tcode{T} names a (possibly cv-qualified) unsigned integer + type\iref{basic.fundamental} then the member typedef + \tcode{type} names the type \tcode{T}; otherwise, + if \tcode{T} names a (possibly cv-qualified) signed integer + type then \tcode{type} names the corresponding + unsigned integer type, with the same cv-qualifiers as \tcode{T}; + otherwise, \tcode{type} names the unsigned integer type with smallest + rank\iref{conv.rank} for which + \tcode{sizeof(T) == sizeof(type)}, with the same + cv-qualifiers as \tcode{T}.\br + \mandates \tcode{T} is an integral or enumeration type + other than \cv~\tcode{bool}.\\ +\end{libreqtab2a} + +\rSec3[meta.trans.arr]{Array modifications} +\begin{libreqtab2a}{Array modifications}{meta.trans.arr} +\\ \topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endhead + +\indexlibraryglobal{remove_extent}% +\tcode{template\br + struct remove_extent;} & + If \tcode{T} names a type ``array of \tcode{U}'', + the member typedef \tcode{type} shall + be \tcode{U}, otherwise \tcode{T}. + \begin{tailnote} +For multidimensional arrays, only the first array dimension is + removed. For a type ``array of \tcode{const U}'', the resulting type is + \tcode{const U}. +\end{tailnote} +\\ \rowsep + +\indexlibraryglobal{remove_all_extents}% +\tcode{template\br + struct remove_all_extents;} & + If \tcode{T} is ``multi-dimensional array of \tcode{U}'', the resulting member + typedef \tcode{type} is \tcode{U}, otherwise \tcode{T}. \\ +\end{libreqtab2a} + +\pnum +\begin{example} +\begin{codeblock} +// the following assertions hold: +assert((is_same_v, int>)); +assert((is_same_v, int>)); +assert((is_same_v, int[3]>)); +assert((is_same_v, int[3]>)); +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblock} +// the following assertions hold: +assert((is_same_v, int>)); +assert((is_same_v, int>)); +assert((is_same_v, int>)); +assert((is_same_v, int>)); +\end{codeblock} +\end{example} + +\rSec3[meta.trans.ptr]{Pointer modifications} +\begin{libreqtab2a}{Pointer modifications}{meta.trans.ptr} +\\ \topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endhead + +\indexlibraryglobal{remove_pointer}% +\tcode{template\br + struct remove_pointer;} & + If \tcode{T} has type ``(possibly cv-qualified) pointer + to \tcode{T1}'' then the member typedef \tcode{type} + names \tcode{T1}; otherwise, it names \tcode{T}.\\ \rowsep + +\indexlibraryglobal{add_pointer}% +\tcode{template\br + struct add_pointer;} & + If \tcode{T} names a referenceable type\iref{defns.referenceable} or a + \cv{}~\keyword{void} type then + the member typedef \tcode{type} names the same type as + \tcode{remove_reference_t*}; + otherwise, \tcode{type} names \tcode{T}. \\ +\end{libreqtab2a} + +\rSec3[meta.trans.other]{Other transformations} + +\begin{libreqtab2a}{Other transformations}{meta.trans.other} +\\ \topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Template} & \rhdr{Comments} \\ \capsep +\endhead + +\indexlibraryglobal{type_identity}% +\tcode{template\br + struct type_identity;} + & + The member typedef \tcode{type} names the type \tcode{T}. \\ \rowsep + +\indexlibraryglobal{remove_cvref}% +\tcode{template\br struct remove_cvref;} + & + The member typedef \tcode{type} names the same type as + \tcode{remove_cv_t>}. + \\ \rowsep + +\indexlibraryglobal{decay}% +\tcode{template\br struct decay;} + & + Let \tcode{U} be \tcode{remove_reference_t}. If \tcode{is_array_v} is + \tcode{true}, the member typedef \tcode{type} equals + \tcode{remove_extent_t*}. If \tcode{is_function_v} is \tcode{true}, + the member typedef \tcode{type} equals \tcode{add_pointer_t}. Otherwise + the member typedef \tcode{type} equals \tcode{remove_cv_t}. +\begin{tailnote} +This behavior is similar to the lvalue-to-rvalue\iref{conv.lval}, +array-to-pointer\iref{conv.array}, and function-to-pointer\iref{conv.func} +conversions applied when an lvalue is used as an rvalue, but also +strips cv-qualifiers from class types in order to more closely model by-value +argument passing. +\end{tailnote} + \\ \rowsep + +\indexlibraryglobal{enable_if}% +\tcode{template} \tcode{struct enable_if;} + & + If \tcode{B} is \tcode{true}, the member typedef \tcode{type} + shall equal \tcode{T}; otherwise, there shall be no member + \tcode{type}. \\ \rowsep + +\tcode{template}\br + \tcode{struct conditional;} + & + If \tcode{B} is \tcode{true}, the member typedef \tcode{type} shall equal \tcode{T}. + If \tcode{B} is \tcode{false}, the member typedef \tcode{type} shall equal \tcode{F}. \\ \rowsep + + \tcode{template} \tcode{struct common_type;} + & + Unless this trait is specialized (as specified in Note B, below), + the member \tcode{type} is defined or omitted as specified in Note A, below. + If it is omitted, there shall be no member \tcode{type}. + Each type in the template parameter pack \tcode{T} shall be + complete, \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep + +\indexlibraryglobal{basic_common_reference}% +\tcode{template class,} + \hspace*{2ex}\tcode{template class>} + \keyword{struct} + \hspace*{2ex}\tcode{basic_common_reference;} + & + Unless this trait is specialized (as specified in Note D, below), + there shall be no member \tcode{type}. \\ \rowsep + +\indexlibraryglobal{common_reference}% +\tcode{template} \tcode{struct common_reference;} + & + The member \grammarterm{typedef-name} \tcode{type} is defined or omitted + as specified in Note C, below. Each type in the parameter pack \tcode{T} shall + be complete or \cv{} \keyword{void}. \\ \rowsep + +\indexlibraryglobal{underlying_type}% +\tcode{template}\br + \tcode{struct underlying_type;} + & + If \tcode{T} is an enumeration type, the member typedef \tcode{type} names + the underlying type of \tcode{T}\iref{dcl.enum}; + otherwise, there is no member \tcode{type}.\br + \mandates \tcode{T} is not an incomplete enumeration type. \\ \rowsep + +\tcode{template}\br + \tcode{struct invoke_result;} + & + If the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} + is well-formed when treated as an unevaluated operand\iref{term.unevaluated.operand}, + the member typedef \tcode{type} names the type + \tcode{decltype(\placeholdernc{INVOKE}(declval(), declval()...))}; + otherwise, there shall be no member \tcode{type}. Access checking is + performed as if in a context unrelated to \tcode{Fn} and + \tcode{ArgTypes}. Only the validity of the immediate context of the + expression is considered. + \begin{note} + The compilation of the expression can result in side effects such as + the instantiation of class template specializations and function + template specializations, the generation of implicitly-defined + functions, and so on. Such side effects are not in the ``immediate + context'' and can result in the program being ill-formed. + \end{note} + \expects \tcode{Fn} and all types in the template parameter pack \tcode{ArgTypes} + are complete types, \cv{}~\keyword{void}, or arrays of + unknown bound.\\ \rowsep + +\indexlibraryglobal{unwrap_reference}% +\tcode{template} \tcode{struct unwrap_reference;} + & + If \tcode{T} is + a specialization \tcode{reference_wrapper} for some type \tcode{X}, + the member typedef \tcode{type} of \tcode{unwrap_reference} is \tcode{X\&}, + otherwise it is \tcode{T}. \\ \rowsep + +\indexlibraryglobal{unwrap_ref_decay}% +\tcode{template} \tcode{unwrap_ref_decay;} + & + The member typedef \tcode{type} of \tcode{unwrap_ref_decay} + denotes the type \tcode{unwrap_reference_t>}.\\ +\end{libreqtab2a} + +\pnum +In addition to being available via inclusion +of the \tcode{} header, the templates +\tcode{unwrap_reference}, +\tcode{unwrap_ref_decay}, +\tcode{unwrap_reference_t}, and +\tcode{unwrap_ref_decay_t} +are available +when the header \tcode{}\iref{functional.syn} is included. + +\indexlibraryglobal{common_type}% +\pnum +Let: +\begin{itemize} +\item \tcode{\placeholdernc{CREF}(A)} be + \tcode{add_lvalue_reference_t{}>}, +\item \tcode{\placeholdernc{XREF}(A)} denote a unary alias template \tcode{T} + such that \tcode{T} denotes the same type as \tcode{U} with the addition + of \tcode{A}'s cv and reference qualifiers, for a non-reference cv-unqualified + type \tcode{U}, +\item \tcode{\placeholdernc{COPYCV}(FROM, TO)} be an alias for type \tcode{TO} + with the addition of \tcode{FROM}'s top-level cv-qualifiers, + \begin{example} + \tcode{\placeholdernc{COPYCV}(const int, volatile short)} is an alias for + \tcode{const volatile short}. + \end{example} +\item \tcode{\placeholdernc{COND-RES}(X, Y)} be + \tcode{decltype(false ?\ declval()() :\ declval()())}. +\end{itemize} +Given types \tcode{A} and \tcode{B}, +let \tcode{X} be \tcode{remove_reference_t}, +let \tcode{Y} be \tcode{remove_reference_t}, and +let \tcode{\placeholdernc{COMMON-\brk{}REF}(A, B)} be: +\begin{itemize} +\item If \tcode{A} and \tcode{B} are both lvalue reference types, + \tcode{\placeholdernc{COMMON-REF}(A, B)} is + \tcode{\placeholdernc{COND-RES}(\placeholdernc{COPYCV}(X, Y) \&, + \placeholdernc{COPYCV}(\brk{}Y, X) \&)} if that type exists + and is a reference type. +\item Otherwise, let \tcode{C} be + \tcode{remove_reference_t<\placeholdernc{COMMON-REF}(X\&, Y\&)>\&\&}. + If \tcode{A} and \tcode{B} are both rvalue reference types, + \tcode{C} is well-formed, and + \tcode{is_convertible_v \&\& is_convertible_v} is \tcode{true}, + then \tcode{\placeholdernc{COMMON-REF}(A, B)} is \tcode{C}. +\item Otherwise, let \tcode{D} be + \tcode{\placeholdernc{COMMON-REF}(const X\&, Y\&)}. If \tcode{A} is an rvalue + reference and \tcode{B} is an lvalue reference and \tcode{D} is + well-formed and \tcode{is_convertible_v} is + \tcode{true}, then \tcode{\placeholdernc{COMMON-REF}(A, B)} is \tcode{D}. +\item Otherwise, if \tcode{A} is an lvalue reference and \tcode{B} + is an rvalue reference, then \tcode{\placeholdernc{COMMON-REF}(A, B)} is + \tcode{\placeholdernc{COMMON-REF}(B, A)}. +\item Otherwise, \tcode{\placeholdernc{COMMON-REF}(A, B)} is ill-formed. +\end{itemize} + +If any of the types computed above is ill-formed, then +\tcode{\placeholdernc{COMMON-REF}(A, B)} is ill-formed. + +\pnum +Note A: +For the \tcode{common_type} trait applied to a template parameter pack \tcode{T} of types, +the member \tcode{type} shall be either defined or not present as follows: + +\begin{itemize} +\item If \tcode{sizeof...(T)} is zero, there shall be no member \tcode{type}. + +\item If \tcode{sizeof...(T)} is one, let \tcode{T0} denote the sole type +constituting the pack \tcode{T}. +The member \grammarterm{typedef-name} \tcode{type} shall denote the same +type, if any, as \tcode{common_type_t}; +otherwise there shall be no member \tcode{type}. + +\item If \tcode{sizeof...(T)} is two, +let the first and second types constituting \tcode{T} be denoted +by \tcode{T1} and \tcode{T2}, respectively, and +let \tcode{D1} and \tcode{D2} denote +the same types as \tcode{decay_t} and \tcode{decay_t}, respectively. + \begin{itemize} + \item If \tcode{is_same_v} is \tcode{false} or + \tcode{is_same_v} is \tcode{false}, + let \tcode{C} denote the same type, if any, + as \tcode{common_type_t}. + \item + \begin{note} + None of the following will apply if there is a specialization + \tcode{common_type}. + \end{note} + \item Otherwise, if +\begin{codeblock} +decay_t() : declval())> +\end{codeblock} + denotes a valid type, let \tcode{C} denote that type. + \item Otherwise, if + \tcode{\placeholdernc{COND-RES}(\placeholdernc{CREF}(D1), + \placeholdernc{CREF}(D2))} + denotes a type, let \tcode{C} denote the type + \tcode{decay_t<\placeholdernc{COND-RES}(\placeholdernc{CREF}(D1), + \placeholdernc{CREF}(D2))>}. + \end{itemize} +In either case, the member \grammarterm{typedef-name} \tcode{type} shall denote +the same type, if any, as \tcode{C}. +Otherwise, there shall be no member \tcode{type}. + +\item If \tcode{sizeof...(T)} is greater than two, +let \tcode{T1}, \tcode{T2}, and \tcode{R}, respectively, +denote the first, second, and (pack of) remaining types constituting \tcode{T}. +Let \tcode{C} denote the same type, if any, as \tcode{common_type_t}. +If there is such a type \tcode{C}, the member \grammarterm{typedef-name} \tcode{type} +shall denote the same type, if any, as \tcode{common_type_t}. +Otherwise, there shall be no member \tcode{type}. +\end{itemize} + +\pnum +Note B: Notwithstanding the provisions of \ref{meta.type.synop}, and +pursuant to \ref{namespace.std}, +a program may specialize \tcode{common_type} +for types \tcode{T1} and \tcode{T2} such that +\tcode{is_same_v>} and +\tcode{is_same_v>} are each \tcode{true}. +\begin{note} +Such specializations are needed when only explicit conversions +are desired between the template arguments. +\end{note} +Such a specialization need not have a member named \tcode{type}, +but if it does, +the \grammarterm{qualified-id} \tcode{common_type::type} shall denote +a cv-unqualified non-reference type +to which each of the types \tcode{T1} and \tcode{T2} is explicitly convertible. +Moreover, \tcode{common_type_t} shall denote +the same type, if any, as does \tcode{common_type_t}. +No diagnostic is required for a violation of this Note's rules. + +\pnum +Note C: For the \tcode{common_reference} trait applied to a parameter pack +\tcode{T} of types, the member \tcode{type} shall be either defined or not +present as follows: +\begin{itemize} +\item If \tcode{sizeof...(T)} is zero, there shall be no member \tcode{type}. + +\item Otherwise, if \tcode{sizeof...(T)} is one, let \tcode{T0} denote the sole + type in the pack \tcode{T}. The member typedef \tcode{type} shall denote the + same type as \tcode{T0}. + +\item Otherwise, if \tcode{sizeof...(T)} is two, let \tcode{T1} and \tcode{T2} + denote the two types in the pack \tcode{T}. Then + \begin{itemize} + \item If \tcode{T1} and \tcode{T2} are reference types and + \tcode{\placeholdernc{COMMON-REF}(T1, T2)} is well-formed, then the member + typedef \tcode{type} denotes that type. + + \item Otherwise, if + \tcode{basic_common_reference, remove_cvref_t, + \brk{}\placeholdernc{XREF}(\brk{}T1), \placeholdernc{XREF}(T2)>::type} + is well-formed, then the member typedef \tcode{type} denotes that type. + + \item Otherwise, if \tcode{\placeholdernc{COND-RES}(T1, T2)} is well-formed, + then the member typedef \tcode{type} denotes that type. + + \item Otherwise, if \tcode{common_type_t} is well-formed, then the + member typedef \tcode{type} denotes that type. + + \item Otherwise, there shall be no member \tcode{type}. + \end{itemize} + +\item Otherwise, if \tcode{sizeof...(T)} is greater than two, let \tcode{T1}, + \tcode{T2}, and \tcode{Rest}, respectively, denote the first, second, and + (pack of) remaining types comprising \tcode{T}. Let \tcode{C} be the type + \tcode{common_reference_t}. Then: + \begin{itemize} + \item If there is such a type \tcode{C}, the member typedef \tcode{type} shall + denote the same type, if any, as \tcode{common_reference_t}. + + \item Otherwise, there shall be no member \tcode{type}. + \end{itemize} +\end{itemize} + +\pnum +Note D: Notwithstanding the provisions of \ref{meta.type.synop}, and +pursuant to \ref{namespace.std}, a program may partially specialize +\tcode{basic_common_reference} +for types \tcode{T} and \tcode{U} such that +\tcode{is_same_v>} and +\tcode{is_same_v>} are each \tcode{true}. +\begin{note} +Such specializations +can be used to influence the result of \tcode{common_reference}, and +are needed when only explicit conversions are desired +between the template arguments. +\end{note} +Such a specialization need not have a member named \tcode{type}, but if it does, +the \grammarterm{qualified-id} +\tcode{basic_common_reference::type} +shall denote a type +to which each of the types \tcode{TQual} and +\tcode{UQual} is convertible. +Moreover, \tcode{basic_common_reference::type} shall denote +the same type, if any, as does +\tcode{basic_common_reference::type}. +No diagnostic is required for a violation of these rules. + +\pnum +\begin{example} +Given these definitions: +\begin{codeblock} +using PF1 = bool (&)(); +using PF2 = short (*)(long); + +struct S { + operator PF2() const; + double operator()(char, int&); + void fn(long) const; + char data; +}; + +using PMF = void (S::*)(long) const; +using PMD = char S::*; +\end{codeblock} +the following assertions will hold: +\begin{codeblock} +static_assert(is_same_v, short>); +static_assert(is_same_v, double>); +static_assert(is_same_v, bool>); +static_assert(is_same_v, int>, void>); +static_assert(is_same_v, char&&>); +static_assert(is_same_v, const char&>); +\end{codeblock} +\end{example} + +\rSec2[meta.logical]{Logical operator traits} + +\pnum +This subclause describes type traits for applying logical operators +to other type traits. + +\indexlibraryglobal{conjunction}% +\begin{itemdecl} +template struct conjunction : @\seebelow@ { }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The class template \tcode{conjunction} +forms the logical conjunction of its template type arguments. + +\pnum +For a specialization \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>}, +if there is a template type argument $\tcode{B}_{i}$ +for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{false}, +then instantiating \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>::value} +does not require the instantiation of \tcode{$\tcode{B}_{j}$::value} for $j > i$. +\begin{note} +This is analogous to the short-circuiting behavior of +the built-in operator \tcode{\&\&}. +\end{note} + +\pnum +Every template type argument +for which \tcode{$\tcode{B}_{i}$::value} is instantiated +shall be usable as a base class and +shall have a member \tcode{value} which +is convertible to \tcode{bool}, +is not hidden, and +is unambiguously available in the type. + +\pnum +The specialization \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>} +has a public and unambiguous base that is either +\begin{itemize} +\item +the first type $\tcode{B}_{i}$ in the list \tcode{true_type, $\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$} +for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{false}, or +\item +if there is no such $\tcode{B}_{i}$, the last type in the list. +\end{itemize} +\begin{note} +This means a specialization of \tcode{conjunction} +does not necessarily inherit from +either \tcode{true_type} or \tcode{false_type}. +\end{note} + +\pnum +The member names of the base class, other than \tcode{conjunction} and +\tcode{operator=}, shall not be hidden and shall be unambiguously available +in \tcode{conjunction}. +\end{itemdescr} + +\indexlibraryglobal{disjunction}% +\begin{itemdecl} +template struct disjunction : @\seebelow@ { }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The class template \tcode{disjunction} +forms the logical disjunction of its template type arguments. + +\pnum +For a specialization \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>}, +if there is a template type argument $\tcode{B}_{i}$ +for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{true}, +then instantiating \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>::value} +does not require the instantiation of \tcode{$\tcode{B}_{j}$::value} for $j > i$. +\begin{note} +This is analogous to the short-circuiting behavior of +the built-in operator \tcode{||}. +\end{note} + +\pnum +Every template type argument +for which \tcode{$\tcode{B}_{i}$::value} is instantiated +shall be usable as a base class and +shall have a member \tcode{value} which +is convertible to \tcode{bool}, +is not hidden, and +is unambiguously available in the type. + +\pnum +The specialization \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>} +has a public and unambiguous base that is either +\begin{itemize} +\item the first type $\tcode{B}_{i}$ in the list \tcode{false_type, $\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$} +for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{true}, or +\item if there is no such $\tcode{B}_{i}$, the last type in the list. +\end{itemize} +\begin{note} +This means a specialization of \tcode{disjunction} +does not necessarily inherit from +either \tcode{true_type} or \tcode{false_type}. +\end{note} + +\pnum +The member names of the base class, +other than \tcode{disjunction} and \tcode{operator=}, +shall not be hidden and shall be unambiguously available in \tcode{disjunction}. +\end{itemdescr} + +\indexlibraryglobal{negation}% +\begin{itemdecl} +template struct negation : @\seebelow@ { }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The class template \tcode{negation} +forms the logical negation of its template type argument. +The type \tcode{negation} +is a \oldconcept{UnaryTypeTrait} with a base characteristic of \tcode{bool_constant}. +\end{itemdescr} + +\rSec2[meta.member]{Member relationships} + +\indexlibraryglobal{is_pointer_interconvertible_with_class} +\begin{itemdecl} +template + constexpr bool is_pointer_interconvertible_with_class(M S::*m) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{S} is a complete type. + +\pnum +\returns +\tcode{true} if and only if + \tcode{S} is a standard-layout type, + \tcode{M} is an object type, + \tcode{m} is not null, + and each object \tcode{s} of type \tcode{S} + is pointer-interconvertible\iref{basic.compound} + with its subobject \tcode{s.*m}. +\end{itemdescr} + +\indexlibraryglobal{is_corresponding_member} +\begin{itemdecl} +template + constexpr bool is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{S1} and \tcode{S2} are complete types. + +\pnum +\returns +\tcode{true} if and only if + \tcode{S1} and \tcode{S2} are standard-layout struct\iref{class.prop} types, + \tcode{M1} and \tcode{M2} are object types, + \tcode{m1} and \tcode{m2} are not null, + and \tcode{m1} and \tcode{m2} point to corresponding members of + the common initial sequence\iref{class.mem} of \tcode{S1} and \tcode{S2}. +\end{itemdescr} + +\pnum +\begin{note} +The type of a pointer-to-member expression \tcode{\&C::b} +is not always a pointer to member of \tcode{C}, +leading to potentially surprising results +when using these functions in conjunction with inheritance. +\begin{example} +\begin{codeblock} +struct A { int a; }; // a standard-layout class +struct B { int b; }; // a standard-layout class +struct C: public A, public B { }; // not a standard-layout class + +static_assert( is_pointer_interconvertible_with_class( &C::b ) ); + // Succeeds because, despite its appearance, \tcode{\&C::b} has type + // ``pointer to member of \tcode{B} of type \tcode{int}''. +static_assert( is_pointer_interconvertible_with_class( &C::b ) ); + // Forces the use of class \tcode{C}, and fails. + +static_assert( is_corresponding_member( &C::a, &C::b ) ); + // Succeeds because, despite its appearance, \tcode{\&C::a} and \tcode{\&C::b} have types + // ``pointer to member of \tcode{A} of type \tcode{int}'' and + // ``pointer to member of \tcode{B} of type \tcode{int}'', respectively. +static_assert( is_corresponding_member( &C::a, &C::b ) ); + // Forces the use of class \tcode{C}, and fails. +\end{codeblock} +\end{example} +\end{note} + +\rSec2[meta.const.eval]{Constant evaluation context} +\begin{itemdecl} +constexpr bool is_constant_evaluated() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if consteval { + return true; +} else { + return false; +} +\end{codeblock} + +\pnum +\begin{example} +\begin{codeblock} +constexpr void f(unsigned char *p, int n) { + if (std::is_constant_evaluated()) { // should not be a constexpr if statement + for (int k = 0; k} synopsis} + +\indexheader{ratio}% +\begin{codeblockdigitsep} +namespace std { + // \ref{ratio.ratio}, class template \tcode{ratio} + template class ratio; + + // \ref{ratio.arithmetic}, ratio arithmetic + template using ratio_add = @\seebelow@; + template using ratio_subtract = @\seebelow@; + template using ratio_multiply = @\seebelow@; + template using ratio_divide = @\seebelow@; + + // \ref{ratio.comparison}, ratio comparison + template struct ratio_equal; + template struct ratio_not_equal; + template struct ratio_less; + template struct ratio_less_equal; + template struct ratio_greater; + template struct ratio_greater_equal; + + template + inline constexpr bool @\libglobal{ratio_equal_v}@ = ratio_equal::value; + template + inline constexpr bool @\libglobal{ratio_not_equal_v}@ = ratio_not_equal::value; + template + inline constexpr bool @\libglobal{ratio_less_v}@ = ratio_less::value; + template + inline constexpr bool @\libglobal{ratio_less_equal_v}@ = ratio_less_equal::value; + template + inline constexpr bool @\libglobal{ratio_greater_v}@ = ratio_greater::value; + template + inline constexpr bool @\libglobal{ratio_greater_equal_v}@ = ratio_greater_equal::value; + + // \ref{ratio.si}, convenience SI typedefs + using yocto = ratio<1, 1'000'000'000'000'000'000'000'000>; // see below + using zepto = ratio<1, 1'000'000'000'000'000'000'000>; // see below + using atto = ratio<1, 1'000'000'000'000'000'000>; + using femto = ratio<1, 1'000'000'000'000'000>; + using pico = ratio<1, 1'000'000'000'000>; + using nano = ratio<1, 1'000'000'000>; + using micro = ratio<1, 1'000'000>; + using milli = ratio<1, 1'000>; + using centi = ratio<1, 100>; + using deci = ratio<1, 10>; + using deca = ratio< 10, 1>; + using hecto = ratio< 100, 1>; + using kilo = ratio< 1'000, 1>; + using mega = ratio< 1'000'000, 1>; + using giga = ratio< 1'000'000'000, 1>; + using tera = ratio< 1'000'000'000'000, 1>; + using peta = ratio< 1'000'000'000'000'000, 1>; + using exa = ratio< 1'000'000'000'000'000'000, 1>; + using zetta = ratio< 1'000'000'000'000'000'000'000, 1>; // see below + using yotta = ratio<1'000'000'000'000'000'000'000'000, 1>; // see below +} +\end{codeblockdigitsep} + +\rSec2[ratio.ratio]{Class template \tcode{ratio}} + +\indexlibraryglobal{ratio}% +\begin{codeblock} +namespace std { + template class ratio { + public: + static constexpr intmax_t num; + static constexpr intmax_t den; + using type = ratio; + }; +} +\end{codeblock} + +\pnum +\indextext{signed integer representation!two's complement}% +If the template argument \tcode{D} is zero or the absolute values of either of the +template arguments \tcode{N} and \tcode{D} is not representable by type +\tcode{intmax_t}, the program is ill-formed. +\begin{note} +These rules ensure that infinite +ratios are avoided and that for any negative input, there exists a representable value +of its absolute value which is positive. +This excludes the most negative value. +\end{note} + +\pnum +The static data members \tcode{num} and \tcode{den} shall have the following values, +where \tcode{gcd} represents the greatest common divisor of the absolute values of +\tcode{N} and \tcode{D}: + +\begin{itemize} +\item \tcode{num} shall have the value \tcode{sign(N) * sign(D) * abs(N) / gcd}. +\item \tcode{den} shall have the value \tcode{abs(D) / gcd}. +\end{itemize} + +\rSec2[ratio.arithmetic]{Arithmetic on \tcode{ratio}{s}} + +\pnum +Each of the alias templates \tcode{ratio_add}, \tcode{ratio_subtract}, \tcode{ratio_multiply}, +and \tcode{ratio_divide} denotes the result of an arithmetic computation on two +\tcode{ratio}{s} \tcode{R1} and \tcode{R2}. With \tcode{X} and \tcode{Y} computed (in the +absence of arithmetic overflow) as specified by \tref{ratio.arithmetic}, each alias +denotes a \tcode{ratio} such that \tcode{U} is the same as \tcode{ratio::num} and +\tcode{V} is the same as \tcode{ratio::den}. + +\pnum +If it is not possible to represent \tcode{U} or \tcode{V} with \tcode{intmax_t}, the program is +ill-formed. Otherwise, an implementation should yield correct values of \tcode{U} and +\tcode{V}. If it is not possible to represent \tcode{X} or \tcode{Y} with \tcode{intmax_t}, the +program is ill-formed unless the implementation yields correct values of \tcode{U} and +\tcode{V}. + +\begin{floattable}{Expressions used to perform ratio arithmetic}{ratio.arithmetic} +{lll} +\topline +\lhdr{Type} & + \chdr{Value of \tcode{X}} & + \rhdr{Value of \tcode{Y}} \\ \rowsep + +\tcode{ratio_add} & + \tcode{R1::num * R2::den +} & + \tcode{R1::den * R2::den} \\ + & + \tcode{R2::num * R1::den} & + \\ \rowsep + +\tcode{ratio_subtract} & + \tcode{R1::num * R2::den -} & + \tcode{R1::den * R2::den} \\ + & + \tcode{R2::num * R1::den} & + \\ \rowsep + +\tcode{ratio_multiply} & + \tcode{R1::num * R2::num} & + \tcode{R1::den * R2::den} \\ \rowsep + +\tcode{ratio_divide} & + \tcode{R1::num * R2::den} & + \tcode{R1::den * R2::num} \\ +\end{floattable} + +\pnum +\begin{example} +\begin{codeblock} +static_assert(ratio_add, ratio<1, 6>>::num == 1, "1/3+1/6 == 1/2"); +static_assert(ratio_add, ratio<1, 6>>::den == 2, "1/3+1/6 == 1/2"); +static_assert(ratio_multiply, ratio<3, 2>>::num == 1, "1/3*3/2 == 1/2"); +static_assert(ratio_multiply, ratio<3, 2>>::den == 2, "1/3*3/2 == 1/2"); + +// The following cases may cause the program to be ill-formed under some implementations +static_assert(ratio_add, ratio<1, INT_MAX>>::num == 2, + "1/MAX+1/MAX == 2/MAX"); +static_assert(ratio_add, ratio<1, INT_MAX>>::den == INT_MAX, + "1/MAX+1/MAX == 2/MAX"); +static_assert(ratio_multiply, ratio>::num == 1, + "1/MAX * MAX/2 == 1/2"); +static_assert(ratio_multiply, ratio>::den == 2, + "1/MAX * MAX/2 == 1/2"); +\end{codeblock} + +\end{example} + +\rSec2[ratio.comparison]{Comparison of \tcode{ratio}{s}} + +\indexlibraryglobal{ratio_equal}% +\begin{itemdecl} +template + struct ratio_equal : bool_constant { }; +\end{itemdecl} + +\indexlibraryglobal{ratio_not_equal}% +\begin{itemdecl} +template + struct ratio_not_equal : bool_constant> { }; +\end{itemdecl} + +\indexlibraryglobal{ratio_less}% +\begin{itemdecl} +template + struct ratio_less : bool_constant<@\seebelow@> { }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +If \tcode{R1::num} $\times$ \tcode{R2::den} is less than \tcode{R2::num} $\times$ \tcode{R1::den}, +\tcode{ratio_less} shall be +derived from \tcode{bool_constant}; otherwise it shall be derived from +\tcode{bool_constant}. Implementations may use other algorithms to +compute this relationship to avoid overflow. If overflow occurs, the program is ill-formed. +\end{itemdescr} + +\indexlibraryglobal{ratio_less_equal}% +\begin{itemdecl} +template + struct ratio_less_equal : bool_constant> { }; +\end{itemdecl} + +\indexlibraryglobal{ratio_greater}% +\begin{itemdecl} +template + struct ratio_greater : bool_constant> { }; +\end{itemdecl} + +\indexlibraryglobal{ratio_greater_equal}% +\begin{itemdecl} +template + struct ratio_greater_equal : bool_constant> { }; +\end{itemdecl} + +\rSec2[ratio.si]{SI types for \tcode{ratio}} + +\pnum +For each of the \grammarterm{typedef-name}{s} \tcode{yocto}, \tcode{zepto}, +\tcode{zetta}, and \tcode{yotta}, if both of the constants used in its +specification are representable by \tcode{intmax_t}, the typedef is +defined; if either of the constants is not representable by \tcode{intmax_t}, +the typedef is not defined. + diff --git a/source/std.tex b/source/std.tex index dc5385f897..aaad1709ee 100644 --- a/source/std.tex +++ b/source/std.tex @@ -120,6 +120,7 @@ \include{concepts} \include{diagnostics} \include{memory} +\include{meta} \include{utilities} \include{strings} \include{containers} diff --git a/source/utilities.tex b/source/utilities.tex index 52a1a16d73..f2c3b14f78 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -10,7 +10,6 @@ \begin{libsumtab}{General utilities library summary}{utilities.summary} \ref{utility} & Utility components & \tcode{} \\ -\ref{intseq} & Compile-time integer sequences & \\ \ref{pairs} & Pairs & \\ \rowsep \ref{tuple} & Tuples & \tcode{} \\ \rowsep \ref{optional} & Optional objects & \tcode{} \\ \rowsep @@ -19,8 +18,6 @@ \ref{expected} & Expected objects & \tcode{} \\ \rowsep \ref{bitset} & Fixed-size sequences of bits & \tcode{} \\ \rowsep \ref{function.objects} & Function objects & \tcode{} \\ \rowsep -\ref{meta} & Type traits & \tcode{} \\ \rowsep -\ref{ratio} & Compile-time rational arithmetic & \tcode{} \\ \rowsep \ref{type.index} & Type indexes & \tcode{} \\ \rowsep \ref{execpol} & Execution policies & \tcode{} \\ \rowsep \ref{charconv} & Primitive numeric conversions & \tcode{} \\ \rowsep @@ -645,61 +642,6 @@ \end{example} \end{itemdescr} -\rSec1[intseq]{Compile-time integer sequences} - -\rSec2[intseq.general]{In general} - -\pnum -The library provides a class template that can represent an integer sequence. -When used as an argument to a function template the template parameter pack defining the -sequence can be deduced and used in a pack expansion. -\begin{note} -The \tcode{index_sequence} alias template is provided for the common case of -an integer sequence of type \tcode{size_t}; see also \ref{tuple.apply}. -\end{note} - -\rSec2[intseq.intseq]{Class template \tcode{integer_sequence}} - -\indexlibraryglobal{integer_sequence}% -\indexlibrarymember{value_type}{integer_sequence}% -\begin{codeblock} -namespace std { - template struct integer_sequence { - using value_type = T; - static constexpr size_t size() noexcept { return sizeof...(I); } - }; -} -\end{codeblock} - -\pnum -\mandates -\tcode{T} is an integer type. - -\rSec2[intseq.make]{Alias template \tcode{make_integer_sequence}} - -\indexlibraryglobal{make_integer_sequence}% -\begin{itemdecl} -template - using make_integer_sequence = integer_sequence; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -$\tcode{N} \geq 0$. - -\pnum -The alias template -\tcode{make_integer_sequence} denotes a specialization of -\tcode{integer_sequence} with \tcode{N} non-type template arguments. -The type \tcode{make_integer_sequence} is an alias for the type -\tcode{integer_sequence}. -\begin{note} -\tcode{make_integer_sequence} is an alias for the type -\tcode{integer_sequence}. -\end{note} -\end{itemdescr} - \rSec1[pairs]{Pairs} \rSec2[pairs.general]{In general} @@ -12706,2566 +12648,6 @@ program-defined specialization. \end{itemize} -\rSec1[meta]{Metaprogramming and type traits} - -\rSec2[meta.general]{General} - -\pnum -Subclause \ref{meta} describes components used by \Cpp{} programs, particularly in -templates, to support the widest possible range of types, optimise -template code usage, detect type related user errors, and perform -type inference and transformation at compile time. It includes type -classification traits, type property inspection traits, and type -transformations. The type classification traits describe a complete taxonomy -of all possible \Cpp{} types, and state where in that taxonomy a given -type belongs. The type property inspection traits allow important -characteristics of types or of combinations of types to be inspected. The -type transformations allow certain properties of types to be manipulated. - -\pnum -\indextext{signal-safe!type traits}% -All functions specified in \ref{meta} are signal-safe\iref{support.signal}. - -\rSec2[meta.rqmts]{Requirements} - -\pnum -A \defnoldconcept{UnaryTypeTrait} describes a property -of a type. It shall be a class template that takes one template type -argument and, optionally, additional arguments that help define the -property being described. It shall be \oldconcept{DefaultConstructible}, -\oldconcept{CopyConstructible}, -and publicly and unambiguously derived, directly or indirectly, from -its \defn{base characteristic}, which is -a specialization of the template -\tcode{integral_constant}\iref{meta.help}, with -the arguments to the template \tcode{integral_constant} determined by the -requirements for the particular property being described. -The member names of the base characteristic shall not be hidden and shall be -unambiguously available in the \oldconcept{UnaryTypeTrait}. - -\pnum -A \defnoldconcept{BinaryTypeTrait} describes a -relationship between two types. It shall be a class template that -takes two template type arguments and, optionally, additional -arguments that help define the relationship being described. It shall -be \oldconcept{DefaultConstructible}, \oldconcept{CopyConstructible}, -and publicly and unambiguously derived, directly or -indirectly, from -its \term{base characteristic}, which is a specialization -of the template -\tcode{integral_constant}\iref{meta.help}, with -the arguments to the template \tcode{integral_constant} determined by the -requirements for the particular relationship being described. -The member names of the base characteristic shall not be hidden and shall be -unambiguously available in the \oldconcept{BinaryTypeTrait}. - -\pnum -A \defnoldconcept{TransformationTrait} -modifies a property -of a type. It shall be a class template that takes one -template type argument and, optionally, additional arguments that help -define the modification. It shall define a publicly accessible nested type -named \tcode{type}, which shall be a synonym for the modified type. - -\pnum -Unless otherwise specified, -the behavior of a program that adds specializations -for any of the templates specified in \ref{meta} -is undefined. - -\pnum -Unless otherwise specified, an incomplete type may be used -to instantiate a template specified in \ref{meta}. -The behavior of a program is undefined if: -\begin{itemize} -\item - an instantiation of a template specified in \ref{meta} - directly or indirectly depends on - an incompletely-defined object type \tcode{T}, and -\item - that instantiation could yield a different result - were \tcode{T} hypothetically completed. -\end{itemize} - -\rSec2[meta.type.synop]{Header \tcode{} synopsis} - -\indexheader{type_traits}% -% FIXME: Many index entries missing. -\begin{codeblock} -namespace std { - // \ref{meta.help}, helper class - template struct integral_constant; - - template - using bool_constant = integral_constant; - using true_type = bool_constant; - using false_type = bool_constant; - - // \ref{meta.unary.cat}, primary type categories - template struct is_void; - template struct is_null_pointer; - template struct is_integral; - template struct is_floating_point; - template struct is_array; - template struct is_pointer; - template struct is_lvalue_reference; - template struct is_rvalue_reference; - template struct is_member_object_pointer; - template struct is_member_function_pointer; - template struct is_enum; - template struct is_union; - template struct is_class; - template struct is_function; - - // \ref{meta.unary.comp}, composite type categories - template struct is_reference; - template struct is_arithmetic; - template struct is_fundamental; - template struct is_object; - template struct is_scalar; - template struct is_compound; - template struct is_member_pointer; - - // \ref{meta.unary.prop}, type properties - template struct is_const; - template struct is_volatile; - template struct is_trivial; - template struct is_trivially_copyable; - template struct is_standard_layout; - template struct is_empty; - template struct is_polymorphic; - template struct is_abstract; - template struct is_final; - template struct is_aggregate; - - template struct is_signed; - template struct is_unsigned; - template struct is_bounded_array; - template struct is_unbounded_array; - template struct is_scoped_enum; - - template struct is_constructible; - template struct is_default_constructible; - template struct is_copy_constructible; - template struct is_move_constructible; - - template struct is_assignable; - template struct is_copy_assignable; - template struct is_move_assignable; - - template struct is_swappable_with; - template struct is_swappable; - - template struct is_destructible; - - template struct is_trivially_constructible; - template struct is_trivially_default_constructible; - template struct is_trivially_copy_constructible; - template struct is_trivially_move_constructible; - - template struct is_trivially_assignable; - template struct is_trivially_copy_assignable; - template struct is_trivially_move_assignable; - template struct is_trivially_destructible; - - template struct is_nothrow_constructible; - template struct is_nothrow_default_constructible; - template struct is_nothrow_copy_constructible; - template struct is_nothrow_move_constructible; - - template struct is_nothrow_assignable; - template struct is_nothrow_copy_assignable; - template struct is_nothrow_move_assignable; - - template struct is_nothrow_swappable_with; - template struct is_nothrow_swappable; - - template struct is_nothrow_destructible; - - template struct has_virtual_destructor; - - template struct has_unique_object_representations; - - template struct reference_constructs_from_temporary; - template struct reference_converts_from_temporary; - - // \ref{meta.unary.prop.query}, type property queries - template struct alignment_of; - template struct rank; - template struct extent; - - // \ref{meta.rel}, type relations - template struct is_same; - template struct is_base_of; - template struct is_convertible; - template struct is_nothrow_convertible; - template struct is_layout_compatible; - template struct is_pointer_interconvertible_base_of; - - template struct is_invocable; - template struct is_invocable_r; - - template struct is_nothrow_invocable; - template struct is_nothrow_invocable_r; - - // \ref{meta.trans.cv}, const-volatile modifications - template struct remove_const; - template struct remove_volatile; - template struct remove_cv; - template struct add_const; - template struct add_volatile; - template struct add_cv; - - template - using @\libglobal{remove_const_t}@ = typename remove_const::type; - template - using @\libglobal{remove_volatile_t}@ = typename remove_volatile::type; - template - using @\libglobal{remove_cv_t}@ = typename remove_cv::type; - template - using @\libglobal{add_const_t}@ = typename add_const::type; - template - using @\libglobal{add_volatile_t}@ = typename add_volatile::type; - template - using @\libglobal{add_cv_t}@ = typename add_cv::type; - - // \ref{meta.trans.ref}, reference modifications - template struct remove_reference; - template struct add_lvalue_reference; - template struct add_rvalue_reference; - - template - using @\libglobal{remove_reference_t}@ = typename remove_reference::type; - template - using @\libglobal{add_lvalue_reference_t}@ = typename add_lvalue_reference::type; - template - using @\libglobal{add_rvalue_reference_t}@ = typename add_rvalue_reference::type; - - // \ref{meta.trans.sign}, sign modifications - template struct make_signed; - template struct make_unsigned; - - template - using @\libglobal{make_signed_t}@ = typename make_signed::type; - template - using @\libglobal{make_unsigned_t}@ = typename make_unsigned::type; - - // \ref{meta.trans.arr}, array modifications - template struct remove_extent; - template struct remove_all_extents; - - template - using @\libglobal{remove_extent_t}@ = typename remove_extent::type; - template - using @\libglobal{remove_all_extents_t}@ = typename remove_all_extents::type; - - // \ref{meta.trans.ptr}, pointer modifications - template struct remove_pointer; - template struct add_pointer; - - template - using @\libglobal{remove_pointer_t}@ = typename remove_pointer::type; - template - using @\libglobal{add_pointer_t}@ = typename add_pointer::type; - - // \ref{meta.trans.other}, other transformations - template struct type_identity; - template struct remove_cvref; - template struct decay; - template struct enable_if; - template struct conditional; - template struct common_type; - template class TQual, template class UQual> - struct basic_common_reference { }; - template struct common_reference; - template struct underlying_type; - template struct invoke_result; - template struct unwrap_reference; - template struct unwrap_ref_decay; - - template - using @\libglobal{type_identity_t}@ = typename type_identity::type; - template - using @\libglobal{remove_cvref_t}@ = typename remove_cvref::type; - template - using @\libglobal{decay_t}@ = typename decay::type; - template - using @\libglobal{enable_if_t}@ = typename enable_if::type; - template - using @\libglobal{conditional_t}@ = typename conditional::type; - template - using @\libglobal{common_type_t}@ = typename common_type::type; - template - using @\libglobal{common_reference_t}@ = typename common_reference::type; - template - using @\libglobal{underlying_type_t}@ = typename underlying_type::type; - template - using @\libglobal{invoke_result_t}@ = typename invoke_result::type; - template - using unwrap_reference_t = typename unwrap_reference::type; - template - using unwrap_ref_decay_t = typename unwrap_ref_decay::type; - template - using @\libglobal{void_t}@ = void; - - // \ref{meta.logical}, logical operator traits - template struct conjunction; - template struct disjunction; - template struct negation; - - // \ref{meta.unary.cat}, primary type categories - template - inline constexpr bool @\libglobal{is_void_v}@ = is_void::value; - template - inline constexpr bool @\libglobal{is_null_pointer_v}@ = is_null_pointer::value; - template - inline constexpr bool @\libglobal{is_integral_v}@ = is_integral::value; - template - inline constexpr bool @\libglobal{is_floating_point_v}@ = is_floating_point::value; - template - inline constexpr bool @\libglobal{is_array_v}@ = is_array::value; - template - inline constexpr bool @\libglobal{is_pointer_v}@ = is_pointer::value; - template - inline constexpr bool @\libglobal{is_lvalue_reference_v}@ = is_lvalue_reference::value; - template - inline constexpr bool @\libglobal{is_rvalue_reference_v}@ = is_rvalue_reference::value; - template - inline constexpr bool @\libglobal{is_member_object_pointer_v}@ = is_member_object_pointer::value; - template - inline constexpr bool @\libglobal{is_member_function_pointer_v}@ = is_member_function_pointer::value; - template - inline constexpr bool @\libglobal{is_enum_v}@ = is_enum::value; - template - inline constexpr bool @\libglobal{is_union_v}@ = is_union::value; - template - inline constexpr bool @\libglobal{is_class_v}@ = is_class::value; - template - inline constexpr bool @\libglobal{is_function_v}@ = is_function::value; - - // \ref{meta.unary.comp}, composite type categories - template - inline constexpr bool @\libglobal{is_reference_v}@ = is_reference::value; - template - inline constexpr bool @\libglobal{is_arithmetic_v}@ = is_arithmetic::value; - template - inline constexpr bool @\libglobal{is_fundamental_v}@ = is_fundamental::value; - template - inline constexpr bool @\libglobal{is_object_v}@ = is_object::value; - template - inline constexpr bool @\libglobal{is_scalar_v}@ = is_scalar::value; - template - inline constexpr bool @\libglobal{is_compound_v}@ = is_compound::value; - template - inline constexpr bool @\libglobal{is_member_pointer_v}@ = is_member_pointer::value; - - // \ref{meta.unary.prop}, type properties - template - inline constexpr bool @\libglobal{is_const_v}@ = is_const::value; - template - inline constexpr bool @\libglobal{is_volatile_v}@ = is_volatile::value; - template - inline constexpr bool @\libglobal{is_trivial_v}@ = is_trivial::value; - template - inline constexpr bool @\libglobal{is_trivially_copyable_v}@ = is_trivially_copyable::value; - template - inline constexpr bool @\libglobal{is_standard_layout_v}@ = is_standard_layout::value; - template - inline constexpr bool @\libglobal{is_empty_v}@ = is_empty::value; - template - inline constexpr bool @\libglobal{is_polymorphic_v}@ = is_polymorphic::value; - template - inline constexpr bool @\libglobal{is_abstract_v}@ = is_abstract::value; - template - inline constexpr bool @\libglobal{is_final_v}@ = is_final::value; - template - inline constexpr bool @\libglobal{is_aggregate_v}@ = is_aggregate::value; - template - inline constexpr bool @\libglobal{is_signed_v}@ = is_signed::value; - template - inline constexpr bool @\libglobal{is_unsigned_v}@ = is_unsigned::value; - template - inline constexpr bool @\libglobal{is_bounded_array_v}@ = is_bounded_array::value; - template - inline constexpr bool @\libglobal{is_unbounded_array_v}@ = is_unbounded_array::value; - template - inline constexpr bool @\libglobal{is_scoped_enum_v}@ = is_scoped_enum::value; - template - inline constexpr bool @\libglobal{is_constructible_v}@ = is_constructible::value; - template - inline constexpr bool @\libglobal{is_default_constructible_v}@ = is_default_constructible::value; - template - inline constexpr bool @\libglobal{is_copy_constructible_v}@ = is_copy_constructible::value; - template - inline constexpr bool @\libglobal{is_move_constructible_v}@ = is_move_constructible::value; - template - inline constexpr bool @\libglobal{is_assignable_v}@ = is_assignable::value; - template - inline constexpr bool @\libglobal{is_copy_assignable_v}@ = is_copy_assignable::value; - template - inline constexpr bool @\libglobal{is_move_assignable_v}@ = is_move_assignable::value; - template - inline constexpr bool @\libglobal{is_swappable_with_v}@ = is_swappable_with::value; - template - inline constexpr bool @\libglobal{is_swappable_v}@ = is_swappable::value; - template - inline constexpr bool @\libglobal{is_destructible_v}@ = is_destructible::value; - template - inline constexpr bool is_trivially_constructible_v - = is_trivially_constructible::value; - template - inline constexpr bool is_trivially_default_constructible_v - = is_trivially_default_constructible::value; - template - inline constexpr bool is_trivially_copy_constructible_v - = is_trivially_copy_constructible::value; - template - inline constexpr bool is_trivially_move_constructible_v - = is_trivially_move_constructible::value; - template - inline constexpr bool @\libglobal{is_trivially_assignable_v}@ = is_trivially_assignable::value; - template - inline constexpr bool is_trivially_copy_assignable_v - = is_trivially_copy_assignable::value; - template - inline constexpr bool is_trivially_move_assignable_v - = is_trivially_move_assignable::value; - template - inline constexpr bool @\libglobal{is_trivially_destructible_v}@ = is_trivially_destructible::value; - template - inline constexpr bool is_nothrow_constructible_v - = is_nothrow_constructible::value; - template - inline constexpr bool is_nothrow_default_constructible_v - = is_nothrow_default_constructible::value; - template - inline constexpr bool is_nothrow_copy_constructible_v - = is_nothrow_copy_constructible::value; - template - inline constexpr bool is_nothrow_move_constructible_v - = is_nothrow_move_constructible::value; - template - inline constexpr bool @\libglobal{is_nothrow_assignable_v}@ = is_nothrow_assignable::value; - template - inline constexpr bool @\libglobal{is_nothrow_copy_assignable_v}@ = is_nothrow_copy_assignable::value; - template - inline constexpr bool @\libglobal{is_nothrow_move_assignable_v}@ = is_nothrow_move_assignable::value; - template - inline constexpr bool @\libglobal{is_nothrow_swappable_with_v}@ = is_nothrow_swappable_with::value; - template - inline constexpr bool @\libglobal{is_nothrow_swappable_v}@ = is_nothrow_swappable::value; - template - inline constexpr bool @\libglobal{is_nothrow_destructible_v}@ = is_nothrow_destructible::value; - template - inline constexpr bool @\libglobal{has_virtual_destructor_v}@ = has_virtual_destructor::value; - template - inline constexpr bool has_unique_object_representations_v - = has_unique_object_representations::value; - template - inline constexpr bool @\libglobal{reference_constructs_from_temporary_v}@ - = reference_constructs_from_temporary::value; - template - inline constexpr bool @\libglobal{reference_converts_from_temporary_v}@ - = reference_converts_from_temporary::value; - - // \ref{meta.unary.prop.query}, type property queries - template - inline constexpr size_t @\libglobal{alignment_of_v}@ = alignment_of::value; - template - inline constexpr size_t @\libglobal{rank_v}@ = rank::value; - template - inline constexpr size_t @\libglobal{extent_v}@ = extent::value; - - // \ref{meta.rel}, type relations - template - inline constexpr bool @\libglobal{is_same_v}@ = is_same::value; - template - inline constexpr bool @\libglobal{is_base_of_v}@ = is_base_of::value; - template - inline constexpr bool @\libglobal{is_convertible_v}@ = is_convertible::value; - template - inline constexpr bool @\libglobal{is_nothrow_convertible_v}@ = is_nothrow_convertible::value; - template - inline constexpr bool @\libglobal{is_layout_compatible_v}@ = is_layout_compatible::value; - template - inline constexpr bool is_pointer_interconvertible_base_of_v - = is_pointer_interconvertible_base_of::value; - template - inline constexpr bool @\libglobal{is_invocable_v}@ = is_invocable::value; - template - inline constexpr bool @\libglobal{is_invocable_r_v}@ = is_invocable_r::value; - template - inline constexpr bool @\libglobal{is_nothrow_invocable_v}@ = is_nothrow_invocable::value; - template - inline constexpr bool is_nothrow_invocable_r_v - = is_nothrow_invocable_r::value; - - // \ref{meta.logical}, logical operator traits - template - inline constexpr bool @\libglobal{conjunction_v}@ = conjunction::value; - template - inline constexpr bool @\libglobal{disjunction_v}@ = disjunction::value; - template - inline constexpr bool @\libglobal{negation_v}@ = negation::value; - - // \ref{meta.member}, member relationships - template - constexpr bool is_pointer_interconvertible_with_class(M S::*m) noexcept; - template - constexpr bool is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept; - - // \ref{meta.const.eval}, constant evaluation context - constexpr bool is_constant_evaluated() noexcept; -} -\end{codeblock} - -\rSec2[meta.help]{Helper classes} - -\indexlibrarymember{value_type}{integral_constant}% -\begin{codeblock} -namespace std { - template struct integral_constant { - static constexpr T value = v; - - using value_type = T; - using type = integral_constant; - - constexpr operator value_type() const noexcept { return value; } - constexpr value_type operator()() const noexcept { return value; } - }; -} -\end{codeblock} - -\indexlibraryglobal{integral_constant}% -\indexlibraryglobal{bool_constant}% -\indexlibraryglobal{true_type}% -\indexlibraryglobal{false_type}% -\pnum -The class template \tcode{integral_constant}, -alias template \tcode{bool_constant}, and -its associated \grammarterm{typedef-name}{s} -\tcode{true_type} and \tcode{false_type} -are used as base classes to define -the interface for various type traits. - -\rSec2[meta.unary]{Unary type traits} - -\rSec3[meta.unary.general]{General} - -\pnum -Subclause \ref{meta.unary} contains templates that may be used to query the -properties of a type at compile time. - -\pnum -Each of these templates shall be a -\oldconcept{UnaryTypeTrait}\iref{meta.rqmts} -with a base characteristic of -\tcode{true_type} if the corresponding condition is \tcode{true}, otherwise -\tcode{false_type}. - -\rSec3[meta.unary.cat]{Primary type categories} - -\pnum -The primary type categories correspond to the descriptions given in -subclause~\ref{basic.types} of the \Cpp{} standard. - -\pnum -For any given type \tcode{T}, the result of applying one of these templates to -\tcode{T} and to \cv{}~\tcode{T} shall yield the same result. - -\pnum -\begin{note} -For any given type \tcode{T}, exactly one of the primary type categories -has a \tcode{value} member that evaluates to \tcode{true}. -\end{note} - -\begin{libreqtab3e}{Primary type category predicates}{meta.unary.cat} -\\ \topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\\capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep -\endhead -\indexlibraryglobal{is_void}% -\tcode{template}\br - \tcode{struct is_void;} & -\tcode{T} is \keyword{void} & \\ \rowsep -\indexlibraryglobal{is_null_pointer}% -\tcode{template}\br - \tcode{struct is_null_pointer;} & -\tcode{T} is \tcode{nullptr_t}\iref{basic.fundamental} & \\ \rowsep -\indexlibraryglobal{is_integral}% -\tcode{template}\br - \tcode{struct is_integral;} & -\tcode{T} is an integral type\iref{basic.fundamental} & \\ \rowsep -\indexlibraryglobal{is_floating_point}% -\tcode{template}\br - \tcode{struct is_floating_point;} & -\tcode{T} is a floating-point type\iref{basic.fundamental} & \\ \rowsep -\indexlibraryglobal{is_array}% -\tcode{template}\br - \tcode{struct is_array;} & -\tcode{T} is an array type\iref{basic.compound} of known or unknown extent & -Class template \tcode{array}\iref{array} -is not an array type. \\ \rowsep -\indexlibraryglobal{is_pointer}% -\tcode{template}\br - \tcode{struct is_pointer;} & -\tcode{T} is a pointer type\iref{basic.compound} & -Includes pointers to functions -but not pointers to non-static members. \\ \rowsep -\indexlibraryglobal{is_lvalue_reference}% -\tcode{template}\br - \tcode{struct is_lvalue_reference;} & - \tcode{T} is an lvalue reference type\iref{dcl.ref} & \\ \rowsep -\indexlibraryglobal{is_rvalue_reference}% -\tcode{template}\br - \tcode{struct is_rvalue_reference;} & - \tcode{T} is an rvalue reference type\iref{dcl.ref} & \\ \rowsep -\indexlibraryglobal{is_member_object_pointer}% -\tcode{template}\br - \tcode{struct is_member_object_pointer;}& - \tcode{T} is a pointer to data member & \\ \rowsep -\indexlibraryglobal{is_member_function_pointer}% -\tcode{template}\br - \tcode{struct is_member_function_pointer;}& -\tcode{T} is a pointer to member function & \\ \rowsep -\indexlibraryglobal{is_enum}% -\tcode{template}\br - \tcode{struct is_enum;} & -\tcode{T} is an enumeration type\iref{basic.compound} & \\ \rowsep -\indexlibraryglobal{is_union}% -\tcode{template}\br - \tcode{struct is_union;} & -\tcode{T} is a union type\iref{basic.compound} & \\ \rowsep -\indexlibraryglobal{is_class}% -\tcode{template}\br - \tcode{struct is_class;} & -\tcode{T} is a non-union class type\iref{basic.compound} & \\ \rowsep -\indexlibraryglobal{is_function}% -\tcode{template}\br - \tcode{struct is_function;} & -\tcode{T} is a function type\iref{basic.compound} & \\ -\end{libreqtab3e} - -\rSec3[meta.unary.comp]{Composite type traits} - -\pnum -These templates provide convenient compositions of the primary type -categories, corresponding to the descriptions given in subclause~\ref{basic.types}. - -\pnum -For any given type \tcode{T}, the result of applying one of these templates to -\tcode{T} and to \cv{}~\tcode{T} shall yield the same result. - -\begin{libreqtab3b}{Composite type category predicates}{meta.unary.comp} -\\ \topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep -\endhead -\indexlibraryglobal{is_reference}% -\tcode{template}\br - \tcode{struct is_reference;} & - \tcode{T} is an lvalue reference or an rvalue reference & \\ \rowsep -\indexlibraryglobal{is_arithmetic}% -\tcode{template}\br - \tcode{struct is_arithmetic;} & - \tcode{T} is an arithmetic type\iref{basic.fundamental} & \\ \rowsep -\indexlibraryglobal{is_fundamental}% -\tcode{template}\br - \tcode{struct is_fundamental;} & - \tcode{T} is a fundamental type\iref{basic.fundamental} & \\ \rowsep -\indexlibraryglobal{is_object}% -\tcode{template}\br - \tcode{struct is_object;} & - \tcode{T} is an object type\iref{term.object.type} & \\ \rowsep -\indexlibraryglobal{is_scalar}% -\tcode{template}\br - \tcode{struct is_scalar;} & - \tcode{T} is a scalar type\iref{term.scalar.type} & \\ \rowsep -\indexlibraryglobal{is_compound}% -\tcode{template}\br - \tcode{struct is_compound;} & - \tcode{T} is a compound type\iref{basic.compound} & \\ \rowsep -\indexlibraryglobal{is_member_pointer}% -\tcode{template}\br - \tcode{struct is_member_pointer;} & - \tcode{T} is a pointer-to-member type\iref{basic.compound} & \\ -\end{libreqtab3b} - -\rSec3[meta.unary.prop]{Type properties} - -\pnum -These templates provide access to some of the more important -properties of types. - -\pnum -It is unspecified whether the library defines any full or partial -specializations of any of these templates. - -\pnum -For all of the class templates \tcode{X} declared in this subclause, -instantiating that template with a template-argument that is a class -template specialization may result in the implicit instantiation of -the template argument if and only if the semantics of \tcode{X} require that -the argument is a complete type. - -\pnum -For the purpose of defining the templates in this subclause, -a function call expression \tcode{declval()} for any type \tcode{T} -is considered to be a trivial\iref{term.trivial.type,special} function call -that is not an odr-use\iref{term.odr.use} of \tcode{declval} -in the context of the corresponding definition -notwithstanding the restrictions of~\ref{declval}. - -\pnum -For the purpose of defining the templates in this subclause, -let \tcode{\placeholdernc{VAL}} for some type \tcode{T} be -an expression defined as follows: -\begin{itemize} -\item -If \tcode{T} is a reference or function type, -\tcode{\placeholdernc{VAL}} is an expression -with the same type and value category as \tcode{declval()}. -\item -Otherwise, \tcode{\placeholdernc{VAL}} is a prvalue -that initially has type \tcode{T}. -\begin{note} -If \tcode{T} is cv-qualified, -the cv-qualification is subject to adjustment\iref{expr.type}. -\end{note} -\end{itemize} - -\begin{libreqtab3b}{Type property predicates}{meta.unary.prop} -\\ \topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Preconditions} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Preconditions} \\ \capsep -\endhead - -\indexlibraryglobal{is_const}% -\tcode{template}\br - \tcode{struct is_const;} & - \tcode{T} is const-qualified\iref{basic.type.qualifier} & \\ \rowsep - -\indexlibraryglobal{is_volatile}% -\tcode{template}\br - \tcode{struct is_volatile;} & - \tcode{T} is volatile-qualified\iref{basic.type.qualifier} & \\ \rowsep - - -\indexlibraryglobal{is_trivial}% -\tcode{template}\br - \tcode{struct is_trivial;} & - \tcode{T} is a trivial type\iref{term.trivial.type} & - \tcode{remove_all_extents_t} shall be a complete - type or \cv{}~\keyword{void}. \\ \rowsep - -\indexlibraryglobal{is_trivially_copyable}% -\tcode{template}\br - \tcode{struct is_trivially_copyable;} & - \tcode{T} is a trivially copyable type\iref{term.trivially.copyable.type} & - \tcode{remove_all_extents_t} shall be a complete type or - \cv{}~\keyword{void}. \\ \rowsep - -\indexlibraryglobal{is_standard_layout}% -\tcode{template}\br - \tcode{struct is_standard_layout;} & - \tcode{T} is a standard-layout type\iref{term.standard.layout.type} & - \tcode{remove_all_extents_t} shall be a complete - type or \cv{}~\keyword{void}. \\ \rowsep - -\indexlibrary{\idxcode{is_empty}!class}% -\tcode{template}\br - \tcode{struct is_empty;} & - \tcode{T} is a class type, but not a union type, with no non-static data - members other than subobjects of zero size, no virtual member functions, - no virtual base classes, and no base class \tcode{B} for - which \tcode{is_empty_v} is \tcode{false}. & - If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep - -\indexlibraryglobal{is_polymorphic}% -\tcode{template}\br - \tcode{struct is_polymorphic;} & - \tcode{T} is a polymorphic class\iref{class.virtual} & - If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep - -\indexlibraryglobal{is_abstract}% -\tcode{template}\br - \tcode{struct is_abstract;} & - \tcode{T} is an abstract class\iref{class.abstract} & - If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep - -\indexlibraryglobal{is_final}% -\tcode{template}\br - \tcode{struct is_final;} & - \tcode{T} is a class type marked with the \grammarterm{class-virt-specifier} - \tcode{final}\iref{class.pre}. -\begin{tailnote} -A union is a class type that - can be marked with \tcode{final}. -\end{tailnote} -& - If \tcode{T} is a class type, \tcode{T} shall be a complete type. \\ \rowsep - -\indexlibraryglobal{is_aggregate}% -\tcode{template}\br - \tcode{struct is_aggregate;} & - \tcode{T} is an aggregate type\iref{dcl.init.aggr} & - \tcode{remove_all_extents_t} shall be a complete type or \cv~\keyword{void}. \\ \rowsep - -\indexlibrary{\idxcode{is_signed}!class}% -\tcode{template}\br - \tcode{struct is_signed;} & - If \tcode{is_arithmetic_v} is \tcode{true}, the same result as - \tcode{T(-1) < T(0)}; - otherwise, \tcode{false} & \\ \rowsep - -\indexlibraryglobal{is_unsigned}% -\tcode{template}\br - \tcode{struct is_unsigned;} & - If \tcode{is_arithmetic_v} is \tcode{true}, the same result as - \tcode{T(0) < T(-1)}; - otherwise, \tcode{false} & \\ \rowsep - -\indexlibraryglobal{is_bounded_array}% -\tcode{template}\br - \tcode{struct is_bounded_array;} & - \tcode{T} is an array type of known bound\iref{dcl.array} - & \\ \rowsep - -\indexlibraryglobal{is_unbounded_array}% -\tcode{template}\br - \tcode{struct is_unbounded_array;} & - \tcode{T} is an array type of unknown bound\iref{dcl.array} - & \\ \rowsep - -\indexlibraryglobal{is_scoped_enum}% -\tcode{template}\br - \tcode{struct is_scoped_enum;} & - \tcode{T} is a scoped enumeration\iref{dcl.enum} - & \\ \rowsep - -\indexlibraryglobal{is_constructible}% -\tcode{template}\br - \tcode{struct is_constructible;} & - For a function type \tcode{T} or - for a \cv{}~\keyword{void} type \tcode{T}, - \tcode{is_constructible_v} is \tcode{false}, - otherwise \seebelow & - \tcode{T} and all types in the template parameter pack \tcode{Args} - shall be complete types, \cv{}~\keyword{void}, - or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_default_constructible}% -\tcode{template}\br - \tcode{struct is_default_constructible;} & - \tcode{is_constructible_v} is \tcode{true}. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, - or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_copy_constructible}% -\tcode{template}\br - \tcode{struct is_copy_constructible;} & - For a referenceable type \tcode{T}\iref{defns.referenceable}, the same result as - \tcode{is_constructible_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, - or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_move_constructible}% -\tcode{template}\br - \tcode{struct is_move_constructible;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_constructible_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, - or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_assignable}% -\tcode{template}\br - \tcode{struct is_assignable;} & - The expression \tcode{declval() =} \tcode{declval()} is well-formed - when treated as an unevaluated - operand\iref{term.unevaluated.operand}. Access checking is performed as if in a context - unrelated to \tcode{T} and \tcode{U}. Only the validity of the immediate context - of the assignment expression is considered. -\begin{tailnote} -The compilation of the - expression can result in side effects such as the instantiation of class template - specializations and function template specializations, the generation of - implicitly-defined functions, and so on. Such side effects are not in the ``immediate - context'' and can result in the program being ill-formed. -\end{tailnote} -& - \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, - or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_copy_assignable}% -\tcode{template}\br - \tcode{struct is_copy_assignable;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_assignable_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, - or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_move_assignable}% -\tcode{template}\br - \tcode{struct is_move_assignable;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_assignable_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, - or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_swappable_with}% -\tcode{template}\br - \tcode{struct is_swappable_with;} & - The expressions \tcode{swap(declval(), declval())} and - \tcode{swap(declval(), declval())} are each well-formed - when treated as an unevaluated operand\iref{term.unevaluated.operand} - in an overload-resolution context - for swappable values\iref{swappable.requirements}. - Access checking is performed as if in a context - unrelated to \tcode{T} and \tcode{U}. - Only the validity of the immediate context - of the \tcode{swap} expressions is considered. - \begin{tailnote} - The compilation of the expressions can result in side effects - such as the instantiation of class template specializations and - function template specializations, - the generation of implicitly-defined functions, and so on. - Such side effects are not in the ``immediate context'' and - can result in the program being ill-formed. - \end{tailnote} -& - \tcode{T} and \tcode{U} shall be complete types, - \cv{}~\keyword{void}, or - arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_swappable}% -\tcode{template}\br - \tcode{struct is_swappable;} & - For a referenceable type \tcode{T}, - the same result as \tcode{is_swappable_with_v}, - otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or - an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_destructible}% -\tcode{template}\br - \tcode{struct is_destructible;} & - Either \tcode{T} is a reference type, - or \tcode{T} is a complete object type - for which the expression - \tcode{declval().\~U()} - is well-formed - when treated as an unevaluated operand\iref{term.unevaluated.operand}, - where \tcode{U} is - \tcode{remove_all_extents_t}. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, - or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_constructible}% -\tcode{template}\br - \keyword{struct}\br - \tcode{is_trivially_constructible;} & - \tcode{is_constructible_v} is \tcode{true} and the variable - definition for \tcode{is_constructible}, as defined below, is known to call - no operation that is not trivial\iref{term.trivial.type,special}. & - \tcode{T} and all types in the template parameter pack \tcode{Args} shall be complete types, - \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_default_constructible}% -\tcode{template}\br - \tcode{struct is_trivially_default_constructible;} & - \tcode{is_trivially_constructible_v} is \tcode{true}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_copy_constructible}% -\tcode{template}\br - \tcode{struct is_trivially_copy_constructible;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_trivially_constructible_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_move_constructible}% -\tcode{template}\br - \tcode{struct is_trivially_move_constructible;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_trivially_constructible_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_assignable}% -\tcode{template}\br - \tcode{struct is_trivially_assignable;} & - \tcode{is_assignable_v} is \tcode{true} and the assignment, as defined by - \tcode{is_assignable}, is known to call no operation that is not - trivial\iref{term.trivial.type,special}. & - \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, - or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_copy_assignable}% -\tcode{template}\br - \tcode{struct is_trivially_copy_assignable;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_trivially_assignable_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_move_assignable}% -\tcode{template}\br - \tcode{struct is_trivially_move_assignable;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_trivially_assignable_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_trivially_destructible}% -\tcode{template}\br - \tcode{struct is_trivially_destructible;} & - \tcode{is_destructible_v} is \tcode{true} and - \tcode{remove_all_extents_t} is either a non-class type or - a class type with a trivial destructor. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_constructible}% -\tcode{template}\br - \tcode{struct is_nothrow_constructible;} & - \tcode{is_constructible_v} is \tcode{true} - and the - variable definition for \tcode{is_constructible}, as defined below, is known not to - throw any exceptions\iref{expr.unary.noexcept}. - & - \tcode{T} and all types in the template parameter pack \tcode{Args} - shall be complete types, \cv{}~\keyword{void}, - or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_default_constructible}% -\tcode{template}\br - \tcode{struct is_nothrow_default_constructible;} & - \tcode{is_nothrow_constructible_v} is \tcode{true}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_copy_constructible}% -\tcode{template}\br - \tcode{struct is_nothrow_copy_constructible;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_nothrow_constructible_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_move_constructible}% -\tcode{template}\br - \tcode{struct is_nothrow_move_constructible;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_nothrow_constructible_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_assignable}% -\tcode{template}\br - \tcode{struct is_nothrow_assignable;} & - \tcode{is_assignable_v} is \tcode{true} and the assignment is known not to - throw any exceptions\iref{expr.unary.noexcept}. & - \tcode{T} and \tcode{U} shall be complete types, \cv{}~\keyword{void}, - or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_copy_assignable}% -\tcode{template}\br - \tcode{struct is_nothrow_copy_assignable;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_nothrow_assignable_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_move_assignable}% -\tcode{template}\br - \tcode{struct is_nothrow_move_assignable;} & - For a referenceable type \tcode{T}, the same result as - \tcode{is_nothrow_assignable_v}, otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_swappable_with}% -\tcode{template}\br - \tcode{struct is_nothrow_swappable_with;} & - \tcode{is_swappable_with_v} is \tcode{true} and - each \tcode{swap} expression of the definition of - \tcode{is_swappable_with} is known not to throw - any exceptions\iref{expr.unary.noexcept}. & - \tcode{T} and \tcode{U} shall be complete types, - \cv{}~\keyword{void}, or - arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_swappable}% -\tcode{template}\br - \tcode{struct is_nothrow_swappable;} & - For a referenceable type \tcode{T}, - the same result as \tcode{is_nothrow_swappable_with_v}, - otherwise \tcode{false}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or - an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_destructible}% -\tcode{template}\br - \tcode{struct is_nothrow_destructible;} & - \tcode{is_destructible_v} is \tcode{true} and the indicated destructor is known - not to throw any exceptions\iref{expr.unary.noexcept}. & - \tcode{T} shall be a complete type, - \cv{}~\keyword{void}, or an array of unknown - bound. \\ \rowsep - -\indexlibraryglobal{has_virtual_destructor}% -\tcode{template}\br - \tcode{struct has_virtual_destructor;} & - \tcode{T} has a virtual destructor\iref{class.dtor} & - If \tcode{T} is a non-union class type, \tcode{T} shall be a complete type. \\ \rowsep - -\indexlibraryglobal{has_unique_object_representations}% -\tcode{template}\br - \tcode{struct has_unique_object_representations;} & - For an array type \tcode{T}, the same result as - \tcode{has_unique_object_representations_v>}, - otherwise \seebelow. & - \tcode{T} shall be a complete type, \cv{}~\keyword{void}, or - an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{reference_constructs_from_temporary}% -\tcode{template}\br - \tcode{struct reference_constructs_from_temporary;} & - \tcode{conjunction_v, is_constructible>} - is \tcode{true}, and - the initialization \tcode{T t(\exposidnc{VAL});} binds \tcode{t} to - a temporary object whose lifetime is extended\iref{class.temporary}. & - \tcode{T} and \tcode{U} shall be - complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{reference_converts_from_temporary}% -\tcode{template}\br - \tcode{struct reference_converts_from_temporary;} & - \tcode{conjunction_v, is_convertible>} is \tcode{true}, - and the initialization \tcode{T t = \exposidnc{VAL};} binds \tcode{t} to - a temporary object whose lifetime is extended\iref{class.temporary}. & - \tcode{T} and \tcode{U} shall be - complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep - -\end{libreqtab3b} - -\pnum -\begin{example} -\begin{codeblock} -is_const_v // \tcode{true} -is_const_v // \tcode{false} -is_const_v // \tcode{false} -is_const_v // \tcode{false} -is_const_v // \tcode{true} -\end{codeblock} -\end{example} - -\pnum -\begin{example} -\begin{codeblock} -remove_const_t // \tcode{volatile int} -remove_const_t // \tcode{const int*} -remove_const_t // \tcode{const int\&} -remove_const_t // \tcode{int[3]} -\end{codeblock} -\end{example} - -\pnum -\begin{example} -\begin{codeblock} -// Given: -struct P final { }; -union U1 { }; -union U2 final { }; - -// the following assertions hold: -static_assert(!is_final_v); -static_assert(is_final_v

); -static_assert(!is_final_v); -static_assert(is_final_v); -\end{codeblock} -\end{example} - -\indexlibraryglobal{is_constructible}% -\pnum -The predicate condition for a template specialization -\tcode{is_constructible} shall be satisfied if and only if the -following variable definition would be well-formed for some invented variable \tcode{t}: - -\begin{codeblock} -T t(declval()...); -\end{codeblock} - -\begin{note} -These tokens are never interpreted as a function declaration. -\end{note} -Access checking is performed as if in a context unrelated to \tcode{T} -and any of the \tcode{Args}. Only the validity of the immediate context of the -variable initialization is considered. -\begin{note} -The evaluation of the -initialization can result in side effects such as the instantiation of class -template specializations and function template specializations, the generation -of implicitly-defined functions, and so on. Such side effects are not in the -``immediate context'' and can result in the program being ill-formed. -\end{note} - -\indexlibraryglobal{has_unique_object_representations}% -\pnum -The predicate condition for a template specialization -\tcode{has_unique_object_representations} -shall be satisfied if and only if: -\begin{itemize} -\item \tcode{T} is trivially copyable, and -\item any two objects of type \tcode{T} with the same value -have the same object representation, where -two objects of array or non-union class type are considered to have the same value -if their respective sequences of direct subobjects have the same values, and -two objects of union type are considered to have the same value -if they have the same active member and the corresponding members have the same value. -\end{itemize} -The set of scalar types for which this condition holds is -\impldef{which scalar types have unique object representations}. -\begin{note} -If a type has padding bits, the condition does not hold; -otherwise, the condition holds true for integral types. -\end{note} - -\rSec2[meta.unary.prop.query]{Type property queries} - -\pnum -This subclause contains templates that may be used to query -properties of types at compile time. - -\begin{libreqtab2a}{Type property queries}{meta.unary.prop.query} -\\ \topline -\lhdr{Template} & \rhdr{Value} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Value} \\ \capsep -\endhead - -\indexlibraryglobal{alignment_of}% -\tcode{template\br - struct alignment_of;} & - \tcode{alignof(T)}.\br - \mandates - \tcode{alignof(T)} is a valid expression\iref{expr.alignof} \\ \rowsep - -\indexlibraryglobal{rank}% -\tcode{template\br - struct rank;} & - If \tcode{T} names an array type, an integer value representing - the number of dimensions of \tcode{T}; otherwise, 0. \\ \rowsep - -\indexlibraryglobal{extent}% -\tcode{template\br - struct extent;} & - If \tcode{T} is not an array type, or if it has rank less - than or equal to \tcode{I}, or if \tcode{I} is 0 and \tcode{T} - has type ``array of unknown bound of \tcode{U}'', then - 0; otherwise, the bound\iref{dcl.array} of the $\tcode{I}^\text{th}$ dimension of -\tcode{T}, where indexing of \tcode{I} is zero-based \\ -\end{libreqtab2a} - -\pnum -Each of these templates shall be a \oldconcept{UnaryTypeTrait}\iref{meta.rqmts} with a -base characteristic of \tcode{integral_constant}. - -\pnum -\begin{example} -\begin{codeblock} -// the following assertions hold: -assert(rank_v == 0); -assert(rank_v == 1); -assert(rank_v == 2); -\end{codeblock} -\end{example} - -\pnum -\begin{example} -\begin{codeblock} -// the following assertions hold: -assert(extent_v == 0); -assert(extent_v == 2); -assert(extent_v == 2); -assert(extent_v == 0); -assert((extent_v) == 0); -assert((extent_v) == 0); -assert((extent_v) == 4); -assert((extent_v) == 4); -\end{codeblock} -\end{example} - -\rSec2[meta.rel]{Relationships between types} - -\pnum -This subclause contains templates that may be used to query -relationships between types at compile time. - -\pnum -Each of these templates shall be a -\oldconcept{BinaryTypeTrait}\iref{meta.rqmts} -with a base characteristic of -\tcode{true_type} if the corresponding condition is true, otherwise -\tcode{false_type}. - -\begin{libreqtab3f}{Type relationship predicates}{meta.rel} -\\ \topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep -\endhead -\tcode{template}\br - \tcode{struct is_same;} & - \tcode{T} and \tcode{U} name the same type with the same cv-qualifications & \\ \rowsep - -\indexlibraryglobal{is_base_of}% -\tcode{template}\br - \tcode{struct is_base_of;} & - \tcode{Base} is a base class of \tcode{Derived}\iref{class.derived} - without regard to cv-qualifiers - or \tcode{Base} and \tcode{Derived} are not unions and - name the same class type - without regard to cv-qualifiers & - If \tcode{Base} and - \tcode{Derived} are non-union class types and are -not possibly cv-qualified versions of the same type, - \tcode{Derived} shall be a complete - type. - \begin{tailnote} -Base classes that are private, protected, or ambiguous - are, nonetheless, base classes. -\end{tailnote} -\\ \rowsep - -\indexlibraryglobal{is_convertible}% -\tcode{template}\br - \tcode{struct is_convertible;} & - \seebelow & - \tcode{From} and \tcode{To} shall be complete types, - \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_convertible}% -\tcode{template}\br - \tcode{struct is_nothrow_convertible;} & - \tcode{is_convertible_v} is \tcode{true} and - the conversion, as defined by \tcode{is_convertible}, - is known not to throw any exceptions\iref{expr.unary.noexcept} & - \tcode{From} and \tcode{To} shall be complete types, - \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_layout_compatible}% -\tcode{template}\br - \tcode{struct is_layout_compatible;} & - \tcode{T} and \tcode{U} are layout-compatible\iref{term.layout.compatible.type} & - \tcode{T} and \tcode{U} shall be complete types, - \cv{}~\keyword{void}, - or arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_pointer_interconvertible_base_of}% -\tcode{template}\br - \tcode{struct is_pointer_interconvertible_base_of;} & - \tcode{Derived} is unambiguously derived from \tcode{Base} - without regard to cv-qualifiers, - and each object of type \tcode{Derived} - is pointer-interconvertible\iref{basic.compound} with - its \tcode{Base} subobject, - or \tcode{Base} and \tcode{Derived} are not unions - and name the same class type - without regard to cv-qualifiers. & - If \tcode{Base} and \tcode{Derived} are non-union class types - and are not (possibly cv-qualified versions of) the same type, - \tcode{Derived} shall be a complete type. \\ \rowsep - -\indexlibraryglobal{is_invocable}% -\tcode{template}\br - \tcode{struct is_invocable;} & - The expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} - is well-formed when treated as an unevaluated operand\iref{term.unevaluated.operand} & - \tcode{Fn} and all types in the template parameter pack \tcode{ArgTypes} - shall be complete types, \cv{}~\keyword{void}, or - arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_invocable_r}% -\tcode{template}\br - \tcode{struct is_invocable_r;} & - The expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} - is well-formed when treated as an unevaluated operand & - \tcode{Fn}, \tcode{R}, and all types in the template parameter pack \tcode{ArgTypes} - shall be complete types, \cv{}~\keyword{void}, or - arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_invocable}% -\tcode{template}\br - \tcode{struct is_nothrow_invocable;} & - \tcode{is_invocable_v<}\br\tcode{Fn, ArgTypes...>} is \tcode{true} and - the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} - is known not to throw any exceptions\iref{expr.unary.noexcept} & - \tcode{Fn} and all types in the template parameter pack \tcode{ArgTypes} - shall be complete types, \cv{}~\keyword{void}, or - arrays of unknown bound. \\ \rowsep - -\indexlibraryglobal{is_nothrow_invocable_r}% -\tcode{template}\br - \tcode{struct is_nothrow_invocable_r;} & - \tcode{is_invocable_r_v<}\br\tcode{R, Fn, ArgTypes...>} is \tcode{true} and - the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} - is known not to throw any exceptions\iref{expr.unary.noexcept} & - \tcode{Fn}, \tcode{R}, and all types in the template parameter pack \tcode{ArgTypes} - shall be complete types, \cv{}~\keyword{void}, or - arrays of unknown bound. \\ -\end{libreqtab3f} - -\pnum -For the purpose of defining the templates in this subclause, -a function call expression \tcode{declval()} for any type \tcode{T} -is considered to be a trivial\iref{term.trivial.type,special} function call -that is not an odr-use\iref{term.odr.use} of \tcode{declval} -in the context of the corresponding definition -notwithstanding the restrictions of~\ref{declval}. - -\pnum -\begin{example} -\begin{codeblock} -struct B {}; -struct B1 : B {}; -struct B2 : B {}; -struct D : private B1, private B2 {}; - -is_base_of_v // \tcode{true} -is_base_of_v // \tcode{true} -is_base_of_v // \tcode{true} -is_base_of_v // \tcode{true} -is_base_of_v // \tcode{false} -is_base_of_v // \tcode{false} -is_base_of_v // \tcode{false} -is_base_of_v // \tcode{false} -\end{codeblock} -\end{example} - -\indexlibraryglobal{is_convertible}% -\pnum -The predicate condition for a template specialization \tcode{is_convertible} -shall be satisfied if and only if the return expression in the following code would be -well-formed, including any implicit conversions to the return type of the function: - -\begin{codeblock} -To test() { - return declval(); -} -\end{codeblock} - -\begin{note} -This requirement gives well-defined results for reference types, -array types, function types, and \cv{}~\keyword{void}. -\end{note} -Access checking is performed -in a context unrelated to \tcode{To} and \tcode{From}. Only the validity of -the immediate context of the \grammarterm{expression} of the \tcode{return} statement\iref{stmt.return} -(including initialization of the returned object or reference) is considered. -\begin{note} -The -initialization can result in side effects such as the -instantiation of class template specializations and function template -specializations, the generation of implicitly-defined functions, and so on. Such -side effects are not in the ``immediate context'' and can result in the program -being ill-formed. -\end{note} - -\rSec2[meta.trans]{Transformations between types} - -\rSec3[meta.trans.general]{General} -\pnum -Subclause \ref{meta.trans} contains templates that may be used to transform one -type to another following some predefined rule. - -\pnum -Each of the templates in \ref{meta.trans} shall be a -\oldconcept{TransformationTrait}\iref{meta.rqmts}. - -\rSec3[meta.trans.cv]{Const-volatile modifications} - -\begin{libreqtab2a}{Const-volatile modifications}{meta.trans.cv} -\\ \topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endhead - -\indexlibraryglobal{remove_const}% -\tcode{template\br - struct remove_const;} & - The member typedef \tcode{type} names - the same type as \tcode{T} - except that any top-level const-qualifier has been removed. - \begin{tailexample} -\tcode{remove_const_t} evaluates - to \tcode{volatile int}, whereas \tcode{remove_const_t} evaluates to - \tcode{const int*}. -\end{tailexample} -\\ \rowsep - -\indexlibraryglobal{remove_volatile}% -\tcode{template\br - struct remove_volatile;} & - The member typedef \tcode{type} names - the same type as \tcode{T} - except that any top-level volatile-qualifier has been removed. - \begin{tailexample} -\tcode{remove_volatile_t} - evaluates to \tcode{const int}, - whereas \tcode{remove_volatile_t} evaluates to \tcode{volatile int*}. - \end{tailexample} -\\ \rowsep - -\indexlibraryglobal{remove_cv}% -\tcode{template\br - struct remove_cv;} & - The member typedef \tcode{type} shall be the same as \tcode{T} - except that any top-level cv-qualifier has been removed. - \begin{tailexample} -\tcode{remove_cv_t} - evaluates to \tcode{int}, whereas \tcode{remove_cv_t} - evaluates to \tcode{const volatile int*}. -\end{tailexample} -\\ \rowsep - -\indexlibraryglobal{add_const}% -\tcode{template\br - struct add_const;} & - If \tcode{T} is a reference, function, or top-level const-qualified - type, then \tcode{type} names - the same type as \tcode{T}, otherwise - \tcode{T const}. \\ \rowsep - -\indexlibraryglobal{add_volatile}% -\tcode{template\br - struct add_volatile;} & - If \tcode{T} is a reference, function, or top-level volatile-qualified - type, then \tcode{type} names - the same type as \tcode{T}, otherwise - \tcode{T volatile}. \\ \rowsep - -\indexlibraryglobal{add_cv}% -\tcode{template\br - struct add_cv;} & - The member typedef \tcode{type} names - the same type as - \tcode{add_const_t>}. \\ -\end{libreqtab2a} - -\rSec3[meta.trans.ref]{Reference modifications} - -\begin{libreqtab2a}{Reference modifications}{meta.trans.ref} -\\ \topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endhead - -\indexlibraryglobal{remove_reference}% -\tcode{template\br - struct remove_reference;} & - If \tcode{T} has type ``reference to \tcode{T1}'' then the - member typedef \tcode{type} names \tcode{T1}; - otherwise, \tcode{type} names \tcode{T}.\\ \rowsep - -\indexlibraryglobal{add_lvalue_reference}% -\tcode{template\br - struct add_lvalue_reference;} & - If \tcode{T} names a referenceable type\iref{defns.referenceable} then - the member typedef \tcode{type} names \tcode{T\&}; - otherwise, \tcode{type} names \tcode{T}. - \begin{tailnote} - This rule reflects the semantics of reference collapsing\iref{dcl.ref}. - \end{tailnote} -\\ \rowsep - -\indexlibraryglobal{add_rvalue_reference}% -\tcode{template}\br - \tcode{struct add_rvalue_reference;} & - If \tcode{T} names a referenceable type then - the member typedef \tcode{type} names \tcode{T\&\&}; - otherwise, \tcode{type} names \tcode{T}. - \begin{tailnote} -This rule reflects the semantics of reference collapsing\iref{dcl.ref}. - For example, when a type \tcode{T} names a type \tcode{T1\&}, the type - \tcode{add_rvalue_reference_t} is not an rvalue reference. - \end{tailnote} -\\ -\end{libreqtab2a} - -\rSec3[meta.trans.sign]{Sign modifications} -\begin{libreqtab2a}{Sign modifications}{meta.trans.sign} -\\ \topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endhead - -\indexlibraryglobal{make_signed}% -\tcode{template}\br - \tcode{struct make_signed;} & - If \tcode{T} names a (possibly cv-qualified) signed integer - type\iref{basic.fundamental} then the member typedef - \tcode{type} names the type \tcode{T}; otherwise, - if \tcode{T} names a (possibly cv-qualified) unsigned integer - type then \tcode{type} names the corresponding - signed integer type, with the same cv-qualifiers as \tcode{T}; - otherwise, \tcode{type} names the signed integer type with smallest - rank\iref{conv.rank} for which - \tcode{sizeof(T) == sizeof(type)}, with the same - cv-qualifiers as \tcode{T}.\br - \mandates \tcode{T} is an integral or enumeration type - other than \cv~\tcode{bool}.\\ \rowsep - -\indexlibraryglobal{make_unsigned}% -\tcode{template}\br - \tcode{struct make_unsigned;} & - If \tcode{T} names a (possibly cv-qualified) unsigned integer - type\iref{basic.fundamental} then the member typedef - \tcode{type} names the type \tcode{T}; otherwise, - if \tcode{T} names a (possibly cv-qualified) signed integer - type then \tcode{type} names the corresponding - unsigned integer type, with the same cv-qualifiers as \tcode{T}; - otherwise, \tcode{type} names the unsigned integer type with smallest - rank\iref{conv.rank} for which - \tcode{sizeof(T) == sizeof(type)}, with the same - cv-qualifiers as \tcode{T}.\br - \mandates \tcode{T} is an integral or enumeration type - other than \cv~\tcode{bool}.\\ -\end{libreqtab2a} - -\rSec3[meta.trans.arr]{Array modifications} -\begin{libreqtab2a}{Array modifications}{meta.trans.arr} -\\ \topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endhead - -\indexlibraryglobal{remove_extent}% -\tcode{template\br - struct remove_extent;} & - If \tcode{T} names a type ``array of \tcode{U}'', - the member typedef \tcode{type} shall - be \tcode{U}, otherwise \tcode{T}. - \begin{tailnote} -For multidimensional arrays, only the first array dimension is - removed. For a type ``array of \tcode{const U}'', the resulting type is - \tcode{const U}. -\end{tailnote} -\\ \rowsep - -\indexlibraryglobal{remove_all_extents}% -\tcode{template\br - struct remove_all_extents;} & - If \tcode{T} is ``multi-dimensional array of \tcode{U}'', the resulting member - typedef \tcode{type} is \tcode{U}, otherwise \tcode{T}. \\ -\end{libreqtab2a} - -\pnum -\begin{example} -\begin{codeblock} -// the following assertions hold: -assert((is_same_v, int>)); -assert((is_same_v, int>)); -assert((is_same_v, int[3]>)); -assert((is_same_v, int[3]>)); -\end{codeblock} -\end{example} - -\pnum -\begin{example} -\begin{codeblock} -// the following assertions hold: -assert((is_same_v, int>)); -assert((is_same_v, int>)); -assert((is_same_v, int>)); -assert((is_same_v, int>)); -\end{codeblock} -\end{example} - -\rSec3[meta.trans.ptr]{Pointer modifications} -\begin{libreqtab2a}{Pointer modifications}{meta.trans.ptr} -\\ \topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endhead - -\indexlibraryglobal{remove_pointer}% -\tcode{template\br - struct remove_pointer;} & - If \tcode{T} has type ``(possibly cv-qualified) pointer - to \tcode{T1}'' then the member typedef \tcode{type} - names \tcode{T1}; otherwise, it names \tcode{T}.\\ \rowsep - -\indexlibraryglobal{add_pointer}% -\tcode{template\br - struct add_pointer;} & - If \tcode{T} names a referenceable type\iref{defns.referenceable} or a - \cv{}~\keyword{void} type then - the member typedef \tcode{type} names the same type as - \tcode{remove_reference_t*}; - otherwise, \tcode{type} names \tcode{T}. \\ -\end{libreqtab2a} - -\rSec3[meta.trans.other]{Other transformations} - -\begin{libreqtab2a}{Other transformations}{meta.trans.other} -\\ \topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endfirsthead -\continuedcaption\\ -\topline -\lhdr{Template} & \rhdr{Comments} \\ \capsep -\endhead - -\indexlibraryglobal{type_identity}% -\tcode{template\br - struct type_identity;} - & - The member typedef \tcode{type} names the type \tcode{T}. \\ \rowsep - -\indexlibraryglobal{remove_cvref}% -\tcode{template\br struct remove_cvref;} - & - The member typedef \tcode{type} names the same type as - \tcode{remove_cv_t>}. - \\ \rowsep - -\indexlibraryglobal{decay}% -\tcode{template\br struct decay;} - & - Let \tcode{U} be \tcode{remove_reference_t}. If \tcode{is_array_v} is - \tcode{true}, the member typedef \tcode{type} equals - \tcode{remove_extent_t*}. If \tcode{is_function_v} is \tcode{true}, - the member typedef \tcode{type} equals \tcode{add_pointer_t}. Otherwise - the member typedef \tcode{type} equals \tcode{remove_cv_t}. -\begin{tailnote} -This behavior is similar to the lvalue-to-rvalue\iref{conv.lval}, -array-to-pointer\iref{conv.array}, and function-to-pointer\iref{conv.func} -conversions applied when an lvalue is used as an rvalue, but also -strips cv-qualifiers from class types in order to more closely model by-value -argument passing. -\end{tailnote} - \\ \rowsep - -\indexlibraryglobal{enable_if}% -\tcode{template} \tcode{struct enable_if;} - & - If \tcode{B} is \tcode{true}, the member typedef \tcode{type} - shall equal \tcode{T}; otherwise, there shall be no member - \tcode{type}. \\ \rowsep - -\tcode{template}\br - \tcode{struct conditional;} - & - If \tcode{B} is \tcode{true}, the member typedef \tcode{type} shall equal \tcode{T}. - If \tcode{B} is \tcode{false}, the member typedef \tcode{type} shall equal \tcode{F}. \\ \rowsep - - \tcode{template} \tcode{struct common_type;} - & - Unless this trait is specialized (as specified in Note B, below), - the member \tcode{type} is defined or omitted as specified in Note A, below. - If it is omitted, there shall be no member \tcode{type}. - Each type in the template parameter pack \tcode{T} shall be - complete, \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep - -\indexlibraryglobal{basic_common_reference}% -\tcode{template class,} - \hspace*{2ex}\tcode{template class>} - \keyword{struct} - \hspace*{2ex}\tcode{basic_common_reference;} - & - Unless this trait is specialized (as specified in Note D, below), - there shall be no member \tcode{type}. \\ \rowsep - -\indexlibraryglobal{common_reference}% -\tcode{template} \tcode{struct common_reference;} - & - The member \grammarterm{typedef-name} \tcode{type} is defined or omitted - as specified in Note C, below. Each type in the parameter pack \tcode{T} shall - be complete or \cv{} \keyword{void}. \\ \rowsep - -\indexlibraryglobal{underlying_type}% -\tcode{template}\br - \tcode{struct underlying_type;} - & - If \tcode{T} is an enumeration type, the member typedef \tcode{type} names - the underlying type of \tcode{T}\iref{dcl.enum}; - otherwise, there is no member \tcode{type}.\br - \mandates \tcode{T} is not an incomplete enumeration type. \\ \rowsep - -\tcode{template}\br - \tcode{struct invoke_result;} - & - If the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)} - is well-formed when treated as an unevaluated operand\iref{term.unevaluated.operand}, - the member typedef \tcode{type} names the type - \tcode{decltype(\placeholdernc{INVOKE}(declval(), declval()...))}; - otherwise, there shall be no member \tcode{type}. Access checking is - performed as if in a context unrelated to \tcode{Fn} and - \tcode{ArgTypes}. Only the validity of the immediate context of the - expression is considered. - \begin{note} - The compilation of the expression can result in side effects such as - the instantiation of class template specializations and function - template specializations, the generation of implicitly-defined - functions, and so on. Such side effects are not in the ``immediate - context'' and can result in the program being ill-formed. - \end{note} - \expects \tcode{Fn} and all types in the template parameter pack \tcode{ArgTypes} - are complete types, \cv{}~\keyword{void}, or arrays of - unknown bound.\\ \rowsep - -\indexlibraryglobal{unwrap_reference}% -\tcode{template} \tcode{struct unwrap_reference;} - & - If \tcode{T} is - a specialization \tcode{reference_wrapper} for some type \tcode{X}, - the member typedef \tcode{type} of \tcode{unwrap_reference} is \tcode{X\&}, - otherwise it is \tcode{T}. \\ \rowsep - -\indexlibraryglobal{unwrap_ref_decay}% -\tcode{template} \tcode{unwrap_ref_decay;} - & - The member typedef \tcode{type} of \tcode{unwrap_ref_decay} - denotes the type \tcode{unwrap_reference_t>}.\\ -\end{libreqtab2a} - -\pnum -In addition to being available via inclusion -of the \tcode{} header, the templates -\tcode{unwrap_reference}, -\tcode{unwrap_ref_decay}, -\tcode{unwrap_reference_t}, and -\tcode{unwrap_ref_decay_t} -are available -when the header \tcode{}\iref{functional.syn} is included. - -\indexlibraryglobal{common_type}% -\pnum -Let: -\begin{itemize} -\item \tcode{\placeholdernc{CREF}(A)} be - \tcode{add_lvalue_reference_t{}>}, -\item \tcode{\placeholdernc{XREF}(A)} denote a unary alias template \tcode{T} - such that \tcode{T} denotes the same type as \tcode{U} with the addition - of \tcode{A}'s cv and reference qualifiers, for a non-reference cv-unqualified - type \tcode{U}, -\item \tcode{\placeholdernc{COPYCV}(FROM, TO)} be an alias for type \tcode{TO} - with the addition of \tcode{FROM}'s top-level cv-qualifiers, - \begin{example} - \tcode{\placeholdernc{COPYCV}(const int, volatile short)} is an alias for - \tcode{const volatile short}. - \end{example} -\item \tcode{\placeholdernc{COND-RES}(X, Y)} be - \tcode{decltype(false ?\ declval()() :\ declval()())}. -\end{itemize} -Given types \tcode{A} and \tcode{B}, -let \tcode{X} be \tcode{remove_reference_t}, -let \tcode{Y} be \tcode{remove_reference_t}, and -let \tcode{\placeholdernc{COMMON-\brk{}REF}(A, B)} be: -\begin{itemize} -\item If \tcode{A} and \tcode{B} are both lvalue reference types, - \tcode{\placeholdernc{COMMON-REF}(A, B)} is - \tcode{\placeholdernc{COND-RES}(\placeholdernc{COPYCV}(X, Y) \&, - \placeholdernc{COPYCV}(\brk{}Y, X) \&)} if that type exists - and is a reference type. -\item Otherwise, let \tcode{C} be - \tcode{remove_reference_t<\placeholdernc{COMMON-REF}(X\&, Y\&)>\&\&}. - If \tcode{A} and \tcode{B} are both rvalue reference types, - \tcode{C} is well-formed, and - \tcode{is_convertible_v \&\& is_convertible_v} is \tcode{true}, - then \tcode{\placeholdernc{COMMON-REF}(A, B)} is \tcode{C}. -\item Otherwise, let \tcode{D} be - \tcode{\placeholdernc{COMMON-REF}(const X\&, Y\&)}. If \tcode{A} is an rvalue - reference and \tcode{B} is an lvalue reference and \tcode{D} is - well-formed and \tcode{is_convertible_v} is - \tcode{true}, then \tcode{\placeholdernc{COMMON-REF}(A, B)} is \tcode{D}. -\item Otherwise, if \tcode{A} is an lvalue reference and \tcode{B} - is an rvalue reference, then \tcode{\placeholdernc{COMMON-REF}(A, B)} is - \tcode{\placeholdernc{COMMON-REF}(B, A)}. -\item Otherwise, \tcode{\placeholdernc{COMMON-REF}(A, B)} is ill-formed. -\end{itemize} - -If any of the types computed above is ill-formed, then -\tcode{\placeholdernc{COMMON-REF}(A, B)} is ill-formed. - -\pnum -Note A: -For the \tcode{common_type} trait applied to a template parameter pack \tcode{T} of types, -the member \tcode{type} shall be either defined or not present as follows: - -\begin{itemize} -\item If \tcode{sizeof...(T)} is zero, there shall be no member \tcode{type}. - -\item If \tcode{sizeof...(T)} is one, let \tcode{T0} denote the sole type -constituting the pack \tcode{T}. -The member \grammarterm{typedef-name} \tcode{type} shall denote the same -type, if any, as \tcode{common_type_t}; -otherwise there shall be no member \tcode{type}. - -\item If \tcode{sizeof...(T)} is two, -let the first and second types constituting \tcode{T} be denoted -by \tcode{T1} and \tcode{T2}, respectively, and -let \tcode{D1} and \tcode{D2} denote -the same types as \tcode{decay_t} and \tcode{decay_t}, respectively. - \begin{itemize} - \item If \tcode{is_same_v} is \tcode{false} or - \tcode{is_same_v} is \tcode{false}, - let \tcode{C} denote the same type, if any, - as \tcode{common_type_t}. - \item - \begin{note} - None of the following will apply if there is a specialization - \tcode{common_type}. - \end{note} - \item Otherwise, if -\begin{codeblock} -decay_t() : declval())> -\end{codeblock} - denotes a valid type, let \tcode{C} denote that type. - \item Otherwise, if - \tcode{\placeholdernc{COND-RES}(\placeholdernc{CREF}(D1), - \placeholdernc{CREF}(D2))} - denotes a type, let \tcode{C} denote the type - \tcode{decay_t<\placeholdernc{COND-RES}(\placeholdernc{CREF}(D1), - \placeholdernc{CREF}(D2))>}. - \end{itemize} -In either case, the member \grammarterm{typedef-name} \tcode{type} shall denote -the same type, if any, as \tcode{C}. -Otherwise, there shall be no member \tcode{type}. - -\item If \tcode{sizeof...(T)} is greater than two, -let \tcode{T1}, \tcode{T2}, and \tcode{R}, respectively, -denote the first, second, and (pack of) remaining types constituting \tcode{T}. -Let \tcode{C} denote the same type, if any, as \tcode{common_type_t}. -If there is such a type \tcode{C}, the member \grammarterm{typedef-name} \tcode{type} -shall denote the same type, if any, as \tcode{common_type_t}. -Otherwise, there shall be no member \tcode{type}. -\end{itemize} - -\pnum -Note B: Notwithstanding the provisions of \ref{meta.type.synop}, and -pursuant to \ref{namespace.std}, -a program may specialize \tcode{common_type} -for types \tcode{T1} and \tcode{T2} such that -\tcode{is_same_v>} and -\tcode{is_same_v>} are each \tcode{true}. -\begin{note} -Such specializations are needed when only explicit conversions -are desired between the template arguments. -\end{note} -Such a specialization need not have a member named \tcode{type}, -but if it does, -the \grammarterm{qualified-id} \tcode{common_type::type} shall denote -a cv-unqualified non-reference type -to which each of the types \tcode{T1} and \tcode{T2} is explicitly convertible. -Moreover, \tcode{common_type_t} shall denote -the same type, if any, as does \tcode{common_type_t}. -No diagnostic is required for a violation of this Note's rules. - -\pnum -Note C: For the \tcode{common_reference} trait applied to a parameter pack -\tcode{T} of types, the member \tcode{type} shall be either defined or not -present as follows: -\begin{itemize} -\item If \tcode{sizeof...(T)} is zero, there shall be no member \tcode{type}. - -\item Otherwise, if \tcode{sizeof...(T)} is one, let \tcode{T0} denote the sole - type in the pack \tcode{T}. The member typedef \tcode{type} shall denote the - same type as \tcode{T0}. - -\item Otherwise, if \tcode{sizeof...(T)} is two, let \tcode{T1} and \tcode{T2} - denote the two types in the pack \tcode{T}. Then - \begin{itemize} - \item If \tcode{T1} and \tcode{T2} are reference types and - \tcode{\placeholdernc{COMMON-REF}(T1, T2)} is well-formed, then the member - typedef \tcode{type} denotes that type. - - \item Otherwise, if - \tcode{basic_common_reference, remove_cvref_t, - \brk{}\placeholdernc{XREF}(\brk{}T1), \placeholdernc{XREF}(T2)>::type} - is well-formed, then the member typedef \tcode{type} denotes that type. - - \item Otherwise, if \tcode{\placeholdernc{COND-RES}(T1, T2)} is well-formed, - then the member typedef \tcode{type} denotes that type. - - \item Otherwise, if \tcode{common_type_t} is well-formed, then the - member typedef \tcode{type} denotes that type. - - \item Otherwise, there shall be no member \tcode{type}. - \end{itemize} - -\item Otherwise, if \tcode{sizeof...(T)} is greater than two, let \tcode{T1}, - \tcode{T2}, and \tcode{Rest}, respectively, denote the first, second, and - (pack of) remaining types comprising \tcode{T}. Let \tcode{C} be the type - \tcode{common_reference_t}. Then: - \begin{itemize} - \item If there is such a type \tcode{C}, the member typedef \tcode{type} shall - denote the same type, if any, as \tcode{common_reference_t}. - - \item Otherwise, there shall be no member \tcode{type}. - \end{itemize} -\end{itemize} - -\pnum -Note D: Notwithstanding the provisions of \ref{meta.type.synop}, and -pursuant to \ref{namespace.std}, a program may partially specialize -\tcode{basic_common_reference} -for types \tcode{T} and \tcode{U} such that -\tcode{is_same_v>} and -\tcode{is_same_v>} are each \tcode{true}. -\begin{note} -Such specializations -can be used to influence the result of \tcode{common_reference}, and -are needed when only explicit conversions are desired -between the template arguments. -\end{note} -Such a specialization need not have a member named \tcode{type}, but if it does, -the \grammarterm{qualified-id} -\tcode{basic_common_reference::type} -shall denote a type -to which each of the types \tcode{TQual} and -\tcode{UQual} is convertible. -Moreover, \tcode{basic_common_reference::type} shall denote -the same type, if any, as does -\tcode{basic_common_reference::type}. -No diagnostic is required for a violation of these rules. - -\pnum -\begin{example} -Given these definitions: -\begin{codeblock} -using PF1 = bool (&)(); -using PF2 = short (*)(long); - -struct S { - operator PF2() const; - double operator()(char, int&); - void fn(long) const; - char data; -}; - -using PMF = void (S::*)(long) const; -using PMD = char S::*; -\end{codeblock} -the following assertions will hold: -\begin{codeblock} -static_assert(is_same_v, short>); -static_assert(is_same_v, double>); -static_assert(is_same_v, bool>); -static_assert(is_same_v, int>, void>); -static_assert(is_same_v, char&&>); -static_assert(is_same_v, const char&>); -\end{codeblock} -\end{example} - -\rSec2[meta.logical]{Logical operator traits} - -\pnum -This subclause describes type traits for applying logical operators -to other type traits. - -\indexlibraryglobal{conjunction}% -\begin{itemdecl} -template struct conjunction : @\seebelow@ { }; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The class template \tcode{conjunction} -forms the logical conjunction of its template type arguments. - -\pnum -For a specialization \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>}, -if there is a template type argument $\tcode{B}_{i}$ -for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{false}, -then instantiating \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>::value} -does not require the instantiation of \tcode{$\tcode{B}_{j}$::value} for $j > i$. -\begin{note} -This is analogous to the short-circuiting behavior of -the built-in operator \tcode{\&\&}. -\end{note} - -\pnum -Every template type argument -for which \tcode{$\tcode{B}_{i}$::value} is instantiated -shall be usable as a base class and -shall have a member \tcode{value} which -is convertible to \tcode{bool}, -is not hidden, and -is unambiguously available in the type. - -\pnum -The specialization \tcode{conjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>} -has a public and unambiguous base that is either -\begin{itemize} -\item -the first type $\tcode{B}_{i}$ in the list \tcode{true_type, $\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$} -for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{false}, or -\item -if there is no such $\tcode{B}_{i}$, the last type in the list. -\end{itemize} -\begin{note} -This means a specialization of \tcode{conjunction} -does not necessarily inherit from -either \tcode{true_type} or \tcode{false_type}. -\end{note} - -\pnum -The member names of the base class, other than \tcode{conjunction} and -\tcode{operator=}, shall not be hidden and shall be unambiguously available -in \tcode{conjunction}. -\end{itemdescr} - -\indexlibraryglobal{disjunction}% -\begin{itemdecl} -template struct disjunction : @\seebelow@ { }; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The class template \tcode{disjunction} -forms the logical disjunction of its template type arguments. - -\pnum -For a specialization \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>}, -if there is a template type argument $\tcode{B}_{i}$ -for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{true}, -then instantiating \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>::value} -does not require the instantiation of \tcode{$\tcode{B}_{j}$::value} for $j > i$. -\begin{note} -This is analogous to the short-circuiting behavior of -the built-in operator \tcode{||}. -\end{note} - -\pnum -Every template type argument -for which \tcode{$\tcode{B}_{i}$::value} is instantiated -shall be usable as a base class and -shall have a member \tcode{value} which -is convertible to \tcode{bool}, -is not hidden, and -is unambiguously available in the type. - -\pnum -The specialization \tcode{disjunction<$\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$>} -has a public and unambiguous base that is either -\begin{itemize} -\item the first type $\tcode{B}_{i}$ in the list \tcode{false_type, $\tcode{B}_{1}$, $\dotsc$, $\tcode{B}_{N}$} -for which \tcode{bool($\tcode{B}_{i}$::value)} is \tcode{true}, or -\item if there is no such $\tcode{B}_{i}$, the last type in the list. -\end{itemize} -\begin{note} -This means a specialization of \tcode{disjunction} -does not necessarily inherit from -either \tcode{true_type} or \tcode{false_type}. -\end{note} - -\pnum -The member names of the base class, -other than \tcode{disjunction} and \tcode{operator=}, -shall not be hidden and shall be unambiguously available in \tcode{disjunction}. -\end{itemdescr} - -\indexlibraryglobal{negation}% -\begin{itemdecl} -template struct negation : @\seebelow@ { }; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The class template \tcode{negation} -forms the logical negation of its template type argument. -The type \tcode{negation} -is a \oldconcept{UnaryTypeTrait} with a base characteristic of \tcode{bool_constant}. -\end{itemdescr} - -\rSec2[meta.member]{Member relationships} - -\indexlibraryglobal{is_pointer_interconvertible_with_class} -\begin{itemdecl} -template - constexpr bool is_pointer_interconvertible_with_class(M S::*m) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{S} is a complete type. - -\pnum -\returns -\tcode{true} if and only if - \tcode{S} is a standard-layout type, - \tcode{M} is an object type, - \tcode{m} is not null, - and each object \tcode{s} of type \tcode{S} - is pointer-interconvertible\iref{basic.compound} - with its subobject \tcode{s.*m}. -\end{itemdescr} - -\indexlibraryglobal{is_corresponding_member} -\begin{itemdecl} -template - constexpr bool is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{S1} and \tcode{S2} are complete types. - -\pnum -\returns -\tcode{true} if and only if - \tcode{S1} and \tcode{S2} are standard-layout struct\iref{class.prop} types, - \tcode{M1} and \tcode{M2} are object types, - \tcode{m1} and \tcode{m2} are not null, - and \tcode{m1} and \tcode{m2} point to corresponding members of - the common initial sequence\iref{class.mem} of \tcode{S1} and \tcode{S2}. -\end{itemdescr} - -\pnum -\begin{note} -The type of a pointer-to-member expression \tcode{\&C::b} -is not always a pointer to member of \tcode{C}, -leading to potentially surprising results -when using these functions in conjunction with inheritance. -\begin{example} -\begin{codeblock} -struct A { int a; }; // a standard-layout class -struct B { int b; }; // a standard-layout class -struct C: public A, public B { }; // not a standard-layout class - -static_assert( is_pointer_interconvertible_with_class( &C::b ) ); - // Succeeds because, despite its appearance, \tcode{\&C::b} has type - // ``pointer to member of \tcode{B} of type \tcode{int}''. -static_assert( is_pointer_interconvertible_with_class( &C::b ) ); - // Forces the use of class \tcode{C}, and fails. - -static_assert( is_corresponding_member( &C::a, &C::b ) ); - // Succeeds because, despite its appearance, \tcode{\&C::a} and \tcode{\&C::b} have types - // ``pointer to member of \tcode{A} of type \tcode{int}'' and - // ``pointer to member of \tcode{B} of type \tcode{int}'', respectively. -static_assert( is_corresponding_member( &C::a, &C::b ) ); - // Forces the use of class \tcode{C}, and fails. -\end{codeblock} -\end{example} -\end{note} - -\rSec2[meta.const.eval]{Constant evaluation context} -\begin{itemdecl} -constexpr bool is_constant_evaluated() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -if consteval { - return true; -} else { - return false; -} -\end{codeblock} - -\pnum -\begin{example} -\begin{codeblock} -constexpr void f(unsigned char *p, int n) { - if (std::is_constant_evaluated()) { // should not be a constexpr if statement - for (int k = 0; k} synopsis} - -\indexheader{ratio}% -\begin{codeblockdigitsep} -namespace std { - // \ref{ratio.ratio}, class template \tcode{ratio} - template class ratio; - - // \ref{ratio.arithmetic}, ratio arithmetic - template using ratio_add = @\seebelow@; - template using ratio_subtract = @\seebelow@; - template using ratio_multiply = @\seebelow@; - template using ratio_divide = @\seebelow@; - - // \ref{ratio.comparison}, ratio comparison - template struct ratio_equal; - template struct ratio_not_equal; - template struct ratio_less; - template struct ratio_less_equal; - template struct ratio_greater; - template struct ratio_greater_equal; - - template - inline constexpr bool @\libglobal{ratio_equal_v}@ = ratio_equal::value; - template - inline constexpr bool @\libglobal{ratio_not_equal_v}@ = ratio_not_equal::value; - template - inline constexpr bool @\libglobal{ratio_less_v}@ = ratio_less::value; - template - inline constexpr bool @\libglobal{ratio_less_equal_v}@ = ratio_less_equal::value; - template - inline constexpr bool @\libglobal{ratio_greater_v}@ = ratio_greater::value; - template - inline constexpr bool @\libglobal{ratio_greater_equal_v}@ = ratio_greater_equal::value; - - // \ref{ratio.si}, convenience SI typedefs - using yocto = ratio<1, 1'000'000'000'000'000'000'000'000>; // see below - using zepto = ratio<1, 1'000'000'000'000'000'000'000>; // see below - using atto = ratio<1, 1'000'000'000'000'000'000>; - using femto = ratio<1, 1'000'000'000'000'000>; - using pico = ratio<1, 1'000'000'000'000>; - using nano = ratio<1, 1'000'000'000>; - using micro = ratio<1, 1'000'000>; - using milli = ratio<1, 1'000>; - using centi = ratio<1, 100>; - using deci = ratio<1, 10>; - using deca = ratio< 10, 1>; - using hecto = ratio< 100, 1>; - using kilo = ratio< 1'000, 1>; - using mega = ratio< 1'000'000, 1>; - using giga = ratio< 1'000'000'000, 1>; - using tera = ratio< 1'000'000'000'000, 1>; - using peta = ratio< 1'000'000'000'000'000, 1>; - using exa = ratio< 1'000'000'000'000'000'000, 1>; - using zetta = ratio< 1'000'000'000'000'000'000'000, 1>; // see below - using yotta = ratio<1'000'000'000'000'000'000'000'000, 1>; // see below -} -\end{codeblockdigitsep} - -\rSec2[ratio.ratio]{Class template \tcode{ratio}} - -\indexlibraryglobal{ratio}% -\begin{codeblock} -namespace std { - template class ratio { - public: - static constexpr intmax_t num; - static constexpr intmax_t den; - using type = ratio; - }; -} -\end{codeblock} - -\pnum -\indextext{signed integer representation!two's complement}% -If the template argument \tcode{D} is zero or the absolute values of either of the -template arguments \tcode{N} and \tcode{D} is not representable by type -\tcode{intmax_t}, the program is ill-formed. -\begin{note} -These rules ensure that infinite -ratios are avoided and that for any negative input, there exists a representable value -of its absolute value which is positive. -This excludes the most negative value. -\end{note} - -\pnum -The static data members \tcode{num} and \tcode{den} shall have the following values, -where \tcode{gcd} represents the greatest common divisor of the absolute values of -\tcode{N} and \tcode{D}: - -\begin{itemize} -\item \tcode{num} shall have the value \tcode{sign(N) * sign(D) * abs(N) / gcd}. -\item \tcode{den} shall have the value \tcode{abs(D) / gcd}. -\end{itemize} - -\rSec2[ratio.arithmetic]{Arithmetic on \tcode{ratio}{s}} - -\pnum -Each of the alias templates \tcode{ratio_add}, \tcode{ratio_subtract}, \tcode{ratio_multiply}, -and \tcode{ratio_divide} denotes the result of an arithmetic computation on two -\tcode{ratio}{s} \tcode{R1} and \tcode{R2}. With \tcode{X} and \tcode{Y} computed (in the -absence of arithmetic overflow) as specified by \tref{ratio.arithmetic}, each alias -denotes a \tcode{ratio} such that \tcode{U} is the same as \tcode{ratio::num} and -\tcode{V} is the same as \tcode{ratio::den}. - -\pnum -If it is not possible to represent \tcode{U} or \tcode{V} with \tcode{intmax_t}, the program is -ill-formed. Otherwise, an implementation should yield correct values of \tcode{U} and -\tcode{V}. If it is not possible to represent \tcode{X} or \tcode{Y} with \tcode{intmax_t}, the -program is ill-formed unless the implementation yields correct values of \tcode{U} and -\tcode{V}. - -\begin{floattable}{Expressions used to perform ratio arithmetic}{ratio.arithmetic} -{lll} -\topline -\lhdr{Type} & - \chdr{Value of \tcode{X}} & - \rhdr{Value of \tcode{Y}} \\ \rowsep - -\tcode{ratio_add} & - \tcode{R1::num * R2::den +} & - \tcode{R1::den * R2::den} \\ - & - \tcode{R2::num * R1::den} & - \\ \rowsep - -\tcode{ratio_subtract} & - \tcode{R1::num * R2::den -} & - \tcode{R1::den * R2::den} \\ - & - \tcode{R2::num * R1::den} & - \\ \rowsep - -\tcode{ratio_multiply} & - \tcode{R1::num * R2::num} & - \tcode{R1::den * R2::den} \\ \rowsep - -\tcode{ratio_divide} & - \tcode{R1::num * R2::den} & - \tcode{R1::den * R2::num} \\ -\end{floattable} - -\pnum -\begin{example} -\begin{codeblock} -static_assert(ratio_add, ratio<1, 6>>::num == 1, "1/3+1/6 == 1/2"); -static_assert(ratio_add, ratio<1, 6>>::den == 2, "1/3+1/6 == 1/2"); -static_assert(ratio_multiply, ratio<3, 2>>::num == 1, "1/3*3/2 == 1/2"); -static_assert(ratio_multiply, ratio<3, 2>>::den == 2, "1/3*3/2 == 1/2"); - -// The following cases may cause the program to be ill-formed under some implementations -static_assert(ratio_add, ratio<1, INT_MAX>>::num == 2, - "1/MAX+1/MAX == 2/MAX"); -static_assert(ratio_add, ratio<1, INT_MAX>>::den == INT_MAX, - "1/MAX+1/MAX == 2/MAX"); -static_assert(ratio_multiply, ratio>::num == 1, - "1/MAX * MAX/2 == 1/2"); -static_assert(ratio_multiply, ratio>::den == 2, - "1/MAX * MAX/2 == 1/2"); -\end{codeblock} - -\end{example} - -\rSec2[ratio.comparison]{Comparison of \tcode{ratio}{s}} - -\indexlibraryglobal{ratio_equal}% -\begin{itemdecl} -template - struct ratio_equal : bool_constant { }; -\end{itemdecl} - -\indexlibraryglobal{ratio_not_equal}% -\begin{itemdecl} -template - struct ratio_not_equal : bool_constant> { }; -\end{itemdecl} - -\indexlibraryglobal{ratio_less}% -\begin{itemdecl} -template - struct ratio_less : bool_constant<@\seebelow@> { }; -\end{itemdecl} - -\begin{itemdescr} -\pnum -If \tcode{R1::num} $\times$ \tcode{R2::den} is less than \tcode{R2::num} $\times$ \tcode{R1::den}, -\tcode{ratio_less} shall be -derived from \tcode{bool_constant}; otherwise it shall be derived from -\tcode{bool_constant}. Implementations may use other algorithms to -compute this relationship to avoid overflow. If overflow occurs, the program is ill-formed. -\end{itemdescr} - -\indexlibraryglobal{ratio_less_equal}% -\begin{itemdecl} -template - struct ratio_less_equal : bool_constant> { }; -\end{itemdecl} - -\indexlibraryglobal{ratio_greater}% -\begin{itemdecl} -template - struct ratio_greater : bool_constant> { }; -\end{itemdecl} - -\indexlibraryglobal{ratio_greater_equal}% -\begin{itemdecl} -template - struct ratio_greater_equal : bool_constant> { }; -\end{itemdecl} - -\rSec2[ratio.si]{SI types for \tcode{ratio}} - -\pnum -For each of the \grammarterm{typedef-name}{s} \tcode{yocto}, \tcode{zepto}, -\tcode{zetta}, and \tcode{yotta}, if both of the constants used in its -specification are representable by \tcode{intmax_t}, the typedef is -defined; if either of the constants is not representable by \tcode{intmax_t}, -the typedef is not defined. - \rSec1[type.index]{Class \tcode{type_index}} \rSec2[type.index.synopsis]{Header \tcode{} synopsis} diff --git a/tools/check-source.sh b/tools/check-source.sh index 6a8b21ecd7..8bd157fe6a 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -6,7 +6,7 @@ failed=0 # Ignore files where rules may be violated within macro definitions. texfiles=$(ls *.tex | grep -v macros.tex | grep -v layout.tex | grep -v tables.tex) -texlibdesc="support.tex concepts.tex diagnostics.tex memory.tex utilities.tex strings.tex containers.tex iterators.tex ranges.tex algorithms.tex numerics.tex time.tex locales.tex iostreams.tex regex.tex atomics.tex threads.tex" +texlibdesc="support.tex concepts.tex diagnostics.tex memory.tex meta.tex utilities.tex strings.tex containers.tex iterators.tex ranges.tex algorithms.tex numerics.tex time.tex locales.tex iostreams.tex regex.tex atomics.tex threads.tex" texlib="lib-intro.tex $texlibdesc" # Filter that reformats the error message as a "workflow command", From af8334b94be2df5bf009ef7381460f56e6224c44 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 23 Feb 2022 23:06:45 +0100 Subject: [PATCH 161/182] [meta] Adjust cross-references --- source/compatibility.tex | 2 +- source/meta.tex | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/source/compatibility.tex b/source/compatibility.tex index a5b7bac5ee..77cf38c7ec 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -1591,7 +1591,7 @@ \libheaderrefx{system_error}{system.error.syn}, \libheaderref{thread}, \libheaderref{tuple}, -\libheaderrefx{typeindex}{type.index.synopsis}, +\libheaderrefx{type\-index}{type.index.synopsis}, \libheaderrefx{type_traits}{meta.type.synop}, \libheaderrefx{unordered_map}{unord.map.syn}, and diff --git a/source/meta.tex b/source/meta.tex index bd138d5e90..6c6d7914fd 100644 --- a/source/meta.tex +++ b/source/meta.tex @@ -73,8 +73,8 @@ \rSec2[type.traits.general]{General} \pnum -Subclause \ref{meta} describes components used by \Cpp{} programs, particularly in -templates, to support the widest possible range of types, optimise +Subclause \ref{type.traits} describes components used by \Cpp{} programs, particularly in +templates, to support the widest possible range of types, optimize template code usage, detect type related user errors, and perform type inference and transformation at compile time. It includes type classification traits, type property inspection traits, and type @@ -86,7 +86,7 @@ \pnum \indextext{signal-safe!type traits}% -All functions specified in \ref{meta} are signal-safe\iref{support.signal}. +All functions specified in \ref{type.traits} are signal-safe\iref{support.signal}. \rSec2[meta.rqmts]{Requirements} @@ -132,16 +132,16 @@ \pnum Unless otherwise specified, the behavior of a program that adds specializations -for any of the templates specified in \ref{meta} +for any of the templates specified in \ref{type.traits} is undefined. \pnum Unless otherwise specified, an incomplete type may be used -to instantiate a template specified in \ref{meta}. +to instantiate a template specified in \ref{type.traits}. The behavior of a program is undefined if: \begin{itemize} \item - an instantiation of a template specified in \ref{meta} + an instantiation of a template specified in \ref{type.traits} directly or indirectly depends on an incompletely-defined object type \tcode{T}, and \item @@ -2627,4 +2627,3 @@ specification are representable by \tcode{intmax_t}, the typedef is defined; if either of the constants is not representable by \tcode{intmax_t}, the typedef is not defined. - From d74c2170a9f4c928519461d7742293af2d141852 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 23 Feb 2022 23:19:51 +0100 Subject: [PATCH 162/182] Move [atomics] into [thread] Rename [thread] to 'Concurrency support library'. --- source/atomics.tex | 3851 ----------------------------------------- source/lib-intro.tex | 10 +- source/std.tex | 1 - source/threads.tex | 3837 ++++++++++++++++++++++++++++++++++++++++ tools/check-source.sh | 2 +- 5 files changed, 3841 insertions(+), 3860 deletions(-) delete mode 100644 source/atomics.tex diff --git a/source/atomics.tex b/source/atomics.tex deleted file mode 100644 index a68674b232..0000000000 --- a/source/atomics.tex +++ /dev/null @@ -1,3851 +0,0 @@ -%!TEX root = std.tex -\rSec0[atomics]{Atomic operations library} - -\rSec1[atomics.general]{General} - -\pnum -This Clause describes components for fine-grained atomic access. This access is -provided via operations on atomic objects. - -\pnum -The following subclauses describe atomics requirements and components for types -and operations, as summarized in \tref{atomics.summary}. - -\begin{libsumtab}{Atomics library summary}{atomics.summary} -\ref{atomics.alias} & Type aliases & \tcode{} \\ -\ref{atomics.order} & Order and consistency & \\ -\ref{atomics.lockfree} & Lock-free property & \\ -\ref{atomics.wait} & Waiting and notifying & \\ -\ref{atomics.ref.generic} & Class template \tcode{atomic_ref} & \\ -\ref{atomics.types.generic} & Class template \tcode{atomic} & \\ -\ref{atomics.nonmembers} & Non-member functions & \\ -\ref{atomics.flag} & Flag type and operations & \\ -\ref{atomics.fences} & Fences & \\ \rowsep -\ref{stdatomic.h.syn} & C compatibility & \tcode{} \\ -\end{libsumtab} - -\rSec1[atomics.syn]{Header \tcode{} synopsis} - -\indexheader{atomic}% -\begin{codeblock} -namespace std { - // \ref{atomics.order}, order and consistency - enum class memory_order : @\unspec@; - template - T kill_dependency(T y) noexcept; -} - -// \ref{atomics.lockfree}, lock-free property -#define ATOMIC_BOOL_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR8_T_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR16_T_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR32_T_LOCK_FREE @\unspec@ -#define ATOMIC_WCHAR_T_LOCK_FREE @\unspec@ -#define ATOMIC_SHORT_LOCK_FREE @\unspec@ -#define ATOMIC_INT_LOCK_FREE @\unspec@ -#define ATOMIC_LONG_LOCK_FREE @\unspec@ -#define ATOMIC_LLONG_LOCK_FREE @\unspec@ -#define ATOMIC_POINTER_LOCK_FREE @\unspec@ - -namespace std { - // \ref{atomics.ref.generic}, class template \tcode{atomic_ref} - template struct atomic_ref; - // \ref{atomics.ref.pointer}, partial specialization for pointers - template struct atomic_ref; - - // \ref{atomics.types.generic}, class template \tcode{atomic} - template struct atomic; - // \ref{atomics.types.pointer}, partial specialization for pointers - template struct atomic; - - // \ref{atomics.nonmembers}, non-member functions - template - bool atomic_is_lock_free(const volatile atomic*) noexcept; - template - bool atomic_is_lock_free(const atomic*) noexcept; - template - void atomic_store(volatile atomic*, typename atomic::value_type) noexcept; - template - void atomic_store(atomic*, typename atomic::value_type) noexcept; - template - void atomic_store_explicit(volatile atomic*, typename atomic::value_type, - memory_order) noexcept; - template - void atomic_store_explicit(atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_load(const volatile atomic*) noexcept; - template - T atomic_load(const atomic*) noexcept; - template - T atomic_load_explicit(const volatile atomic*, memory_order) noexcept; - template - T atomic_load_explicit(const atomic*, memory_order) noexcept; - template - T atomic_exchange(volatile atomic*, typename atomic::value_type) noexcept; - template - T atomic_exchange(atomic*, typename atomic::value_type) noexcept; - template - T atomic_exchange_explicit(volatile atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_exchange_explicit(atomic*, typename atomic::value_type, - memory_order) noexcept; - template - bool atomic_compare_exchange_weak(volatile atomic*, - typename atomic::value_type*, - typename atomic::value_type) noexcept; - template - bool atomic_compare_exchange_weak(atomic*, - typename atomic::value_type*, - typename atomic::value_type) noexcept; - template - bool atomic_compare_exchange_strong(volatile atomic*, - typename atomic::value_type*, - typename atomic::value_type) noexcept; - template - bool atomic_compare_exchange_strong(atomic*, - typename atomic::value_type*, - typename atomic::value_type) noexcept; - template - bool atomic_compare_exchange_weak_explicit(volatile atomic*, - typename atomic::value_type*, - typename atomic::value_type, - memory_order, memory_order) noexcept; - template - bool atomic_compare_exchange_weak_explicit(atomic*, - typename atomic::value_type*, - typename atomic::value_type, - memory_order, memory_order) noexcept; - template - bool atomic_compare_exchange_strong_explicit(volatile atomic*, - typename atomic::value_type*, - typename atomic::value_type, - memory_order, memory_order) noexcept; - template - bool atomic_compare_exchange_strong_explicit(atomic*, - typename atomic::value_type*, - typename atomic::value_type, - memory_order, memory_order) noexcept; - - template - T atomic_fetch_add(volatile atomic*, typename atomic::difference_type) noexcept; - template - T atomic_fetch_add(atomic*, typename atomic::difference_type) noexcept; - template - T atomic_fetch_add_explicit(volatile atomic*, typename atomic::difference_type, - memory_order) noexcept; - template - T atomic_fetch_add_explicit(atomic*, typename atomic::difference_type, - memory_order) noexcept; - template - T atomic_fetch_sub(volatile atomic*, typename atomic::difference_type) noexcept; - template - T atomic_fetch_sub(atomic*, typename atomic::difference_type) noexcept; - template - T atomic_fetch_sub_explicit(volatile atomic*, typename atomic::difference_type, - memory_order) noexcept; - template - T atomic_fetch_sub_explicit(atomic*, typename atomic::difference_type, - memory_order) noexcept; - template - T atomic_fetch_and(volatile atomic*, typename atomic::value_type) noexcept; - template - T atomic_fetch_and(atomic*, typename atomic::value_type) noexcept; - template - T atomic_fetch_and_explicit(volatile atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_fetch_and_explicit(atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_fetch_or(volatile atomic*, typename atomic::value_type) noexcept; - template - T atomic_fetch_or(atomic*, typename atomic::value_type) noexcept; - template - T atomic_fetch_or_explicit(volatile atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_fetch_or_explicit(atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_fetch_xor(volatile atomic*, typename atomic::value_type) noexcept; - template - T atomic_fetch_xor(atomic*, typename atomic::value_type) noexcept; - template - T atomic_fetch_xor_explicit(volatile atomic*, typename atomic::value_type, - memory_order) noexcept; - template - T atomic_fetch_xor_explicit(atomic*, typename atomic::value_type, - memory_order) noexcept; - - template - void atomic_wait(const volatile atomic*, typename atomic::value_type); - template - void atomic_wait(const atomic*, typename atomic::value_type); - template - void atomic_wait_explicit(const volatile atomic*, typename atomic::value_type, - memory_order); - template - void atomic_wait_explicit(const atomic*, typename atomic::value_type, - memory_order); - template - void atomic_notify_one(volatile atomic*); - template - void atomic_notify_one(atomic*); - template - void atomic_notify_all(volatile atomic*); - template - void atomic_notify_all(atomic*); - - // \ref{atomics.alias}, type aliases - using atomic_bool = atomic; - using atomic_char = atomic; - using atomic_schar = atomic; - using atomic_uchar = atomic; - using atomic_short = atomic; - using atomic_ushort = atomic; - using atomic_int = atomic; - using atomic_uint = atomic; - using atomic_long = atomic; - using atomic_ulong = atomic; - using atomic_llong = atomic; - using atomic_ullong = atomic; - using atomic_char8_t = atomic; - using atomic_char16_t = atomic; - using atomic_char32_t = atomic; - using atomic_wchar_t = atomic; - - using atomic_int8_t = atomic; - using atomic_uint8_t = atomic; - using atomic_int16_t = atomic; - using atomic_uint16_t = atomic; - using atomic_int32_t = atomic; - using atomic_uint32_t = atomic; - using atomic_int64_t = atomic; - using atomic_uint64_t = atomic; - - using atomic_int_least8_t = atomic; - using atomic_uint_least8_t = atomic; - using atomic_int_least16_t = atomic; - using atomic_uint_least16_t = atomic; - using atomic_int_least32_t = atomic; - using atomic_uint_least32_t = atomic; - using atomic_int_least64_t = atomic; - using atomic_uint_least64_t = atomic; - - using atomic_int_fast8_t = atomic; - using atomic_uint_fast8_t = atomic; - using atomic_int_fast16_t = atomic; - using atomic_uint_fast16_t = atomic; - using atomic_int_fast32_t = atomic; - using atomic_uint_fast32_t = atomic; - using atomic_int_fast64_t = atomic; - using atomic_uint_fast64_t = atomic; - - using atomic_intptr_t = atomic; - using atomic_uintptr_t = atomic; - using atomic_size_t = atomic; - using atomic_ptrdiff_t = atomic; - using atomic_intmax_t = atomic; - using atomic_uintmax_t = atomic; - - using atomic_signed_lock_free = @\seebelow@; - using atomic_unsigned_lock_free = @\seebelow@; - - // \ref{atomics.flag}, flag type and operations - struct atomic_flag; - - bool atomic_flag_test(const volatile atomic_flag*) noexcept; - bool atomic_flag_test(const atomic_flag*) noexcept; - bool atomic_flag_test_explicit(const volatile atomic_flag*, memory_order) noexcept; - bool atomic_flag_test_explicit(const atomic_flag*, memory_order) noexcept; - bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept; - bool atomic_flag_test_and_set(atomic_flag*) noexcept; - bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, memory_order) noexcept; - bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order) noexcept; - void atomic_flag_clear(volatile atomic_flag*) noexcept; - void atomic_flag_clear(atomic_flag*) noexcept; - void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept; - void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept; - - void atomic_flag_wait(const volatile atomic_flag*, bool) noexcept; - void atomic_flag_wait(const atomic_flag*, bool) noexcept; - void atomic_flag_wait_explicit(const volatile atomic_flag*, - bool, memory_order) noexcept; - void atomic_flag_wait_explicit(const atomic_flag*, - bool, memory_order) noexcept; - void atomic_flag_notify_one(volatile atomic_flag*) noexcept; - void atomic_flag_notify_one(atomic_flag*) noexcept; - void atomic_flag_notify_all(volatile atomic_flag*) noexcept; - void atomic_flag_notify_all(atomic_flag*) noexcept; - - // \ref{atomics.fences}, fences - extern "C" void atomic_thread_fence(memory_order) noexcept; - extern "C" void atomic_signal_fence(memory_order) noexcept; -} -\end{codeblock} - -\rSec1[atomics.alias]{Type aliases} -\indexlibraryglobal{atomic_bool}% -\indexlibraryglobal{atomic_char}% -\indexlibraryglobal{atomic_schar}% -\indexlibraryglobal{atomic_uchar}% -\indexlibraryglobal{atomic_short}% -\indexlibraryglobal{atomic_ushort}% -\indexlibraryglobal{atomic_int}% -\indexlibraryglobal{atomic_uint}% -\indexlibraryglobal{atomic_long}% -\indexlibraryglobal{atomic_ulong}% -\indexlibraryglobal{atomic_llong}% -\indexlibraryglobal{atomic_ullong}% -\indexlibraryglobal{atomic_char8_t}% -\indexlibraryglobal{atomic_char16_t}% -\indexlibraryglobal{atomic_char32_t}% -\indexlibraryglobal{atomic_wchar_t}% -\indexlibraryglobal{atomic_int8_t}% -\indexlibraryglobal{atomic_uint8_t}% -\indexlibraryglobal{atomic_int16_t}% -\indexlibraryglobal{atomic_uint16_t}% -\indexlibraryglobal{atomic_int32_t}% -\indexlibraryglobal{atomic_uint32_t}% -\indexlibraryglobal{atomic_int64_t}% -\indexlibraryglobal{atomic_uint64_t}% -\indexlibraryglobal{atomic_int_least8_t}% -\indexlibraryglobal{atomic_uint_least8_t}% -\indexlibraryglobal{atomic_int_least16_t}% -\indexlibraryglobal{atomic_uint_least16_t}% -\indexlibraryglobal{atomic_int_least32_t}% -\indexlibraryglobal{atomic_uint_least32_t}% -\indexlibraryglobal{atomic_int_least64_t}% -\indexlibraryglobal{atomic_uint_least64_t}% -\indexlibraryglobal{atomic_int_fast8_t}% -\indexlibraryglobal{atomic_uint_fast8_t}% -\indexlibraryglobal{atomic_int_fast16_t}% -\indexlibraryglobal{atomic_uint_fast16_t}% -\indexlibraryglobal{atomic_int_fast32_t}% -\indexlibraryglobal{atomic_uint_fast32_t}% -\indexlibraryglobal{atomic_int_fast64_t}% -\indexlibraryglobal{atomic_uint_fast64_t}% -\indexlibraryglobal{atomic_intptr_t}% -\indexlibraryglobal{atomic_uintptr_t}% -\indexlibraryglobal{atomic_size_t}% -\indexlibraryglobal{atomic_ptrdiff_t}% -\indexlibraryglobal{atomic_intmax_t}% -\indexlibraryglobal{atomic_uintmax_t}% -\pnum -The type aliases \tcode{atomic_int$N$_t}, \tcode{atomic_uint$N$_t}, -\tcode{atomic_intptr_t}, and \tcode{atomic_uintptr_t} -are defined if and only if -\tcode{int$N$_t}, \tcode{uint$N$_t}, -\tcode{intptr_t}, and \tcode{uintptr_t} -are defined, respectively. - -\pnum -\indexlibraryglobal{atomic_signed_lock_free}% -\indexlibraryglobal{atomic_unsigned_lock_free}% -The type aliases -\tcode{atomic_signed_lock_free} and \tcode{atomic_unsigned_lock_free} -name specializations of \tcode{atomic} -whose template arguments are integral types, respectively signed and unsigned, -and whose \tcode{is_always_lock_free} property is \tcode{true}. -\begin{note} -\indextext{implementation!freestanding}% -These aliases are optional in freestanding implementations\iref{compliance}. -\end{note} -Implementations should choose for these aliases -the integral specializations of \tcode{atomic} -for which the atomic waiting and notifying operations\iref{atomics.wait} -are most efficient. - -\rSec1[atomics.order]{Order and consistency} -\indexlibraryglobal{memory_order}% -\indexlibrarymember{relaxed}{memory_order}% -\indexlibrarymember{consume}{memory_order}% -\indexlibrarymember{acquire}{memory_order}% -\indexlibrarymember{release}{memory_order}% -\indexlibrarymember{acq_rel}{memory_order}% -\indexlibrarymember{seq_cst}{memory_order}% -\indexlibraryglobal{memory_order_relaxed}% -\indexlibraryglobal{memory_order_consume}% -\indexlibraryglobal{memory_order_acquire}% -\indexlibraryglobal{memory_order_release}% -\indexlibraryglobal{memory_order_acq_rel}% -\indexlibraryglobal{memory_order_seq_cst}% - -\begin{codeblock} -namespace std { - enum class memory_order : @\unspec@ { - relaxed, consume, acquire, release, acq_rel, seq_cst - }; - inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; - inline constexpr memory_order memory_order_consume = memory_order::consume; - inline constexpr memory_order memory_order_acquire = memory_order::acquire; - inline constexpr memory_order memory_order_release = memory_order::release; - inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; - inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; -} -\end{codeblock} - -\pnum -The enumeration \tcode{memory_order} specifies the detailed regular -(non-atomic) memory synchronization order as defined in -\ref{intro.multithread} and may provide for operation ordering. Its -enumerated values and their meanings are as follows: - -\begin{itemize} -\item \tcode{memory_order::relaxed}: no operation orders memory. - -\item \tcode{memory_order::release}, \tcode{memory_order::acq_rel}, and -\tcode{memory_order::seq_cst}: a store operation performs a release operation on the -affected memory location. - -\item \tcode{memory_order::consume}: a load operation performs a consume operation on the -affected memory location. -\begin{note} -Prefer \tcode{memory_order::acquire}, which provides stronger guarantees -than \tcode{memory_order::consume}. Implementations have found it infeasible -to provide performance better than that of \tcode{memory_order::acquire}. -Specification revisions are under consideration. -\end{note} - -\item \tcode{memory_order::acquire}, \tcode{memory_order::acq_rel}, and -\tcode{memory_order::seq_cst}: a load operation performs an acquire operation on the -affected memory location. -\end{itemize} - -\begin{note} -Atomic operations specifying \tcode{memory_order::relaxed} are relaxed -with respect to memory ordering. Implementations must still guarantee that any -given atomic access to a particular atomic object be indivisible with respect -to all other atomic accesses to that object. -\end{note} - -\pnum -An atomic operation $A$ that performs a release operation on an atomic -object $M$ synchronizes with an atomic operation $B$ that performs -an acquire operation on $M$ and takes its value from any side effect in the -release sequence headed by $A$. - -\pnum -An atomic operation $A$ on some atomic object $M$ is -\defn{coherence-ordered before} -another atomic operation $B$ on $M$ if -\begin{itemize} -\item $A$ is a modification, and -$B$ reads the value stored by $A$, or -\item $A$ precedes $B$ -in the modification order of $M$, or -\item $A$ and $B$ are not -the same atomic read-modify-write operation, and -there exists an atomic modification $X$ of $M$ -such that $A$ reads the value stored by $X$ and -$X$ precedes $B$ -in the modification order of $M$, or -\item there exists an atomic modification $X$ of $M$ -such that $A$ is coherence-ordered before $X$ and -$X$ is coherence-ordered before $B$. -\end{itemize} - -\pnum -There is a single total order $S$ -on all \tcode{memory_order::seq_cst} operations, including fences, -that satisfies the following constraints. -First, if $A$ and $B$ are -\tcode{memory_order::seq_cst} operations and -$A$ strongly happens before $B$, -then $A$ precedes $B$ in $S$. -Second, for every pair of atomic operations $A$ and -$B$ on an object $M$, -where $A$ is coherence-ordered before $B$, -the following four conditions are required to be satisfied by $S$: -\begin{itemize} -\item if $A$ and $B$ are both -\tcode{memory_order::seq_cst} operations, -then $A$ precedes $B$ in $S$; and -\item if $A$ is a \tcode{memory_order::seq_cst} operation and -$B$ happens before -a \tcode{memory_order::seq_cst} fence $Y$, -then $A$ precedes $Y$ in $S$; and -\item if a \tcode{memory_order::seq_cst} fence $X$ -happens before $A$ and -$B$ is a \tcode{memory_order::seq_cst} operation, -then $X$ precedes $B$ in $S$; and -\item if a \tcode{memory_order::seq_cst} fence $X$ -happens before $A$ and -$B$ happens before -a \tcode{memory_order::seq_cst} fence $Y$, -then $X$ precedes $Y$ in $S$. -\end{itemize} - -\pnum -\begin{note} -This definition ensures that $S$ is consistent with -the modification order of any atomic object $M$. -It also ensures that -a \tcode{memory_order::seq_cst} load $A$ of $M$ -gets its value either from the last modification of $M$ -that precedes $A$ in $S$ or -from some non-\tcode{memory_order::seq_cst} modification of $M$ -that does not happen before any modification of $M$ -that precedes $A$ in $S$. -\end{note} - -\pnum -\begin{note} -We do not require that $S$ be consistent with -``happens before''\iref{intro.races}. -This allows more efficient implementation -of \tcode{memory_order::acquire} and \tcode{memory_order::release} -on some machine architectures. -It can produce surprising results -when these are mixed with \tcode{memory_order::seq_cst} accesses. -\end{note} - -\pnum -\begin{note} -\tcode{memory_order::seq_cst} ensures sequential consistency only -for a program that is free of data races and -uses exclusively \tcode{memory_order::seq_cst} atomic operations. -Any use of weaker ordering will invalidate this guarantee -unless extreme care is used. -In many cases, \tcode{memory_order::seq_cst} atomic operations are reorderable -with respect to other atomic operations performed by the same thread. -\end{note} - -\pnum -Implementations should ensure that no ``out-of-thin-air'' values are computed that -circularly depend on their own computation. - -\begin{note} -For example, with \tcode{x} and \tcode{y} initially zero, -\begin{codeblock} -// Thread 1: -r1 = y.load(memory_order::relaxed); -x.store(r1, memory_order::relaxed); -\end{codeblock} - -\begin{codeblock} -// Thread 2: -r2 = x.load(memory_order::relaxed); -y.store(r2, memory_order::relaxed); -\end{codeblock} -this recommendation discourages producing \tcode{r1 == r2 == 42}, since the store of 42 to \tcode{y} is only -possible if the store to \tcode{x} stores \tcode{42}, which circularly depends on the -store to \tcode{y} storing \tcode{42}. Note that without this restriction, such an -execution is possible. -\end{note} - -\pnum -\begin{note} -The recommendation similarly disallows \tcode{r1 == r2 == 42} in the -following example, with \tcode{x} and \tcode{y} again initially zero: - -\begin{codeblock} -// Thread 1: -r1 = x.load(memory_order::relaxed); -if (r1 == 42) y.store(42, memory_order::relaxed); -\end{codeblock} - -\begin{codeblock} -// Thread 2: -r2 = y.load(memory_order::relaxed); -if (r2 == 42) x.store(42, memory_order::relaxed); -\end{codeblock} -\end{note} - -\pnum -Atomic read-modify-write operations shall always read the last value -(in the modification order) written before the write associated with -the read-modify-write operation. - -\pnum -Implementations should make atomic stores visible to atomic loads within a reasonable -amount of time. - -\indexlibraryglobal{kill_dependency}% -\begin{itemdecl} -template - T kill_dependency(T y) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -The argument does not carry a dependency to the return -value\iref{intro.multithread}. - -\pnum -\returns -\tcode{y}. -\end{itemdescr} - - -\rSec1[atomics.lockfree]{Lock-free property} - -\indexlibraryglobal{ATOMIC_BOOL_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_CHAR_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_CHAR8_T_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_CHAR16_T_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_CHAR32_T_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_WCHAR_T_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_SHORT_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_INT_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_LONG_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_LLONG_LOCK_FREE}% -\indexlibraryglobal{ATOMIC_POINTER_LOCK_FREE}% -\indeximpldef{values of various \tcode{ATOMIC_..._LOCK_FREE} macros} -\begin{codeblock} -#define ATOMIC_BOOL_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR8_T_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR16_T_LOCK_FREE @\unspec@ -#define ATOMIC_CHAR32_T_LOCK_FREE @\unspec@ -#define ATOMIC_WCHAR_T_LOCK_FREE @\unspec@ -#define ATOMIC_SHORT_LOCK_FREE @\unspec@ -#define ATOMIC_INT_LOCK_FREE @\unspec@ -#define ATOMIC_LONG_LOCK_FREE @\unspec@ -#define ATOMIC_LLONG_LOCK_FREE @\unspec@ -#define ATOMIC_POINTER_LOCK_FREE @\unspec@ -\end{codeblock} - -\pnum -The \tcode{ATOMIC_..._LOCK_FREE} macros indicate the lock-free property of the -corresponding atomic types, with the signed and unsigned variants grouped -together. The properties also apply to the corresponding (partial) specializations of the -\tcode{atomic} template. A value of 0 indicates that the types are never -lock-free. A value of 1 indicates that the types are sometimes lock-free. A -value of 2 indicates that the types are always lock-free. - -\pnum -At least one signed integral specialization of the \tcode{atomic} template, -along with the specialization -for the corresponding unsigned type\iref{basic.fundamental}, -is always lock-free. -\begin{note} -\indextext{implementation!freestanding}% -This requirement is optional in freestanding implementations\iref{compliance}. -\end{note} - -\pnum -The functions \tcode{atomic::is_lock_free} and -\tcode{atomic_is_lock_free}\iref{atomics.types.operations} -indicate whether the object is lock-free. In any given program execution, the -result of the lock-free query -is the same for all atomic objects of the same type. - -\pnum -Atomic operations that are not lock-free are considered to potentially -block\iref{intro.progress}. - -\pnum -\recommended -Operations that are lock-free should also be address-free. -\begin{footnote} -That is, -atomic operations on the same memory location via two different addresses will -communicate atomically. -\end{footnote} -The implementation of these operations should not depend on any per-process state. -\begin{note} -This restriction enables communication by memory that is -mapped into a process more than once and by memory that is shared between two -processes. -\end{note} - -\rSec1[atomics.wait]{Waiting and notifying} - -\pnum -\defnx{Atomic waiting operations}{atomic!waiting operation} -and \defnx{atomic notifying operations}{atomic!notifying operation} -provide a mechanism to wait for the value of an atomic object to change -more efficiently than can be achieved with polling. -An atomic waiting operation may block until it is unblocked -by an atomic notifying operation, according to each function's effects. -\begin{note} -Programs are not guaranteed to observe transient atomic values, -an issue known as the A-B-A problem, -resulting in continued blocking if a condition is only temporarily met. -\end{note} - -\pnum -\begin{note} -The following functions are atomic waiting operations: -\begin{itemize} -\item \tcode{atomic::wait}, -\item \tcode{atomic_flag::wait}, -\item \tcode{atomic_wait} and \tcode{atomic_wait_explicit}, -\item \tcode{atomic_flag_wait} and \tcode{atomic_flag_wait_explicit}, and -\item \tcode{atomic_ref::wait}. -\end{itemize} -\end{note} - -\pnum -\begin{note} -The following functions are atomic notifying operations: -\begin{itemize} -\item \tcode{atomic::notify_one} and \tcode{atomic::notify_all}, -\item \tcode{atomic_flag::notify_one} and \tcode{atomic_flag::notify_all}, -\item \tcode{atomic_notify_one} and \tcode{atomic_notify_all}, -\item \tcode{atomic_flag_notify_one} and \tcode{atomic_flag_notify_all}, and -\item \tcode{atomic_ref::notify_one} and \tcode{atomic_ref::notify_all}. -\end{itemize} -\end{note} - -\indextext{atomic!waiting operation!eligible to be unblocked}% -\pnum -A call to an atomic waiting operation on an atomic object \tcode{M} -is \defn{eligible to be unblocked} -by a call to an atomic notifying operation on \tcode{M} -if there exist side effects \tcode{X} and \tcode{Y} on \tcode{M} such that: -\begin{itemize} -\item the atomic waiting operation has blocked after observing the result of \tcode{X}, -\item \tcode{X} precedes \tcode{Y} in the modification order of \tcode{M}, and -\item \tcode{Y} happens before the call to the atomic notifying operation. -\end{itemize} - -\rSec1[atomics.ref.generic]{Class template \tcode{atomic_ref}} - -\rSec2[atomics.ref.generic.general]{General} - -\indexlibraryglobal{atomic_ref}% -\indexlibrarymember{value_type}{atomic_ref}% -\begin{codeblock} -namespace std { - template struct atomic_ref { - private: - T* ptr; // \expos - public: - using value_type = T; - static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; - bool is_lock_free() const noexcept; - - explicit atomic_ref(T&); - atomic_ref(const atomic_ref&) noexcept; - atomic_ref& operator=(const atomic_ref&) = delete; - - void store(T, memory_order = memory_order::seq_cst) const noexcept; - T operator=(T) const noexcept; - T load(memory_order = memory_order::seq_cst) const noexcept; - operator T() const noexcept; - - T exchange(T, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(T&, T, - memory_order, memory_order) const noexcept; - bool compare_exchange_strong(T&, T, - memory_order, memory_order) const noexcept; - bool compare_exchange_weak(T&, T, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(T&, T, - memory_order = memory_order::seq_cst) const noexcept; - - void wait(T, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; - }; -} -\end{codeblock} - -\pnum -An \tcode{atomic_ref} object applies atomic operations\iref{atomics.general} to -the object referenced by \tcode{*ptr} such that, -for the lifetime\iref{basic.life} of the \tcode{atomic_ref} object, -the object referenced by \tcode{*ptr} is an atomic object\iref{intro.races}. - -\pnum -The program is ill-formed if \tcode{is_trivially_copyable_v} is \tcode{false}. - -\pnum -The lifetime\iref{basic.life} of an object referenced by \tcode{*ptr} -shall exceed the lifetime of all \tcode{atomic_ref}s that reference the object. -While any \tcode{atomic_ref} instances exist -that reference the \tcode{*ptr} object, -all accesses to that object shall exclusively occur -through those \tcode{atomic_ref} instances. -No subobject of the object referenced by \tcode{atomic_ref} -shall be concurrently referenced by any other \tcode{atomic_ref} object. - -\pnum -Atomic operations applied to an object -through a referencing \tcode{atomic_ref} are atomic with respect to -atomic operations applied through any other \tcode{atomic_ref} -referencing the same object. -\begin{note} -Atomic operations or the \tcode{atomic_ref} constructor can acquire -a shared resource, such as a lock associated with the referenced object, -to enable atomic operations to be applied to the referenced object. -\end{note} - -\rSec2[atomics.ref.ops]{Operations} - -\indexlibrarymember{required_alignment}{atomic_ref}% -\indexlibrarymember{required_alignment}{atomic_ref}% -\indexlibrarymember{required_alignment}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{required_alignment}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -static constexpr size_t required_alignment; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The alignment required for an object to be referenced by an atomic reference, -which is at least \tcode{alignof(T)}. - -\pnum -\begin{note} -Hardware could require an object -referenced by an \tcode{atomic_ref} -to have stricter alignment\iref{basic.align} -than other objects of type \tcode{T}. -Further, whether operations on an \tcode{atomic_ref} -are lock-free could depend on the alignment of the referenced object. -For example, lock-free operations on \tcode{std::complex} -could be supported only if aligned to \tcode{2*alignof(double)}. -\end{note} -\end{itemdescr} - -\indexlibrarymember{is_always_lock_free}{atomic_ref}% -\indexlibrarymember{is_always_lock_free}{atomic_ref}% -\indexlibrarymember{is_always_lock_free}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{is_always_lock_free}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -static constexpr bool is_always_lock_free; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The static data member \tcode{is_always_lock_free} is \tcode{true} -if the \tcode{atomic_ref} type's operations are always lock-free, -and \tcode{false} otherwise. -\end{itemdescr} - -\indexlibrarymember{is_lock_free}{atomic_ref}% -\indexlibrarymember{is_lock_free}{atomic_ref}% -\indexlibrarymember{is_lock_free}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{is_lock_free}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -bool is_lock_free() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if operations on all objects of the type \tcode{atomic_ref} -are lock-free, -\tcode{false} otherwise. -\end{itemdescr} - -\indexlibraryctor{atomic_ref}% -\indexlibraryctor{atomic_ref}% -\indexlibrary{\idxcode{atomic_ref<\placeholder{integral}>}!constructor}% -\indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point}>}!constructor}% -\begin{itemdecl} -atomic_ref(T& obj); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The referenced object is aligned to \tcode{required_alignment}. - -\pnum -\ensures -\tcode{*this} references \tcode{obj}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibraryctor{atomic_ref}% -\indexlibraryctor{atomic_ref}% -\indexlibrary{\idxcode{atomic_ref<\placeholder{integral}>}!constructor}% -\indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point}>}!constructor}% -\begin{itemdecl} -atomic_ref(const atomic_ref& ref) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{*this} references the object referenced by \tcode{ref}. -\end{itemdescr} - -\indexlibrarymember{store}{atomic_ref}% -\indexlibrarymember{store}{atomic_ref}% -\indexlibrarymember{store}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{store}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -void store(T desired, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The \tcode{order} argument is neither -\tcode{memory_order::consume}, -\tcode{memory_order::acquire}, nor -\tcode{memory_order::acq_rel}. - -\pnum -\effects -Atomically replaces the value referenced by \tcode{*ptr} -with the value of \tcode{desired}. -Memory is affected according to the value of \tcode{order}. -\end{itemdescr} - -\indexlibrarymember{operator=}{atomic_ref}% -\indexlibrarymember{operator=}{atomic_ref}% -\indexlibrarymember{operator=}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{operator=}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -T operator=(T desired) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -store(desired); -return desired; -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{load}{atomic_ref}% -\indexlibrarymember{load}{atomic_ref}% -\indexlibrarymember{load}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{load}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -T load(memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The \tcode{order} argument is neither -\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Memory is affected according to the value of \tcode{order}. - -\pnum -\returns -Atomically returns the value referenced by \tcode{*ptr}. -\end{itemdescr} - -\indexlibrarymember{operator \placeholder{type}}{atomic_ref}% -\indexlibrarymember{operator T*}{atomic_ref}% -\indexlibrarymember{operator \placeholder{integral}}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{operator \placeholder{floating-point}}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -operator T() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return load();} -\end{itemdescr} - -\indexlibrarymember{exchange}{atomic_ref}% -\indexlibrarymember{exchange}{atomic_ref}% -\indexlibrarymember{exchange}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{exchange}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -T exchange(T desired, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Atomically replaces the value referenced by \tcode{*ptr} -with \tcode{desired}. -Memory is affected according to the value of \tcode{order}. -This operation is an atomic read-modify-write operation\iref{intro.multithread}. - -\pnum -\returns -Atomically returns the value referenced by \tcode{*ptr} -immediately before the effects. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_weak}{atomic_ref}% -\indexlibrarymember{compare_exchange_weak}{atomic_ref}% -\indexlibrarymember{compare_exchange_weak}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{compare_exchange_weak}{atomic_ref<\placeholder{floating-point}>}% -\indexlibrarymember{compare_exchange_strong}{atomic_ref}% -\indexlibrarymember{compare_exchange_strong}{atomic_ref}% -\indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -bool compare_exchange_weak(T& expected, T desired, - memory_order success, memory_order failure) const noexcept; - -bool compare_exchange_strong(T& expected, T desired, - memory_order success, memory_order failure) const noexcept; - -bool compare_exchange_weak(T& expected, T desired, - memory_order order = memory_order::seq_cst) const noexcept; - -bool compare_exchange_strong(T& expected, T desired, - memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The \tcode{failure} argument is neither -\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Retrieves the value in \tcode{expected}. -It then atomically compares the value representation of -the value referenced by \tcode{*ptr} for equality -with that previously retrieved from \tcode{expected}, -and if \tcode{true}, replaces the value referenced by \tcode{*ptr} -with that in \tcode{desired}. -If and only if the comparison is \tcode{true}, -memory is affected according to the value of \tcode{success}, and -if the comparison is \tcode{false}, -memory is affected according to the value of \tcode{failure}. -When only one \tcode{memory_order} argument is supplied, -the value of \tcode{success} is \tcode{order}, and -the value of \tcode{failure} is \tcode{order} -except that a value of \tcode{memory_order::acq_rel} shall be replaced by -the value \tcode{memory_order::acquire} and -a value of \tcode{memory_order::release} shall be replaced by -the value \tcode{memory_order::relaxed}. -If and only if the comparison is \tcode{false} then, -after the atomic operation, -the value in \tcode{expected} is replaced by -the value read from the value referenced by \tcode{*ptr} -during the atomic comparison. -If the operation returns \tcode{true}, -these operations are atomic read-modify-write operations\iref{intro.races} -on the value referenced by \tcode{*ptr}. -Otherwise, these operations are atomic load operations on that memory. - -\pnum -\returns -The result of the comparison. - -\pnum -\remarks -A weak compare-and-exchange operation may fail spuriously. -That is, even when the contents of memory referred to -by \tcode{expected} and \tcode{ptr} are equal, -it may return \tcode{false} and -store back to \tcode{expected} the same memory contents -that were originally there. -\begin{note} -This spurious failure enables implementation of compare-and-exchange -on a broader class of machines, e.g., load-locked store-conditional machines. -A consequence of spurious failure is -that nearly all uses of weak compare-and-exchange will be in a loop. -When a compare-and-exchange is in a loop, -the weak version will yield better performance on some platforms. -When a weak compare-and-exchange would require a loop and -a strong one would not, the strong one is preferable. -\end{note} -\end{itemdescr} - -\indexlibrarymember{wait}{atomic_ref}% -\begin{itemdecl} -void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is -neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Repeatedly performs the following steps, in order: -\begin{itemize} -\item - Evaluates \tcode{load(order)} and - compares its value representation for equality against that of \tcode{old}. -\item - If they compare unequal, returns. -\item - Blocks until it - is unblocked by an atomic notifying operation or is unblocked spuriously. -\end{itemize} - -\pnum -\remarks -This function is an atomic waiting operation\iref{atomics.wait} -on atomic object \tcode{*ptr}. -\end{itemdescr} - -\indexlibrarymember{notify_one}{atomic_ref}% -\begin{itemdecl} -void notify_one() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of at least one atomic waiting operation on \tcode{*ptr} -that is eligible to be unblocked\iref{atomics.wait} by this call, -if any such atomic waiting operations exist. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait} -on atomic object \tcode{*ptr}. -\end{itemdescr} - -\indexlibrarymember{notify_all}{atomic_ref}% -\begin{itemdecl} -void notify_all() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of all atomic waiting operations on \tcode{*ptr} -that are eligible to be unblocked\iref{atomics.wait} by this call. - -\pnum -\remarks - This function is an atomic notifying operation\iref{atomics.wait} - on atomic object \tcode{*ptr}. -\end{itemdescr} - -\rSec2[atomics.ref.int]{Specializations for integral types} - -\pnum -\indexlibrary{\idxcode{atomic_ref<\placeholder{integral}>}}% -There are specializations of the \tcode{atomic_ref} class template -for the integral types -\tcode{char}, -\tcode{signed char}, -\tcode{unsigned char}, -\tcode{short}, -\tcode{unsigned short}, -\tcode{int}, -\tcode{unsigned int}, -\tcode{long}, -\tcode{unsigned long}, -\tcode{long long}, -\tcode{unsigned long long}, -\keyword{char8_t}, -\keyword{char16_t}, -\keyword{char32_t}, -\keyword{wchar_t}, -and any other types needed by the typedefs in the header \libheaderref{cstdint}. -For each such type \tcode{\placeholder{integral}}, -the specialization \tcode{atomic_ref<\placeholder{integral}>} provides -additional atomic operations appropriate to integral types. -\begin{note} -The specialization \tcode{atomic_ref} -uses the primary template\iref{atomics.ref.generic}. -\end{note} - -\begin{codeblock} -namespace std { - template<> struct atomic_ref<@\placeholder{integral}@> { - private: - @\placeholder{integral}@* ptr; // \expos - public: - using value_type = @\placeholder{integral}@; - using difference_type = value_type; - static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; - bool is_lock_free() const noexcept; - - explicit atomic_ref(@\placeholder{integral}@&); - atomic_ref(const atomic_ref&) noexcept; - atomic_ref& operator=(const atomic_ref&) = delete; - - void store(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral}@ operator=(@\placeholder{integral}@) const noexcept; - @\placeholdernc{integral}@ load(memory_order = memory_order::seq_cst) const noexcept; - operator @\placeholdernc{integral}@() const noexcept; - - @\placeholdernc{integral}@ exchange(@\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholder{integral}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholder{integral}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholder{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholder{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - - @\placeholdernc{integral}@ fetch_add(@\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral}@ fetch_sub(@\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral}@ fetch_and(@\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral}@ fetch_or(@\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral}@ fetch_xor(@\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) const noexcept; - - @\placeholdernc{integral}@ operator++(int) const noexcept; - @\placeholdernc{integral}@ operator--(int) const noexcept; - @\placeholdernc{integral}@ operator++() const noexcept; - @\placeholdernc{integral}@ operator--() const noexcept; - @\placeholdernc{integral}@ operator+=(@\placeholdernc{integral}@) const noexcept; - @\placeholdernc{integral}@ operator-=(@\placeholdernc{integral}@) const noexcept; - @\placeholdernc{integral}@ operator&=(@\placeholdernc{integral}@) const noexcept; - @\placeholdernc{integral}@ operator|=(@\placeholdernc{integral}@) const noexcept; - @\placeholdernc{integral}@ operator^=(@\placeholdernc{integral}@) const noexcept; - - void wait(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; - }; -} -\end{codeblock} - -\pnum -Descriptions are provided below only for members -that differ from the primary template. - -\pnum -The following operations perform arithmetic computations. -The correspondence among key, operator, and computation is specified -in \tref{atomic.types.int.comp}. - -\indexlibrarymember{fetch_add}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{fetch_and}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{fetch_or}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{fetch_xor}{atomic_ref<\placeholder{integral}>}% -\begin{itemdecl} -@\placeholdernc{integral}@ fetch_@\placeholdernc{key}@(@\placeholdernc{integral}@ operand, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Atomically replaces the value referenced by \tcode{*ptr} with -the result of the computation applied to the value referenced by \tcode{*ptr} -and the given operand. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.races}. - -\pnum -\returns -Atomically, the value referenced by \tcode{*ptr} -immediately before the effects. - -\pnum -\indextext{signed integer representation!two's complement}% -\remarks -For signed integer types, -the result is as if the object value and parameters -were converted to their corresponding unsigned types, -the computation performed on those types, and -the result converted back to the signed type. -\begin{note} -There are no undefined results arising from the computation. -\end{note} -\end{itemdescr} - -\indexlibrarymember{operator+=}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{operator-=}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{operator\&=}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{operator"|=}{atomic_ref<\placeholder{integral}>}% -\indexlibrarymember{operator\caret=}{atomic_ref<\placeholder{integral}>}% -\begin{itemdecl} -@\placeholdernc{integral}@ operator @\placeholder{op}@=(@\placeholdernc{integral}@ operand) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\tcode{return fetch_\placeholdernc{key}(operand) \placeholder{op} operand;} -\end{itemdescr} - -\rSec2[atomics.ref.float]{Specializations for floating-point types} - -\pnum -\indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point}>}}% -There are specializations of the \tcode{atomic_ref} class template -for the floating-point types -\tcode{float}, -\tcode{double}, and -\tcode{long double}. -For each such type \tcode{\placeholder{floating-point}}, -the specialization \tcode{atomic_ref<\placeholder{floating-\-point}>} provides -additional atomic operations appropriate to floating-point types. - -\begin{codeblock} -namespace std { - template<> struct atomic_ref<@\placeholder{floating-point}@> { - private: - @\placeholder{floating-point}@* ptr; // \expos - public: - using value_type = @\placeholder{floating-point}@; - using difference_type = value_type; - static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; - bool is_lock_free() const noexcept; - - explicit atomic_ref(@\placeholder{floating-point}@&); - atomic_ref(const atomic_ref&) noexcept; - atomic_ref& operator=(const atomic_ref&) = delete; - - void store(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point}@ operator=(@\placeholder{floating-point}@) const noexcept; - @\placeholder{floating-point}@ load(memory_order = memory_order::seq_cst) const noexcept; - operator @\placeholdernc{floating-point}@() const noexcept; - - @\placeholder{floating-point}@ exchange(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) const noexcept; - - @\placeholder{floating-point}@ fetch_add(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point}@ fetch_sub(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) const noexcept; - - @\placeholder{floating-point}@ operator+=(@\placeholder{floating-point}@) const noexcept; - @\placeholder{floating-point}@ operator-=(@\placeholder{floating-point}@) const noexcept; - - void wait(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; - }; -} -\end{codeblock} - -\pnum -Descriptions are provided below only for members -that differ from the primary template. - -\pnum -The following operations perform arithmetic computations. -The correspondence among key, operator, and computation is specified -in \tref{atomic.types.int.comp}. - -\indexlibrarymember{fetch_add}{atomic_ref<\placeholder{floating-point}>}% -\indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -@\placeholder{floating-point}@ fetch_@\placeholdernc{key}@(@\placeholder{floating-point}@ operand, - memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Atomically replaces the value referenced by \tcode{*ptr} with -the result of the computation applied to the value referenced by \tcode{*ptr} -and the given operand. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.races}. - -\pnum -\returns -Atomically, the value referenced by \tcode{*ptr} -immediately before the effects. - -\pnum -\remarks -If the result is not a representable value for its type\iref{expr.pre}, -the result is unspecified, -but the operations otherwise have no undefined behavior. -Atomic arithmetic operations on \tcode{\placeholder{floating-point}} should conform to -the \tcode{std::numeric_limits<\placeholder{floating-point}>} traits -associated with the floating-point type\iref{limits.syn}. -The floating-point environment\iref{cfenv} -for atomic arithmetic operations on \tcode{\placeholder{floating-point}} -may be different than the calling thread's floating-point environment. -\end{itemdescr} - -\indexlibrarymember{operator+=}{atomic_ref<\placeholder{floating-point}>}% -\indexlibrarymember{operator-=}{atomic_ref<\placeholder{floating-point}>}% -\begin{itemdecl} -@\placeholder{floating-point}@ operator @\placeholder{op}@=(@\placeholder{floating-point}@ operand) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\tcode{return fetch_\placeholder{key}(operand) \placeholdernc{op} operand;} -\end{itemdescr} - -\rSec2[atomics.ref.pointer]{Partial specialization for pointers} -\indexlibraryglobal{atomic_ref}% - -\begin{codeblock} -namespace std { - template struct atomic_ref { - private: - T** ptr; // \expos - public: - using value_type = T*; - using difference_type = ptrdiff_t; - static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; - bool is_lock_free() const noexcept; - - explicit atomic_ref(T*&); - atomic_ref(const atomic_ref&) noexcept; - atomic_ref& operator=(const atomic_ref&) = delete; - - void store(T*, memory_order = memory_order::seq_cst) const noexcept; - T* operator=(T*) const noexcept; - T* load(memory_order = memory_order::seq_cst) const noexcept; - operator T*() const noexcept; - - T* exchange(T*, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(T*&, T*, - memory_order, memory_order) const noexcept; - bool compare_exchange_strong(T*&, T*, - memory_order, memory_order) const noexcept; - bool compare_exchange_weak(T*&, T*, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(T*&, T*, - memory_order = memory_order::seq_cst) const noexcept; - - T* fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept; - T* fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept; - - T* operator++(int) const noexcept; - T* operator--(int) const noexcept; - T* operator++() const noexcept; - T* operator--() const noexcept; - T* operator+=(difference_type) const noexcept; - T* operator-=(difference_type) const noexcept; - - void wait(T*, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; - }; -} -\end{codeblock} - -\pnum -Descriptions are provided below only for members -that differ from the primary template. - -\pnum -The following operations perform arithmetic computations. -The correspondence among key, operator, and computation is specified -in \tref{atomic.types.pointer.comp}. - -\indexlibrarymember{fetch_add}{atomic_ref}% -\indexlibrarymember{fetch_sub}{atomic_ref}% -\begin{itemdecl} -T* fetch_@\placeholdernc{key}@(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{T} is a complete object type. - -\pnum -\effects -Atomically replaces the value referenced by \tcode{*ptr} with -the result of the computation applied to the value referenced by \tcode{*ptr} -and the given operand. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.races}. - -\pnum -\returns -Atomically, the value referenced by \tcode{*ptr} -immediately before the effects. - -\pnum -\remarks -The result may be an undefined address, -but the operations otherwise have no undefined behavior. -\end{itemdescr} - -\indexlibrarymember{operator+=}{atomic_ref}% -\indexlibrarymember{operator-=}{atomic_ref}% -\begin{itemdecl} -T* operator @\placeholder{op}@=(difference_type operand) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\tcode{return fetch_\placeholder{key}(operand) \placeholdernc{op} operand;} -\end{itemdescr} - -\rSec2[atomics.ref.memop]{Member operators - common to integers and pointers to objects} - -\indexlibrarymember{operator++}{atomic_ref}% -\indexlibrarymember{operator++}{atomic_ref<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator++(int) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return fetch_add(1);} -\end{itemdescr} - -\indexlibrarymember{operator--}{atomic_ref}% -\indexlibrarymember{operator--}{atomic_ref<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator--(int) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return fetch_sub(1);} -\end{itemdescr} - -\indexlibrarymember{operator++}{atomic_ref}% -\indexlibrarymember{operator++}{atomic_ref<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator++() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return fetch_add(1) + 1;} -\end{itemdescr} - -\indexlibrarymember{operator--}{atomic_ref}% -\indexlibrarymember{operator--}{atomic_ref<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator--() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return fetch_sub(1) - 1;} -\end{itemdescr} - -\rSec1[atomics.types.generic]{Class template \tcode{atomic}} - -\rSec2[atomics.types.generic.general]{General} - -\indexlibraryglobal{atomic}% -\indexlibrarymember{value_type}{atomic}% -\begin{codeblock} -namespace std { - template struct atomic { - using value_type = T; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; - bool is_lock_free() const volatile noexcept; - bool is_lock_free() const noexcept; - - // \ref{atomics.types.operations}, operations on atomic types - constexpr atomic() noexcept(is_nothrow_default_constructible_v); - constexpr atomic(T) noexcept; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - T load(memory_order = memory_order::seq_cst) const volatile noexcept; - T load(memory_order = memory_order::seq_cst) const noexcept; - operator T() const volatile noexcept; - operator T() const noexcept; - void store(T, memory_order = memory_order::seq_cst) volatile noexcept; - void store(T, memory_order = memory_order::seq_cst) noexcept; - T operator=(T) volatile noexcept; - T operator=(T) noexcept; - - T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept; - T exchange(T, memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept; - bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept; - bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept; - - void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(T, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() volatile noexcept; - void notify_one() noexcept; - void notify_all() volatile noexcept; - void notify_all() noexcept; - }; -} -\end{codeblock} - -\indexlibraryglobal{atomic}% -\pnum -The template argument for \tcode{T} shall meet the -\oldconcept{CopyConstructible} and \oldconcept{CopyAssignable} requirements. -The program is ill-formed if any of -\begin{itemize} -\item \tcode{is_trivially_copyable_v}, -\item \tcode{is_copy_constructible_v}, -\item \tcode{is_move_constructible_v}, -\item \tcode{is_copy_assignable_v}, or -\item \tcode{is_move_assignable_v} -\end{itemize} -is \tcode{false}. -\begin{note} -Type arguments that are -not also statically initializable can be difficult to use. -\end{note} - -\pnum -The specialization \tcode{atomic} is a standard-layout struct. - -\pnum -\begin{note} -The representation of an atomic specialization -need not have the same size and alignment requirement as -its corresponding argument type. -\end{note} - -\rSec2[atomics.types.operations]{Operations on atomic types} - -\indexlibraryctor{atomic}% -\indexlibraryctor{atomic}% -\indexlibrary{\idxcode{atomic<\placeholder{integral}>}!constructor}% -\indexlibrary{\idxcode{atomic<\placeholder{floating-point}>}!constructor}% -\begin{itemdecl} -constexpr atomic() noexcept(is_nothrow_default_constructible_v); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{is_default_constructible_v} is \tcode{true}. - -\pnum -\effects -Initializes the atomic object with the value of \tcode{T()}. -Initialization is not an atomic operation\iref{intro.multithread}. -\end{itemdescr} - -\indexlibraryctor{atomic}% -\indexlibraryctor{atomic}% -\indexlibrary{\idxcode{atomic<\placeholder{integral}>}!constructor}% -\indexlibrary{\idxcode{atomic<\placeholder{floating-point}>}!constructor}% -\begin{itemdecl} -constexpr atomic(T desired) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the object with the value \tcode{desired}. -Initialization is not an atomic operation\iref{intro.multithread}. -\begin{note} -It is possible to have an access to an atomic object \tcode{A} -race with its construction, for example by communicating the address of the -just-constructed object \tcode{A} to another thread via -\tcode{memory_order::relaxed} operations on a suitable atomic pointer -variable, and then immediately accessing \tcode{A} in the receiving thread. -This results in undefined behavior. -\end{note} -\end{itemdescr} - -\indexlibrarymember{is_always_lock_free}{atomic}% -\indexlibrarymember{is_always_lock_free}{atomic}% -\indexlibrarymember{is_always_lock_free}{atomic<\placeholder{integral}>}% -\indexlibrarymember{is_always_lock_free}{atomic<\placeholder{floating-point}>}% -\indexlibrarymember{is_always_lock_free}{atomic>}% -\indexlibrarymember{is_always_lock_free}{atomic>}% -\begin{itemdecl} -static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The \keyword{static} data member \tcode{is_always_lock_free} is \tcode{true} -if the atomic type's operations are always lock-free, and \tcode{false} otherwise. -\begin{note} -The value of \tcode{is_always_lock_free} is consistent with the value of -the corresponding \tcode{ATOMIC_..._LOCK_FREE} macro, if defined. -\end{note} -\end{itemdescr} - -\indexlibraryglobal{atomic_is_lock_free}% -\indexlibrarymember{is_lock_free}{atomic}% -\indexlibrarymember{is_lock_free}{atomic}% -\indexlibrarymember{is_lock_free}{atomic<\placeholder{integral}>}% -\indexlibrarymember{is_lock_free}{atomic<\placeholder{floating-point}>}% -\indexlibrarymember{is_lock_free}{atomic>}% -\indexlibrarymember{is_lock_free}{atomic>}% -\begin{itemdecl} -bool is_lock_free() const volatile noexcept; -bool is_lock_free() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if the object's operations are lock-free, \tcode{false} otherwise. -\begin{note} -The return value of the \tcode{is_lock_free} member function -is consistent with the value of \tcode{is_always_lock_free} for the same type. -\end{note} -\end{itemdescr} - -\indexlibraryglobal{atomic_store}% -\indexlibraryglobal{atomic_store_explicit}% -\indexlibrarymember{store}{atomic}% -\indexlibrarymember{store}{atomic}% -\indexlibrarymember{store}{atomic<\placeholder{integral}>}% -\indexlibrarymember{store}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; -void store(T desired, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\expects -The \tcode{order} argument is neither \tcode{memory_order::consume}, -\tcode{memory_order::acquire}, nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Atomically replaces the value pointed to by \keyword{this} -with the value of \tcode{desired}. Memory is affected according to the value of -\tcode{order}. -\end{itemdescr} - -\indexlibrarymember{operator=}{atomic}% -\indexlibrarymember{operator=}{atomic}% -\indexlibrarymember{operator=}{atomic<\placeholder{integral}>}% -\indexlibrarymember{operator=}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -T operator=(T desired) volatile noexcept; -T operator=(T desired) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to \tcode{store(desired)}. - -\pnum -\returns -\tcode{desired}. -\end{itemdescr} - -\indexlibraryglobal{atomic_load}% -\indexlibraryglobal{atomic_load_explicit}% -\indexlibrarymember{load}{atomic}% -\indexlibrarymember{load}{atomic}% -\indexlibrarymember{load}{atomic<\placeholder{integral}>}% -\indexlibrarymember{load}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -T load(memory_order order = memory_order::seq_cst) const volatile noexcept; -T load(memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\expects -The \tcode{order} argument is neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Memory is affected according to the value of \tcode{order}. - -\pnum -\returns -Atomically returns the value pointed to by \keyword{this}. -\end{itemdescr} - -\indexlibrarymember{operator \placeholder{type}}{atomic}% -\indexlibrarymember{operator T*}{atomic}% -\indexlibrarymember{operator \placeholder{integral}}{atomic<\placeholder{integral}>}% -\indexlibrarymember{operator \placeholder{floating-point}}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -operator T() const volatile noexcept; -operator T() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return load();} -\end{itemdescr} - - -\indexlibraryglobal{atomic_exchange}% -\indexlibraryglobal{atomic_exchange_explicit}% -\indexlibrarymember{exchange}{atomic}% -\indexlibrarymember{exchange}{atomic}% -\indexlibrarymember{exchange}{atomic<\placeholder{integral}>}% -\indexlibrarymember{exchange}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; -T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Atomically replaces the value pointed to by \keyword{this} -with \tcode{desired}. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.multithread}. - -\pnum -\returns -Atomically returns the value pointed to by \keyword{this} immediately before the effects. -\end{itemdescr} - -\indexlibraryglobal{atomic_compare_exchange_weak}% -\indexlibraryglobal{atomic_compare_exchange_strong}% -\indexlibraryglobal{atomic_compare_exchange_weak_explicit}% -\indexlibraryglobal{atomic_compare_exchange_strong_explicit}% -\indexlibrarymember{compare_exchange_weak}{atomic}% -\indexlibrarymember{compare_exchange_weak}{atomic}% -\indexlibrarymember{compare_exchange_weak}{atomic<\placeholder{integral}>}% -\indexlibrarymember{compare_exchange_weak}{atomic<\placeholder{floating-point}>}% -\indexlibrarymember{compare_exchange_strong}{atomic}% -\indexlibrarymember{compare_exchange_strong}{atomic}% -\indexlibrarymember{compare_exchange_strong}{atomic<\placeholder{integral}>}% -\indexlibrarymember{compare_exchange_strong}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -bool compare_exchange_weak(T& expected, T desired, - memory_order success, memory_order failure) volatile noexcept; -bool compare_exchange_weak(T& expected, T desired, - memory_order success, memory_order failure) noexcept; -bool compare_exchange_strong(T& expected, T desired, - memory_order success, memory_order failure) volatile noexcept; -bool compare_exchange_strong(T& expected, T desired, - memory_order success, memory_order failure) noexcept; -bool compare_exchange_weak(T& expected, T desired, - memory_order order = memory_order::seq_cst) volatile noexcept; -bool compare_exchange_weak(T& expected, T desired, - memory_order order = memory_order::seq_cst) noexcept; -bool compare_exchange_strong(T& expected, T desired, - memory_order order = memory_order::seq_cst) volatile noexcept; -bool compare_exchange_strong(T& expected, T desired, - memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\expects -The \tcode{failure} argument is neither \tcode{memory_order::release} nor -\tcode{memory_order::acq_rel}. - -\pnum -\effects -Retrieves the value in \tcode{expected}. It then atomically -compares the value representation of the value pointed to by \keyword{this} -for equality with that previously retrieved from \tcode{expected}, -and if true, replaces the value pointed to -by \keyword{this} with that in \tcode{desired}. -If and only if the comparison is \tcode{true}, memory is affected according to the -value of \tcode{success}, and if the comparison is false, memory is affected according -to the value of \tcode{failure}. When only one \tcode{memory_order} argument is -supplied, the value of \tcode{success} is \tcode{order}, and the value of -\tcode{failure} is \tcode{order} except that a value of \tcode{memory_order::acq_rel} -shall be replaced by the value \tcode{memory_order::acquire} and a value of -\tcode{memory_order::release} shall be replaced by the value -\tcode{memory_order::relaxed}. -If and only if the comparison is false then, after the atomic operation, -the value in \tcode{expected} is replaced by the value -pointed to by \keyword{this} during the atomic comparison. -If the operation returns \tcode{true}, these -operations are atomic read-modify-write -operations\iref{intro.multithread} on the memory -pointed to by \keyword{this}. -Otherwise, these operations are atomic load operations on that memory. - -\pnum -\returns -The result of the comparison. - -\pnum -\begin{note} -For example, the effect of -\tcode{compare_exchange_strong} -on objects without padding bits\iref{term.padding.bits} is -\begin{codeblock} -if (memcmp(this, &expected, sizeof(*this)) == 0) - memcpy(this, &desired, sizeof(*this)); -else - memcpy(&expected, this, sizeof(*this)); -\end{codeblock} -\end{note} -\begin{example} -The expected use of the compare-and-exchange operations is as follows. The -compare-and-exchange operations will update \tcode{expected} when another iteration of -the loop is needed. -\begin{codeblock} -expected = current.load(); -do { - desired = function(expected); -} while (!current.compare_exchange_weak(expected, desired)); -\end{codeblock} -\end{example} -\begin{example} -Because the expected value is updated only on failure, -code releasing the memory containing the \tcode{expected} value on success will work. -For example, list head insertion will act atomically and would not introduce a -data race in the following code: -\begin{codeblock} -do { - p->next = head; // make new list node point to the current head -} while (!head.compare_exchange_weak(p->next, p)); // try to insert -\end{codeblock} -\end{example} - -\pnum -Implementations should ensure that weak compare-and-exchange operations do not -consistently return \tcode{false} unless either the atomic object has value -different from \tcode{expected} or there are concurrent modifications to the -atomic object. - -\pnum -\remarks -A weak compare-and-exchange operation may fail spuriously. That is, even when -the contents of memory referred to by \tcode{expected} and \keyword{this} are -equal, it may return \tcode{false} and store back to \tcode{expected} the same memory -contents that were originally there. -\begin{note} -This -spurious failure enables implementation of compare-and-exchange on a broader class of -machines, e.g., load-locked store-conditional machines. A -consequence of spurious failure is that nearly all uses of weak compare-and-exchange -will be in a loop. -When a compare-and-exchange is in a loop, the weak version will yield better performance -on some platforms. When a weak compare-and-exchange would require a loop and a strong one -would not, the strong one is preferable. -\end{note} - -\pnum -\begin{note} -Under cases where the \tcode{memcpy} and \tcode{memcmp} semantics of the compare-and-exchange -operations apply, the comparisons can fail for values that compare equal with -\tcode{operator==} if the value representation has trap bits or alternate -representations of the same value. Notably, on implementations conforming to -ISO/IEC/IEEE 60559, floating-point \tcode{-0.0} and \tcode{+0.0} -will not compare equal with \tcode{memcmp} but will compare equal with \tcode{operator==}, -and NaNs with the same payload will compare equal with \tcode{memcmp} but will not -compare equal with \tcode{operator==}. -\end{note} -\begin{note} -Because compare-and-exchange acts on an object's value representation, -padding bits that never participate in the object's value representation -are ignored. As a consequence, the following code is guaranteed to avoid -spurious failure: -\begin{codeblock} -struct padded { - char clank = 0x42; - // Padding here. - unsigned biff = 0xC0DEFEFE; -}; -atomic pad = {}; - -bool zap() { - padded expected, desired{0, 0}; - return pad.compare_exchange_strong(expected, desired); -} -\end{codeblock} -\end{note} -\begin{note} -For a union with bits that participate in the value representation -of some members but not others, compare-and-exchange might always fail. -This is because such padding bits have an indeterminate value when they -do not participate in the value representation of the active member. -As a consequence, the following code is not guaranteed to ever succeed: -\begin{codeblock} -union pony { - double celestia = 0.; - short luna; // padded -}; -atomic princesses = {}; - -bool party(pony desired) { - pony expected; - return princesses.compare_exchange_strong(expected, desired); -} -\end{codeblock} -\end{note} -\end{itemdescr} - -\indexlibrarymember{wait}{atomic}% -\indexlibrarymember{wait}{atomic}% -\indexlibrarymember{wait}{atomic<\placeholder{integral}>}% -\indexlibrarymember{wait}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept; -void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Repeatedly performs the following steps, in order: -\begin{itemize} -\item - Evaluates \tcode{load(order)} and - compares its value representation for equality against that of \tcode{old}. -\item - If they compare unequal, returns. -\item - Blocks until it - is unblocked by an atomic notifying operation or is unblocked spuriously. -\end{itemize} - -\pnum -\remarks -This function is an atomic waiting operation\iref{atomics.wait}. -\end{itemdescr} - -\indexlibrarymember{notify_one}{atomic}% -\indexlibrarymember{notify_one}{atomic}% -\indexlibrarymember{notify_one}{atomic<\placeholder{integral}>}% -\indexlibrarymember{notify_one}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -void notify_one() volatile noexcept; -void notify_one() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of at least one atomic waiting operation -that is eligible to be unblocked\iref{atomics.wait} by this call, -if any such atomic waiting operations exist. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\indexlibrarymember{notify_all}{atomic}% -\indexlibrarymember{notify_all}{atomic}% -\indexlibrarymember{notify_all}{atomic<\placeholder{integral}>}% -\indexlibrarymember{notify_all}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -void notify_all() volatile noexcept; -void notify_all() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of all atomic waiting operations -that are eligible to be unblocked\iref{atomics.wait} by this call. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\rSec2[atomics.types.int]{Specializations for integers} - -\indexlibrary{\idxcode{atomic<\placeholder{integral}>}}% -\pnum -There are specializations of the \tcode{atomic} -class template for the integral types -\tcode{char}, -\tcode{signed char}, -\tcode{unsigned char}, -\tcode{short}, -\tcode{unsigned short}, -\tcode{int}, -\tcode{unsigned int}, -\tcode{long}, -\tcode{unsigned long}, -\tcode{long long}, -\tcode{unsigned long long}, -\keyword{char8_t}, -\keyword{char16_t}, -\keyword{char32_t}, -\keyword{wchar_t}, -and any other types needed by the typedefs in the header \libheaderref{cstdint}. -For each such type \tcode{\placeholder{integral}}, the specialization -\tcode{atomic<\placeholder{integral}>} provides additional atomic operations appropriate to integral types. -\begin{note} -The specialization \tcode{atomic} -uses the primary template\iref{atomics.types.generic}. -\end{note} - -\begin{codeblock} -namespace std { - template<> struct atomic<@\placeholder{integral}@> { - using value_type = @\placeholder{integral}@; - using difference_type = value_type; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; - bool is_lock_free() const volatile noexcept; - bool is_lock_free() const noexcept; - - constexpr atomic() noexcept; - constexpr atomic(@\placeholdernc{integral}@) noexcept; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - void store(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - void store(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{integral}@ operator=(@\placeholdernc{integral}@) volatile noexcept; - @\placeholdernc{integral}@ operator=(@\placeholdernc{integral}@) noexcept; - @\placeholdernc{integral}@ load(memory_order = memory_order::seq_cst) const volatile noexcept; - @\placeholdernc{integral}@ load(memory_order = memory_order::seq_cst) const noexcept; - operator @\placeholdernc{integral}@() const volatile noexcept; - operator @\placeholdernc{integral}@() const noexcept; - - @\placeholdernc{integral}@ exchange(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral}@ exchange(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order, memory_order) noexcept; - bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order, memory_order) noexcept; - bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, - memory_order = memory_order::seq_cst) noexcept; - - @\placeholdernc{integral}@ fetch_add(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral}@ fetch_add(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{integral}@ fetch_sub(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral}@ fetch_sub(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{integral}@ fetch_and(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral}@ fetch_and(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{integral}@ fetch_or(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral}@ fetch_or(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{integral}@ fetch_xor(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral}@ fetch_xor(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; - - @\placeholdernc{integral}@ operator++(int) volatile noexcept; - @\placeholdernc{integral}@ operator++(int) noexcept; - @\placeholdernc{integral}@ operator--(int) volatile noexcept; - @\placeholdernc{integral}@ operator--(int) noexcept; - @\placeholdernc{integral}@ operator++() volatile noexcept; - @\placeholdernc{integral}@ operator++() noexcept; - @\placeholdernc{integral}@ operator--() volatile noexcept; - @\placeholdernc{integral}@ operator--() noexcept; - @\placeholdernc{integral}@ operator+=(@\placeholdernc{integral}@) volatile noexcept; - @\placeholdernc{integral}@ operator+=(@\placeholdernc{integral}@) noexcept; - @\placeholdernc{integral}@ operator-=(@\placeholdernc{integral}@) volatile noexcept; - @\placeholdernc{integral}@ operator-=(@\placeholdernc{integral}@) noexcept; - @\placeholdernc{integral}@ operator&=(@\placeholdernc{integral}@) volatile noexcept; - @\placeholdernc{integral}@ operator&=(@\placeholdernc{integral}@) noexcept; - @\placeholdernc{integral}@ operator|=(@\placeholdernc{integral}@) volatile noexcept; - @\placeholdernc{integral}@ operator|=(@\placeholdernc{integral}@) noexcept; - @\placeholdernc{integral}@ operator^=(@\placeholdernc{integral}@) volatile noexcept; - @\placeholdernc{integral}@ operator^=(@\placeholdernc{integral}@) noexcept; - - void wait(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() volatile noexcept; - void notify_one() noexcept; - void notify_all() volatile noexcept; - void notify_all() noexcept; - }; -} -\end{codeblock} - -\pnum -The atomic integral specializations -are standard-layout structs. -They each have -a trivial destructor. - -\pnum -Descriptions are provided below only for members that differ from the primary template. - -\pnum -The following operations perform arithmetic computations. -The correspondence among key, operator, and computation is specified -in \tref{atomic.types.int.comp}. - -\begin{floattable} -{Atomic arithmetic computations}{atomic.types.int.comp}{lll|lll} -\hline -\hdstyle{\tcode{\placeholder{key}}} & - \hdstyle{Op} & - \hdstyle{Computation} & -\hdstyle{\tcode{\placeholder{key}}} & - \hdstyle{Op} & - \hdstyle{Computation} \\ \hline -\tcode{add} & - \tcode{+} & - addition & -\tcode{sub} & - \tcode{-} & - subtraction \\ -\tcode{or} & - \tcode{|} & - bitwise inclusive or & -\tcode{xor} & - \tcode{\caret} & - bitwise exclusive or \\ -\tcode{and} & - \tcode{\&} & - bitwise and &&&\\ -\end{floattable} - -\indexlibraryglobal{atomic_fetch_add}% -\indexlibraryglobal{atomic_fetch_and}% -\indexlibraryglobal{atomic_fetch_or}% -\indexlibraryglobal{atomic_fetch_sub}% -\indexlibraryglobal{atomic_fetch_xor}% -\indexlibraryglobal{atomic_fetch_add_explicit}% -\indexlibraryglobal{atomic_fetch_and_explicit}% -\indexlibraryglobal{atomic_fetch_or_explicit}% -\indexlibraryglobal{atomic_fetch_sub_explicit}% -\indexlibraryglobal{atomic_fetch_xor_explicit}% -\indexlibrarymember{fetch_add}{atomic<\placeholder{integral}>}% -\indexlibrarymember{fetch_and}{atomic<\placeholder{integral}>}% -\indexlibrarymember{fetch_or}{atomic<\placeholder{integral}>}% -\indexlibrarymember{fetch_sub}{atomic<\placeholder{integral}>}% -\indexlibrarymember{fetch_xor}{atomic<\placeholder{integral}>}% -\begin{itemdecl} -T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; -T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Atomically replaces the value pointed to by -\keyword{this} with the result of the computation applied to the -value pointed to by \keyword{this} and the given \tcode{operand}. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.multithread}. - -\pnum -\returns -Atomically, the value pointed to by \keyword{this} immediately before the effects. - -\pnum -\indextext{signed integer representation!two's complement}% -\remarks -For signed integer types, -the result is as if the object value and parameters -were converted to their corresponding unsigned types, -the computation performed on those types, and -the result converted back to the signed type. -\begin{note} -There are no undefined results arising from the computation. -\end{note} - -\end{itemdescr} - -\indexlibrarymember{operator+=}{atomic}% -\indexlibrarymember{operator-=}{atomic}% -\indexlibrarymember{operator+=}{atomic<\placeholder{integral}>}% -\indexlibrarymember{operator-=}{atomic<\placeholder{integral}>}% -\indexlibrarymember{operator\&=}{atomic<\placeholder{integral}>}% -\indexlibrarymember{operator"|=}{atomic<\placeholder{integral}>}% -\indexlibrarymember{operator\caret=}{atomic<\placeholder{integral}>}% -\begin{itemdecl} -T operator @\placeholder{op}@=(T operand) volatile noexcept; -T operator @\placeholder{op}@=(T operand) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_\placeholder{key}(operand) \placeholder{op} operand;} -\end{itemdescr} - -\rSec2[atomics.types.float]{Specializations for floating-point types} - -\indexlibrary{\idxcode{atomic<\placeholder{floating-point}>}}% -\pnum -There are specializations of the \tcode{atomic} -class template for the floating-point types -\tcode{float}, -\tcode{double}, and -\tcode{long double}. -For each such type \tcode{\placeholdernc{floating-point}}, -the specialization \tcode{atomic<\placeholder{floating-point}>} -provides additional atomic operations appropriate to floating-point types. - -\begin{codeblock} -namespace std { - template<> struct atomic<@\placeholder{floating-point}@> { - using value_type = @\placeholdernc{floating-point}@; - using difference_type = value_type; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; - bool is_lock_free() const volatile noexcept; - bool is_lock_free() const noexcept; - - constexpr atomic() noexcept; - constexpr atomic(@\placeholder{floating-point}@) noexcept; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - void store(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) volatile noexcept; - void store(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{floating-point}@ operator=(@\placeholder{floating-point}@) volatile noexcept; - @\placeholdernc{floating-point}@ operator=(@\placeholder{floating-point}@) noexcept; - @\placeholdernc{floating-point}@ load(memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point}@ load(memory_order = memory_order::seq_cst) noexcept; - operator @\placeholdernc{floating-point}@() volatile noexcept; - operator @\placeholdernc{floating-point}@() noexcept; - - @\placeholdernc{floating-point}@ exchange(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point}@ exchange(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order, memory_order) noexcept; - bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order, memory_order) noexcept; - bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) noexcept; - - @\placeholdernc{floating-point}@ fetch_add(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point}@ fetch_add(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{floating-point}@ fetch_sub(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point}@ fetch_sub(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) noexcept; - - @\placeholdernc{floating-point}@ operator+=(@\placeholder{floating-point}@) volatile noexcept; - @\placeholdernc{floating-point}@ operator+=(@\placeholder{floating-point}@) noexcept; - @\placeholdernc{floating-point}@ operator-=(@\placeholder{floating-point}@) volatile noexcept; - @\placeholdernc{floating-point}@ operator-=(@\placeholder{floating-point}@) noexcept; - - void wait(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() volatile noexcept; - void notify_one() noexcept; - void notify_all() volatile noexcept; - void notify_all() noexcept; - }; -} -\end{codeblock} - -\pnum -The atomic floating-point specializations -are standard-layout structs. -They each have -a trivial destructor. - -\pnum -Descriptions are provided below only for members that differ from the primary template. - -\pnum -The following operations perform arithmetic addition and subtraction computations. -The correspondence among key, operator, and computation is specified -in \tref{atomic.types.int.comp}. - -\indexlibraryglobal{atomic_fetch_add}% -\indexlibraryglobal{atomic_fetch_sub}% -\indexlibraryglobal{atomic_fetch_add_explicit}% -\indexlibraryglobal{atomic_fetch_sub_explicit}% -\indexlibrarymember{fetch_add}{atomic<\placeholder{floating-point}>}% -\indexlibrarymember{fetch_sub}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; -T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Atomically replaces the value pointed to by \keyword{this} -with the result of the computation applied to the value pointed -to by \keyword{this} and the given \tcode{operand}. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.multithread}. - -\pnum -\returns -Atomically, the value pointed to by \keyword{this} immediately before the effects. - -\pnum -\remarks -If the result is not a representable value for its type\iref{expr.pre} -the result is unspecified, but the operations otherwise have no undefined -behavior. Atomic arithmetic operations on \tcode{\placeholder{floating-point}} -should conform to the \tcode{std::numeric_limits<\placeholder{floating-point}>} -traits associated with the floating-point type\iref{limits.syn}. -The floating-point environment\iref{cfenv} for atomic arithmetic operations -on \tcode{\placeholder{floating-point}} may be different than the -calling thread's floating-point environment. -\end{itemdescr} - -\indexlibrarymember{operator+=}{atomic}% -\indexlibrarymember{operator-=}{atomic}% -\indexlibrarymember{operator+=}{atomic<\placeholder{floating-point}>}% -\indexlibrarymember{operator-=}{atomic<\placeholder{floating-point}>}% -\begin{itemdecl} -T operator @\placeholder{op}@=(T operand) volatile noexcept; -T operator @\placeholder{op}@=(T operand) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_\placeholder{key}(operand) \placeholder{op} operand;} - -\pnum -\remarks -If the result is not a representable value for its type\iref{expr.pre} -the result is unspecified, but the operations otherwise have no undefined -behavior. Atomic arithmetic operations on \tcode{\placeholder{floating-point}} -should conform to the \tcode{std::numeric_limits<\placeholder{floating-point}>} -traits associated with the floating-point type\iref{limits.syn}. -The floating-point environment\iref{cfenv} for atomic arithmetic operations -on \tcode{\placeholder{floating-point}} may be different than the -calling thread's floating-point environment. -\end{itemdescr} - -\rSec2[atomics.types.pointer]{Partial specialization for pointers} -\indexlibraryglobal{atomic}% - -\begin{codeblock} -namespace std { - template struct atomic { - using value_type = T*; - using difference_type = ptrdiff_t; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; - bool is_lock_free() const volatile noexcept; - bool is_lock_free() const noexcept; - - constexpr atomic() noexcept; - constexpr atomic(T*) noexcept; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - void store(T*, memory_order = memory_order::seq_cst) volatile noexcept; - void store(T*, memory_order = memory_order::seq_cst) noexcept; - T* operator=(T*) volatile noexcept; - T* operator=(T*) noexcept; - T* load(memory_order = memory_order::seq_cst) const volatile noexcept; - T* load(memory_order = memory_order::seq_cst) const noexcept; - operator T*() const volatile noexcept; - operator T*() const noexcept; - - T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept; - T* exchange(T*, memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept; - bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept; - bool compare_exchange_weak(T*&, T*, - memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(T*&, T*, - memory_order = memory_order::seq_cst) noexcept; - bool compare_exchange_strong(T*&, T*, - memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(T*&, T*, - memory_order = memory_order::seq_cst) noexcept; - - T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; - T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; - T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; - T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; - - T* operator++(int) volatile noexcept; - T* operator++(int) noexcept; - T* operator--(int) volatile noexcept; - T* operator--(int) noexcept; - T* operator++() volatile noexcept; - T* operator++() noexcept; - T* operator--() volatile noexcept; - T* operator--() noexcept; - T* operator+=(ptrdiff_t) volatile noexcept; - T* operator+=(ptrdiff_t) noexcept; - T* operator-=(ptrdiff_t) volatile noexcept; - T* operator-=(ptrdiff_t) noexcept; - - void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(T*, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() volatile noexcept; - void notify_one() noexcept; - void notify_all() volatile noexcept; - void notify_all() noexcept; - }; -} -\end{codeblock} - -\indexlibraryglobal{atomic}% -\pnum -There is a partial specialization of the \tcode{atomic} class template for pointers. -Specializations of this partial specialization are standard-layout structs. -They each have a trivial destructor. - -\pnum -Descriptions are provided below only for members that differ from the primary template. - -\pnum -The following operations perform pointer arithmetic. -The correspondence among key, operator, and computation is specified -in \tref{atomic.types.pointer.comp}. - -\begin{floattable} -{Atomic pointer computations}{atomic.types.pointer.comp}{lll|lll} -\hline -\hdstyle{\tcode{\placeholder{key}}} & - \hdstyle{Op} & - \hdstyle{Computation} & -\hdstyle{\tcode{\placeholder{key}}} & - \hdstyle{Op} & - \hdstyle{Computation} \\ \hline -\tcode{add} & - \tcode{+} & - addition & -\tcode{sub} & - \tcode{-} & - subtraction \\ -\end{floattable} - -\indexlibraryglobal{atomic_fetch_add}% -\indexlibraryglobal{atomic_fetch_sub}% -\indexlibraryglobal{atomic_fetch_add_explicit}% -\indexlibraryglobal{atomic_fetch_sub_explicit}% -\indexlibrarymember{fetch_add}{atomic}% -\indexlibrarymember{fetch_sub}{atomic}% -\begin{itemdecl} -T* fetch_@\placeholdernc{key}@(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept; -T* fetch_@\placeholdernc{key}@(ptrdiff_t operand, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\mandates -\tcode{T} is a complete object type. -\begin{note} -Pointer arithmetic on \tcode{void*} or function pointers is ill-formed. -\end{note} - -\pnum -\effects -Atomically replaces the value pointed to by -\keyword{this} with the result of the computation applied to the -value pointed to by \keyword{this} and the given \tcode{operand}. -Memory is affected according to the value of \tcode{order}. -These operations are atomic read-modify-write operations\iref{intro.multithread}. - -\pnum -\returns -Atomically, the value pointed to by \keyword{this} immediately before the effects. - -\pnum -\remarks -The result may be an undefined address, -but the operations otherwise have no undefined behavior. -\end{itemdescr} - -\indexlibrarymember{operator+=}{atomic}% -\indexlibrarymember{operator-=}{atomic}% -\begin{itemdecl} -T* operator @\placeholder{op}@=(ptrdiff_t operand) volatile noexcept; -T* operator @\placeholder{op}@=(ptrdiff_t operand) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_\placeholder{key}(operand) \placeholder{op} operand;} -\end{itemdescr} - -\rSec2[atomics.types.memop]{Member operators common to integers and pointers to objects} - -\indexlibrarymember{operator++}{atomic}% -\indexlibrarymember{operator++}{atomic<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator++(int) volatile noexcept; -value_type operator++(int) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_add(1);} -\end{itemdescr} - -\indexlibrarymember{operator--}{atomic}% -\indexlibrarymember{operator--}{atomic<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator--(int) volatile noexcept; -value_type operator--(int) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_sub(1);} -\end{itemdescr} - -\indexlibrarymember{operator++}{atomic}% -\indexlibrarymember{operator++}{atomic<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator++() volatile noexcept; -value_type operator++() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_add(1) + 1;} -\end{itemdescr} - -\indexlibrarymember{operator--}{atomic}% -\indexlibrarymember{operator--}{atomic<\placeholder{integral}>}% -\begin{itemdecl} -value_type operator--() volatile noexcept; -value_type operator--() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -For the \tcode{volatile} overload of this function, -\tcode{is_always_lock_free} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return fetch_sub(1) - 1;} -\end{itemdescr} - -\rSec2[util.smartptr.atomic]{Partial specializations for smart pointers}% -\indextext{atomic!smart pointers|(}% - -\rSec3[util.smartptr.atomic.general]{General} - -\pnum -The library provides partial specializations of the \tcode{atomic} template -for shared-ownership smart pointers\iref{util.sharedptr}. -\begin{note} -The partial specializations are declared in header \libheaderref{memory}. -\end{note} -The behavior of all operations is as specified in \ref{atomics.types.generic}, -unless specified otherwise. -The template parameter \tcode{T} of these partial specializations -may be an incomplete type. - -\pnum -All changes to an atomic smart pointer in \ref{util.smartptr.atomic}, and -all associated \tcode{use_count} increments, -are guaranteed to be performed atomically. -Associated \tcode{use_count} decrements -are sequenced after the atomic operation, -but are not required to be part of it. -Any associated deletion and deallocation -are sequenced after the atomic update step and -are not part of the atomic operation. -\begin{note} -If the atomic operation uses locks, -locks acquired by the implementation -will be held when any \tcode{use_count} adjustments are performed, and -will not be held when any destruction or deallocation -resulting from this is performed. -\end{note} - -\pnum -\begin{example} -\begin{codeblock} -template class atomic_list { - struct node { - T t; - shared_ptr next; - }; - atomic> head; - -public: - auto find(T t) const { - auto p = head.load(); - while (p && p->t != t) - p = p->next; - - return shared_ptr(move(p)); - } - - void push_front(T t) { - auto p = make_shared(); - p->t = t; - p->next = head; - while (!head.compare_exchange_weak(p->next, p)) {} - } -}; -\end{codeblock} -\end{example} - -\rSec3[util.smartptr.atomic.shared]{Partial specialization for \tcode{shared_ptr}} -\indexlibraryglobal{atomic>}% -\begin{codeblock} -namespace std { - template struct atomic> { - using value_type = shared_ptr; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; - bool is_lock_free() const noexcept; - - constexpr atomic() noexcept; - constexpr atomic(nullptr_t) noexcept : atomic() { } - atomic(shared_ptr desired) noexcept; - atomic(const atomic&) = delete; - void operator=(const atomic&) = delete; - - shared_ptr load(memory_order order = memory_order::seq_cst) const noexcept; - operator shared_ptr() const noexcept; - void store(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; - void operator=(shared_ptr desired) noexcept; - - shared_ptr exchange(shared_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; - bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, - memory_order success, memory_order failure) noexcept; - bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, - memory_order success, memory_order failure) noexcept; - bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; - bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; - - void wait(shared_ptr old, memory_order order = memory_order::seq_cst) const noexcept; - void notify_one() noexcept; - void notify_all() noexcept; - - private: - shared_ptr p; // \expos - }; -} -\end{codeblock} - -\indexlibraryctor{atomic>}% -\begin{itemdecl} -constexpr atomic() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{p\{\}}. -\end{itemdescr} - -\indexlibraryctor{atomic>}% -\begin{itemdecl} -atomic(shared_ptr desired) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the object with the value \tcode{desired}. -Initialization is not an atomic operation\iref{intro.multithread}. -\begin{note} -It is possible to have an access to -an atomic object \tcode{A} race with its construction, -for example, -by communicating the address of the just-constructed object \tcode{A} -to another thread via \tcode{memory_order::relaxed} operations -on a suitable atomic pointer variable, and -then immediately accessing \tcode{A} in the receiving thread. -This results in undefined behavior. -\end{note} -\end{itemdescr} - -\indexlibrarymember{store}{atomic>}% -\begin{itemdecl} -void store(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is neither -\tcode{memory_order::consume}, -\tcode{memory_order::acquire}, nor -\tcode{memory_order::acq_rel}. - -\pnum -\effects -Atomically replaces the value pointed to by \keyword{this} with -the value of \tcode{desired} as if by \tcode{p.swap(desired)}. -Memory is affected according to the value of \tcode{order}. -\end{itemdescr} - -\indexlibrarymember{operator=}{atomic>}% -\begin{itemdecl} -void operator=(shared_ptr desired) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{store(desired)}. -\end{itemdescr} - -\indexlibrarymember{load}{atomic>}% -\begin{itemdecl} -shared_ptr load(memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is neither -\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Memory is affected according to the value of \tcode{order}. - -\pnum -\returns -Atomically returns \tcode{p}. -\end{itemdescr} - -\indexlibrarymember{operator shared_ptr}{atomic>}% -\begin{itemdecl} -operator shared_ptr() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return load();} -\end{itemdescr} - -\indexlibrarymember{exchange}{atomic>}% -\begin{itemdecl} -shared_ptr exchange(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Atomically replaces \tcode{p} with \tcode{desired} -as if by \tcode{p.swap(desired)}. -Memory is affected according to the value of \tcode{order}. -This is an atomic read-modify-write operation\iref{intro.races}. - -\pnum -\returns -Atomically returns the value of \tcode{p} immediately before the effects. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_weak}{atomic>}% -\indexlibrarymember{compare_exchange_strong}{atomic>}% -\begin{itemdecl} -bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, - memory_order success, memory_order failure) noexcept; -bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, - memory_order success, memory_order failure) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{failure} is neither -\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -If \tcode{p} is equivalent to \tcode{expected}, -assigns \tcode{desired} to \tcode{p} and -has synchronization semantics corresponding to the value of \tcode{success}, -otherwise assigns \tcode{p} to \tcode{expected} and -has synchronization semantics corresponding to the value of \tcode{failure}. - -\pnum -\returns -\tcode{true} if \tcode{p} was equivalent to \tcode{expected}, -\tcode{false} otherwise. - -\pnum -\remarks -Two \tcode{shared_ptr} objects are equivalent if -they store the same pointer value and -either share ownership or are both empty. -The weak form may fail spuriously. See \ref{atomics.types.operations}. - -\pnum -If the operation returns \tcode{true}, -\tcode{expected} is not accessed after the atomic update and -the operation is an atomic read-modify-write operation\iref{intro.multithread} -on the memory pointed to by \keyword{this}. -Otherwise, the operation is an atomic load operation on that memory, and -\tcode{expected} is updated with the existing value -read from the atomic object in the attempted atomic update. -The \tcode{use_count} update corresponding to the write to \tcode{expected} -is part of the atomic operation. -The write to \tcode{expected} itself -is not required to be part of the atomic operation. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_weak}{atomic>}% -\begin{itemdecl} -bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -return compare_exchange_weak(expected, desired, order, fail_order); -\end{codeblock} -where \tcode{fail_order} is the same as \tcode{order} -except that a value of \tcode{memory_order::acq_rel} -shall be replaced by the value \tcode{memory_order::acquire} and -a value of \tcode{memory_order::release} -shall be replaced by the value \tcode{memory_order::relaxed}. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_strong}{atomic>}% -\begin{itemdecl} -bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -return compare_exchange_strong(expected, desired, order, fail_order); -\end{codeblock} -where \tcode{fail_order} is the same as \tcode{order} -except that a value of \tcode{memory_order::acq_rel} -shall be replaced by the value \tcode{memory_order::acquire} and -a value of \tcode{memory_order::release} -shall be replaced by the value \tcode{memory_order::relaxed}. -\end{itemdescr} - -\indexlibrarymember{wait}{atomic>}% -\begin{itemdecl} -void wait(shared_ptr old, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is -neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Repeatedly performs the following steps, in order: -\begin{itemize} -\item - Evaluates \tcode{load(order)} and compares it to \tcode{old}. -\item - If the two are not equivalent, returns. -\item - Blocks until it - is unblocked by an atomic notifying operation or is unblocked spuriously. -\end{itemize} - -\pnum -\remarks -Two \tcode{shared_ptr} objects are equivalent -if they store the same pointer and either share ownership or are both empty. -This function is an atomic waiting operation\iref{atomics.wait}. -\end{itemdescr} - -\indexlibrarymember{notify_one}{atomic>}% -\begin{itemdecl} -void notify_one() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of at least one atomic waiting operation -that is eligible to be unblocked\iref{atomics.wait} by this call, -if any such atomic waiting operations exist. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\indexlibrarymember{notify_all}{atomic>}% -\begin{itemdecl} -void notify_all() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of all atomic waiting operations -that are eligible to be unblocked\iref{atomics.wait} by this call. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\rSec3[util.smartptr.atomic.weak]{Partial specialization for \tcode{weak_ptr}} -\indexlibraryglobal{atomic>}% -\begin{codeblock} -namespace std { - template struct atomic> { - using value_type = weak_ptr; - - static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; - bool is_lock_free() const noexcept; - - constexpr atomic() noexcept; - atomic(weak_ptr desired) noexcept; - atomic(const atomic&) = delete; - void operator=(const atomic&) = delete; - - weak_ptr load(memory_order order = memory_order::seq_cst) const noexcept; - operator weak_ptr() const noexcept; - void store(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; - void operator=(weak_ptr desired) noexcept; - - weak_ptr exchange(weak_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; - bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, - memory_order success, memory_order failure) noexcept; - bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, - memory_order success, memory_order failure) noexcept; - bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; - bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; - - void wait(weak_ptr old, memory_order order = memory_order::seq_cst) const noexcept; - void notify_one() noexcept; - void notify_all() noexcept; - - private: - weak_ptr p; // \expos - }; -} -\end{codeblock} - -\indexlibraryctor{atomic>}% -\begin{itemdecl} -constexpr atomic() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{p\{\}}. -\end{itemdescr} - -\indexlibraryctor{atomic>}% -\begin{itemdecl} -atomic(weak_ptr desired) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the object with the value \tcode{desired}. -Initialization is not an atomic operation\iref{intro.multithread}. -\begin{note} -It is possible to have an access to -an atomic object \tcode{A} race with its construction, -for example, -by communicating the address of the just-constructed object \tcode{A} -to another thread via \tcode{memory_order::relaxed} operations -on a suitable atomic pointer variable, and -then immediately accessing \tcode{A} in the receiving thread. -This results in undefined behavior. -\end{note} -\end{itemdescr} - -\indexlibrarymember{store}{atomic>}% -\begin{itemdecl} -void store(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is neither -\tcode{memory_order::consume}, -\tcode{memory_order::acquire}, nor -\tcode{memory_order::acq_rel}. - -\pnum -\effects -Atomically replaces the value pointed to by \keyword{this} with -the value of \tcode{desired} as if by \tcode{p.swap(desired)}. -Memory is affected according to the value of \tcode{order}. -\end{itemdescr} - -\indexlibrarymember{operator=}{atomic>}% -\begin{itemdecl} -void operator=(weak_ptr desired) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{store(desired)}. -\end{itemdescr} - -\indexlibrarymember{load}{atomic>}% -\begin{itemdecl} -weak_ptr load(memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is neither -\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Memory is affected according to the value of \tcode{order}. - -\pnum -\returns -Atomically returns \tcode{p}. -\end{itemdescr} - -\indexlibrarymember{operator weak_ptr}{atomic>}% -\begin{itemdecl} -operator weak_ptr() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return load();} -\end{itemdescr} - -\indexlibrarymember{exchange}{atomic>}% -\begin{itemdecl} -weak_ptr exchange(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Atomically replaces \tcode{p} with \tcode{desired} -as if by \tcode{p.swap(desired)}. -Memory is affected according to the value of \tcode{order}. -This is an atomic read-modify-write operation\iref{intro.races}. - -\pnum -\returns -Atomically returns the value of \tcode{p} immediately before the effects. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_weak}{atomic>}% -\begin{itemdecl} -bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, - memory_order success, memory_order failure) noexcept; -bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, - memory_order success, memory_order failure) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{failure} is neither -\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -If \tcode{p} is equivalent to \tcode{expected}, -assigns \tcode{desired} to \tcode{p} and -has synchronization semantics corresponding to the value of \tcode{success}, -otherwise assigns \tcode{p} to \tcode{expected} and -has synchronization semantics corresponding to the value of \tcode{failure}. - -\pnum -\returns -\tcode{true} if \tcode{p} was equivalent to \tcode{expected}, -\tcode{false} otherwise. - -\pnum -\remarks -Two \tcode{weak_ptr} objects are equivalent if -they store the same pointer value and -either share ownership or are both empty. -The weak form may fail spuriously. See \ref{atomics.types.operations}. - -\pnum -If the operation returns \tcode{true}, -\tcode{expected} is not accessed after the atomic update and -the operation is an atomic read-modify-write operation\iref{intro.multithread} -on the memory pointed to by \keyword{this}. -Otherwise, the operation is an atomic load operation on that memory, and -\tcode{expected} is updated with the existing value -read from the atomic object in the attempted atomic update. -The \tcode{use_count} update corresponding to the write to \tcode{expected} -is part of the atomic operation. -The write to \tcode{expected} itself -is not required to be part of the atomic operation. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_weak}{atomic>}% -\begin{itemdecl} -bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -return compare_exchange_weak(expected, desired, order, fail_order); -\end{codeblock} -where \tcode{fail_order} is the same as \tcode{order} -except that a value of \tcode{memory_order::acq_rel} -shall be replaced by the value \tcode{memory_order::acquire} and -a value of \tcode{memory_order::release} -shall be replaced by the value \tcode{memory_order::relaxed}. -\end{itemdescr} - -\indexlibrarymember{compare_exchange_strong}{atomic>}% -\begin{itemdecl} -bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, - memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -return compare_exchange_strong(expected, desired, order, fail_order); -\end{codeblock} -where \tcode{fail_order} is the same as \tcode{order} -except that a value of \tcode{memory_order::acq_rel} -shall be replaced by the value \tcode{memory_order::acquire} and -a value of \tcode{memory_order::release} -shall be replaced by the value \tcode{memory_order::relaxed}. -\end{itemdescr} - -\indexlibrarymember{wait}{atomic>}% -\begin{itemdecl} -void wait(weak_ptr old, memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{order} is -neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Repeatedly performs the following steps, in order: -\begin{itemize} -\item - Evaluates \tcode{load(order)} and compares it to \tcode{old}. -\item - If the two are not equivalent, returns. -\item - Blocks until it - is unblocked by an atomic notifying operation or is unblocked spuriously. -\end{itemize} - -\pnum -\remarks -Two \tcode{weak_ptr} objects are equivalent -if they store the same pointer and either share ownership or are both empty. -This function is an atomic waiting operation\iref{atomics.wait}. -\end{itemdescr} - - -\indexlibrarymember{notify_one}{atomic>}% -\begin{itemdecl} -void notify_one() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of at least one atomic waiting operation -that is eligible to be unblocked\iref{atomics.wait} by this call, -if any such atomic waiting operations exist. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\indexlibrarymember{notify_all}{atomic>}% -\begin{itemdecl} -void notify_all() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of all atomic waiting operations -that are eligible to be unblocked\iref{atomics.wait} by this call. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} -\indextext{atomic!smart pointers|)} - -\rSec1[atomics.nonmembers]{Non-member functions} - -\pnum -A non-member function template whose name matches the pattern -\tcode{atomic_\placeholder{f}} or the pattern \tcode{atomic_\placeholder{f}_explicit} -invokes the member function \tcode{\placeholder{f}}, with the value of the -first parameter as the object expression and the values of the remaining parameters -(if any) as the arguments of the member function call, in order. An argument -for a parameter of type \tcode{atomic::value_type*} is dereferenced when -passed to the member function call. -If no such member function exists, the program is ill-formed. - -\pnum -\begin{note} -The non-member functions enable programmers to write code that can be -compiled as either C or \Cpp{}, for example in a shared header file. -\end{note} - -\rSec1[atomics.flag]{Flag type and operations} - -\begin{codeblock} -namespace std { - struct atomic_flag { - constexpr atomic_flag() noexcept; - atomic_flag(const atomic_flag&) = delete; - atomic_flag& operator=(const atomic_flag&) = delete; - atomic_flag& operator=(const atomic_flag&) volatile = delete; - - bool test(memory_order = memory_order::seq_cst) const volatile noexcept; - bool test(memory_order = memory_order::seq_cst) const noexcept; - bool test_and_set(memory_order = memory_order::seq_cst) volatile noexcept; - bool test_and_set(memory_order = memory_order::seq_cst) noexcept; - void clear(memory_order = memory_order::seq_cst) volatile noexcept; - void clear(memory_order = memory_order::seq_cst) noexcept; - - void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(bool, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() volatile noexcept; - void notify_one() noexcept; - void notify_all() volatile noexcept; - void notify_all() noexcept; - }; -} -\end{codeblock} - -\pnum -The \tcode{atomic_flag} type provides the classic test-and-set functionality. It has two states, set and clear. - -\pnum -Operations on an object of type \tcode{atomic_flag} shall be lock-free. -The operations should also be address-free. - -\pnum -The \tcode{atomic_flag} type is a standard-layout struct. -It has a trivial destructor. - -\indexlibraryctor{atomic_flag}% -\begin{itemdecl} -constexpr atomic_flag::atomic_flag() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{*this} to the clear state. -\end{itemdescr} - -\indexlibraryglobal{atomic_flag_test}% -\indexlibraryglobal{atomic_flag_test_explicit}% -\indexlibrarymember{test}{atomic_flag}% -\begin{itemdecl} -bool atomic_flag_test(const volatile atomic_flag* object) noexcept; -bool atomic_flag_test(const atomic_flag* object) noexcept; -bool atomic_flag_test_explicit(const volatile atomic_flag* object, - memory_order order) noexcept; -bool atomic_flag_test_explicit(const atomic_flag* object, - memory_order order) noexcept; -bool atomic_flag::test(memory_order order = memory_order::seq_cst) const volatile noexcept; -bool atomic_flag::test(memory_order order = memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -For \tcode{atomic_flag_test}, let \tcode{order} be \tcode{memory_order::seq_cst}. - -\pnum -\expects -\tcode{order} is -neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Memory is affected according to the value of \tcode{order}. - -\pnum -\returns -Atomically returns the value pointed to by \tcode{object} or \keyword{this}. -\end{itemdescr} - -\indexlibraryglobal{atomic_flag_test_and_set}% -\indexlibraryglobal{atomic_flag_test_and_set_explicit}% -\indexlibrarymember{test_and_set}{atomic_flag}% -\begin{itemdecl} -bool atomic_flag_test_and_set(volatile atomic_flag* object) noexcept; -bool atomic_flag_test_and_set(atomic_flag* object) noexcept; -bool atomic_flag_test_and_set_explicit(volatile atomic_flag* object, memory_order order) noexcept; -bool atomic_flag_test_and_set_explicit(atomic_flag* object, memory_order order) noexcept; -bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) volatile noexcept; -bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Atomically sets the value pointed to by \tcode{object} or by \keyword{this} to \tcode{true}. Memory is affected according to the value of -\tcode{order}. These operations are atomic read-modify-write operations\iref{intro.multithread}. - -\pnum -\returns -Atomically, the value of the object immediately before the effects. -\end{itemdescr} - -\indexlibraryglobal{atomic_flag_clear}% -\indexlibraryglobal{atomic_flag_clear_explicit}% -\indexlibrarymember{clear}{atomic_flag}% -\begin{itemdecl} -void atomic_flag_clear(volatile atomic_flag* object) noexcept; -void atomic_flag_clear(atomic_flag* object) noexcept; -void atomic_flag_clear_explicit(volatile atomic_flag* object, memory_order order) noexcept; -void atomic_flag_clear_explicit(atomic_flag* object, memory_order order) noexcept; -void atomic_flag::clear(memory_order order = memory_order::seq_cst) volatile noexcept; -void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The \tcode{order} argument is neither \tcode{memory_order::consume}, -\tcode{memory_order::acquire}, nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Atomically sets the value pointed to by \tcode{object} or by \keyword{this} to -\tcode{false}. Memory is affected according to the value of \tcode{order}. -\end{itemdescr} - -\indexlibraryglobal{atomic_flag_wait}% -\indexlibraryglobal{atomic_flag_wait_explicit}% -\indexlibrarymember{wait}{atomic_flag}% -\begin{itemdecl} -void atomic_flag_wait(const volatile atomic_flag* object, bool old) noexcept; -void atomic_flag_wait(const atomic_flag* object, bool old) noexcept; -void atomic_flag_wait_explicit(const volatile atomic_flag* object, - bool old, memory_order order) noexcept; -void atomic_flag_wait_explicit(const atomic_flag* object, - bool old, memory_order order) noexcept; -void atomic_flag::wait(bool old, memory_order order = - memory_order::seq_cst) const volatile noexcept; -void atomic_flag::wait(bool old, memory_order order = - memory_order::seq_cst) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -For \tcode{atomic_flag_wait}, -let \tcode{order} be \tcode{memory_order::seq_cst}. -Let \tcode{flag} be \tcode{object} for the non-member functions and -\keyword{this} for the member functions. - -\pnum -\expects -\tcode{order} is -neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -Repeatedly performs the following steps, in order: -\begin{itemize} -\item - Evaluates \tcode{flag->test(order) != old}. -\item - If the result of that evaluation is \tcode{true}, returns. -\item - Blocks until it - is unblocked by an atomic notifying operation or is unblocked spuriously. -\end{itemize} - -\pnum -\remarks -This function is an atomic waiting operation\iref{atomics.wait}. -\end{itemdescr} - -\begin{itemdecl} -void atomic_flag_notify_one(volatile atomic_flag* object) noexcept; -void atomic_flag_notify_one(atomic_flag* object) noexcept; -void atomic_flag::notify_one() volatile noexcept; -void atomic_flag::notify_one() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of at least one atomic waiting operation -that is eligible to be unblocked\iref{atomics.wait} by this call, -if any such atomic waiting operations exist. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\begin{itemdecl} -void atomic_flag_notify_all(volatile atomic_flag* object) noexcept; -void atomic_flag_notify_all(atomic_flag* object) noexcept; -void atomic_flag::notify_all() volatile noexcept; -void atomic_flag::notify_all() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Unblocks the execution of all atomic waiting operations -that are eligible to be unblocked\iref{atomics.wait} by this call. - -\pnum -\remarks -This function is an atomic notifying operation\iref{atomics.wait}. -\end{itemdescr} - -\rSec1[atomics.fences]{Fences} - -\pnum -This subclause introduces synchronization primitives called \term{fences}. Fences can have -acquire semantics, release semantics, or both. A fence with acquire semantics is called -an \term{acquire fence}. A fence with release semantics is called a \term{release -fence}. - -\pnum -A release fence $A$ synchronizes with an acquire fence $B$ if there exist -atomic operations $X$ and $Y$, both operating on some atomic object -$M$, such that $A$ is sequenced before $X$, $X$ modifies -$M$, $Y$ is sequenced before $B$, and $Y$ reads the value -written by $X$ or a value written by any side effect in the hypothetical release -sequence $X$ would head if it were a release operation. - -\pnum -A release fence $A$ synchronizes with an atomic operation $B$ that -performs an acquire operation on an atomic object $M$ if there exists an atomic -operation $X$ such that $A$ is sequenced before $X$, $X$ -modifies $M$, and $B$ reads the value written by $X$ or a value -written by any side effect in the hypothetical release sequence $X$ would head if -it were a release operation. - -\pnum -An atomic operation $A$ that is a release operation on an atomic object -$M$ synchronizes with an acquire fence $B$ if there exists some atomic -operation $X$ on $M$ such that $X$ is sequenced before $B$ -and reads the value written by $A$ or a value written by any side effect in the -release sequence headed by $A$. - -\indexlibraryglobal{atomic_thread_fence}% -\begin{itemdecl} -extern "C" void atomic_thread_fence(memory_order order) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Depending on the value of \tcode{order}, this operation: -\begin{itemize} -\item has no effects, if \tcode{order == memory_order::relaxed}; - -\item is an acquire fence, if \tcode{order == memory_order::acquire} or \tcode{order == memory_order::consume}; - -\item is a release fence, if \tcode{order == memory_order::release}; - -\item is both an acquire fence and a release fence, if \tcode{order == memory_order::acq_rel}; - -\item is a sequentially consistent acquire and release fence, if \tcode{order == memory_order::seq_cst}. -\end{itemize} -\end{itemdescr} - -\indexlibraryglobal{atomic_signal_fence}% -\begin{itemdecl} -extern "C" void atomic_signal_fence(memory_order order) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{atomic_thread_fence(order)}, except that -the resulting ordering constraints are established only between a thread and a -signal handler executed in the same thread. - -\pnum -\begin{note} -\tcode{atomic_signal_fence} can be used to specify the order in which actions -performed by the thread become visible to the signal handler. -Compiler optimizations and reorderings of loads and stores are inhibited in -the same way as with \tcode{atomic_thread_fence}, but the hardware fence instructions -that \tcode{atomic_thread_fence} would have inserted are not emitted. -\end{note} -\end{itemdescr} - -\rSec1[stdatomic.h.syn]{C compatibility} - -The header \libheaderdef{stdatomic.h} provides the following definitions: - -\begin{codeblock} -template - using @\exposid{std-atomic}@ = std::atomic; // \expos - -#define _Atomic(T) @\exposid{std-atomic}@ - -#define ATOMIC_BOOL_LOCK_FREE @\seebelow@ -#define ATOMIC_CHAR_LOCK_FREE @\seebelow@ -#define ATOMIC_CHAR16_T_LOCK_FREE @\seebelow@ -#define ATOMIC_CHAR32_T_LOCK_FREE @\seebelow@ -#define ATOMIC_WCHAR_T_LOCK_FREE @\seebelow@ -#define ATOMIC_SHORT_LOCK_FREE @\seebelow@ -#define ATOMIC_INT_LOCK_FREE @\seebelow@ -#define ATOMIC_LONG_LOCK_FREE @\seebelow@ -#define ATOMIC_LLONG_LOCK_FREE @\seebelow@ -#define ATOMIC_POINTER_LOCK_FREE @\seebelow@ - -using std::@\libglobal{memory_order}@; // \seebelow -using std::@\libglobal{memory_order_relaxed}@; // \seebelow -using std::@\libglobal{memory_order_consume}@; // \seebelow -using std::@\libglobal{memory_order_acquire}@; // \seebelow -using std::@\libglobal{memory_order_release}@; // \seebelow -using std::@\libglobal{memory_order_acq_rel}@; // \seebelow -using std::@\libglobal{memory_order_seq_cst}@; // \seebelow - -using std::@\libglobal{atomic_flag}@; // \seebelow - -using std::@\libglobal{atomic_bool}@; // \seebelow -using std::@\libglobal{atomic_char}@; // \seebelow -using std::@\libglobal{atomic_schar}@; // \seebelow -using std::@\libglobal{atomic_uchar}@; // \seebelow -using std::@\libglobal{atomic_short}@; // \seebelow -using std::@\libglobal{atomic_ushort}@; // \seebelow -using std::@\libglobal{atomic_int}@; // \seebelow -using std::@\libglobal{atomic_uint}@; // \seebelow -using std::@\libglobal{atomic_long}@; // \seebelow -using std::@\libglobal{atomic_ulong}@; // \seebelow -using std::@\libglobal{atomic_llong}@; // \seebelow -using std::@\libglobal{atomic_ullong}@; // \seebelow -using std::@\libglobal{atomic_char8_t}@; // \seebelow -using std::@\libglobal{atomic_char16_t}@; // \seebelow -using std::@\libglobal{atomic_char32_t}@; // \seebelow -using std::@\libglobal{atomic_wchar_t}@; // \seebelow -using std::@\libglobal{atomic_int8_t}@; // \seebelow -using std::@\libglobal{atomic_uint8_t}@; // \seebelow -using std::@\libglobal{atomic_int16_t}@; // \seebelow -using std::@\libglobal{atomic_uint16_t}@; // \seebelow -using std::@\libglobal{atomic_int32_t}@; // \seebelow -using std::@\libglobal{atomic_uint32_t}@; // \seebelow -using std::@\libglobal{atomic_int64_t}@; // \seebelow -using std::@\libglobal{atomic_uint64_t}@; // \seebelow -using std::@\libglobal{atomic_int_least8_t}@; // \seebelow -using std::@\libglobal{atomic_uint_least8_t}@; // \seebelow -using std::@\libglobal{atomic_int_least16_t}@; // \seebelow -using std::@\libglobal{atomic_uint_least16_t}@; // \seebelow -using std::@\libglobal{atomic_int_least32_t}@; // \seebelow -using std::@\libglobal{atomic_uint_least32_t}@; // \seebelow -using std::@\libglobal{atomic_int_least64_t}@; // \seebelow -using std::@\libglobal{atomic_uint_least64_t}@; // \seebelow -using std::@\libglobal{atomic_int_fast8_t}@; // \seebelow -using std::@\libglobal{atomic_uint_fast8_t}@; // \seebelow -using std::@\libglobal{atomic_int_fast16_t}@; // \seebelow -using std::@\libglobal{atomic_uint_fast16_t}@; // \seebelow -using std::@\libglobal{atomic_int_fast32_t}@; // \seebelow -using std::@\libglobal{atomic_uint_fast32_t}@; // \seebelow -using std::@\libglobal{atomic_int_fast64_t}@; // \seebelow -using std::@\libglobal{atomic_uint_fast64_t}@; // \seebelow -using std::@\libglobal{atomic_intptr_t}@; // \seebelow -using std::@\libglobal{atomic_uintptr_t}@; // \seebelow -using std::@\libglobal{atomic_size_t}@; // \seebelow -using std::@\libglobal{atomic_ptrdiff_t}@; // \seebelow -using std::@\libglobal{atomic_intmax_t}@; // \seebelow -using std::@\libglobal{atomic_uintmax_t}@; // \seebelow - -using std::@\libglobal{atomic_is_lock_free}@; // \seebelow -using std::@\libglobal{atomic_load}@; // \seebelow -using std::@\libglobal{atomic_load_explicit}@; // \seebelow -using std::@\libglobal{atomic_store}@; // \seebelow -using std::@\libglobal{atomic_store_explicit}@; // \seebelow -using std::@\libglobal{atomic_exchange}@; // \seebelow -using std::@\libglobal{atomic_exchange_explicit}@; // \seebelow -using std::@\libglobal{atomic_compare_exchange_strong}@; // \seebelow -using std::@\libglobal{atomic_compare_exchange_strong_explicit}@; // \seebelow -using std::@\libglobal{atomic_compare_exchange_weak}@; // \seebelow -using std::@\libglobal{atomic_compare_exchange_weak_explicit}@; // \seebelow -using std::@\libglobal{atomic_fetch_add}@; // \seebelow -using std::@\libglobal{atomic_fetch_add_explicit}@; // \seebelow -using std::@\libglobal{atomic_fetch_sub}@; // \seebelow -using std::@\libglobal{atomic_fetch_sub_explicit}@; // \seebelow -using std::@\libglobal{atomic_fetch_or}@; // \seebelow -using std::@\libglobal{atomic_fetch_or_explicit}@; // \seebelow -using std::@\libglobal{atomic_fetch_and}@; // \seebelow -using std::@\libglobal{atomic_fetch_and_explicit}@; // \seebelow -using std::@\libglobal{atomic_flag_test_and_set}@; // \seebelow -using std::@\libglobal{atomic_flag_test_and_set_explicit}@; // \seebelow -using std::@\libglobal{atomic_flag_clear}@; // \seebelow -using std::@\libglobal{atomic_flag_clear_explicit}@; // \seebelow - -using std::@\libglobal{atomic_thread_fence}@; // \seebelow -using std::@\libglobal{atomic_signal_fence}@; // \seebelow -\end{codeblock} - -\pnum -Each \grammarterm{using-declaration} for some name $A$ in the synopsis above -makes available the same entity as \tcode{std::$A$} -declared in \libheaderrefx{atomic}{atomics.syn}. -Each macro listed above other than \tcode{_Atomic(T)} -is defined as in \libheader{atomic}. -It is unspecified whether \libheader{stdatomic.h} makes available -any declarations in namespace \tcode{std}. - -\pnum -Each of the \grammarterm{using-declaration}s for -\tcode{int$N$_t}, \tcode{uint$N$_t}, \tcode{intptr_t}, and \tcode{uintptr_t} -listed above is defined if and only if the implementation defines -the corresponding \grammarterm{typedef-name} in \ref{atomics.syn}. - -\pnum -Neither the \tcode{_Atomic} macro, -nor any of the non-macro global namespace declarations, -are provided by any \Cpp{} standard library header -other than \libheader{stdatomic.h}. - -\pnum -\recommended -Implementations should ensure -that C and \Cpp{} representations of atomic objects are compatible, -so that the same object can be accessed as both an \tcode{_Atomic(T)} -from C code and an \tcode{atomic} from \Cpp{} code. -The representations should be the same, and -the mechanisms used to ensure atomicity and memory ordering -should be compatible. diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 6405c26b63..6c61e9440b 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -42,8 +42,7 @@ \ref{localization} & Localization library \\ \ref{input.output} & Input/output library \\ \ref{re} & Regular expressions library \\ -\ref{atomics} & Atomic operations library \\ -\ref{thread} & Thread support library \\ +\ref{thread} & Concurrency support library \\ \end{floattable} \pnum @@ -121,13 +120,10 @@ \pnum The regular expressions library\iref{re} provides regular expression matching and searching. -\pnum -The atomic operations library\iref{atomics} allows more fine-grained -concurrent access to shared data than is possible with locks. - \pnum The thread support library\iref{thread} provides components to create -and manage threads, including mutual exclusion and interthread communication. +and manage threads, +including atomic operations, mutual exclusion, and interthread communication. \rSec1[library.c]{The C standard library} diff --git a/source/std.tex b/source/std.tex index aaad1709ee..040decb135 100644 --- a/source/std.tex +++ b/source/std.tex @@ -132,7 +132,6 @@ \include{locales} \include{iostreams} \include{regex} -\include{atomics} \include{threads} %%-------------------------------------------------- diff --git a/source/threads.tex b/source/threads.tex index 5f8da57d2f..7b59b6c533 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -13,6 +13,8 @@ \ref{thread.req} & Requirements & \\ \rowsep \ref{thread.stoptoken}& Stop tokens & \tcode{} \\ \rowsep \ref{thread.threads} & Threads & \tcode{} \\ \rowsep +\ref{atomics} & Atomic operations & + \tcode{} \tcode{} \tcode{} \\ \rowsep \ref{thread.mutex} & Mutual exclusion & \tcode{}, \tcode{} \\ \rowsep \ref{thread.condition}& Condition variables & \tcode{} \\ \rowsep @@ -2032,6 +2034,3841 @@ Timeout-related exceptions\iref{thread.req.timing}. \end{itemdescr} +\rSec1[atomics]{Atomic operations} + +\rSec2[atomics.general]{General} + +\pnum +Subclause \ref{atomics} describes components for fine-grained atomic access. +This access is provided via operations on atomic objects. + +\rSec2[atomics.syn]{Header \tcode{} synopsis} + +\indexheader{atomic}% +\begin{codeblock} +namespace std { + // \ref{atomics.order}, order and consistency + enum class memory_order : @\unspec@; + template + T kill_dependency(T y) noexcept; +} + +// \ref{atomics.lockfree}, lock-free property +#define ATOMIC_BOOL_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR8_T_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR16_T_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR32_T_LOCK_FREE @\unspec@ +#define ATOMIC_WCHAR_T_LOCK_FREE @\unspec@ +#define ATOMIC_SHORT_LOCK_FREE @\unspec@ +#define ATOMIC_INT_LOCK_FREE @\unspec@ +#define ATOMIC_LONG_LOCK_FREE @\unspec@ +#define ATOMIC_LLONG_LOCK_FREE @\unspec@ +#define ATOMIC_POINTER_LOCK_FREE @\unspec@ + +namespace std { + // \ref{atomics.ref.generic}, class template \tcode{atomic_ref} + template struct atomic_ref; + // \ref{atomics.ref.pointer}, partial specialization for pointers + template struct atomic_ref; + + // \ref{atomics.types.generic}, class template \tcode{atomic} + template struct atomic; + // \ref{atomics.types.pointer}, partial specialization for pointers + template struct atomic; + + // \ref{atomics.nonmembers}, non-member functions + template + bool atomic_is_lock_free(const volatile atomic*) noexcept; + template + bool atomic_is_lock_free(const atomic*) noexcept; + template + void atomic_store(volatile atomic*, typename atomic::value_type) noexcept; + template + void atomic_store(atomic*, typename atomic::value_type) noexcept; + template + void atomic_store_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; + template + void atomic_store_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_load(const volatile atomic*) noexcept; + template + T atomic_load(const atomic*) noexcept; + template + T atomic_load_explicit(const volatile atomic*, memory_order) noexcept; + template + T atomic_load_explicit(const atomic*, memory_order) noexcept; + template + T atomic_exchange(volatile atomic*, typename atomic::value_type) noexcept; + template + T atomic_exchange(atomic*, typename atomic::value_type) noexcept; + template + T atomic_exchange_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_exchange_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; + template + bool atomic_compare_exchange_weak(volatile atomic*, + typename atomic::value_type*, + typename atomic::value_type) noexcept; + template + bool atomic_compare_exchange_weak(atomic*, + typename atomic::value_type*, + typename atomic::value_type) noexcept; + template + bool atomic_compare_exchange_strong(volatile atomic*, + typename atomic::value_type*, + typename atomic::value_type) noexcept; + template + bool atomic_compare_exchange_strong(atomic*, + typename atomic::value_type*, + typename atomic::value_type) noexcept; + template + bool atomic_compare_exchange_weak_explicit(volatile atomic*, + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; + template + bool atomic_compare_exchange_weak_explicit(atomic*, + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; + template + bool atomic_compare_exchange_strong_explicit(volatile atomic*, + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; + template + bool atomic_compare_exchange_strong_explicit(atomic*, + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; + + template + T atomic_fetch_add(volatile atomic*, typename atomic::difference_type) noexcept; + template + T atomic_fetch_add(atomic*, typename atomic::difference_type) noexcept; + template + T atomic_fetch_add_explicit(volatile atomic*, typename atomic::difference_type, + memory_order) noexcept; + template + T atomic_fetch_add_explicit(atomic*, typename atomic::difference_type, + memory_order) noexcept; + template + T atomic_fetch_sub(volatile atomic*, typename atomic::difference_type) noexcept; + template + T atomic_fetch_sub(atomic*, typename atomic::difference_type) noexcept; + template + T atomic_fetch_sub_explicit(volatile atomic*, typename atomic::difference_type, + memory_order) noexcept; + template + T atomic_fetch_sub_explicit(atomic*, typename atomic::difference_type, + memory_order) noexcept; + template + T atomic_fetch_and(volatile atomic*, typename atomic::value_type) noexcept; + template + T atomic_fetch_and(atomic*, typename atomic::value_type) noexcept; + template + T atomic_fetch_and_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_fetch_and_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_fetch_or(volatile atomic*, typename atomic::value_type) noexcept; + template + T atomic_fetch_or(atomic*, typename atomic::value_type) noexcept; + template + T atomic_fetch_or_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_fetch_or_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_fetch_xor(volatile atomic*, typename atomic::value_type) noexcept; + template + T atomic_fetch_xor(atomic*, typename atomic::value_type) noexcept; + template + T atomic_fetch_xor_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; + template + T atomic_fetch_xor_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; + + template + void atomic_wait(const volatile atomic*, typename atomic::value_type); + template + void atomic_wait(const atomic*, typename atomic::value_type); + template + void atomic_wait_explicit(const volatile atomic*, typename atomic::value_type, + memory_order); + template + void atomic_wait_explicit(const atomic*, typename atomic::value_type, + memory_order); + template + void atomic_notify_one(volatile atomic*); + template + void atomic_notify_one(atomic*); + template + void atomic_notify_all(volatile atomic*); + template + void atomic_notify_all(atomic*); + + // \ref{atomics.alias}, type aliases + using atomic_bool = atomic; + using atomic_char = atomic; + using atomic_schar = atomic; + using atomic_uchar = atomic; + using atomic_short = atomic; + using atomic_ushort = atomic; + using atomic_int = atomic; + using atomic_uint = atomic; + using atomic_long = atomic; + using atomic_ulong = atomic; + using atomic_llong = atomic; + using atomic_ullong = atomic; + using atomic_char8_t = atomic; + using atomic_char16_t = atomic; + using atomic_char32_t = atomic; + using atomic_wchar_t = atomic; + + using atomic_int8_t = atomic; + using atomic_uint8_t = atomic; + using atomic_int16_t = atomic; + using atomic_uint16_t = atomic; + using atomic_int32_t = atomic; + using atomic_uint32_t = atomic; + using atomic_int64_t = atomic; + using atomic_uint64_t = atomic; + + using atomic_int_least8_t = atomic; + using atomic_uint_least8_t = atomic; + using atomic_int_least16_t = atomic; + using atomic_uint_least16_t = atomic; + using atomic_int_least32_t = atomic; + using atomic_uint_least32_t = atomic; + using atomic_int_least64_t = atomic; + using atomic_uint_least64_t = atomic; + + using atomic_int_fast8_t = atomic; + using atomic_uint_fast8_t = atomic; + using atomic_int_fast16_t = atomic; + using atomic_uint_fast16_t = atomic; + using atomic_int_fast32_t = atomic; + using atomic_uint_fast32_t = atomic; + using atomic_int_fast64_t = atomic; + using atomic_uint_fast64_t = atomic; + + using atomic_intptr_t = atomic; + using atomic_uintptr_t = atomic; + using atomic_size_t = atomic; + using atomic_ptrdiff_t = atomic; + using atomic_intmax_t = atomic; + using atomic_uintmax_t = atomic; + + using atomic_signed_lock_free = @\seebelow@; + using atomic_unsigned_lock_free = @\seebelow@; + + // \ref{atomics.flag}, flag type and operations + struct atomic_flag; + + bool atomic_flag_test(const volatile atomic_flag*) noexcept; + bool atomic_flag_test(const atomic_flag*) noexcept; + bool atomic_flag_test_explicit(const volatile atomic_flag*, memory_order) noexcept; + bool atomic_flag_test_explicit(const atomic_flag*, memory_order) noexcept; + bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept; + bool atomic_flag_test_and_set(atomic_flag*) noexcept; + bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, memory_order) noexcept; + bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order) noexcept; + void atomic_flag_clear(volatile atomic_flag*) noexcept; + void atomic_flag_clear(atomic_flag*) noexcept; + void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept; + void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept; + + void atomic_flag_wait(const volatile atomic_flag*, bool) noexcept; + void atomic_flag_wait(const atomic_flag*, bool) noexcept; + void atomic_flag_wait_explicit(const volatile atomic_flag*, + bool, memory_order) noexcept; + void atomic_flag_wait_explicit(const atomic_flag*, + bool, memory_order) noexcept; + void atomic_flag_notify_one(volatile atomic_flag*) noexcept; + void atomic_flag_notify_one(atomic_flag*) noexcept; + void atomic_flag_notify_all(volatile atomic_flag*) noexcept; + void atomic_flag_notify_all(atomic_flag*) noexcept; + + // \ref{atomics.fences}, fences + extern "C" void atomic_thread_fence(memory_order) noexcept; + extern "C" void atomic_signal_fence(memory_order) noexcept; +} +\end{codeblock} + +\rSec2[atomics.alias]{Type aliases} +\indexlibraryglobal{atomic_bool}% +\indexlibraryglobal{atomic_char}% +\indexlibraryglobal{atomic_schar}% +\indexlibraryglobal{atomic_uchar}% +\indexlibraryglobal{atomic_short}% +\indexlibraryglobal{atomic_ushort}% +\indexlibraryglobal{atomic_int}% +\indexlibraryglobal{atomic_uint}% +\indexlibraryglobal{atomic_long}% +\indexlibraryglobal{atomic_ulong}% +\indexlibraryglobal{atomic_llong}% +\indexlibraryglobal{atomic_ullong}% +\indexlibraryglobal{atomic_char8_t}% +\indexlibraryglobal{atomic_char16_t}% +\indexlibraryglobal{atomic_char32_t}% +\indexlibraryglobal{atomic_wchar_t}% +\indexlibraryglobal{atomic_int8_t}% +\indexlibraryglobal{atomic_uint8_t}% +\indexlibraryglobal{atomic_int16_t}% +\indexlibraryglobal{atomic_uint16_t}% +\indexlibraryglobal{atomic_int32_t}% +\indexlibraryglobal{atomic_uint32_t}% +\indexlibraryglobal{atomic_int64_t}% +\indexlibraryglobal{atomic_uint64_t}% +\indexlibraryglobal{atomic_int_least8_t}% +\indexlibraryglobal{atomic_uint_least8_t}% +\indexlibraryglobal{atomic_int_least16_t}% +\indexlibraryglobal{atomic_uint_least16_t}% +\indexlibraryglobal{atomic_int_least32_t}% +\indexlibraryglobal{atomic_uint_least32_t}% +\indexlibraryglobal{atomic_int_least64_t}% +\indexlibraryglobal{atomic_uint_least64_t}% +\indexlibraryglobal{atomic_int_fast8_t}% +\indexlibraryglobal{atomic_uint_fast8_t}% +\indexlibraryglobal{atomic_int_fast16_t}% +\indexlibraryglobal{atomic_uint_fast16_t}% +\indexlibraryglobal{atomic_int_fast32_t}% +\indexlibraryglobal{atomic_uint_fast32_t}% +\indexlibraryglobal{atomic_int_fast64_t}% +\indexlibraryglobal{atomic_uint_fast64_t}% +\indexlibraryglobal{atomic_intptr_t}% +\indexlibraryglobal{atomic_uintptr_t}% +\indexlibraryglobal{atomic_size_t}% +\indexlibraryglobal{atomic_ptrdiff_t}% +\indexlibraryglobal{atomic_intmax_t}% +\indexlibraryglobal{atomic_uintmax_t}% +\pnum +The type aliases \tcode{atomic_int$N$_t}, \tcode{atomic_uint$N$_t}, +\tcode{atomic_intptr_t}, and \tcode{atomic_uintptr_t} +are defined if and only if +\tcode{int$N$_t}, \tcode{uint$N$_t}, +\tcode{intptr_t}, and \tcode{uintptr_t} +are defined, respectively. + +\pnum +\indexlibraryglobal{atomic_signed_lock_free}% +\indexlibraryglobal{atomic_unsigned_lock_free}% +The type aliases +\tcode{atomic_signed_lock_free} and \tcode{atomic_unsigned_lock_free} +name specializations of \tcode{atomic} +whose template arguments are integral types, respectively signed and unsigned, +and whose \tcode{is_always_lock_free} property is \tcode{true}. +\begin{note} +\indextext{implementation!freestanding}% +These aliases are optional in freestanding implementations\iref{compliance}. +\end{note} +Implementations should choose for these aliases +the integral specializations of \tcode{atomic} +for which the atomic waiting and notifying operations\iref{atomics.wait} +are most efficient. + +\rSec2[atomics.order]{Order and consistency} +\indexlibraryglobal{memory_order}% +\indexlibrarymember{relaxed}{memory_order}% +\indexlibrarymember{consume}{memory_order}% +\indexlibrarymember{acquire}{memory_order}% +\indexlibrarymember{release}{memory_order}% +\indexlibrarymember{acq_rel}{memory_order}% +\indexlibrarymember{seq_cst}{memory_order}% +\indexlibraryglobal{memory_order_relaxed}% +\indexlibraryglobal{memory_order_consume}% +\indexlibraryglobal{memory_order_acquire}% +\indexlibraryglobal{memory_order_release}% +\indexlibraryglobal{memory_order_acq_rel}% +\indexlibraryglobal{memory_order_seq_cst}% + +\begin{codeblock} +namespace std { + enum class memory_order : @\unspec@ { + relaxed, consume, acquire, release, acq_rel, seq_cst + }; + inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; + inline constexpr memory_order memory_order_consume = memory_order::consume; + inline constexpr memory_order memory_order_acquire = memory_order::acquire; + inline constexpr memory_order memory_order_release = memory_order::release; + inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; + inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; +} +\end{codeblock} + +\pnum +The enumeration \tcode{memory_order} specifies the detailed regular +(non-atomic) memory synchronization order as defined in +\ref{intro.multithread} and may provide for operation ordering. Its +enumerated values and their meanings are as follows: + +\begin{itemize} +\item \tcode{memory_order::relaxed}: no operation orders memory. + +\item \tcode{memory_order::release}, \tcode{memory_order::acq_rel}, and +\tcode{memory_order::seq_cst}: a store operation performs a release operation on the +affected memory location. + +\item \tcode{memory_order::consume}: a load operation performs a consume operation on the +affected memory location. +\begin{note} +Prefer \tcode{memory_order::acquire}, which provides stronger guarantees +than \tcode{memory_order::consume}. Implementations have found it infeasible +to provide performance better than that of \tcode{memory_order::acquire}. +Specification revisions are under consideration. +\end{note} + +\item \tcode{memory_order::acquire}, \tcode{memory_order::acq_rel}, and +\tcode{memory_order::seq_cst}: a load operation performs an acquire operation on the +affected memory location. +\end{itemize} + +\begin{note} +Atomic operations specifying \tcode{memory_order::relaxed} are relaxed +with respect to memory ordering. Implementations must still guarantee that any +given atomic access to a particular atomic object be indivisible with respect +to all other atomic accesses to that object. +\end{note} + +\pnum +An atomic operation $A$ that performs a release operation on an atomic +object $M$ synchronizes with an atomic operation $B$ that performs +an acquire operation on $M$ and takes its value from any side effect in the +release sequence headed by $A$. + +\pnum +An atomic operation $A$ on some atomic object $M$ is +\defn{coherence-ordered before} +another atomic operation $B$ on $M$ if +\begin{itemize} +\item $A$ is a modification, and +$B$ reads the value stored by $A$, or +\item $A$ precedes $B$ +in the modification order of $M$, or +\item $A$ and $B$ are not +the same atomic read-modify-write operation, and +there exists an atomic modification $X$ of $M$ +such that $A$ reads the value stored by $X$ and +$X$ precedes $B$ +in the modification order of $M$, or +\item there exists an atomic modification $X$ of $M$ +such that $A$ is coherence-ordered before $X$ and +$X$ is coherence-ordered before $B$. +\end{itemize} + +\pnum +There is a single total order $S$ +on all \tcode{memory_order::seq_cst} operations, including fences, +that satisfies the following constraints. +First, if $A$ and $B$ are +\tcode{memory_order::seq_cst} operations and +$A$ strongly happens before $B$, +then $A$ precedes $B$ in $S$. +Second, for every pair of atomic operations $A$ and +$B$ on an object $M$, +where $A$ is coherence-ordered before $B$, +the following four conditions are required to be satisfied by $S$: +\begin{itemize} +\item if $A$ and $B$ are both +\tcode{memory_order::seq_cst} operations, +then $A$ precedes $B$ in $S$; and +\item if $A$ is a \tcode{memory_order::seq_cst} operation and +$B$ happens before +a \tcode{memory_order::seq_cst} fence $Y$, +then $A$ precedes $Y$ in $S$; and +\item if a \tcode{memory_order::seq_cst} fence $X$ +happens before $A$ and +$B$ is a \tcode{memory_order::seq_cst} operation, +then $X$ precedes $B$ in $S$; and +\item if a \tcode{memory_order::seq_cst} fence $X$ +happens before $A$ and +$B$ happens before +a \tcode{memory_order::seq_cst} fence $Y$, +then $X$ precedes $Y$ in $S$. +\end{itemize} + +\pnum +\begin{note} +This definition ensures that $S$ is consistent with +the modification order of any atomic object $M$. +It also ensures that +a \tcode{memory_order::seq_cst} load $A$ of $M$ +gets its value either from the last modification of $M$ +that precedes $A$ in $S$ or +from some non-\tcode{memory_order::seq_cst} modification of $M$ +that does not happen before any modification of $M$ +that precedes $A$ in $S$. +\end{note} + +\pnum +\begin{note} +We do not require that $S$ be consistent with +``happens before''\iref{intro.races}. +This allows more efficient implementation +of \tcode{memory_order::acquire} and \tcode{memory_order::release} +on some machine architectures. +It can produce surprising results +when these are mixed with \tcode{memory_order::seq_cst} accesses. +\end{note} + +\pnum +\begin{note} +\tcode{memory_order::seq_cst} ensures sequential consistency only +for a program that is free of data races and +uses exclusively \tcode{memory_order::seq_cst} atomic operations. +Any use of weaker ordering will invalidate this guarantee +unless extreme care is used. +In many cases, \tcode{memory_order::seq_cst} atomic operations are reorderable +with respect to other atomic operations performed by the same thread. +\end{note} + +\pnum +Implementations should ensure that no ``out-of-thin-air'' values are computed that +circularly depend on their own computation. + +\begin{note} +For example, with \tcode{x} and \tcode{y} initially zero, +\begin{codeblock} +// Thread 1: +r1 = y.load(memory_order::relaxed); +x.store(r1, memory_order::relaxed); +\end{codeblock} + +\begin{codeblock} +// Thread 2: +r2 = x.load(memory_order::relaxed); +y.store(r2, memory_order::relaxed); +\end{codeblock} +this recommendation discourages producing \tcode{r1 == r2 == 42}, since the store of 42 to \tcode{y} is only +possible if the store to \tcode{x} stores \tcode{42}, which circularly depends on the +store to \tcode{y} storing \tcode{42}. Note that without this restriction, such an +execution is possible. +\end{note} + +\pnum +\begin{note} +The recommendation similarly disallows \tcode{r1 == r2 == 42} in the +following example, with \tcode{x} and \tcode{y} again initially zero: + +\begin{codeblock} +// Thread 1: +r1 = x.load(memory_order::relaxed); +if (r1 == 42) y.store(42, memory_order::relaxed); +\end{codeblock} + +\begin{codeblock} +// Thread 2: +r2 = y.load(memory_order::relaxed); +if (r2 == 42) x.store(42, memory_order::relaxed); +\end{codeblock} +\end{note} + +\pnum +Atomic read-modify-write operations shall always read the last value +(in the modification order) written before the write associated with +the read-modify-write operation. + +\pnum +Implementations should make atomic stores visible to atomic loads within a reasonable +amount of time. + +\indexlibraryglobal{kill_dependency}% +\begin{itemdecl} +template + T kill_dependency(T y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +The argument does not carry a dependency to the return +value\iref{intro.multithread}. + +\pnum +\returns +\tcode{y}. +\end{itemdescr} + + +\rSec2[atomics.lockfree]{Lock-free property} + +\indexlibraryglobal{ATOMIC_BOOL_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_CHAR_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_CHAR8_T_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_CHAR16_T_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_CHAR32_T_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_WCHAR_T_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_SHORT_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_INT_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_LONG_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_LLONG_LOCK_FREE}% +\indexlibraryglobal{ATOMIC_POINTER_LOCK_FREE}% +\indeximpldef{values of various \tcode{ATOMIC_..._LOCK_FREE} macros} +\begin{codeblock} +#define ATOMIC_BOOL_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR8_T_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR16_T_LOCK_FREE @\unspec@ +#define ATOMIC_CHAR32_T_LOCK_FREE @\unspec@ +#define ATOMIC_WCHAR_T_LOCK_FREE @\unspec@ +#define ATOMIC_SHORT_LOCK_FREE @\unspec@ +#define ATOMIC_INT_LOCK_FREE @\unspec@ +#define ATOMIC_LONG_LOCK_FREE @\unspec@ +#define ATOMIC_LLONG_LOCK_FREE @\unspec@ +#define ATOMIC_POINTER_LOCK_FREE @\unspec@ +\end{codeblock} + +\pnum +The \tcode{ATOMIC_..._LOCK_FREE} macros indicate the lock-free property of the +corresponding atomic types, with the signed and unsigned variants grouped +together. The properties also apply to the corresponding (partial) specializations of the +\tcode{atomic} template. A value of 0 indicates that the types are never +lock-free. A value of 1 indicates that the types are sometimes lock-free. A +value of 2 indicates that the types are always lock-free. + +\pnum +At least one signed integral specialization of the \tcode{atomic} template, +along with the specialization +for the corresponding unsigned type\iref{basic.fundamental}, +is always lock-free. +\begin{note} +\indextext{implementation!freestanding}% +This requirement is optional in freestanding implementations\iref{compliance}. +\end{note} + +\pnum +The functions \tcode{atomic::is_lock_free} and +\tcode{atomic_is_lock_free}\iref{atomics.types.operations} +indicate whether the object is lock-free. In any given program execution, the +result of the lock-free query +is the same for all atomic objects of the same type. + +\pnum +Atomic operations that are not lock-free are considered to potentially +block\iref{intro.progress}. + +\pnum +\recommended +Operations that are lock-free should also be address-free. +\begin{footnote} +That is, +atomic operations on the same memory location via two different addresses will +communicate atomically. +\end{footnote} +The implementation of these operations should not depend on any per-process state. +\begin{note} +This restriction enables communication by memory that is +mapped into a process more than once and by memory that is shared between two +processes. +\end{note} + +\rSec2[atomics.wait]{Waiting and notifying} + +\pnum +\defnx{Atomic waiting operations}{atomic!waiting operation} +and \defnx{atomic notifying operations}{atomic!notifying operation} +provide a mechanism to wait for the value of an atomic object to change +more efficiently than can be achieved with polling. +An atomic waiting operation may block until it is unblocked +by an atomic notifying operation, according to each function's effects. +\begin{note} +Programs are not guaranteed to observe transient atomic values, +an issue known as the A-B-A problem, +resulting in continued blocking if a condition is only temporarily met. +\end{note} + +\pnum +\begin{note} +The following functions are atomic waiting operations: +\begin{itemize} +\item \tcode{atomic::wait}, +\item \tcode{atomic_flag::wait}, +\item \tcode{atomic_wait} and \tcode{atomic_wait_explicit}, +\item \tcode{atomic_flag_wait} and \tcode{atomic_flag_wait_explicit}, and +\item \tcode{atomic_ref::wait}. +\end{itemize} +\end{note} + +\pnum +\begin{note} +The following functions are atomic notifying operations: +\begin{itemize} +\item \tcode{atomic::notify_one} and \tcode{atomic::notify_all}, +\item \tcode{atomic_flag::notify_one} and \tcode{atomic_flag::notify_all}, +\item \tcode{atomic_notify_one} and \tcode{atomic_notify_all}, +\item \tcode{atomic_flag_notify_one} and \tcode{atomic_flag_notify_all}, and +\item \tcode{atomic_ref::notify_one} and \tcode{atomic_ref::notify_all}. +\end{itemize} +\end{note} + +\indextext{atomic!waiting operation!eligible to be unblocked}% +\pnum +A call to an atomic waiting operation on an atomic object \tcode{M} +is \defn{eligible to be unblocked} +by a call to an atomic notifying operation on \tcode{M} +if there exist side effects \tcode{X} and \tcode{Y} on \tcode{M} such that: +\begin{itemize} +\item the atomic waiting operation has blocked after observing the result of \tcode{X}, +\item \tcode{X} precedes \tcode{Y} in the modification order of \tcode{M}, and +\item \tcode{Y} happens before the call to the atomic notifying operation. +\end{itemize} + +\rSec2[atomics.ref.generic]{Class template \tcode{atomic_ref}} + +\rSec3[atomics.ref.generic.general]{General} + +\indexlibraryglobal{atomic_ref}% +\indexlibrarymember{value_type}{atomic_ref}% +\begin{codeblock} +namespace std { + template struct atomic_ref { + private: + T* ptr; // \expos + public: + using value_type = T; + static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; + bool is_lock_free() const noexcept; + + explicit atomic_ref(T&); + atomic_ref(const atomic_ref&) noexcept; + atomic_ref& operator=(const atomic_ref&) = delete; + + void store(T, memory_order = memory_order::seq_cst) const noexcept; + T operator=(T) const noexcept; + T load(memory_order = memory_order::seq_cst) const noexcept; + operator T() const noexcept; + + T exchange(T, memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_weak(T&, T, + memory_order, memory_order) const noexcept; + bool compare_exchange_strong(T&, T, + memory_order, memory_order) const noexcept; + bool compare_exchange_weak(T&, T, + memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_strong(T&, T, + memory_order = memory_order::seq_cst) const noexcept; + + void wait(T, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() const noexcept; + void notify_all() const noexcept; + }; +} +\end{codeblock} + +\pnum +An \tcode{atomic_ref} object applies atomic operations\iref{atomics.general} to +the object referenced by \tcode{*ptr} such that, +for the lifetime\iref{basic.life} of the \tcode{atomic_ref} object, +the object referenced by \tcode{*ptr} is an atomic object\iref{intro.races}. + +\pnum +The program is ill-formed if \tcode{is_trivially_copyable_v} is \tcode{false}. + +\pnum +The lifetime\iref{basic.life} of an object referenced by \tcode{*ptr} +shall exceed the lifetime of all \tcode{atomic_ref}s that reference the object. +While any \tcode{atomic_ref} instances exist +that reference the \tcode{*ptr} object, +all accesses to that object shall exclusively occur +through those \tcode{atomic_ref} instances. +No subobject of the object referenced by \tcode{atomic_ref} +shall be concurrently referenced by any other \tcode{atomic_ref} object. + +\pnum +Atomic operations applied to an object +through a referencing \tcode{atomic_ref} are atomic with respect to +atomic operations applied through any other \tcode{atomic_ref} +referencing the same object. +\begin{note} +Atomic operations or the \tcode{atomic_ref} constructor can acquire +a shared resource, such as a lock associated with the referenced object, +to enable atomic operations to be applied to the referenced object. +\end{note} + +\rSec3[atomics.ref.ops]{Operations} + +\indexlibrarymember{required_alignment}{atomic_ref}% +\indexlibrarymember{required_alignment}{atomic_ref}% +\indexlibrarymember{required_alignment}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{required_alignment}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +static constexpr size_t required_alignment; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The alignment required for an object to be referenced by an atomic reference, +which is at least \tcode{alignof(T)}. + +\pnum +\begin{note} +Hardware could require an object +referenced by an \tcode{atomic_ref} +to have stricter alignment\iref{basic.align} +than other objects of type \tcode{T}. +Further, whether operations on an \tcode{atomic_ref} +are lock-free could depend on the alignment of the referenced object. +For example, lock-free operations on \tcode{std::complex} +could be supported only if aligned to \tcode{2*alignof(double)}. +\end{note} +\end{itemdescr} + +\indexlibrarymember{is_always_lock_free}{atomic_ref}% +\indexlibrarymember{is_always_lock_free}{atomic_ref}% +\indexlibrarymember{is_always_lock_free}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{is_always_lock_free}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +static constexpr bool is_always_lock_free; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The static data member \tcode{is_always_lock_free} is \tcode{true} +if the \tcode{atomic_ref} type's operations are always lock-free, +and \tcode{false} otherwise. +\end{itemdescr} + +\indexlibrarymember{is_lock_free}{atomic_ref}% +\indexlibrarymember{is_lock_free}{atomic_ref}% +\indexlibrarymember{is_lock_free}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{is_lock_free}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +bool is_lock_free() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if operations on all objects of the type \tcode{atomic_ref} +are lock-free, +\tcode{false} otherwise. +\end{itemdescr} + +\indexlibraryctor{atomic_ref}% +\indexlibraryctor{atomic_ref}% +\indexlibrary{\idxcode{atomic_ref<\placeholder{integral}>}!constructor}% +\indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point}>}!constructor}% +\begin{itemdecl} +atomic_ref(T& obj); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The referenced object is aligned to \tcode{required_alignment}. + +\pnum +\ensures +\tcode{*this} references \tcode{obj}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibraryctor{atomic_ref}% +\indexlibraryctor{atomic_ref}% +\indexlibrary{\idxcode{atomic_ref<\placeholder{integral}>}!constructor}% +\indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point}>}!constructor}% +\begin{itemdecl} +atomic_ref(const atomic_ref& ref) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{*this} references the object referenced by \tcode{ref}. +\end{itemdescr} + +\indexlibrarymember{store}{atomic_ref}% +\indexlibrarymember{store}{atomic_ref}% +\indexlibrarymember{store}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{store}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +void store(T desired, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The \tcode{order} argument is neither +\tcode{memory_order::consume}, +\tcode{memory_order::acquire}, nor +\tcode{memory_order::acq_rel}. + +\pnum +\effects +Atomically replaces the value referenced by \tcode{*ptr} +with the value of \tcode{desired}. +Memory is affected according to the value of \tcode{order}. +\end{itemdescr} + +\indexlibrarymember{operator=}{atomic_ref}% +\indexlibrarymember{operator=}{atomic_ref}% +\indexlibrarymember{operator=}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{operator=}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +T operator=(T desired) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +store(desired); +return desired; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{load}{atomic_ref}% +\indexlibrarymember{load}{atomic_ref}% +\indexlibrarymember{load}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{load}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +T load(memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The \tcode{order} argument is neither +\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Memory is affected according to the value of \tcode{order}. + +\pnum +\returns +Atomically returns the value referenced by \tcode{*ptr}. +\end{itemdescr} + +\indexlibrarymember{operator \placeholder{type}}{atomic_ref}% +\indexlibrarymember{operator T*}{atomic_ref}% +\indexlibrarymember{operator \placeholder{integral}}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{operator \placeholder{floating-point}}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +operator T() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return load();} +\end{itemdescr} + +\indexlibrarymember{exchange}{atomic_ref}% +\indexlibrarymember{exchange}{atomic_ref}% +\indexlibrarymember{exchange}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{exchange}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +T exchange(T desired, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Atomically replaces the value referenced by \tcode{*ptr} +with \tcode{desired}. +Memory is affected according to the value of \tcode{order}. +This operation is an atomic read-modify-write operation\iref{intro.multithread}. + +\pnum +\returns +Atomically returns the value referenced by \tcode{*ptr} +immediately before the effects. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_weak}{atomic_ref}% +\indexlibrarymember{compare_exchange_weak}{atomic_ref}% +\indexlibrarymember{compare_exchange_weak}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{compare_exchange_weak}{atomic_ref<\placeholder{floating-point}>}% +\indexlibrarymember{compare_exchange_strong}{atomic_ref}% +\indexlibrarymember{compare_exchange_strong}{atomic_ref}% +\indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +bool compare_exchange_weak(T& expected, T desired, + memory_order success, memory_order failure) const noexcept; + +bool compare_exchange_strong(T& expected, T desired, + memory_order success, memory_order failure) const noexcept; + +bool compare_exchange_weak(T& expected, T desired, + memory_order order = memory_order::seq_cst) const noexcept; + +bool compare_exchange_strong(T& expected, T desired, + memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The \tcode{failure} argument is neither +\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Retrieves the value in \tcode{expected}. +It then atomically compares the value representation of +the value referenced by \tcode{*ptr} for equality +with that previously retrieved from \tcode{expected}, +and if \tcode{true}, replaces the value referenced by \tcode{*ptr} +with that in \tcode{desired}. +If and only if the comparison is \tcode{true}, +memory is affected according to the value of \tcode{success}, and +if the comparison is \tcode{false}, +memory is affected according to the value of \tcode{failure}. +When only one \tcode{memory_order} argument is supplied, +the value of \tcode{success} is \tcode{order}, and +the value of \tcode{failure} is \tcode{order} +except that a value of \tcode{memory_order::acq_rel} shall be replaced by +the value \tcode{memory_order::acquire} and +a value of \tcode{memory_order::release} shall be replaced by +the value \tcode{memory_order::relaxed}. +If and only if the comparison is \tcode{false} then, +after the atomic operation, +the value in \tcode{expected} is replaced by +the value read from the value referenced by \tcode{*ptr} +during the atomic comparison. +If the operation returns \tcode{true}, +these operations are atomic read-modify-write operations\iref{intro.races} +on the value referenced by \tcode{*ptr}. +Otherwise, these operations are atomic load operations on that memory. + +\pnum +\returns +The result of the comparison. + +\pnum +\remarks +A weak compare-and-exchange operation may fail spuriously. +That is, even when the contents of memory referred to +by \tcode{expected} and \tcode{ptr} are equal, +it may return \tcode{false} and +store back to \tcode{expected} the same memory contents +that were originally there. +\begin{note} +This spurious failure enables implementation of compare-and-exchange +on a broader class of machines, e.g., load-locked store-conditional machines. +A consequence of spurious failure is +that nearly all uses of weak compare-and-exchange will be in a loop. +When a compare-and-exchange is in a loop, +the weak version will yield better performance on some platforms. +When a weak compare-and-exchange would require a loop and +a strong one would not, the strong one is preferable. +\end{note} +\end{itemdescr} + +\indexlibrarymember{wait}{atomic_ref}% +\begin{itemdecl} +void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is +neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Repeatedly performs the following steps, in order: +\begin{itemize} +\item + Evaluates \tcode{load(order)} and + compares its value representation for equality against that of \tcode{old}. +\item + If they compare unequal, returns. +\item + Blocks until it + is unblocked by an atomic notifying operation or is unblocked spuriously. +\end{itemize} + +\pnum +\remarks +This function is an atomic waiting operation\iref{atomics.wait} +on atomic object \tcode{*ptr}. +\end{itemdescr} + +\indexlibrarymember{notify_one}{atomic_ref}% +\begin{itemdecl} +void notify_one() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of at least one atomic waiting operation on \tcode{*ptr} +that is eligible to be unblocked\iref{atomics.wait} by this call, +if any such atomic waiting operations exist. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait} +on atomic object \tcode{*ptr}. +\end{itemdescr} + +\indexlibrarymember{notify_all}{atomic_ref}% +\begin{itemdecl} +void notify_all() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of all atomic waiting operations on \tcode{*ptr} +that are eligible to be unblocked\iref{atomics.wait} by this call. + +\pnum +\remarks + This function is an atomic notifying operation\iref{atomics.wait} + on atomic object \tcode{*ptr}. +\end{itemdescr} + +\rSec3[atomics.ref.int]{Specializations for integral types} + +\pnum +\indexlibrary{\idxcode{atomic_ref<\placeholder{integral}>}}% +There are specializations of the \tcode{atomic_ref} class template +for the integral types +\tcode{char}, +\tcode{signed char}, +\tcode{unsigned char}, +\tcode{short}, +\tcode{unsigned short}, +\tcode{int}, +\tcode{unsigned int}, +\tcode{long}, +\tcode{unsigned long}, +\tcode{long long}, +\tcode{unsigned long long}, +\keyword{char8_t}, +\keyword{char16_t}, +\keyword{char32_t}, +\keyword{wchar_t}, +and any other types needed by the typedefs in the header \libheaderref{cstdint}. +For each such type \tcode{\placeholder{integral}}, +the specialization \tcode{atomic_ref<\placeholder{integral}>} provides +additional atomic operations appropriate to integral types. +\begin{note} +The specialization \tcode{atomic_ref} +uses the primary template\iref{atomics.ref.generic}. +\end{note} + +\begin{codeblock} +namespace std { + template<> struct atomic_ref<@\placeholder{integral}@> { + private: + @\placeholder{integral}@* ptr; // \expos + public: + using value_type = @\placeholder{integral}@; + using difference_type = value_type; + static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; + bool is_lock_free() const noexcept; + + explicit atomic_ref(@\placeholder{integral}@&); + atomic_ref(const atomic_ref&) noexcept; + atomic_ref& operator=(const atomic_ref&) = delete; + + void store(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const noexcept; + @\placeholdernc{integral}@ operator=(@\placeholder{integral}@) const noexcept; + @\placeholdernc{integral}@ load(memory_order = memory_order::seq_cst) const noexcept; + operator @\placeholdernc{integral}@() const noexcept; + + @\placeholdernc{integral}@ exchange(@\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholder{integral}@, + memory_order, memory_order) const noexcept; + bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholder{integral}@, + memory_order, memory_order) const noexcept; + bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholder{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholder{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + + @\placeholdernc{integral}@ fetch_add(@\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + @\placeholdernc{integral}@ fetch_sub(@\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + @\placeholdernc{integral}@ fetch_and(@\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + @\placeholdernc{integral}@ fetch_or(@\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + @\placeholdernc{integral}@ fetch_xor(@\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) const noexcept; + + @\placeholdernc{integral}@ operator++(int) const noexcept; + @\placeholdernc{integral}@ operator--(int) const noexcept; + @\placeholdernc{integral}@ operator++() const noexcept; + @\placeholdernc{integral}@ operator--() const noexcept; + @\placeholdernc{integral}@ operator+=(@\placeholdernc{integral}@) const noexcept; + @\placeholdernc{integral}@ operator-=(@\placeholdernc{integral}@) const noexcept; + @\placeholdernc{integral}@ operator&=(@\placeholdernc{integral}@) const noexcept; + @\placeholdernc{integral}@ operator|=(@\placeholdernc{integral}@) const noexcept; + @\placeholdernc{integral}@ operator^=(@\placeholdernc{integral}@) const noexcept; + + void wait(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() const noexcept; + void notify_all() const noexcept; + }; +} +\end{codeblock} + +\pnum +Descriptions are provided below only for members +that differ from the primary template. + +\pnum +The following operations perform arithmetic computations. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.int.comp}. + +\indexlibrarymember{fetch_add}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{fetch_and}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{fetch_or}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{fetch_xor}{atomic_ref<\placeholder{integral}>}% +\begin{itemdecl} +@\placeholdernc{integral}@ fetch_@\placeholdernc{key}@(@\placeholdernc{integral}@ operand, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Atomically replaces the value referenced by \tcode{*ptr} with +the result of the computation applied to the value referenced by \tcode{*ptr} +and the given operand. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.races}. + +\pnum +\returns +Atomically, the value referenced by \tcode{*ptr} +immediately before the effects. + +\pnum +\indextext{signed integer representation!two's complement}% +\remarks +For signed integer types, +the result is as if the object value and parameters +were converted to their corresponding unsigned types, +the computation performed on those types, and +the result converted back to the signed type. +\begin{note} +There are no undefined results arising from the computation. +\end{note} +\end{itemdescr} + +\indexlibrarymember{operator+=}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{operator-=}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{operator\&=}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{operator"|=}{atomic_ref<\placeholder{integral}>}% +\indexlibrarymember{operator\caret=}{atomic_ref<\placeholder{integral}>}% +\begin{itemdecl} +@\placeholdernc{integral}@ operator @\placeholder{op}@=(@\placeholdernc{integral}@ operand) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return fetch_\placeholdernc{key}(operand) \placeholder{op} operand;} +\end{itemdescr} + +\rSec3[atomics.ref.float]{Specializations for floating-point types} + +\pnum +\indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point}>}}% +There are specializations of the \tcode{atomic_ref} class template +for the floating-point types +\tcode{float}, +\tcode{double}, and +\tcode{long double}. +For each such type \tcode{\placeholder{floating-point}}, +the specialization \tcode{atomic_ref<\placeholder{floating-\-point}>} provides +additional atomic operations appropriate to floating-point types. + +\begin{codeblock} +namespace std { + template<> struct atomic_ref<@\placeholder{floating-point}@> { + private: + @\placeholder{floating-point}@* ptr; // \expos + public: + using value_type = @\placeholder{floating-point}@; + using difference_type = value_type; + static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; + bool is_lock_free() const noexcept; + + explicit atomic_ref(@\placeholder{floating-point}@&); + atomic_ref(const atomic_ref&) noexcept; + atomic_ref& operator=(const atomic_ref&) = delete; + + void store(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const noexcept; + @\placeholder{floating-point}@ operator=(@\placeholder{floating-point}@) const noexcept; + @\placeholder{floating-point}@ load(memory_order = memory_order::seq_cst) const noexcept; + operator @\placeholdernc{floating-point}@() const noexcept; + + @\placeholder{floating-point}@ exchange(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order, memory_order) const noexcept; + bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order, memory_order) const noexcept; + bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) const noexcept; + + @\placeholder{floating-point}@ fetch_add(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) const noexcept; + @\placeholder{floating-point}@ fetch_sub(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) const noexcept; + + @\placeholder{floating-point}@ operator+=(@\placeholder{floating-point}@) const noexcept; + @\placeholder{floating-point}@ operator-=(@\placeholder{floating-point}@) const noexcept; + + void wait(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() const noexcept; + void notify_all() const noexcept; + }; +} +\end{codeblock} + +\pnum +Descriptions are provided below only for members +that differ from the primary template. + +\pnum +The following operations perform arithmetic computations. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.int.comp}. + +\indexlibrarymember{fetch_add}{atomic_ref<\placeholder{floating-point}>}% +\indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +@\placeholder{floating-point}@ fetch_@\placeholdernc{key}@(@\placeholder{floating-point}@ operand, + memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Atomically replaces the value referenced by \tcode{*ptr} with +the result of the computation applied to the value referenced by \tcode{*ptr} +and the given operand. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.races}. + +\pnum +\returns +Atomically, the value referenced by \tcode{*ptr} +immediately before the effects. + +\pnum +\remarks +If the result is not a representable value for its type\iref{expr.pre}, +the result is unspecified, +but the operations otherwise have no undefined behavior. +Atomic arithmetic operations on \tcode{\placeholder{floating-point}} should conform to +the \tcode{std::numeric_limits<\placeholder{floating-point}>} traits +associated with the floating-point type\iref{limits.syn}. +The floating-point environment\iref{cfenv} +for atomic arithmetic operations on \tcode{\placeholder{floating-point}} +may be different than the calling thread's floating-point environment. +\end{itemdescr} + +\indexlibrarymember{operator+=}{atomic_ref<\placeholder{floating-point}>}% +\indexlibrarymember{operator-=}{atomic_ref<\placeholder{floating-point}>}% +\begin{itemdecl} +@\placeholder{floating-point}@ operator @\placeholder{op}@=(@\placeholder{floating-point}@ operand) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return fetch_\placeholder{key}(operand) \placeholdernc{op} operand;} +\end{itemdescr} + +\rSec3[atomics.ref.pointer]{Partial specialization for pointers} +\indexlibraryglobal{atomic_ref}% + +\begin{codeblock} +namespace std { + template struct atomic_ref { + private: + T** ptr; // \expos + public: + using value_type = T*; + using difference_type = ptrdiff_t; + static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; + bool is_lock_free() const noexcept; + + explicit atomic_ref(T*&); + atomic_ref(const atomic_ref&) noexcept; + atomic_ref& operator=(const atomic_ref&) = delete; + + void store(T*, memory_order = memory_order::seq_cst) const noexcept; + T* operator=(T*) const noexcept; + T* load(memory_order = memory_order::seq_cst) const noexcept; + operator T*() const noexcept; + + T* exchange(T*, memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_weak(T*&, T*, + memory_order, memory_order) const noexcept; + bool compare_exchange_strong(T*&, T*, + memory_order, memory_order) const noexcept; + bool compare_exchange_weak(T*&, T*, + memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_strong(T*&, T*, + memory_order = memory_order::seq_cst) const noexcept; + + T* fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept; + T* fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept; + + T* operator++(int) const noexcept; + T* operator--(int) const noexcept; + T* operator++() const noexcept; + T* operator--() const noexcept; + T* operator+=(difference_type) const noexcept; + T* operator-=(difference_type) const noexcept; + + void wait(T*, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() const noexcept; + void notify_all() const noexcept; + }; +} +\end{codeblock} + +\pnum +Descriptions are provided below only for members +that differ from the primary template. + +\pnum +The following operations perform arithmetic computations. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.pointer.comp}. + +\indexlibrarymember{fetch_add}{atomic_ref}% +\indexlibrarymember{fetch_sub}{atomic_ref}% +\begin{itemdecl} +T* fetch_@\placeholdernc{key}@(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is a complete object type. + +\pnum +\effects +Atomically replaces the value referenced by \tcode{*ptr} with +the result of the computation applied to the value referenced by \tcode{*ptr} +and the given operand. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.races}. + +\pnum +\returns +Atomically, the value referenced by \tcode{*ptr} +immediately before the effects. + +\pnum +\remarks +The result may be an undefined address, +but the operations otherwise have no undefined behavior. +\end{itemdescr} + +\indexlibrarymember{operator+=}{atomic_ref}% +\indexlibrarymember{operator-=}{atomic_ref}% +\begin{itemdecl} +T* operator @\placeholder{op}@=(difference_type operand) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return fetch_\placeholder{key}(operand) \placeholdernc{op} operand;} +\end{itemdescr} + +\rSec3[atomics.ref.memop]{Member operators + common to integers and pointers to objects} + +\indexlibrarymember{operator++}{atomic_ref}% +\indexlibrarymember{operator++}{atomic_ref<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator++(int) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return fetch_add(1);} +\end{itemdescr} + +\indexlibrarymember{operator--}{atomic_ref}% +\indexlibrarymember{operator--}{atomic_ref<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator--(int) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return fetch_sub(1);} +\end{itemdescr} + +\indexlibrarymember{operator++}{atomic_ref}% +\indexlibrarymember{operator++}{atomic_ref<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator++() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return fetch_add(1) + 1;} +\end{itemdescr} + +\indexlibrarymember{operator--}{atomic_ref}% +\indexlibrarymember{operator--}{atomic_ref<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator--() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return fetch_sub(1) - 1;} +\end{itemdescr} + +\rSec2[atomics.types.generic]{Class template \tcode{atomic}} + +\rSec3[atomics.types.generic.general]{General} + +\indexlibraryglobal{atomic}% +\indexlibrarymember{value_type}{atomic}% +\begin{codeblock} +namespace std { + template struct atomic { + using value_type = T; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; + bool is_lock_free() const volatile noexcept; + bool is_lock_free() const noexcept; + + // \ref{atomics.types.operations}, operations on atomic types + constexpr atomic() noexcept(is_nothrow_default_constructible_v); + constexpr atomic(T) noexcept; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + T load(memory_order = memory_order::seq_cst) const volatile noexcept; + T load(memory_order = memory_order::seq_cst) const noexcept; + operator T() const volatile noexcept; + operator T() const noexcept; + void store(T, memory_order = memory_order::seq_cst) volatile noexcept; + void store(T, memory_order = memory_order::seq_cst) noexcept; + T operator=(T) volatile noexcept; + T operator=(T) noexcept; + + T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept; + T exchange(T, memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept; + bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept; + bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept; + bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept; + bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept; + + void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept; + void wait(T, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() volatile noexcept; + void notify_one() noexcept; + void notify_all() volatile noexcept; + void notify_all() noexcept; + }; +} +\end{codeblock} + +\indexlibraryglobal{atomic}% +\pnum +The template argument for \tcode{T} shall meet the +\oldconcept{CopyConstructible} and \oldconcept{CopyAssignable} requirements. +The program is ill-formed if any of +\begin{itemize} +\item \tcode{is_trivially_copyable_v}, +\item \tcode{is_copy_constructible_v}, +\item \tcode{is_move_constructible_v}, +\item \tcode{is_copy_assignable_v}, or +\item \tcode{is_move_assignable_v} +\end{itemize} +is \tcode{false}. +\begin{note} +Type arguments that are +not also statically initializable can be difficult to use. +\end{note} + +\pnum +The specialization \tcode{atomic} is a standard-layout struct. + +\pnum +\begin{note} +The representation of an atomic specialization +need not have the same size and alignment requirement as +its corresponding argument type. +\end{note} + +\rSec3[atomics.types.operations]{Operations on atomic types} + +\indexlibraryctor{atomic}% +\indexlibraryctor{atomic}% +\indexlibrary{\idxcode{atomic<\placeholder{integral}>}!constructor}% +\indexlibrary{\idxcode{atomic<\placeholder{floating-point}>}!constructor}% +\begin{itemdecl} +constexpr atomic() noexcept(is_nothrow_default_constructible_v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_default_constructible_v} is \tcode{true}. + +\pnum +\effects +Initializes the atomic object with the value of \tcode{T()}. +Initialization is not an atomic operation\iref{intro.multithread}. +\end{itemdescr} + +\indexlibraryctor{atomic}% +\indexlibraryctor{atomic}% +\indexlibrary{\idxcode{atomic<\placeholder{integral}>}!constructor}% +\indexlibrary{\idxcode{atomic<\placeholder{floating-point}>}!constructor}% +\begin{itemdecl} +constexpr atomic(T desired) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes the object with the value \tcode{desired}. +Initialization is not an atomic operation\iref{intro.multithread}. +\begin{note} +It is possible to have an access to an atomic object \tcode{A} +race with its construction, for example by communicating the address of the +just-constructed object \tcode{A} to another thread via +\tcode{memory_order::relaxed} operations on a suitable atomic pointer +variable, and then immediately accessing \tcode{A} in the receiving thread. +This results in undefined behavior. +\end{note} +\end{itemdescr} + +\indexlibrarymember{is_always_lock_free}{atomic}% +\indexlibrarymember{is_always_lock_free}{atomic}% +\indexlibrarymember{is_always_lock_free}{atomic<\placeholder{integral}>}% +\indexlibrarymember{is_always_lock_free}{atomic<\placeholder{floating-point}>}% +\indexlibrarymember{is_always_lock_free}{atomic>}% +\indexlibrarymember{is_always_lock_free}{atomic>}% +\begin{itemdecl} +static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The \keyword{static} data member \tcode{is_always_lock_free} is \tcode{true} +if the atomic type's operations are always lock-free, and \tcode{false} otherwise. +\begin{note} +The value of \tcode{is_always_lock_free} is consistent with the value of +the corresponding \tcode{ATOMIC_..._LOCK_FREE} macro, if defined. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{atomic_is_lock_free}% +\indexlibrarymember{is_lock_free}{atomic}% +\indexlibrarymember{is_lock_free}{atomic}% +\indexlibrarymember{is_lock_free}{atomic<\placeholder{integral}>}% +\indexlibrarymember{is_lock_free}{atomic<\placeholder{floating-point}>}% +\indexlibrarymember{is_lock_free}{atomic>}% +\indexlibrarymember{is_lock_free}{atomic>}% +\begin{itemdecl} +bool is_lock_free() const volatile noexcept; +bool is_lock_free() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if the object's operations are lock-free, \tcode{false} otherwise. +\begin{note} +The return value of the \tcode{is_lock_free} member function +is consistent with the value of \tcode{is_always_lock_free} for the same type. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{atomic_store}% +\indexlibraryglobal{atomic_store_explicit}% +\indexlibrarymember{store}{atomic}% +\indexlibrarymember{store}{atomic}% +\indexlibrarymember{store}{atomic<\placeholder{integral}>}% +\indexlibrarymember{store}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; +void store(T desired, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\expects +The \tcode{order} argument is neither \tcode{memory_order::consume}, +\tcode{memory_order::acquire}, nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Atomically replaces the value pointed to by \keyword{this} +with the value of \tcode{desired}. Memory is affected according to the value of +\tcode{order}. +\end{itemdescr} + +\indexlibrarymember{operator=}{atomic}% +\indexlibrarymember{operator=}{atomic}% +\indexlibrarymember{operator=}{atomic<\placeholder{integral}>}% +\indexlibrarymember{operator=}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +T operator=(T desired) volatile noexcept; +T operator=(T desired) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to \tcode{store(desired)}. + +\pnum +\returns +\tcode{desired}. +\end{itemdescr} + +\indexlibraryglobal{atomic_load}% +\indexlibraryglobal{atomic_load_explicit}% +\indexlibrarymember{load}{atomic}% +\indexlibrarymember{load}{atomic}% +\indexlibrarymember{load}{atomic<\placeholder{integral}>}% +\indexlibrarymember{load}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +T load(memory_order order = memory_order::seq_cst) const volatile noexcept; +T load(memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\expects +The \tcode{order} argument is neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Memory is affected according to the value of \tcode{order}. + +\pnum +\returns +Atomically returns the value pointed to by \keyword{this}. +\end{itemdescr} + +\indexlibrarymember{operator \placeholder{type}}{atomic}% +\indexlibrarymember{operator T*}{atomic}% +\indexlibrarymember{operator \placeholder{integral}}{atomic<\placeholder{integral}>}% +\indexlibrarymember{operator \placeholder{floating-point}}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +operator T() const volatile noexcept; +operator T() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return load();} +\end{itemdescr} + + +\indexlibraryglobal{atomic_exchange}% +\indexlibraryglobal{atomic_exchange_explicit}% +\indexlibrarymember{exchange}{atomic}% +\indexlibrarymember{exchange}{atomic}% +\indexlibrarymember{exchange}{atomic<\placeholder{integral}>}% +\indexlibrarymember{exchange}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; +T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Atomically replaces the value pointed to by \keyword{this} +with \tcode{desired}. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.multithread}. + +\pnum +\returns +Atomically returns the value pointed to by \keyword{this} immediately before the effects. +\end{itemdescr} + +\indexlibraryglobal{atomic_compare_exchange_weak}% +\indexlibraryglobal{atomic_compare_exchange_strong}% +\indexlibraryglobal{atomic_compare_exchange_weak_explicit}% +\indexlibraryglobal{atomic_compare_exchange_strong_explicit}% +\indexlibrarymember{compare_exchange_weak}{atomic}% +\indexlibrarymember{compare_exchange_weak}{atomic}% +\indexlibrarymember{compare_exchange_weak}{atomic<\placeholder{integral}>}% +\indexlibrarymember{compare_exchange_weak}{atomic<\placeholder{floating-point}>}% +\indexlibrarymember{compare_exchange_strong}{atomic}% +\indexlibrarymember{compare_exchange_strong}{atomic}% +\indexlibrarymember{compare_exchange_strong}{atomic<\placeholder{integral}>}% +\indexlibrarymember{compare_exchange_strong}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +bool compare_exchange_weak(T& expected, T desired, + memory_order success, memory_order failure) volatile noexcept; +bool compare_exchange_weak(T& expected, T desired, + memory_order success, memory_order failure) noexcept; +bool compare_exchange_strong(T& expected, T desired, + memory_order success, memory_order failure) volatile noexcept; +bool compare_exchange_strong(T& expected, T desired, + memory_order success, memory_order failure) noexcept; +bool compare_exchange_weak(T& expected, T desired, + memory_order order = memory_order::seq_cst) volatile noexcept; +bool compare_exchange_weak(T& expected, T desired, + memory_order order = memory_order::seq_cst) noexcept; +bool compare_exchange_strong(T& expected, T desired, + memory_order order = memory_order::seq_cst) volatile noexcept; +bool compare_exchange_strong(T& expected, T desired, + memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\expects +The \tcode{failure} argument is neither \tcode{memory_order::release} nor +\tcode{memory_order::acq_rel}. + +\pnum +\effects +Retrieves the value in \tcode{expected}. It then atomically +compares the value representation of the value pointed to by \keyword{this} +for equality with that previously retrieved from \tcode{expected}, +and if true, replaces the value pointed to +by \keyword{this} with that in \tcode{desired}. +If and only if the comparison is \tcode{true}, memory is affected according to the +value of \tcode{success}, and if the comparison is false, memory is affected according +to the value of \tcode{failure}. When only one \tcode{memory_order} argument is +supplied, the value of \tcode{success} is \tcode{order}, and the value of +\tcode{failure} is \tcode{order} except that a value of \tcode{memory_order::acq_rel} +shall be replaced by the value \tcode{memory_order::acquire} and a value of +\tcode{memory_order::release} shall be replaced by the value +\tcode{memory_order::relaxed}. +If and only if the comparison is false then, after the atomic operation, +the value in \tcode{expected} is replaced by the value +pointed to by \keyword{this} during the atomic comparison. +If the operation returns \tcode{true}, these +operations are atomic read-modify-write +operations\iref{intro.multithread} on the memory +pointed to by \keyword{this}. +Otherwise, these operations are atomic load operations on that memory. + +\pnum +\returns +The result of the comparison. + +\pnum +\begin{note} +For example, the effect of +\tcode{compare_exchange_strong} +on objects without padding bits\iref{term.padding.bits} is +\begin{codeblock} +if (memcmp(this, &expected, sizeof(*this)) == 0) + memcpy(this, &desired, sizeof(*this)); +else + memcpy(&expected, this, sizeof(*this)); +\end{codeblock} +\end{note} +\begin{example} +The expected use of the compare-and-exchange operations is as follows. The +compare-and-exchange operations will update \tcode{expected} when another iteration of +the loop is needed. +\begin{codeblock} +expected = current.load(); +do { + desired = function(expected); +} while (!current.compare_exchange_weak(expected, desired)); +\end{codeblock} +\end{example} +\begin{example} +Because the expected value is updated only on failure, +code releasing the memory containing the \tcode{expected} value on success will work. +For example, list head insertion will act atomically and would not introduce a +data race in the following code: +\begin{codeblock} +do { + p->next = head; // make new list node point to the current head +} while (!head.compare_exchange_weak(p->next, p)); // try to insert +\end{codeblock} +\end{example} + +\pnum +Implementations should ensure that weak compare-and-exchange operations do not +consistently return \tcode{false} unless either the atomic object has value +different from \tcode{expected} or there are concurrent modifications to the +atomic object. + +\pnum +\remarks +A weak compare-and-exchange operation may fail spuriously. That is, even when +the contents of memory referred to by \tcode{expected} and \keyword{this} are +equal, it may return \tcode{false} and store back to \tcode{expected} the same memory +contents that were originally there. +\begin{note} +This +spurious failure enables implementation of compare-and-exchange on a broader class of +machines, e.g., load-locked store-conditional machines. A +consequence of spurious failure is that nearly all uses of weak compare-and-exchange +will be in a loop. +When a compare-and-exchange is in a loop, the weak version will yield better performance +on some platforms. When a weak compare-and-exchange would require a loop and a strong one +would not, the strong one is preferable. +\end{note} + +\pnum +\begin{note} +Under cases where the \tcode{memcpy} and \tcode{memcmp} semantics of the compare-and-exchange +operations apply, the comparisons can fail for values that compare equal with +\tcode{operator==} if the value representation has trap bits or alternate +representations of the same value. Notably, on implementations conforming to +ISO/IEC/IEEE 60559, floating-point \tcode{-0.0} and \tcode{+0.0} +will not compare equal with \tcode{memcmp} but will compare equal with \tcode{operator==}, +and NaNs with the same payload will compare equal with \tcode{memcmp} but will not +compare equal with \tcode{operator==}. +\end{note} +\begin{note} +Because compare-and-exchange acts on an object's value representation, +padding bits that never participate in the object's value representation +are ignored. As a consequence, the following code is guaranteed to avoid +spurious failure: +\begin{codeblock} +struct padded { + char clank = 0x42; + // Padding here. + unsigned biff = 0xC0DEFEFE; +}; +atomic pad = {}; + +bool zap() { + padded expected, desired{0, 0}; + return pad.compare_exchange_strong(expected, desired); +} +\end{codeblock} +\end{note} +\begin{note} +For a union with bits that participate in the value representation +of some members but not others, compare-and-exchange might always fail. +This is because such padding bits have an indeterminate value when they +do not participate in the value representation of the active member. +As a consequence, the following code is not guaranteed to ever succeed: +\begin{codeblock} +union pony { + double celestia = 0.; + short luna; // padded +}; +atomic princesses = {}; + +bool party(pony desired) { + pony expected; + return princesses.compare_exchange_strong(expected, desired); +} +\end{codeblock} +\end{note} +\end{itemdescr} + +\indexlibrarymember{wait}{atomic}% +\indexlibrarymember{wait}{atomic}% +\indexlibrarymember{wait}{atomic<\placeholder{integral}>}% +\indexlibrarymember{wait}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept; +void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Repeatedly performs the following steps, in order: +\begin{itemize} +\item + Evaluates \tcode{load(order)} and + compares its value representation for equality against that of \tcode{old}. +\item + If they compare unequal, returns. +\item + Blocks until it + is unblocked by an atomic notifying operation or is unblocked spuriously. +\end{itemize} + +\pnum +\remarks +This function is an atomic waiting operation\iref{atomics.wait}. +\end{itemdescr} + +\indexlibrarymember{notify_one}{atomic}% +\indexlibrarymember{notify_one}{atomic}% +\indexlibrarymember{notify_one}{atomic<\placeholder{integral}>}% +\indexlibrarymember{notify_one}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +void notify_one() volatile noexcept; +void notify_one() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of at least one atomic waiting operation +that is eligible to be unblocked\iref{atomics.wait} by this call, +if any such atomic waiting operations exist. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\indexlibrarymember{notify_all}{atomic}% +\indexlibrarymember{notify_all}{atomic}% +\indexlibrarymember{notify_all}{atomic<\placeholder{integral}>}% +\indexlibrarymember{notify_all}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +void notify_all() volatile noexcept; +void notify_all() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of all atomic waiting operations +that are eligible to be unblocked\iref{atomics.wait} by this call. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\rSec3[atomics.types.int]{Specializations for integers} + +\indexlibrary{\idxcode{atomic<\placeholder{integral}>}}% +\pnum +There are specializations of the \tcode{atomic} +class template for the integral types +\tcode{char}, +\tcode{signed char}, +\tcode{unsigned char}, +\tcode{short}, +\tcode{unsigned short}, +\tcode{int}, +\tcode{unsigned int}, +\tcode{long}, +\tcode{unsigned long}, +\tcode{long long}, +\tcode{unsigned long long}, +\keyword{char8_t}, +\keyword{char16_t}, +\keyword{char32_t}, +\keyword{wchar_t}, +and any other types needed by the typedefs in the header \libheaderref{cstdint}. +For each such type \tcode{\placeholder{integral}}, the specialization +\tcode{atomic<\placeholder{integral}>} provides additional atomic operations appropriate to integral types. +\begin{note} +The specialization \tcode{atomic} +uses the primary template\iref{atomics.types.generic}. +\end{note} + +\begin{codeblock} +namespace std { + template<> struct atomic<@\placeholder{integral}@> { + using value_type = @\placeholder{integral}@; + using difference_type = value_type; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; + bool is_lock_free() const volatile noexcept; + bool is_lock_free() const noexcept; + + constexpr atomic() noexcept; + constexpr atomic(@\placeholdernc{integral}@) noexcept; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + void store(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + void store(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{integral}@ operator=(@\placeholdernc{integral}@) volatile noexcept; + @\placeholdernc{integral}@ operator=(@\placeholdernc{integral}@) noexcept; + @\placeholdernc{integral}@ load(memory_order = memory_order::seq_cst) const volatile noexcept; + @\placeholdernc{integral}@ load(memory_order = memory_order::seq_cst) const noexcept; + operator @\placeholdernc{integral}@() const volatile noexcept; + operator @\placeholdernc{integral}@() const noexcept; + + @\placeholdernc{integral}@ exchange(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{integral}@ exchange(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order, memory_order) volatile noexcept; + bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order, memory_order) noexcept; + bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order, memory_order) volatile noexcept; + bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order, memory_order) noexcept; + bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_weak(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_strong(@\placeholder{integral}@&, @\placeholdernc{integral}@, + memory_order = memory_order::seq_cst) noexcept; + + @\placeholdernc{integral}@ fetch_add(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{integral}@ fetch_add(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{integral}@ fetch_sub(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{integral}@ fetch_sub(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{integral}@ fetch_and(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{integral}@ fetch_and(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{integral}@ fetch_or(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{integral}@ fetch_or(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{integral}@ fetch_xor(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{integral}@ fetch_xor(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) noexcept; + + @\placeholdernc{integral}@ operator++(int) volatile noexcept; + @\placeholdernc{integral}@ operator++(int) noexcept; + @\placeholdernc{integral}@ operator--(int) volatile noexcept; + @\placeholdernc{integral}@ operator--(int) noexcept; + @\placeholdernc{integral}@ operator++() volatile noexcept; + @\placeholdernc{integral}@ operator++() noexcept; + @\placeholdernc{integral}@ operator--() volatile noexcept; + @\placeholdernc{integral}@ operator--() noexcept; + @\placeholdernc{integral}@ operator+=(@\placeholdernc{integral}@) volatile noexcept; + @\placeholdernc{integral}@ operator+=(@\placeholdernc{integral}@) noexcept; + @\placeholdernc{integral}@ operator-=(@\placeholdernc{integral}@) volatile noexcept; + @\placeholdernc{integral}@ operator-=(@\placeholdernc{integral}@) noexcept; + @\placeholdernc{integral}@ operator&=(@\placeholdernc{integral}@) volatile noexcept; + @\placeholdernc{integral}@ operator&=(@\placeholdernc{integral}@) noexcept; + @\placeholdernc{integral}@ operator|=(@\placeholdernc{integral}@) volatile noexcept; + @\placeholdernc{integral}@ operator|=(@\placeholdernc{integral}@) noexcept; + @\placeholdernc{integral}@ operator^=(@\placeholdernc{integral}@) volatile noexcept; + @\placeholdernc{integral}@ operator^=(@\placeholdernc{integral}@) noexcept; + + void wait(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const volatile noexcept; + void wait(@\placeholdernc{integral}@, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() volatile noexcept; + void notify_one() noexcept; + void notify_all() volatile noexcept; + void notify_all() noexcept; + }; +} +\end{codeblock} + +\pnum +The atomic integral specializations +are standard-layout structs. +They each have +a trivial destructor. + +\pnum +Descriptions are provided below only for members that differ from the primary template. + +\pnum +The following operations perform arithmetic computations. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.int.comp}. + +\begin{floattable} +{Atomic arithmetic computations}{atomic.types.int.comp}{lll|lll} +\hline +\hdstyle{\tcode{\placeholder{key}}} & + \hdstyle{Op} & + \hdstyle{Computation} & +\hdstyle{\tcode{\placeholder{key}}} & + \hdstyle{Op} & + \hdstyle{Computation} \\ \hline +\tcode{add} & + \tcode{+} & + addition & +\tcode{sub} & + \tcode{-} & + subtraction \\ +\tcode{or} & + \tcode{|} & + bitwise inclusive or & +\tcode{xor} & + \tcode{\caret} & + bitwise exclusive or \\ +\tcode{and} & + \tcode{\&} & + bitwise and &&&\\ +\end{floattable} + +\indexlibraryglobal{atomic_fetch_add}% +\indexlibraryglobal{atomic_fetch_and}% +\indexlibraryglobal{atomic_fetch_or}% +\indexlibraryglobal{atomic_fetch_sub}% +\indexlibraryglobal{atomic_fetch_xor}% +\indexlibraryglobal{atomic_fetch_add_explicit}% +\indexlibraryglobal{atomic_fetch_and_explicit}% +\indexlibraryglobal{atomic_fetch_or_explicit}% +\indexlibraryglobal{atomic_fetch_sub_explicit}% +\indexlibraryglobal{atomic_fetch_xor_explicit}% +\indexlibrarymember{fetch_add}{atomic<\placeholder{integral}>}% +\indexlibrarymember{fetch_and}{atomic<\placeholder{integral}>}% +\indexlibrarymember{fetch_or}{atomic<\placeholder{integral}>}% +\indexlibrarymember{fetch_sub}{atomic<\placeholder{integral}>}% +\indexlibrarymember{fetch_xor}{atomic<\placeholder{integral}>}% +\begin{itemdecl} +T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; +T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Atomically replaces the value pointed to by +\keyword{this} with the result of the computation applied to the +value pointed to by \keyword{this} and the given \tcode{operand}. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.multithread}. + +\pnum +\returns +Atomically, the value pointed to by \keyword{this} immediately before the effects. + +\pnum +\indextext{signed integer representation!two's complement}% +\remarks +For signed integer types, +the result is as if the object value and parameters +were converted to their corresponding unsigned types, +the computation performed on those types, and +the result converted back to the signed type. +\begin{note} +There are no undefined results arising from the computation. +\end{note} + +\end{itemdescr} + +\indexlibrarymember{operator+=}{atomic}% +\indexlibrarymember{operator-=}{atomic}% +\indexlibrarymember{operator+=}{atomic<\placeholder{integral}>}% +\indexlibrarymember{operator-=}{atomic<\placeholder{integral}>}% +\indexlibrarymember{operator\&=}{atomic<\placeholder{integral}>}% +\indexlibrarymember{operator"|=}{atomic<\placeholder{integral}>}% +\indexlibrarymember{operator\caret=}{atomic<\placeholder{integral}>}% +\begin{itemdecl} +T operator @\placeholder{op}@=(T operand) volatile noexcept; +T operator @\placeholder{op}@=(T operand) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_\placeholder{key}(operand) \placeholder{op} operand;} +\end{itemdescr} + +\rSec3[atomics.types.float]{Specializations for floating-point types} + +\indexlibrary{\idxcode{atomic<\placeholder{floating-point}>}}% +\pnum +There are specializations of the \tcode{atomic} +class template for the floating-point types +\tcode{float}, +\tcode{double}, and +\tcode{long double}. +For each such type \tcode{\placeholdernc{floating-point}}, +the specialization \tcode{atomic<\placeholder{floating-point}>} +provides additional atomic operations appropriate to floating-point types. + +\begin{codeblock} +namespace std { + template<> struct atomic<@\placeholder{floating-point}@> { + using value_type = @\placeholdernc{floating-point}@; + using difference_type = value_type; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; + bool is_lock_free() const volatile noexcept; + bool is_lock_free() const noexcept; + + constexpr atomic() noexcept; + constexpr atomic(@\placeholder{floating-point}@) noexcept; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + void store(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) volatile noexcept; + void store(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point}@ operator=(@\placeholder{floating-point}@) volatile noexcept; + @\placeholdernc{floating-point}@ operator=(@\placeholder{floating-point}@) noexcept; + @\placeholdernc{floating-point}@ load(memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{floating-point}@ load(memory_order = memory_order::seq_cst) noexcept; + operator @\placeholdernc{floating-point}@() volatile noexcept; + operator @\placeholdernc{floating-point}@() noexcept; + + @\placeholdernc{floating-point}@ exchange(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{floating-point}@ exchange(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order, memory_order) volatile noexcept; + bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order, memory_order) noexcept; + bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order, memory_order) volatile noexcept; + bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order, memory_order) noexcept; + bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_weak(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_strong(@\placeholder{floating-point}@&, @\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) noexcept; + + @\placeholdernc{floating-point}@ fetch_add(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{floating-point}@ fetch_add(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point}@ fetch_sub(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) volatile noexcept; + @\placeholdernc{floating-point}@ fetch_sub(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) noexcept; + + @\placeholdernc{floating-point}@ operator+=(@\placeholder{floating-point}@) volatile noexcept; + @\placeholdernc{floating-point}@ operator+=(@\placeholder{floating-point}@) noexcept; + @\placeholdernc{floating-point}@ operator-=(@\placeholder{floating-point}@) volatile noexcept; + @\placeholdernc{floating-point}@ operator-=(@\placeholder{floating-point}@) noexcept; + + void wait(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const volatile noexcept; + void wait(@\placeholdernc{floating-point}@, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() volatile noexcept; + void notify_one() noexcept; + void notify_all() volatile noexcept; + void notify_all() noexcept; + }; +} +\end{codeblock} + +\pnum +The atomic floating-point specializations +are standard-layout structs. +They each have +a trivial destructor. + +\pnum +Descriptions are provided below only for members that differ from the primary template. + +\pnum +The following operations perform arithmetic addition and subtraction computations. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.int.comp}. + +\indexlibraryglobal{atomic_fetch_add}% +\indexlibraryglobal{atomic_fetch_sub}% +\indexlibraryglobal{atomic_fetch_add_explicit}% +\indexlibraryglobal{atomic_fetch_sub_explicit}% +\indexlibrarymember{fetch_add}{atomic<\placeholder{floating-point}>}% +\indexlibrarymember{fetch_sub}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; +T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Atomically replaces the value pointed to by \keyword{this} +with the result of the computation applied to the value pointed +to by \keyword{this} and the given \tcode{operand}. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.multithread}. + +\pnum +\returns +Atomically, the value pointed to by \keyword{this} immediately before the effects. + +\pnum +\remarks +If the result is not a representable value for its type\iref{expr.pre} +the result is unspecified, but the operations otherwise have no undefined +behavior. Atomic arithmetic operations on \tcode{\placeholder{floating-point}} +should conform to the \tcode{std::numeric_limits<\placeholder{floating-point}>} +traits associated with the floating-point type\iref{limits.syn}. +The floating-point environment\iref{cfenv} for atomic arithmetic operations +on \tcode{\placeholder{floating-point}} may be different than the +calling thread's floating-point environment. +\end{itemdescr} + +\indexlibrarymember{operator+=}{atomic}% +\indexlibrarymember{operator-=}{atomic}% +\indexlibrarymember{operator+=}{atomic<\placeholder{floating-point}>}% +\indexlibrarymember{operator-=}{atomic<\placeholder{floating-point}>}% +\begin{itemdecl} +T operator @\placeholder{op}@=(T operand) volatile noexcept; +T operator @\placeholder{op}@=(T operand) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_\placeholder{key}(operand) \placeholder{op} operand;} + +\pnum +\remarks +If the result is not a representable value for its type\iref{expr.pre} +the result is unspecified, but the operations otherwise have no undefined +behavior. Atomic arithmetic operations on \tcode{\placeholder{floating-point}} +should conform to the \tcode{std::numeric_limits<\placeholder{floating-point}>} +traits associated with the floating-point type\iref{limits.syn}. +The floating-point environment\iref{cfenv} for atomic arithmetic operations +on \tcode{\placeholder{floating-point}} may be different than the +calling thread's floating-point environment. +\end{itemdescr} + +\rSec3[atomics.types.pointer]{Partial specialization for pointers} +\indexlibraryglobal{atomic}% + +\begin{codeblock} +namespace std { + template struct atomic { + using value_type = T*; + using difference_type = ptrdiff_t; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; + bool is_lock_free() const volatile noexcept; + bool is_lock_free() const noexcept; + + constexpr atomic() noexcept; + constexpr atomic(T*) noexcept; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + void store(T*, memory_order = memory_order::seq_cst) volatile noexcept; + void store(T*, memory_order = memory_order::seq_cst) noexcept; + T* operator=(T*) volatile noexcept; + T* operator=(T*) noexcept; + T* load(memory_order = memory_order::seq_cst) const volatile noexcept; + T* load(memory_order = memory_order::seq_cst) const noexcept; + operator T*() const volatile noexcept; + operator T*() const noexcept; + + T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept; + T* exchange(T*, memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept; + bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept; + bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept; + bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept; + bool compare_exchange_weak(T*&, T*, + memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_weak(T*&, T*, + memory_order = memory_order::seq_cst) noexcept; + bool compare_exchange_strong(T*&, T*, + memory_order = memory_order::seq_cst) volatile noexcept; + bool compare_exchange_strong(T*&, T*, + memory_order = memory_order::seq_cst) noexcept; + + T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; + T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; + T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; + T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; + + T* operator++(int) volatile noexcept; + T* operator++(int) noexcept; + T* operator--(int) volatile noexcept; + T* operator--(int) noexcept; + T* operator++() volatile noexcept; + T* operator++() noexcept; + T* operator--() volatile noexcept; + T* operator--() noexcept; + T* operator+=(ptrdiff_t) volatile noexcept; + T* operator+=(ptrdiff_t) noexcept; + T* operator-=(ptrdiff_t) volatile noexcept; + T* operator-=(ptrdiff_t) noexcept; + + void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept; + void wait(T*, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() volatile noexcept; + void notify_one() noexcept; + void notify_all() volatile noexcept; + void notify_all() noexcept; + }; +} +\end{codeblock} + +\indexlibraryglobal{atomic}% +\pnum +There is a partial specialization of the \tcode{atomic} class template for pointers. +Specializations of this partial specialization are standard-layout structs. +They each have a trivial destructor. + +\pnum +Descriptions are provided below only for members that differ from the primary template. + +\pnum +The following operations perform pointer arithmetic. +The correspondence among key, operator, and computation is specified +in \tref{atomic.types.pointer.comp}. + +\begin{floattable} +{Atomic pointer computations}{atomic.types.pointer.comp}{lll|lll} +\hline +\hdstyle{\tcode{\placeholder{key}}} & + \hdstyle{Op} & + \hdstyle{Computation} & +\hdstyle{\tcode{\placeholder{key}}} & + \hdstyle{Op} & + \hdstyle{Computation} \\ \hline +\tcode{add} & + \tcode{+} & + addition & +\tcode{sub} & + \tcode{-} & + subtraction \\ +\end{floattable} + +\indexlibraryglobal{atomic_fetch_add}% +\indexlibraryglobal{atomic_fetch_sub}% +\indexlibraryglobal{atomic_fetch_add_explicit}% +\indexlibraryglobal{atomic_fetch_sub_explicit}% +\indexlibrarymember{fetch_add}{atomic}% +\indexlibrarymember{fetch_sub}{atomic}% +\begin{itemdecl} +T* fetch_@\placeholdernc{key}@(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept; +T* fetch_@\placeholdernc{key}@(ptrdiff_t operand, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\mandates +\tcode{T} is a complete object type. +\begin{note} +Pointer arithmetic on \tcode{void*} or function pointers is ill-formed. +\end{note} + +\pnum +\effects +Atomically replaces the value pointed to by +\keyword{this} with the result of the computation applied to the +value pointed to by \keyword{this} and the given \tcode{operand}. +Memory is affected according to the value of \tcode{order}. +These operations are atomic read-modify-write operations\iref{intro.multithread}. + +\pnum +\returns +Atomically, the value pointed to by \keyword{this} immediately before the effects. + +\pnum +\remarks +The result may be an undefined address, +but the operations otherwise have no undefined behavior. +\end{itemdescr} + +\indexlibrarymember{operator+=}{atomic}% +\indexlibrarymember{operator-=}{atomic}% +\begin{itemdecl} +T* operator @\placeholder{op}@=(ptrdiff_t operand) volatile noexcept; +T* operator @\placeholder{op}@=(ptrdiff_t operand) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_\placeholder{key}(operand) \placeholder{op} operand;} +\end{itemdescr} + +\rSec3[atomics.types.memop]{Member operators common to integers and pointers to objects} + +\indexlibrarymember{operator++}{atomic}% +\indexlibrarymember{operator++}{atomic<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator++(int) volatile noexcept; +value_type operator++(int) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_add(1);} +\end{itemdescr} + +\indexlibrarymember{operator--}{atomic}% +\indexlibrarymember{operator--}{atomic<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator--(int) volatile noexcept; +value_type operator--(int) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_sub(1);} +\end{itemdescr} + +\indexlibrarymember{operator++}{atomic}% +\indexlibrarymember{operator++}{atomic<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator++() volatile noexcept; +value_type operator++() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_add(1) + 1;} +\end{itemdescr} + +\indexlibrarymember{operator--}{atomic}% +\indexlibrarymember{operator--}{atomic<\placeholder{integral}>}% +\begin{itemdecl} +value_type operator--() volatile noexcept; +value_type operator--() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +For the \tcode{volatile} overload of this function, +\tcode{is_always_lock_free} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return fetch_sub(1) - 1;} +\end{itemdescr} + +\rSec3[util.smartptr.atomic]{Partial specializations for smart pointers}% +\indextext{atomic!smart pointers|(}% + +\rSec4[util.smartptr.atomic.general]{General} + +\pnum +The library provides partial specializations of the \tcode{atomic} template +for shared-ownership smart pointers\iref{util.sharedptr}. +\begin{note} +The partial specializations are declared in header \libheaderref{memory}. +\end{note} +The behavior of all operations is as specified in \ref{atomics.types.generic}, +unless specified otherwise. +The template parameter \tcode{T} of these partial specializations +may be an incomplete type. + +\pnum +All changes to an atomic smart pointer in \ref{util.smartptr.atomic}, and +all associated \tcode{use_count} increments, +are guaranteed to be performed atomically. +Associated \tcode{use_count} decrements +are sequenced after the atomic operation, +but are not required to be part of it. +Any associated deletion and deallocation +are sequenced after the atomic update step and +are not part of the atomic operation. +\begin{note} +If the atomic operation uses locks, +locks acquired by the implementation +will be held when any \tcode{use_count} adjustments are performed, and +will not be held when any destruction or deallocation +resulting from this is performed. +\end{note} + +\pnum +\begin{example} +\begin{codeblock} +template class atomic_list { + struct node { + T t; + shared_ptr next; + }; + atomic> head; + +public: + auto find(T t) const { + auto p = head.load(); + while (p && p->t != t) + p = p->next; + + return shared_ptr(move(p)); + } + + void push_front(T t) { + auto p = make_shared(); + p->t = t; + p->next = head; + while (!head.compare_exchange_weak(p->next, p)) {} + } +}; +\end{codeblock} +\end{example} + +\rSec4[util.smartptr.atomic.shared]{Partial specialization for \tcode{shared_ptr}} +\indexlibraryglobal{atomic>}% +\begin{codeblock} +namespace std { + template struct atomic> { + using value_type = shared_ptr; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; + bool is_lock_free() const noexcept; + + constexpr atomic() noexcept; + constexpr atomic(nullptr_t) noexcept : atomic() { } + atomic(shared_ptr desired) noexcept; + atomic(const atomic&) = delete; + void operator=(const atomic&) = delete; + + shared_ptr load(memory_order order = memory_order::seq_cst) const noexcept; + operator shared_ptr() const noexcept; + void store(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; + void operator=(shared_ptr desired) noexcept; + + shared_ptr exchange(shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, + memory_order success, memory_order failure) noexcept; + bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, + memory_order success, memory_order failure) noexcept; + bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + + void wait(shared_ptr old, memory_order order = memory_order::seq_cst) const noexcept; + void notify_one() noexcept; + void notify_all() noexcept; + + private: + shared_ptr p; // \expos + }; +} +\end{codeblock} + +\indexlibraryctor{atomic>}% +\begin{itemdecl} +constexpr atomic() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{p\{\}}. +\end{itemdescr} + +\indexlibraryctor{atomic>}% +\begin{itemdecl} +atomic(shared_ptr desired) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes the object with the value \tcode{desired}. +Initialization is not an atomic operation\iref{intro.multithread}. +\begin{note} +It is possible to have an access to +an atomic object \tcode{A} race with its construction, +for example, +by communicating the address of the just-constructed object \tcode{A} +to another thread via \tcode{memory_order::relaxed} operations +on a suitable atomic pointer variable, and +then immediately accessing \tcode{A} in the receiving thread. +This results in undefined behavior. +\end{note} +\end{itemdescr} + +\indexlibrarymember{store}{atomic>}% +\begin{itemdecl} +void store(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is neither +\tcode{memory_order::consume}, +\tcode{memory_order::acquire}, nor +\tcode{memory_order::acq_rel}. + +\pnum +\effects +Atomically replaces the value pointed to by \keyword{this} with +the value of \tcode{desired} as if by \tcode{p.swap(desired)}. +Memory is affected according to the value of \tcode{order}. +\end{itemdescr} + +\indexlibrarymember{operator=}{atomic>}% +\begin{itemdecl} +void operator=(shared_ptr desired) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{store(desired)}. +\end{itemdescr} + +\indexlibrarymember{load}{atomic>}% +\begin{itemdecl} +shared_ptr load(memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is neither +\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Memory is affected according to the value of \tcode{order}. + +\pnum +\returns +Atomically returns \tcode{p}. +\end{itemdescr} + +\indexlibrarymember{operator shared_ptr}{atomic>}% +\begin{itemdecl} +operator shared_ptr() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return load();} +\end{itemdescr} + +\indexlibrarymember{exchange}{atomic>}% +\begin{itemdecl} +shared_ptr exchange(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Atomically replaces \tcode{p} with \tcode{desired} +as if by \tcode{p.swap(desired)}. +Memory is affected according to the value of \tcode{order}. +This is an atomic read-modify-write operation\iref{intro.races}. + +\pnum +\returns +Atomically returns the value of \tcode{p} immediately before the effects. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_weak}{atomic>}% +\indexlibrarymember{compare_exchange_strong}{atomic>}% +\begin{itemdecl} +bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, + memory_order success, memory_order failure) noexcept; +bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, + memory_order success, memory_order failure) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{failure} is neither +\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +If \tcode{p} is equivalent to \tcode{expected}, +assigns \tcode{desired} to \tcode{p} and +has synchronization semantics corresponding to the value of \tcode{success}, +otherwise assigns \tcode{p} to \tcode{expected} and +has synchronization semantics corresponding to the value of \tcode{failure}. + +\pnum +\returns +\tcode{true} if \tcode{p} was equivalent to \tcode{expected}, +\tcode{false} otherwise. + +\pnum +\remarks +Two \tcode{shared_ptr} objects are equivalent if +they store the same pointer value and +either share ownership or are both empty. +The weak form may fail spuriously. See \ref{atomics.types.operations}. + +\pnum +If the operation returns \tcode{true}, +\tcode{expected} is not accessed after the atomic update and +the operation is an atomic read-modify-write operation\iref{intro.multithread} +on the memory pointed to by \keyword{this}. +Otherwise, the operation is an atomic load operation on that memory, and +\tcode{expected} is updated with the existing value +read from the atomic object in the attempted atomic update. +The \tcode{use_count} update corresponding to the write to \tcode{expected} +is part of the atomic operation. +The write to \tcode{expected} itself +is not required to be part of the atomic operation. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_weak}{atomic>}% +\begin{itemdecl} +bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return compare_exchange_weak(expected, desired, order, fail_order); +\end{codeblock} +where \tcode{fail_order} is the same as \tcode{order} +except that a value of \tcode{memory_order::acq_rel} +shall be replaced by the value \tcode{memory_order::acquire} and +a value of \tcode{memory_order::release} +shall be replaced by the value \tcode{memory_order::relaxed}. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_strong}{atomic>}% +\begin{itemdecl} +bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return compare_exchange_strong(expected, desired, order, fail_order); +\end{codeblock} +where \tcode{fail_order} is the same as \tcode{order} +except that a value of \tcode{memory_order::acq_rel} +shall be replaced by the value \tcode{memory_order::acquire} and +a value of \tcode{memory_order::release} +shall be replaced by the value \tcode{memory_order::relaxed}. +\end{itemdescr} + +\indexlibrarymember{wait}{atomic>}% +\begin{itemdecl} +void wait(shared_ptr old, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is +neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Repeatedly performs the following steps, in order: +\begin{itemize} +\item + Evaluates \tcode{load(order)} and compares it to \tcode{old}. +\item + If the two are not equivalent, returns. +\item + Blocks until it + is unblocked by an atomic notifying operation or is unblocked spuriously. +\end{itemize} + +\pnum +\remarks +Two \tcode{shared_ptr} objects are equivalent +if they store the same pointer and either share ownership or are both empty. +This function is an atomic waiting operation\iref{atomics.wait}. +\end{itemdescr} + +\indexlibrarymember{notify_one}{atomic>}% +\begin{itemdecl} +void notify_one() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of at least one atomic waiting operation +that is eligible to be unblocked\iref{atomics.wait} by this call, +if any such atomic waiting operations exist. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\indexlibrarymember{notify_all}{atomic>}% +\begin{itemdecl} +void notify_all() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of all atomic waiting operations +that are eligible to be unblocked\iref{atomics.wait} by this call. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\rSec4[util.smartptr.atomic.weak]{Partial specialization for \tcode{weak_ptr}} + +\indexlibraryglobal{atomic>}% +\begin{codeblock} +namespace std { + template struct atomic> { + using value_type = weak_ptr; + + static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic} type's operations are always lock free}@; + bool is_lock_free() const noexcept; + + constexpr atomic() noexcept; + atomic(weak_ptr desired) noexcept; + atomic(const atomic&) = delete; + void operator=(const atomic&) = delete; + + weak_ptr load(memory_order order = memory_order::seq_cst) const noexcept; + operator weak_ptr() const noexcept; + void store(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; + void operator=(weak_ptr desired) noexcept; + + weak_ptr exchange(weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, + memory_order success, memory_order failure) noexcept; + bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, + memory_order success, memory_order failure) noexcept; + bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + + void wait(weak_ptr old, memory_order order = memory_order::seq_cst) const noexcept; + void notify_one() noexcept; + void notify_all() noexcept; + + private: + weak_ptr p; // \expos + }; +} +\end{codeblock} + +\indexlibraryctor{atomic>}% +\begin{itemdecl} +constexpr atomic() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{p\{\}}. +\end{itemdescr} + +\indexlibraryctor{atomic>}% +\begin{itemdecl} +atomic(weak_ptr desired) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes the object with the value \tcode{desired}. +Initialization is not an atomic operation\iref{intro.multithread}. +\begin{note} +It is possible to have an access to +an atomic object \tcode{A} race with its construction, +for example, +by communicating the address of the just-constructed object \tcode{A} +to another thread via \tcode{memory_order::relaxed} operations +on a suitable atomic pointer variable, and +then immediately accessing \tcode{A} in the receiving thread. +This results in undefined behavior. +\end{note} +\end{itemdescr} + +\indexlibrarymember{store}{atomic>}% +\begin{itemdecl} +void store(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is neither +\tcode{memory_order::consume}, +\tcode{memory_order::acquire}, nor +\tcode{memory_order::acq_rel}. + +\pnum +\effects +Atomically replaces the value pointed to by \keyword{this} with +the value of \tcode{desired} as if by \tcode{p.swap(desired)}. +Memory is affected according to the value of \tcode{order}. +\end{itemdescr} + +\indexlibrarymember{operator=}{atomic>}% +\begin{itemdecl} +void operator=(weak_ptr desired) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{store(desired)}. +\end{itemdescr} + +\indexlibrarymember{load}{atomic>}% +\begin{itemdecl} +weak_ptr load(memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is neither +\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Memory is affected according to the value of \tcode{order}. + +\pnum +\returns +Atomically returns \tcode{p}. +\end{itemdescr} + +\indexlibrarymember{operator weak_ptr}{atomic>}% +\begin{itemdecl} +operator weak_ptr() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return load();} +\end{itemdescr} + +\indexlibrarymember{exchange}{atomic>}% +\begin{itemdecl} +weak_ptr exchange(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Atomically replaces \tcode{p} with \tcode{desired} +as if by \tcode{p.swap(desired)}. +Memory is affected according to the value of \tcode{order}. +This is an atomic read-modify-write operation\iref{intro.races}. + +\pnum +\returns +Atomically returns the value of \tcode{p} immediately before the effects. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_weak}{atomic>}% +\begin{itemdecl} +bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, + memory_order success, memory_order failure) noexcept; +bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, + memory_order success, memory_order failure) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{failure} is neither +\tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +If \tcode{p} is equivalent to \tcode{expected}, +assigns \tcode{desired} to \tcode{p} and +has synchronization semantics corresponding to the value of \tcode{success}, +otherwise assigns \tcode{p} to \tcode{expected} and +has synchronization semantics corresponding to the value of \tcode{failure}. + +\pnum +\returns +\tcode{true} if \tcode{p} was equivalent to \tcode{expected}, +\tcode{false} otherwise. + +\pnum +\remarks +Two \tcode{weak_ptr} objects are equivalent if +they store the same pointer value and +either share ownership or are both empty. +The weak form may fail spuriously. See \ref{atomics.types.operations}. + +\pnum +If the operation returns \tcode{true}, +\tcode{expected} is not accessed after the atomic update and +the operation is an atomic read-modify-write operation\iref{intro.multithread} +on the memory pointed to by \keyword{this}. +Otherwise, the operation is an atomic load operation on that memory, and +\tcode{expected} is updated with the existing value +read from the atomic object in the attempted atomic update. +The \tcode{use_count} update corresponding to the write to \tcode{expected} +is part of the atomic operation. +The write to \tcode{expected} itself +is not required to be part of the atomic operation. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_weak}{atomic>}% +\begin{itemdecl} +bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return compare_exchange_weak(expected, desired, order, fail_order); +\end{codeblock} +where \tcode{fail_order} is the same as \tcode{order} +except that a value of \tcode{memory_order::acq_rel} +shall be replaced by the value \tcode{memory_order::acquire} and +a value of \tcode{memory_order::release} +shall be replaced by the value \tcode{memory_order::relaxed}. +\end{itemdescr} + +\indexlibrarymember{compare_exchange_strong}{atomic>}% +\begin{itemdecl} +bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return compare_exchange_strong(expected, desired, order, fail_order); +\end{codeblock} +where \tcode{fail_order} is the same as \tcode{order} +except that a value of \tcode{memory_order::acq_rel} +shall be replaced by the value \tcode{memory_order::acquire} and +a value of \tcode{memory_order::release} +shall be replaced by the value \tcode{memory_order::relaxed}. +\end{itemdescr} + +\indexlibrarymember{wait}{atomic>}% +\begin{itemdecl} +void wait(weak_ptr old, memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is +neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Repeatedly performs the following steps, in order: +\begin{itemize} +\item + Evaluates \tcode{load(order)} and compares it to \tcode{old}. +\item + If the two are not equivalent, returns. +\item + Blocks until it + is unblocked by an atomic notifying operation or is unblocked spuriously. +\end{itemize} + +\pnum +\remarks +Two \tcode{weak_ptr} objects are equivalent +if they store the same pointer and either share ownership or are both empty. +This function is an atomic waiting operation\iref{atomics.wait}. +\end{itemdescr} + + +\indexlibrarymember{notify_one}{atomic>}% +\begin{itemdecl} +void notify_one() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of at least one atomic waiting operation +that is eligible to be unblocked\iref{atomics.wait} by this call, +if any such atomic waiting operations exist. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\indexlibrarymember{notify_all}{atomic>}% +\begin{itemdecl} +void notify_all() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of all atomic waiting operations +that are eligible to be unblocked\iref{atomics.wait} by this call. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} +\indextext{atomic!smart pointers|)} + +\rSec2[atomics.nonmembers]{Non-member functions} + +\pnum +A non-member function template whose name matches the pattern +\tcode{atomic_\placeholder{f}} or the pattern \tcode{atomic_\placeholder{f}_explicit} +invokes the member function \tcode{\placeholder{f}}, with the value of the +first parameter as the object expression and the values of the remaining parameters +(if any) as the arguments of the member function call, in order. An argument +for a parameter of type \tcode{atomic::value_type*} is dereferenced when +passed to the member function call. +If no such member function exists, the program is ill-formed. + +\pnum +\begin{note} +The non-member functions enable programmers to write code that can be +compiled as either C or \Cpp{}, for example in a shared header file. +\end{note} + +\rSec2[atomics.flag]{Flag type and operations} + +\begin{codeblock} +namespace std { + struct atomic_flag { + constexpr atomic_flag() noexcept; + atomic_flag(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) volatile = delete; + + bool test(memory_order = memory_order::seq_cst) const volatile noexcept; + bool test(memory_order = memory_order::seq_cst) const noexcept; + bool test_and_set(memory_order = memory_order::seq_cst) volatile noexcept; + bool test_and_set(memory_order = memory_order::seq_cst) noexcept; + void clear(memory_order = memory_order::seq_cst) volatile noexcept; + void clear(memory_order = memory_order::seq_cst) noexcept; + + void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept; + void wait(bool, memory_order = memory_order::seq_cst) const noexcept; + void notify_one() volatile noexcept; + void notify_one() noexcept; + void notify_all() volatile noexcept; + void notify_all() noexcept; + }; +} +\end{codeblock} + +\pnum +The \tcode{atomic_flag} type provides the classic test-and-set functionality. It has two states, set and clear. + +\pnum +Operations on an object of type \tcode{atomic_flag} shall be lock-free. +The operations should also be address-free. + +\pnum +The \tcode{atomic_flag} type is a standard-layout struct. +It has a trivial destructor. + +\indexlibraryctor{atomic_flag}% +\begin{itemdecl} +constexpr atomic_flag::atomic_flag() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{*this} to the clear state. +\end{itemdescr} + +\indexlibraryglobal{atomic_flag_test}% +\indexlibraryglobal{atomic_flag_test_explicit}% +\indexlibrarymember{test}{atomic_flag}% +\begin{itemdecl} +bool atomic_flag_test(const volatile atomic_flag* object) noexcept; +bool atomic_flag_test(const atomic_flag* object) noexcept; +bool atomic_flag_test_explicit(const volatile atomic_flag* object, + memory_order order) noexcept; +bool atomic_flag_test_explicit(const atomic_flag* object, + memory_order order) noexcept; +bool atomic_flag::test(memory_order order = memory_order::seq_cst) const volatile noexcept; +bool atomic_flag::test(memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +For \tcode{atomic_flag_test}, let \tcode{order} be \tcode{memory_order::seq_cst}. + +\pnum +\expects +\tcode{order} is +neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Memory is affected according to the value of \tcode{order}. + +\pnum +\returns +Atomically returns the value pointed to by \tcode{object} or \keyword{this}. +\end{itemdescr} + +\indexlibraryglobal{atomic_flag_test_and_set}% +\indexlibraryglobal{atomic_flag_test_and_set_explicit}% +\indexlibrarymember{test_and_set}{atomic_flag}% +\begin{itemdecl} +bool atomic_flag_test_and_set(volatile atomic_flag* object) noexcept; +bool atomic_flag_test_and_set(atomic_flag* object) noexcept; +bool atomic_flag_test_and_set_explicit(volatile atomic_flag* object, memory_order order) noexcept; +bool atomic_flag_test_and_set_explicit(atomic_flag* object, memory_order order) noexcept; +bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) volatile noexcept; +bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Atomically sets the value pointed to by \tcode{object} or by \keyword{this} to \tcode{true}. Memory is affected according to the value of +\tcode{order}. These operations are atomic read-modify-write operations\iref{intro.multithread}. + +\pnum +\returns +Atomically, the value of the object immediately before the effects. +\end{itemdescr} + +\indexlibraryglobal{atomic_flag_clear}% +\indexlibraryglobal{atomic_flag_clear_explicit}% +\indexlibrarymember{clear}{atomic_flag}% +\begin{itemdecl} +void atomic_flag_clear(volatile atomic_flag* object) noexcept; +void atomic_flag_clear(atomic_flag* object) noexcept; +void atomic_flag_clear_explicit(volatile atomic_flag* object, memory_order order) noexcept; +void atomic_flag_clear_explicit(atomic_flag* object, memory_order order) noexcept; +void atomic_flag::clear(memory_order order = memory_order::seq_cst) volatile noexcept; +void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The \tcode{order} argument is neither \tcode{memory_order::consume}, +\tcode{memory_order::acquire}, nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Atomically sets the value pointed to by \tcode{object} or by \keyword{this} to +\tcode{false}. Memory is affected according to the value of \tcode{order}. +\end{itemdescr} + +\indexlibraryglobal{atomic_flag_wait}% +\indexlibraryglobal{atomic_flag_wait_explicit}% +\indexlibrarymember{wait}{atomic_flag}% +\begin{itemdecl} +void atomic_flag_wait(const volatile atomic_flag* object, bool old) noexcept; +void atomic_flag_wait(const atomic_flag* object, bool old) noexcept; +void atomic_flag_wait_explicit(const volatile atomic_flag* object, + bool old, memory_order order) noexcept; +void atomic_flag_wait_explicit(const atomic_flag* object, + bool old, memory_order order) noexcept; +void atomic_flag::wait(bool old, memory_order order = + memory_order::seq_cst) const volatile noexcept; +void atomic_flag::wait(bool old, memory_order order = + memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +For \tcode{atomic_flag_wait}, +let \tcode{order} be \tcode{memory_order::seq_cst}. +Let \tcode{flag} be \tcode{object} for the non-member functions and +\keyword{this} for the member functions. + +\pnum +\expects +\tcode{order} is +neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. + +\pnum +\effects +Repeatedly performs the following steps, in order: +\begin{itemize} +\item + Evaluates \tcode{flag->test(order) != old}. +\item + If the result of that evaluation is \tcode{true}, returns. +\item + Blocks until it + is unblocked by an atomic notifying operation or is unblocked spuriously. +\end{itemize} + +\pnum +\remarks +This function is an atomic waiting operation\iref{atomics.wait}. +\end{itemdescr} + +\begin{itemdecl} +void atomic_flag_notify_one(volatile atomic_flag* object) noexcept; +void atomic_flag_notify_one(atomic_flag* object) noexcept; +void atomic_flag::notify_one() volatile noexcept; +void atomic_flag::notify_one() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of at least one atomic waiting operation +that is eligible to be unblocked\iref{atomics.wait} by this call, +if any such atomic waiting operations exist. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\begin{itemdecl} +void atomic_flag_notify_all(volatile atomic_flag* object) noexcept; +void atomic_flag_notify_all(atomic_flag* object) noexcept; +void atomic_flag::notify_all() volatile noexcept; +void atomic_flag::notify_all() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Unblocks the execution of all atomic waiting operations +that are eligible to be unblocked\iref{atomics.wait} by this call. + +\pnum +\remarks +This function is an atomic notifying operation\iref{atomics.wait}. +\end{itemdescr} + +\rSec2[atomics.fences]{Fences} + +\pnum +This subclause introduces synchronization primitives called \term{fences}. Fences can have +acquire semantics, release semantics, or both. A fence with acquire semantics is called +an \term{acquire fence}. A fence with release semantics is called a \term{release +fence}. + +\pnum +A release fence $A$ synchronizes with an acquire fence $B$ if there exist +atomic operations $X$ and $Y$, both operating on some atomic object +$M$, such that $A$ is sequenced before $X$, $X$ modifies +$M$, $Y$ is sequenced before $B$, and $Y$ reads the value +written by $X$ or a value written by any side effect in the hypothetical release +sequence $X$ would head if it were a release operation. + +\pnum +A release fence $A$ synchronizes with an atomic operation $B$ that +performs an acquire operation on an atomic object $M$ if there exists an atomic +operation $X$ such that $A$ is sequenced before $X$, $X$ +modifies $M$, and $B$ reads the value written by $X$ or a value +written by any side effect in the hypothetical release sequence $X$ would head if +it were a release operation. + +\pnum +An atomic operation $A$ that is a release operation on an atomic object +$M$ synchronizes with an acquire fence $B$ if there exists some atomic +operation $X$ on $M$ such that $X$ is sequenced before $B$ +and reads the value written by $A$ or a value written by any side effect in the +release sequence headed by $A$. + +\indexlibraryglobal{atomic_thread_fence}% +\begin{itemdecl} +extern "C" void atomic_thread_fence(memory_order order) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Depending on the value of \tcode{order}, this operation: +\begin{itemize} +\item has no effects, if \tcode{order == memory_order::relaxed}; + +\item is an acquire fence, if \tcode{order == memory_order::acquire} or \tcode{order == memory_order::consume}; + +\item is a release fence, if \tcode{order == memory_order::release}; + +\item is both an acquire fence and a release fence, if \tcode{order == memory_order::acq_rel}; + +\item is a sequentially consistent acquire and release fence, if \tcode{order == memory_order::seq_cst}. +\end{itemize} +\end{itemdescr} + +\indexlibraryglobal{atomic_signal_fence}% +\begin{itemdecl} +extern "C" void atomic_signal_fence(memory_order order) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{atomic_thread_fence(order)}, except that +the resulting ordering constraints are established only between a thread and a +signal handler executed in the same thread. + +\pnum +\begin{note} +\tcode{atomic_signal_fence} can be used to specify the order in which actions +performed by the thread become visible to the signal handler. +Compiler optimizations and reorderings of loads and stores are inhibited in +the same way as with \tcode{atomic_thread_fence}, but the hardware fence instructions +that \tcode{atomic_thread_fence} would have inserted are not emitted. +\end{note} +\end{itemdescr} + +\rSec2[stdatomic.h.syn]{C compatibility} + +The header \libheaderdef{stdatomic.h} provides the following definitions: + +\begin{codeblock} +template + using @\exposid{std-atomic}@ = std::atomic; // \expos + +#define _Atomic(T) @\exposid{std-atomic}@ + +#define ATOMIC_BOOL_LOCK_FREE @\seebelow@ +#define ATOMIC_CHAR_LOCK_FREE @\seebelow@ +#define ATOMIC_CHAR16_T_LOCK_FREE @\seebelow@ +#define ATOMIC_CHAR32_T_LOCK_FREE @\seebelow@ +#define ATOMIC_WCHAR_T_LOCK_FREE @\seebelow@ +#define ATOMIC_SHORT_LOCK_FREE @\seebelow@ +#define ATOMIC_INT_LOCK_FREE @\seebelow@ +#define ATOMIC_LONG_LOCK_FREE @\seebelow@ +#define ATOMIC_LLONG_LOCK_FREE @\seebelow@ +#define ATOMIC_POINTER_LOCK_FREE @\seebelow@ + +using std::@\libglobal{memory_order}@; // \seebelow +using std::@\libglobal{memory_order_relaxed}@; // \seebelow +using std::@\libglobal{memory_order_consume}@; // \seebelow +using std::@\libglobal{memory_order_acquire}@; // \seebelow +using std::@\libglobal{memory_order_release}@; // \seebelow +using std::@\libglobal{memory_order_acq_rel}@; // \seebelow +using std::@\libglobal{memory_order_seq_cst}@; // \seebelow + +using std::@\libglobal{atomic_flag}@; // \seebelow + +using std::@\libglobal{atomic_bool}@; // \seebelow +using std::@\libglobal{atomic_char}@; // \seebelow +using std::@\libglobal{atomic_schar}@; // \seebelow +using std::@\libglobal{atomic_uchar}@; // \seebelow +using std::@\libglobal{atomic_short}@; // \seebelow +using std::@\libglobal{atomic_ushort}@; // \seebelow +using std::@\libglobal{atomic_int}@; // \seebelow +using std::@\libglobal{atomic_uint}@; // \seebelow +using std::@\libglobal{atomic_long}@; // \seebelow +using std::@\libglobal{atomic_ulong}@; // \seebelow +using std::@\libglobal{atomic_llong}@; // \seebelow +using std::@\libglobal{atomic_ullong}@; // \seebelow +using std::@\libglobal{atomic_char8_t}@; // \seebelow +using std::@\libglobal{atomic_char16_t}@; // \seebelow +using std::@\libglobal{atomic_char32_t}@; // \seebelow +using std::@\libglobal{atomic_wchar_t}@; // \seebelow +using std::@\libglobal{atomic_int8_t}@; // \seebelow +using std::@\libglobal{atomic_uint8_t}@; // \seebelow +using std::@\libglobal{atomic_int16_t}@; // \seebelow +using std::@\libglobal{atomic_uint16_t}@; // \seebelow +using std::@\libglobal{atomic_int32_t}@; // \seebelow +using std::@\libglobal{atomic_uint32_t}@; // \seebelow +using std::@\libglobal{atomic_int64_t}@; // \seebelow +using std::@\libglobal{atomic_uint64_t}@; // \seebelow +using std::@\libglobal{atomic_int_least8_t}@; // \seebelow +using std::@\libglobal{atomic_uint_least8_t}@; // \seebelow +using std::@\libglobal{atomic_int_least16_t}@; // \seebelow +using std::@\libglobal{atomic_uint_least16_t}@; // \seebelow +using std::@\libglobal{atomic_int_least32_t}@; // \seebelow +using std::@\libglobal{atomic_uint_least32_t}@; // \seebelow +using std::@\libglobal{atomic_int_least64_t}@; // \seebelow +using std::@\libglobal{atomic_uint_least64_t}@; // \seebelow +using std::@\libglobal{atomic_int_fast8_t}@; // \seebelow +using std::@\libglobal{atomic_uint_fast8_t}@; // \seebelow +using std::@\libglobal{atomic_int_fast16_t}@; // \seebelow +using std::@\libglobal{atomic_uint_fast16_t}@; // \seebelow +using std::@\libglobal{atomic_int_fast32_t}@; // \seebelow +using std::@\libglobal{atomic_uint_fast32_t}@; // \seebelow +using std::@\libglobal{atomic_int_fast64_t}@; // \seebelow +using std::@\libglobal{atomic_uint_fast64_t}@; // \seebelow +using std::@\libglobal{atomic_intptr_t}@; // \seebelow +using std::@\libglobal{atomic_uintptr_t}@; // \seebelow +using std::@\libglobal{atomic_size_t}@; // \seebelow +using std::@\libglobal{atomic_ptrdiff_t}@; // \seebelow +using std::@\libglobal{atomic_intmax_t}@; // \seebelow +using std::@\libglobal{atomic_uintmax_t}@; // \seebelow + +using std::@\libglobal{atomic_is_lock_free}@; // \seebelow +using std::@\libglobal{atomic_load}@; // \seebelow +using std::@\libglobal{atomic_load_explicit}@; // \seebelow +using std::@\libglobal{atomic_store}@; // \seebelow +using std::@\libglobal{atomic_store_explicit}@; // \seebelow +using std::@\libglobal{atomic_exchange}@; // \seebelow +using std::@\libglobal{atomic_exchange_explicit}@; // \seebelow +using std::@\libglobal{atomic_compare_exchange_strong}@; // \seebelow +using std::@\libglobal{atomic_compare_exchange_strong_explicit}@; // \seebelow +using std::@\libglobal{atomic_compare_exchange_weak}@; // \seebelow +using std::@\libglobal{atomic_compare_exchange_weak_explicit}@; // \seebelow +using std::@\libglobal{atomic_fetch_add}@; // \seebelow +using std::@\libglobal{atomic_fetch_add_explicit}@; // \seebelow +using std::@\libglobal{atomic_fetch_sub}@; // \seebelow +using std::@\libglobal{atomic_fetch_sub_explicit}@; // \seebelow +using std::@\libglobal{atomic_fetch_or}@; // \seebelow +using std::@\libglobal{atomic_fetch_or_explicit}@; // \seebelow +using std::@\libglobal{atomic_fetch_and}@; // \seebelow +using std::@\libglobal{atomic_fetch_and_explicit}@; // \seebelow +using std::@\libglobal{atomic_flag_test_and_set}@; // \seebelow +using std::@\libglobal{atomic_flag_test_and_set_explicit}@; // \seebelow +using std::@\libglobal{atomic_flag_clear}@; // \seebelow +using std::@\libglobal{atomic_flag_clear_explicit}@; // \seebelow + +using std::@\libglobal{atomic_thread_fence}@; // \seebelow +using std::@\libglobal{atomic_signal_fence}@; // \seebelow +\end{codeblock} + +\pnum +Each \grammarterm{using-declaration} for some name $A$ in the synopsis above +makes available the same entity as \tcode{std::$A$} +declared in \libheaderrefx{atomic}{atomics.syn}. +Each macro listed above other than \tcode{_Atomic(T)} +is defined as in \libheader{atomic}. +It is unspecified whether \libheader{stdatomic.h} makes available +any declarations in namespace \tcode{std}. + +\pnum +Each of the \grammarterm{using-declaration}s for +\tcode{int$N$_t}, \tcode{uint$N$_t}, \tcode{intptr_t}, and \tcode{uintptr_t} +listed above is defined if and only if the implementation defines +the corresponding \grammarterm{typedef-name} in \ref{atomics.syn}. + +\pnum +Neither the \tcode{_Atomic} macro, +nor any of the non-macro global namespace declarations, +are provided by any \Cpp{} standard library header +other than \libheader{stdatomic.h}. + +\pnum +\recommended +Implementations should ensure +that C and \Cpp{} representations of atomic objects are compatible, +so that the same object can be accessed as both an \tcode{_Atomic(T)} +from C code and an \tcode{atomic} from \Cpp{} code. +The representations should be the same, and +the mechanisms used to ensure atomicity and memory ordering +should be compatible. + \rSec1[thread.mutex]{Mutual exclusion} \rSec2[thread.mutex.general]{General} diff --git a/tools/check-source.sh b/tools/check-source.sh index 8bd157fe6a..fb1c2518cc 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -6,7 +6,7 @@ failed=0 # Ignore files where rules may be violated within macro definitions. texfiles=$(ls *.tex | grep -v macros.tex | grep -v layout.tex | grep -v tables.tex) -texlibdesc="support.tex concepts.tex diagnostics.tex memory.tex meta.tex utilities.tex strings.tex containers.tex iterators.tex ranges.tex algorithms.tex numerics.tex time.tex locales.tex iostreams.tex regex.tex atomics.tex threads.tex" +texlibdesc="support.tex concepts.tex diagnostics.tex memory.tex meta.tex utilities.tex strings.tex containers.tex iterators.tex ranges.tex algorithms.tex numerics.tex time.tex locales.tex iostreams.tex regex.tex threads.tex" texlib="lib-intro.tex $texlibdesc" # Filter that reformats the error message as a "workflow command", From 9268bb772f53c4ea334908c27ff0131edcdcfd9a Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 22 Feb 2022 22:37:15 +0100 Subject: [PATCH 163/182] [std] Add space between cv-qualifier and ref-qualifier --- source/basic.tex | 2 +- source/ranges.tex | 30 +++++++------- source/utilities.tex | 96 ++++++++++++++++++++++---------------------- 3 files changed, 64 insertions(+), 64 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index fcc799b661..ab94c86677 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -965,7 +965,7 @@ void h(this X&, int); void h(int) &&; // OK, another overload void j(this const X&); - void j() const&; // error: redeclaration + void j() const &; // error: redeclaration void k(); void k(this X&); // error: redeclaration }; diff --git a/source/ranges.tex b/source/ranges.tex index 201cbec456..ecd96d0e3a 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -3761,9 +3761,9 @@ owning_view& operator=(owning_view&&) = default; constexpr R& base() & noexcept { return @\exposid{r_}@; } - constexpr const R& base() const& noexcept { return @\exposid{r_}@; } + constexpr const R& base() const & noexcept { return @\exposid{r_}@; } constexpr R&& base() && noexcept { return std::move(@\exposid{r_}@); } - constexpr const R&& base() const&& noexcept { return std::move(@\exposid{r_}@); } + constexpr const R&& base() const && noexcept { return std::move(@\exposid{r_}@); } constexpr iterator_t begin() { return ranges::begin(@\exposid{r_}@); } constexpr sentinel_t end() { return ranges::end(@\exposid{r_}@); } @@ -3851,7 +3851,7 @@ filter_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; constexpr filter_view(V base, Pred pred); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr const Pred& pred() const; @@ -4278,7 +4278,7 @@ transform_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; constexpr transform_view(V base, F fun); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr @\exposid{iterator}@ begin(); @@ -5002,7 +5002,7 @@ take_view() requires @\libconcept{default_initializable}@ = default; constexpr take_view(V base, range_difference_t count); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() requires (!@\exposconcept{simple-view}@) { @@ -5217,7 +5217,7 @@ take_while_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; constexpr take_while_view(V base, Pred pred); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr const Pred& pred() const; @@ -5426,7 +5426,7 @@ drop_view() requires @\libconcept{default_initializable}@ = default; constexpr drop_view(V base, range_difference_t count); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() @@ -5551,7 +5551,7 @@ drop_while_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; constexpr drop_while_view(V base, Pred pred); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr const Pred& pred() const; @@ -5677,7 +5677,7 @@ join_view() requires @\libconcept{default_initializable}@ = default; constexpr explicit join_view(V base); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() { @@ -6183,7 +6183,7 @@ @\libconcept{constructible_from}@>> constexpr join_with_view(R&& r, range_value_t<@\exposid{InnerRng}@> e); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() { @@ -6767,7 +6767,7 @@ @\libconcept{constructible_from}@>> constexpr lazy_split_view(R&& r, range_value_t e); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() { @@ -7310,7 +7310,7 @@ @\libconcept{constructible_from}@>> constexpr split_view(R&& r, range_value_t e); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr @\exposid{iterator}@ begin(); @@ -7660,7 +7660,7 @@ constexpr explicit common_view(V r); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() { @@ -7781,7 +7781,7 @@ constexpr explicit reverse_view(V r); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr reverse_iterator> begin(); @@ -7953,7 +7953,7 @@ elements_view() requires @\libconcept{default_initializable}@ = default; constexpr explicit elements_view(V base); - constexpr V base() const& requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } constexpr V base() && { return std::move(@\exposid{base_}@); } constexpr auto begin() requires (!@\exposconcept{simple-view}@) diff --git a/source/utilities.tex b/source/utilities.tex index f2c3b14f78..0638d02eb0 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -2862,30 +2862,30 @@ // \ref{optional.observe}, observers constexpr const T* operator->() const noexcept; constexpr T* operator->() noexcept; - constexpr const T& operator*() const& noexcept; + constexpr const T& operator*() const & noexcept; constexpr T& operator*() & noexcept; constexpr T&& operator*() && noexcept; - constexpr const T&& operator*() const&& noexcept; + constexpr const T&& operator*() const && noexcept; constexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept; - constexpr const T& value() const&; + constexpr const T& value() const &; constexpr T& value() &; constexpr T&& value() &&; - constexpr const T&& value() const&&; - template constexpr T value_or(U&&) const&; + constexpr const T&& value() const &&; + template constexpr T value_or(U&&) const &; template constexpr T value_or(U&&) &&; // \ref{optional.monadic}, monadic operations template constexpr auto and_then(F&& f) &; template constexpr auto and_then(F&& f) &&; - template constexpr auto and_then(F&& f) const&; - template constexpr auto and_then(F&& f) const&&; + template constexpr auto and_then(F&& f) const &; + template constexpr auto and_then(F&& f) const &&; template constexpr auto transform(F&& f) &; template constexpr auto transform(F&& f) &&; - template constexpr auto transform(F&& f) const&; - template constexpr auto transform(F&& f) const&&; + template constexpr auto transform(F&& f) const &; + template constexpr auto transform(F&& f) const &&; template constexpr optional or_else(F&& f) &&; - template constexpr optional or_else(F&& f) const&; + template constexpr optional or_else(F&& f) const &; // \ref{optional.mod}, modifiers constexpr void reset() noexcept; @@ -3612,7 +3612,7 @@ \indexlibrarymember{operator*}{optional}% \begin{itemdecl} -constexpr const T& operator*() const& noexcept; +constexpr const T& operator*() const & noexcept; constexpr T& operator*() & noexcept; \end{itemdecl} @@ -3633,7 +3633,7 @@ \indexlibrarymember{operator*}{optional}% \begin{itemdecl} constexpr T&& operator*() && noexcept; -constexpr const T&& operator*() const&& noexcept; +constexpr const T&& operator*() const && noexcept; \end{itemdecl} \begin{itemdescr} @@ -3678,7 +3678,7 @@ \indexlibrarymember{value}{optional}% \begin{itemdecl} -constexpr const T& value() const&; +constexpr const T& value() const &; constexpr T& value() &; \end{itemdecl} @@ -3694,7 +3694,7 @@ \indexlibrarymember{value}{optional}% \begin{itemdecl} constexpr T&& value() &&; -constexpr const T&& value() const&&; +constexpr const T&& value() const &&; \end{itemdecl} \begin{itemdescr} @@ -3709,7 +3709,7 @@ \indexlibrarymember{value_or}{optional}% \begin{itemdecl} -template constexpr T value_or(U&& v) const&; +template constexpr T value_or(U&& v) const &; \end{itemdecl} \begin{itemdescr} @@ -3748,7 +3748,7 @@ \indexlibrarymember{and_then}{optional} \begin{itemdecl} template constexpr auto and_then(F&& f) &; -template constexpr auto and_then(F&& f) const&; +template constexpr auto and_then(F&& f) const &; \end{itemdecl} \begin{itemdescr} @@ -3774,7 +3774,7 @@ \indexlibrarymember{and_then}{optional} \begin{itemdecl} template constexpr auto and_then(F&& f) &&; -template constexpr auto and_then(F&& f) const&&; +template constexpr auto and_then(F&& f) const &&; \end{itemdecl} \begin{itemdescr} @@ -3800,7 +3800,7 @@ \indexlibrarymember{transform}{optional} \begin{itemdecl} template constexpr auto transform(F&& f) &; -template constexpr auto transform(F&& f) const&; +template constexpr auto transform(F&& f) const &; \end{itemdecl} \begin{itemdescr} @@ -3831,7 +3831,7 @@ \indexlibrarymember{transform}{optional} \begin{itemdecl} template constexpr auto transform(F&& f) &&; -template constexpr auto transform(F&& f) const&&; +template constexpr auto transform(F&& f) const &&; \end{itemdecl} \begin{itemdescr} @@ -3862,7 +3862,7 @@ \indexlibrarymember{or_else}{optional} \begin{itemdecl} -template constexpr optional or_else(F&& f) const&; +template constexpr optional or_else(F&& f) const &; \end{itemdecl} \begin{itemdescr} @@ -6550,9 +6550,9 @@ constexpr unexpected& operator=(const unexpected&) = default; constexpr unexpected& operator=(unexpected&&) = default; - constexpr const E& value() const& noexcept; + constexpr const E& value() const & noexcept; constexpr E& value() & noexcept; - constexpr const E&& value() const&& noexcept; + constexpr const E&& value() const && noexcept; constexpr E&& value() && noexcept; constexpr void swap(unexpected& other) noexcept(@\seebelow@); @@ -6653,7 +6653,7 @@ \indexlibrarymember{value}{unexpected}% \begin{itemdecl} -constexpr const E& value() const& noexcept; +constexpr const E& value() const & noexcept; constexpr E& value() & noexcept; \end{itemdecl} @@ -6666,7 +6666,7 @@ \indexlibrarymember{value}{unexpected}% \begin{itemdecl} constexpr E&& value() && noexcept; -constexpr const E&& value() const&& noexcept; +constexpr const E&& value() const && noexcept; \end{itemdecl} \begin{itemdescr} @@ -6737,9 +6737,9 @@ explicit bad_expected_access(E); const char* what() const noexcept override; E& error() & noexcept; - const E& error() const& noexcept; + const E& error() const & noexcept; E&& error() && noexcept; - const E&& error() const&& noexcept; + const E&& error() const && noexcept; private: E @\exposid{val}@; // \expos }; @@ -6765,7 +6765,7 @@ \indexlibrarymember{error}{bad_expected_access}% \begin{itemdecl} -const E& error() const& noexcept; +const E& error() const & noexcept; E& error() & noexcept; \end{itemdecl} @@ -6778,7 +6778,7 @@ \indexlibrarymember{error}{bad_expected_access}% \begin{itemdecl} E&& error() && noexcept; -const E&& error() const&& noexcept; +const E&& error() const && noexcept; \end{itemdecl} \begin{itemdescr} @@ -6894,21 +6894,21 @@ // \ref{expected.object.obs}, observers constexpr const T* operator->() const noexcept; constexpr T* operator->() noexcept; - constexpr const T& operator*() const& noexcept; + constexpr const T& operator*() const & noexcept; constexpr T& operator*() & noexcept; - constexpr const T&& operator*() const&& noexcept; + constexpr const T&& operator*() const && noexcept; constexpr T&& operator*() && noexcept; constexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept; - constexpr const T& value() const&; + constexpr const T& value() const &; constexpr T& value() &; - constexpr const T&& value() const&&; + constexpr const T&& value() const &&; constexpr T&& value() &&; - constexpr const E& error() const&; + constexpr const E& error() const &; constexpr E& error() &; - constexpr const E&& error() const&&; + constexpr const E&& error() const &&; constexpr E&& error() &&; - template constexpr T value_or(U&&) const&; + template constexpr T value_or(U&&) const &; template constexpr T value_or(U&&) &&; // \ref{expected.object.eq}, equality operators @@ -7707,7 +7707,7 @@ \indexlibrarymember{operator*}{expected}% \begin{itemdecl} -constexpr const T& operator*() const& noexcept; +constexpr const T& operator*() const & noexcept; constexpr T& operator*() & noexcept; \end{itemdecl} @@ -7724,7 +7724,7 @@ \indexlibrarymember{operator*}{expected}% \begin{itemdecl} constexpr T&& operator*() && noexcept; -constexpr const T&& operator*() const&& noexcept; +constexpr const T&& operator*() const && noexcept; \end{itemdecl} \begin{itemdescr} @@ -7752,7 +7752,7 @@ \indexlibrarymember{value}{expected}% \begin{itemdecl} -constexpr const T& value() const&; +constexpr const T& value() const &; constexpr T& value() &; \end{itemdecl} @@ -7769,7 +7769,7 @@ \indexlibrarymember{value}{expected}% \begin{itemdecl} constexpr T&& value() &&; -constexpr const T&& value() const&&; +constexpr const T&& value() const &&; \end{itemdecl} \begin{itemdescr} @@ -7785,7 +7785,7 @@ \indexlibrarymember{error}{expected}% \begin{itemdecl} -constexpr const E& error() const& noexcept; +constexpr const E& error() const & noexcept; constexpr E& error() & noexcept; \end{itemdecl} @@ -7802,7 +7802,7 @@ \indexlibrarymember{error}{expected}% \begin{itemdecl} constexpr E&& error() && noexcept; -constexpr const E&& error() const&& noexcept; +constexpr const E&& error() const && noexcept; \end{itemdecl} \begin{itemdescr} @@ -7817,7 +7817,7 @@ \indexlibrarymember{value_or}{expected}% \begin{itemdecl} -template constexpr T value_or(U&& v) const&; +template constexpr T value_or(U&& v) const &; \end{itemdecl} \begin{itemdescr} @@ -7959,11 +7959,11 @@ constexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept; constexpr void operator*() const noexcept; - constexpr void value() const&; + constexpr void value() const &; constexpr void value() &&; - constexpr const E& error() const&; + constexpr const E& error() const &; constexpr E& error() &; - constexpr const E&& error() const&&; + constexpr const E&& error() const &&; constexpr E&& error() &&; // \ref{expected.void.eq}, equality operators @@ -8425,7 +8425,7 @@ \indexlibrarymember{value}{expected}% \begin{itemdecl} -constexpr void value() const&; +constexpr void value() const &; \end{itemdecl} \begin{itemdescr} @@ -8448,7 +8448,7 @@ \indexlibrarymember{error}{expected}% \begin{itemdecl} -constexpr const E& error() const&; +constexpr const E& error() const &; constexpr E& error() &; \end{itemdecl} @@ -8465,7 +8465,7 @@ \indexlibrarymember{error}{expected}% \begin{itemdecl} constexpr E&& error() &&; -constexpr const E&& error() const&&; +constexpr const E&& error() const &&; \end{itemdecl} \begin{itemdescr} From a5f7f11129604e98517dc19349a4ea6ae0b62b29 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Tue, 22 Feb 2022 22:35:04 +0100 Subject: [PATCH 164/182] [check] Enforce space between cv-qualifier and ref-qualifier --- tools/check-source.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/check-source.sh b/tools/check-source.sh index fb1c2518cc..6d53272b64 100755 --- a/tools/check-source.sh +++ b/tools/check-source.sh @@ -120,6 +120,10 @@ for f in $texlib; do done | fail 'No namespace around class definition' || failed=1 +# ref-qualifier on member functions with no space, e.g. "const&" +fgrep -ne ') const&' $texlib | + fail 'no space between cv-qualifier and ref-qualifier' || failed=1 + # \begin{example/note} with non-whitespace in front on the same line. grep -ne '^.*[^ ]\s*\\\(begin\|end\){\(example\|note\)}' $texfiles | fail "non-whitespace before note/example begins" || failed=1 From 8e578085840d3602b26d7c65a08adec5c127aa6f Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Thu, 24 Feb 2022 11:26:39 +0800 Subject: [PATCH 165/182] [expected.syn] Index --- source/utilities.tex | 1 + 1 file changed, 1 insertion(+) diff --git a/source/utilities.tex b/source/utilities.tex index 0638d02eb0..0ea252fc38 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -6493,6 +6493,7 @@ \rSec2[expected.syn]{Header \tcode{} synopsis} +\indexheader{expected}% \indexlibraryglobal{unexpect_t}% \indexlibraryglobal{unexpect}% \begin{codeblock} From 888602381e6c4e5fc886a7e575a95c905998b487 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Thu, 24 Feb 2022 11:35:19 +0800 Subject: [PATCH 166/182] [headers] List --- source/lib-intro.tex | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 6c61e9440b..1a82d464f2 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -1027,9 +1027,10 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ -\tcode{} \\ \columnbreak +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1049,8 +1050,8 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \columnbreak +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1070,8 +1071,8 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \columnbreak +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ From aa2c64589cf2a784e9c551a2a54df59b880613d3 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 24 Feb 2022 15:09:08 +0100 Subject: [PATCH 167/182] [thread] Rename to 'Concurrency support library' Missed update with commit d74c2170a9f4c928519461d7742293af2d141852. --- source/threads.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/threads.tex b/source/threads.tex index 7b59b6c533..6a59070e5a 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -1,5 +1,5 @@ %!TEX root = std.tex -\rSec0[thread]{Thread support library} +\rSec0[thread]{Concurrency support library} \rSec1[thread.general]{General} From 000d4c091a244b3bf81470c6c6a4f2f35c3ec602 Mon Sep 17 00:00:00 2001 From: hewillk <67143766+hewillk@users.noreply.github.com> Date: Fri, 25 Feb 2022 01:14:48 +0800 Subject: [PATCH 168/182] [range.chunk.outer.value] Add missing private specifier --- source/ranges.tex | 1 + 1 file changed, 1 insertion(+) diff --git a/source/ranges.tex b/source/ranges.tex index ecd96d0e3a..de30c50d95 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -11209,6 +11209,7 @@ template<@\libconcept{view}@ V> requires @\libconcept{input_range}@ struct chunk_view::@\exposid{outer-iterator}@::value_type : view_interface { + private: chunk_view* @\exposid{parent_}@; // \expos constexpr explicit value_type(chunk_view& parent); // \expos From e7ffdb1961ef402ee6f404020faaaaf48d126eac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Fri, 25 Feb 2022 13:25:43 +0000 Subject: [PATCH 169/182] [{lower,upper}.bound, string.view.template.general] Linebreaking tweaks --- source/algorithms.tex | 4 ++-- source/strings.tex | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/source/algorithms.tex b/source/algorithms.tex index 4352a1fedd..4c0f369fac 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -6808,7 +6808,7 @@ \pnum \expects The elements \tcode{e} of \range{first}{last} -are partitioned with respect to the expression +are partitioned with respect to the expression\\ \tcode{bool(invoke(comp, invoke(proj, e), value))}. \pnum @@ -6855,7 +6855,7 @@ \pnum \expects The elements \tcode{e} of \range{first}{last} -are partitioned with respect to the expression +are partitioned with respect to the expression\\ \tcode{!bool(invoke(comp, value, invoke(proj, e)))}. \pnum diff --git a/source/strings.tex b/source/strings.tex index 46d10379b4..d163c25419 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -749,7 +749,10 @@ \pnum For a \tcode{basic_string_view str}, any operation that invalidates a pointer -in the range \range{str.data()}{\brk{}str.data() + str.size()} +in the range +\begin{codeblock} +@\range{str.data()}{\brk{}str.data() + str.size()}@ +\end{codeblock} invalidates pointers, iterators, and references returned from \tcode{str}'s member functions. From b9e683e4a39df414acaf325779c7fef7abe7ac6c Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 25 Feb 2022 13:23:28 +0100 Subject: [PATCH 170/182] [macros] Use maths mode for range delimiters (#5164) Ranges are mathematical notation and not valid syntax, so it is more appropriate to typeset them as maths than as code. --- source/macros.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/macros.tex b/source/macros.tex index 08826b05c4..f7107b70bc 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -476,7 +476,7 @@ \newcommand{\defexposconceptnc}[1]{\ecname{#1}\indexconcept{\idxexposconcept{#1}|idxbfpage}\itcorr[-1]} % macro length: 18 %% Ranges -\newcommand{\Range}[4]{\tcode{#1#3,\penalty2000{} #4#2}} +\newcommand{\Range}[4]{\ensuremath{#1}\tcode{#3}\ensuremath{,}\,\penalty2000{}\tcode{#4}\ensuremath{#2}} \newcommand{\crange}[2]{\Range{[}{]}{#1}{#2}} \newcommand{\brange}[2]{\Range{(}{]}{#1}{#2}} \newcommand{\orange}[2]{\Range{(}{)}{#1}{#2}} From 2901f3f6c00060e6c0a368efd28fd50ba07350f1 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Fri, 25 Feb 2022 23:38:49 +0100 Subject: [PATCH 171/182] [diff.cpp20.library] Add subclause, highlighting new headers --- source/compatibility.tex | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/source/compatibility.tex b/source/compatibility.tex index 77cf38c7ec..6070af42ea 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -55,6 +55,22 @@ // now equivalent to \tcode{arr.operator[](1, 2)} or ill-formed \end{codeblock} +\rSec2[diff.cpp20.library]{\ref{library}: library introduction} + +\diffref{headers} +\change +New headers. +\rationale +New functionality. +\effect +The following \Cpp{} headers are new: +\libheaderref{expected}, +\libheaderref{stdatomic.h}, +\libheaderref{spanstream}, and +\libheaderref{stacktrace}. +Valid \CppXX{} code that \tcode{\#include}{s} headers with these names may be +invalid in this revision of \Cpp{}. + \rSec2[diff.cpp20.utilities]{\ref{utilities}: general utilities library} \diffref{format} From b2821c7cfc3e63675e5b00ea2d42af8e9eba1142 Mon Sep 17 00:00:00 2001 From: Eelis Date: Sun, 27 Feb 2022 08:11:26 +0100 Subject: [PATCH 172/182] [range.chunk.inner.iter] Fix index reference (#5325) --- source/ranges.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/ranges.tex b/source/ranges.tex index de30c50d95..101428f561 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -11299,7 +11299,7 @@ friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{inner-iterator}@& x) requires @\libconcept{sized_sentinel_for}@, iterator_t>; friend constexpr difference_type operator-(const @\exposid{inner-iterator}@& x, default_sentinel_t y) - requires @\libconcept{sized_sentinel_fo}@r, iterator_t>; + requires @\libconcept{sized_sentinel_for}@, iterator_t>; }; } \end{codeblock} From 1c88b6bdafb2eb128e7da05815f3b30fa52d3710 Mon Sep 17 00:00:00 2001 From: hewillk <67143766+hewillk@users.noreply.github.com> Date: Sun, 27 Feb 2022 21:23:40 +0800 Subject: [PATCH 173/182] [range.slide.overview] Fix bad quotation marks for string-literal (#5326) --- source/ranges.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/ranges.tex b/source/ranges.tex index 101428f561..9a3f2443ae 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -11923,7 +11923,7 @@ vector v = {1, 2, 3, 4}; for (auto i : v | views::slide(2)) { - cout << '[' << i[0] << ', ' << i[1] << "] "; // prints: [1, 2] [2, 3] [3, 4] + cout << '[' << i[0] << ", " << i[1] << "] "; // prints: [1, 2] [2, 3] [3, 4] } \end{codeblock} \end{example} From 1c162a7b10b392b5b770e339f5f241572c04adae Mon Sep 17 00:00:00 2001 From: hewillk <67143766+hewillk@users.noreply.github.com> Date: Fri, 4 Mar 2022 20:00:33 +0800 Subject: [PATCH 174/182] [range.chunk.outer.value] Fix missing \tcode markup (#5329) --- source/ranges.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/ranges.tex b/source/ranges.tex index 9a3f2443ae..f980dd7eca 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -11241,7 +11241,7 @@ \begin{itemdescr} \pnum \returns -\exposid{inner-iterator}(*\exposid{parent_}). +\tcode{\exposid{inner-iterator}(*\exposid{parent_})}. \end{itemdescr} \begin{itemdecl} From dd346dcbd723ae27d6a2c2a74aad8a17a62ea687 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 6 Mar 2022 00:18:57 +0100 Subject: [PATCH 175/182] [expr.const] Add cross-reference for construct_at --- source/expressions.tex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/expressions.tex b/source/expressions.tex index 30fe24187e..6710c39aeb 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -7457,7 +7457,8 @@ even if the actual evaluation of such a call would otherwise fail the requirements for a core constant expression. Similarly, the evaluation of a call to -\tcode{std::construct_at} or \tcode{std::ranges::construct_at} +\tcode{std::construct_at} or +\tcode{std::ranges::construct_at}\iref{specialized.construct} does not disqualify $E$ from being a core constant expression unless the first argument, of type \tcode{T*}, does not point From 8679960561e6f18ca533915626cdd5ecd349bcf4 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 27 Feb 2022 22:22:30 +0100 Subject: [PATCH 176/182] [allocator.requirements.general] Replace table for descriptive variables --- source/lib-intro.tex | 89 ++++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 1a82d464f2..3ef4fd71ef 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -1840,43 +1840,61 @@ \tcode{match_results}\iref{re} are parameterized in terms of allocators. -\begin{shortlibreqtab2} -{Descriptive variable definitions} -{allocator.req.var} -\topline -\lhdr{Variable} & \rhdr{Definition} \\ \capsep -\tcode{T, U, C} & any \cv-unqualified object type\iref{term.object.type} \\ \rowsep -\tcode{X} & an allocator class for type \tcode{T} \\ \rowsep -\tcode{Y} & the corresponding allocator class for type \tcode{U} \\ \rowsep -\tcode{XX} & the type \tcode{allocator_traits} \\ \rowsep -\tcode{YY} & the type \tcode{allocator_traits} \\ \rowsep -\tcode{a, a1, a2} & lvalues of type \tcode{X} \\ \rowsep -\tcode{u} & the name of a variable being declared \\ \rowsep -\tcode{b} & a value of type \tcode{Y} \\ \rowsep -\tcode{c} & a pointer of type \tcode{C*} through which indirection is valid \\ \rowsep -\tcode{p} & a value of type \tcode{XX::pointer}, obtained -by calling \tcode{a1.allocate}, where \tcode{a1 == a} \\ \rowsep -\tcode{q} & a value of type \tcode{XX::const_pointer} -obtained by conversion from a value \tcode{p} \\ \rowsep -\tcode{r} & a value of type \tcode{T\&} -obtained by the expression \tcode{*p} \\ \rowsep -\tcode{w} & a value of type \tcode{XX::void_pointer} obtained by - conversion from a value \tcode{p} \\ \rowsep -\tcode{x} & a value of type \tcode{XX::const_void_pointer} obtained by - conversion from a value \tcode{q} or a value \tcode{w} \\ \rowsep -\tcode{y} & a value of type \tcode{XX::const_void_pointer} obtained by -conversion from a result value of \tcode{YY::allocate}, or else a value of -type (possibly \keyword{const}) \tcode{std::nullptr_t} \\ \rowsep -\tcode{n} & a value of type \tcode{XX::size_type} \\ \rowsep -\tcode{Args} & a template parameter pack \\ \rowsep -\tcode{args} & a function parameter pack with the pattern \tcode{Args\&\&} \\ -\end{shortlibreqtab2} +\pnum +In subclause \ref{allocator.requirements}, +\begin{itemize} +\item +\tcode{T}, \tcode{U}, \tcode{C} denote +any \cv-unqualified object type\iref{term.object.type}, +\item +\tcode{X} denotes an allocator class for type \tcode{T}, +\item +\tcode{Y} denotes the corresponding allocator class for type \tcode{U}, +\item +\tcode{XX} denotes the type \tcode{allocator_traits}, +\item +\tcode{YY} denotes the type \tcode{allocator_traits}, +\item +\tcode{a}, \tcode{a1}, \tcode{a2} denote lvalues of type \tcode{X}, +\item +\tcode{u} denotes the name of a variable being declared, +\item +\tcode{b} denotes a value of type \tcode{Y}, +\item +\tcode{c} denotes a pointer of type \tcode{C*} +through which indirection is valid, +\item +\tcode{p} denotes a value of type \tcode{XX::pointer} +obtained by calling \tcode{a1.allocate}, where \tcode{a1 == a}, +\item +\tcode{q} denotes a value of type \tcode{XX::const_pointer} +obtained by conversion from a value \tcode{p}, +\item +\tcode{r} denotes a value of type \tcode{T\&} +obtained by the expression \tcode{*p}, +\item +\tcode{w} denotes a value of type \tcode{XX::void_pointer} +obtained by conversion from a value \tcode{p}, +\item +\tcode{x} denotes a value of type \tcode{XX::const_void_pointer} +obtained by conversion from a value \tcode{q} or a value \tcode{w}, +\item +\tcode{y} denotes a value of type \tcode{XX::const_void_pointer} +obtained by conversion from a result value of \tcode{YY::allocate}, or else +a value of type (possibly \tcode{const}) \tcode{std::nullptr_t}, +\item +\tcode{n} denotes a value of type \tcode{XX::size_type}, +\item +\tcode{Args} denotes a template parameter pack, and +\item +\tcode{args} denotes +a function parameter pack with the pattern \tcode{Args\&\&}. +\end{itemize} \pnum The class template \tcode{allocator_traits}\iref{allocator.traits} supplies a uniform interface to all allocator types. -\tref{allocator.req.var} describes the types manipulated -through allocators. \tref{cpp17.allocator} +\tref{cpp17.allocator} describes the requirements on allocator types and thus on types used to instantiate \tcode{allocator_traits}. A requirement is optional if the last column of @@ -1885,10 +1903,7 @@ template, an optional requirement that is not supplied by an allocator is replaced by the specified default expression. A user specialization of \tcode{allocator_traits} may provide different defaults and may provide -defaults for different requirements than the primary template. Within -Tables~\ref{tab:allocator.req.var} and~\ref{tab:cpp17.allocator}, -the use of \tcode{move} and \tcode{forward} always refers to \tcode{std::move} -and \tcode{std::forward}, respectively. +defaults for different requirements than the primary template. \begin{libreqtab4d} {\oldconcept{Allocator} requirements} From 0befc0e9f7e1df2451fa115b9ff12dbd8d384c5d Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Sun, 27 Feb 2022 23:59:42 +0100 Subject: [PATCH 177/182] [allocator.requirements.general] Dismantle requirements table --- source/lib-intro.tex | 876 ++++++++++++++++++++++++++++++------------- 1 file changed, 623 insertions(+), 253 deletions(-) diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 3ef4fd71ef..4028cdf3a4 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -1894,98 +1894,269 @@ \pnum The class template \tcode{allocator_traits}\iref{allocator.traits} supplies a uniform interface to all allocator types. -\tref{cpp17.allocator} +This subclause describes the requirements on allocator types -and thus on types used to instantiate \tcode{allocator_traits}. A requirement -is optional if the last column of -\tref{cpp17.allocator} specifies a default for a -given expression. Within the standard library \tcode{allocator_traits} +and thus on types used to instantiate \tcode{allocator_traits}. +A requirement is optional if a default for a +given type or expression is specified. +Within the standard library \tcode{allocator_traits} template, an optional requirement that is not supplied by an allocator is -replaced by the specified default expression. A user specialization of +replaced by the specified default type or expression. A user specialization of \tcode{allocator_traits} may provide different defaults and may provide defaults for different requirements than the primary template. -\begin{libreqtab4d} -{\oldconcept{Allocator} requirements} -{cpp17.allocator} -\\ \topline -\lhdr{Expression} & \chdr{Return type} & \chdr{Assertion/note} & \rhdr{Default} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endfirsthead -\continuedcaption\\ -\hline -\lhdr{Expression} & \chdr{Return type} & \chdr{Assertion/note} & \rhdr{Default} \\ - & & \chdr{pre-/post-condition} & \\ \capsep -\endhead -\tcode{X::pointer} & & & \tcode{T*} \\ \rowsep - -\tcode{X::const_pointer} & - & - \tcode{X::pointer} is convertible to \tcode{X::const_pointer} & - \tcode{pointer_traits::\brk{}rebind} \\ \rowsep - -\tcode{X::void_pointer}\br\tcode{Y::void_pointer} & - & - \tcode{X::pointer} is convertible to \tcode{X::void_pointer}. - \tcode{X::void_pointer} and \tcode{Y::void_pointer} are the same type. & - \tcode{pointer_traits::\brk{}rebind} \\ \rowsep - -\tcode{X::const_void_pointer}\br\tcode{Y::const_void_pointer} & - & - \tcode{X::pointer}, \tcode{X::const_pointer}, and \tcode{X::void_pointer} are convertible to \tcode{X::const_void_pointer}. - \tcode{X::const_void_pointer} and \tcode{Y::const_void_pointer} are the same type. & - \tcode{pointer_traits::\brk{}rebind} \\ \rowsep - -\tcode{X::value_type} & - Identical to \tcode{T} & & \\ \rowsep - -\tcode{X::size_type} & - unsigned integer type & - a type that can represent the size of the largest object in the allocation model & - \tcode{make_unsigned_t} \\ \rowsep - -\tcode{X::difference_type} & - signed integer type & - a type that can represent the difference between any two pointers - in the allocation model & - \tcode{pointer_traits::\brk{}difference_type} \\ \rowsep - -\tcode{typename X::template rebind::other} & - \tcode{Y} & - For all \tcode{U} (including \tcode{T}), \tcode{Y::template rebind::other} - is \tcode{X}. & - See Note A, below. \\ \rowsep - -\tcode{*p} & - \tcode{T\&} && \\ \rowsep - -\tcode{*q} & - \tcode{const T\&} & - \tcode{*q} refers to the same object as \tcode{*p}. & \\ \rowsep - -\tcode{p->m} & - type of \tcode{T::m} & - \expects \tcode{(*p).m} is well-defined.\br - equivalent to \tcode{(*p).m} & \\ \rowsep - -\tcode{q->m} & - type of \tcode{T::m} & - \expects \tcode{(*q).m} is well-defined.\br - equivalent to \tcode{(*q).m} & \\ \rowsep - -\tcode{static_cast<\brk{}X::pointer\brk{}>(w)} & - \tcode{X::pointer} & - \tcode{static_cast(w) == p} & \\ \rowsep - -\tcode{static_cast<\brk{}X::const_pointer\brk{}>(x)} & - \tcode{X::const_pointer} & - \tcode{static_cast<} \tcode{X::const_pointer\brk{}>(x) == q} & \\ \rowsep - -\tcode{pointer_traits<\brk{}X::pointer\brk{}>::pointer_to(r)} & - \tcode{X::pointer} & - same as \tcode{p} & \\ \rowsep - -\tcode{a.allocate(n)} & \tcode{X::pointer} & +\begin{itemdecl} +typename X::pointer +\end{itemdecl} + +\begin{itemdescr} +\pnum +\remarks +Default: \tcode{T*} +\end{itemdescr} + +\begin{itemdecl} +typename X::const_pointer +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{X::pointer} is convertible to \tcode{X::const_pointer}. + +\pnum +\remarks +Default: \tcode{pointer_traits::rebind} +\end{itemdescr} + +\begin{itemdecl} +typename X::void_pointer +typename Y::void_pointer +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{X::pointer} is convertible to \tcode{X::void_pointer}. +\tcode{X::void_pointer} and \tcode{Y::void_pointer} are the same type. + +\pnum +\remarks +Default: +\tcode{pointer_traits::rebind} +\end{itemdescr} + +\begin{itemdecl} +typename X::const_void_pointer +typename Y::const_void_pointer +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{X::pointer}, \tcode{X::const_pointer}, and \tcode{X::void_pointer} +are convertible to \tcode{X::const_void_pointer}. +\tcode{X::const_void_pointer} and \tcode{Y::const_void_pointer} +are the same type. + +\pnum +\remarks +Default: +\tcode{pointer_traits::rebind} +\end{itemdescr} + +\begin{itemdecl} +typename X::value_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Identical to \tcode{T}. +\end{itemdescr} + +\begin{itemdecl} +typename X::size_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +An unsigned integer type +that can represent the size of the largest object in the allocation model. + +\pnum +\remarks +Default: +\tcode{make_unsigned_t} +\end{itemdescr} + +\begin{itemdecl} +typename X::difference_type +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +A signed integer type that can represent +the difference between any two pointers in the allocation model. + +\pnum +\remarks +Default: +\tcode{pointer_traits::difference_type} +\end{itemdescr} + +\begin{itemdecl} +typename X::template rebind::other +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{Y} + +\pnum +\ensures +For all \tcode{U} (including \tcode{T}), +\tcode{Y::template rebind::other} is \tcode{X}. + +\pnum +\remarks +If \tcode{Allocator} is a class template instantiation of the form +\tcode{SomeAllocator}, where \tcode{Args} is zero or more type +arguments, and \tcode{Allocator} does not supply a \tcode{rebind} member +template, the standard \tcode{allocator_traits} template uses +\tcode{SomeAllocator} in place of \tcode{Allocator::re\-bind::other} +by default. For allocator types that are not template instantiations of the +above form, no default is provided. + +\pnum +\begin{note} +The member class template \tcode{rebind} of \tcode{X} is +effectively a typedef template. +In general, if +the name \tcode{Allocator} is bound to \tcode{SomeAllocator}, then +\tcode{Allocator::rebind::other} is the same type as +\tcode{SomeAllocator}, where +\tcode{SomeAllocator::value_type} is \tcode{T} and +\tcode{SomeAllocator::value_type} is \tcode{U}. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +*p +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{T\&} +\end{itemdescr} + +\begin{itemdecl} +*q +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{const T\&} + +\pnum +\ensures +\tcode{*q} refers to the same object as \tcode{*p}. +\end{itemdescr} + +\begin{itemdecl} +p->m +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Type of \tcode{T::m}. + +\pnum +\expects +\tcode{(*p).m} is well-defined. + +\pnum +\effects +Equivalent to \tcode{(*p).m}. +\end{itemdescr} + +\begin{itemdecl} +q->m +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Type of \tcode{T::m}. + +\pnum +\expects +\tcode{(*q).m} is well-defined. + +\pnum +\effects +Equivalent to \tcode{(*q).m}. +\end{itemdescr} + +\begin{itemdecl} +static_cast(w) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::pointer} + +\pnum +\ensures +\tcode{static_cast(w) == p}. +\end{itemdescr} + +\begin{itemdecl} +static_cast(x) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::const_pointer} + +\pnum +\ensures +\tcode{static_cast(x) == q}. +\end{itemdescr} + +\begin{itemdecl} +pointer_traits::pointer_to(r) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::pointer} + +\pnum +\ensures +Same as \tcode{p}. +\end{itemdescr} + +\begin{itemdecl} +a.allocate(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::pointer} + +\pnum +\effects Memory is allocated for an array of \tcode{n} \tcode{T} and such an object is created but array elements are not constructed. @@ -1995,189 +2166,388 @@ can be used to implicitly create a suitable array object and obtain a pointer to it. \end{example} + +\pnum +\throws \tcode{allocate} may throw an appropriate exception. -\begin{footnote} + +\pnum +\begin{note} It is intended that \tcode{a.allocate} be an efficient means of allocating a single object of type \tcode{T}, even when \tcode{sizeof(T)} is small. That is, there is no need for a container to maintain its own free list. -\end{footnote} -See Note C, below. -& \\ \rowsep - -\tcode{a.allocate(n, y)} & - \tcode{X::pointer} & - Same as \tcode{a.allocate(n)}. The use of \tcode{y} is unspecified, but - it is intended as an aid to locality. & - \tcode{a.allocate(n)} \\ \rowsep - -\tcode{a.allocate_at_least(n)} & - \tcode{allocation_result} & - \returns - \tcode{allocation_result\{ptr, count\}} - where \tcode{ptr} is memory allocated for an array of \tcode{count} \tcode{T} - and such an object is created but array elements are not constructed, - such that $\tcode{count} \geq \tcode{n}$. - \tcode{allocate_at_least} may throw an appropriate exception. - See Note C, below. & - See Note D, below. \\ \rowsep - -\tcode{a.deallocate(p,n)} & - (not used) & - \expects - \begin{itemize} - \item - If \tcode{p} is memory - that was obtained by a call to \tcode{a.allocate_at_least}, - let \tcode{ret} be the value returned and - \tcode{req} be the value passed as the first argument of that call. - \tcode{p} is equal to \tcode{ret.ptr} and - \tcode{n} is a value such that - $\tcode{req} \leq \tcode{n} \leq \tcode{ret.count}$. - \item - Otherwise, \tcode{p} is a pointer value obtained from \tcode{allocate}. - \tcode{n} equals the value passed as the first argument - to the invocation of \tcode{allocate} which returned \tcode{p}. - \end{itemize} - \tcode{p} has not been invalidated by - an intervening call to \tcode{deallocate}.\br - \throws Nothing. & \\ \rowsep - -\tcode{a.max_size()} & - \tcode{X::size_type} & - the largest value that can meaningfully be passed to \tcode{X::allocate()} & - \tcode{numeric_limits::max() / sizeof\brk{}(value_type)} \\ \rowsep - -\tcode{a1 == a2} & - \tcode{bool} & - Returns \tcode{true} only if storage allocated from each can - be deallocated via the other. \tcode{operator==} shall be reflexive, symmetric, - and transitive, and shall not exit via an exception. & \\ \rowsep - -\tcode{a1 != a2} & - \tcode{bool} & - same as \tcode{!(a1 == a2)} & \\ \rowsep - -\tcode{a == b} & - \tcode{bool} & - same as \tcode{a ==} \tcode{Y::rebind::other(b)} & \\ \rowsep - -\tcode{a != b} & - \tcode{bool} & - same as \tcode{!(a == b)} & \\ \rowsep - -\tcode{X u(a)}; \br -\tcode{X u = a;} & - & - Shall not exit via an exception.\br - \ensures \tcode{u == a} & \\ \rowsep - -\tcode{X u(b);} & - & - Shall not exit via an exception.\br - \ensures \tcode{Y(u) == b}, \tcode{u == X(b)} & \\ \rowsep - -\tcode{X u(std::move(a));} \br -\tcode{X u = std::move(a);} & - & - Shall not exit via an exception.\br - \ensures The value of \tcode{a} is unchanged and is equal to \tcode{u}. & \\ \rowsep - -\tcode{X u(std::move(b));} & - & - Shall not exit via an exception.\br - \ensures \tcode{u} is equal to the prior value of \tcode{X(b)}. & \\ \rowsep - -\tcode{a.construct(c, args)}& - (not used) & - \effects Constructs an object of type \tcode{C} at - \tcode{c}. & - \tcode{construct_at(c,~std::\brk{}forward\brk{}(args)...)} \\ \rowsep - -\tcode{a.destroy(c)} & - (not used) & - \effects Destroys the object at \tcode{c} & - \tcode{destroy_at(c)} \\ \rowsep - -\tcode{a.select_on_container_copy_construction()} & - \tcode{X} & - Typically returns either \tcode{a} or \tcode{X()}. & - \tcode{return a;} \\ \rowsep - -\tcode{X::propagate_on_container_copy_assignment} & - Identical to or derived from \tcode{true_type} or \tcode{false_type} & - \tcode{true_type} only if an allocator of type \tcode{X} should be copied - when the client container is copy-assigned. - See Note B, below. & - \tcode{false_type} \\ \rowsep - -\tcode{X::propagate_on_container_move_assignment} & - Identical to or derived from \tcode{true_type} or \tcode{false_type} & - \tcode{true_type} only if an allocator of type \tcode{X} should be moved - when the client container is move-assigned. - See Note B, below. & - \tcode{false_type} \\ \rowsep - -\tcode{X::propagate_on_-} \tcode{container_swap} & - Identical to or derived from \tcode{true_type} or \tcode{false_type} & - \tcode{true_type} only if an allocator of type \tcode{X} should be swapped - when the client container is swapped. - See Note B, below. & - \tcode{false_type} \\ \rowsep - -\tcode{X::is_always_equal} & - Identical to or derived from \tcode{true_type} or \tcode{false_type} & - \tcode{true_type} only if the expression \tcode{a1 == a2} is guaranteed - to be \tcode{true} for any two (possibly \keyword{const}) values - \tcode{a1}, \tcode{a2} of type \tcode{X}. & - \tcode{is_empty::\brk{}type} \\ - -\end{libreqtab4d} - -\pnum -Note A: The member class template \tcode{rebind} in the table above is -effectively a typedef template. -\begin{note} -In general, if -the name \tcode{Allocator} is bound to \tcode{SomeAllocator}, then -\tcode{Allocator::rebind::other} is the same type as -\tcode{SomeAllocator}, where -\tcode{SomeAllocator::value_type} is \tcode{T} and -\tcode{SomeAllocator::\brk{}value_type} is \tcode{U}. \end{note} -If -\tcode{Allocator} is a class template instantiation of the form -\tcode{SomeAllocator}, where \tcode{Args} is zero or more type -arguments, and \tcode{Allocator} does not supply a \tcode{rebind} member -template, the standard \tcode{allocator_traits} template uses -\tcode{SomeAllocator} in place of \tcode{Allocator::\brk{}rebind::other} -by default. For allocator types that are not template instantiations of the -above form, no default is provided. \pnum -Note B: -If \tcode{X::propagate_on_container_copy_assignment::value} is \tcode{true}, -\tcode{X} shall meet the -\oldconcept{\-Copy\-Assign\-able} requirements (\tref{cpp17.copyassignable}) -and the copy operation shall not throw exceptions. -If \tcode{X::propagate_on_container_move_assignment::value} is \tcode{true}, -\tcode{X} shall meet the -\oldconcept{\-Move\-Assign\-able} requirements (\tref{cpp17.moveassignable}) -and the move operation shall not throw exceptions. -If \tcode{X::propagate_on_container_swap::value} is \tcode{true}, -lvalues of type \tcode{X} shall be swappable\iref{swappable.requirements} -and the \tcode{swap} operation shall not throw exceptions. +\remarks +If \tcode{n == 0}, the return value is unspecified. +\end{itemdescr} + +\begin{itemdecl} +a.allocate(n, y) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::pointer} + +\pnum +\effects +Same as \tcode{a.allocate(n)}. +The use of \tcode{y} is unspecified, but it is intended as an aid to locality. + +\pnum +\remarks +Default: \tcode{a.allocate(n)} +\end{itemdescr} + +\begin{itemdecl} +a.allocate_at_least(n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{allocation_result} \pnum -Note C: +\returns +\tcode{allocation_result\{ptr, count\}} +where \tcode{ptr} is memory allocated for an array of \tcode{count} \tcode{T} +and such an object is created but array elements are not constructed, +such that $\tcode{count} \geq \tcode{n}$. If \tcode{n == 0}, the return value is unspecified. \pnum -Note D: +\throws +\tcode{allocate_at_least} may throw an appropriate exception. + +\pnum +\remarks An allocator need not support \tcode{allocate_at_least}, but no default is provided in \tcode{allocator_traits}. If an allocator has an \tcode{allocate_at_least} member, it shall satisfy the requirements. +\end{itemdescr} + +\begin{itemdecl} +a.deallocate(p, n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +(not used) + +\pnum +\expects +\begin{itemize} +\item +If \tcode{p} is memory +that was obtained by a call to \tcode{a.allocate_at_least}, +let \tcode{ret} be the value returned and +\tcode{req} be the value passed as the first argument of that call. +\tcode{p} is equal to \tcode{ret.ptr} and +\tcode{n} is a value such that +$\tcode{req} \leq \tcode{n} \leq \tcode{ret.count}$. +\item +Otherwise, \tcode{p} is a pointer value obtained from \tcode{allocate}. +\tcode{n} equals the value passed as the first argument +to the invocation of \tcode{allocate} which returned \tcode{p}. +\end{itemize} +\tcode{p} has not been invalidated by +an intervening call to \tcode{deallocate}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +a.max_size() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X::size_type} + +\pnum +\returns +The largest value that can meaningfully be passed to \tcode{X::allocate()}. + +\pnum +\remarks +Default: +\tcode{numeric_limits::max() / sizeof(value_type)} +\end{itemdescr} + +\begin{itemdecl} +a1 == a2 +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\returns +\tcode{true} only if storage allocated from each can +be deallocated via the other. + +\pnum +\throws +Nothing. + +\pnum +\remarks +\tcode{operator==} shall be reflexive, symmetric, +and transitive. +\end{itemdescr} + +\begin{itemdecl} +a1 != a2 +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\returns +\tcode{!(a1 == a2)}. +\end{itemdescr} + +\begin{itemdecl} +a == b +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\returns +\tcode{a == Y::rebind::other(b)}. +\end{itemdescr} + +\begin{itemdecl} +a != b +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{bool} + +\pnum +\returns +\tcode{!(a == b)}. +\end{itemdescr} + +\begin{itemdecl} +X u(a); +X u = a; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{u == a} + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +X u(b); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{Y(u) == b} and \tcode{u == X(b)}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +X u(std::move(a)); +X u = std::move(a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +The value of \tcode{a} is unchanged and is equal to \tcode{u}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +X u(std::move(b)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{u} is equal to the prior value of \tcode{X(b)}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\begin{itemdecl} +a.construct(c, args) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +(not used) + +\pnum +\effects +Constructs an object of type \tcode{C} at \tcode{c}. + +\pnum +\remarks +Default: +\tcode{construct_at(c, std::forward(args)...)} +\end{itemdescr} + +\begin{itemdecl} +a.destroy(c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +(not used) + +\pnum +\effects +Destroys the object at \tcode{c}. + +\pnum +\remarks +Default: \tcode{destroy_at(c)} +\end{itemdescr} + +\begin{itemdecl} +a.select_on_container_copy_construction() +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{X} + +\pnum +\returns +Typically returns either \tcode{a} or \tcode{X()}. + +\pnum +\remarks +Default: \tcode{return a;} +\end{itemdescr} + +\begin{itemdecl} +X::propagate_on_container_copy_assignment +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Identical to or derived from \tcode{true_type} or \tcode{false_type}. + +\pnum +\returns +\tcode{true_type} only if an allocator of type \tcode{X} should be copied +when the client container is copy-assigned; +if so, \tcode{X} shall meet +the \oldconcept{CopyAssignable} requirements (\tref{cpp17.copyassignable}) and +the copy operation shall not throw exceptions. + +\pnum +\remarks +Default: \tcode{false_type} +\end{itemdescr} + +\begin{itemdecl} +X::propagate_on_container_move_assignment +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Identical to or derived from \tcode{true_type} or \tcode{false_type}. + +\pnum +\returns +\tcode{true_type} only if an allocator of type \tcode{X} should be moved +when the client container is move-assigned; +if so, \tcode{X} shall meet +the \oldconcept{MoveAssignable} requirements (\tref{cpp17.moveassignable}) and +the move operation shall not throw exceptions. + +\pnum +\remarks +Default: \tcode{false_type} +\end{itemdescr} + +\begin{itemdecl} +X::propagate_on_container_swap +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Identical to or derived from \tcode{true_type} or \tcode{false_type}. + +\pnum +\returns +\tcode{true_type} only if an allocator of type \tcode{X} should be swapped +when the client container is swapped; +if so, +lvalues of type \tcode{X} shall be swappable\iref{swappable.requirements} and +the \tcode{swap} operation shall not throw exceptions. + +\pnum +\remarks +Default: \tcode{false_type} +\end{itemdescr} + +\begin{itemdecl} +X::is_always_equal +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +Identical to or derived from \tcode{true_type} or \tcode{false_type}. + +\pnum +\returns +\tcode{true_type} only if the expression \tcode{a1 == a2} is guaranteed +to be \tcode{true} for any two (possibly \tcode{const}) values +\tcode{a1}, \tcode{a2} of type \tcode{X}. + +\pnum +\remarks +Default: \tcode{is_empty::type} +\end{itemdescr} \pnum An allocator type \tcode{X} shall meet the From 4e4aa46276d1542b2f0ff66ebd0f66df8ba0d785 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Mon, 28 Feb 2022 00:17:47 +0100 Subject: [PATCH 178/182] [lib] Fix cross-references to replaced table cpp17.allocator --- source/iostreams.tex | 8 ++++---- source/lib-intro.tex | 3 +-- source/memory.tex | 14 ++++++++------ source/threads.tex | 4 ++-- source/utilities.tex | 8 ++++---- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/source/iostreams.tex b/source/iostreams.tex index e7fa8f0516..bb586b70d6 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -12151,8 +12151,8 @@ \end{codeblock} \pnum -\tcode{Allocator} shall meet the \oldconcept{Allocator} requirements -(\tref{cpp17.allocator}). +\tcode{Allocator} shall meet +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \pnum \begin{example} @@ -12458,8 +12458,8 @@ \end{note} \pnum -Template parameters named \tcode{Allocator} shall meet the -\oldconcept{Allocator} requirements (\tref{cpp17.allocator}). +Template parameters named \tcode{Allocator} shall meet +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \rSec2[fs.filesystem.syn]{Header \tcode{} synopsis} diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 4028cdf3a4..04ada51d52 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -2621,8 +2621,7 @@ \pnum \begin{example} The following is an allocator class template supporting the minimal -interface that meets the requirements of -\tref{cpp17.allocator}: +interface that meets the requirements of \ref{allocator.requirements.general}: \begin{codeblock} template diff --git a/source/memory.tex b/source/memory.tex index 668bdf2667..576a28b9fc 100644 --- a/source/memory.tex +++ b/source/memory.tex @@ -815,7 +815,7 @@ disambiguate constructor and function overloading. Specifically, several types (see \tcode{tuple}~\ref{tuple}) have constructors with \tcode{allocator_arg_t} as the first argument, immediately followed by an argument of a type that meets the -\oldconcept{Allocator} requirements (\tref{cpp17.allocator}). +\oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \rSec2[allocator.uses]{\tcode{uses_allocator}} @@ -1913,7 +1913,7 @@ \pnum \begin{example} -Given an allocator type \tcode{X} (\tref{cpp17.allocator}) and +Given an allocator type \tcode{X}\iref{allocator.requirements.general} and letting \tcode{A} be a synonym for \tcode{allocator_traits}, the types \tcode{A::pointer}, \tcode{A::const_pointer}, \tcode{A::void_pointer}, and \tcode{A::const_void_pointer} may be used as \tcode{unique_ptr::pointer}. @@ -3188,7 +3188,8 @@ initialized with \tcode{std::move(d)} do not throw exceptions. The expression \tcode{d(p)} has well-defined behavior and does not throw exceptions. -\tcode{A} meets the \oldconcept{Allocator} requirements (\tref{cpp17.allocator}). +\tcode{A} meets +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \pnum \effects @@ -3673,7 +3674,8 @@ \begin{itemdescr} \pnum \expects -\tcode{A} meets the \oldconcept{Allocator} requirements (\tref{cpp17.allocator}). +\tcode{A} meets +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \pnum \effects @@ -5389,8 +5391,8 @@ \rSec3[mem.poly.allocator.class.general]{General} \pnum -A specialization of class template \tcode{pmr::polymorphic_allocator} -meets the \oldconcept{Allocator} requirements (\tref{cpp17.allocator}). +A specialization of class template \tcode{pmr::polymorphic_allocator} meets +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. Constructed with different memory resources, different instances of the same specialization of \tcode{pmr::polymorphic_allocator} can exhibit entirely different allocation behavior. diff --git a/source/threads.tex b/source/threads.tex index 6a59070e5a..b2a90ea8d3 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -10137,8 +10137,8 @@ \begin{itemdescr} \pnum \expects -\tcode{Alloc} meets the \oldconcept{Allocator} -requirements (\tref{cpp17.allocator}). +\tcode{Alloc} meets +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \end{itemdescr} \indexlibraryctor{promise}% diff --git a/source/utilities.tex b/source/utilities.tex index 0ea252fc38..b85cbf93e1 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -1861,8 +1861,8 @@ \begin{itemdescr} \pnum \expects -\tcode{Alloc} meets the -\oldconcept{Allocator} requirements (\tref{cpp17.allocator}). +\tcode{Alloc} meets +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \pnum \effects @@ -2675,8 +2675,8 @@ \begin{itemdescr} \pnum \expects -\tcode{Alloc} meets the \oldconcept{Allocator} -requirements (\tref{cpp17.allocator}). +\tcode{Alloc} meets +the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \pnum \begin{note} From 2d8e11333fe4e188a940bc5c4e1a2f33b139ee3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Mon, 21 Feb 2022 14:49:31 -0400 Subject: [PATCH 179/182] [array.overview] Don't mention swap as an exception The container requirements already describe this behavior, so from the POV of this subclause, there's no exception. --- source/containers.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index c3342af987..42eb10bbd3 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -6123,8 +6123,8 @@ of a container\iref{container.reqmts} and of a reversible container\iref{container.rev.reqmts}, except that a default -constructed \tcode{array} object is not empty and that \tcode{swap} does not have constant -complexity. An \tcode{array} meets some of the requirements of a sequence +constructed \tcode{array} object is not empty. +An \tcode{array} meets some of the requirements of a sequence container\iref{sequence.reqmts}. Descriptions are provided here only for operations on \tcode{array} that are not described in From 65e74383deb8bcc0cab8e813b6360e9b1e8f6b10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Mon, 21 Feb 2022 14:52:15 -0400 Subject: [PATCH 180/182] [array.overview] Mention condition of exception --- source/containers.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/containers.tex b/source/containers.tex index 42eb10bbd3..258a4e7ffb 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -6123,7 +6123,7 @@ of a container\iref{container.reqmts} and of a reversible container\iref{container.rev.reqmts}, except that a default -constructed \tcode{array} object is not empty. +constructed \tcode{array} object is not empty if $\tcode{N} > 0$. An \tcode{array} meets some of the requirements of a sequence container\iref{sequence.reqmts}. Descriptions are provided here From 7b84fe3774863406c81818a5906e555dbe9e3125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Thu, 17 Mar 2022 16:38:51 +0000 Subject: [PATCH 181/182] [macros] Remove unused "element-like" macros. --- source/macros.tex | 4 ---- 1 file changed, 4 deletions(-) diff --git a/source/macros.tex b/source/macros.tex index f7107b70bc..84f6ecbf71 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -341,11 +341,7 @@ \newcommand{\replaceable}{\Fundesc{Replaceable}} \newcommand{\result}{\Fundesc{Result}} \newcommand{\returntype}{\Fundesc{Return type}} -\newcommand{\cvalue}{\Fundesc{Value}} \newcommand{\ctype}{\Fundesc{Type}} -\newcommand{\ctypes}{\Fundesc{Types}} -\newcommand{\dtype}{\Fundesc{Default type}} -\newcommand{\ctemplate}{\Fundesc{Class template}} \newcommand{\templalias}{\Fundesc{Alias template}} %% Cross reference From d17e8fe027780c2ec47384bb5653ea83d7da556c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Wed, 16 Mar 2022 00:46:13 +0000 Subject: [PATCH 182/182] Update configuration for new working draft N4910 and add corresponding Editors' Report N4911 --- papers/n4911.html | 1027 ++++++++++++++++++++++++++++++++++++++++++++ papers/n4911.md | 892 ++++++++++++++++++++++++++++++++++++++ papers/wd-index.md | 5 +- source/config.tex | 2 +- 4 files changed, 1923 insertions(+), 3 deletions(-) create mode 100644 papers/n4911.html create mode 100644 papers/n4911.md diff --git a/papers/n4911.html b/papers/n4911.html new file mode 100644 index 0000000000..11b62cf3a1 --- /dev/null +++ b/papers/n4911.html @@ -0,0 +1,1027 @@ + + + + + +N4911 + + +

N4911 Editors' Report -- Programming Languages -- C++

+ +

Date: 2022-03-17

+ +

Thomas Köppe (editor, Google DeepMind)
+Jens Maurer (co-editor)
+Dawn Perchik (co-editor, Bright Side Computing, LLC)
+Richard Smith (co-editor, Google Inc)

+ +

Email: cxxeditor@gmail.com

+ +

Acknowledgements

+ +

Thanks to all those who have submitted editorial +issues +and to those who have provided pull requests with fixes, and special thanks to +Johel Ernesto Guerrero Peña for providing in-depth review of most of the draft +motion applications.

+ +

New papers

+ +
    +
  • N4910 is the +current working draft for C++23. It replaces +N4901.
  • +
  • N4911 is this Editors' Report.
  • +
+ +

Motions incorporated into working draft

+ +

Core working group polls

+ +

CWG poll 1: Accept as Defect Reports all issues except issue 2502 in +P2533R0 +(Core Language Working Group "ready" Issues for the February, 2022 meeting) and +apply the proposed resolutions for all of the issues to the C++ working paper.

+ +

CWG poll 2: Apply the changes in +P2173R1 +(Attributes on Lambda-Expressions) to the C++ Working Paper.

+ +

CWG poll 3: Apply the changes in +P2493R0 +(Missing feature test macros for C++20 core papers) to the C++ Working Paper.

+ +

Library working group polls

+ +

LWG poll 1: Apply the changes for all Tentatively Ready issues in +P2531R0 (C++ +Standard Library Issues to be moved in Virtual Plenary, Feb. 2022) to the C++ +working paper.

+ +

LWG poll 2: Apply the changes in +P0323R12 +(std::expected) to the C++ working paper.

+ +

LWG poll 3: Apply the changes in +P0533R9 +(constexpr for <cmath> and <cstdlib>) to the C++ working paper.

+ +

LWG poll 4: Apply the changes in +P0627R6 +(Function to mark unreachable code) to the C++ working paper.

+ +

LWG poll 5: Apply the changes in +P1206R7 +(ranges::to: A function to convert any range to a container) to the C++ working +paper.

+ +

LWG poll 6: Apply the changes in +P1413R3 +(Deprecate std::aligned_storage and std::aligned_union) to the C++ working +paper.

+ +

LWG poll 7: Apply the changes in +P2255R2 (A +type trait to detect reference binding to temporary) to the C++ working paper.

+ +

LWG poll 8: Apply the changes in +P2273R3 +(Making std::unique_ptr constexpr) to the C++ working paper.

+ +

LWG poll 9: Apply the changes in +P2387R3 +(Pipe support for user-defined range adaptors) to the C++ working paper.

+ +

LWG poll 10: Apply the changes in +P2440R1 +(ranges::iota, ranges::shift_left and ranges::shift_right) to the C++ +working paper.

+ +

LWG poll 11: Apply the changes in +P2441R2 +(views::join_with) to the C++ working paper.

+ +

LWG poll 12: Apply the changes in +P2442R1 +(Windowing range adaptors: views::chunk and views::slide) to the C++ working +paper.

+ +

LWG poll 13: Apply the changes in +P2443R1 +(views::chunk_by) to the C++ working paper.

+ +

Editorial changes

+ +

Notes on motions

+ +
    +
  • Poll CWG-2: The wording was adjusted to integrate with the new wording +from issue +CWG-2509 +to use the new term lambda-specifier-seq instead of the original +decl-specifier-seq.

  • +
  • Poll LWG-1: Issue +LWG-3616 +was skipped, since it had already been applied +editorially.

  • +
  • Poll LWG-8: The wording was integrated with the resolution of +LWG-3632.

  • +
+ +

Clause reorganization

+ +

We rearranged several clauses and subclauses. Over the years, the original +clause structure had been becoming less appropriate for the growing amount of +content, and we hope that the new structure is more suitable to the current (and +anticipated future) content.

+ +
    +
  • New top-level clause "Memory management library [mem]", after [diagnostics]. +This clause contains <memory>, memory parts of <cstdlib>, smart pointers, +memory resources, and scoped allocators, previously part of [utilities].

  • +
  • The "Metaprogramming library [meta]" subclause from [utilities] is now a +new top-level clause, in between [mem] and [utilities]. We expect future +reflection material to be added to this clause.

  • +
  • The "Atomic operations [atomics]" clause has been integrated into the +top-level [thread] clause, which has been renamed to "Concurrency support +library [thread]".

  • +
  • "Bit manipulation [bit]" has been moved to the end of the [utilities] clause.

  • +
  • "Stacktrace [stacktrace]" has been moved to the end of the [diagnostics] clause.

  • +
  • "String view classes [string.view]" has been moved to immediately before +[string.classes].

  • +
  • "Allocation and deallocation functions [class.free]" has been moved to +immediately before [class.nest].

  • +
+ +

We are aiming to not change the top-level clause structure more than once per +standard publication cycle. We have had suggestions to create a new top-level +clause "Text" for text-related content (such as locales and regular expressions, +but also anticipating new material). We have not yet reached consensus, and we +will probably perform that reorganization during the C++26 cycle.

+ +

Requirements tables

+ +

We have begun replacing the large requirements tables in the library with more +conventional paragraphs, as described in editorial paper +P2416R2. +Each requirement is now presented in a style similar to that of function +declarations, followed by as many specification elements as appropriate. A new +"Result:" element has been added to capture the type of a type requirement, +and the type and value category of an expression requirement.

+ +

We have applied these changes to the container, allocator, and regular +expression trait requirements.

+ +

Term labels

+ +

We have started introducing explicit LaTeX labels for defined terms, and we have +updated cross references to refer to those term labels instead of the label of +the subclause that contains the term. This does not change the presentation of +the reference, but makes it less likely that cross references are invalidated by +moving text around.

+ +

In the future, we might extend this to turn the use of a term into a hyperlink +to the page on which the term's definition appears.

+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4901 is below. This +list excludes changes that do not affect the body text or only affect whitespace +or typeface. For a complete list including such changes (or for the actual +deltas applied by these changes), consult the draft sources on +github.

+ +
commit 04e0ea7074c9b0d0ca939821ce0f575c589df6b7
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Oct 21 23:52:55 2021 +0200
+
+    [pairs.pair] Use T1/T2, not first_type/second_type
+
+commit ed6e1b5da5d13449cf27c878c60e90892289f98a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Oct 23 01:20:31 2021 +0200
+
+    [index] Fix dangling 'see' references
+
+    Also update the automatic check script to prevent
+    further occurrences.
+
+commit 3d1424716844aef59891d770709e19d83b5bea35
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Oct 24 22:05:40 2021 +0200
+
+    [ranges] Remove \expos markers for nested types (#4829)
+
+    An \expos marker should appear only on the first
+    declaration of a name.
+
+commit 741c20794fdc7aec28afcd9e6c52d6d184d2845c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Oct 26 16:36:39 2021 +0200
+
+    [class.copy.assign] Fix phrasing in note to avoid 'could'. (#4418)
+
+commit f3ab334c789ac89d2f6baf501d60716278cb8fa3
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Jul 4 23:30:42 2021 +0200
+
+    [contents] Add special lookup treatment for swap
+
+commit 280684c7824b6b7f62c003b909ccf3703d82681b
+Author: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+Date:   Mon Nov 8 07:19:14 2021 -0400
+
+    [defs] Update introduction to match ISO Directives (#5096)
+
+    Reference: https://www.iso.org/sites/directives/current/part2/index.xhtml#_idTextAnchor218
+
+commit 1567c481e3ca3c52f80e4a33db0f913ce1392c4d
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Nov 9 09:31:08 2021 +0000
+
+    [intro.refs] Update dated reference to previous POSIX standard
+
+    Fixes #5098
+
+commit c8ec4ab45f58e3a16d8dcb12bd660dd2cf6e936a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Nov 23 17:22:38 2021 +0100
+
+    [refwrap.general] Add cross-references to the class synopsis (#5122)
+
+    Also rename [refwrap.const], because it does not specify
+    any destructors.
+
+commit b4bf594c81865f892bae81342ffb67c8ca8adb74
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Nov 23 17:24:35 2021 +0100
+
+    [smartptr] Rework subclause nesting (#5119)
+
+commit d0cb462d511e5c9bf1ae7403c275f7c1ccf2543d
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Sat Nov 20 02:16:40 2021 +0800
+
+    [range.adjacent.overview] Fix multi-character in example
+
+commit 26f6a1f7573ea54ed93b4e90d0e487fe39d44b87
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Nov 13 10:01:36 2021 +0100
+
+    [dcl.typedef] Add explanation for lookup failure in example
+
+commit c63e5e836e8dbe0ae6c7ebc1b2a1b1534d37a220
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Nov 10 23:40:48 2021 +0100
+
+    [input.output] Fix headings of 'assign and swap' subclauses
+
+commit d2699e5de0c10085df309074d2dfbc57d5bc86bb
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Oct 27 21:20:02 2021 +0200
+
+    [std] Replace 'OK:' in code comments with 'OK,'
+
+    In contrast to errors, which use a colon, an OK comment
+    is not followed by any unique reason why the code is
+    well-formed, but by a subjective highlighting of a fact.
+
+commit 5e3f1ad0ceb89feb2977a0531422bcbe9ab8fba7
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Oct 26 21:49:15 2021 +0200
+
+    [stdatomic.h.syn] Fix missing \expos
+
+    and augment the autmatic checks accordingly.
+
+commit 16e60c63ad14f3f3fc9132a8443421a15ebec8fc
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Nov 9 13:09:27 2021 +0100
+
+    [locale.time.get] Replace 'ISO/IEC 9945' with 'POSIX'
+
+    We introduce POSIX as an alias for ISO/IEC 9945, and we use 'POSIX'
+    everywhere else.
+
+commit 31c32e035770797eedc69f150c3a3484bbe828a5
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Nov 9 17:54:18 2021 +0100
+
+    [locale.time.get.virtuals] Use 'conversion specification'
+
+    POSIX does not define the term 'conversion directive'.
+
+commit fbab3f13719c34affdb7b712aed7f6d2313570d7
+Author: languagelawyer <38548419+languagelawyer@users.noreply.github.com>
+Date:   Tue Nov 23 20:03:13 2021 +0300
+
+    [defns.access, basic.lval] Clarify what can be accessed and how (#4777)
+
+commit 5475bdab828b3585a21172945303ccebbcefb516
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Oct 21 22:11:07 2021 +0200
+
+    [c.mb.wcs] mbrtoc8 stores code units, not characters
+
+commit ba4bb3ee56b94b63d0d1e5914a136a04b1620052
+Author: mordante <koraq@xs4all.nl>
+Date:   Tue Nov 23 18:13:22 2021 +0100
+
+    [format.functions] Add "std::move" around "out" (#5069)
+
+    This fixes a misapplication of the resolution of LWG 3539.
+
+commit 0d0ec1a1393b3baae564234007c94b80da9bab48
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Nov 23 18:15:55 2021 +0100
+
+    [func.wrap.{func.general, move.class}] Remove 'first-class object' (#5067)
+
+    The term is undefined and does not improve the specification.
+
+commit d27c3b388befadc4c35aac1d12f0ba8581f14a5f
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Nov 12 14:29:00 2021 +0000
+
+    [spanstream.ctor] Fix base class name in effects
+
+commit c1935504da840995b1bb60eba536cb12bca5ae71
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Tue Nov 23 11:51:37 2021 -0600
+
+    [basic.start.main] Remove redundant phrase (#5083)
+
+commit 70eb0406596b4f4e3d97ed50b3fd6d93b3032d18
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Oct 25 23:57:58 2021 +0200
+
+    [basic.start.main] Avoid implementation guidance in a note
+
+commit ac8d6611a739c64eda4a7062f2cb83f770cd8a53
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Oct 25 23:58:08 2021 +0200
+
+    [dcl.link] Avoid implementation guidance in a note
+
+commit 2ad67aefe350017c4e9403ba2015af683813787f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Nov 6 22:08:47 2021 +0100
+
+    [lex] Remove Unicode character name abbreviations
+
+    They are not part of the character name or alias.
+    The presentation in ISO 10646 is misleading, though.
+
+commit 29c89b16e92cd03a76eb2a19866e683a7bb7ac80
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Nov 6 22:15:05 2021 +0100
+
+    [lex] Rename U+0007 BELL to ALERT
+
+    The former is ambiguous with U+1F514 BELL.
+    The ALERT alias is defined in UCD NameAliases.txt.
+
+commit 408623b7d8f0efd77403d1d0142d9bd59d1cfe55
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Dec 4 11:19:54 2021 +0100
+
+    [associative.reqmts.general] Fix typo: 'kx', not 'rx' (#5136)
+
+commit f03473cd1e32691c105260e65dd534960cf9db21
+Author: Neven Sajko <nsajko@gmail.com>
+Date:   Sun Dec 5 21:19:00 2021 +0100
+
+    [over.sub] Fix typo: change oeprator to operator (#5140)
+
+commit c69a35501174f5ab5d3f13f12186cc9b1fcd40dd
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Dec 14 11:24:04 2021 +0100
+
+    [range.access] Fix cross-references for 'array' (#5147)
+
+    Also introduce a label 'term.array.type' in [dcl.array].
+
+commit 7a09dddd036359a10cf10b8e7d80c8edd8c76817
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 16 19:39:18 2021 +0100
+
+    [basic.fundamental] Excise normative requirements on std::numeric_limits (#5105)
+
+commit c2617432eac3313abd2134a26e2d8a1d925dfd15
+Author: Casey Carter <Casey@Carter.net>
+Date:   Thu Dec 16 23:53:17 2021 -0800
+
+    [depr.default.allocator] Index allocator::is_always_equal here (#5152)
+
+    LWG3170 deprecated `allocator::is_always_equal`. We moved it to Annex D, but left the index entry behind.
+
+commit 28effaea15ef697f5a64fba47b9c095c9fbfe82a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Dec 19 22:16:18 2021 +0100
+
+    [ptr.align,re.regiter.incr] Replace 'compiler' with 'implementation'
+
+commit 575b9a99062de34cc44bc45aeb459f32aa12b98f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Dec 19 22:19:19 2021 +0100
+
+    [smartptr.adapt] Emphasize that casting might not always be viable
+
+commit 9ba8e0329a0f5db15544c31c514ff44e0003f08f
+Author: frederick-vs-ja <de34@live.cn>
+Date:   Tue Jan 11 23:29:26 2022 +0800
+
+    [pairs.pair] Add missing _v for type traits (#5196)
+
+commit dae6769d9767e2e47f2fe451d9c796dd07d0ae29
+Author: zhihaoy <43971430+zhihaoy@users.noreply.github.com>
+Date:   Thu Jan 13 14:03:25 2022 -0800
+
+    [func.memfn] Correct target object by fixing typo (#5202)
+
+commit 5f830f97829965cf791dfe6eef6b84d6283712be
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Nov 24 22:04:55 2021 +0100
+
+    [lib] Add 'namespace std' wrappings around class definitions
+
+    Those were missing in a few places, notably [rand].
+
+    Also add an automated check.
+
+commit 1031a409dfacb84b9871b16502c73e15249160eb
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Nov 19 23:02:19 2021 +0100
+
+    [chrono.syn] Use nested namespace definitions for clarity
+
+commit dad631ac4bd30e7ab6de5a888f77ed2b5b44c17d
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Nov 6 09:39:55 2021 +0100
+
+    [except.throw,except.handle] Move lvalue specification for copies
+
+commit c6e5eea4f11efec62a4718acd4eb17fb99fd4899
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Oct 25 23:41:31 2021 +0200
+
+    [expr.prim.req.general] Change requirement-seq to right-recursive
+
+    consistent with the specification of other -seq non-terminals.
+
+commit 872fce6effc603735c9717981807eb6bb8b4f838
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Dec 4 11:33:32 2021 +0100
+
+    [associative.reqmts.general] Fix confusing local use of 'r'
+
+commit 3d1bf58b74860fc1e86cd1cf536b7022b90d688d
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Jan 7 20:26:15 2022 +0100
+
+    [temp.res.general] Clarify binding of names
+
+commit 4123264d22c7617d828083c9ad954b5541934621
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Oct 25 18:15:14 2021 +0200
+
+    [temp.constr.atomic] Fix phrasing in note
+
+commit 26ce304780d79bba03a791b2f4299f083f021238
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Dec 14 09:25:41 2021 +0100
+
+    [dcl.meaning.general] Clarify correspondence for block-scope friends
+
+commit 3c19e315dbb05a2c22b8f5b075af39a7572cdaa1
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 23 11:18:17 2021 +0100
+
+    [meta.rel] Avoid undefined term 'void types'
+
+commit 90d178d022c7d597629853ebc70262489e49d5e9
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Jan 14 19:46:15 2022 +0100
+
+    [class.default.ctor] Fix implicit invocation of default constructor  (#4026)
+
+    Initialization is fully specified in [dcl.init],
+    so turn the list of default-initialization cases
+    into a note and shorten it appropriately.
+
+commit e1bfc25c56c7ab303241f980fa00d7ae402e1f5c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Jul 5 23:51:41 2021 +0200
+
+    [stmt.return,class.{ctor,dtor}] Clarify no return operand
+
+    Highlight that constructors and destructors do not have a
+    return type and thus a return statement within a constructor
+    or destructor cannot have an operand.
+
+commit b345505b88b376d547220254fd858840efbfb937
+Author: Chuanqi Xu <yedeng.yd@linux.alibaba.com>
+Date:   Fri Jan 14 10:10:11 2022 +0800
+
+    [temp.param] Delete outdated wording at p15
+
+    The wording at [temp.param]/15 says:
+    > A template-parameter shall not be given default arguments by two
+    > different declarations if one is reachable from the other.
+
+    But it is conflicted with [basic.def.odr]/13:
+    > There can be more than one definition of a
+    > ...
+    >       default template argument
+    > ...
+    > in a program provided that each definition appears in a different
+    > translation unit and the definitions satisfy the [same-meaning
+    > criteria of the ODR].
+
+    [temp.param] should be deleted otherwise we couldn't modularize a real
+    project.
+
+commit fc9818bcdaa08f65c8d99f7df70b418810c36893
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Jan 15 09:43:55 2022 +0100
+
+    [util.smartptr.atomic] Add cross-reference to <memory> header (#5207)
+
+commit 5c59ede65b362afb418bda3cf82123ae2ca2553c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 23 11:36:39 2021 +0100
+
+    [locale.ctype.virtuals] Clarify do_widen parameter
+
+commit cec2d218209abf2979a3c7fabc9970d8677b9e63
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 23 12:53:01 2021 +0100
+
+    [diff.stmt] Properly refer to function return types
+
+    Also annotate the 'void' and 'int' keywords.
+
+commit ba9124e62ea85c922d501dfc52bc4d44c85933bd
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Jan 21 15:57:58 2022 +0000
+
+    [util.smartptr.atomic.general] Fix cross-reference to shared_ptr (#5222)
+
+commit 3cb2ee9d67360612e6361aa26d1805c8ed30c6e6
+Author: Chuanqi Xu <68680648+ChuanqiXu9@users.noreply.github.com>
+Date:   Sat Jan 22 17:43:22 2022 +0800
+
+    [temp.dep.general] add trailing 'or' (#5186)
+
+commit 4e2dbd25fa137f12c8fa6b960bc2db45be994414
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Jan 22 13:38:10 2022 +0100
+
+    [class.free] Move into [class.mem]
+
+    The class-specific allocation and deallocation functions,
+    whose declaration properties are specified in this section,
+    are class member functions.
+
+commit 7987ef93488842bbdbbd6e4de996f463939fe0e8
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Jan 22 13:45:23 2022 +0100
+
+    [class.free] Change subclause heading and add indexing
+
+    Rename the heading to "Allocation and deallocation functions",
+    which is more appropriate for the contents of the subclause.
+
+commit 07db0b3182495339b00221bba41549913e0a6a0e
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Jan 22 14:35:11 2022 +0100
+
+    [stacktrace] Move into [diagnostics]
+
+commit 0df02c99d04dd0e0d29ea520904ea64f69ea6c36
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Jan 20 19:42:09 2022 +0100
+
+    [class.mem.general] Add cross-reference for 'layout-compatible type'
+
+commit 2e5976f894d821e442a6f98c3e235381f8067570
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Jan 20 19:36:15 2022 +0100
+
+    [stmt.return] Clarify flowing off the end of a function
+
+commit 88541f7ad5de85389adb0e88f295091d29f00030
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Jan 25 23:12:55 2022 +0100
+
+    [range.req.general] Remove incorrect normative duplication for 'view' (#5235)
+
+commit 0539c5e2cdf7605c5704eb2b63916b6c5c3b9539
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Feb 18 13:42:57 2021 +0100
+
+    [macros,structure.specifications] Add 'Result' element
+
+commit 408a22b1b58207de4af28d59afd20156e715e35f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Jan 7 23:48:43 2021 +0100
+
+    [re.req] Replace requirements table with \itemdescr
+
+commit 93ff092d1cd2b335f372b9546365b3d495caf2d8
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Nov 14 20:05:03 2021 +0100
+
+    [container.requirements] Replace requirements tables with \itemdescr
+
+    and adjust cross-references to container requirements tables
+    throughout the standard library.
+
+commit 4b1a735f393aa5c864d0a5aba45514aec63f5a90
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Jun 27 11:26:39 2021 +0200
+
+    [container.requirements] Omit redundant specification
+
+    where "Effects: Equivalent to" wording is used.
+
+commit d37470de0392f032d96c85610c947918269532a9
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Feb 20 00:09:56 2022 +0100
+
+    [lex.name] Rephrase note to avoid upper/lower-case
+
+commit efd0cab6f2d11f29f205c15672108f6e20de6010
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Feb 20 14:28:36 2022 +0100
+
+    [lib] Add missing \pnum before descriptive elements
+
+    Also fix the ineffective check script by rewriting the
+    check in straightforward awk.
+
+commit ff92c80b70b9cd887512f96e5d5525c20550d12f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Feb 6 09:52:01 2022 +0100
+
+    [iterator.concept.winc] Remove duplicate paragraph
+
+    This fixes a bad merge between P2393R1 Cleaning up integer-class types
+    and P2321R2 zip.
+
+commit a4dfa1f0c46152d3a3399bc32a60fcf11edd4a5d
+Author: Chuanqi Xu <68680648+ChuanqiXu9@users.noreply.github.com>
+Date:   Mon Feb 21 07:18:41 2022 +0800
+
+    [module.interface] Add adjective 'exported' (#5290)
+
+    It was clear in context that "the declaration" is exported, but
+    it is easier to understand if we restate "an exported declaration".
+
+commit 90ef396f088a4e1730a3f73f3db44d9ad8b872b7
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Feb 1 13:58:38 2022 +0000
+
+    [fs.class.directory.iterator.general] Fix grammar
+
+commit 1155c4a361c446eee4602b7fd2e82eba7a4f8c4f
+Author: languagelawyer <language.lawyer@gmail.com>
+Date:   Sat Jan 22 23:27:49 2022 +0300
+
+    [temp.res] Move a note outside itemize environment
+
+commit 44c79f59de6c4ea179bacc698272d713e696b117
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Jan 29 09:37:59 2022 +0100
+
+    [derivation] Remove 'basic integral type' from footnote
+
+    Also switch footnote to note.
+
+commit 785b0a84e7b0f8108b5140f33494ceff3d0bd282
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 23 11:40:48 2021 +0100
+
+    [diff.expr] Replace 'will' with present tense
+
+    Also annotate the 'void' keyword.
+
+commit 97a72e1c4f1616f2163d34deafea010d68099a7c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Dec 5 21:22:48 2021 +0100
+
+    [temp.local] Fix type-name interpretation of injected-class-name
+
+commit a8e63922a5f049ab2c58a33117913688b8dc096a
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Feb 21 20:27:01 2022 +0800
+
+    [container.gen.reqmts] Replace "Value:" with "Returns:" (#5256)
+
+commit d267cde4fcc2c13ef87170d68f94f1ae6e499c23
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Feb 21 13:51:45 2022 +0100
+
+    [over.best.ics] Clarify phrasing around user-defined conversion sequence (#5086)
+
+    This replaces the use of "with" that is popular in mathematical writing
+    with a more common construction.
+
+commit 7424b45d8470b8765cdf3b25bcfd9a9a89c0c936
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Jan 3 22:24:23 2022 +0100
+
+    [expr] Cleanup for 'discarded-value expression'
+
+commit b5ce71b34217f9d974e96cc366984cbd5f4b71e6
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Dec 17 20:31:57 2021 +0100
+
+    [atomics] Harmonize references to atomics operations tables
+
+commit ef78018c8d61d79dc9cddc5f4b2d00a7929964fa
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Jan 21 23:01:25 2022 +0100
+
+    [std] Replace hyphen with period in labels
+
+    and add a check.
+
+commit 58ea575dd9b4a410dcf457b3357bef4a720e1608
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Jan 13 23:21:05 2022 +0100
+
+    [function.objects,ranges] Introduce labels for call wrappers
+
+    In particular, 'term.perfect.forwarding.call.wrapper'
+    and 'term.simple.call.wrapper', and refer to them.
+
+commit 0c53beacef2289e4cc4fabbdff99eb3b6c7ae4ad
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Jul 5 23:16:20 2021 +0200
+
+    [unique.ptr.single] Rephrase destruction
+
+commit 03b9040814ecd548f2de18668df0655ef7b37efb
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Tue Feb 22 09:39:37 2022 +0800
+
+    [version.syn] Remove mention of nonexistent header `<priority_queue>`
+
+commit 97430e8f867f5b97f79c8064c32dd1bde117198a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Nov 22 22:20:16 2021 +0100
+
+    [allocator.adaptor.members] Fix select_on_container_copy_construction
+
+    The description was confusing objects and types.
+
+commit 2cd31adb2033b4ae82339ef270bc058128cbd199
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 22:38:13 2022 +0100
+
+    [bit] Move into [utilities]
+
+commit e3532fd233355f93558f6a53d14b72e16a1f1ed2
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 22:44:52 2022 +0100
+
+    [memory] Create new clause
+
+    and move [memory], [smartptr], [mem.res], and [allocator.adaptor]
+    from [utilities] into the new clause.
+
+commit cb7b98d46c4603ccc485fe826fb4363cb2c039bf
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 22:48:10 2022 +0100
+
+    [comparisons.three.way,func.search] Add namespace around class definition
+
+commit 1daeb8e44b659c5cdf7133df68def1264c8b5774
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 22:54:01 2022 +0100
+
+    Move [string.view] to before [string.classes]
+
+commit 724e83e4d0cd82737952711d31505872188269ab
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 23:01:35 2022 +0100
+
+    [meta] Create new clause
+
+    and move [intseq], [meta], and [ratio] from [utilities] into the
+    new clause.
+
+commit af8334b94be2df5bf009ef7381460f56e6224c44
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 23:06:45 2022 +0100
+
+    [meta] Adjust cross-references
+
+commit d74c2170a9f4c928519461d7742293af2d141852
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 23 23:19:51 2022 +0100
+
+    Move [atomics] into [thread]
+
+    Rename [thread] to 'Concurrency support library'.
+
+commit 888602381e6c4e5fc886a7e575a95c905998b487
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Feb 24 11:35:19 2022 +0800
+
+    [headers] List <expected>
+
+commit aa2c64589cf2a784e9c551a2a54df59b880613d3
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Feb 24 15:09:08 2022 +0100
+
+    [thread] Rename to 'Concurrency support library'
+
+    Missed update with commit d74c2170a9f4c928519461d7742293af2d141852.
+
+commit 000d4c091a244b3bf81470c6c6a4f2f35c3ec602
+Author: hewillk <67143766+hewillk@users.noreply.github.com>
+Date:   Fri Feb 25 01:14:48 2022 +0800
+
+    [range.chunk.outer.value] Add missing private specifier
+
+commit 2901f3f6c00060e6c0a368efd28fd50ba07350f1
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Feb 25 23:38:49 2022 +0100
+
+    [diff.cpp20.library] Add subclause, highlighting new headers
+
+commit 1c88b6bdafb2eb128e7da05815f3b30fa52d3710
+Author: hewillk <67143766+hewillk@users.noreply.github.com>
+Date:   Sun Feb 27 21:23:40 2022 +0800
+
+    [range.slide.overview] Fix bad quotation marks for string-literal (#5326)
+
+commit dd346dcbd723ae27d6a2c2a74aad8a17a62ea687
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Mar 6 00:18:57 2022 +0100
+
+    [expr.const] Add cross-reference for construct_at
+
+commit 8679960561e6f18ca533915626cdd5ecd349bcf4
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Feb 27 22:22:30 2022 +0100
+
+    [allocator.requirements.general] Replace table for descriptive variables
+
+commit 0befc0e9f7e1df2451fa115b9ff12dbd8d384c5d
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Feb 27 23:59:42 2022 +0100
+
+    [allocator.requirements.general] Dismantle requirements table
+
+commit 4e4aa46276d1542b2f0ff66ebd0f66df8ba0d785
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Feb 28 00:17:47 2022 +0100
+
+    [lib] Fix cross-references to replaced table cpp17.allocator
+
+commit 2d8e11333fe4e188a940bc5c4e1a2f33b139ee3b
+Author: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+Date:   Mon Feb 21 14:49:31 2022 -0400
+
+    [array.overview] Don't mention swap as an exception
+
+    The container requirements already describe this behavior,
+    so from the POV of this subclause, there's no exception.
+
+commit 65e74383deb8bcc0cab8e813b6360e9b1e8f6b10
+Author: Johel Ernesto Guerrero Peña <johelegp@gmail.com>
+Date:   Mon Feb 21 14:52:15 2022 -0400
+
+    [array.overview] Mention condition of exception
+
diff --git a/papers/n4911.md b/papers/n4911.md new file mode 100644 index 0000000000..35188804ab --- /dev/null +++ b/papers/n4911.md @@ -0,0 +1,892 @@ +# N4911 Editors' Report -- Programming Languages -- C++ + +Date: 2022-03-17 + +Thomas Köppe (editor, Google DeepMind) +Jens Maurer (co-editor) +Dawn Perchik (co-editor, Bright Side Computing, LLC) +Richard Smith (co-editor, Google Inc) + +Email: `cxxeditor@gmail.com` + +## Acknowledgements + +Thanks to all those who have [submitted editorial +issues](https://github.com/cplusplus/draft/wiki/How-to-submit-an-editorial-issue) +and to those who have provided pull requests with fixes, and special thanks to +Johel Ernesto Guerrero Peña for providing in-depth review of most of the draft +motion applications. + +## New papers + + * [N4910](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4910.pdf) is the + current working draft for C++23. It replaces + [N4901](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4901.pdf). + * N4911 is this Editors' Report. + +## Motions incorporated into working draft + +### Core working group polls + +CWG poll 1: Accept as Defect Reports all issues _except issue 2502_ in +[P2533R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2533r0.html) +(Core Language Working Group "ready" Issues for the February, 2022 meeting) and +apply the proposed resolutions for all of the issues to the C++ working paper. + +CWG poll 2: Apply the changes in +[P2173R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2173r1.pdf) +(Attributes on Lambda-Expressions) to the C++ Working Paper. + +CWG poll 3: Apply the changes in +[P2493R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2493r0.html) +(Missing feature test macros for C++20 core papers) to the C++ Working Paper. + +### Library working group polls + +LWG poll 1: Apply the changes for all Tentatively Ready issues in +[P2531R0](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2531r0.html) (C++ +Standard Library Issues to be moved in Virtual Plenary, Feb. 2022) to the C++ +working paper. + +LWG poll 2: Apply the changes in +[P0323R12](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p0323r12.html) +(`std::expected`) to the C++ working paper. + +LWG poll 3: Apply the changes in +[P0533R9](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0533r9.pdf) +(constexpr for `` and ``) to the C++ working paper. + +LWG poll 4: Apply the changes in +[P0627R6](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0627r6.pdf) +(Function to mark unreachable code) to the C++ working paper. + +LWG poll 5: Apply the changes in +[P1206R7](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1206r7.pdf) +(ranges::to: A function to convert any range to a container) to the C++ working +paper. + +LWG poll 6: Apply the changes in +[P1413R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1413r3.pdf) +(Deprecate `std::aligned_storage` and `std::aligned_union`) to the C++ working +paper. + +LWG poll 7: Apply the changes in +[P2255R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2255r2.html) (A +type trait to detect reference binding to temporary) to the C++ working paper. + +LWG poll 8: Apply the changes in +[P2273R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2273r3.pdf) +(Making `std::unique_ptr` constexpr) to the C++ working paper. + +LWG poll 9: Apply the changes in +[P2387R3](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2387r3.html) +(Pipe support for user-defined range adaptors) to the C++ working paper. + +LWG poll 10: Apply the changes in +[P2440R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2440r1.html) +(`ranges::iota`, `ranges::shift_left` and `ranges::shift_right`) to the C++ +working paper. + +LWG poll 11: Apply the changes in +[P2441R2](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2441r2.html) +(`views::join_with`) to the C++ working paper. + +LWG poll 12: Apply the changes in +[P2442R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2442r1.html) +(Windowing range adaptors: `views::chunk` and `views::slide`) to the C++ working +paper. + +LWG poll 13: Apply the changes in +[P2443R1](http://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2443r1.html) +(`views::chunk_by`) to the C++ working paper. + +## Editorial changes + +### Notes on motions + +* **Poll CWG-2:** The wording was adjusted to integrate with the new wording + from issue + [CWG-2509](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2533r0.html#2509) + to use the new term _lambda-specifier-seq_ instead of the original + _decl-specifier-seq_. + +* **Poll LWG-1:** Issue + [LWG-3616](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2531r0.html#3616) + was skipped, since it had already been [applied + editorially](https://github.com/cplusplus/draft/commit/8753efabbbfec8371a82de1af60337fa6a6b6dc2). + +* **Poll LWG-8:** The wording was integrated with the resolution of + [LWG-3632](http://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2531r0.html#3632). + +### Clause reorganization + +We rearranged several clauses and subclauses. Over the years, the original +clause structure had been becoming less appropriate for the growing amount of +content, and we hope that the new structure is more suitable to the current (and +anticipated future) content. + +* New top-level clause "Memory management library [mem]", after [diagnostics]. + This clause contains ``, memory parts of ``, smart pointers, + memory resources, and scoped allocators, previously part of [utilities]. + +* The "Metaprogramming library [meta]" subclause from [utilities] is now a + new top-level clause, in between [mem] and [utilities]. We expect future + reflection material to be added to this clause. + +* The "Atomic operations [atomics]" clause has been integrated into the + top-level [thread] clause, which has been renamed to "Concurrency support + library [thread]". + +* "Bit manipulation [bit]" has been moved to the end of the [utilities] clause. + +* "Stacktrace [stacktrace]" has been moved to the end of the [diagnostics] clause. + +* "String view classes [string.view]" has been moved to immediately before + [string.classes]. + +* "Allocation and deallocation functions [class.free]" has been moved to + immediately before [class.nest]. + +We are aiming to not change the top-level clause structure more than once per +standard publication cycle. We have had suggestions to create a new top-level +clause "Text" for text-related content (such as locales and regular expressions, +but also anticipating new material). We have not yet reached consensus, and we +will probably perform that reorganization during the C++26 cycle. + +### Requirements tables + +We have begun replacing the large requirements tables in the library with more +conventional paragraphs, as described in editorial paper +[P2416R2](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2416r2.pdf). +Each requirement is now presented in a style similar to that of function +declarations, followed by as many specification elements as appropriate. A new +"_Result_:" element has been added to capture the type of a type requirement, +and the type and value category of an expression requirement. + +We have applied these changes to the container, allocator, and regular +expression trait requirements. + +### Term labels + +We have started introducing explicit LaTeX labels for defined terms, and we have +updated cross references to refer to those term labels instead of the label of +the subclause that contains the term. This does not change the presentation of +the reference, but makes it less likely that cross references are invalidated by +moving text around. + +In the future, we might extend this to turn the use of a term into a hyperlink +to the page on which the term's definition appears. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4901 is below. This +list excludes changes that do not affect the body text or only affect whitespace +or typeface. For a complete list including such changes (or for the actual +deltas applied by these changes), consult the [draft sources on +github](https://github.com/cplusplus/draft/compare/n4901...n4910). + + commit 04e0ea7074c9b0d0ca939821ce0f575c589df6b7 + Author: Jens Maurer + Date: Thu Oct 21 23:52:55 2021 +0200 + + [pairs.pair] Use T1/T2, not first_type/second_type + + commit ed6e1b5da5d13449cf27c878c60e90892289f98a + Author: Jens Maurer + Date: Sat Oct 23 01:20:31 2021 +0200 + + [index] Fix dangling 'see' references + + Also update the automatic check script to prevent + further occurrences. + + commit 3d1424716844aef59891d770709e19d83b5bea35 + Author: Jens Maurer + Date: Sun Oct 24 22:05:40 2021 +0200 + + [ranges] Remove \expos markers for nested types (#4829) + + An \expos marker should appear only on the first + declaration of a name. + + commit 741c20794fdc7aec28afcd9e6c52d6d184d2845c + Author: Jens Maurer + Date: Tue Oct 26 16:36:39 2021 +0200 + + [class.copy.assign] Fix phrasing in note to avoid 'could'. (#4418) + + commit f3ab334c789ac89d2f6baf501d60716278cb8fa3 + Author: Jens Maurer + Date: Sun Jul 4 23:30:42 2021 +0200 + + [contents] Add special lookup treatment for swap + + commit 280684c7824b6b7f62c003b909ccf3703d82681b + Author: Johel Ernesto Guerrero Peña + Date: Mon Nov 8 07:19:14 2021 -0400 + + [defs] Update introduction to match ISO Directives (#5096) + + Reference: https://www.iso.org/sites/directives/current/part2/index.xhtml#_idTextAnchor218 + + commit 1567c481e3ca3c52f80e4a33db0f913ce1392c4d + Author: Jonathan Wakely + Date: Tue Nov 9 09:31:08 2021 +0000 + + [intro.refs] Update dated reference to previous POSIX standard + + Fixes #5098 + + commit c8ec4ab45f58e3a16d8dcb12bd660dd2cf6e936a + Author: Jens Maurer + Date: Tue Nov 23 17:22:38 2021 +0100 + + [refwrap.general] Add cross-references to the class synopsis (#5122) + + Also rename [refwrap.const], because it does not specify + any destructors. + + commit b4bf594c81865f892bae81342ffb67c8ca8adb74 + Author: Jens Maurer + Date: Tue Nov 23 17:24:35 2021 +0100 + + [smartptr] Rework subclause nesting (#5119) + + commit d0cb462d511e5c9bf1ae7403c275f7c1ccf2543d + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Sat Nov 20 02:16:40 2021 +0800 + + [range.adjacent.overview] Fix multi-character in example + + commit 26f6a1f7573ea54ed93b4e90d0e487fe39d44b87 + Author: Jens Maurer + Date: Sat Nov 13 10:01:36 2021 +0100 + + [dcl.typedef] Add explanation for lookup failure in example + + commit c63e5e836e8dbe0ae6c7ebc1b2a1b1534d37a220 + Author: Jens Maurer + Date: Wed Nov 10 23:40:48 2021 +0100 + + [input.output] Fix headings of 'assign and swap' subclauses + + commit d2699e5de0c10085df309074d2dfbc57d5bc86bb + Author: Jens Maurer + Date: Wed Oct 27 21:20:02 2021 +0200 + + [std] Replace 'OK:' in code comments with 'OK,' + + In contrast to errors, which use a colon, an OK comment + is not followed by any unique reason why the code is + well-formed, but by a subjective highlighting of a fact. + + commit 5e3f1ad0ceb89feb2977a0531422bcbe9ab8fba7 + Author: Jens Maurer + Date: Tue Oct 26 21:49:15 2021 +0200 + + [stdatomic.h.syn] Fix missing \expos + + and augment the autmatic checks accordingly. + + commit 16e60c63ad14f3f3fc9132a8443421a15ebec8fc + Author: Jens Maurer + Date: Tue Nov 9 13:09:27 2021 +0100 + + [locale.time.get] Replace 'ISO/IEC 9945' with 'POSIX' + + We introduce POSIX as an alias for ISO/IEC 9945, and we use 'POSIX' + everywhere else. + + commit 31c32e035770797eedc69f150c3a3484bbe828a5 + Author: Jens Maurer + Date: Tue Nov 9 17:54:18 2021 +0100 + + [locale.time.get.virtuals] Use 'conversion specification' + + POSIX does not define the term 'conversion directive'. + + commit fbab3f13719c34affdb7b712aed7f6d2313570d7 + Author: languagelawyer <38548419+languagelawyer@users.noreply.github.com> + Date: Tue Nov 23 20:03:13 2021 +0300 + + [defns.access, basic.lval] Clarify what can be accessed and how (#4777) + + commit 5475bdab828b3585a21172945303ccebbcefb516 + Author: Jens Maurer + Date: Thu Oct 21 22:11:07 2021 +0200 + + [c.mb.wcs] mbrtoc8 stores code units, not characters + + commit ba4bb3ee56b94b63d0d1e5914a136a04b1620052 + Author: mordante + Date: Tue Nov 23 18:13:22 2021 +0100 + + [format.functions] Add "std::move" around "out" (#5069) + + This fixes a misapplication of the resolution of LWG 3539. + + commit 0d0ec1a1393b3baae564234007c94b80da9bab48 + Author: Jens Maurer + Date: Tue Nov 23 18:15:55 2021 +0100 + + [func.wrap.{func.general, move.class}] Remove 'first-class object' (#5067) + + The term is undefined and does not improve the specification. + + commit d27c3b388befadc4c35aac1d12f0ba8581f14a5f + Author: Jonathan Wakely + Date: Fri Nov 12 14:29:00 2021 +0000 + + [spanstream.ctor] Fix base class name in effects + + commit c1935504da840995b1bb60eba536cb12bca5ae71 + Author: timsong-cpp + Date: Tue Nov 23 11:51:37 2021 -0600 + + [basic.start.main] Remove redundant phrase (#5083) + + commit 70eb0406596b4f4e3d97ed50b3fd6d93b3032d18 + Author: Jens Maurer + Date: Mon Oct 25 23:57:58 2021 +0200 + + [basic.start.main] Avoid implementation guidance in a note + + commit ac8d6611a739c64eda4a7062f2cb83f770cd8a53 + Author: Jens Maurer + Date: Mon Oct 25 23:58:08 2021 +0200 + + [dcl.link] Avoid implementation guidance in a note + + commit 2ad67aefe350017c4e9403ba2015af683813787f + Author: Jens Maurer + Date: Sat Nov 6 22:08:47 2021 +0100 + + [lex] Remove Unicode character name abbreviations + + They are not part of the character name or alias. + The presentation in ISO 10646 is misleading, though. + + commit 29c89b16e92cd03a76eb2a19866e683a7bb7ac80 + Author: Jens Maurer + Date: Sat Nov 6 22:15:05 2021 +0100 + + [lex] Rename U+0007 BELL to ALERT + + The former is ambiguous with U+1F514 BELL. + The ALERT alias is defined in UCD NameAliases.txt. + + commit 408623b7d8f0efd77403d1d0142d9bd59d1cfe55 + Author: Jens Maurer + Date: Sat Dec 4 11:19:54 2021 +0100 + + [associative.reqmts.general] Fix typo: 'kx', not 'rx' (#5136) + + commit f03473cd1e32691c105260e65dd534960cf9db21 + Author: Neven Sajko + Date: Sun Dec 5 21:19:00 2021 +0100 + + [over.sub] Fix typo: change oeprator to operator (#5140) + + commit c69a35501174f5ab5d3f13f12186cc9b1fcd40dd + Author: Jens Maurer + Date: Tue Dec 14 11:24:04 2021 +0100 + + [range.access] Fix cross-references for 'array' (#5147) + + Also introduce a label 'term.array.type' in [dcl.array]. + + commit 7a09dddd036359a10cf10b8e7d80c8edd8c76817 + Author: Jens Maurer + Date: Thu Dec 16 19:39:18 2021 +0100 + + [basic.fundamental] Excise normative requirements on std::numeric_limits (#5105) + + commit c2617432eac3313abd2134a26e2d8a1d925dfd15 + Author: Casey Carter + Date: Thu Dec 16 23:53:17 2021 -0800 + + [depr.default.allocator] Index allocator::is_always_equal here (#5152) + + LWG3170 deprecated `allocator::is_always_equal`. We moved it to Annex D, but left the index entry behind. + + commit 28effaea15ef697f5a64fba47b9c095c9fbfe82a + Author: Jens Maurer + Date: Sun Dec 19 22:16:18 2021 +0100 + + [ptr.align,re.regiter.incr] Replace 'compiler' with 'implementation' + + commit 575b9a99062de34cc44bc45aeb459f32aa12b98f + Author: Jens Maurer + Date: Sun Dec 19 22:19:19 2021 +0100 + + [smartptr.adapt] Emphasize that casting might not always be viable + + commit 9ba8e0329a0f5db15544c31c514ff44e0003f08f + Author: frederick-vs-ja + Date: Tue Jan 11 23:29:26 2022 +0800 + + [pairs.pair] Add missing _v for type traits (#5196) + + commit dae6769d9767e2e47f2fe451d9c796dd07d0ae29 + Author: zhihaoy <43971430+zhihaoy@users.noreply.github.com> + Date: Thu Jan 13 14:03:25 2022 -0800 + + [func.memfn] Correct target object by fixing typo (#5202) + + commit 5f830f97829965cf791dfe6eef6b84d6283712be + Author: Jens Maurer + Date: Wed Nov 24 22:04:55 2021 +0100 + + [lib] Add 'namespace std' wrappings around class definitions + + Those were missing in a few places, notably [rand]. + + Also add an automated check. + + commit 1031a409dfacb84b9871b16502c73e15249160eb + Author: Jens Maurer + Date: Fri Nov 19 23:02:19 2021 +0100 + + [chrono.syn] Use nested namespace definitions for clarity + + commit dad631ac4bd30e7ab6de5a888f77ed2b5b44c17d + Author: Jens Maurer + Date: Sat Nov 6 09:39:55 2021 +0100 + + [except.throw,except.handle] Move lvalue specification for copies + + commit c6e5eea4f11efec62a4718acd4eb17fb99fd4899 + Author: Jens Maurer + Date: Mon Oct 25 23:41:31 2021 +0200 + + [expr.prim.req.general] Change requirement-seq to right-recursive + + consistent with the specification of other -seq non-terminals. + + commit 872fce6effc603735c9717981807eb6bb8b4f838 + Author: Jens Maurer + Date: Sat Dec 4 11:33:32 2021 +0100 + + [associative.reqmts.general] Fix confusing local use of 'r' + + commit 3d1bf58b74860fc1e86cd1cf536b7022b90d688d + Author: Jens Maurer + Date: Fri Jan 7 20:26:15 2022 +0100 + + [temp.res.general] Clarify binding of names + + commit 4123264d22c7617d828083c9ad954b5541934621 + Author: Jens Maurer + Date: Mon Oct 25 18:15:14 2021 +0200 + + [temp.constr.atomic] Fix phrasing in note + + commit 26ce304780d79bba03a791b2f4299f083f021238 + Author: Jens Maurer + Date: Tue Dec 14 09:25:41 2021 +0100 + + [dcl.meaning.general] Clarify correspondence for block-scope friends + + commit 3c19e315dbb05a2c22b8f5b075af39a7572cdaa1 + Author: Jens Maurer + Date: Thu Dec 23 11:18:17 2021 +0100 + + [meta.rel] Avoid undefined term 'void types' + + commit 90d178d022c7d597629853ebc70262489e49d5e9 + Author: Jens Maurer + Date: Fri Jan 14 19:46:15 2022 +0100 + + [class.default.ctor] Fix implicit invocation of default constructor (#4026) + + Initialization is fully specified in [dcl.init], + so turn the list of default-initialization cases + into a note and shorten it appropriately. + + commit e1bfc25c56c7ab303241f980fa00d7ae402e1f5c + Author: Jens Maurer + Date: Mon Jul 5 23:51:41 2021 +0200 + + [stmt.return,class.{ctor,dtor}] Clarify no return operand + + Highlight that constructors and destructors do not have a + return type and thus a return statement within a constructor + or destructor cannot have an operand. + + commit b345505b88b376d547220254fd858840efbfb937 + Author: Chuanqi Xu + Date: Fri Jan 14 10:10:11 2022 +0800 + + [temp.param] Delete outdated wording at p15 + + The wording at [temp.param]/15 says: + > A template-parameter shall not be given default arguments by two + > different declarations if one is reachable from the other. + + But it is conflicted with [basic.def.odr]/13: + > There can be more than one definition of a + > ... + > default template argument + > ... + > in a program provided that each definition appears in a different + > translation unit and the definitions satisfy the [same-meaning + > criteria of the ODR]. + + [temp.param] should be deleted otherwise we couldn't modularize a real + project. + + commit fc9818bcdaa08f65c8d99f7df70b418810c36893 + Author: Jens Maurer + Date: Sat Jan 15 09:43:55 2022 +0100 + + [util.smartptr.atomic] Add cross-reference to header (#5207) + + commit 5c59ede65b362afb418bda3cf82123ae2ca2553c + Author: Jens Maurer + Date: Thu Dec 23 11:36:39 2021 +0100 + + [locale.ctype.virtuals] Clarify do_widen parameter + + commit cec2d218209abf2979a3c7fabc9970d8677b9e63 + Author: Jens Maurer + Date: Thu Dec 23 12:53:01 2021 +0100 + + [diff.stmt] Properly refer to function return types + + Also annotate the 'void' and 'int' keywords. + + commit ba9124e62ea85c922d501dfc52bc4d44c85933bd + Author: Jonathan Wakely + Date: Fri Jan 21 15:57:58 2022 +0000 + + [util.smartptr.atomic.general] Fix cross-reference to shared_ptr (#5222) + + commit 3cb2ee9d67360612e6361aa26d1805c8ed30c6e6 + Author: Chuanqi Xu <68680648+ChuanqiXu9@users.noreply.github.com> + Date: Sat Jan 22 17:43:22 2022 +0800 + + [temp.dep.general] add trailing 'or' (#5186) + + commit 4e2dbd25fa137f12c8fa6b960bc2db45be994414 + Author: Jens Maurer + Date: Sat Jan 22 13:38:10 2022 +0100 + + [class.free] Move into [class.mem] + + The class-specific allocation and deallocation functions, + whose declaration properties are specified in this section, + are class member functions. + + commit 7987ef93488842bbdbbd6e4de996f463939fe0e8 + Author: Jens Maurer + Date: Sat Jan 22 13:45:23 2022 +0100 + + [class.free] Change subclause heading and add indexing + + Rename the heading to "Allocation and deallocation functions", + which is more appropriate for the contents of the subclause. + + commit 07db0b3182495339b00221bba41549913e0a6a0e + Author: Jens Maurer + Date: Sat Jan 22 14:35:11 2022 +0100 + + [stacktrace] Move into [diagnostics] + + commit 0df02c99d04dd0e0d29ea520904ea64f69ea6c36 + Author: Jens Maurer + Date: Thu Jan 20 19:42:09 2022 +0100 + + [class.mem.general] Add cross-reference for 'layout-compatible type' + + commit 2e5976f894d821e442a6f98c3e235381f8067570 + Author: Jens Maurer + Date: Thu Jan 20 19:36:15 2022 +0100 + + [stmt.return] Clarify flowing off the end of a function + + commit 88541f7ad5de85389adb0e88f295091d29f00030 + Author: Jens Maurer + Date: Tue Jan 25 23:12:55 2022 +0100 + + [range.req.general] Remove incorrect normative duplication for 'view' (#5235) + + commit 0539c5e2cdf7605c5704eb2b63916b6c5c3b9539 + Author: Jens Maurer + Date: Thu Feb 18 13:42:57 2021 +0100 + + [macros,structure.specifications] Add 'Result' element + + commit 408a22b1b58207de4af28d59afd20156e715e35f + Author: Jens Maurer + Date: Thu Jan 7 23:48:43 2021 +0100 + + [re.req] Replace requirements table with \itemdescr + + commit 93ff092d1cd2b335f372b9546365b3d495caf2d8 + Author: Jens Maurer + Date: Sun Nov 14 20:05:03 2021 +0100 + + [container.requirements] Replace requirements tables with \itemdescr + + and adjust cross-references to container requirements tables + throughout the standard library. + + commit 4b1a735f393aa5c864d0a5aba45514aec63f5a90 + Author: Jens Maurer + Date: Sun Jun 27 11:26:39 2021 +0200 + + [container.requirements] Omit redundant specification + + where "Effects: Equivalent to" wording is used. + + commit d37470de0392f032d96c85610c947918269532a9 + Author: Jens Maurer + Date: Sun Feb 20 00:09:56 2022 +0100 + + [lex.name] Rephrase note to avoid upper/lower-case + + commit efd0cab6f2d11f29f205c15672108f6e20de6010 + Author: Jens Maurer + Date: Sun Feb 20 14:28:36 2022 +0100 + + [lib] Add missing \pnum before descriptive elements + + Also fix the ineffective check script by rewriting the + check in straightforward awk. + + commit ff92c80b70b9cd887512f96e5d5525c20550d12f + Author: Jens Maurer + Date: Sun Feb 6 09:52:01 2022 +0100 + + [iterator.concept.winc] Remove duplicate paragraph + + This fixes a bad merge between P2393R1 Cleaning up integer-class types + and P2321R2 zip. + + commit a4dfa1f0c46152d3a3399bc32a60fcf11edd4a5d + Author: Chuanqi Xu <68680648+ChuanqiXu9@users.noreply.github.com> + Date: Mon Feb 21 07:18:41 2022 +0800 + + [module.interface] Add adjective 'exported' (#5290) + + It was clear in context that "the declaration" is exported, but + it is easier to understand if we restate "an exported declaration". + + commit 90ef396f088a4e1730a3f73f3db44d9ad8b872b7 + Author: Jonathan Wakely + Date: Tue Feb 1 13:58:38 2022 +0000 + + [fs.class.directory.iterator.general] Fix grammar + + commit 1155c4a361c446eee4602b7fd2e82eba7a4f8c4f + Author: languagelawyer + Date: Sat Jan 22 23:27:49 2022 +0300 + + [temp.res] Move a note outside itemize environment + + commit 44c79f59de6c4ea179bacc698272d713e696b117 + Author: Jens Maurer + Date: Sat Jan 29 09:37:59 2022 +0100 + + [derivation] Remove 'basic integral type' from footnote + + Also switch footnote to note. + + commit 785b0a84e7b0f8108b5140f33494ceff3d0bd282 + Author: Jens Maurer + Date: Thu Dec 23 11:40:48 2021 +0100 + + [diff.expr] Replace 'will' with present tense + + Also annotate the 'void' keyword. + + commit 97a72e1c4f1616f2163d34deafea010d68099a7c + Author: Jens Maurer + Date: Sun Dec 5 21:22:48 2021 +0100 + + [temp.local] Fix type-name interpretation of injected-class-name + + commit a8e63922a5f049ab2c58a33117913688b8dc096a + Author: A. Jiang + Date: Mon Feb 21 20:27:01 2022 +0800 + + [container.gen.reqmts] Replace "Value:" with "Returns:" (#5256) + + commit d267cde4fcc2c13ef87170d68f94f1ae6e499c23 + Author: Jens Maurer + Date: Mon Feb 21 13:51:45 2022 +0100 + + [over.best.ics] Clarify phrasing around user-defined conversion sequence (#5086) + + This replaces the use of "with" that is popular in mathematical writing + with a more common construction. + + commit 7424b45d8470b8765cdf3b25bcfd9a9a89c0c936 + Author: Jens Maurer + Date: Mon Jan 3 22:24:23 2022 +0100 + + [expr] Cleanup for 'discarded-value expression' + + commit b5ce71b34217f9d974e96cc366984cbd5f4b71e6 + Author: Jens Maurer + Date: Fri Dec 17 20:31:57 2021 +0100 + + [atomics] Harmonize references to atomics operations tables + + commit ef78018c8d61d79dc9cddc5f4b2d00a7929964fa + Author: Jens Maurer + Date: Fri Jan 21 23:01:25 2022 +0100 + + [std] Replace hyphen with period in labels + + and add a check. + + commit 58ea575dd9b4a410dcf457b3357bef4a720e1608 + Author: Jens Maurer + Date: Thu Jan 13 23:21:05 2022 +0100 + + [function.objects,ranges] Introduce labels for call wrappers + + In particular, 'term.perfect.forwarding.call.wrapper' + and 'term.simple.call.wrapper', and refer to them. + + commit 0c53beacef2289e4cc4fabbdff99eb3b6c7ae4ad + Author: Jens Maurer + Date: Mon Jul 5 23:16:20 2021 +0200 + + [unique.ptr.single] Rephrase destruction + + commit 03b9040814ecd548f2de18668df0655ef7b37efb + Author: S. B. Tam + Date: Tue Feb 22 09:39:37 2022 +0800 + + [version.syn] Remove mention of nonexistent header `` + + commit 97430e8f867f5b97f79c8064c32dd1bde117198a + Author: Jens Maurer + Date: Mon Nov 22 22:20:16 2021 +0100 + + [allocator.adaptor.members] Fix select_on_container_copy_construction + + The description was confusing objects and types. + + commit 2cd31adb2033b4ae82339ef270bc058128cbd199 + Author: Jens Maurer + Date: Wed Feb 23 22:38:13 2022 +0100 + + [bit] Move into [utilities] + + commit e3532fd233355f93558f6a53d14b72e16a1f1ed2 + Author: Jens Maurer + Date: Wed Feb 23 22:44:52 2022 +0100 + + [memory] Create new clause + + and move [memory], [smartptr], [mem.res], and [allocator.adaptor] + from [utilities] into the new clause. + + commit cb7b98d46c4603ccc485fe826fb4363cb2c039bf + Author: Jens Maurer + Date: Wed Feb 23 22:48:10 2022 +0100 + + [comparisons.three.way,func.search] Add namespace around class definition + + commit 1daeb8e44b659c5cdf7133df68def1264c8b5774 + Author: Jens Maurer + Date: Wed Feb 23 22:54:01 2022 +0100 + + Move [string.view] to before [string.classes] + + commit 724e83e4d0cd82737952711d31505872188269ab + Author: Jens Maurer + Date: Wed Feb 23 23:01:35 2022 +0100 + + [meta] Create new clause + + and move [intseq], [meta], and [ratio] from [utilities] into the + new clause. + + commit af8334b94be2df5bf009ef7381460f56e6224c44 + Author: Jens Maurer + Date: Wed Feb 23 23:06:45 2022 +0100 + + [meta] Adjust cross-references + + commit d74c2170a9f4c928519461d7742293af2d141852 + Author: Jens Maurer + Date: Wed Feb 23 23:19:51 2022 +0100 + + Move [atomics] into [thread] + + Rename [thread] to 'Concurrency support library'. + + commit 888602381e6c4e5fc886a7e575a95c905998b487 + Author: A. Jiang + Date: Thu Feb 24 11:35:19 2022 +0800 + + [headers] List + + commit aa2c64589cf2a784e9c551a2a54df59b880613d3 + Author: Jens Maurer + Date: Thu Feb 24 15:09:08 2022 +0100 + + [thread] Rename to 'Concurrency support library' + + Missed update with commit d74c2170a9f4c928519461d7742293af2d141852. + + commit 000d4c091a244b3bf81470c6c6a4f2f35c3ec602 + Author: hewillk <67143766+hewillk@users.noreply.github.com> + Date: Fri Feb 25 01:14:48 2022 +0800 + + [range.chunk.outer.value] Add missing private specifier + + commit 2901f3f6c00060e6c0a368efd28fd50ba07350f1 + Author: Jens Maurer + Date: Fri Feb 25 23:38:49 2022 +0100 + + [diff.cpp20.library] Add subclause, highlighting new headers + + commit 1c88b6bdafb2eb128e7da05815f3b30fa52d3710 + Author: hewillk <67143766+hewillk@users.noreply.github.com> + Date: Sun Feb 27 21:23:40 2022 +0800 + + [range.slide.overview] Fix bad quotation marks for string-literal (#5326) + + commit dd346dcbd723ae27d6a2c2a74aad8a17a62ea687 + Author: Jens Maurer + Date: Sun Mar 6 00:18:57 2022 +0100 + + [expr.const] Add cross-reference for construct_at + + commit 8679960561e6f18ca533915626cdd5ecd349bcf4 + Author: Jens Maurer + Date: Sun Feb 27 22:22:30 2022 +0100 + + [allocator.requirements.general] Replace table for descriptive variables + + commit 0befc0e9f7e1df2451fa115b9ff12dbd8d384c5d + Author: Jens Maurer + Date: Sun Feb 27 23:59:42 2022 +0100 + + [allocator.requirements.general] Dismantle requirements table + + commit 4e4aa46276d1542b2f0ff66ebd0f66df8ba0d785 + Author: Jens Maurer + Date: Mon Feb 28 00:17:47 2022 +0100 + + [lib] Fix cross-references to replaced table cpp17.allocator + + commit 2d8e11333fe4e188a940bc5c4e1a2f33b139ee3b + Author: Johel Ernesto Guerrero Peña + Date: Mon Feb 21 14:49:31 2022 -0400 + + [array.overview] Don't mention swap as an exception + + The container requirements already describe this behavior, + so from the POV of this subclause, there's no exception. + + commit 65e74383deb8bcc0cab8e813b6360e9b1e8f6b10 + Author: Johel Ernesto Guerrero Peña + Date: Mon Feb 21 14:52:15 2022 -0400 + + [array.overview] Mention condition of exception diff --git a/papers/wd-index.md b/papers/wd-index.md index 675cf0c61b..5b3d4dee1e 100644 --- a/papers/wd-index.md +++ b/papers/wd-index.md @@ -38,5 +38,6 @@ * [N4868](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4868.pdf) 2020-10 C++ Working Draft * [N4878](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4878.pdf) 2020-12 C++ Working Draft * [N4885](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4885.pdf) 2021-03 C++ Working Draft - * [N4892](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4892.pdf) 2021-03 C++ Working Draft - * [N4901](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4901.pdf) 2021-03 C++ Working Draft + * [N4892](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4892.pdf) 2021-06 C++ Working Draft + * [N4901](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4901.pdf) 2021-10 C++ Working Draft + * [N4910](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4910.pdf) 2022-03 C++ Working Draft diff --git a/source/config.tex b/source/config.tex index 556faf904a..5f56bc933e 100644 --- a/source/config.tex +++ b/source/config.tex @@ -1,7 +1,7 @@ %!TEX root = std.tex %%-------------------------------------------------- %% Version numbers -\newcommand{\docno}{Dxxxx} +\newcommand{\docno}{N4910} \newcommand{\prevdocno}{N4901} \newcommand{\cppver}{202002L}