diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index f3d4a5f770..e6fa6d7203 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -17,57 +17,56 @@ jobs: strategy: matrix: cfg: - - { name: 'Linux', os: 'ubuntu-22.04' } - - { name: 'MacOS', os: 'macos-13' } + - { name: 'Linux', os: 'ubuntu-24.04' } + - { name: 'MacOS', os: 'macos-15' } steps: - name: checkout uses: actions/checkout@v4 - name: install GNU tools - if: matrix.cfg.os == 'macos-13' + if: matrix.cfg.os == 'macos-15' run: | brew install gnu-sed - echo "/usr/local/opt/gnu-sed/libexec/gnubin" >> ${GITHUB_PATH} + echo "/opt/homebrew/opt/gnu-sed/libexec/gnubin" >> ${GITHUB_PATH} - name: check-source.sh run: ../tools/check-source.sh - name: update brew - if: matrix.cfg.os == 'macos-13' - run: | - brew update + if: matrix.cfg.os == 'macos-15' + run: brew update - name: update-apt-cache - if: matrix.cfg.os == 'ubuntu-22.04' + if: matrix.cfg.os == 'ubuntu-24.04' run: sudo apt-get update - name: install (Linux) - if: matrix.cfg.os == 'ubuntu-22.04' + if: matrix.cfg.os == 'ubuntu-24.04' run: sudo apt-get install latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended lmodern - name: install (MacOS) - if: matrix.cfg.os == 'macos-13' + if: matrix.cfg.os == 'macos-15' run: | brew install basictex eval "$(/usr/libexec/path_helper)" echo "PATH=${PATH}" >> ${GITHUB_ENV} sudo tlmgr update --self - sudo tlmgr install latexmk isodate substr relsize ulem fixme rsfs extract layouts enumitem l3packages l3kernel imakeidx splitindex xstring + sudo tlmgr install latexmk isodate substr relsize ulem fixme rsfs environ layouts enumitem l3packages l3kernel imakeidx splitindex xstring - name: make (Linux) - if: matrix.cfg.os == 'ubuntu-22.04' + if: matrix.cfg.os == 'ubuntu-24.04' run: make quiet - name: make (MacOS) - if: matrix.cfg.os == 'macos-13' + if: matrix.cfg.os == 'macos-15' run: make full - name: check-output.sh run: ../tools/check-output.sh - name: upload PDF - if: matrix.cfg.os == 'ubuntu-22.04' + if: matrix.cfg.os == 'ubuntu-24.04' uses: actions/upload-artifact@v4 with: name: draft-snapshot diff --git a/.gitignore b/.gitignore index bcaa1569dd..9286aae13e 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ std-gram.ext tools/sections *.synctex.gz *.synctex* +.check.stamp diff --git a/.gitorder b/.gitorder index abebabaa77..edc39fbf98 100644 --- a/.gitorder +++ b/.gitorder @@ -5,6 +5,7 @@ source/macros.tex source/tables.tex source/cover-*.tex source/front.tex +source/preface.tex source/intro.tex source/lex.tex source/basic.tex @@ -21,22 +22,24 @@ source/lib-intro.tex source/support.tex source/concepts.tex source/diagnostics.tex +source/memory.tex +source/meta.tex source/utilities.tex -source/strings.tex source/containers.tex source/iterators.tex source/ranges.tex source/algorithms.tex +source/strings.tex +source/text.tex source/numerics.tex source/time.tex -source/locales.tex source/iostreams.tex -source/regex.tex -source/atomics.tex source/threads.tex +source/exec.tex source/grammar.tex source/limits.tex source/compatibility.tex source/future.tex +source/uax31.tex source/back.tex source/xrefdelta.tex diff --git a/README.rst b/README.rst index 4ab1c20b2d..c737a81a71 100644 --- a/README.rst +++ b/README.rst @@ -22,7 +22,7 @@ Getting Started on Mac OS X Install the `MacTeX distribution `_. If you are on a slow network, you'll want to get the `BasicTeX package `_ instead, -then run the following command to install the other packages that the draft requires: +then run the following command to install the other packages that the draft requires:: sudo tlmgr install latexmk isodate substr relsize ulem fixme rsfs extract layouts enumitem l3packages l3kernel imakeidx splitindex xstring @@ -30,7 +30,7 @@ then run the following command to install the other packages that the draft requ Getting Started on Debian-based Systems --------------------------------------- -Install the following packages: +Install the following packages:: sudo apt-get install latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended lmodern @@ -38,7 +38,7 @@ Install the following packages: Getting Started on Fedora ------------------------- -Install the following packages: +Install the following packages:: dnf install latexmk texlive texlive-isodate texlive-relsize texlive-ulem texlive-fixme texlive-extract texlive-l3kernel texlive-l3packages texlive-splitindex texlive-imakeidx @@ -46,7 +46,7 @@ Install the following packages: Getting Started on Arch Linux ----------------------------- -Install the following packages: +Install the following packages:: pacman -S make texlive-latexextra texlive-binextra texlive-plaingeneric texlive-fontsrecommended @@ -59,6 +59,10 @@ See `sample instructions `_ +Alternatively, you can `install WSL `_ +and a Linux distribution, +and follow the instructions for Linux above. + ------------ Instructions ------------ @@ -80,6 +84,22 @@ For example:: make figvirt.pdf +Verifying input and output when making changes +============================================== + +While in the ``source`` directory, +you can check for common mistakes such as misaligned comments with:: + + ../tools/check-source.sh + +After typesetting the document, +you can also check the output for further problems with:: + + ../tools/check-output.sh + +GitHub Actions will also run these checks when you create a pull request, +but it's often faster if you run them locally first. + ---------------- Acknowledgements ---------------- diff --git a/papers/n4982.html b/papers/n4982.html new file mode 100644 index 0000000000..3f97397fec --- /dev/null +++ b/papers/n4982.html @@ -0,0 +1,613 @@ + + + + + +N4982 + + +

N4982 Editors’ Report:
Programming Languages — C++

+ +

Date: 2024-04-16

+ +

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.

+ +

New papers

+ +
    +
  • N4981 is the +current working draft for C++26. It replaces +N4971.
  • +
  • N4982 is this Editors' Report.
  • +
+ +

Motions incorporated into working draft

+ +

Notes on motions

+ +

All motions were applied cleanly.

+ +

Core working group polls

+ +

CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues in +P3196R0 +(Core Language Working Group "ready" Issues for the March, 2024 meeting) to the C++ Working Paper.

+ +

CWG Poll 2. Apply the changes in +P2748R5 +(Disallow Binding a Returned Glvalue to a Temporary) to the C++ Working Paper.

+ +

CWG Poll 3. Accept as a Defect Report and apply the changes in P3106R1 (Clarifying rules for brace elision in aggregate initialization) to the C++ Working Paper, resolving core issue 2149.

+ +

CWG Poll 4. Apply the changes in +P0609R3 +(Attributes for Structured Bindings) to the C++ Working Paper.

+ +

CWG Poll 5. Accept as a Defect Report and apply the changes in +P3034R1 +(Module Declarations Shouldn’t be Macros) to the C++ Working Paper.

+ +

CWG Poll 6. Accept as a Defect Report and apply the changes in +P2809R3 +(Trivial infinite loops are not Undefined Behavior) to the C++ Working Paper.

+ +

CWG Poll 7. Apply the changes in +P2795R5 +(Erroneous behaviour for uninitialized reads) to the C++ Working Paper.

+ +

CWG Poll 9. Apply the changes in +P2573R2 +(= delete("should have a reason");) to the C++ Working Paper.

+ +

CWG Poll 10. Apply the changes in +P2893R3 +(Variadic friends) to the C++ Working Paper.

+ +

CWG Poll 8 was withdrawn.

+ +

Library working group polls

+ +

LWG Poll 1: Apply the changes for all Ready and Tentatively Ready issues in +P3180R0 +(C++ Standard Library Ready Issues to be moved in Tokyo, Mar. 2024) to the C++ working paper.

+ +

LWG Poll 2: Apply the changes in +P2875R4 +(Undeprecate polymorphic_allocator::destroy for C++26) to the C++ working paper.

+ +

LWG Poll 3: Apply the changes in +P2867R2 +(Remove Deprecated strstreams From C++26) to the C++ working paper.

+ +

LWG Poll 4: Apply the changes in +P2869R4 +(Remove Deprecated shared_ptr Atomic Access APIs from C++26) to the C++ working paper.

+ +

LWG Poll 5: Apply the changes in +P2872R3 +(Remove wstring_convert From C++26) to the C++ working paper.

+ +

LWG Poll 6: Accept as a Defect Report and apply the changes in +P3107R5 +(Permit an efficient implementation of std::print) to the C++ working paper.

+ +

LWG Poll 7: Apply the changes in +P3142R0 +(Printing Blank Lines with println) to the C++ working paper.

+ +

LWG Poll 8: Apply the changes in +P2845R8 +(Formatting of std::filesystem::path) to the C++ working paper.

+ +

LWG Poll 9: Apply the changes in +P0493R5 +(Atomic minimum/maximum) to the C++ working paper.

+ +

LWG Poll 10: Apply the changes in +P2542R8 +(views::concat) to the C++ working paper.

+ +

LWG Poll 11: Apply the changes in +P2591R5 +(Concatenation of strings and string views) to the C++ working paper.

+ +

LWG Poll 12: Apply the changes in +P2248R8 +(Enabling list-initialization for algorithms) to the C++ working paper.

+ +

LWG Poll 13: Apply the changes in +P2810R4 +(is_debugger_present is_replaceable) to the C++ working paper.

+ +

LWG Poll 14: Apply the changes in +P1068R11 +(Vector API for random number generation) to the C++ working paper.

+ +

LWG Poll 16: Apply the changes in +P2944R3 +(Comparisons for reference_wrapper) to the C++ working paper.

+ +

LWG Poll 17: Apply the changes in +P2642R6 +(Padded mdspan layouts) to the C++ working paper.

+ +

LWG Poll 18: Apply the changes in +P3029R1 +(Better mdspan's CTAD) to the C++ working paper.

+ +

LWG Poll 15 was withdrawn.

+ +

Editorial changes

+ +

Major editorial changes

+ +

There have not been any major editorial changes since the last working draft.

+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4971 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 08649a5a81ba91d8597c263b99dc80ed71767940
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Fri Dec 22 11:33:39 2023 +0100
+
+    [stmt.expr] Use \grammarterm for expression (#6469)
+
+commit acb68797051c9a6a5f51e4adb5091b376f1ba13a
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Jan 1 16:23:56 2024 +0100
+
+    [basic.life] Fix indentation in example (#6727)
+
+commit f6692f25130834672ba5a212f739100669abbbe8
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Jan 2 20:21:54 2024 +0100
+
+    [basic.scope.pdecl,basic.types.general] Remove extra whitespace (#6756)
+
+commit 7ddcd43c96589fc13342ac4cee549da75360fde7
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Fri Jan 5 15:41:01 2024 -0500
+
+    [basic.scope.param] Add missing \grammarterm for requires-expression (#6759)
+
+commit 29c0e4882a1ae62e7cd5f8d3fabcb22ae6153219
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Dec 18 17:22:30 2023 +0100
+
+    [std] Remove problematic 'requires' phrases from notes.
+
+    Only specific phrases involving the word "required" are problematic,
+    namely when they appear to establish a normative requirement. They
+    have been reworded, often by replacing "is required" with "needs",
+    sometimes with slightly larger edits.
+
+commit 43fc5a16147e720568b68ecae77f12fa3fb15102
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jan 5 15:32:55 2024 +0000
+
+    [std] Reword "necessary", "permitted", "allowed", "may" in notes.
+
+    This is so that notes do not (inappropriately) state requirements or
+    permissions.
+
+commit 74433025763f83bbccfb001dab8aa084647ffb2f
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Jan 11 19:11:17 2024 +0100
+
+    [basic.def] Fix punctuation (#6766)
+
+commit b67e0b70e88abf65d9b49875133c68d55744b1de
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Jan 12 12:53:10 2024 +0000
+
+    [text.encoding.overview] Use same parameter names as detailed description (#6768)
+
+commit bc5a56b6e9cadd030d48066601fc8098382c7469
+Author: Casey Carter <Casey@Carter.net>
+Date:   Mon Jan 15 11:19:13 2024 -0800
+
+    [exception] Paragraph two is no longer universally true
+
+    We recently added `bad_expected_access<void>` to the Standard Library, which derives from `exception`, but does not have "the following publicly accessible member functions, each of them having a non-throwing exception specification." For clarity, we should point out that this provision is not universal.
+
+commit 2055c2feabee6ec9df24ea07f8451ad33618be45
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Jan 16 09:20:44 2024 +0100
+
+    [zombie.names] Remove superfluous period (#6774)
+
+commit 8410aac1b84ec161b6990441acde53185f958135
+Author: Daniel Krügler <daniel.kruegler@gmail.com>
+Date:   Sun Jan 21 22:39:02 2024 +0100
+
+    [tuple.helper] Paragraph 1 not universally true (#6777)
+
+    [tuple.helper] p1 defines a general requirement that all specializations of `tuple_size`
+    shall meet the *Cpp17UnaryTypeTrait* requirements, but p4 actually defines a
+    special situation where this requirement is not met ("Otherwise, it has no member value").
+    We have the same seemingly contradiction in [depr.tuple] p2. For clarity, we should
+    point out that this provision is not universal.
+
+commit 4fe9190fa05c4fb4e83c1a1ba68aa12aa49542e9
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Sat Jan 27 14:38:55 2024 +0800
+
+    [locale.ctype.members] Add missing parameter name
+
+commit 74f5f61cac56a4eca5389a51754fe7e60e6b7449
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Sat Jan 27 11:26:37 2024 +0000
+
+    [tuple.cnstr] Do not use code font for cardinal number 1 (#6785)
+
+commit cb8ff12806b67990665100baaacb9a16040bce8c
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Jan 27 17:11:23 2024 +0100
+
+    [container.alloc.reqmts] End note with period (#6787)
+
+commit 70b99af0dfcb9cae82bcd97c7b24a2e84edfb2cd
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Jan 27 18:03:16 2024 +0100
+
+    [class.mem.general,class.mfct.non.static] End note with period (#6778)
+
+commit db80a4612af561e8473fd8fb3724ae9db2c72578
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Mon Feb 5 15:51:03 2024 +0000
+
+    [rand.dist.samp.plinear] Fix copy & paste error in Mandates (#6794)
+
+    This error was present in the incoming P1719R2 paper (Mandating the
+    Standard Library: Clause 26 - Numerics Library), but is obviously bogus.
+    There is no UnaryOperation type in that constructor. The correct
+    requirement is taken from the corresponding constructor in
+    [rand.dist.samp.pconst].
+
+commit e51d5733b1bd1531d6e3b63617d12414a56678c0
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Wed Feb 7 10:37:06 2024 -0500
+
+    [temp.res.general] Grammatical parallelism: remove a stray "a" (#6796)
+
+commit 8238252bcec14f76e97133db32721beaec5c749b
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Feb 8 06:59:10 2024 +0100
+
+    [iterator.concept.winc] Fix typo (#6800)
+
+commit 19caa61068d3f3aa2453e1ba7256536b8464c25c
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Dec 28 10:07:15 2023 +0800
+
+    [mem.res.private] Say `*this` instead of improper  `this`
+
+commit 419190062806ae257e5efe7057551fd626bd9516
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Dec 28 10:08:04 2023 +0800
+
+    [mem.res.monotonic.buffer.mem] Say `*this` instead of improper `this`
+
+commit 6ecda0b20664fc6b8450157e1cd9f0580c32e5e1
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Dec 28 10:09:08 2023 +0800
+
+    [re.traits] Say `*this` instead of improper `this`
+
+commit 9305893dfd250d876edf4555cf96c665e2e71e75
+Author: Casey Carter <Casey@Carter.net>
+Date:   Thu Feb 15 13:16:33 2024 -0800
+
+    [thread.once.callonce] INVOKE is evaluated, not called (#6810)
+
+commit 3616a40ded794e94181a5405672b1c36f7774684
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Feb 21 19:05:13 2024 +0100
+
+    [temp.pre] Add comma after introductory clause (#6814)
+
+commit 30debb0c5d5dc42fa36864aac76b82f49319ad84
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Feb 21 21:39:56 2024 +0100
+
+    [temp.constr.order] Move index entry to correct paragraph (#6812)
+
+commit fb0277664fd53efea93d95202784f78aea610f31
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Feb 22 20:28:15 2024 +0100
+
+    [semaphore.syn] Add binary_semaphore to index (#6781)
+
+commit 090840673ee58d3c1e8d2844d3c716ee5ce245bc
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Feb 22 20:31:19 2024 +0100
+
+    [format.parse.ctx] Improve readability of paragraphs 12 and 14 (#6815)
+
+commit a5825b1905b06d730a46e64fb5b379f48cbc6e51
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Feb 22 20:33:18 2024 +0100
+
+    [format.parse.ctx] Add comma (#6817)
+
+commit 8c8e05d7ff6cda6329ca898e7a270547a85675d7
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Feb 22 20:35:21 2024 +0100
+
+    [format.parse.ctx] Move non-normative explanations of errors into notes (#6816)
+
+commit 48f90026631638c91b3d8138bed49cd0450380c7
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Feb 28 10:23:51 2024 +0100
+
+    [stmt.while] Add comma after introductory phrase
+
+commit d5ad3794937429b1410071037af9ddfb0aa8c861
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Feb 28 10:24:26 2024 +0100
+
+    [stmt.do] Add comma after introductory phrase
+
+commit 78ecd23f22f00be4bffaf806a6747417ce2150a2
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Feb 28 18:06:26 2024 +0100
+
+    [stmt.jump] Add cross-reference to [stmt.dcl] for destruction of local variables (#6829)
+
+commit 66b6b97c8f3969f96e3ca8df1180c18b1c57af8c
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Feb 28 21:50:50 2024 +0100
+
+    [expr.dynamic.cast] Add comma after conditional clause (#6830)
+
+commit 23430d7e605d62f5a4a1769611e3c415d6510b65
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Mar 1 11:06:34 2024 +0100
+
+    [bibliography] Replace HTTP link with HTTPS link (#6831)
+
+commit 20c2851a3c8f480a017cef6602b1b6a4d32bc5e4
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Mar 1 16:03:04 2024 +0100
+
+    [time.parse] Hyphenate argument-dependent lookup
+
+commit e0287d17110f86e3724bda5ebe74de249508490f
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Mar 1 16:04:02 2024 +0100
+
+    [diff.cpp17.temp] Hyphenate argument-dependent lookup
+
+commit ceff4ea83b511be01a8e1756386ce6a2e06e323c
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Fri Mar 1 18:06:00 2024 +0100
+
+    [headers] Strike incorrect quote of subclause heading (#6832)
+
+commit 9878cfbea12b517d32c5af1bbfa7c8b8c4ff9cab
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Mar 3 08:42:45 2024 +0100
+
+    [handler.functions] Add cross-reference to [intro.races] (#6845)
+
+commit 9ec133c8e51aae98297255563250a2f6656e4636
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Mar 19 15:36:51 2024 +0000
+
+    [time.hash] Fix spelling of 'Cpp17Hash'
+
+commit 2b7cd6e8be2bc8a9ae97da9bf03ae4efa7fe1a9c
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Tue Apr 16 20:03:29 2024 +0800
+
+    [expos.only.entity] Add/fix \expos for exposition-only names (#6924)
+
+commit aa21c812f629975d5d25d4639053482f346751a8
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Tue Apr 16 08:07:44 2024 -0400
+
+    [dcl.type.elab] Move note to separate paragraph
+
+    Also clarify that the next paragraph is talking about any elaborated-type-specifier at all, not just the ones in p4.
+
+commit 397384c90e3ead9f832a3a269335fbfe53328180
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Feb 16 06:51:03 2024 +0100
+
+    [rand.adapt.ibits,rand.dist.pois.poisson] Add namespace std in class template
+
+    [rand.adapt.ibits] 28.5.5.3-4
+    [rand.dist.pois.poisson] 28.5.9.4.1-1
+
+commit fbf3d76683d269a0a5313fb69b5aa483ddd3a18a
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Feb 22 21:41:42 2024 +0100
+
+    [expr.unary.op] remove redundant value category wording
+
+commit 498cd7720bb2e53fb323144f956e67900a054e34
+Author: Daniel Krügler <daniel.kruegler@gmail.com>
+Date:   Sun Feb 4 17:57:38 2024 +0100
+
+    [iterator.requirements.general] Clarify that "constexpr iterator" is a requirement to be met
+
+    [iterator.requirements.general] p16 says "Iterators are called _constexpr iterators_ [..]", but all referencing sections say "meet the constexpr iterator requirements". For clarity, we should reword the definition to make it clear that this is a named requirement.
+
+commit 89cd1467f354a2b9b05ac57ad1f90f483aab22b9
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Sun Jan 28 13:54:17 2024 +0800
+
+    [range.drop.overview] Remove redundant \iref for subrange
+
+    ..which already existed in the previous bullet.
+
+commit bee055de1c5e23ce0b301138998633dc64169b4a
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Nov 23 09:33:39 2023 +0800
+
+    [dcl.init.ref] Change "function lvalue" to "lvalue of function type"
+
+commit ce31d424ba6753be1c87a4cf3face42f89b9e010
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Nov 23 09:36:28 2023 +0800
+
+    [over.ics.ref] Simplify wording by not using "function lvalue"
+
+commit 2a07c133732dcc7ea57aeb32612b15b50837a4df
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Nov 23 09:38:41 2023 +0800
+
+    [over.ics.rank] Change "function lvalue" to "lvalue of function type"
+
+commit 7675c4c1abf1986241e8a20463fd71f2841d3c39
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Sep 1 10:27:25 2023 +0200
+
+    [res.on.exception.handling] use grammarterm instead of informal term and add ref
+
+ + diff --git a/papers/n4982.md b/papers/n4982.md new file mode 100644 index 0000000000..92a68b0900 --- /dev/null +++ b/papers/n4982.md @@ -0,0 +1,472 @@ +# N4982 Editors' Report -- Programming Languages -- C++ + +Date: 2024-04-16 + +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. + +## New papers + + * [N4981](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4981.pdf) is the + current working draft for C++26. It replaces + [N4971](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4971.pdf). + * N4982 is this Editors' Report. + +## Motions incorporated into working draft + +### Notes on motions + +All motions were applied cleanly. + +### Core working group polls + +CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues in +[P3196R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3196r0.html) +(Core Language Working Group "ready" Issues for the March, 2024 meeting) to the C++ Working Paper. + +CWG Poll 2. Apply the changes in +[P2748R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2748r5.html) +(Disallow Binding a Returned Glvalue to a Temporary) to the C++ Working Paper. + +CWG Poll 3. Accept as a Defect Report and apply the changes in [P3106R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3106r1.html) (Clarifying rules for brace elision in aggregate initialization) to the C++ Working Paper, resolving core issue 2149. + +CWG Poll 4. Apply the changes in +[P0609R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p0609r3.pdf) +(Attributes for Structured Bindings) to the C++ Working Paper. + +CWG Poll 5. Accept as a Defect Report and apply the changes in +[P3034R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3034r1.html) +(Module Declarations Shouldn’t be Macros) to the C++ Working Paper. + +CWG Poll 6. Accept as a Defect Report and apply the changes in +[P2809R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2809r3.html) +(Trivial infinite loops are not Undefined Behavior) to the C++ Working Paper. + +CWG Poll 7. Apply the changes in +[P2795R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2795r5.html) +(Erroneous behaviour for uninitialized reads) to the C++ Working Paper. + +CWG Poll 9. Apply the changes in +[P2573R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2573r2.html) +(`= delete("should have a reason");`) to the C++ Working Paper. + +CWG Poll 10. Apply the changes in +[P2893R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2893r3.html) +(Variadic friends) to the C++ Working Paper. + +CWG Poll 8 was withdrawn. + +### Library working group polls + +LWG Poll 1: Apply the changes for all Ready and Tentatively Ready issues in +[P3180R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3180r0.html) +(C++ Standard Library Ready Issues to be moved in Tokyo, Mar. 2024) to the C++ working paper. + +LWG Poll 2: Apply the changes in +[P2875R4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2875r4.pdf) +(Undeprecate `polymorphic_allocator::destroy` for C++26) to the C++ working paper. + +LWG Poll 3: Apply the changes in +[P2867R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2867r2.html) +(Remove Deprecated `strstream`s From C++26) to the C++ working paper. + +LWG Poll 4: Apply the changes in +[P2869R4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2869r4.pdf) +(Remove Deprecated `shared_ptr` Atomic Access APIs from C++26) to the C++ working paper. + +LWG Poll 5: Apply the changes in +[P2872R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2872r3.pdf) +(Remove `wstring_convert` From C++26) to the C++ working paper. + +LWG Poll 6: Accept as a Defect Report and apply the changes in +[P3107R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3107r5.html) +(Permit an efficient implementation of `std::print`) to the C++ working paper. + +LWG Poll 7: Apply the changes in +[P3142R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3142r0.pdf) +(Printing Blank Lines with `println`) to the C++ working paper. + +LWG Poll 8: Apply the changes in +[P2845R8](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2845r8.html) +(Formatting of `std::filesystem::path`) to the C++ working paper. + +LWG Poll 9: Apply the changes in +[P0493R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p0493r5.pdf) +(Atomic minimum/maximum) to the C++ working paper. + +LWG Poll 10: Apply the changes in +[P2542R8](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2542r8.html) +(`views::concat`) to the C++ working paper. + +LWG Poll 11: Apply the changes in +[P2591R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2591r5.html) +(Concatenation of strings and string views) to the C++ working paper. + +LWG Poll 12: Apply the changes in +[P2248R8](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2248r8.html) +(Enabling list-initialization for algorithms) to the C++ working paper. + +LWG Poll 13: Apply the changes in +[P2810R4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2810r4.html) +(`is_debugger_present` `is_replaceable`) to the C++ working paper. + +LWG Poll 14: Apply the changes in +[P1068R11](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p1068r11.html) +(Vector API for random number generation) to the C++ working paper. + +LWG Poll 16: Apply the changes in +[P2944R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2944r3.html) +(Comparisons for `reference_wrapper`) to the C++ working paper. + +LWG Poll 17: Apply the changes in +[P2642R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2642r6.pdf) +(Padded `mdspan` layouts) to the C++ working paper. + +LWG Poll 18: Apply the changes in +[P3029R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3029r1.html) +(Better `mdspan`'s CTAD) to the C++ working paper. + +LWG Poll 15 was withdrawn. + +## Editorial changes + +### Major editorial changes + +There have not been any major editorial changes since the last working draft. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4971 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/n4971...n4981). + + commit 08649a5a81ba91d8597c263b99dc80ed71767940 + Author: Jan Schultke + Date: Fri Dec 22 11:33:39 2023 +0100 + + [stmt.expr] Use \grammarterm for expression (#6469) + + commit acb68797051c9a6a5f51e4adb5091b376f1ba13a + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Jan 1 16:23:56 2024 +0100 + + [basic.life] Fix indentation in example (#6727) + + commit f6692f25130834672ba5a212f739100669abbbe8 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Jan 2 20:21:54 2024 +0100 + + [basic.scope.pdecl,basic.types.general] Remove extra whitespace (#6756) + + commit 7ddcd43c96589fc13342ac4cee549da75360fde7 + Author: Alisdair Meredith + Date: Fri Jan 5 15:41:01 2024 -0500 + + [basic.scope.param] Add missing \grammarterm for requires-expression (#6759) + + commit 29c0e4882a1ae62e7cd5f8d3fabcb22ae6153219 + Author: Jens Maurer + Date: Mon Dec 18 17:22:30 2023 +0100 + + [std] Remove problematic 'requires' phrases from notes. + + Only specific phrases involving the word "required" are problematic, + namely when they appear to establish a normative requirement. They + have been reworded, often by replacing "is required" with "needs", + sometimes with slightly larger edits. + + commit 43fc5a16147e720568b68ecae77f12fa3fb15102 + Author: Thomas Köppe + Date: Fri Jan 5 15:32:55 2024 +0000 + + [std] Reword "necessary", "permitted", "allowed", "may" in notes. + + This is so that notes do not (inappropriately) state requirements or + permissions. + + commit 74433025763f83bbccfb001dab8aa084647ffb2f + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Jan 11 19:11:17 2024 +0100 + + [basic.def] Fix punctuation (#6766) + + commit b67e0b70e88abf65d9b49875133c68d55744b1de + Author: Jonathan Wakely + Date: Fri Jan 12 12:53:10 2024 +0000 + + [text.encoding.overview] Use same parameter names as detailed description (#6768) + + commit bc5a56b6e9cadd030d48066601fc8098382c7469 + Author: Casey Carter + Date: Mon Jan 15 11:19:13 2024 -0800 + + [exception] Paragraph two is no longer universally true + + We recently added `bad_expected_access` to the Standard Library, which derives from `exception`, but does not have "the following publicly accessible member functions, each of them having a non-throwing exception specification." For clarity, we should point out that this provision is not universal. + + commit 2055c2feabee6ec9df24ea07f8451ad33618be45 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Jan 16 09:20:44 2024 +0100 + + [zombie.names] Remove superfluous period (#6774) + + commit 8410aac1b84ec161b6990441acde53185f958135 + Author: Daniel Krügler + Date: Sun Jan 21 22:39:02 2024 +0100 + + [tuple.helper] Paragraph 1 not universally true (#6777) + + [tuple.helper] p1 defines a general requirement that all specializations of `tuple_size` + shall meet the *Cpp17UnaryTypeTrait* requirements, but p4 actually defines a + special situation where this requirement is not met ("Otherwise, it has no member value"). + We have the same seemingly contradiction in [depr.tuple] p2. For clarity, we should + point out that this provision is not universal. + + commit 4fe9190fa05c4fb4e83c1a1ba68aa12aa49542e9 + Author: S. B. Tam + Date: Sat Jan 27 14:38:55 2024 +0800 + + [locale.ctype.members] Add missing parameter name + + commit 74f5f61cac56a4eca5389a51754fe7e60e6b7449 + Author: Jonathan Wakely + Date: Sat Jan 27 11:26:37 2024 +0000 + + [tuple.cnstr] Do not use code font for cardinal number 1 (#6785) + + commit cb8ff12806b67990665100baaacb9a16040bce8c + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Jan 27 17:11:23 2024 +0100 + + [container.alloc.reqmts] End note with period (#6787) + + commit 70b99af0dfcb9cae82bcd97c7b24a2e84edfb2cd + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Jan 27 18:03:16 2024 +0100 + + [class.mem.general,class.mfct.non.static] End note with period (#6778) + + commit db80a4612af561e8473fd8fb3724ae9db2c72578 + Author: Jonathan Wakely + Date: Mon Feb 5 15:51:03 2024 +0000 + + [rand.dist.samp.plinear] Fix copy & paste error in Mandates (#6794) + + This error was present in the incoming P1719R2 paper (Mandating the + Standard Library: Clause 26 - Numerics Library), but is obviously bogus. + There is no UnaryOperation type in that constructor. The correct + requirement is taken from the corresponding constructor in + [rand.dist.samp.pconst]. + + commit e51d5733b1bd1531d6e3b63617d12414a56678c0 + Author: Arthur O'Dwyer + Date: Wed Feb 7 10:37:06 2024 -0500 + + [temp.res.general] Grammatical parallelism: remove a stray "a" (#6796) + + commit 8238252bcec14f76e97133db32721beaec5c749b + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Feb 8 06:59:10 2024 +0100 + + [iterator.concept.winc] Fix typo (#6800) + + commit 19caa61068d3f3aa2453e1ba7256536b8464c25c + Author: A. Jiang + Date: Thu Dec 28 10:07:15 2023 +0800 + + [mem.res.private] Say `*this` instead of improper `this` + + commit 419190062806ae257e5efe7057551fd626bd9516 + Author: A. Jiang + Date: Thu Dec 28 10:08:04 2023 +0800 + + [mem.res.monotonic.buffer.mem] Say `*this` instead of improper `this` + + commit 6ecda0b20664fc6b8450157e1cd9f0580c32e5e1 + Author: A. Jiang + Date: Thu Dec 28 10:09:08 2023 +0800 + + [re.traits] Say `*this` instead of improper `this` + + commit 9305893dfd250d876edf4555cf96c665e2e71e75 + Author: Casey Carter + Date: Thu Feb 15 13:16:33 2024 -0800 + + [thread.once.callonce] INVOKE is evaluated, not called (#6810) + + commit 3616a40ded794e94181a5405672b1c36f7774684 + Author: Jan Schultke + Date: Wed Feb 21 19:05:13 2024 +0100 + + [temp.pre] Add comma after introductory clause (#6814) + + commit 30debb0c5d5dc42fa36864aac76b82f49319ad84 + Author: Jens Maurer + Date: Wed Feb 21 21:39:56 2024 +0100 + + [temp.constr.order] Move index entry to correct paragraph (#6812) + + commit fb0277664fd53efea93d95202784f78aea610f31 + Author: Jan Schultke + Date: Thu Feb 22 20:28:15 2024 +0100 + + [semaphore.syn] Add binary_semaphore to index (#6781) + + commit 090840673ee58d3c1e8d2844d3c716ee5ce245bc + Author: Jan Schultke + Date: Thu Feb 22 20:31:19 2024 +0100 + + [format.parse.ctx] Improve readability of paragraphs 12 and 14 (#6815) + + commit a5825b1905b06d730a46e64fb5b379f48cbc6e51 + Author: Jan Schultke + Date: Thu Feb 22 20:33:18 2024 +0100 + + [format.parse.ctx] Add comma (#6817) + + commit 8c8e05d7ff6cda6329ca898e7a270547a85675d7 + Author: Jan Schultke + Date: Thu Feb 22 20:35:21 2024 +0100 + + [format.parse.ctx] Move non-normative explanations of errors into notes (#6816) + + commit 48f90026631638c91b3d8138bed49cd0450380c7 + Author: Eisenwave + Date: Wed Feb 28 10:23:51 2024 +0100 + + [stmt.while] Add comma after introductory phrase + + commit d5ad3794937429b1410071037af9ddfb0aa8c861 + Author: Eisenwave + Date: Wed Feb 28 10:24:26 2024 +0100 + + [stmt.do] Add comma after introductory phrase + + commit 78ecd23f22f00be4bffaf806a6747417ce2150a2 + Author: Jan Schultke + Date: Wed Feb 28 18:06:26 2024 +0100 + + [stmt.jump] Add cross-reference to [stmt.dcl] for destruction of local variables (#6829) + + commit 66b6b97c8f3969f96e3ca8df1180c18b1c57af8c + Author: Jan Schultke + Date: Wed Feb 28 21:50:50 2024 +0100 + + [expr.dynamic.cast] Add comma after conditional clause (#6830) + + commit 23430d7e605d62f5a4a1769611e3c415d6510b65 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Mar 1 11:06:34 2024 +0100 + + [bibliography] Replace HTTP link with HTTPS link (#6831) + + commit 20c2851a3c8f480a017cef6602b1b6a4d32bc5e4 + Author: Eisenwave + Date: Fri Mar 1 16:03:04 2024 +0100 + + [time.parse] Hyphenate argument-dependent lookup + + commit e0287d17110f86e3724bda5ebe74de249508490f + Author: Eisenwave + Date: Fri Mar 1 16:04:02 2024 +0100 + + [diff.cpp17.temp] Hyphenate argument-dependent lookup + + commit ceff4ea83b511be01a8e1756386ce6a2e06e323c + Author: Jan Schultke + Date: Fri Mar 1 18:06:00 2024 +0100 + + [headers] Strike incorrect quote of subclause heading (#6832) + + commit 9878cfbea12b517d32c5af1bbfa7c8b8c4ff9cab + Author: Jan Schultke + Date: Sun Mar 3 08:42:45 2024 +0100 + + [handler.functions] Add cross-reference to [intro.races] (#6845) + + commit 9ec133c8e51aae98297255563250a2f6656e4636 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Mar 19 15:36:51 2024 +0000 + + [time.hash] Fix spelling of 'Cpp17Hash' + + commit 2b7cd6e8be2bc8a9ae97da9bf03ae4efa7fe1a9c + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Tue Apr 16 20:03:29 2024 +0800 + + [expos.only.entity] Add/fix \expos for exposition-only names (#6924) + + commit aa21c812f629975d5d25d4639053482f346751a8 + Author: Arthur O'Dwyer + Date: Tue Apr 16 08:07:44 2024 -0400 + + [dcl.type.elab] Move note to separate paragraph + + Also clarify that the next paragraph is talking about any elaborated-type-specifier at all, not just the ones in p4. + + commit 397384c90e3ead9f832a3a269335fbfe53328180 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Feb 16 06:51:03 2024 +0100 + + [rand.adapt.ibits,rand.dist.pois.poisson] Add namespace std in class template + + [rand.adapt.ibits] 28.5.5.3-4 + [rand.dist.pois.poisson] 28.5.9.4.1-1 + + commit fbf3d76683d269a0a5313fb69b5aa483ddd3a18a + Author: Jan Schultke + Date: Thu Feb 22 21:41:42 2024 +0100 + + [expr.unary.op] remove redundant value category wording + + commit 498cd7720bb2e53fb323144f956e67900a054e34 + Author: Daniel Krügler + Date: Sun Feb 4 17:57:38 2024 +0100 + + [iterator.requirements.general] Clarify that "constexpr iterator" is a requirement to be met + + [iterator.requirements.general] p16 says "Iterators are called _constexpr iterators_ [..]", but all referencing sections say "meet the constexpr iterator requirements". For clarity, we should reword the definition to make it clear that this is a named requirement. + + commit 89cd1467f354a2b9b05ac57ad1f90f483aab22b9 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Sun Jan 28 13:54:17 2024 +0800 + + [range.drop.overview] Remove redundant \iref for subrange + + ..which already existed in the previous bullet. + + commit bee055de1c5e23ce0b301138998633dc64169b4a + Author: A. Jiang + Date: Thu Nov 23 09:33:39 2023 +0800 + + [dcl.init.ref] Change "function lvalue" to "lvalue of function type" + + commit ce31d424ba6753be1c87a4cf3face42f89b9e010 + Author: A. Jiang + Date: Thu Nov 23 09:36:28 2023 +0800 + + [over.ics.ref] Simplify wording by not using "function lvalue" + + commit 2a07c133732dcc7ea57aeb32612b15b50837a4df + Author: A. Jiang + Date: Thu Nov 23 09:38:41 2023 +0800 + + [over.ics.rank] Change "function lvalue" to "lvalue of function type" + + commit 7675c4c1abf1986241e8a20463fd71f2841d3c39 + Author: Eisenwave + Date: Fri Sep 1 10:27:25 2023 +0200 + + [res.on.exception.handling] use grammarterm instead of informal term and add ref diff --git a/papers/n4987.html b/papers/n4987.html new file mode 100644 index 0000000000..3099e7e867 --- /dev/null +++ b/papers/n4987.html @@ -0,0 +1,915 @@ + + + + + +N4987 + + +

N4987 Editors’ Report:
Programming Languages — C++

+ +

Date: 2024-07-16

+ +

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.

+ +

New papers

+ +
    +
  • N4986 is the +current working draft for C++26. It replaces +N4981.
  • +
  • N4987 is this Editors' Report.
  • +
+ +

Motions incorporated into working draft

+ +

Notes on motions

+ +

All passed motions from CWG and LWG motions 1 through 9 were applied cleanly. +LWG motions 10, 11, and 12 have not yet been applied due to a lack of time, +but will be included in the next draft.

+ +

In CWG Poll 1, issue CWG2144 contains no wording changes since it is subsumed by CWG2876, which is part of Poll 2. +The wording changes from issue CWG2867 of CWG Poll 1 affect the same wording as CWG Poll 7; the wording has been reconciled.

+ +

Core working group polls

+ +

CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues except 2819, 2858, and 2876 in +P3345R0 +(Core Language Working Group "ready" Issues for the June, 2024 meeting) to the C++ Working Paper.

+ +

CWG Poll 2. Apply the proposed resolution of issues 2819, 2858, and 2876 in +P3345R0 +(Core Language Working Group "ready" Issues for the June, 2024 meeting) to the C++ Working Paper.

+ +

CWG Poll 3. Apply the changes in +P2747R2 +(constexpr placement new) to the C++ Working Paper.

+ +

CWG Poll 5. Apply the changes in +P3144R2 +(Deleting a Pointer to an Incomplete Type Should be Ill-formed) to the C++ Working Paper.

+ +

CWG Poll 6. Apply the changes in +P2963R3 +(Ordering of constraints involving fold expressions) to the C++ Working Paper.

+ +

CWG Poll 7. Apply the changes in +P0963R3 +(Structured binding declaration as a condition) to the C++ Working Paper.

+ +

CWG Poll 4 did not have consensus.

+ +

Library working group polls

+ +

LWG Poll 1. Apply the changes for all Ready and Tentatively Ready issues in +P3341R0 +(C++ Standard Library Ready Issues to be moved in St. Louis, Jun. 2024) to the C++ working paper.

+ +

LWG Poll 2. Apply the changes in +P2997R1 +(Removing the common reference requirement from the indirectly invocable concepts) to the C++ working paper.

+ +

LWG Poll 3. Apply the changes in +P2389R2 +(dextents Index Type Parameter) to the C++ working paper.

+ +

LWG Poll 4. Apply the changes in +P3168R2 +(Give std::optional Range Support) to the C++ working paper.

+ +

LWG Poll 5. Apply the changes in +P3217R0 +(Adjoints to "Enabling list-initialization for algorithms": find_last) to the C++ working paper.

+ +

LWG Poll 6. Apply the changes in +P2985R0 +(A type trait for detecting virtual base classes) to the C++ working paper.

+ +

LWG Poll 7. Apply the changes in +P0843R14 +(inplace_vector) to the C++ working paper.

+ +

LWG Poll 8. Accept as a Defect Report and apply the changes in +P3235R3 +(std::print more types faster with less memory) to the C++ working paper.

+ +

LWG Poll 9. Apply the changes in +P2968R2 +(Make std::ignore a first-class object) to the C++ working paper.

+ +

Not yet applied:

+ +

LWG Poll 10. Apply the changes in +P2075R6 +(Philox as an extension of the C++ RNG engines) to the C++ working paper.

+ +

LWG Poll 11. Apply the changes in +P2422R1 +(Remove nodiscard annotations from the standard library specification) to the C++ working paper.

+ +

LWG Poll 12. Apply the changes in +P2300R10 +(std::execution) to the C++ working paper.

+ +

Editorial changes

+ +

Major editorial changes

+ +

A number of editorial changes have been applied that resulted from the ongoing review of the +C++23 IS with the ISO secretariat.

+ +

Mathematical formulae are now numbered, and they must be referenced explicitly from the text.

+ +

We avoid writing references as "subclause 1.2.3" in favour of just "1.2.3" now whenever that is +equally clear.

+ +

Examples in Annex C now use the regular example style, as opposed to the previous ad-hoc style.

+ +

We changed how we refer to the C++ standard itself and how we cite other standards. The page +footers have been changed to show the page number and the copyright over two lines, and the +display of Annex titles has been changed, both in accordance with new ISO style advice. For +details see the following listing.

+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4981 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 59d6bfc0c23b61cabb72d9a48270ed1c3b7e02f9
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Apr 16 09:57:19 2024 -0400
+
+    [basic.life] Reflow text defining transparently replaceable
+
+    p8 is difficult to read as it defines transparently replaceable
+    only after it has made all use of it.  The edit pulls the
+    definition of transparently replaceable into its own preceding
+    paragraph, and then simplifies the sentence that uses this term.
+
+commit ccfb6adea4373a63b7063f4d41cb9d47876a9347
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Apr 17 03:08:36 2024 -0400
+
+    [tab:headers.cpp.fs] Move the debugging library to numberically sorted position (#6927)
+
+commit c82e95ca91b313bc2cfde60aac9abbd49406d930
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Apr 17 18:42:19 2024 -0400
+
+    [zombie.names] Turn lists of zombie names into tables (#6925)
+
+commit c1eec01966d6383dabfaa4304939ce3be3868f1f
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Thu Apr 18 23:51:53 2024 +0800
+
+    [range.concat.overview] Remove unnecessary `std::` prefix from example (#6931)
+
+commit 2de15529d3f98a5de25cecf9ac8ed5b104d776e1
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Apr 18 18:00:42 2024 +0200
+
+    [charconv.syn] Clarify types matching integer-type (#6847)
+
+commit bae18b69cbca566eac284c8c2f316407fda98d16
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Fri Apr 19 01:21:19 2024 +0800
+
+    [range.concat.view] Format code to match the current style (#6929)
+
+commit 79dcca82c22d75fc2b2b6cbc1c338a0229db9a34
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Fri Apr 19 19:51:29 2024 +0800
+
+    [range.utility.conv.general] Fix misapplication of LWG4016 (#6932)
+
+commit e572580d71dfc8bdb32b8d1a21a2e493676e2151
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Fri Apr 19 21:57:48 2024 +0800
+
+    [range.concat.iterator] Remove @ outside of codeblocks (#6934)
+
+commit 5a5295d9c9e1881e58d3b4696fe45f00ef1cc507
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Fri Apr 19 17:32:53 2024 -0400
+
+    [index] Add missing entries for Cpp17 concepts (#6940)
+
+commit 5d4d9508bca4709366a0ff7acb17ba7b3a2efced
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Sat Apr 20 20:16:23 2024 +0800
+
+    [range.join.with.iterator] Add missing 'template' keyword for dependent name 'emplace' (#5455)
+
+commit 0ac38fd4c4548ff61cd378f98eff3e18f4463caf
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Fri Aug 18 15:12:08 2023 +0800
+
+    Fix typo (`dynamic_rank` => `rank_dynamic`)
+
+commit 47c2f68d84cb13a7ca83a507fb1f32ddf4774ec1
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Apr 22 23:19:41 2024 +0200
+
+    [mdspan.layout.leftpad.obs] Remove superfluous \item (#6944)
+
+commit 4f0779d5a3665af9dd92a96e52d809ba3911495d
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Tue Apr 23 12:13:27 2024 +0200
+
+    [intro.execution] Add comma after conditional clause (#6945)
+
+commit 12b6307589257a803527eb38c43f08f867d59322
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Mon Apr 29 15:23:41 2024 +0800
+
+    [algorithm.syn,alg.fill] Fix typos in constraints (#6957)
+
+commit 927d0dba2b068ba9f2136479b4ba05a430eec348
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Mon Apr 29 22:43:49 2024 +0800
+
+    [alg.rand.generate] Remove brace typo (#6956)
+
+commit 480adbe4d6ae54e03b6cec5f8784689445c36eee
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Apr 30 07:48:14 2024 +0200
+
+    [print.syn] Correctly order println overloads
+
+commit 3333421819c1b2c6dec1becd0dd2a9fa0aeba8cd
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Tue Apr 30 20:22:43 2024 +0800
+
+    [range.concat.iterator] Remove superfluous period (#6960)
+
+commit 513635b371c6a664be2a0ea6fc6939350b9b5e6b
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Fri May 10 00:17:43 2024 +0800
+
+    [range.reverse.overview] Replace 'equivalent to' with 'then' (#6966)
+
+commit be18ecc17114bcae4acdad10a3467686510b22c2
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat May 11 21:51:48 2024 +0200
+
+    [class.derived.general] Restore accidental reversal of P2662R3 change
+
+    P2662R3 contained a rename of the grammar production "class-or-decltype"
+    to "class-or-computed-type-specifier".  That was editorially reverted
+    with commit c831ec0b8aac369aa61ce392783865ff04b84b19, but that commit
+    also accidentally reverted the change from "decltype-specifier" to
+    "computed-type-specifier" as one of the options for "class-or-decltype".
+
+    This commit restores the latter change, as intended by P2662R3.
+
+commit 9dcff41d2d26577c2ec0643056187a0f8094832e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun May 12 15:24:43 2024 +0100
+
+    [intro.refs] Fix document titles
+
+commit 5b332fed1a4577ad08ed469da26c9c7864ea9e11
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun May 12 15:31:43 2024 +0100
+
+    [intro.refs, intro.defs] Update ISO 80000-2:2009 to :2019, change "and" to comma
+
+commit 85f4bb454effe50029de636d6f206f9c1153236a
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun May 12 15:53:11 2024 +0100
+
+    [defns.order.ptr] Add missing hypen in "built-in"
+
+commit 9cd8d6ce9cc446c94d91e1350b9113906774f0af
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Tue May 14 21:49:55 2024 +0800
+
+    [format.context] Fix error in example (#6970)
+
+commit 951ded4880e4295981c0d691915a81d84c2baa9d
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun May 12 16:01:09 2024 +0100
+
+    [defns.unblock] Italicize entire term "blocked", not just "block".
+
+    ISO has indicated that this is the acceptable way to state a reference to another definition, in this case "block" [defns.block].
+
+commit 1cb3842f83412720a23c664f478a4167cb3162a2
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue May 14 18:52:30 2024 +0200
+
+    [styles] Redesign Annex titles per Rice Model Standard
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 2f23560744a966f7a455629506468a02055d53ea
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Mon May 20 05:52:26 2024 -0400
+
+    [alg.ends.with] Replace drop_view with views::drop (#6773)
+
+commit bbac8a98d303d3ad5ecd9514fb2db37745d16984
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Mon May 20 07:24:27 2024 -0400
+
+    [dcl.init.list] Eliminate "specialization of initializer_list<X>" (#6258)
+
+commit ad37b863dec4af4c88d8f2154d5f3e4a9b2a3b33
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Tue May 21 07:12:32 2024 -0400
+
+    [support.initlist] "initializer list" should be "initializer_list" (#6680)
+
+    This note is talking about the class type, not the grammatical construct.
+
+commit 2e455af5d6a2bdaac7e9d0d4e7f23ac7a6c0451d
+Author: zhihaoy <43971430+zhihaoy@users.noreply.github.com>
+Date:   Tue May 21 22:50:56 2024 -0700
+
+    [util.smartptr.shared.cast] Properly describe possibility of double deletion in notes (#7037)
+
+commit 4b3f32ae814c8da3faccc0dc307904bd250371d9
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue May 28 22:10:36 2024 +0100
+
+    [input.output] Add cross-references to header synopses (#7005)
+
+    Several of the synopses are not adjacent to the types they declare.
+    Adding cross-references makes it easier to find the relevant definitions
+    of classes and class templates.
+
+    Also make the title of [ostream.manip] more specific to its content.
+
+commit dbf17528619707307f859bac1b36c52654fecfc8
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Mon Jun 10 17:06:15 2024 -0400
+
+    [container.adaptors] Reorder constructors for flat_* adaptors (#6274)
+
+    Canonicalize the ordering of the constructors for the flat_* adaptors:
+     - default constructor is first
+     - each overload without `key_compare` is followed by the corresponding one with `key_compare`
+     - each pair of overloads without `sorted_unique` is followed by the corresponding pair with `sorted_unique`
+
+commit ae9b2d7481af415076ffdf33d5920e31e5591eb1
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Tue Jun 11 15:32:36 2024 +0200
+
+    [res.on.exception.handling] Add cross-reference to [except.spec] (#7058)
+
+commit c95ff039b634388962e1fa242e772da8466d49b6
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Jun 12 12:36:02 2024 +0200
+
+    [stmt.if] Add missing comma after conditional clause (#7061)
+
+commit 42a38b072a471a112720535c087d96c8f4865a47
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Jun 12 18:56:14 2024 +0200
+
+    [stmt.pre] Add a cross-reference to [intro.execution] (#7060)
+
+commit 3680e10a5a7eb48b35f150429ce6b3313583bb87
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Fri Jun 14 12:48:46 2024 +0200
+
+    [class.virtual] Add commas (#7062)
+
+commit 9ad7d63f8db28c88dfa68866d23c5ab742be3f80
+Author: Antony Polukhin <antoshkka@gmail.com>
+Date:   Tue Jun 18 19:00:34 2024 +0300
+
+    [associative.reqmts.general] Fix typo (#7069)
+
+commit a24620eced94b1f04fcbd8add49f5e9ca6326ed4
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Jun 21 12:36:01 2024 +0200
+
+    [class.union.general] Add comma (#7072)
+
+commit 59e634a8a841f58efeac873459bedf28928a83f9
+Author: Johannes Sixt <j6t@kdbg.org>
+Date:   Wed Jun 26 11:53:47 2024 +0200
+
+    [func.require] Add missing formatting of subscript index (#7071)
+
+commit 6d67d200863e430650047adb651324bc5663b6fc
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue May 14 13:13:42 2024 +0200
+
+    [diff] Mark examples as such
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 21e022557462544e2e6d32411f71e42a378d2236
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Jul 2 14:31:08 2024 +0100
+
+    [depr.c.macros] Fix "macro" singular when referring to two macros
+
+    This should have been applied as part of LWG 4036.
+
+commit 8bb63636c37f8e67808de1e1ce1142a3028293fd
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Wed Jul 3 20:53:40 2024 +0100
+
+    [istream.unformatted] add missing semi-colon to list item (#7117)
+
+commit 8227c196af96f157a539e5181f7a75ab3de3a096
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Jul 5 10:03:47 2024 +0200
+
+    [except.throw] Add comma (#7118)
+
+commit 07c20b75a867b66c858de716dfb639b0a9d1da2c
+Author: Yihe Li <winmikedows@hotmail.com>
+Date:   Sat Jul 6 23:32:43 2024 +0800
+
+    [version.syn] Remove redundant <version> for __cpp_lib_ranges_enumerate (#7120)
+
+commit 15b7ea6c95e471888cda2c334ba8ac30cabccf64
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sun Jul 7 10:23:09 2024 +0200
+
+    [basic.start.main] fix definite article (#7121)
+
+commit 61d85d3f9b78d792bd1bdb1d15202f9cdd931b31
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 9 00:57:58 2024 +0100
+
+    [intro.compliance.general] Cite Annex B more normatively.
+
+commit 2048179f82bbe92dcccee3cc6bbdac4973c77606
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 9 01:25:28 2024 +0100
+
+    [intro.compliance.general] Cite Annex D more normatively.
+
+commit 6b67a856495634df3a0bd0d8abee36eb0d3c8c6f
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Jul 9 08:29:50 2024 +0200
+
+    [temp.inst] Fix definite article
+
+commit 43c47b42fd1f7cd4d095299aca98666c06e45949
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 9 01:44:08 2024 +0100
+
+    [uaxid] Clarify that requirements come "from UAX #31", and use "this document".
+
+commit 7c35cb057ef4885e091bf65c1103d64946e7c8d1
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 9 14:47:10 2024 +0100
+
+    [std] Make bibliography reference link colour more citely
+
+commit bc2c80c23133a0581a847bd7fcfaca621ca86ffe
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon May 13 20:17:21 2024 +0200
+
+    [dcl.init.list] Add commas and period for bulleted list
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 868db7356ad1490890391e8c82888de5c4d4aad4
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon May 13 20:18:20 2024 +0200
+
+    [facet.num.get.virtuals] Add missing punctuation
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 77ee6ed3b8865b2bb514cb8446488aa6fb032dda
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon May 13 23:39:13 2024 +0200
+
+    [lex.literal] Properly format table headings
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit cb9850377b88a4d7da12d05bcdf11948c384f699
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon May 13 23:47:55 2024 +0200
+
+    [basic.fundamental] Center second column of "integer width" table
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 2a2b8732e0d81dd9f5d3880b70bd451173e5f5fc
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 9 15:41:56 2024 +0100
+
+    [intro.defs] Minor rewording. Avoid sounding like a requirement.
+
+commit 4746925c7117015480542fd68ad5f595b78173d2
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue May 14 14:11:53 2024 +0200
+
+    [numeric.limits.members,bibliography] Remove LIA-1 abbreviation for ISO 10967
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit c18d51ddf436abf39065ea86497161383bba11c0
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed May 15 09:05:36 2024 +0200
+
+    [intro.memory] Move footnote about Unicode trademark to [lex.phases]
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 1f32f6aa8000f194f1b5c4daba94d271eea817fb
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed May 15 16:28:34 2024 +0200
+
+    [diff,bibliography] Move details of old C++ standards to the bibliography
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit d5410b4035e3108d48a63434abfff7e377c996d2
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed May 15 18:31:14 2024 +0200
+
+    [diff.cpp20,diff.cpp17] Add missing inclusion clause
+
+commit af4cf904c3d2df0675dbd456af2de2f1259e370c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu May 16 12:56:12 2024 +0200
+
+    [std] Rename 'In general' headings to 'General' for consistency
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 9d3011b4224bb63636f4a117967e8ba8110f5ba4
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri May 17 14:11:48 2024 +0200
+
+    [implimits] Rephrase introductory sentence for list of quantities
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 260d3a0d0cde1431dd4221115e1b37979ee07e7d
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu May 16 12:30:44 2024 +0200
+
+    [class.copy.ctor] Remove reference to non-existing example
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 0bc3e030be28ff2191af8e9c9c202bff6e23c320
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu May 16 12:37:12 2024 +0200
+
+    [class.conv.general] Remove vague reference to unhelpful examples
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 861f07de24c5cfbd69840038d8589bc13b24b7e7
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed May 15 21:58:36 2024 +0200
+
+    [cpp.predefined,namespace.future,version.syn] Replace 'C++' with 'this document'
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit a7a2cbd10ea752d49ca286e3fea3e7cbbb9b6e9d
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri May 17 00:44:32 2024 +0200
+
+    [futures.state] Turn note into example
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 88c48bb78815576fb20db42b89f381c580d28b0e
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue May 14 22:41:24 2024 +0200
+
+    [std] Remove colons in front of bulleted lists
+
+commit 9d7aa6108b84a09117463d0b13bc24cf61926897
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue May 14 22:47:38 2024 +0200
+
+    [iterators] Add colon after 'model ... only if' when complete sentences follow
+
+commit 79ac47f7053da4ef20c117e282377591d028e7a5
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed May 15 21:42:09 2024 +0200
+
+    [basic.fundamental,cstdarg.syn] Use full reference for ISO C sections
+
+    Fixes ISO/CS comment (C++23)
+
+commit 2bbf136502811925250b09fd73909b78e0236091
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu May 16 12:51:32 2024 +0200
+
+    [execpol.general] Use 'this document', not 'this standard'
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit e65393f3c87d323258e38c498b849dc57404a20b
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed May 15 22:13:14 2024 +0200
+
+    [format.string.std] Add (R) symbol after Windows
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit dafefea895de358b8edcb6780e3c7b71d209b458
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue May 14 19:12:57 2024 +0200
+
+    [rand.req] Replace 'that Table' with a precise reference
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 361e7769a245aad263574bbe83b9266d8da3b01b
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri May 17 09:42:22 2024 +0200
+
+    [std] Replace 'this standard' with 'this document'
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit e86031dd14e052956fc23ec4dbc1510b7438ba5b
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon May 13 23:19:57 2024 +0200
+
+    [time.format,time.parse] Fix references to ISO week calendar
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 868b0b29ac16370ed8792442a0ab41be91c5d575
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon May 13 19:01:05 2024 +0200
+
+    [std] Avoid hanging paragraphs by introducing "General" subclauses
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit f0580700cf0e8e920ceb3a078b6872a4c16fa225
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed May 15 21:49:31 2024 +0200
+
+    [std] Remove ISO from any mention of 'C'
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 69f184ea599635dac4cd9dc06a3303bed93b26f7
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon May 13 19:30:38 2024 +0200
+
+    [std] Remove mid-sentence 'subclause' introducer
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit ecb071672b02a4b7bc829f87433d98785d9dd701
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon May 13 19:44:40 2024 +0200
+
+    [std] Remove incorrect or duplicative 'this subclause' introducers
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit a249f9f37531fe79e768f19a45f1b1a70685c2c6
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 9 22:48:20 2024 +0100
+
+    [classes] Turn ad-hoc examples into proper examples (#7125)
+
+commit eade3851e174ac014b478b8d4f097103d3b996ae
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu May 16 12:44:01 2024 +0200
+
+    [lex.ccon,expr.prim.lambda.capture] Excise 'ISO' prefix
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 5383169856690cf05d946f058ed861119405d126
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu May 16 14:32:49 2024 +0200
+
+    [fs.class.path.general] Defuse cross-reference to POSIX
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 5731ab6a9122763bf6193d1382a05c7bebe82b38
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 9 23:24:09 2024 +0100
+
+    [time.format] Remove mid-sentence 'subclause' introducer from external reference
+
+commit 856d175973d343d8e16d641221f47357672d9959
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri May 17 14:26:54 2024 +0200
+
+    [lib] Excise Note A, Note B, etc. designations
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 5508a007540d790a8f5cd30f863f4d329edf2694
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu May 16 15:07:27 2024 +0200
+
+    [macros,numerics] Add and use numbered 'formula' environment
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 2b0ff8d6bd285bbe8b27fdab47e268b115a3f930
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Jul 10 11:33:23 2024 +0100
+
+    [lex.string] Replace colon with full stop to end the sentence.
+
+    On request of ISO/CS, for otherwise we should have made the next 'if'
+    lowercase, because: "Grammatically this is the same sentence,
+    as there is no full stop, so the 'if' should be lowercase."
+
+    If a colon really doesn't end a sentence, then we should make it so
+    that the sentence really does end.
+
+commit 064fb0b34eb8cbb14f52dc966c833ef7c749c82c
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue May 14 08:23:07 2024 +0200
+
+    [macros] Prefer page break above 'note' or 'example' introducers
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 13b08d0f58dfea7ae2e19b1d931094d4523a52d2
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Jul 11 01:41:29 2024 +0100
+
+    [layout, styles] New ISO header and footer layout.
+
+    The footer now takes up two lines, one for the copyright and one for
+    the page number.
+
+commit 7f6069c794abb56e51affdc2923e3d33b3a547a8
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Jul 11 12:27:28 2024 +0100
+
+    [cover-reg] Update regular cover
+
+commit f41a619cf852ae638bfe4792ec78ac1f214a7d23
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 12 01:28:38 2024 +0100
+
+    [impldefindex] Reinstate full page mark
+
+    As of 13b08d0f58dfea7ae2e19b1d931094d4523a52d2 we have space for it.
+
+commit b2870b5c87765946f5c4a644da508adcc483045e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 12 01:30:06 2024 +0100
+
+    [macros, std] Create macros for ISO/IEC 60559 and ISO/IEC/IEEE 9945.
+
+    As a side effect, this corrects the title of ISO/IEC 60559(:2020),
+    whose previous version was ISO/IEC/IEEE 60559:2011.
+
+ + diff --git a/papers/n4987.md b/papers/n4987.md new file mode 100644 index 0000000000..d405f0b427 --- /dev/null +++ b/papers/n4987.md @@ -0,0 +1,774 @@ +# N4987 Editors' Report -- Programming Languages -- C++ + +Date: 2024-07-16 + +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. + +## New papers + + * [N4986](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4986.pdf) is the + current working draft for C++26. It replaces + [N4981](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4981.pdf). + * N4987 is this Editors' Report. + +## Motions incorporated into working draft + +### Notes on motions + +All passed motions from CWG and LWG motions 1 through 9 were applied cleanly. +LWG motions 10, 11, and 12 have not yet been applied due to a lack of time, +but will be included in the next draft. + +In CWG Poll 1, issue CWG2144 contains no wording changes since it is subsumed by CWG2876, which is part of Poll 2. +The wording changes from issue CWG2867 of CWG Poll 1 affect the same wording as CWG Poll 7; the wording has been reconciled. + +### Core working group polls + +CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues except 2819, 2858, and 2876 in +[P3345R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3345r0.html) +(Core Language Working Group "ready" Issues for the June, 2024 meeting) to the C++ Working Paper. + +CWG Poll 2. Apply the proposed resolution of issues 2819, 2858, and 2876 in +[P3345R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3345r0.html) +(Core Language Working Group "ready" Issues for the June, 2024 meeting) to the C++ Working Paper. + +CWG Poll 3. Apply the changes in +[P2747R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2747r2.html) +(`constexpr` placement new) to the C++ Working Paper. + +CWG Poll 5. Apply the changes in +[P3144R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3144r2.pdf) +(Deleting a Pointer to an Incomplete Type Should be Ill-formed) to the C++ Working Paper. + +CWG Poll 6. Apply the changes in +[P2963R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2963r3.pdf) +(Ordering of constraints involving fold expressions) to the C++ Working Paper. + +CWG Poll 7. Apply the changes in +[P0963R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p0963r3.html) +(Structured binding declaration as a condition) to the C++ Working Paper. + +CWG Poll 4 did not have consensus. + +### Library working group polls + +LWG Poll 1. Apply the changes for all Ready and Tentatively Ready issues in +[P3341R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3341r0.html) +(C++ Standard Library Ready Issues to be moved in St. Louis, Jun. 2024) to the C++ working paper. + +LWG Poll 2. Apply the changes in +[P2997R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2997r1.html) +(Removing the common reference requirement from the indirectly invocable concepts) to the C++ working paper. + +LWG Poll 3. Apply the changes in +[P2389R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2389r2.html) +(`dextents` Index Type Parameter) to the C++ working paper. + +LWG Poll 4. Apply the changes in +[P3168R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3168r2.html) +(Give `std::optional` Range Support) to the C++ working paper. + +LWG Poll 5. Apply the changes in +[P3217R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3217r0.html) +(Adjoints to "Enabling list-initialization for algorithms": `find_last`) to the C++ working paper. + +LWG Poll 6. Apply the changes in +[P2985R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2985r0.html) +(A type trait for detecting virtual base classes) to the C++ working paper. + +LWG Poll 7. Apply the changes in +[P0843R14](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p0843r14.html) +(`inplace_vector`) to the C++ working paper. + +LWG Poll 8. Accept as a Defect Report and apply the changes in +[P3235R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3235r3.html) +(std::print more types faster with less memory) to the C++ working paper. + +LWG Poll 9. Apply the changes in +[P2968R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2968r2.html) +(Make std::ignore a first-class object) to the C++ working paper. + +**Not yet applied:** + +LWG Poll 10. Apply the changes in +[P2075R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2075r6.html) +(Philox as an extension of the C++ RNG engines) to the C++ working paper. + +LWG Poll 11. Apply the changes in +[P2422R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2422r1.html) +(Remove nodiscard annotations from the standard library specification) to the C++ working paper. + +LWG Poll 12. Apply the changes in +[P2300R10](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html) +(std::execution) to the C++ working paper. + +## Editorial changes + +### Major editorial changes + +A number of editorial changes have been applied that resulted from the ongoing review of the +C++23 IS with the ISO secretariat. + +Mathematical formulae are now numbered, and they must be referenced explicitly from the text. + +We avoid writing references as "subclause 1.2.3" in favour of just "1.2.3" now whenever that is +equally clear. + +Examples in Annex C now use the regular example style, as opposed to the previous ad-hoc style. + +We changed how we refer to the C++ standard itself and how we cite other standards. The page +footers have been changed to show the page number and the copyright over two lines, and the +display of Annex titles has been changed, both in accordance with new ISO style advice. For +details see the following listing. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4981 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/n4981...n4986). + + commit 59d6bfc0c23b61cabb72d9a48270ed1c3b7e02f9 + Author: Alisdair Meredith + Date: Tue Apr 16 09:57:19 2024 -0400 + + [basic.life] Reflow text defining transparently replaceable + + p8 is difficult to read as it defines transparently replaceable + only after it has made all use of it. The edit pulls the + definition of transparently replaceable into its own preceding + paragraph, and then simplifies the sentence that uses this term. + + commit ccfb6adea4373a63b7063f4d41cb9d47876a9347 + Author: Alisdair Meredith + Date: Wed Apr 17 03:08:36 2024 -0400 + + [tab:headers.cpp.fs] Move the debugging library to numberically sorted position (#6927) + + commit c82e95ca91b313bc2cfde60aac9abbd49406d930 + Author: Alisdair Meredith + Date: Wed Apr 17 18:42:19 2024 -0400 + + [zombie.names] Turn lists of zombie names into tables (#6925) + + commit c1eec01966d6383dabfaa4304939ce3be3868f1f + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Thu Apr 18 23:51:53 2024 +0800 + + [range.concat.overview] Remove unnecessary `std::` prefix from example (#6931) + + commit 2de15529d3f98a5de25cecf9ac8ed5b104d776e1 + Author: Jan Schultke + Date: Thu Apr 18 18:00:42 2024 +0200 + + [charconv.syn] Clarify types matching integer-type (#6847) + + commit bae18b69cbca566eac284c8c2f316407fda98d16 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Fri Apr 19 01:21:19 2024 +0800 + + [range.concat.view] Format code to match the current style (#6929) + + commit 79dcca82c22d75fc2b2b6cbc1c338a0229db9a34 + Author: S. B. Tam + Date: Fri Apr 19 19:51:29 2024 +0800 + + [range.utility.conv.general] Fix misapplication of LWG4016 (#6932) + + commit e572580d71dfc8bdb32b8d1a21a2e493676e2151 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Fri Apr 19 21:57:48 2024 +0800 + + [range.concat.iterator] Remove @ outside of codeblocks (#6934) + + commit 5a5295d9c9e1881e58d3b4696fe45f00ef1cc507 + Author: Alisdair Meredith + Date: Fri Apr 19 17:32:53 2024 -0400 + + [index] Add missing entries for Cpp17 concepts (#6940) + + commit 5d4d9508bca4709366a0ff7acb17ba7b3a2efced + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Sat Apr 20 20:16:23 2024 +0800 + + [range.join.with.iterator] Add missing 'template' keyword for dependent name 'emplace' (#5455) + + commit 0ac38fd4c4548ff61cd378f98eff3e18f4463caf + Author: S. B. Tam + Date: Fri Aug 18 15:12:08 2023 +0800 + + Fix typo (`dynamic_rank` => `rank_dynamic`) + + commit 47c2f68d84cb13a7ca83a507fb1f32ddf4774ec1 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Apr 22 23:19:41 2024 +0200 + + [mdspan.layout.leftpad.obs] Remove superfluous \item (#6944) + + commit 4f0779d5a3665af9dd92a96e52d809ba3911495d + Author: Jan Schultke + Date: Tue Apr 23 12:13:27 2024 +0200 + + [intro.execution] Add comma after conditional clause (#6945) + + commit 12b6307589257a803527eb38c43f08f867d59322 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Mon Apr 29 15:23:41 2024 +0800 + + [algorithm.syn,alg.fill] Fix typos in constraints (#6957) + + commit 927d0dba2b068ba9f2136479b4ba05a430eec348 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Mon Apr 29 22:43:49 2024 +0800 + + [alg.rand.generate] Remove brace typo (#6956) + + commit 480adbe4d6ae54e03b6cec5f8784689445c36eee + Author: Jens Maurer + Date: Tue Apr 30 07:48:14 2024 +0200 + + [print.syn] Correctly order println overloads + + commit 3333421819c1b2c6dec1becd0dd2a9fa0aeba8cd + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Tue Apr 30 20:22:43 2024 +0800 + + [range.concat.iterator] Remove superfluous period (#6960) + + commit 513635b371c6a664be2a0ea6fc6939350b9b5e6b + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Fri May 10 00:17:43 2024 +0800 + + [range.reverse.overview] Replace 'equivalent to' with 'then' (#6966) + + commit be18ecc17114bcae4acdad10a3467686510b22c2 + Author: Jens Maurer + Date: Sat May 11 21:51:48 2024 +0200 + + [class.derived.general] Restore accidental reversal of P2662R3 change + + P2662R3 contained a rename of the grammar production "class-or-decltype" + to "class-or-computed-type-specifier". That was editorially reverted + with commit c831ec0b8aac369aa61ce392783865ff04b84b19, but that commit + also accidentally reverted the change from "decltype-specifier" to + "computed-type-specifier" as one of the options for "class-or-decltype". + + This commit restores the latter change, as intended by P2662R3. + + commit 9dcff41d2d26577c2ec0643056187a0f8094832e + Author: Thomas Köppe + Date: Sun May 12 15:24:43 2024 +0100 + + [intro.refs] Fix document titles + + commit 5b332fed1a4577ad08ed469da26c9c7864ea9e11 + Author: Thomas Köppe + Date: Sun May 12 15:31:43 2024 +0100 + + [intro.refs, intro.defs] Update ISO 80000-2:2009 to :2019, change "and" to comma + + commit 85f4bb454effe50029de636d6f206f9c1153236a + Author: Thomas Köppe + Date: Sun May 12 15:53:11 2024 +0100 + + [defns.order.ptr] Add missing hypen in "built-in" + + commit 9cd8d6ce9cc446c94d91e1350b9113906774f0af + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Tue May 14 21:49:55 2024 +0800 + + [format.context] Fix error in example (#6970) + + commit 951ded4880e4295981c0d691915a81d84c2baa9d + Author: Thomas Köppe + Date: Sun May 12 16:01:09 2024 +0100 + + [defns.unblock] Italicize entire term "blocked", not just "block". + + ISO has indicated that this is the acceptable way to state a reference to another definition, in this case "block" [defns.block]. + + commit 1cb3842f83412720a23c664f478a4167cb3162a2 + Author: Jens Maurer + Date: Tue May 14 18:52:30 2024 +0200 + + [styles] Redesign Annex titles per Rice Model Standard + + Fixes ISO/CS comment (C++23 proof) + + commit 2f23560744a966f7a455629506468a02055d53ea + Author: Arthur O'Dwyer + Date: Mon May 20 05:52:26 2024 -0400 + + [alg.ends.with] Replace drop_view with views::drop (#6773) + + commit bbac8a98d303d3ad5ecd9514fb2db37745d16984 + Author: Arthur O'Dwyer + Date: Mon May 20 07:24:27 2024 -0400 + + [dcl.init.list] Eliminate "specialization of initializer_list" (#6258) + + commit ad37b863dec4af4c88d8f2154d5f3e4a9b2a3b33 + Author: Arthur O'Dwyer + Date: Tue May 21 07:12:32 2024 -0400 + + [support.initlist] "initializer list" should be "initializer_list" (#6680) + + This note is talking about the class type, not the grammatical construct. + + commit 2e455af5d6a2bdaac7e9d0d4e7f23ac7a6c0451d + Author: zhihaoy <43971430+zhihaoy@users.noreply.github.com> + Date: Tue May 21 22:50:56 2024 -0700 + + [util.smartptr.shared.cast] Properly describe possibility of double deletion in notes (#7037) + + commit 4b3f32ae814c8da3faccc0dc307904bd250371d9 + Author: Jonathan Wakely + Date: Tue May 28 22:10:36 2024 +0100 + + [input.output] Add cross-references to header synopses (#7005) + + Several of the synopses are not adjacent to the types they declare. + Adding cross-references makes it easier to find the relevant definitions + of classes and class templates. + + Also make the title of [ostream.manip] more specific to its content. + + commit dbf17528619707307f859bac1b36c52654fecfc8 + Author: Arthur O'Dwyer + Date: Mon Jun 10 17:06:15 2024 -0400 + + [container.adaptors] Reorder constructors for flat_* adaptors (#6274) + + Canonicalize the ordering of the constructors for the flat_* adaptors: + - default constructor is first + - each overload without `key_compare` is followed by the corresponding one with `key_compare` + - each pair of overloads without `sorted_unique` is followed by the corresponding pair with `sorted_unique` + + commit ae9b2d7481af415076ffdf33d5920e31e5591eb1 + Author: Jan Schultke + Date: Tue Jun 11 15:32:36 2024 +0200 + + [res.on.exception.handling] Add cross-reference to [except.spec] (#7058) + + commit c95ff039b634388962e1fa242e772da8466d49b6 + Author: Jan Schultke + Date: Wed Jun 12 12:36:02 2024 +0200 + + [stmt.if] Add missing comma after conditional clause (#7061) + + commit 42a38b072a471a112720535c087d96c8f4865a47 + Author: Jan Schultke + Date: Wed Jun 12 18:56:14 2024 +0200 + + [stmt.pre] Add a cross-reference to [intro.execution] (#7060) + + commit 3680e10a5a7eb48b35f150429ce6b3313583bb87 + Author: Jan Schultke + Date: Fri Jun 14 12:48:46 2024 +0200 + + [class.virtual] Add commas (#7062) + + commit 9ad7d63f8db28c88dfa68866d23c5ab742be3f80 + Author: Antony Polukhin + Date: Tue Jun 18 19:00:34 2024 +0300 + + [associative.reqmts.general] Fix typo (#7069) + + commit a24620eced94b1f04fcbd8add49f5e9ca6326ed4 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Jun 21 12:36:01 2024 +0200 + + [class.union.general] Add comma (#7072) + + commit 59e634a8a841f58efeac873459bedf28928a83f9 + Author: Johannes Sixt + Date: Wed Jun 26 11:53:47 2024 +0200 + + [func.require] Add missing formatting of subscript index (#7071) + + commit 6d67d200863e430650047adb651324bc5663b6fc + Author: Jens Maurer + Date: Tue May 14 13:13:42 2024 +0200 + + [diff] Mark examples as such + + Fixes ISO/CS comment (C++23 proof) + + commit 21e022557462544e2e6d32411f71e42a378d2236 + Author: Jonathan Wakely + Date: Tue Jul 2 14:31:08 2024 +0100 + + [depr.c.macros] Fix "macro" singular when referring to two macros + + This should have been applied as part of LWG 4036. + + commit 8bb63636c37f8e67808de1e1ce1142a3028293fd + Author: Jonathan Wakely + Date: Wed Jul 3 20:53:40 2024 +0100 + + [istream.unformatted] add missing semi-colon to list item (#7117) + + commit 8227c196af96f157a539e5181f7a75ab3de3a096 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Jul 5 10:03:47 2024 +0200 + + [except.throw] Add comma (#7118) + + commit 07c20b75a867b66c858de716dfb639b0a9d1da2c + Author: Yihe Li + Date: Sat Jul 6 23:32:43 2024 +0800 + + [version.syn] Remove redundant for __cpp_lib_ranges_enumerate (#7120) + + commit 15b7ea6c95e471888cda2c334ba8ac30cabccf64 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sun Jul 7 10:23:09 2024 +0200 + + [basic.start.main] fix definite article (#7121) + + commit 61d85d3f9b78d792bd1bdb1d15202f9cdd931b31 + Author: Thomas Köppe + Date: Tue Jul 9 00:57:58 2024 +0100 + + [intro.compliance.general] Cite Annex B more normatively. + + commit 2048179f82bbe92dcccee3cc6bbdac4973c77606 + Author: Thomas Köppe + Date: Tue Jul 9 01:25:28 2024 +0100 + + [intro.compliance.general] Cite Annex D more normatively. + + commit 6b67a856495634df3a0bd0d8abee36eb0d3c8c6f + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Jul 9 08:29:50 2024 +0200 + + [temp.inst] Fix definite article + + commit 43c47b42fd1f7cd4d095299aca98666c06e45949 + Author: Thomas Köppe + Date: Tue Jul 9 01:44:08 2024 +0100 + + [uaxid] Clarify that requirements come "from UAX #31", and use "this document". + + commit 7c35cb057ef4885e091bf65c1103d64946e7c8d1 + Author: Thomas Köppe + Date: Tue Jul 9 14:47:10 2024 +0100 + + [std] Make bibliography reference link colour more citely + + commit bc2c80c23133a0581a847bd7fcfaca621ca86ffe + Author: Jens Maurer + Date: Mon May 13 20:17:21 2024 +0200 + + [dcl.init.list] Add commas and period for bulleted list + + Fixes ISO/CS comment (C++23 proof) + + commit 868db7356ad1490890391e8c82888de5c4d4aad4 + Author: Jens Maurer + Date: Mon May 13 20:18:20 2024 +0200 + + [facet.num.get.virtuals] Add missing punctuation + + Fixes ISO/CS comment (C++23 proof) + + commit 77ee6ed3b8865b2bb514cb8446488aa6fb032dda + Author: Jens Maurer + Date: Mon May 13 23:39:13 2024 +0200 + + [lex.literal] Properly format table headings + + Fixes ISO/CS comment (C++23 proof) + + commit cb9850377b88a4d7da12d05bcdf11948c384f699 + Author: Jens Maurer + Date: Mon May 13 23:47:55 2024 +0200 + + [basic.fundamental] Center second column of "integer width" table + + Fixes ISO/CS comment (C++23 proof) + + commit 2a2b8732e0d81dd9f5d3880b70bd451173e5f5fc + Author: Thomas Köppe + Date: Tue Jul 9 15:41:56 2024 +0100 + + [intro.defs] Minor rewording. Avoid sounding like a requirement. + + commit 4746925c7117015480542fd68ad5f595b78173d2 + Author: Jens Maurer + Date: Tue May 14 14:11:53 2024 +0200 + + [numeric.limits.members,bibliography] Remove LIA-1 abbreviation for ISO 10967 + + Fixes ISO/CS comment (C++23 proof) + + commit c18d51ddf436abf39065ea86497161383bba11c0 + Author: Jens Maurer + Date: Wed May 15 09:05:36 2024 +0200 + + [intro.memory] Move footnote about Unicode trademark to [lex.phases] + + Fixes ISO/CS comment (C++23 proof) + + commit 1f32f6aa8000f194f1b5c4daba94d271eea817fb + Author: Jens Maurer + Date: Wed May 15 16:28:34 2024 +0200 + + [diff,bibliography] Move details of old C++ standards to the bibliography + + Fixes ISO/CS comment (C++23 proof) + + commit d5410b4035e3108d48a63434abfff7e377c996d2 + Author: Jens Maurer + Date: Wed May 15 18:31:14 2024 +0200 + + [diff.cpp20,diff.cpp17] Add missing inclusion clause + + commit af4cf904c3d2df0675dbd456af2de2f1259e370c + Author: Jens Maurer + Date: Thu May 16 12:56:12 2024 +0200 + + [std] Rename 'In general' headings to 'General' for consistency + + Fixes ISO/CS comment (C++23 proof) + + commit 9d3011b4224bb63636f4a117967e8ba8110f5ba4 + Author: Jens Maurer + Date: Fri May 17 14:11:48 2024 +0200 + + [implimits] Rephrase introductory sentence for list of quantities + + Fixes ISO/CS comment (C++23 proof) + + commit 260d3a0d0cde1431dd4221115e1b37979ee07e7d + Author: Jens Maurer + Date: Thu May 16 12:30:44 2024 +0200 + + [class.copy.ctor] Remove reference to non-existing example + + Fixes ISO/CS comment (C++23 proof) + + commit 0bc3e030be28ff2191af8e9c9c202bff6e23c320 + Author: Jens Maurer + Date: Thu May 16 12:37:12 2024 +0200 + + [class.conv.general] Remove vague reference to unhelpful examples + + Fixes ISO/CS comment (C++23 proof) + + commit 861f07de24c5cfbd69840038d8589bc13b24b7e7 + Author: Jens Maurer + Date: Wed May 15 21:58:36 2024 +0200 + + [cpp.predefined,namespace.future,version.syn] Replace 'C++' with 'this document' + + Fixes ISO/CS comment (C++23 proof) + + commit a7a2cbd10ea752d49ca286e3fea3e7cbbb9b6e9d + Author: Jens Maurer + Date: Fri May 17 00:44:32 2024 +0200 + + [futures.state] Turn note into example + + Fixes ISO/CS comment (C++23 proof) + + commit 88c48bb78815576fb20db42b89f381c580d28b0e + Author: Jens Maurer + Date: Tue May 14 22:41:24 2024 +0200 + + [std] Remove colons in front of bulleted lists + + commit 9d7aa6108b84a09117463d0b13bc24cf61926897 + Author: Jens Maurer + Date: Tue May 14 22:47:38 2024 +0200 + + [iterators] Add colon after 'model ... only if' when complete sentences follow + + commit 79ac47f7053da4ef20c117e282377591d028e7a5 + Author: Jens Maurer + Date: Wed May 15 21:42:09 2024 +0200 + + [basic.fundamental,cstdarg.syn] Use full reference for ISO C sections + + Fixes ISO/CS comment (C++23) + + commit 2bbf136502811925250b09fd73909b78e0236091 + Author: Jens Maurer + Date: Thu May 16 12:51:32 2024 +0200 + + [execpol.general] Use 'this document', not 'this standard' + + Fixes ISO/CS comment (C++23 proof) + + commit e65393f3c87d323258e38c498b849dc57404a20b + Author: Jens Maurer + Date: Wed May 15 22:13:14 2024 +0200 + + [format.string.std] Add (R) symbol after Windows + + Fixes ISO/CS comment (C++23 proof) + + commit dafefea895de358b8edcb6780e3c7b71d209b458 + Author: Jens Maurer + Date: Tue May 14 19:12:57 2024 +0200 + + [rand.req] Replace 'that Table' with a precise reference + + Fixes ISO/CS comment (C++23 proof) + + commit 361e7769a245aad263574bbe83b9266d8da3b01b + Author: Jens Maurer + Date: Fri May 17 09:42:22 2024 +0200 + + [std] Replace 'this standard' with 'this document' + + Fixes ISO/CS comment (C++23 proof) + + commit e86031dd14e052956fc23ec4dbc1510b7438ba5b + Author: Jens Maurer + Date: Mon May 13 23:19:57 2024 +0200 + + [time.format,time.parse] Fix references to ISO week calendar + + Fixes ISO/CS comment (C++23 proof) + + commit 868b0b29ac16370ed8792442a0ab41be91c5d575 + Author: Jens Maurer + Date: Mon May 13 19:01:05 2024 +0200 + + [std] Avoid hanging paragraphs by introducing "General" subclauses + + Fixes ISO/CS comment (C++23 proof) + + commit f0580700cf0e8e920ceb3a078b6872a4c16fa225 + Author: Jens Maurer + Date: Wed May 15 21:49:31 2024 +0200 + + [std] Remove ISO from any mention of 'C' + + Fixes ISO/CS comment (C++23 proof) + + commit 69f184ea599635dac4cd9dc06a3303bed93b26f7 + Author: Jens Maurer + Date: Mon May 13 19:30:38 2024 +0200 + + [std] Remove mid-sentence 'subclause' introducer + + Fixes ISO/CS comment (C++23 proof) + + commit ecb071672b02a4b7bc829f87433d98785d9dd701 + Author: Jens Maurer + Date: Mon May 13 19:44:40 2024 +0200 + + [std] Remove incorrect or duplicative 'this subclause' introducers + + Fixes ISO/CS comment (C++23 proof) + + commit a249f9f37531fe79e768f19a45f1b1a70685c2c6 + Author: Thomas Köppe + Date: Tue Jul 9 22:48:20 2024 +0100 + + [classes] Turn ad-hoc examples into proper examples (#7125) + + commit eade3851e174ac014b478b8d4f097103d3b996ae + Author: Jens Maurer + Date: Thu May 16 12:44:01 2024 +0200 + + [lex.ccon,expr.prim.lambda.capture] Excise 'ISO' prefix + + Fixes ISO/CS comment (C++23 proof) + + commit 5383169856690cf05d946f058ed861119405d126 + Author: Jens Maurer + Date: Thu May 16 14:32:49 2024 +0200 + + [fs.class.path.general] Defuse cross-reference to POSIX + + Fixes ISO/CS comment (C++23 proof) + + commit 5731ab6a9122763bf6193d1382a05c7bebe82b38 + Author: Thomas Köppe + Date: Tue Jul 9 23:24:09 2024 +0100 + + [time.format] Remove mid-sentence 'subclause' introducer from external reference + + commit 856d175973d343d8e16d641221f47357672d9959 + Author: Jens Maurer + Date: Fri May 17 14:26:54 2024 +0200 + + [lib] Excise Note A, Note B, etc. designations + + Fixes ISO/CS comment (C++23 proof) + + commit 5508a007540d790a8f5cd30f863f4d329edf2694 + Author: Jens Maurer + Date: Thu May 16 15:07:27 2024 +0200 + + [macros,numerics] Add and use numbered 'formula' environment + + Fixes ISO/CS comment (C++23 proof) + + commit 2b0ff8d6bd285bbe8b27fdab47e268b115a3f930 + Author: Thomas Köppe + Date: Wed Jul 10 11:33:23 2024 +0100 + + [lex.string] Replace colon with full stop to end the sentence. + + On request of ISO/CS, for otherwise we should have made the next 'if' + lowercase, because: "Grammatically this is the same sentence, + as there is no full stop, so the 'if' should be lowercase." + + If a colon really doesn't end a sentence, then we should make it so + that the sentence really does end. + + commit 064fb0b34eb8cbb14f52dc966c833ef7c749c82c + Author: Jens Maurer + Date: Tue May 14 08:23:07 2024 +0200 + + [macros] Prefer page break above 'note' or 'example' introducers + + Fixes ISO/CS comment (C++23 proof) + + commit 13b08d0f58dfea7ae2e19b1d931094d4523a52d2 + Author: Thomas Köppe + Date: Thu Jul 11 01:41:29 2024 +0100 + + [layout, styles] New ISO header and footer layout. + + The footer now takes up two lines, one for the copyright and one for + the page number. + + commit 7f6069c794abb56e51affdc2923e3d33b3a547a8 + Author: Thomas Köppe + Date: Thu Jul 11 12:27:28 2024 +0100 + + [cover-reg] Update regular cover + + commit f41a619cf852ae638bfe4792ec78ac1f214a7d23 + Author: Thomas Köppe + Date: Fri Jul 12 01:28:38 2024 +0100 + + [impldefindex] Reinstate full page mark + + As of 13b08d0f58dfea7ae2e19b1d931094d4523a52d2 we have space for it. + + commit b2870b5c87765946f5c4a644da508adcc483045e + Author: Thomas Köppe + Date: Fri Jul 12 01:30:06 2024 +0100 + + [macros, std] Create macros for ISO/IEC 60559 and ISO/IEC/IEEE 9945. + + As a side effect, this corrects the title of ISO/IEC 60559(:2020), + whose previous version was ISO/IEC/IEEE 60559:2011. diff --git a/papers/n4989.html b/papers/n4989.html new file mode 100644 index 0000000000..00eecf259e --- /dev/null +++ b/papers/n4989.html @@ -0,0 +1,569 @@ + + + + + +N4989 Editors’ Report: Programming Languages — C++ + + +

N4989 Editors’ Report:
Programming Languages — C++

+ +

Date: 2024-08-05

+ +

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.

+ +

New papers

+ +
    +
  • N4988 is the +current working draft for C++26. It replaces +N4986.
  • +
  • N4989 is this Editors' Report.
  • +
+ +

Draft approval

+ +

The previous draft +N4986 +was not approved at any WG21 meeting. For approval of this draft, N4988, +please consult the previous Editors' report +N4987 +as well as this one.

+ +

Motions incorporated into working draft

+ +

Notes on motions

+ +

All passed motions from CWG and LWG motions 1 through 9 were applied in the previous draft +N4986. +LWG motions 10, 11, and 12 had not yet been applied due to a lack of time, +and are included in this draft.

+ +

The full list of approved motions is included here for ease of reference.

+ +

Core working group polls

+ +

Already applied in previous draft.

+ +

CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues except 2819, 2858, and 2876 in +P3345R0 +(Core Language Working Group "ready" Issues for the June, 2024 meeting) to the C++ Working Paper.

+ +

CWG Poll 2. Apply the proposed resolution of issues 2819, 2858, and 2876 in +P3345R0 +(Core Language Working Group "ready" Issues for the June, 2024 meeting) to the C++ Working Paper.

+ +

CWG Poll 3. Apply the changes in +P2747R2 +(constexpr placement new) to the C++ Working Paper.

+ +

CWG Poll 5. Apply the changes in +P3144R2 +(Deleting a Pointer to an Incomplete Type Should be Ill-formed) to the C++ Working Paper.

+ +

CWG Poll 6. Apply the changes in +P2963R3 +(Ordering of constraints involving fold expressions) to the C++ Working Paper.

+ +

CWG Poll 7. Apply the changes in +P0963R3 +(Structured binding declaration as a condition) to the C++ Working Paper.

+ +

CWG Poll 4 did not have consensus.

+ +

Library working group polls

+ +

Already applied in previous draft.

+ +

LWG Poll 1. Apply the changes for all Ready and Tentatively Ready issues in +P3341R0 +(C++ Standard Library Ready Issues to be moved in St. Louis, Jun. 2024) to the C++ working paper.

+ +

LWG Poll 2. Apply the changes in +P2997R1 +(Removing the common reference requirement from the indirectly invocable concepts) to the C++ working paper.

+ +

LWG Poll 3. Apply the changes in +P2389R2 +(dextents Index Type Parameter) to the C++ working paper.

+ +

LWG Poll 4. Apply the changes in +P3168R2 +(Give std::optional Range Support) to the C++ working paper.

+ +

LWG Poll 5. Apply the changes in +P3217R0 +(Adjoints to "Enabling list-initialization for algorithms": find_last) to the C++ working paper.

+ +

LWG Poll 6. Apply the changes in +P2985R0 +(A type trait for detecting virtual base classes) to the C++ working paper.

+ +

LWG Poll 7. Apply the changes in +P0843R14 +(inplace_vector) to the C++ working paper.

+ +

LWG Poll 8. Accept as a Defect Report and apply the changes in +P3235R3 +(std::print more types faster with less memory) to the C++ working paper.

+ +

LWG Poll 9. Apply the changes in +P2968R2 +(Make std::ignore a first-class object) to the C++ working paper.

+ +

Newly applied in this draft:

+ +

LWG Poll 10. Apply the changes in +P2075R6 +(Philox as an extension of the C++ RNG engines) to the C++ working paper.

+ +

LWG Poll 11. Apply the changes in +P2422R1 +(Remove nodiscard annotations from the standard library specification) to the C++ working paper.

+ +

LWG Poll 12. Apply the changes in +P2300R10 +(std::execution) to the C++ working paper.

+ +

Editorial changes

+ +

Major editorial changes

+ +

There were no major editorial changes.

+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4986 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 a52859fad0d3bc56ec941fc287d5cebc0fd080dc
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 12 14:35:07 2024 +0100
+
+    [diff.cpp23.dcl.dcl] Fix capitalisation of heading
+
+commit 811e9bb15fe6b8fe0a6e5584525b7839e329126b
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 23 00:19:37 2024 +0100
+
+    [intro.refs] Move footnote
+
+    As requested by ISO/CS.
+
+commit dd306a57cdcce4596fb9d5ce917075eee8e60f4b
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 23 00:22:31 2024 +0100
+
+    [intro.races] Rephrase note to avoid awkward "can not".
+
+    Suggested by ISO/CS.
+
+commit 3dc8333128753e8eb4c39f353aa272a63221e6d5
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 23 00:28:48 2024 +0100
+
+    [library.c] Clarify that Annex F comes from ISO/IEC 9899:2018
+
+commit b303620f529bfe517fb0c79d3e7f644c54a1e6cb
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 23 00:20:42 2024 +0100
+
+    [rand.dist] Remove textual elements from forumla.
+
+    Those were left over from when we converted the text-integrated
+    formula to self-contained, numbered ones.
+
+commit 7228e06a7973282cf1034a9cdb095dd863aef377
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Jul 17 00:48:45 2024 +0100
+
+    [tab:headers.cpp.fs] Use a more appropriate subclause for inplace_vector
+
+commit 3f5771916e846d16330a87df15d35e797ea66437
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Jul 23 17:48:36 2024 -0400
+
+    [depr.c.macros] Cross-reference the C headers for deprecated macros
+
+commit be25cad169c62518e934cd3269e966091b20a4c4
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Jul 22 17:25:04 2024 +0800
+
+    [inplace.vector.syn] Default template argument for `erase`
+
+    The default template argument is already in [inplace.vector.erasure].
+
+commit e0fe4a30614303116dc91357ab1bb483dc98b2ca
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Mon Jul 22 00:24:26 2024 +0800
+
+    [inplace.vector.modifiers] Fix typo
+
+commit 420cff6a620498b6e6b0a4a7f0757bfa8dfb2a1c
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Sun Jul 28 00:05:29 2024 +0800
+
+    [func.search.bm] Remove superfluous the (#7160)
+
+commit cf27216f6aeba4a7e1debed304303fc2e69b2d65
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Mon Jul 22 13:11:05 2024 +0800
+
+    [inplace.vector.erasure] Added missing return statement
+
+commit dc8b2d4d198a307b749832044e2819de1378ace7
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Jul 23 22:28:38 2024 -0400
+
+    [locale.ctype.general] Better cross-ref standard headers
+
+commit f181708d17038c0ebe42aff9d61e79222e5a06b0
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Jul 19 20:33:06 2024 +0100
+
+    [basic.indet] Fix "errorneous" typo
+
+commit 1a15d3a3d84549687eb65a870952441c869f31a9
+Author: A. Jiang <de34@live.cn>
+Date:   Sun Jul 28 07:56:03 2024 +0800
+
+    Make cross-reference more precise. (#7144)
+
+    Co-authored-by: Eelis van der Weegen <eelis@eelis.net>
+
+commit 930502061ea47c184c3b25ed623801dfa5284167
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sun Jul 28 01:57:52 2024 +0200
+
+    [temp.constr.normal] Remove duplicate "the" (#7135)
+
+commit 11e13d5d858f06ec163ece2881af642a23fe5b96
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sun Jul 28 01:58:09 2024 +0200
+
+    [diff.cpp23.expr] Remove duplicate "that" (#7134)
+
+commit 8ead4680a67cacffe82e2fd74e64df76120cb1a9
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Wed Jul 10 20:28:34 2024 +0800
+
+    [variant.visit] Add constexpr to as-variant
+
+commit 8d8861cdc944b784db14be27ce2541071288dcc5
+Author: A. Jiang <de34@live.cn>
+Date:   Mon May 13 00:33:24 2024 +0800
+
+    [print.syn] Show `locking` functions in the synopsis of `<print>`
+
+commit 5c3858e09e73c49748901aceb33acc7cd86bd7de
+Author: Eelis <github.com@contacts.eelis.net>
+Date:   Sun Jul 28 13:35:39 2024 +0200
+
+    [exec.snd.general] Add missing period (#7172)
+
+commit 3e87f29c42ad38e224ac6e7e75dc08220b440189
+Author: Eelis <github.com@contacts.eelis.net>
+Date:   Sun Jul 28 13:37:06 2024 +0200
+
+    [out.ptr.t] Fix bullet placement for item that starts with codeblock (#7173)
+
+commit 81d85dfbee01b8fdf993fac4efeb40fb00b18144
+Author: Eelis <github.com@contacts.eelis.net>
+Date:   Sun Jul 28 13:39:12 2024 +0200
+
+    [range.concat.iterator] Remove stray hyphen (#7171)
+
+commit 500b8f49f28b51c576eb671ee067efcc1bc002a9
+Author: A. Jiang <de34@live.cn>
+Date:   Sun Jul 28 22:22:54 2024 +0800
+
+    [print.syn] Update `locking` to `buffered` (#7168)
+
+    The function names were changed by P3235R3.
+
+commit 9b3d01e82b03e26cf9e1fa06a582ec931ca00052
+Author: Eelis <github.com@contacts.eelis.net>
+Date:   Sun Jul 28 21:16:58 2024 +0200
+
+    [execution.syn] Fix read_env name (#7169)
+
+commit 5bac031ccb4f7ce511c6e95b63b39eee2eb14c87
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Jul 27 00:48:42 2024 +0100
+
+    [stoptoken.general, stopsource.general] Remove DMI from stop-state member
+
+    For stoptoken::stop-state, the default-initialized value is already
+    correct, and no further "{}" initializer is needed.
+
+    For stopsource::stop-state, the DMI "{}" is never used, since the
+    constructor is explicitly specified and not defaulted.
+
+commit 917c271c926214e286f560c4a3f2aadc59dadcb7
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Jul 27 00:12:22 2024 +0100
+
+    [exec.snd.general] Remove disconnected and obsolete paragraph.
+
+commit 609068d41d699b85b0677fbb206235a4bc30fd77
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat Jun 8 16:13:36 2024 +0200
+
+    [array.cons] Fix various wording issues
+
+commit f8468b9606aa4db0a55f1ecde046025876c5de23
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sun Aug 6 21:52:00 2023 +0200
+
+    [expr.cond] itemize p4
+
+commit d9bff4abf4e4de12ef816d3e9df4ed5c6733da64
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Mon Jul 29 23:31:19 2024 +0800
+
+    [coro.generator] Rename the generator's template parameter "V" to "Val" (#7129)
+
+commit aa4a13e9ea6e81e7d2ef5205de9e1f765a27bbbe
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat Aug 19 13:33:10 2023 +0200
+
+    [basic.fundamental] itemize uses of void expressions
+
+commit 0711baa8bf611656aae770a6bc23b7ee96ed5811
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat Aug 19 13:47:04 2023 +0200
+
+    [basic.fundamental] remove redundant void conversion wording
+
+commit 5342083f2c84f6592c455562d8a6b464d39d86ba
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Jun 17 10:55:22 2024 +0700
+
+    [cpp.pre] define, index, and consistently use the term 'logical source line'
+
+commit 56079f18c4751d4dd15fbdf7d50179d2044345f3
+Author: Casey Carter <Casey@Carter.net>
+Date:   Fri Jan 12 10:35:39 2024 -0800
+
+    [structure.specifications] clarify description of Results element
+
+    The text "... 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" clearly indicates that a Result element describes the type and value category of an expression, yet we summarize it as only "a description of the type of the expression".
+
+commit 407c552023c069afc2438cd462049a323c971bb1
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Tue Jul 16 19:41:36 2024 -0400
+
+    [deque, forward.list, list, vector] Fix instances of "FooInsertable into *this"
+
+    Fixes #7133
+
+commit 4bf5bd233461b49924ea330b95698fdc43cf3636
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Apr 25 00:46:41 2024 +0800
+
+    [alg.replace] Fix misapplication of P2248R8 to `std::replace_copy`
+
+    Removes wrongly added default template arguments that are not present in that paper.
+
+commit d0615b3d8b991fd0cd58fbd6b75da727423cff4e
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Jul 23 22:20:27 2024 -0400
+
+    [containers] Consistently xref header synopses from General clauses
+
+commit 35904b92e4bbabd0303f8fb7cbbe3a6142639876
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Apr 27 00:46:29 2024 +0800
+
+    [expr.call] Say implicit object parameter instead of `this`
+
+    And correct the initialization of the implicit object parameter.
+
+commit 7f76c21f933b167d71a1ff12584911e82477454d
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Mon Jul 29 18:48:49 2024 +0100
+
+    [alg.search] Replace "the following corresponding conditions"
+
+    It's not clear which conditions correspond to each overload.
+
+commit 69ddb6ec0b50c92390391ec54b97c92ef2179869
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Jul 29 21:54:11 2024 +0200
+
+    [exec.stopped.opt] Fix indefinite article (#7186)
+
+commit 4800c7b83d2fbde2c63c6811716bf62df047f5ae
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Tue Jul 30 18:02:17 2024 +0800
+
+    [range.join.with.iterator] Fix typo (#7131)
+
+commit 3dba07b8277a59792430cd166192ed41e428c6f7
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Jul 30 12:03:20 2024 +0200
+
+    [exec.util.cmplsig.trans] Fix English grammar (#7188)
+
+commit f640daed4a6304ef4e2c289c6d42e754d06cd4ee
+Author: Anoop Rana <93918384+ranaanoop@users.noreply.github.com>
+Date:   Thu Jul 25 19:57:36 2024 +0530
+
+    [basic.scope.scope] Replaced the term top-level reference with just reference
+
+    [basic.scope.scope] Replaced the term top-level reference with just reference in light of [this issue](https://github.com/cplusplus/CWG/issues/569)
+
+commit 54fb7eb6ada6e7a4d47c9a310675d5cf55bbd5c7
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Jul 30 16:22:02 2024 -0400
+
+    [lex.pptoken] Consistent use of preprocessing vs processing
+
+    There are three cases here all doing the same thing.  Two
+    refer to preprocessing a directive, while the first refers
+    to processing without the pre.
+
+ + diff --git a/papers/n4989.md b/papers/n4989.md new file mode 100644 index 0000000000..6a639a8806 --- /dev/null +++ b/papers/n4989.md @@ -0,0 +1,428 @@ +# N4989 Editors' Report -- Programming Languages -- C++ + +Date: 2024-08-05 + +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. + +## New papers + + * [N4988](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4988.pdf) is the + current working draft for C++26. It replaces + [N4986](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4986.pdf). + * N4989 is this Editors' Report. + +## Draft approval + +The previous draft +[N4986](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4986.pdf) +was not approved at any WG21 meeting. For approval of this draft, N4988, +please consult the previous Editors' report +[N4987](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4987.html) +as well as this one. + +## Motions incorporated into working draft + +### Notes on motions + +All passed motions from CWG and LWG motions 1 through 9 were applied in the previous draft +[N4986](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4986.pdf). +LWG motions 10, 11, and 12 had not yet been applied due to a lack of time, +and are included in this draft. + +The full list of approved motions is included here for ease of reference. + +### Core working group polls + +**Already applied in previous draft.** + +CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues except 2819, 2858, and 2876 in +[P3345R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3345r0.html) +(Core Language Working Group "ready" Issues for the June, 2024 meeting) to the C++ Working Paper. + +CWG Poll 2. Apply the proposed resolution of issues 2819, 2858, and 2876 in +[P3345R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3345r0.html) +(Core Language Working Group "ready" Issues for the June, 2024 meeting) to the C++ Working Paper. + +CWG Poll 3. Apply the changes in +[P2747R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2747r2.html) +(`constexpr` placement new) to the C++ Working Paper. + +CWG Poll 5. Apply the changes in +[P3144R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3144r2.pdf) +(Deleting a Pointer to an Incomplete Type Should be Ill-formed) to the C++ Working Paper. + +CWG Poll 6. Apply the changes in +[P2963R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2963r3.pdf) +(Ordering of constraints involving fold expressions) to the C++ Working Paper. + +CWG Poll 7. Apply the changes in +[P0963R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p0963r3.html) +(Structured binding declaration as a condition) to the C++ Working Paper. + +CWG Poll 4 did not have consensus. + +### Library working group polls + +**Already applied in previous draft.** + +LWG Poll 1. Apply the changes for all Ready and Tentatively Ready issues in +[P3341R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3341r0.html) +(C++ Standard Library Ready Issues to be moved in St. Louis, Jun. 2024) to the C++ working paper. + +LWG Poll 2. Apply the changes in +[P2997R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2997r1.html) +(Removing the common reference requirement from the indirectly invocable concepts) to the C++ working paper. + +LWG Poll 3. Apply the changes in +[P2389R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2389r2.html) +(`dextents` Index Type Parameter) to the C++ working paper. + +LWG Poll 4. Apply the changes in +[P3168R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3168r2.html) +(Give `std::optional` Range Support) to the C++ working paper. + +LWG Poll 5. Apply the changes in +[P3217R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3217r0.html) +(Adjoints to "Enabling list-initialization for algorithms": `find_last`) to the C++ working paper. + +LWG Poll 6. Apply the changes in +[P2985R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2985r0.html) +(A type trait for detecting virtual base classes) to the C++ working paper. + +LWG Poll 7. Apply the changes in +[P0843R14](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p0843r14.html) +(`inplace_vector`) to the C++ working paper. + +LWG Poll 8. Accept as a Defect Report and apply the changes in +[P3235R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3235r3.html) +(std::print more types faster with less memory) to the C++ working paper. + +LWG Poll 9. Apply the changes in +[P2968R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2968r2.html) +(Make std::ignore a first-class object) to the C++ working paper. + +**Newly applied in this draft:** + +LWG Poll 10. Apply the changes in +[P2075R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2075r6.pdf) +(Philox as an extension of the C++ RNG engines) to the C++ working paper. + +LWG Poll 11. Apply the changes in +[P2422R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2422r1.html) +(Remove nodiscard annotations from the standard library specification) to the C++ working paper. + +LWG Poll 12. Apply the changes in +[P2300R10](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html) +(std::execution) to the C++ working paper. + +## Editorial changes + +### Major editorial changes + +There were no major editorial changes. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4986 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/n4986...n4988). + + commit a52859fad0d3bc56ec941fc287d5cebc0fd080dc + Author: Thomas Köppe + Date: Fri Jul 12 14:35:07 2024 +0100 + + [diff.cpp23.dcl.dcl] Fix capitalisation of heading + + commit 811e9bb15fe6b8fe0a6e5584525b7839e329126b + Author: Thomas Köppe + Date: Tue Jul 23 00:19:37 2024 +0100 + + [intro.refs] Move footnote + + As requested by ISO/CS. + + commit dd306a57cdcce4596fb9d5ce917075eee8e60f4b + Author: Thomas Köppe + Date: Tue Jul 23 00:22:31 2024 +0100 + + [intro.races] Rephrase note to avoid awkward "can not". + + Suggested by ISO/CS. + + commit 3dc8333128753e8eb4c39f353aa272a63221e6d5 + Author: Thomas Köppe + Date: Tue Jul 23 00:28:48 2024 +0100 + + [library.c] Clarify that Annex F comes from ISO/IEC 9899:2018 + + commit b303620f529bfe517fb0c79d3e7f644c54a1e6cb + Author: Thomas Köppe + Date: Tue Jul 23 00:20:42 2024 +0100 + + [rand.dist] Remove textual elements from forumla. + + Those were left over from when we converted the text-integrated + formula to self-contained, numbered ones. + + commit 7228e06a7973282cf1034a9cdb095dd863aef377 + Author: Thomas Köppe + Date: Wed Jul 17 00:48:45 2024 +0100 + + [tab:headers.cpp.fs] Use a more appropriate subclause for inplace_vector + + commit 3f5771916e846d16330a87df15d35e797ea66437 + Author: Alisdair Meredith + Date: Tue Jul 23 17:48:36 2024 -0400 + + [depr.c.macros] Cross-reference the C headers for deprecated macros + + commit be25cad169c62518e934cd3269e966091b20a4c4 + Author: A. Jiang + Date: Mon Jul 22 17:25:04 2024 +0800 + + [inplace.vector.syn] Default template argument for `erase` + + The default template argument is already in [inplace.vector.erasure]. + + commit e0fe4a30614303116dc91357ab1bb483dc98b2ca + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Mon Jul 22 00:24:26 2024 +0800 + + [inplace.vector.modifiers] Fix typo + + commit 420cff6a620498b6e6b0a4a7f0757bfa8dfb2a1c + Author: Hewill Kang + Date: Sun Jul 28 00:05:29 2024 +0800 + + [func.search.bm] Remove superfluous the (#7160) + + commit cf27216f6aeba4a7e1debed304303fc2e69b2d65 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Mon Jul 22 13:11:05 2024 +0800 + + [inplace.vector.erasure] Added missing return statement + + commit dc8b2d4d198a307b749832044e2819de1378ace7 + Author: Alisdair Meredith + Date: Tue Jul 23 22:28:38 2024 -0400 + + [locale.ctype.general] Better cross-ref standard headers + + commit f181708d17038c0ebe42aff9d61e79222e5a06b0 + Author: Jonathan Wakely + Date: Fri Jul 19 20:33:06 2024 +0100 + + [basic.indet] Fix "errorneous" typo + + commit 1a15d3a3d84549687eb65a870952441c869f31a9 + Author: A. Jiang + Date: Sun Jul 28 07:56:03 2024 +0800 + + Make cross-reference more precise. (#7144) + + Co-authored-by: Eelis van der Weegen + + commit 930502061ea47c184c3b25ed623801dfa5284167 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sun Jul 28 01:57:52 2024 +0200 + + [temp.constr.normal] Remove duplicate "the" (#7135) + + commit 11e13d5d858f06ec163ece2881af642a23fe5b96 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sun Jul 28 01:58:09 2024 +0200 + + [diff.cpp23.expr] Remove duplicate "that" (#7134) + + commit 8ead4680a67cacffe82e2fd74e64df76120cb1a9 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Wed Jul 10 20:28:34 2024 +0800 + + [variant.visit] Add constexpr to as-variant + + commit 8d8861cdc944b784db14be27ce2541071288dcc5 + Author: A. Jiang + Date: Mon May 13 00:33:24 2024 +0800 + + [print.syn] Show `locking` functions in the synopsis of `` + + commit 5c3858e09e73c49748901aceb33acc7cd86bd7de + Author: Eelis + Date: Sun Jul 28 13:35:39 2024 +0200 + + [exec.snd.general] Add missing period (#7172) + + commit 3e87f29c42ad38e224ac6e7e75dc08220b440189 + Author: Eelis + Date: Sun Jul 28 13:37:06 2024 +0200 + + [out.ptr.t] Fix bullet placement for item that starts with codeblock (#7173) + + commit 81d85dfbee01b8fdf993fac4efeb40fb00b18144 + Author: Eelis + Date: Sun Jul 28 13:39:12 2024 +0200 + + [range.concat.iterator] Remove stray hyphen (#7171) + + commit 500b8f49f28b51c576eb671ee067efcc1bc002a9 + Author: A. Jiang + Date: Sun Jul 28 22:22:54 2024 +0800 + + [print.syn] Update `locking` to `buffered` (#7168) + + The function names were changed by P3235R3. + + commit 9b3d01e82b03e26cf9e1fa06a582ec931ca00052 + Author: Eelis + Date: Sun Jul 28 21:16:58 2024 +0200 + + [execution.syn] Fix read_env name (#7169) + + commit 5bac031ccb4f7ce511c6e95b63b39eee2eb14c87 + Author: Thomas Köppe + Date: Sat Jul 27 00:48:42 2024 +0100 + + [stoptoken.general, stopsource.general] Remove DMI from stop-state member + + For stoptoken::stop-state, the default-initialized value is already + correct, and no further "{}" initializer is needed. + + For stopsource::stop-state, the DMI "{}" is never used, since the + constructor is explicitly specified and not defaulted. + + commit 917c271c926214e286f560c4a3f2aadc59dadcb7 + Author: Thomas Köppe + Date: Sat Jul 27 00:12:22 2024 +0100 + + [exec.snd.general] Remove disconnected and obsolete paragraph. + + commit 609068d41d699b85b0677fbb206235a4bc30fd77 + Author: Eisenwave + Date: Sat Jun 8 16:13:36 2024 +0200 + + [array.cons] Fix various wording issues + + commit f8468b9606aa4db0a55f1ecde046025876c5de23 + Author: Eisenwave + Date: Sun Aug 6 21:52:00 2023 +0200 + + [expr.cond] itemize p4 + + commit d9bff4abf4e4de12ef816d3e9df4ed5c6733da64 + Author: Hewill Kang + Date: Mon Jul 29 23:31:19 2024 +0800 + + [coro.generator] Rename the generator's template parameter "V" to "Val" (#7129) + + commit aa4a13e9ea6e81e7d2ef5205de9e1f765a27bbbe + Author: Eisenwave + Date: Sat Aug 19 13:33:10 2023 +0200 + + [basic.fundamental] itemize uses of void expressions + + commit 0711baa8bf611656aae770a6bc23b7ee96ed5811 + Author: Eisenwave + Date: Sat Aug 19 13:47:04 2023 +0200 + + [basic.fundamental] remove redundant void conversion wording + + commit 5342083f2c84f6592c455562d8a6b464d39d86ba + Author: Alisdair Meredith + Date: Mon Jun 17 10:55:22 2024 +0700 + + [cpp.pre] define, index, and consistently use the term 'logical source line' + + commit 56079f18c4751d4dd15fbdf7d50179d2044345f3 + Author: Casey Carter + Date: Fri Jan 12 10:35:39 2024 -0800 + + [structure.specifications] clarify description of Results element + + The text "... 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" clearly indicates that a Result element describes the type and value category of an expression, yet we summarize it as only "a description of the type of the expression". + + commit 407c552023c069afc2438cd462049a323c971bb1 + Author: Arthur O'Dwyer + Date: Tue Jul 16 19:41:36 2024 -0400 + + [deque, forward.list, list, vector] Fix instances of "FooInsertable into *this" + + Fixes #7133 + + commit 4bf5bd233461b49924ea330b95698fdc43cf3636 + Author: A. Jiang + Date: Thu Apr 25 00:46:41 2024 +0800 + + [alg.replace] Fix misapplication of P2248R8 to `std::replace_copy` + + Removes wrongly added default template arguments that are not present in that paper. + + commit d0615b3d8b991fd0cd58fbd6b75da727423cff4e + Author: Alisdair Meredith + Date: Tue Jul 23 22:20:27 2024 -0400 + + [containers] Consistently xref header synopses from General clauses + + commit 35904b92e4bbabd0303f8fb7cbbe3a6142639876 + Author: A. Jiang + Date: Sat Apr 27 00:46:29 2024 +0800 + + [expr.call] Say implicit object parameter instead of `this` + + And correct the initialization of the implicit object parameter. + + commit 7f76c21f933b167d71a1ff12584911e82477454d + Author: Jonathan Wakely + Date: Mon Jul 29 18:48:49 2024 +0100 + + [alg.search] Replace "the following corresponding conditions" + + It's not clear which conditions correspond to each overload. + + commit 69ddb6ec0b50c92390391ec54b97c92ef2179869 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Jul 29 21:54:11 2024 +0200 + + [exec.stopped.opt] Fix indefinite article (#7186) + + commit 4800c7b83d2fbde2c63c6811716bf62df047f5ae + Author: Hewill Kang + Date: Tue Jul 30 18:02:17 2024 +0800 + + [range.join.with.iterator] Fix typo (#7131) + + commit 3dba07b8277a59792430cd166192ed41e428c6f7 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Jul 30 12:03:20 2024 +0200 + + [exec.util.cmplsig.trans] Fix English grammar (#7188) + + commit f640daed4a6304ef4e2c289c6d42e754d06cd4ee + Author: Anoop Rana <93918384+ranaanoop@users.noreply.github.com> + Date: Thu Jul 25 19:57:36 2024 +0530 + + [basic.scope.scope] Replaced the term top-level reference with just reference + + [basic.scope.scope] Replaced the term top-level reference with just reference in light of [this issue](https://github.com/cplusplus/CWG/issues/569) + + commit 54fb7eb6ada6e7a4d47c9a310675d5cf55bbd5c7 + Author: Alisdair Meredith + Date: Tue Jul 30 16:22:02 2024 -0400 + + [lex.pptoken] Consistent use of preprocessing vs processing + + There are three cases here all doing the same thing. Two + refer to preprocessing a directive, while the first refers + to processing without the pre. diff --git a/papers/n4994.html b/papers/n4994.html new file mode 100644 index 0000000000..1778a35243 --- /dev/null +++ b/papers/n4994.html @@ -0,0 +1,737 @@ + + + + + +N4994 Editors’ Report: Programming Languages — C++ + + +

N4994 Editors’ Report:
Programming Languages — C++

+ +

Date: 2024-10-16

+ +

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.

+ +

New papers

+ +
    +
  • N4993 is the +current working draft for C++26. It replaces +N4988.
  • +
  • N4994 is this Editors' Report.
  • +
+ +

Draft approval

+ +

The previous drafts +N4986 +and +N4988 +were not approved at any WG21 meeting. For approval of this draft, N4993, +please consult the previous Editors' reports +N4987 +and +N4989 +as well as this one.

+ +

No motions

+ +

There have been no new, approved WG21 motions. +This revision contains only editorial changes.

+ +

A few of the editorial changes fix mistakes in our LaTeX sources that were +reported to us by the ISO secretariat during the ongoing publication of C++23.

+ +

Editorial changes

+ +

Major editorial changes

+ +

For this revision, we have reorganised several clauses and subclauses. +As a reminder: the editorial team aims to perform only one major reorganisation +that changes top-level clause numbers per C++ revision, and this is it for C++26.

+ +

The changes create a new clause "Text processing library [text]" that collects +formatting, conversions, locales, regular expressions, and text-related C library +facilities. Clauses are rearranged as:

+ +
    +
  • Algorithms library [algorithms]
  • +
  • Strings library [strings]
  • +
  • Text processing library [text]
  • +
  • Numerics library [numerics]
  • +
  • Time library [time]
  • +
  • Input/output library [input.output]
  • +
+ +

The new [text] clause obtains the following contents:

+ +
    +
  • Primitive numeric conversions [charconv], from [utilities]
  • +
  • Formatting [format], from [utilities]
  • +
  • Text encodings identification [text.encoding], extracted from [localization]
  • +
  • Localization library [localization]
  • +
  • Regular expressions library [re]
  • +
  • C library facilities [cctype.syn], [cwctype.syn], [cwchar.syn], [cuchar.syn], and [c.mb.wcs]
  • +
+ +

Additionally, the following subclauses are moved:

+ +
    +
  • Debugging [debugging] from [utilities] to the end of [diagnostics]
  • +
  • Execution policies [execpol] from [utilities] to the end of [algorithms.parallel]
  • +
  • Class type_index [type.index] from [utilities] to [support.rtti]
  • +
+ +

This removes a number of unrelated clauses from the large [utilities] clause.

+ +

Finally, we spread the synopses in [containers] out to appear right in front +of the classes they define.

+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4988 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 15a43d522467d389bd9340081d65dbf17d44d255
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Aug 5 12:21:56 2024 +0100
+
+    [temp.over.link] Reword to clarify that declarations correspond (#5999)
+
+commit 3c0f4cf0a03892157ebf3a472d3e9450a41f038e
+Author: Lewis Baker <lewissbaker@users.noreply.github.com>
+Date:   Sun Aug 4 09:26:26 2024 +0930
+
+    [snd.expos] Fix typo in definition of SCHED-ENV exposition-only helper
+
+    Change `o1` -> `o2` to reference the expression declared as part of the definition of `SCHED-ENV`.
+
+commit 5056b86597f5ba9278601db46a415f2d76e1bc8f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Aug 2 17:38:05 2024 +0200
+
+    [temp.constr.order] Reflect fold expanded constraints in footnotes
+
+commit c92bc384b118412322f9893832508bf17f46f644
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Aug 1 12:35:50 2024 +0200
+
+    [dcl.fct] Fix obsolete phrasing when defining 'function type'
+
+commit fabbff2d812e0a99bd1162460812ec2f5399636e
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Thu Aug 8 17:15:39 2024 -0400
+
+    [sequences] Consistent comma in "If X, there are no effects" (#7139)
+
+commit 04c5a0c509dbf8f9f81223d1de5bb917cd3074c5
+Author: Hana Dusíková <hanicka@hanicka.net>
+Date:   Tue Aug 20 12:21:43 2024 +0200
+
+    [meta.const.eval] Fix function declaration in example (#7234)
+
+commit ab4c0663dc72f09fb8ef6c366352c9d1a68e8fa9
+Author: Vlad Serebrennikov <serebrennikov.vladislav@gmail.com>
+Date:   Fri Aug 23 22:06:05 2024 +0400
+
+    [expr.prim.lambda.capture] Incorporate ellipsis into "captured by copy" definition
+
+commit 6ea6df4c96653d6696bb0133253ea0159b0f278f
+Author: Vlad Serebrennikov <serebrennikov.vladislav@gmail.com>
+Date:   Sat Aug 24 23:24:01 2024 +0400
+
+    [dcl.type.elab] Remove redundant full stop (#7242)
+
+commit 24ceda755967b022e8e089d4f0cdcf4bc99a4adb
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Mon Aug 26 18:29:28 2024 +0800
+
+    [exec.snd.apply,exec.schedule.from] Properly mark "see below" (#7210)
+
+commit 447b6291061d50a582f72dd42d9d6265857ded5c
+Author: Joachim Wuttke <j.wuttke@fz-juelich.de>
+Date:   Mon Aug 26 22:30:39 2024 +0200
+
+    [numerics] Correct typo Bessell -> Bessel (#7244)
+
+commit db0ca108a9b44ef8f06338ecf68f1e4653be4267
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Thu Aug 29 06:13:18 2024 -0400
+
+    [inplace.vector] Fix some spelling/grammar issues (#7243)
+
+commit 21e477fb6dbfa7813eb2263bfa31c748bdce589b
+Author: Casey Carter <Casey@Carter.net>
+Date:   Fri Aug 30 05:07:36 2024 -0700
+
+    [lib] Remove `inline` from variable templates (#7240)
+
+commit c001805bb769fe237034151d59ddd20835a17298
+Author: A. Jiang <de34@live.cn>
+Date:   Fri Aug 30 20:52:00 2024 +0800
+
+    [lib] Remove `friend class X` (#6427)
+
+    Friendship between library classes is considered an implementation detail.
+
+commit 1fafde9a04a3760debb932839791b1d2047ba432
+Author: A. Jiang <de34@live.cn>
+Date:   Fri Aug 30 20:52:49 2024 +0800
+
+    [fs.class.directory.entry.general] Remove superfluous "unneeded" (#7245)
+
+commit e010cf6cde64a498c2bc4291e7e79e66e8ace79a
+Author: Vlad Serebrennikov <serebrennikov.vladislav@gmail.com>
+Date:   Fri Aug 23 21:03:51 2024 +0400
+
+    [basic.scope.scope] Fix a note about declarations that do not bind names
+
+    The note is saying that declarations of qualified names do not bind names, but this is not supported by normative wording in [dcl.meaning]
+
+commit 36a1f39068e71d69e4ca534c5b72891055675e88
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Wed Sep 4 10:23:14 2024 -0400
+
+    [forward.list] Replace misplaced comma with period (#7246)
+
+commit f23059bf704a48b4805db28441ec73b61054ab9d
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Sep 5 00:03:56 2024 +0800
+
+    [optional.syn] Use `decay_t<T>` directly instead of "see below" (#7247)
+
+commit 9d9a3777f1a571dd2648023fe70848c32aebda09
+Author: Casey Carter <Casey@Carter.net>
+Date:   Sun Sep 8 12:13:53 2024 -0700
+
+    [associative.reqmts.general,unord.req.general] Fix cross-references to [container.alloc.reqmts] and [container.reqmts] (#7249)
+
+    Both paragraphs incorrectly point to [container.reqmts] instead of [container.alloc.reqmts] for "the requirements of an allocator-aware container".
+
+commit d930c5fa6728dd0b599f9c7918a2f0a0f747aaa2
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Mon Sep 16 20:35:33 2024 +0200
+
+    [expr.delete] Remove stray "the" between words (#7253)
+
+commit 9243ba5befaea8fd3e878e6114942db8d556a6e0
+Author: Steve Downey <sdowney@gmail.com>
+Date:   Tue Sep 17 06:13:18 2024 -0400
+
+    [optional.assign] Use itemized list for operator=(U&& v) constraints (#7255)
+
+commit 4930897a2a45fa57fd9d766a24229a9e3f14f23e
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Aug 21 13:58:22 2021 +0200
+
+    [dcl.spec.general,dcl.fct.spec] Clarify duplication of decl-specifiers
+
+commit d0c00bf629f4b91d19176c2397aa3ff7c1c0ce63
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Sep 26 18:49:15 2024 +0200
+
+    [tab:lex.charset.literal] Shorten table heading
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 945b1c071ed511d11a2152aa70e08290f91a7856
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Sep 26 19:11:58 2024 +0200
+
+    [tab:re.matchflag] Shorten table heading
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 4e34492bc7279fedb0e066f4925860e686fa81dc
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Sep 26 19:43:50 2024 +0200
+
+    [rand.req] Fix table headers for longtable continued on following page
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 2b1e6d2952987bf4ada8275212a7bb297bb0c1c7
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Sep 26 20:19:01 2024 +0200
+
+    [macros] Fix duplicate vertical lines visible in tables in [optional.assign]
+
+    Fixes ISO/CS comment (C++23 proof)
+
+commit 0680a08ee677e0970b4460fd614f58b122845047
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu Sep 26 21:59:34 2024 +0100
+
+    [ios.init] Remove unused Init::init_cnt static member (#7263)
+
+    The text that made use of this variable was removed by LWG1123 and has
+    not been present in the WP since N3090. The effects of Init construction
+    and destruction are specified entirely without the use of this variable,
+    so it serves no purpose now.
+
+commit afdd158f555892507bc44c6d372c3b45a7f09832
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Sep 27 00:09:11 2024 +0200
+
+    [styles] Format title of \codeblocktu using 'caption' package
+
+    This restores the C++20 status of the formatting.
+
+commit 2b3e09e2cc773b7205310917c5a6b2bdd87340af
+Author: Casey Carter <Casey@Carter.net>
+Date:   Tue Oct 1 03:22:29 2024 -0700
+
+    [inplace.vector.cons] "Constructs an object" is redundant (#7252)
+
+commit 70954edf0b2c915d9b2ca4a1cff99b1c1cba2089
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Oct 1 23:09:04 2024 -0400
+
+    [depr.lit] Fix grammar according to P2361R6
+
+    P2361R6 introduced the notion of unevaluated strings, and
+    updated the grammar for literal operator function accodingly.
+    Unfortunely, the corresponding grammar reference that was
+    deprecated was not similarly updated.
+
+commit 08b167d5476c9fd02a7a0484ae031cb358a99ddf
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Sat Oct 5 22:24:02 2024 +0100
+
+    [priqueue.cons.alloc] Add missing initialization for comp (#7291)
+
+    This is consistent with p2 and p8 which also value-initialize it.
+
+commit 738b14f990e0575a3ca63b579d87edb5a6133ffb
+Author: Casey Carter <Casey@Carter.net>
+Date:   Sat Oct 5 15:03:04 2024 -0700
+
+    [array.creation] Clarify "Mandates" for `to_array` overloads (#7286)
+
+    It's confusing that these `to_array` overloads require `T` to be constructible from various types, when they actually construct `remove_cv_t<T>` objects. We experts know that initialization doesn't depend on the cv-qualification of the target type ([dcl.init.general]/16), but there's no need to make readers jump through hoops to understand the spec.
+
+commit d5c9f2d248860e8e7de78f595b93a8b01c7e02c8
+Author: Lewis Baker <lewissbaker@users.noreply.github.com>
+Date:   Tue Oct 8 21:07:48 2024 +1030
+
+    [exec.split,exec.when.all] Fix typo stop_callback_of_t -> stop_callback_for_t (#7295)
+
+commit 58c01ba5765e8c91ce4aab462d25247167a7e481
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Oct 8 11:38:42 2024 +0100
+
+    [re.grammar] Add missing backslash to UnicodeEscapeSequence example (#7290)
+
+commit ebef68dd9f1c3bccfe06d14eb83c05a7a35dcec3
+Author: Lewis Baker <lewissbaker@users.noreply.github.com>
+Date:   Tue Oct 8 22:06:23 2024 +1030
+
+    [exec.just] Add missing LaTeX escape for product-type construction (#7216)
+
+commit 7ea8f59e19842e720360f15b64c2199ea27641ac
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Oct 10 17:53:54 2024 +0800
+
+    [mutex.syn] Add missing ',' for consistency
+
+commit 7c6322a59e3359c5002357831328b25939cd5383
+Author: Lewis Baker <lewissbaker@users.noreply.github.com>
+Date:   Sun Oct 13 04:07:30 2024 +1030
+
+    [stoptoken.concepts] Remove redundant 'swappable<Token>' clause from 'stoppable_token' concept (#7299)
+
+    The `stoppable_token<Token>` concept requires both `copyable<Token>` and `swappable<Token>`. However, the `copyable<Token>` requirement already subsumes `movable<Token>`, which subsumes `swappable<Token>`.
+
+    Therefore the requirement for `swappable<Token>` can be removed from the `stoppable_token` concept definition with no semantic change.
+
+commit 9bf42221ab5a52ef10cb980a22e8a9617dbbf18b
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Oct 12 22:39:57 2024 +0200
+
+    [rcu.syn] Add missing ',' in comment (#7301)
+
+commit a0411db859cf1eabc2be24a5d2add4eaf288dac5
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Oct 14 12:30:30 2024 +0200
+
+    [expr.const] Add paragraph number for general example
+
+commit 3982d5d5758df949e3c2e0174c72758189be6f2e
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Oct 14 08:54:22 2024 -0400
+
+    [except.ctor] Retitle subclause as 'stack unwinding' (#7282)
+
+    The purpose of this subclause is to define stack unwinding,
+    which in specified in terms of the lifetime of objects, not
+    just class types.  Hence, while much of the text is addressing
+    interactions with contructors and destructors (the original
+    subclause title) it does more than just that.
+
+commit 4eb30d3d618ef44ae3925a1a62090bbbbfe8cabf
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Oct 16 07:39:15 2024 -0400
+
+    [cpp.subst] change "proprocessing file" to "translation unit" (#7293)
+
+    The term 'preprocessing translation unit' is defined in [lex.separate]
+    while the term 'preprocessing file' is never defined, and is
+    not used anywhere else in the standard.  Prefer to use the
+    specified term, as it reasonably covers this case.
+
+commit 40228c690cb8d2ac27bd54bdddeabe425bd022b2
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Oct 16 07:40:20 2024 -0400
+
+    [cpp.import] Change "directive" to "definition" in "active macro directive" (#7292)
+
+    The term 'active macro directive' is defined in p6, but never used.
+    Meanwhile, there are multiple uses of 'active macro definition' but
+    that term is never defined, including in the very sentence following
+    the definition of the unused term, and in other clauses that
+    cross-reference to this clause for their definition.
+
+commit 47da0e8b88bf1aa20aa474edf04a6d29e70b7563
+Author: Anders Schau Knatten <anders@knatten.org>
+Date:   Wed Oct 16 13:41:26 2024 +0200
+
+    [over.oper.general] Change "basic type" to "fundamental type" (#7287)
+
+    The term "basic type" is used twice in this note but it's never defined anywhere, nor used.
+
+commit 7fe7519a5af674cd914344c650529f743fd92fc2
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Oct 1 22:13:53 2024 -0400
+
+    [except.handle] Remove confusing comparison to variadic functions
+
+    The analogy that the ellipsis in an exception handler was similar to an
+    ellipsis in a function declaration may have made sense at one time, but
+    the comparison with a syntax using a macro based API calling 'va_arg'
+    to access its contents --- something that is not possible for an
+    exception handler --- seems more confusing than helpful today.
+
+commit d225f51f8cb799fb014cb73beb7dcccc044392cc
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Aug 20 11:58:24 2024 +0100
+
+    [text.encoding.aliases] Add note about what isn't required
+
+    Make it explicit that `copyable` is intended, rather than `semiregular`,
+    and that the return types of `begin()` and `end()` can differ.
+
+    Also remove a FIXME comment for something that doesn't need fixing.
+    These requirements on a type are specified in our usual form, it would
+    be wrong to use _Remarks_: or _Requires_: here.
+
+commit 6338d95ae620f5e4d37d27a39a40f9de9af37b77
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Oct 16 08:47:02 2024 -0400
+
+    [lex.charset] Introduce parent subclause [lex.char] for character sets and UCNs (#7067)
+
+    The grammar for universal-character-name is oddly sandwiched into the
+    middle of the subclause talking about the different character sets used
+    by the standard.  To improve the flow, extract that grammar into its own
+    subclause.
+
+    In the extraction, I make three other clarifying changes.  First, describe
+    this new subclause as 'a way to name any element of the of the translation
+    character set using just the basic character set' rather than simply
+    'a way to name other characters'. Then, merge the sentence on where universal
+    characters are prohibited into the new intro sentence describing universal
+    characters, to make clear that there is no contradiction between nominating
+    a character, and how that character can be used. Finally, remove the 'one of'
+    in the grammar where there is only one option to choose.
+
+commit 9b6b757f34bf4a1eeb6a66481a444b83f1ee5770
+Author: Matthias Kretz <m.kretz@gsi.de>
+Date:   Thu Sep 12 21:41:02 2024 +0200
+
+    [sf.cmath.assoc.laguerre,sf.cmath.assoc.legendre] Add reference to eq
+
+    The associated Laguerre/Legendre functions build on the
+    Laguerre/Legendre functions, which are defined in different equations.
+    Point to them from the associated functions.
+
+    Also use the correct \ell as used in the formula.
+
+commit 0456a32e41772b0a68b4055fb4e6533cb64e0e3d
+Author: Yihe Li <winmikedows@hotmail.com>
+Date:   Thu Sep 5 23:59:58 2024 +0800
+
+    [utility.syn, flat.map.defn] Remove all [[nodiscard]] from library wording
+
+commit 8b2c7fc3c58bd109c82a016ee2cc5b691bdcd853
+Author: Eisenwave <me@eisenwave.net>
+Date:   Mon Jun 10 23:22:04 2024 +0200
+
+    [expr.new] Extend example for new-expressions with zero size arrays
+
+commit fb34daf31b53389cc35b3f5f65a69785fc6dd1de
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Jul 23 22:32:52 2024 -0400
+
+    [char.traits] Better cross-reference several headers
+
+commit 220cb742e8056ad033ad8dce5630d7d3acaa4c7d
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 16 15:37:39 2024 +0100
+
+    [debugging] Move [debugging] to the end of Clause [diagnostics]
+
+    Part of the C++26 clause restructuring (#5315).
+
+commit 7a2dafa6b4cca842e264bfd544b69452fb448c39
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 16 15:43:39 2024 +0100
+
+    [execpol] Move [execpol] to the end of subclause [algorithms.parallel]
+
+    Part of the C++26 clause restructuring (#5315).
+
+commit 93e2e1c6bcf5e9c3e551d964978e8bf241c392a4
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 16 15:52:54 2024 +0100
+
+    [type.index] Move [type.index] into subclause [support.rtti]
+
+    The subclause is integrated into the structure of [support.rtti],
+    meaning that the synopsis becomes a sibling of the rest, and the
+    subdivisions of the remaining text are removed (in analogy with
+    [type.info]).
+
+    Part of the C++26 clause restructuring (#5315).
+
+commit cdb120a4aee270f4e6e40dd7b07885c70651224e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 16 17:25:51 2024 +0100
+
+    [containers] Move synopses right in front of the classes they define
+
+    Part of the C++26 clause restructuring (#5315).
+
+commit b7e389c9feca4839f77ad60985f509e01f96a399
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 16 15:27:06 2024 +0100
+
+    [std] Reorder clauses: [algorithm], [strings]
+
+    Part of the C++26 clause restructuring (#5315).
+
+commit 5512050c2db44d87566d25ce4f70b530624cb330
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 16 15:36:47 2024 +0100
+
+    [std] Create new top-level Clause [text], following [strings]
+
+    Part of the C++26 clause restructuring (#5315).
+
+commit fc6f670832980fc7b8219cb6945592cbe45d9239
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 16 19:01:21 2024 +0100
+
+    [text, re] Move [re] into [text]
+
+    Part of the C++26 clause restructuring (#5315).
+
+commit 5d106373aada591874ab5e38301502b3012e0502
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 16 19:06:03 2024 +0100
+
+    [text, localization] Move [localization] into [text]
+
+    The subclause [text.encodings] is extracted and elevated to a sibling
+    subclause of [localization].
+
+    Part of the C++26 clause restructuring (#5315).
+
+commit 804846a56f7e73dafe4ebd621fa81097d2e94603
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 16 20:15:42 2024 +0100
+
+    [charconv, format] Move [charconv], [format] to [text]
+
+    Part of the C++26 clause restructuring (#5315).
+
+commit 4b1a9a76c29c31cc3f679a8bdb1603842baf3501
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 16 20:31:33 2024 +0100
+
+    [text, c.strings] Move text-related parts of [c.strings] to [text]
+
+    The text-related subclauses [cctype.syn], [cwctype.syn], [cwchar.syn],
+    [cuchar.syn], and [c.mb.wcs] are moved to a new subclause [text.c.strings].
+
+    Part of the C++26 clause restructuring (#5226, #5315).
+
+commit 8003b627a7e336c2e9f350a3bb1ad395ec7c1cc7
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Wed Oct 16 19:41:35 2024 +0000
+
+    [expr, temp.arg.nontype] Use 'pointer to' instead of 'address of' (#6174)
+
+    Specifically, in:
+     * [expr.prim.lambda.closure]p8, p11
+     * [expr.const]p13.3
+     * [temp.arg.nontype]p3
+
+commit 198e991fed47efcd8b7fe1ad98ecde4d8722a201
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Oct 2 15:55:49 2024 -0400
+
+    [except.handle] group all paragraphs on searching for handler
+
+    This commit moves all of the paragraphs involved in the search for a
+    handler for an exception into a single logical sequence.
+
+    After this change, [except.spec] deals only with specifying the
+    'noexcept' function decorator and its interaction with the
+    'noexcept' operator, and contains no text regarding exceptions
+    themselves.  It might be appropriate to move that subclause into
+    the [dcl] structure at a future date.
+
+ + diff --git a/papers/n4994.md b/papers/n4994.md new file mode 100644 index 0000000000..223aaa59bd --- /dev/null +++ b/papers/n4994.md @@ -0,0 +1,590 @@ +# N4994 Editors' Report -- Programming Languages -- C++ + +Date: 2024-10-16 + +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. + +## New papers + + * [N4993](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4993.pdf) is the + current working draft for C++26. It replaces + [N4988](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4988.pdf). + * N4994 is this Editors' Report. + +## Draft approval + +The previous drafts +[N4986](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4986.pdf) +and +[N4988](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4988.pdf) +were not approved at any WG21 meeting. For approval of this draft, N4993, +please consult the previous Editors' reports +[N4987](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4987.html) +and +[N4989](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4989.html) +as well as this one. + +## No motions + +There have been no new, approved WG21 motions. +This revision contains only editorial changes. + +A few of the editorial changes fix mistakes in our LaTeX sources that were +reported to us by the ISO secretariat during the ongoing publication of C++23. + +## Editorial changes + +### Major editorial changes + +For this revision, we have reorganised several clauses and subclauses. +As a reminder: the editorial team aims to perform only one major reorganisation +that changes top-level clause numbers per C++ revision, and this is it for C++26. + +The changes create a new clause "Text processing library `[text]`" that collects +formatting, conversions, locales, regular expressions, and text-related C library +facilities. Clauses are rearranged as: + + * Algorithms library `[algorithms]` + * Strings library `[strings]` + * Text processing library `[text]` + * Numerics library `[numerics]` + * Time library `[time]` + * Input/output library `[input.output]` + +The new `[text]` clause obtains the following contents: + + * Primitive numeric conversions `[charconv]`, from `[utilities]` + * Formatting `[format]`, from `[utilities]` + * Text encodings identification `[text.encoding]`, extracted from `[localization]` + * Localization library `[localization]` + * Regular expressions library `[re]` + * C library facilities `[cctype.syn]`, `[cwctype.syn]`, `[cwchar.syn]`, `[cuchar.syn]`, and `[c.mb.wcs]` + +Additionally, the following subclauses are moved: + +* Debugging `[debugging]` from `[utilities]` to the end of `[diagnostics]` +* Execution policies `[execpol]` from `[utilities]` to the end of `[algorithms.parallel]` +* Class `type_index` `[type.index]` from `[utilities]` to `[support.rtti]` + +This removes a number of unrelated clauses from the large `[utilities]` clause. + +Finally, we spread the synopses in `[containers]` out to appear right in front +of the classes they define. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4988 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/n4988...n4993). + + commit 15a43d522467d389bd9340081d65dbf17d44d255 + Author: Thomas Köppe + Date: Mon Aug 5 12:21:56 2024 +0100 + + [temp.over.link] Reword to clarify that declarations correspond (#5999) + + commit 3c0f4cf0a03892157ebf3a472d3e9450a41f038e + Author: Lewis Baker + Date: Sun Aug 4 09:26:26 2024 +0930 + + [snd.expos] Fix typo in definition of SCHED-ENV exposition-only helper + + Change `o1` -> `o2` to reference the expression declared as part of the definition of `SCHED-ENV`. + + commit 5056b86597f5ba9278601db46a415f2d76e1bc8f + Author: Jens Maurer + Date: Fri Aug 2 17:38:05 2024 +0200 + + [temp.constr.order] Reflect fold expanded constraints in footnotes + + commit c92bc384b118412322f9893832508bf17f46f644 + Author: Jens Maurer + Date: Thu Aug 1 12:35:50 2024 +0200 + + [dcl.fct] Fix obsolete phrasing when defining 'function type' + + commit fabbff2d812e0a99bd1162460812ec2f5399636e + Author: Arthur O'Dwyer + Date: Thu Aug 8 17:15:39 2024 -0400 + + [sequences] Consistent comma in "If X, there are no effects" (#7139) + + commit 04c5a0c509dbf8f9f81223d1de5bb917cd3074c5 + Author: Hana Dusíková + Date: Tue Aug 20 12:21:43 2024 +0200 + + [meta.const.eval] Fix function declaration in example (#7234) + + commit ab4c0663dc72f09fb8ef6c366352c9d1a68e8fa9 + Author: Vlad Serebrennikov + Date: Fri Aug 23 22:06:05 2024 +0400 + + [expr.prim.lambda.capture] Incorporate ellipsis into "captured by copy" definition + + commit 6ea6df4c96653d6696bb0133253ea0159b0f278f + Author: Vlad Serebrennikov + Date: Sat Aug 24 23:24:01 2024 +0400 + + [dcl.type.elab] Remove redundant full stop (#7242) + + commit 24ceda755967b022e8e089d4f0cdcf4bc99a4adb + Author: Hewill Kang + Date: Mon Aug 26 18:29:28 2024 +0800 + + [exec.snd.apply,exec.schedule.from] Properly mark "see below" (#7210) + + commit 447b6291061d50a582f72dd42d9d6265857ded5c + Author: Joachim Wuttke + Date: Mon Aug 26 22:30:39 2024 +0200 + + [numerics] Correct typo Bessell -> Bessel (#7244) + + commit db0ca108a9b44ef8f06338ecf68f1e4653be4267 + Author: Arthur O'Dwyer + Date: Thu Aug 29 06:13:18 2024 -0400 + + [inplace.vector] Fix some spelling/grammar issues (#7243) + + commit 21e477fb6dbfa7813eb2263bfa31c748bdce589b + Author: Casey Carter + Date: Fri Aug 30 05:07:36 2024 -0700 + + [lib] Remove `inline` from variable templates (#7240) + + commit c001805bb769fe237034151d59ddd20835a17298 + Author: A. Jiang + Date: Fri Aug 30 20:52:00 2024 +0800 + + [lib] Remove `friend class X` (#6427) + + Friendship between library classes is considered an implementation detail. + + commit 1fafde9a04a3760debb932839791b1d2047ba432 + Author: A. Jiang + Date: Fri Aug 30 20:52:49 2024 +0800 + + [fs.class.directory.entry.general] Remove superfluous "unneeded" (#7245) + + commit e010cf6cde64a498c2bc4291e7e79e66e8ace79a + Author: Vlad Serebrennikov + Date: Fri Aug 23 21:03:51 2024 +0400 + + [basic.scope.scope] Fix a note about declarations that do not bind names + + The note is saying that declarations of qualified names do not bind names, but this is not supported by normative wording in [dcl.meaning] + + commit 36a1f39068e71d69e4ca534c5b72891055675e88 + Author: Arthur O'Dwyer + Date: Wed Sep 4 10:23:14 2024 -0400 + + [forward.list] Replace misplaced comma with period (#7246) + + commit f23059bf704a48b4805db28441ec73b61054ab9d + Author: A. Jiang + Date: Thu Sep 5 00:03:56 2024 +0800 + + [optional.syn] Use `decay_t` directly instead of "see below" (#7247) + + commit 9d9a3777f1a571dd2648023fe70848c32aebda09 + Author: Casey Carter + Date: Sun Sep 8 12:13:53 2024 -0700 + + [associative.reqmts.general,unord.req.general] Fix cross-references to [container.alloc.reqmts] and [container.reqmts] (#7249) + + Both paragraphs incorrectly point to [container.reqmts] instead of [container.alloc.reqmts] for "the requirements of an allocator-aware container". + + commit d930c5fa6728dd0b599f9c7918a2f0a0f747aaa2 + Author: Jan Schultke + Date: Mon Sep 16 20:35:33 2024 +0200 + + [expr.delete] Remove stray "the" between words (#7253) + + commit 9243ba5befaea8fd3e878e6114942db8d556a6e0 + Author: Steve Downey + Date: Tue Sep 17 06:13:18 2024 -0400 + + [optional.assign] Use itemized list for operator=(U&& v) constraints (#7255) + + commit 4930897a2a45fa57fd9d766a24229a9e3f14f23e + Author: Jens Maurer + Date: Sat Aug 21 13:58:22 2021 +0200 + + [dcl.spec.general,dcl.fct.spec] Clarify duplication of decl-specifiers + + commit d0c00bf629f4b91d19176c2397aa3ff7c1c0ce63 + Author: Jens Maurer + Date: Thu Sep 26 18:49:15 2024 +0200 + + [tab:lex.charset.literal] Shorten table heading + + Fixes ISO/CS comment (C++23 proof) + + commit 945b1c071ed511d11a2152aa70e08290f91a7856 + Author: Jens Maurer + Date: Thu Sep 26 19:11:58 2024 +0200 + + [tab:re.matchflag] Shorten table heading + + Fixes ISO/CS comment (C++23 proof) + + commit 4e34492bc7279fedb0e066f4925860e686fa81dc + Author: Jens Maurer + Date: Thu Sep 26 19:43:50 2024 +0200 + + [rand.req] Fix table headers for longtable continued on following page + + Fixes ISO/CS comment (C++23 proof) + + commit 2b1e6d2952987bf4ada8275212a7bb297bb0c1c7 + Author: Jens Maurer + Date: Thu Sep 26 20:19:01 2024 +0200 + + [macros] Fix duplicate vertical lines visible in tables in [optional.assign] + + Fixes ISO/CS comment (C++23 proof) + + commit 0680a08ee677e0970b4460fd614f58b122845047 + Author: Jonathan Wakely + Date: Thu Sep 26 21:59:34 2024 +0100 + + [ios.init] Remove unused Init::init_cnt static member (#7263) + + The text that made use of this variable was removed by LWG1123 and has + not been present in the WP since N3090. The effects of Init construction + and destruction are specified entirely without the use of this variable, + so it serves no purpose now. + + commit afdd158f555892507bc44c6d372c3b45a7f09832 + Author: Jens Maurer + Date: Fri Sep 27 00:09:11 2024 +0200 + + [styles] Format title of \codeblocktu using 'caption' package + + This restores the C++20 status of the formatting. + + commit 2b3e09e2cc773b7205310917c5a6b2bdd87340af + Author: Casey Carter + Date: Tue Oct 1 03:22:29 2024 -0700 + + [inplace.vector.cons] "Constructs an object" is redundant (#7252) + + commit 70954edf0b2c915d9b2ca4a1cff99b1c1cba2089 + Author: Alisdair Meredith + Date: Tue Oct 1 23:09:04 2024 -0400 + + [depr.lit] Fix grammar according to P2361R6 + + P2361R6 introduced the notion of unevaluated strings, and + updated the grammar for literal operator function accodingly. + Unfortunely, the corresponding grammar reference that was + deprecated was not similarly updated. + + commit 08b167d5476c9fd02a7a0484ae031cb358a99ddf + Author: Jonathan Wakely + Date: Sat Oct 5 22:24:02 2024 +0100 + + [priqueue.cons.alloc] Add missing initialization for comp (#7291) + + This is consistent with p2 and p8 which also value-initialize it. + + commit 738b14f990e0575a3ca63b579d87edb5a6133ffb + Author: Casey Carter + Date: Sat Oct 5 15:03:04 2024 -0700 + + [array.creation] Clarify "Mandates" for `to_array` overloads (#7286) + + It's confusing that these `to_array` overloads require `T` to be constructible from various types, when they actually construct `remove_cv_t` objects. We experts know that initialization doesn't depend on the cv-qualification of the target type ([dcl.init.general]/16), but there's no need to make readers jump through hoops to understand the spec. + + commit d5c9f2d248860e8e7de78f595b93a8b01c7e02c8 + Author: Lewis Baker + Date: Tue Oct 8 21:07:48 2024 +1030 + + [exec.split,exec.when.all] Fix typo stop_callback_of_t -> stop_callback_for_t (#7295) + + commit 58c01ba5765e8c91ce4aab462d25247167a7e481 + Author: Jonathan Wakely + Date: Tue Oct 8 11:38:42 2024 +0100 + + [re.grammar] Add missing backslash to UnicodeEscapeSequence example (#7290) + + commit ebef68dd9f1c3bccfe06d14eb83c05a7a35dcec3 + Author: Lewis Baker + Date: Tue Oct 8 22:06:23 2024 +1030 + + [exec.just] Add missing LaTeX escape for product-type construction (#7216) + + commit 7ea8f59e19842e720360f15b64c2199ea27641ac + Author: A. Jiang + Date: Thu Oct 10 17:53:54 2024 +0800 + + [mutex.syn] Add missing ',' for consistency + + commit 7c6322a59e3359c5002357831328b25939cd5383 + Author: Lewis Baker + Date: Sun Oct 13 04:07:30 2024 +1030 + + [stoptoken.concepts] Remove redundant 'swappable' clause from 'stoppable_token' concept (#7299) + + The `stoppable_token` concept requires both `copyable` and `swappable`. However, the `copyable` requirement already subsumes `movable`, which subsumes `swappable`. + + Therefore the requirement for `swappable` can be removed from the `stoppable_token` concept definition with no semantic change. + + commit 9bf42221ab5a52ef10cb980a22e8a9617dbbf18b + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Oct 12 22:39:57 2024 +0200 + + [rcu.syn] Add missing ',' in comment (#7301) + + commit a0411db859cf1eabc2be24a5d2add4eaf288dac5 + Author: Jens Maurer + Date: Mon Oct 14 12:30:30 2024 +0200 + + [expr.const] Add paragraph number for general example + + commit 3982d5d5758df949e3c2e0174c72758189be6f2e + Author: Alisdair Meredith + Date: Mon Oct 14 08:54:22 2024 -0400 + + [except.ctor] Retitle subclause as 'stack unwinding' (#7282) + + The purpose of this subclause is to define stack unwinding, + which in specified in terms of the lifetime of objects, not + just class types. Hence, while much of the text is addressing + interactions with contructors and destructors (the original + subclause title) it does more than just that. + + commit 4eb30d3d618ef44ae3925a1a62090bbbbfe8cabf + Author: Alisdair Meredith + Date: Wed Oct 16 07:39:15 2024 -0400 + + [cpp.subst] change "proprocessing file" to "translation unit" (#7293) + + The term 'preprocessing translation unit' is defined in [lex.separate] + while the term 'preprocessing file' is never defined, and is + not used anywhere else in the standard. Prefer to use the + specified term, as it reasonably covers this case. + + commit 40228c690cb8d2ac27bd54bdddeabe425bd022b2 + Author: Alisdair Meredith + Date: Wed Oct 16 07:40:20 2024 -0400 + + [cpp.import] Change "directive" to "definition" in "active macro directive" (#7292) + + The term 'active macro directive' is defined in p6, but never used. + Meanwhile, there are multiple uses of 'active macro definition' but + that term is never defined, including in the very sentence following + the definition of the unused term, and in other clauses that + cross-reference to this clause for their definition. + + commit 47da0e8b88bf1aa20aa474edf04a6d29e70b7563 + Author: Anders Schau Knatten + Date: Wed Oct 16 13:41:26 2024 +0200 + + [over.oper.general] Change "basic type" to "fundamental type" (#7287) + + The term "basic type" is used twice in this note but it's never defined anywhere, nor used. + + commit 7fe7519a5af674cd914344c650529f743fd92fc2 + Author: Alisdair Meredith + Date: Tue Oct 1 22:13:53 2024 -0400 + + [except.handle] Remove confusing comparison to variadic functions + + The analogy that the ellipsis in an exception handler was similar to an + ellipsis in a function declaration may have made sense at one time, but + the comparison with a syntax using a macro based API calling 'va_arg' + to access its contents --- something that is not possible for an + exception handler --- seems more confusing than helpful today. + + commit d225f51f8cb799fb014cb73beb7dcccc044392cc + Author: Jonathan Wakely + Date: Tue Aug 20 11:58:24 2024 +0100 + + [text.encoding.aliases] Add note about what isn't required + + Make it explicit that `copyable` is intended, rather than `semiregular`, + and that the return types of `begin()` and `end()` can differ. + + Also remove a FIXME comment for something that doesn't need fixing. + These requirements on a type are specified in our usual form, it would + be wrong to use _Remarks_: or _Requires_: here. + + commit 6338d95ae620f5e4d37d27a39a40f9de9af37b77 + Author: Alisdair Meredith + Date: Wed Oct 16 08:47:02 2024 -0400 + + [lex.charset] Introduce parent subclause [lex.char] for character sets and UCNs (#7067) + + The grammar for universal-character-name is oddly sandwiched into the + middle of the subclause talking about the different character sets used + by the standard. To improve the flow, extract that grammar into its own + subclause. + + In the extraction, I make three other clarifying changes. First, describe + this new subclause as 'a way to name any element of the of the translation + character set using just the basic character set' rather than simply + 'a way to name other characters'. Then, merge the sentence on where universal + characters are prohibited into the new intro sentence describing universal + characters, to make clear that there is no contradiction between nominating + a character, and how that character can be used. Finally, remove the 'one of' + in the grammar where there is only one option to choose. + + commit 9b6b757f34bf4a1eeb6a66481a444b83f1ee5770 + Author: Matthias Kretz + Date: Thu Sep 12 21:41:02 2024 +0200 + + [sf.cmath.assoc.laguerre,sf.cmath.assoc.legendre] Add reference to eq + + The associated Laguerre/Legendre functions build on the + Laguerre/Legendre functions, which are defined in different equations. + Point to them from the associated functions. + + Also use the correct \ell as used in the formula. + + commit 0456a32e41772b0a68b4055fb4e6533cb64e0e3d + Author: Yihe Li + Date: Thu Sep 5 23:59:58 2024 +0800 + + [utility.syn, flat.map.defn] Remove all [[nodiscard]] from library wording + + commit 8b2c7fc3c58bd109c82a016ee2cc5b691bdcd853 + Author: Eisenwave + Date: Mon Jun 10 23:22:04 2024 +0200 + + [expr.new] Extend example for new-expressions with zero size arrays + + commit fb34daf31b53389cc35b3f5f65a69785fc6dd1de + Author: Alisdair Meredith + Date: Tue Jul 23 22:32:52 2024 -0400 + + [char.traits] Better cross-reference several headers + + commit 220cb742e8056ad033ad8dce5630d7d3acaa4c7d + Author: Thomas Köppe + Date: Wed Oct 16 15:37:39 2024 +0100 + + [debugging] Move [debugging] to the end of Clause [diagnostics] + + Part of the C++26 clause restructuring (#5315). + + commit 7a2dafa6b4cca842e264bfd544b69452fb448c39 + Author: Thomas Köppe + Date: Wed Oct 16 15:43:39 2024 +0100 + + [execpol] Move [execpol] to the end of subclause [algorithms.parallel] + + Part of the C++26 clause restructuring (#5315). + + commit 93e2e1c6bcf5e9c3e551d964978e8bf241c392a4 + Author: Thomas Köppe + Date: Wed Oct 16 15:52:54 2024 +0100 + + [type.index] Move [type.index] into subclause [support.rtti] + + The subclause is integrated into the structure of [support.rtti], + meaning that the synopsis becomes a sibling of the rest, and the + subdivisions of the remaining text are removed (in analogy with + [type.info]). + + Part of the C++26 clause restructuring (#5315). + + commit cdb120a4aee270f4e6e40dd7b07885c70651224e + Author: Thomas Köppe + Date: Wed Oct 16 17:25:51 2024 +0100 + + [containers] Move synopses right in front of the classes they define + + Part of the C++26 clause restructuring (#5315). + + commit b7e389c9feca4839f77ad60985f509e01f96a399 + Author: Thomas Köppe + Date: Wed Oct 16 15:27:06 2024 +0100 + + [std] Reorder clauses: [algorithm], [strings] + + Part of the C++26 clause restructuring (#5315). + + commit 5512050c2db44d87566d25ce4f70b530624cb330 + Author: Thomas Köppe + Date: Wed Oct 16 15:36:47 2024 +0100 + + [std] Create new top-level Clause [text], following [strings] + + Part of the C++26 clause restructuring (#5315). + + commit fc6f670832980fc7b8219cb6945592cbe45d9239 + Author: Thomas Köppe + Date: Wed Oct 16 19:01:21 2024 +0100 + + [text, re] Move [re] into [text] + + Part of the C++26 clause restructuring (#5315). + + commit 5d106373aada591874ab5e38301502b3012e0502 + Author: Thomas Köppe + Date: Wed Oct 16 19:06:03 2024 +0100 + + [text, localization] Move [localization] into [text] + + The subclause [text.encodings] is extracted and elevated to a sibling + subclause of [localization]. + + Part of the C++26 clause restructuring (#5315). + + commit 804846a56f7e73dafe4ebd621fa81097d2e94603 + Author: Thomas Köppe + Date: Wed Oct 16 20:15:42 2024 +0100 + + [charconv, format] Move [charconv], [format] to [text] + + Part of the C++26 clause restructuring (#5315). + + commit 4b1a9a76c29c31cc3f679a8bdb1603842baf3501 + Author: Thomas Köppe + Date: Wed Oct 16 20:31:33 2024 +0100 + + [text, c.strings] Move text-related parts of [c.strings] to [text] + + The text-related subclauses [cctype.syn], [cwctype.syn], [cwchar.syn], + [cuchar.syn], and [c.mb.wcs] are moved to a new subclause [text.c.strings]. + + Part of the C++26 clause restructuring (#5226, #5315). + + commit 8003b627a7e336c2e9f350a3bb1ad395ec7c1cc7 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Wed Oct 16 19:41:35 2024 +0000 + + [expr, temp.arg.nontype] Use 'pointer to' instead of 'address of' (#6174) + + Specifically, in: + * [expr.prim.lambda.closure]p8, p11 + * [expr.const]p13.3 + * [temp.arg.nontype]p3 + + commit 198e991fed47efcd8b7fe1ad98ecde4d8722a201 + Author: Alisdair Meredith + Date: Wed Oct 2 15:55:49 2024 -0400 + + [except.handle] group all paragraphs on searching for handler + + This commit moves all of the paragraphs involved in the search for a + handler for an exception into a single logical sequence. + + After this change, [except.spec] deals only with specifying the + 'noexcept' function decorator and its interaction with the + 'noexcept' operator, and contains no text regarding exceptions + themselves. It might be appropriate to move that subclause into + the [dcl] structure at a future date. diff --git a/papers/n5002.html b/papers/n5002.html new file mode 100644 index 0000000000..0c4835ed67 --- /dev/null +++ b/papers/n5002.html @@ -0,0 +1,839 @@ + + + + + +N5002 + + +

N5002 Editors’ Report:
Programming Languages — C++

+ +

Date: 2024-12-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. +Special thanks to Andreas Krug for many timely editorial fixes.

+ +

New papers

+ +
    +
  • N5001 is the +current working draft for C++26. It replaces +N4993.
  • +
  • N5002 is this Editors' Report.
  • +
+ +

Motions incorporated into working draft

+ +

Notes on motions

+ +

CWG Poll 9 was retracted.

+ +

Two LWG Polls, Poll 5 (P0472R2) and Poll 17 (P3019R11) have not been applied and +are being sent back to WG21 for clarification. We expect to see revisions to be +approved at the next meeting:

+ +
    +
  • LWG Poll 5 accidentally polled for the obsolete revision P0472R2 instead of the +intended P0472R3. It is sent back due to unclear intentions, with a request for +WG21 to clarify, and the expectation that R3 will be approved.

  • +
  • LWG Poll 17 caused technical discussion after the meeting, in which some +oversights were observed. The paper authors and the LWG chair agreed that +further LWG review would be in everybody's best interest. The poll is sent back +due to unclear specification, with a request for WG21 to produce a revision, +which we expect to be approved at the next meeting.

  • +
+ +

In CWG Poll 1, issue CWG1965 contains no wording changes since it is subsumed by CWG2879.

+ +

Core working group polls

+ +

CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues in +P3524R0 +(Core Language Working Group "ready" Issues for the November, 2024 meeting) to the C++ Working Paper.

+ +

CWG Poll 2. Apply the changes in +P3340R0 +(A Consistent Grammar for Sequences) to the C++ Working Paper.

+ +

CWG Poll 3. Apply the changes in +P2686R5 +(constexpr structured bindings and references to constexpr variables) to the C++ Working Paper.

+ +

CWG Poll 4. Apply the changes in +P3068R6 +(Allowing exception throwing in constant-evaluation) to the C++ Working Paper.

+ +

CWG Poll 5. Apply the changes in +P3247R2 +(Deprecate the notion of trivial types) to the C++ Working Paper.

+ +

CWG Poll 6. Apply the changes in +P2865R6 +(Remove Deprecated Array Comparisons from C++26) to the C++ Working Paper.

+ +

CWG Poll 7. Apply the changes in +P1061R10 +(Structured Bindings can introduce a Pack) to the C++ Working Paper.

+ +

CWG Poll 8. Apply the changes in +P3176R1 +(The Oxford variadic comma) to the C++ Working Paper.

+ +

CWG Poll 9 was retracted.

+ +

Library working group polls

+ +

LWG Poll 1. Apply the changes for all Ready and Tentatively Ready issues in +P3504R0 +(C++ Standard Library Ready Issues to be moved in Wrocław, Nov. 2024) to the C++ working paper.

+ +

LWG Poll 2. Apply the changes in +P3136R1 +(Retiring niebloids) to the C++ working paper.

+ +

LWG Poll 3. Apply the changes in +P3138R5 +(views::cache_latest) to the C++ working paper.

+ +

LWG Poll 4. Apply the changes in +P3379R0 +(Constrain std::expected equality operators) to the C++ working paper.

+ +

LWG Poll 5 was sent back (see above).

+ +

LWG Poll 6. Apply the changes in +P2862R1 +(text_encoding::name() should never return null values) to the C++ working paper.

+ +

LWG Poll 7. Apply the changes in +P2897R7 +(aligned_accessor: An mdspan accessor expressing pointer over-alignment) to the C++ working paper.

+ +

LWG Poll 8. Apply the changes in +P3355R1 +(Fix submdspan for C++26) to the C++ working paper.

+ +

LWG Poll 9. Apply the changes in +P3222R0 +(Fix C++26 by adding transposed special cases for P2642 layouts) to the C++ working paper.

+ +

LWG Poll 10. Apply the changes in +P3050R2 +(Fix C++26 by optimizing linalg::conjugated for noncomplex value types) to the C++ working paper.

+ +

LWG Poll 11. Apply the changes in +P3396R1 +(std::execution wording fixes) to the C++ working paper.

+ +

LWG Poll 12. Apply the changes in +P2835R7 +(Expose std::atomic_ref's object address) to the C++ working paper.

+ +

LWG Poll 13. Apply the changes in +P3323R1 +(cv-qualified types in atomic and atomic_ref) to the C++ working paper.

+ +

LWG Poll 14. Apply the changes in +P3508R0 +(Wording for "constexpr for specialized memory algorithms") and +P3369R0 +(constexpr for uninitialized_default_construct) to the C++ working paper.

+ +

LWG Poll 15. Apply the changes in +P3370R1 +(Add new library headers from C23) to the C++ working paper.

+ +

LWG Poll 16. Apply the changes in +P3309R3 +(constexpr atomic and atomic_ref) to the C++ working paper.

+ +

LWG Poll 17 was sent back (see above).

+ +

LWG Poll 18. Apply the changes in +P1928R15 +(std::simd — merge data-parallel types from the Parallelism TS 2) to the C++ working paper.

+ +

LWG Poll 19. Apply the changes in +P3325R5 +(A Utility for Creating Execution Environments) to the C++ working paper.

+ +

Editorial changes

+ +

Major editorial changes

+ +

There have not been any major editorial changes.

+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4993 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 e9604bcd3d8325860a4db9d02c4f90d0ae70162e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Oct 16 21:12:40 2024 +0100
+
+    [depr.format.syn] Fix header reference
+
+commit 0b296da823e7af4a987a0a870ae299420b9ae502
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Oct 17 00:39:04 2024 +0100
+
+    [{localization,re}.general] Change "This Clause" to "Subclause".
+
+    These subclauses are no longer top-level clauses.
+
+commit 629e10e2f4177dd24d513be71f2203de325a7e8a
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Oct 17 08:57:39 2024 +0200
+
+    [inplace.vector.overview] Add missing ',' in comment
+
+commit 726e07a3a99a87f5e89dd40a064f4a6bc84ed3ce
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Oct 17 08:25:55 2024 +0200
+
+    [cpp.subst] Fix typo
+
+commit 88b2b8dcbd145782cfab61e6dad9296c9294593d
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Oct 16 22:58:07 2024 +0200
+
+    [exec.domain.default] Add missing \pnum
+
+commit 8698ea48e40acc2e18630e799bbb23c41b9344e6
+Author: James Touton <bekenn@gmail.com>
+Date:   Mon Sep 16 21:47:30 2024 -0700
+
+    [over.match.best.general] Minor formatting fixes
+
+commit 7ad39cbf374764a4e232f967e01541419230fedc
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Oct 17 11:16:28 2024 -0400
+
+    [lex.comment] Move the subclause earlier, to where it better fits
+
+    Comments should fit betweem character sets (to define the basic source
+    character set) and preprocessor tokens, that must already understand
+    comments in order to treat them as whitespace.
+
+commit 7f7170cc9b96e9cc76bc0b765837978856936ab1
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Oct 5 16:21:15 2024 -0400
+
+    [depr] Reorder clauses by origin of deprecation
+
+    Reorders the deprecated features annex to follow the order
+    of the main clauses that the deprecates feature refers to.
+    Where multiple clauses are references, use the one named by
+    the [depr.XXX] stable label.
+
+commit cd21b72788d9066f79f31fb6c4516481dfbb4925
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Fri Oct 18 03:55:20 2024 +0800
+
+    [range.concat.iterator] Remove redundant \expos comments (#6942)
+
+commit 801fb2c0aaf6693a06a9a9e38871bae9536dc194
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Oct 17 17:05:47 2024 -0400
+
+    [lex] Reorder subclauses to better follow phases of translation
+
+    This PR purely moves existing words around, and does not create any new content.
+
+    The proposed subclause ordering is now:
+
+    * 5 Lexical convensions
+      - 5.1 Separate translation
+      - 5.2 Phases of translation
+      - 5.3 Characters
+        - 5.3.1 Character sets
+        - 5.3.2 Universal character names
+      - 5.4 Comments
+      - 5.5 Preprocessing tokens
+      - 5.6 Header names
+      - 5.7 Preprocessing numbers
+      - 5.8 Operators and punctuators
+      - 5.9 Alternative tokens
+      - 5.10 Tokens
+      - 5.11 Identifiers
+      - 5.12 Keywords
+      - 5.13 Literals
+        - 5.13.1 Kinds of literals
+        - 5.13.2 ...
+
+commit 49113a4a577b8d6aed7e5321f0c1fe68d0bd6480
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Oct 18 08:28:28 2024 +0200
+
+    [library.general] Adjust library overview for recent clause restructuring
+
+commit a470ff890be232b9e2a15e44c406ef72c7d816c2
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Oct 19 11:31:59 2024 +0200
+
+    [lex.pptoken] Fix indefinitive article for consistency (#7324)
+
+commit 92594a81f021e76dce6acf7ea5d8176350a1e3fb
+Author: Eelis van der Weegen <eelis@eelis.net>
+Date:   Wed Mar 13 21:04:43 2019 +0100
+
+    [temp.deduct.call] Include surrounding code in math formula
+
+commit 0451d08aefd5318254d7d204ad45700aa4d5a2e7
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Oct 21 19:45:10 2024 +0800
+
+    [specialized.algorithms.general] Restore the note for potentially-overlapping objects and undefined behavior (#7326)
+
+    The original note was incorrect and removed (see #6157). But it turns out
+    that _some_ note is still helpful. This PR tries to find the right way to
+    describe storage reusing and potential subsequent undefined behavior.
+
+commit f6b7ef3f1c6e483d97ad5a4f86b3efed38b74c99
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Oct 19 11:41:35 2024 -0400
+
+    [lex.phases] Add crossreferences from phases 3 and 4
+
+    The phases of translation use forward references to the rest
+    of the standard well, but phases 3 and 4 almost entirely lack
+    such crossreferences, despite doing significant work in the
+    process of translating a file.
+
+commit a69507a54e67ae91424d9c621a9cb57ef3ba1512
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Oct 21 17:48:09 2024 +0200
+
+    [locale.codecvt.virtuals] Fix garbled sentence
+
+commit e0576ed2411f36b0ba648afbf6953a0c72c9effb
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Oct 21 13:09:51 2024 -0400
+
+    [compliance] Sort the freestanding headers after clause reorganization
+
+commit b0135f256e40d45faf1d1ac2aaa3abbda36a17c3
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Tue Oct 22 02:14:47 2024 -0500
+
+    [exec.awaitables] Add missing word (#7340)
+
+commit eb9872aedc581e82e804c0fe8ca7d478ba066b17
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Tue Oct 22 12:09:22 2024 +0200
+
+    [func.wrap.func.con] Fix ill-formed postcondition (#7341)
+
+commit ced2c3866cb3d410c812fa3c359058d185aec329
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Oct 23 13:47:18 2024 -0400
+
+    [allocator.requirements.general] Remove redundant template syntax (#5872)
+
+commit e70d9d6b901457cae9f4f596393f4bf7cee4591a
+Author: Eisenwave <me@eisenwave.net>
+Date:   Mon Oct 21 20:29:10 2024 +0200
+
+    [intro.races] Clarify conflicts for the case where no bits are changed
+
+commit 6ba0dc9b2bf4c3cebc51154e4d543eafb41a8064
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sun Aug 20 00:52:57 2023 +0200
+
+    [intro.memory] remove stray definitions
+
+commit 9dc7b3f30d2971ccb3bb38483a7cdb62065a2c3c
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Oct 22 17:12:25 2024 -0400
+
+    [basic.stc.inherit] Dissolve paragraph into [...general]
+
+    The whole subclause [basic.stc.inherit] is a single sentence that
+    belongs adjacent to the material in [basic.std.general] that
+    specifies how entities acquire a storage duration, wheras all the
+    remaining subclauses below [basic.stc] describe specific storage
+    durations.  Folding that sentence directly into the general clause
+    is even clearer.
+
+commit d5174d561b61304118cdf1042c5697ec6083c181
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Oct 24 09:03:57 2024 +0200
+
+    [basic.link] Add commas between coordinate subclauses (#7342)
+
+commit 8ab0745b6099fd56288763e57ca47dee099db7cb
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Oct 25 10:53:22 2024 +0200
+
+    [bit.cast] change "behaviour" to "behavior" (#7353)
+
+commit 95d491ed6ca7817423855be4f90b61094a1b4312
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Oct 26 15:52:55 2024 +0200
+
+    [associative.reqmts.general] Fix punctuation (#7354)
+
+commit 3eb8c47d8f2fe050e221b5d4c36189d965273b37
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sat Oct 26 16:00:12 2024 +0200
+
+    [basic.compound] Add comma to run-on sentence (#7348)
+
+commit 84af20dcd1976a8982d4418756d1ec9728306580
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sun Oct 27 13:27:34 2024 +0100
+
+    [mdspan.layout.left.cons] Remove duplicate "Effects:" (#7355)
+
+commit ac5b25027266917de3fbb220fc9ecfa4470672f9
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Oct 27 22:46:10 2024 +0100
+
+    [expr.prim.lambda.capture, expr.const, ostream.formatted.print] Reword "automatic variable" (#7358)
+
+commit 324f56439e951773e6ce7437e703fb3aafd5a90c
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Oct 28 07:42:45 2024 -0400
+
+    [lex.pptoken] Reorder paragraphs to define terms before they are used (#7346)
+
+    First move p1 below p2, so that we do not refer to preprocessing tokens before they are defined.
+    Then move p4 up, as it is splitting some unrelated examples, neither of which use its contents.
+
+commit bf43925ff0d9e80997918e98989892b4c7bf15f7
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Oct 29 11:52:02 2024 +0100
+
+    [mdspan.layout.left.cons] Fix typo (#7360)
+
+commit a42d1246936f6376acf6188c1b2053886cdaf3c2
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sat Nov 2 14:38:54 2024 +0100
+
+    [lib.types.movedfrom] Add cross-reference to [defns.valid] (#7365)
+
+commit 6bfbb59e48b6bde05a78d257cbb943acdb2b6781
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Fri Apr 7 17:09:40 2023 +0800
+
+    [format.string.std] Replace "Derived Extracted Property" with simply "property"
+
+commit aa53618e39f16a6fbf147a8ac2d95a33cb8c5cbc
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Fri Aug 9 17:39:07 2024 +0800
+
+    [lex.name] Strike "Derived Core Properties"
+
+commit cb15975d133869eb18a8b7878343a990e63415e2
+Author: Ilya Burylov <burylov@gmail.com>
+Date:   Wed Nov 6 01:44:54 2024 -0800
+
+    [linalg.helpers.mandates] Fix typos (#7372)
+
+commit fcf95f0f1cb3ae11274f1c3477447aadb76b54ca
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Wed Nov 6 13:27:56 2024 +0100
+
+    [exec.opstate.general] Fix typo (#7370)
+
+commit efa0bec63a2718967f7033217a757d536eba3c18
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Wed Nov 6 12:55:52 2024 +0000
+
+    [linalg.reqs.val] Fix use of \defnadjx for value types (#7374)
+
+commit 693835ad625acfdf2d610240b99d6d8fecdb8a6a
+Author: Casey Carter <Casey@Carter.net>
+Date:   Sat Nov 16 06:21:27 2024 -0800
+
+    [fs.op.remove] Clarify "Returns" element (#7387)
+
+    To avoid confusion as in microsoft/STL#5088.
+
+commit 1788b3fcd8f3dbe7b31e6bbfbb968ad43d7ecec3
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Nov 17 20:05:57 2024 +0000
+
+    [over.ics.ref] Fix formatting of 'cv T' (#7389)
+
+commit 16df53c4ab9a17942f5bf994031c98105959a5d5
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Nov 18 17:37:02 2024 +0000
+
+    [defns.regex.primary.equivalence.class] Hyphenate 'locale-specific' (#7395)
+
+commit 4f0facdcd57b922510212ddf44ef39f46dcbe44d
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Nov 18 17:38:09 2024 +0000
+
+    [temp.param] Fix typos (#7394)
+
+commit 99deb7022614be47cfcce4f003d8eb57c02b6926
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Nov 19 05:21:45 2024 +0000
+
+    [over.ics.ref] Capitalize 'Exact Match' (#7392)
+
+commit fb8036b6dfe5ce4a99cd85fddac3f115a7fd96af
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Nov 19 05:25:41 2024 +0000
+
+    [class] Avoid hyphenation for 'multidimensional' (#7391)
+
+commit 3f41cf86547b77854abddde7dcaddf2ff00405bf
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Nov 19 05:26:53 2024 +0000
+
+    [lex.phases] Move cross-reference to the first use of the referenced term (#7393)
+
+commit a05b963e9fe12a8589502b4fbc951c119ae1b3b2
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Jul 30 16:51:21 2024 -0400
+
+    [basic.life] Move definition of before and after from bottom to top of subclause
+
+    The last paragraph of this subclause changes the definition of English words
+    used throughout the preceding paragraphs.  While it might be preferable
+    to replace all such usage with the new definitions, that would be a Core issue,
+    see paragraph 6 for an example of awkward usage.  Hence, we move the
+    redefinition to the start of the subclause so we know how to read this text
+    from the start.
+
+commit 2981bd94f25ea2199fd6b8af7aa76e03cf427697
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Oct 19 08:31:08 2024 -0400
+
+    [basic.align] Move the Alignment subclause adjacent to "Object model"
+
+    Alignment puts additional restrictions on object placement.
+
+commit eac0893a9a90a5704deef6db3deecae026f04271
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Oct 2 14:59:41 2024 -0400
+
+    [except.terminate] Better describe the  function
+
+    While 'std:terminate' was originally conceived as the way to
+    report failures in the exception handling machinery, it has
+    evolved to become a more general tool for reporting unrecoverable
+    failures in the C++ runtime.  This rewording attempts to address
+    that evolving design, and in doing so addresses the outstanding
+    %FIXME% that the current text is not adequately descriptive in
+    the first place.
+
+commit f4c4c7cdfb7fba0a6ffbf8e55f2ea6debdf13e87
+Author: xmh0511 <970252187@qq.com>
+Date:   Wed Nov 20 08:17:02 2024 +0800
+
+    [dcl.link] Change "objects" to "entities"
+
+    "Entities" is more appropriate since it includes functions.
+
+commit 38461e17588aff3c6851de6ffc7f3e89418e0e65
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Nov 7 18:50:10 2024 +0800
+
+    [reverse.iter.cons] Removed redundant wording
+
+commit 8caa49a8266d7ef6b4ef3132588d154de07bbabd
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Mar 1 20:49:37 2024 +0100
+
+    [rand.req.seedseq] Remove 'compile-time' complexity for typedefs
+
+commit e2ddc7ab689bdaf91d2b2aa6424cef2510d3677a
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Mar 1 20:50:27 2024 +0100
+
+    [rand.req.dist] Remove 'compile-time' complexity for typedefs
+
+commit c9155b214a51d069cf4a575f10af2b4c4caca5d7
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Mar 1 20:52:39 2024 +0100
+
+    [char.traits.require] Remove 'compile-time' complexity for typedefs
+
+commit 2cd11c5503e78251c0c0fb4147e2d8ccb0947727
+Author: Vlad Serebrennikov <serebrennikov.vladislav@gmail.com>
+Date:   Tue Oct 8 15:30:13 2024 +0400
+
+    [temp.pre] Fix note about uniqueness of a template name in a scope
+
+commit 2edf50afeec8cf200504718646b2b12492dac8ec
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Oct 21 08:33:19 2024 -0400
+
+    [lex.header] Modernize text around header names
+
+    The footnote better belongs in the main text as a regular note.
+    To make the notes flow consistently, switch the order of the
+    note and normative text in the first paragraph to lead with the
+    normative text.
+
+commit 4a5d988a24f6c9737ca076e790b05e22ba169a7a
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Nov 22 12:55:43 2024 +0100
+
+    [refwrap.invoke] Place period at end (#7402)
+
+commit aed97568c63ad5c3c200eff34799413f3ad842f4
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Nov 23 07:53:16 2024 +0100
+
+    [lex.ccon, except.spec] Remove extraneous trailing linebreaks (#7403)
+
+commit 219b959258b6314a3c96bee86b8a18b0f4a7c37e
+Author: mrussoLuxoft <117848841+mrussoLuxoft@users.noreply.github.com>
+Date:   Sat Nov 30 19:36:56 2024 +0100
+
+    [dcl.spec.auto.general] Clarify sentence structure by adding bullets (#7450)
+
+commit 861071a824419b955c4efb2d07980e78c9fc62c7
+Author: Daniel Krügler <daniel.kruegler@gmail.com>
+Date:   Wed Dec 4 15:05:03 2024 +0100
+
+    [iterator.requirements.general] Revert `indirectly_writable` to "writable" definition (#7471)
+
+    This fixes a misapplication of the 2019 Belfast meeting LWG motion 9 (P1878R1), which erroneously replaced the "writable" definition by the `indirectly_writable` concept.
+
+commit c530fd8e0f80029e88b0977bebbf70252d38795e
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Fri Dec 6 21:52:45 2024 +0800
+
+    [text.encoding.overview] Add cross-reference text_encoding​::​aliases_view (#7476)
+
+commit 10668dceb8186d7990ff4966a6808bb20ba3eed7
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Dec 12 18:47:14 2024 +0000
+
+    [vector.overview,vector.bool.pspc] Move`at() const` to after `at()` (#7484)
+
+    This is consistent with the ordering for operator[].
+
+commit 0b1256638ebf4f1c611c3ca6182bad69be4837ce
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Dec 16 19:53:51 2024 +0100
+
+    [unique.ptr.single.general] Fix typo
+
+commit 76465d7e42f56f763901e3f6a79ae6d77162a510
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Dec 16 12:17:46 2024 +0100
+
+    [expr.type] Fix typo
+
+commit c7fbd5974f4b5e8881d1dc3e8fdf0b59ecba3bab
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Sun Dec 8 07:34:44 2024 +0800
+
+    [locale.ctype.virtuals] Fix a decade-old typo
+
+commit f9c835be8299556ae5943dbb340b4929a6100b15
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Dec 6 16:51:49 2024 +0100
+
+    [except.spec] Remove misleading restriction in list of examples
+
+commit e99e78d67b631fbb328770fbcd4882e683360cb1
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Fri Dec 6 10:57:01 2024 +0100
+
+    [basic.pre,basic.lookup.general] Cleanup definition of term 'name lookup'
+
+commit 57ba5a5f4095ec3df6292cfdc371f554e8b684ef
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Dec 17 12:25:26 2024 -0500
+
+    [lex.phases] Reorder the first two sentences of phase 7 (#7432)
+
+    Currently, the first sentence refers to "tokens" that do not exist until after the second sentence.
+
+commit 55a58f9206e41a831c664747dbacebd25c01b034
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Tue Dec 17 19:34:54 2024 +0100
+
+    [class.conv.ctor] Turn last paragraph into a note (#6505)
+
+commit 3443cd8af21845e5a4fda6246c4c1bbc74cd007b
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Dec 17 19:18:25 2024 +0100
+
+    [exec.envs] Fix typo
+
+commit 14199aed5adb4baaef28245b4de88e7ffe73a365
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Dec 17 20:02:55 2024 +0100
+
+    [atomics.ref.int, atomics.ref.float] Minor \tcode fixes (#7499)
+
+commit daae8f9a9b959c099e99f248324af95bbaf11779
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Dec 18 03:09:10 2024 +0800
+
+    [flat.{map,multimap,set,multiset}] Exposition-only formatting (#6404)
+
+commit 7cbd07c13063b9730d51385198e13bb036d40377
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Dec 16 11:08:10 2024 +0100
+
+    [depr.meta.types] Remove superfluous period
+
+commit 7fe908fa11ad69138975bfec2cf376c66a536d08
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Dec 17 14:13:02 2024 -0500
+
+    [cpp] Distinguish "preprocessing token" from "token" (#7482)
+
+commit 9c9d19f6aef145cf2c074dcdd343e7a2446417a9
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Dec 6 17:37:05 2024 +0000
+
+    [sequence.reqmts] Remove unnecessary qualification of which new element
+
+    There is only one new element, and this avoids having to decide whether it should say args....
+
+ + diff --git a/papers/n5002.md b/papers/n5002.md new file mode 100644 index 0000000000..f5c5e576b1 --- /dev/null +++ b/papers/n5002.md @@ -0,0 +1,697 @@ +# N5002 Editors' Report -- Programming Languages -- C++ + +Date: 2024-12-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. +Special thanks to Andreas Krug for many timely editorial fixes. + +## New papers + + * [N5001](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n5001.pdf) is the + current working draft for C++26. It replaces + [N4993](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4993.pdf). + * N5002 is this Editors' Report. + + +## Motions incorporated into working draft + +### Notes on motions + +CWG Poll 9 was retracted. + +Two LWG Polls, Poll 5 (P0472R2) and Poll 17 (P3019R11) have not been applied and +are being sent back to WG21 for clarification. We expect to see revisions to be +approved at the next meeting: + +* LWG Poll 5 accidentally polled for the obsolete revision P0472R2 instead of the + intended P0472R3. It is sent back due to unclear intentions, with a request for + WG21 to clarify, and the expectation that R3 will be approved. + +* LWG Poll 17 caused technical discussion after the meeting, in which some + oversights were observed. The paper authors and the LWG chair agreed that + further LWG review would be in everybody's best interest. The poll is sent back + due to unclear specification, with a request for WG21 to produce a revision, + which we expect to be approved at the next meeting. + +In CWG Poll 1, issue CWG1965 contains no wording changes since it is subsumed by CWG2879. + +### Core working group polls +CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues in +[P3524R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3524r0.html) +(Core Language Working Group "ready" Issues for the November, 2024 meeting) to the C++ Working Paper. + +CWG Poll 2. Apply the changes in +[P3340R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3340r0.pdf) +(A Consistent Grammar for Sequences) to the C++ Working Paper. + +CWG Poll 3. Apply the changes in +[P2686R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2686r5.pdf) +(constexpr structured bindings and references to constexpr variables) to the C++ Working Paper. + +CWG Poll 4. Apply the changes in +[P3068R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3068r6.html) +(Allowing exception throwing in constant-evaluation) to the C++ Working Paper. + +CWG Poll 5. Apply the changes in +[P3247R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3247r2.html) +(Deprecate the notion of trivial types) to the C++ Working Paper. + +CWG Poll 6. Apply the changes in +[P2865R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2865r6.pdf) +(Remove Deprecated Array Comparisons from C++26) to the C++ Working Paper. + +CWG Poll 7. Apply the changes in +[P1061R10](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p1061r10.html) +(Structured Bindings can introduce a Pack) to the C++ Working Paper. + +CWG Poll 8. Apply the changes in +[P3176R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3176r1.html) +(The Oxford variadic comma) to the C++ Working Paper. + +CWG Poll 9 was retracted. + +### Library working group polls + +LWG Poll 1. Apply the changes for all Ready and Tentatively Ready issues in +[P3504R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3504r0.html) +(C++ Standard Library Ready Issues to be moved in Wrocław, Nov. 2024) to the C++ working paper. + +LWG Poll 2. Apply the changes in +[P3136R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3136r1.html) +(Retiring niebloids) to the C++ working paper. + +LWG Poll 3. Apply the changes in +[P3138R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3138r5.html) +(`views::cache_latest`) to the C++ working paper. + +LWG Poll 4. Apply the changes in +[P3379R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3379r0.html) +(Constrain `std::expected` equality operators) to the C++ working paper. + +LWG Poll 5 was sent back (see above). + +LWG Poll 6. Apply the changes in +[P2862R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2862r1.html) +(`text_encoding::name()` should never return null values) to the C++ working paper. + +LWG Poll 7. Apply the changes in +[P2897R7](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2897r7.html) +(`aligned_accessor`: An `mdspan` accessor expressing pointer over-alignment) to the C++ working paper. + +LWG Poll 8. Apply the changes in +[P3355R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3355r1.html) +(Fix `submdspan` for C++26) to the C++ working paper. + +LWG Poll 9. Apply the changes in +[P3222R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3222r0.html) +(Fix C++26 by adding transposed special cases for P2642 layouts) to the C++ working paper. + +LWG Poll 10. Apply the changes in +[P3050R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3050r2.html) +(Fix C++26 by optimizing `linalg::conjugated` for noncomplex value types) to the C++ working paper. + +LWG Poll 11. Apply the changes in +[P3396R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3396r1.html) +(`std::execution` wording fixes) to the C++ working paper. + +LWG Poll 12. Apply the changes in +[P2835R7](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2835r7.html) +(Expose `std::atomic_ref`'s object address) to the C++ working paper. + +LWG Poll 13. Apply the changes in +[P3323R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3323r1.html) +(cv-qualified types in `atomic` and `atomic_ref`) to the C++ working paper. + +LWG Poll 14. Apply the changes in +[P3508R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3508r0.html) +(Wording for "constexpr for specialized memory algorithms") and +[P3369R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3369r0.html) +(`constexpr` for `uninitialized_default_construct`) to the C++ working paper. + +LWG Poll 15. Apply the changes in +[P3370R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3370r1.html) +(Add new library headers from C23) to the C++ working paper. + +LWG Poll 16. Apply the changes in +[P3309R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3309r3.html) +(constexpr `atomic` and `atomic_ref`) to the C++ working paper. + +LWG Poll 17 was sent back (see above). + +LWG Poll 18. Apply the changes in +[P1928R15](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p1928r15.pdf) +(`std::simd` — merge data-parallel types from the Parallelism TS 2) to the C++ working paper. + +LWG Poll 19. Apply the changes in +[P3325R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3325r5.html) +(A Utility for Creating Execution Environments) to the C++ working paper. + +## Editorial changes + +### Major editorial changes + +There have not been any major editorial changes. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4993 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/n4993...n5001). + + commit e9604bcd3d8325860a4db9d02c4f90d0ae70162e + Author: Thomas Köppe + Date: Wed Oct 16 21:12:40 2024 +0100 + + [depr.format.syn] Fix header reference + + commit 0b296da823e7af4a987a0a870ae299420b9ae502 + Author: Thomas Köppe + Date: Thu Oct 17 00:39:04 2024 +0100 + + [{localization,re}.general] Change "This Clause" to "Subclause". + + These subclauses are no longer top-level clauses. + + commit 629e10e2f4177dd24d513be71f2203de325a7e8a + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Oct 17 08:57:39 2024 +0200 + + [inplace.vector.overview] Add missing ',' in comment + + commit 726e07a3a99a87f5e89dd40a064f4a6bc84ed3ce + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Oct 17 08:25:55 2024 +0200 + + [cpp.subst] Fix typo + + commit 88b2b8dcbd145782cfab61e6dad9296c9294593d + Author: Jens Maurer + Date: Wed Oct 16 22:58:07 2024 +0200 + + [exec.domain.default] Add missing \pnum + + commit 8698ea48e40acc2e18630e799bbb23c41b9344e6 + Author: James Touton + Date: Mon Sep 16 21:47:30 2024 -0700 + + [over.match.best.general] Minor formatting fixes + + commit 7ad39cbf374764a4e232f967e01541419230fedc + Author: Alisdair Meredith + Date: Thu Oct 17 11:16:28 2024 -0400 + + [lex.comment] Move the subclause earlier, to where it better fits + + Comments should fit betweem character sets (to define the basic source + character set) and preprocessor tokens, that must already understand + comments in order to treat them as whitespace. + + commit 7f7170cc9b96e9cc76bc0b765837978856936ab1 + Author: Alisdair Meredith + Date: Sat Oct 5 16:21:15 2024 -0400 + + [depr] Reorder clauses by origin of deprecation + + Reorders the deprecated features annex to follow the order + of the main clauses that the deprecates feature refers to. + Where multiple clauses are references, use the one named by + the [depr.XXX] stable label. + + commit cd21b72788d9066f79f31fb6c4516481dfbb4925 + Author: Hewill Kang + Date: Fri Oct 18 03:55:20 2024 +0800 + + [range.concat.iterator] Remove redundant \expos comments (#6942) + + commit 801fb2c0aaf6693a06a9a9e38871bae9536dc194 + Author: Alisdair Meredith + Date: Thu Oct 17 17:05:47 2024 -0400 + + [lex] Reorder subclauses to better follow phases of translation + + This PR purely moves existing words around, and does not create any new content. + + The proposed subclause ordering is now: + + * 5 Lexical convensions + - 5.1 Separate translation + - 5.2 Phases of translation + - 5.3 Characters + - 5.3.1 Character sets + - 5.3.2 Universal character names + - 5.4 Comments + - 5.5 Preprocessing tokens + - 5.6 Header names + - 5.7 Preprocessing numbers + - 5.8 Operators and punctuators + - 5.9 Alternative tokens + - 5.10 Tokens + - 5.11 Identifiers + - 5.12 Keywords + - 5.13 Literals + - 5.13.1 Kinds of literals + - 5.13.2 ... + + commit 49113a4a577b8d6aed7e5321f0c1fe68d0bd6480 + Author: Jens Maurer + Date: Fri Oct 18 08:28:28 2024 +0200 + + [library.general] Adjust library overview for recent clause restructuring + + commit a470ff890be232b9e2a15e44c406ef72c7d816c2 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Oct 19 11:31:59 2024 +0200 + + [lex.pptoken] Fix indefinitive article for consistency (#7324) + + commit 92594a81f021e76dce6acf7ea5d8176350a1e3fb + Author: Eelis van der Weegen + Date: Wed Mar 13 21:04:43 2019 +0100 + + [temp.deduct.call] Include surrounding code in math formula + + commit 0451d08aefd5318254d7d204ad45700aa4d5a2e7 + Author: A. Jiang + Date: Mon Oct 21 19:45:10 2024 +0800 + + [specialized.algorithms.general] Restore the note for potentially-overlapping objects and undefined behavior (#7326) + + The original note was incorrect and removed (see #6157). But it turns out + that _some_ note is still helpful. This PR tries to find the right way to + describe storage reusing and potential subsequent undefined behavior. + + commit f6b7ef3f1c6e483d97ad5a4f86b3efed38b74c99 + Author: Alisdair Meredith + Date: Sat Oct 19 11:41:35 2024 -0400 + + [lex.phases] Add crossreferences from phases 3 and 4 + + The phases of translation use forward references to the rest + of the standard well, but phases 3 and 4 almost entirely lack + such crossreferences, despite doing significant work in the + process of translating a file. + + commit a69507a54e67ae91424d9c621a9cb57ef3ba1512 + Author: Jens Maurer + Date: Mon Oct 21 17:48:09 2024 +0200 + + [locale.codecvt.virtuals] Fix garbled sentence + + commit e0576ed2411f36b0ba648afbf6953a0c72c9effb + Author: Alisdair Meredith + Date: Mon Oct 21 13:09:51 2024 -0400 + + [compliance] Sort the freestanding headers after clause reorganization + + commit b0135f256e40d45faf1d1ac2aaa3abbda36a17c3 + Author: timsong-cpp + Date: Tue Oct 22 02:14:47 2024 -0500 + + [exec.awaitables] Add missing word (#7340) + + commit eb9872aedc581e82e804c0fe8ca7d478ba066b17 + Author: Jan Schultke + Date: Tue Oct 22 12:09:22 2024 +0200 + + [func.wrap.func.con] Fix ill-formed postcondition (#7341) + + commit ced2c3866cb3d410c812fa3c359058d185aec329 + Author: Alisdair Meredith + Date: Wed Oct 23 13:47:18 2024 -0400 + + [allocator.requirements.general] Remove redundant template syntax (#5872) + + commit e70d9d6b901457cae9f4f596393f4bf7cee4591a + Author: Eisenwave + Date: Mon Oct 21 20:29:10 2024 +0200 + + [intro.races] Clarify conflicts for the case where no bits are changed + + commit 6ba0dc9b2bf4c3cebc51154e4d543eafb41a8064 + Author: Eisenwave + Date: Sun Aug 20 00:52:57 2023 +0200 + + [intro.memory] remove stray definitions + + commit 9dc7b3f30d2971ccb3bb38483a7cdb62065a2c3c + Author: Alisdair Meredith + Date: Tue Oct 22 17:12:25 2024 -0400 + + [basic.stc.inherit] Dissolve paragraph into [...general] + + The whole subclause [basic.stc.inherit] is a single sentence that + belongs adjacent to the material in [basic.std.general] that + specifies how entities acquire a storage duration, wheras all the + remaining subclauses below [basic.stc] describe specific storage + durations. Folding that sentence directly into the general clause + is even clearer. + + commit d5174d561b61304118cdf1042c5697ec6083c181 + Author: Jan Schultke + Date: Thu Oct 24 09:03:57 2024 +0200 + + [basic.link] Add commas between coordinate subclauses (#7342) + + commit 8ab0745b6099fd56288763e57ca47dee099db7cb + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Oct 25 10:53:22 2024 +0200 + + [bit.cast] change "behaviour" to "behavior" (#7353) + + commit 95d491ed6ca7817423855be4f90b61094a1b4312 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Oct 26 15:52:55 2024 +0200 + + [associative.reqmts.general] Fix punctuation (#7354) + + commit 3eb8c47d8f2fe050e221b5d4c36189d965273b37 + Author: Jan Schultke + Date: Sat Oct 26 16:00:12 2024 +0200 + + [basic.compound] Add comma to run-on sentence (#7348) + + commit 84af20dcd1976a8982d4418756d1ec9728306580 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sun Oct 27 13:27:34 2024 +0100 + + [mdspan.layout.left.cons] Remove duplicate "Effects:" (#7355) + + commit ac5b25027266917de3fbb220fc9ecfa4470672f9 + Author: Jan Schultke + Date: Sun Oct 27 22:46:10 2024 +0100 + + [expr.prim.lambda.capture, expr.const, ostream.formatted.print] Reword "automatic variable" (#7358) + + commit 324f56439e951773e6ce7437e703fb3aafd5a90c + Author: Alisdair Meredith + Date: Mon Oct 28 07:42:45 2024 -0400 + + [lex.pptoken] Reorder paragraphs to define terms before they are used (#7346) + + First move p1 below p2, so that we do not refer to preprocessing tokens before they are defined. + Then move p4 up, as it is splitting some unrelated examples, neither of which use its contents. + + commit bf43925ff0d9e80997918e98989892b4c7bf15f7 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Oct 29 11:52:02 2024 +0100 + + [mdspan.layout.left.cons] Fix typo (#7360) + + commit a42d1246936f6376acf6188c1b2053886cdaf3c2 + Author: Jan Schultke + Date: Sat Nov 2 14:38:54 2024 +0100 + + [lib.types.movedfrom] Add cross-reference to [defns.valid] (#7365) + + commit 6bfbb59e48b6bde05a78d257cbb943acdb2b6781 + Author: S. B. Tam + Date: Fri Apr 7 17:09:40 2023 +0800 + + [format.string.std] Replace "Derived Extracted Property" with simply "property" + + commit aa53618e39f16a6fbf147a8ac2d95a33cb8c5cbc + Author: S. B. Tam + Date: Fri Aug 9 17:39:07 2024 +0800 + + [lex.name] Strike "Derived Core Properties" + + commit cb15975d133869eb18a8b7878343a990e63415e2 + Author: Ilya Burylov + Date: Wed Nov 6 01:44:54 2024 -0800 + + [linalg.helpers.mandates] Fix typos (#7372) + + commit fcf95f0f1cb3ae11274f1c3477447aadb76b54ca + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Wed Nov 6 13:27:56 2024 +0100 + + [exec.opstate.general] Fix typo (#7370) + + commit efa0bec63a2718967f7033217a757d536eba3c18 + Author: Jonathan Wakely + Date: Wed Nov 6 12:55:52 2024 +0000 + + [linalg.reqs.val] Fix use of \defnadjx for value types (#7374) + + commit 693835ad625acfdf2d610240b99d6d8fecdb8a6a + Author: Casey Carter + Date: Sat Nov 16 06:21:27 2024 -0800 + + [fs.op.remove] Clarify "Returns" element (#7387) + + To avoid confusion as in microsoft/STL#5088. + + commit 1788b3fcd8f3dbe7b31e6bbfbb968ad43d7ecec3 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Nov 17 20:05:57 2024 +0000 + + [over.ics.ref] Fix formatting of 'cv T' (#7389) + + commit 16df53c4ab9a17942f5bf994031c98105959a5d5 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Nov 18 17:37:02 2024 +0000 + + [defns.regex.primary.equivalence.class] Hyphenate 'locale-specific' (#7395) + + commit 4f0facdcd57b922510212ddf44ef39f46dcbe44d + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Nov 18 17:38:09 2024 +0000 + + [temp.param] Fix typos (#7394) + + commit 99deb7022614be47cfcce4f003d8eb57c02b6926 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Nov 19 05:21:45 2024 +0000 + + [over.ics.ref] Capitalize 'Exact Match' (#7392) + + commit fb8036b6dfe5ce4a99cd85fddac3f115a7fd96af + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Nov 19 05:25:41 2024 +0000 + + [class] Avoid hyphenation for 'multidimensional' (#7391) + + commit 3f41cf86547b77854abddde7dcaddf2ff00405bf + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Nov 19 05:26:53 2024 +0000 + + [lex.phases] Move cross-reference to the first use of the referenced term (#7393) + + commit a05b963e9fe12a8589502b4fbc951c119ae1b3b2 + Author: Alisdair Meredith + Date: Tue Jul 30 16:51:21 2024 -0400 + + [basic.life] Move definition of before and after from bottom to top of subclause + + The last paragraph of this subclause changes the definition of English words + used throughout the preceding paragraphs. While it might be preferable + to replace all such usage with the new definitions, that would be a Core issue, + see paragraph 6 for an example of awkward usage. Hence, we move the + redefinition to the start of the subclause so we know how to read this text + from the start. + + commit 2981bd94f25ea2199fd6b8af7aa76e03cf427697 + Author: Alisdair Meredith + Date: Sat Oct 19 08:31:08 2024 -0400 + + [basic.align] Move the Alignment subclause adjacent to "Object model" + + Alignment puts additional restrictions on object placement. + + commit eac0893a9a90a5704deef6db3deecae026f04271 + Author: Alisdair Meredith + Date: Wed Oct 2 14:59:41 2024 -0400 + + [except.terminate] Better describe the function + + While 'std:terminate' was originally conceived as the way to + report failures in the exception handling machinery, it has + evolved to become a more general tool for reporting unrecoverable + failures in the C++ runtime. This rewording attempts to address + that evolving design, and in doing so addresses the outstanding + %FIXME% that the current text is not adequately descriptive in + the first place. + + commit f4c4c7cdfb7fba0a6ffbf8e55f2ea6debdf13e87 + Author: xmh0511 <970252187@qq.com> + Date: Wed Nov 20 08:17:02 2024 +0800 + + [dcl.link] Change "objects" to "entities" + + "Entities" is more appropriate since it includes functions. + + commit 38461e17588aff3c6851de6ffc7f3e89418e0e65 + Author: A. Jiang + Date: Thu Nov 7 18:50:10 2024 +0800 + + [reverse.iter.cons] Removed redundant wording + + commit 8caa49a8266d7ef6b4ef3132588d154de07bbabd + Author: Eisenwave + Date: Fri Mar 1 20:49:37 2024 +0100 + + [rand.req.seedseq] Remove 'compile-time' complexity for typedefs + + commit e2ddc7ab689bdaf91d2b2aa6424cef2510d3677a + Author: Eisenwave + Date: Fri Mar 1 20:50:27 2024 +0100 + + [rand.req.dist] Remove 'compile-time' complexity for typedefs + + commit c9155b214a51d069cf4a575f10af2b4c4caca5d7 + Author: Eisenwave + Date: Fri Mar 1 20:52:39 2024 +0100 + + [char.traits.require] Remove 'compile-time' complexity for typedefs + + commit 2cd11c5503e78251c0c0fb4147e2d8ccb0947727 + Author: Vlad Serebrennikov + Date: Tue Oct 8 15:30:13 2024 +0400 + + [temp.pre] Fix note about uniqueness of a template name in a scope + + commit 2edf50afeec8cf200504718646b2b12492dac8ec + Author: Alisdair Meredith + Date: Mon Oct 21 08:33:19 2024 -0400 + + [lex.header] Modernize text around header names + + The footnote better belongs in the main text as a regular note. + To make the notes flow consistently, switch the order of the + note and normative text in the first paragraph to lead with the + normative text. + + commit 4a5d988a24f6c9737ca076e790b05e22ba169a7a + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Nov 22 12:55:43 2024 +0100 + + [refwrap.invoke] Place period at end (#7402) + + commit aed97568c63ad5c3c200eff34799413f3ad842f4 + Author: Alisdair Meredith + Date: Sat Nov 23 07:53:16 2024 +0100 + + [lex.ccon, except.spec] Remove extraneous trailing linebreaks (#7403) + + commit 219b959258b6314a3c96bee86b8a18b0f4a7c37e + Author: mrussoLuxoft <117848841+mrussoLuxoft@users.noreply.github.com> + Date: Sat Nov 30 19:36:56 2024 +0100 + + [dcl.spec.auto.general] Clarify sentence structure by adding bullets (#7450) + + commit 861071a824419b955c4efb2d07980e78c9fc62c7 + Author: Daniel Krügler + Date: Wed Dec 4 15:05:03 2024 +0100 + + [iterator.requirements.general] Revert `indirectly_writable` to "writable" definition (#7471) + + This fixes a misapplication of the 2019 Belfast meeting LWG motion 9 (P1878R1), which erroneously replaced the "writable" definition by the `indirectly_writable` concept. + + commit c530fd8e0f80029e88b0977bebbf70252d38795e + Author: Hewill Kang + Date: Fri Dec 6 21:52:45 2024 +0800 + + [text.encoding.overview] Add cross-reference text_encoding​::​aliases_view (#7476) + + commit 10668dceb8186d7990ff4966a6808bb20ba3eed7 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Dec 12 18:47:14 2024 +0000 + + [vector.overview,vector.bool.pspc] Move`at() const` to after `at()` (#7484) + + This is consistent with the ordering for operator[]. + + commit 0b1256638ebf4f1c611c3ca6182bad69be4837ce + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Dec 16 19:53:51 2024 +0100 + + [unique.ptr.single.general] Fix typo + + commit 76465d7e42f56f763901e3f6a79ae6d77162a510 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Dec 16 12:17:46 2024 +0100 + + [expr.type] Fix typo + + commit c7fbd5974f4b5e8881d1dc3e8fdf0b59ecba3bab + Author: S. B. Tam + Date: Sun Dec 8 07:34:44 2024 +0800 + + [locale.ctype.virtuals] Fix a decade-old typo + + commit f9c835be8299556ae5943dbb340b4929a6100b15 + Author: Jens Maurer + Date: Fri Dec 6 16:51:49 2024 +0100 + + [except.spec] Remove misleading restriction in list of examples + + commit e99e78d67b631fbb328770fbcd4882e683360cb1 + Author: Jens Maurer + Date: Fri Dec 6 10:57:01 2024 +0100 + + [basic.pre,basic.lookup.general] Cleanup definition of term 'name lookup' + + commit 57ba5a5f4095ec3df6292cfdc371f554e8b684ef + Author: Alisdair Meredith + Date: Tue Dec 17 12:25:26 2024 -0500 + + [lex.phases] Reorder the first two sentences of phase 7 (#7432) + + Currently, the first sentence refers to "tokens" that do not exist until after the second sentence. + + commit 55a58f9206e41a831c664747dbacebd25c01b034 + Author: Jan Schultke + Date: Tue Dec 17 19:34:54 2024 +0100 + + [class.conv.ctor] Turn last paragraph into a note (#6505) + + commit 3443cd8af21845e5a4fda6246c4c1bbc74cd007b + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Dec 17 19:18:25 2024 +0100 + + [exec.envs] Fix typo + + commit 14199aed5adb4baaef28245b4de88e7ffe73a365 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Dec 17 20:02:55 2024 +0100 + + [atomics.ref.int, atomics.ref.float] Minor \tcode fixes (#7499) + + commit daae8f9a9b959c099e99f248324af95bbaf11779 + Author: A. Jiang + Date: Wed Dec 18 03:09:10 2024 +0800 + + [flat.{map,multimap,set,multiset}] Exposition-only formatting (#6404) + + commit 7cbd07c13063b9730d51385198e13bb036d40377 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Dec 16 11:08:10 2024 +0100 + + [depr.meta.types] Remove superfluous period + + commit 7fe908fa11ad69138975bfec2cf376c66a536d08 + Author: Alisdair Meredith + Date: Tue Dec 17 14:13:02 2024 -0500 + + [cpp] Distinguish "preprocessing token" from "token" (#7482) + + commit 9c9d19f6aef145cf2c074dcdd343e7a2446417a9 + Author: Jonathan Wakely + Date: Fri Dec 6 17:37:05 2024 +0000 + + [sequence.reqmts] Remove unnecessary qualification of which new element + + There is only one new element, and this avoids having to decide whether it should say args.... diff --git a/papers/n5009.html b/papers/n5009.html new file mode 100644 index 0000000000..ec21ca1bed --- /dev/null +++ b/papers/n5009.html @@ -0,0 +1,893 @@ + + + + + +N5009 + + +

N5009 Editors’ Report:
Programming Languages — C++

+ +

Date: 2025-03-15

+ +

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, +to those who have provided pull requests with fixes, +and to everyone who drafted motion applications.

+ +

New papers

+ +
    +
  • N5008 is the +current working draft for C++26. It replaces +N5001.
  • +
  • N5009 is this Editors' Report.
  • +
+ +

Motions incorporated into working draft

+ +

Notes on motions

+ +

LWG Poll 2 was retracted.

+ +

Library issue LWG4189, +adopted by LWG Poll 1 (P3615R0) had the effect of making most of the content of <ranges> +free-standing by default, with the note that "[m]ost future additions to this header should +have no problem being freestanding, so that is the right default." Absent an explicit +opt-out, the new facilities from LWG Poll 14 +(P2846R6), +reserve_hint and approximately_sized_range, are now free-standing as well.

+ +

Core working group polls

+ +

CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues in +P3638R0 +(Core Language Working Group "ready" Issues for the February, 2025 meeting) to the C++ Working Paper.

+ +

CWG Poll 2. Apply the changes in P3542R0 +(Abolish the term "converting constructor") to the C++ Working Paper.

+ +

CWG Poll 3. Apply the changes in P3074R7 +(trivial unions (was std::uninitialized)) to the C++ Working Paper.

+ +

CWG Poll 4. Apply the changes in P1494R5 +(Partial program correctness) to the C++ Working Paper.

+ +

CWG Poll 5. Apply the changes in P2900R14 +(Contracts for C++) to the C++ Working Paper.

+ +

CWG Poll 6. Apply the changes in P3475R2 +(Defang and deprecate memory_order::consume) to the C++ Working Paper.

+ +

CWG Poll 7. Apply the changes in P2841R7 +(Concept and variable-template template-parameters) to the C++ Working Paper.

+ +

CWG Poll 8. Apply the changes in P2786R13 +(Trivial Relocatability For C++26) to the C++ Working Paper.

+ +

CWG Poll 9. Apply the changes in P1967R14 +(#embed - a simple, scannable preprocessor-based resource acquisition method) to the C++ Working Paper.

+ +

Library working group polls

+ +

LWG Poll 1. Apply the changes for all Tentatively Ready issues in +P3615R0 +(C++ Standard Library Ready Issues to be moved in Hagenberg, Feb. 2025) to the C++ working paper.

+ +

LWG Poll 2 was retracted.

+ +

LWG Poll 3. Apply the changes in P3137R3 +(views::to_input) to the C++ working paper.

+ +

LWG Poll 4. Apply the changes in P0472R3 +(Put std::monostate in <utility>) to the C++ working paper.

+ +

LWG Poll 5. Apply the changes in P3349R1 +(Converting contiguous iterators to pointers) to the C++ working paper.

+ +

LWG Poll 6. Apply the changes in P3372R3 +(constexpr containers and adaptors) to the C++ working paper.

+ +

LWG Poll 7. Apply the changes in P3378R2 +(constexpr exception types) to the C++ working paper.

+ +

LWG Poll 8. Apply the changes in P3441R2 +(Rename simd_split to simd_chunk) to the C++ working paper.

+ +

LWG Poll 9. Apply the changes in P3287R3 +(Exploration of namespaces for std::simd) to the C++ working paper.

+ +

LWG Poll 10. Apply the changes in P2976R1 +(Freestanding Library: algorithm, numeric, and random) to the C++ working paper.

+ +

LWG Poll 11. Apply the changes in P3430R3 +(SIMD issues: explicit, unsequenced, identity-element position, and members of disabled SIMD) to the C++ working paper.

+ +

LWG Poll 12. Apply the changes in P2663R7 +(Interleaved complex values support in std::simd) to the C++ working paper.

+ +

LWG Poll 13. Apply the changes in P2933R4 +(Extend <bit> header function with overloads for std::simd) to the C++ working paper.

+ +

LWG Poll 14. Apply the changes in P2846R6 +(reserve_hint: Eagerly reserving memory for not-quite-sized lazy ranges) to the C++ working paper.

+ +

LWG Poll 15. Apply the changes in P3471R4 +(Standard Library Hardening) to the C++ working paper.

+ +

LWG Poll 16. Apply the changes in P0447R28 +(Introduction of std::hive to the standard library) to the C++ working paper.

+ +

LWG Poll 17. Apply the changes in P3019R14 +(indirect and polymorphic: Vocabulary Types for Composite Class Design) to the C++ working paper.

+ +

Editorial changes

+ +

Major editorial changes

+ +

There have not been any major editorial changes.

+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N5001 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 f3676cb1550f1501236cc65c1dfa2dec957bbdf2
+Author: Mark Hoemmen <mhoemmen@users.noreply.github.com>
+Date:   Tue Dec 17 14:15:10 2024 -0700
+
+    [linalg.conj.conjugated] Remove inappropriate "expression-equivalent" wording (#7497)
+
+    This phrase appears to be copy-pasted from elsewhere, but is not meaningful here.
+
+commit be0a25c9a2f2c1f498b0ff84a33c28adae41863e
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Dec 17 20:31:14 2024 +0100
+
+    [simd.alg] Fix range syntax
+
+commit a18040f05ff6a27e5c6425005ab1b21515ad952c
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Nov 1 08:06:28 2024 +0100
+
+    [basic.compound] Update introduction
+
+commit 0131e015c09eca1901d0bfa46744a6c7ab31b00d
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Dec 17 21:21:42 2024 +0000
+
+    [linalg.helpers] Rename template parameter for poison pills
+
+    This avoids reusing `T` which is also used for the type of the
+    subexpression E.
+
+    Fixes #7494
+
+commit 04169bac7059322ad8bf32e605a80e57ef30b922
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Dec 17 22:51:01 2024 +0100
+
+    [inplace.vector.overview] Replace residual use of 'trivial type'
+
+commit 9272753d0ecbc1df9d08178793795f06b623a451
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Tue Nov 19 16:41:00 2024 +0800
+
+    [flat.map.defn, flat.set.defn] Avoid naming the from_range_t tag
+
+commit 85de0af0e0af416f7e73ac096254641c31bf11cc
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Tue Dec 17 23:19:21 2024 +0100
+
+    [basic.fundamental] Ensure consistency with [conv.ptr]
+
+commit 561a4d8cde9e434fe206b88489e95b0e5271f469
+Author: Mark Hoemmen <mhoemmen@users.noreply.github.com>
+Date:   Thu Dec 19 14:35:50 2024 -0700
+
+    [bibliography] Fix spelling and formatting (#7507)
+
+    Fix spelling of one author's name.  Add missing commas
+    and extra spaces after a period ending authors' abbreviated
+    first or middle names.
+
+commit 82153790d8904ea82bc57edc8885b02925e85e93
+Author: Mark Hoemmen <mhoemmen@users.noreply.github.com>
+Date:   Thu Dec 19 14:41:02 2024 -0700
+
+    [simd.general, bibliography] Add SIMD acronym explanation and bibliographic reference (#7504)
+
+    To the existing Note at the beginning of [simd.general],
+    add text that unpacks the SIMD acronym and refers to Flynn 1966.
+
+    Add bibliography entry for Flynn 1966, the paper that introduced what
+    later became known as "Flynn's Taxonomy."  This classifies parallel
+    computer hardware as SISD, SIMD, MISD, or MIMD.
+
+commit e1a368bc157f824cee7702e87a2cca1951e60f98
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu Dec 19 11:02:38 2024 +0000
+
+    [mdspan.sub] Change to "unit-stride slice for mapping"
+
+    This was the wording requested by LWG and approved in P3355R2, but I
+    mistakenly put P3355R1 in the straw polls.
+
+commit 2d3ac367d8605d7172151726e873daea295a573a
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Dec 20 10:15:46 2024 +0100
+
+    [diff.cpp03.library] Correct \effect to \change
+
+    - Correct \effect to \change.
+    - Add period at end.
+    - Add \tcode for swap.
+
+commit a2429a5944b71e3563dc09730426af43fb4b53e1
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Dec 26 01:37:34 2024 +0000
+
+    [class.expl.init] Fix incorrect note
+
+commit 1411cf56fcb41f9fd000406185f17ef47235d26a
+Author: Bronek Kozicki <brok@incorrekt.com>
+Date:   Wed Jan 1 17:00:14 2025 +0000
+
+    [expected.bad.void] Fix syntax error in bad_expected_access<void> (#7529)
+
+    Introduced by commit 8c997445c176c81a334e77f9344b91abc72b2772
+
+commit a137940ac9c807e3ea809c3ff0b3a863795bf742
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Wed Jan 1 22:18:37 2025 +0100
+
+    [filebuf.members,fs.path.req] Fix indefinite article (#7530)
+
+commit d2b48043fcc219b2a141af39dae2eb85934c0847
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Jan 2 10:49:14 2025 +0100
+
+    [expr.const] Properly merge P2686R5
+
+    P2686R5 (applied by commit e220906b71df01f09fe60921e8fac39b80558f78)
+    accidentally reverted a change considering erroneous values made by
+    P2795R5.
+
+commit 22937c04da139226c186973eda2cdb79df640b5b
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Jan 2 15:14:06 2025 +0100
+
+    [format.arg] Fix indefinite article (#7536)
+
+commit 75af9f7f8cd816e1908eb2a3917eb7749c11471a
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Jan 4 02:18:53 2025 +0700
+
+    [tuple.helper] Remove redundant 'public' in base-specifier of struct (#7539)
+
+commit 6ff55d533f72b7222e022513dcb80982f4e887a0
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Dec 30 16:34:49 2024 +0100
+
+    [lex.icon,depr.locale.category] Remove duplicate 'table' in front of table references
+
+commit 70df8aa8f4a30a7d54a604cbe01ebe13f5973043
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Wed Jan 8 13:51:13 2025 +0100
+
+    [linalg.algs.blas2.gemv] Fix singular/plural mismatch (#7546)
+
+commit 0164098f821ae002469c6f23cd03fc66a0a2f7ca
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Jan 9 10:01:36 2025 +0000
+
+    [basic.def.odr] Fix typo and reference the correct subclause
+
+commit 2734ddeb05115f3fddf09c9c15b843083575e9df
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Jan 10 13:13:28 2025 +0100
+
+    [exec.async.ops] Remove stray closing parenthesis (#7555)
+
+commit 77171de904e6008f31717615d5baabf604baeea8
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Fri Jan 10 23:05:58 2025 +0800
+
+    [locale.time.put.members] Remove incorrect footnote (#7553)
+
+commit 6ecd1be67c71001db37883ee45b76cc66ef4101f
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Jan 13 22:34:47 2025 +0100
+
+    [exec.getcomplsigs] Add missing LaTeX escaping of braces (#7541)
+
+commit 1b1914ed868b0b29e63d0d1e4b872daf07b50740
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Jan 14 14:31:09 2025 +0100
+
+    [simd.traits] Remove stray closing parenthesis (#7563)
+
+commit 0ac6f9d7e94a70b48457f289bcbeb069a4662c28
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Wed Jan 15 14:10:57 2025 +0100
+
+    [locale.moneypunct.general] Insert period at end (#7564)
+
+commit 96fad4cf7ff48c8a4ae5442580d55008fb56ca43
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Jan 15 10:06:49 2025 -0500
+
+    [inplace.vector.overview] Remove spurious semicolon closing namespace std (#7566)
+
+commit 1c398ffc71845163ca50b712f1edd9e1b2a87772
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Jan 17 17:11:02 2025 +0000
+
+    [type.info] Remove comments explaining deleted members
+
+    The standard is not a tutorial.
+
+commit 569e2a38cf1aa6d185b4c4d1817d9496ebd087e5
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Jan 18 09:18:53 2025 +0100
+
+    [exec.snd.expos] Move write-env paragraph into itemdescr (#7571)
+
+commit 93aa7cb89b375280cb2d5f385fb0c5a5874e9243
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Jan 18 23:32:20 2025 +0100
+
+    [re.err,re.alg.match,re.tokiter.incr] Add period at end for consistency (#7574)
+
+commit ce5fd62b98d822228f46319f4516e34c492fa257
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Wed Jan 22 16:15:57 2025 +0100
+
+    [string.view.io,string.insert] Add period at end of "Returns" (#7579)
+
+commit 5c4823a05b83a67f7550fdcc1476f8000c29514c
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Jan 23 11:31:05 2025 +0800
+
+    [expr.const] Re-apply CWG2909
+
+commit db563eecdfb63cb24f10afb30f001a0bc6213997
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Jan 15 07:59:51 2025 -0500
+
+    [lex.phases] Update implementation defined text
+
+    Since C++23 we no longer have physical source files, but rather
+    input files.  Update the two implementation-defined references
+    to the mapping from input file to translation character set
+    using the same phrasing so that they provide the same entry
+    in the index of implementation-defined behavior, just as they
+    did in C++20, before getting out of sync when the terminology
+    changed.
+
+commit a39cca2e9c009766da1e205daf5d7bf8cbdccaa3
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu Jan 23 07:28:40 2025 -0500
+
+    [linalg.conj.conjugated] Rearrange to match P3050R3 (#7506)
+
+    This was the wording requested by LWG and approved in P3050R3, but I
+    mistakenly put P3050R2 in the straw polls.
+
+commit 6583c4ac9c2d3bbfb7daac0c79c902a30417c50f
+Author: cor3ntin <corentinjabot@gmail.com>
+Date:   Sat Jan 25 14:11:30 2025 +0100
+
+    [std] Use template-parameter and template parameter more consistently (#7460)
+
+    Try to use template-parameter only when we refer to a
+    grammar construct, and to 'template parameter' everywhere else.
+
+    Adopt the same logic to template-argument/template argument.
+
+    This change might not be  exhaustive.
+
+    The aim is to editorially adopt some of the wording changes
+    made in P2841R5 to ease its review in core.
+
+commit 696dcd809ceed3fc10502161963f8ce13505ec1a
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Jan 25 21:25:32 2025 +0100
+
+    [format.string.general,format.formatter.spec] Fix unparenthesized cross-references
+
+commit 47cf5a67357543b0d45d0072f42fdd29fa028cca
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Wed Jan 29 09:29:54 2025 +0100
+
+    [alg.rand.generate] Add period at end of "Returns" (#7595)
+
+commit b2b266e7b67eb583c50c34a9eceffe44f72ea2f6
+Author: Ivan Lazarić <ivan.lazaric1@gmail.com>
+Date:   Sat Feb 1 09:56:42 2025 +0100
+
+    [temp.res.general] Fix nesting for \terminal{\opt{...}} (#7599)
+
+commit d51e6bedd991d55b7f7fb7f41e1f08083cfd1b1d
+Author: Eric Niebler <eniebler@boost.org>
+Date:   Mon Feb 3 12:05:48 2025 -0800
+
+    [range.view] Change incorrect uses of "which" to "that" (#7606)
+
+commit 1d49b05d1b48a2daa2a88d854e2367e6648c3cb6
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Feb 3 21:14:45 2025 +0100
+
+    [tuple.assign] Remove incorrect comma at end (#7609)
+
+commit 2e1b856b6187fe9a5c74782948982eefd128ecbf
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Feb 3 16:17:48 2025 -0500
+
+    [diff.cpp.library] Add new C23 headers to list of new headers
+
+commit cae9b2a645d5bb91caffc061325f107605e85a0d
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Feb 4 09:30:49 2025 +0100
+
+    [container.alloc.reqmts,sequence.reqmts] Add period at end (#7614)
+
+commit 003506a2779c519d4929cce75c7adeb1b7a76955
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Jan 1 18:45:19 2025 +0700
+
+    [macros] Add LaTeX macros to index library macros
+
+    The immediate idea is to support using the new macros directly
+    in header synopses when defining each library macro.  This will
+    ensure that no macros are accidentally not indexed.
+
+    A follow-up plan is that this separation of library macros will
+    make it easier to create a separate index of macros, or apply
+    other macro-specific renderings, in the future.  To this end,
+    all indexed uses of a macro, not just those in header files,
+    should be replaced by use of these new macros.  Similarly,
+    these LaTeX macros can be used in-place in regular text to
+    index cross-references where standard library macros are used
+    throughout the standard.
+
+commit d7618b4d20a24b37677b92c2fbd80dcee4565bc3
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Feb 7 09:37:37 2025 +0100
+
+    [diff.lex] Add period at end (#7618)
+
+commit 040ff41df1d0e0e4d31bd6c76f084fbc84239e7f
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Sat Feb 8 07:56:45 2025 +0000
+
+    [fs.op.current.path] Remove note discussing design choices (#7620)
+
+commit dfdc64cbdc842f0f7d2a060440ea907b41ce78e6
+Author: Vlad Serebrennikov <serebrennikov.vladislav@gmail.com>
+Date:   Sun Feb 9 20:12:44 2025 +0400
+
+    [basic.scope.scope] Update the note about special cases (#7594)
+
+commit 8948fd9bd8f799d50fc9cbff34b349b9d59157f1
+Author: André Brand <andre.brand@mailbox.org>
+Date:   Sun Feb 9 17:18:12 2025 +0100
+
+    [temp.mem.enum] Remove instantiation in example [temp.inst] (#7558)
+
+    The example is inconsistent with [temp.inst]p3. Since the implicit instantiation
+    does not contribute to the point of [temp.mem.enum], the inconsistency
+    can be resolved by omitting the instantiation.
+
+commit 0d0ea5582082f85fa707c680634044209c2e343d
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Nov 18 13:47:37 2024 +0000
+
+    [defns.argument] Mention braced-init-list
+
+commit 7566675c778f95ef966c4fea058a895def98e6d1
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sun Feb 9 11:23:22 2025 -0500
+
+    [lex.phases] Use preprocessing token consistently (#7361)
+
+    Prior to converting preprocessing tokens to tokens in phase 7,
+    all tokens are strictly preprocessing tokens.
+
+commit b9f054b0cba3a36f9c8eff0c190f85996597dc3d
+Author: cor3ntin <corentinjabot@gmail.com>
+Date:   Mon Feb 10 07:47:58 2025 +0100
+
+    [std] Rename "non-type" to "constant" template parameter/argument (#7587)
+
+    Note that not all instances of "non-type" have been mechanically replaced,
+    as [dcl] and [diff] use the term to refer to anything that is not a type
+    in the context of lookup.
+
+commit 45eb50507a1b6477dea6106c3c26654b96feae4a
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Fri Jan 31 14:04:53 2025 -0500
+
+    [cmath.syn] Consolidate std namespaces
+
+    There is no ordering dependency between the two typedefs
+    in namespace std, the macros that follow, and teh next
+    opening of namespace std, so move the two typedefs to
+    avoid repeatedly opening an closing the namespace.
+
+    Note that we could have done this without moving
+    the typedefs as macros are not bound by namespaces,
+    but our convention very sensibly avoids confusing
+    readers by keeping macro definitions outside of
+    namespaces.
+
+commit 5eab5c6b456db2424b04becb791b23dbf4de356a
+Author: Axel Naumann <Axel.Naumann@cern.ch>
+Date:   Mon Jan 27 15:50:24 2025 +0100
+
+    [class.prop] add ref to actual layout spec in [expr.rel]
+
+commit 2f42a31044cc1ec8cf119b0fd595fdcc1d625c59
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Jan 23 11:37:15 2025 +0800
+
+    [util.smartptr.atomic.{shared,weak}] Fix wording for initialization
+
+    By using more conventional "value-initializes".
+
+commit 4e026ec784007b492eb3d904663cfdc4bf905fd3
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Feb 4 11:09:05 2025 +0000
+
+    [fs.op.funcs] Remove empty parens when referring to functions by name
+
+    As per the Specification Style Guidelines.
+
+    https://github.com/cplusplus/draft/wiki/Specification-Style-Guidelines#describing-function-calls
+
+commit 7f00883b8f65307b7e0df0ad2e55182d699d2804
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Jan 13 22:33:34 2025 +0100
+
+    [xrefdelta] Restore cross-references since C++17
+
+commit 7fbdb79d99338d9aa91f382760ff6e1cb0353c71
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Oct 1 09:20:10 2024 -0400
+
+    [except.uncaught] Tidy the specification for uncaught exceptions
+
+    Several concurrent fixes.  First include the normative wording
+    that 'uncaught_exceptions' returns the number of uncaught
+    exceptions *on the current thread*.  This wording is present
+    in the core language.
+
+    Then move the core wording for when an exception is uncaught
+    directly into the text that talks about caught and uncaught
+    exceptions.  In the process, turn the reference to into a note,
+    so that there is only one normative specification.
+
+    Finally, remove [except.uncaught] as it is now empty.
+
+commit 70abf300ddbb1074cd16e9a5febe7f7c88bdff3d
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Nov 20 02:07:51 2024 +0100
+
+    [except.special.general] Complete the set of clause 17 references
+
+commit 888b0510da303e367f7421ac34607a158ddfc453
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Jan 21 04:31:34 2025 -0500
+
+    [basic.pre] Defragment specification of names and entities
+
+    The current contents of [basic.pre] jump between specifying
+    different things.  This PR moves all the specification of
+    names to the front, followed by the specification of entities.
+
+    There are two main benefits: (1) the specification for when
+    two names are the same is a list of 4 rules that correspond
+    to the 4 things than can form a name --- the connection is
+    much clearer when the paragraphs are adjacent and the list
+    is sorted to the same order; (2) in this form, even though
+    all the words are the same, the reordering and merging of
+    paragraphs a fit on a single page.  The very last paragraph
+    was forced over a page-break in the original layout.
+
+commit 5be40a6b59527e82b13a29722c623635065759bf
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Feb 11 21:42:20 2025 +0100
+
+    [expr.lval] Update cross reference for "invalid pointer value"
+
+commit 83530f54892686c9ba055434d02dfadc00bbb290
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Aug 3 00:54:57 2023 +0800
+
+    [basic.extended.fp] Use "declared" for typedef-names
+
+commit 1542d983b3f690876720d69a44dff2c5574617b3
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Aug 3 01:00:16 2023 +0800
+
+    [expr.{add,alignof,sizeof}] Use "typedef-name", avoid "defined"
+
+commit 152693b46648ea99493aecedbc8051aa2ab7542f
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Wed Feb 12 17:58:51 2025 +0000
+
+    [temp.param, temp.constr.normal] Use \dotsc for a non-code ellipsis (#7397)
+
+commit 930b8f97b0ab7bd9442bd0faf10f7302da5fc89a
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Feb 12 19:22:47 2025 +0100
+
+    [diff.cpp03.library] Fix cross-reference to restriction on macro names
+
+commit 2cfc175a01d2bff1daf084d5c776017c5c049872
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Feb 13 22:28:24 2025 +0000
+
+    [linalg.general] Remove extraneous dot (#7637)
+
+commit 422ded52d1876578f4eeb3bc30d583a193b94f42
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Feb 14 19:13:02 2025 +0100
+
+    [conv.rank] Fix typo
+
+commit 10468bf63eee8926b84b76a10abb2a7d05b43c02
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sun Feb 16 12:13:43 2025 +0100
+
+    [map.overview] Fix punctuation (#7677)
+
+commit a103bf3ea67a731189a8f1453d3e9ab88d589eba
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Mon Feb 24 07:46:22 2025 -0500
+
+    [xrefdelta] Consolidate restored entries (#7631)
+
+    Several entries in the restored larger delta referred
+    to stable labels that have since moved again, or have been
+    removed.  This commit updates their cross-references
+    accordingly, or marks them as removed if appropriate.
+
+commit 9854e729ba5ade9a41bf047b6a5fe6f4bbe038e0
+Author: Hubert Tong <hstong@ca.ibm.com>
+Date:   Thu Feb 13 17:01:13 2025 -0500
+
+    [basic.types.general] Change ordering to "non-variant non-static"
+
+    The definition of literal type is the only place where "non-static
+    non-variant data member" is used as opposed to "non-variant non-static
+    data member".
+
+    Change to use the canonical ordering.
+
+commit c31b8f4111dfa9dd598220b9c6f8c1cf9d4a9b34
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Tue Feb 25 09:54:40 2025 +0000
+
+    [support.srcloc.cons] Update xref to [class.mem.general]
+
+    The cross-reference to [class.mem] was referring to a hanging paragraph
+    that was fixed by 2850139be6285ba10a64fb718125a80ca967c631 so we should
+    be referring to [class.mem.general] now.
+
+commit 912e5cab7565be0daa9c0c6d7c178600b3cd38e6
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sat Mar 15 20:23:43 2025 +0000
+
+    [functional.{syn,bind.place}] Use \vdots; add missing \placeholder (#7723)
+
+commit 0dda8468be890adf880afddc37e449cbc40607cb
+Author: A. Jiang <de34@live.cn>
+Date:   Sun Mar 16 04:26:10 2025 +0800
+
+    [expr.const] Change "value" to "result object" (of a prvalue) (#6267)
+
+commit 4552a92a01a2d1b032264cd6568a860a5244918b
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Nov 7 22:35:21 2021 +0100
+
+    [lex.string] Clarify size of string-literal
+
+commit ec10aaec4e6daac66b7b28426abcc765494194c9
+Author: Hubert Tong <hubert.reinterpretcast@gmail.com>
+Date:   Sat Mar 15 16:41:54 2025 -0400
+
+    [debugging.utility] Clarify wording in notes
+
+    The previous wording in the notes in `breakpoint` and `is_debugger_present`
+    read as statements of fact about the implementation-defined behaviour.
+    The statements are actually ones of intent.
+
+    The specific claim in `breakpoint` that the debugger resumes execution of the program
+    as if the function was not invoked is confusing considering that the debugger may effect
+    side-effects or cause execution to resume from a different evaluation.
+
+    Instead, the idea is that `breakpoint` is not responsible for causing the translation process
+    to make special accomodations for resumption of execution other than in cases
+    where the debugger was strictly used for observation only.
+
+    In `is_debugger_present`, the functionality ascribed to POSIX by the wording
+    ("ptrace") is not present in POSIX. Update to reference the LSB and to use
+    the corresponding terminology ("tracing process").
+
+    The wording implies a preference to return `true` in case it is unknown
+    whether a debugger is present. Add a critical "only" to fix that.
+
+commit 598910dc970bc0bc840ba797983e9bc131cd826e
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Feb 25 07:51:44 2025 +0800
+
+    [ifstream.members] Remove mistakenly added `@`
+
+commit 4b5a0080230ed74d796a3ee909bdde66e2f2b395
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Aug 7 18:45:41 2024 +0800
+
+    [func.wrap.func] Drop Lvalue-Callable
+
+    Replace its usages with `is_invocable_r_v` and remove an unnecessary index.
+
+commit f9847af90413adb0436aae9f6895b4a2e0e173ec
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Feb 17 11:44:11 2025 +0800
+
+    [containers, strings, algorithms, re] Use \range where appropriate
+
+    Currently, there are several cases where `\tcode{[i, j)}` is used for
+    specifying left-closed right-open intervals, where `\range{i}{j}` is proper.
+
+    Co-authored-by: Eelis van der Weegen <eelis@eelis.net>
+
+commit 73699cf37d247a7c1f3a6879197c730a14666b90
+Author: languagelawyer <38548419+languagelawyer@users.noreply.github.com>
+Date:   Fri Feb 26 02:55:52 2021 +0300
+
+    [class.cdtor] Only objects of scalar type can be accessed
+
+ + diff --git a/papers/n5009.md b/papers/n5009.md new file mode 100644 index 0000000000..2caf3f0571 --- /dev/null +++ b/papers/n5009.md @@ -0,0 +1,753 @@ +# N5009 Editors' Report -- Programming Languages -- C++ + +Date: 2025-03-15 + +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), +to those who have provided pull requests with fixes, +and to everyone who drafted motion applications. + +## New papers + + * [N5008](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5008.pdf) is the + current working draft for C++26. It replaces + [N5001](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/n5001.pdf). + * N5009 is this Editors' Report. + +## Motions incorporated into working draft + +### Notes on motions + +LWG Poll 2 was retracted. + +Library issue [LWG4189](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3615r0.html#4189), +adopted by LWG Poll 1 (P3615R0) had the effect of making most of the content of `` +free-standing by default, with the note that "[m]ost future additions to this header should +have no problem being freestanding, so that is the right default." Absent an explicit +opt-out, the new facilities from LWG Poll 14 +([P2846R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2846r6.html)), +`reserve_hint` and `approximately_sized_range`, are now free-standing as well. + +### Core working group polls + +CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues in +[P3638R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3638r0.html) +(Core Language Working Group "ready" Issues for the February, 2025 meeting) to the C++ Working Paper. + +CWG Poll 2. Apply the changes in [P3542R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3542r0.html) +(Abolish the term "converting constructor") to the C++ Working Paper. + +CWG Poll 3. Apply the changes in [P3074R7](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3074r7.html) +(trivial unions (was `std::uninitialized`)) to the C++ Working Paper. + +CWG Poll 4. Apply the changes in [P1494R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p1494r5.html) +(Partial program correctness) to the C++ Working Paper. + +CWG Poll 5. Apply the changes in [P2900R14](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2900r14.pdf) +(Contracts for C++) to the C++ Working Paper. + +CWG Poll 6. Apply the changes in [P3475R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3475r2.pdf) +(Defang and deprecate `memory_order::consume`) to the C++ Working Paper. + +CWG Poll 7. Apply the changes in [P2841R7](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2841r7.pdf) +(Concept and variable-template template-parameters) to the C++ Working Paper. + +CWG Poll 8. Apply the changes in [P2786R13](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2786r13.html) +(Trivial Relocatability For C++26) to the C++ Working Paper. + +CWG Poll 9. Apply the changes in [P1967R14](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p1967r14.html) +(`#embed` - a simple, scannable preprocessor-based resource acquisition method) to the C++ Working Paper. + +### Library working group polls + +LWG Poll 1. Apply the changes for all Tentatively Ready issues in +[P3615R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3615r0.html) +(C++ Standard Library Ready Issues to be moved in Hagenberg, Feb. 2025) to the C++ working paper. + +LWG Poll 2 was retracted. + +LWG Poll 3. Apply the changes in [P3137R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3137r3.html) +(`views::to_input`) to the C++ working paper. + +LWG Poll 4. Apply the changes in [P0472R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p0472r3.pdf) +(Put `std::monostate` in ``) to the C++ working paper. + +LWG Poll 5. Apply the changes in [P3349R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3349r1.html) +(Converting contiguous iterators to pointers) to the C++ working paper. + +LWG Poll 6. Apply the changes in [P3372R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3372r3.html) +(constexpr containers and adaptors) to the C++ working paper. + +LWG Poll 7. Apply the changes in [P3378R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3378r2.html) +(constexpr exception types) to the C++ working paper. + +LWG Poll 8. Apply the changes in [P3441R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3441r2.html) +(Rename `simd_split` to `simd_chunk`) to the C++ working paper. + +LWG Poll 9. Apply the changes in [P3287R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3287r3.pdf) +(Exploration of namespaces for `std::simd`) to the C++ working paper. + +LWG Poll 10. Apply the changes in [P2976R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2976r1.html) +(Freestanding Library: algorithm, numeric, and random) to the C++ working paper. + +LWG Poll 11. Apply the changes in [P3430R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3430r3.pdf) +(SIMD issues: explicit, unsequenced, identity-element position, and members of disabled SIMD) to the C++ working paper. + +LWG Poll 12. Apply the changes in [P2663R7](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2663r7.html) +(Interleaved complex values support in `std::simd`) to the C++ working paper. + +LWG Poll 13. Apply the changes in [P2933R4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2933r4.html) +(Extend `` header function with overloads for `std::simd`) to the C++ working paper. + +LWG Poll 14. Apply the changes in [P2846R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2846r6.pdf) +(`reserve_hint`: Eagerly reserving memory for not-quite-sized lazy ranges) to the C++ working paper. + +LWG Poll 15. Apply the changes in [P3471R4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3471r4.html) +(Standard Library Hardening) to the C++ working paper. + +LWG Poll 16. Apply the changes in [P0447R28](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p0447r28.html) +(Introduction of `std::hive` to the standard library) to the C++ working paper. + +LWG Poll 17. Apply the changes in [P3019R14](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3019r14.pdf) +(`indirect` and `polymorphic`: Vocabulary Types for Composite Class Design) to the C++ working paper. + +## Editorial changes + +### Major editorial changes + +There have not been any major editorial changes. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N5001 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/n5001...n5008). + + commit f3676cb1550f1501236cc65c1dfa2dec957bbdf2 + Author: Mark Hoemmen + Date: Tue Dec 17 14:15:10 2024 -0700 + + [linalg.conj.conjugated] Remove inappropriate "expression-equivalent" wording (#7497) + + This phrase appears to be copy-pasted from elsewhere, but is not meaningful here. + + commit be0a25c9a2f2c1f498b0ff84a33c28adae41863e + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Dec 17 20:31:14 2024 +0100 + + [simd.alg] Fix range syntax + + commit a18040f05ff6a27e5c6425005ab1b21515ad952c + Author: Eisenwave + Date: Fri Nov 1 08:06:28 2024 +0100 + + [basic.compound] Update introduction + + commit 0131e015c09eca1901d0bfa46744a6c7ab31b00d + Author: Jonathan Wakely + Date: Tue Dec 17 21:21:42 2024 +0000 + + [linalg.helpers] Rename template parameter for poison pills + + This avoids reusing `T` which is also used for the type of the + subexpression E. + + Fixes #7494 + + commit 04169bac7059322ad8bf32e605a80e57ef30b922 + Author: Jens Maurer + Date: Tue Dec 17 22:51:01 2024 +0100 + + [inplace.vector.overview] Replace residual use of 'trivial type' + + commit 9272753d0ecbc1df9d08178793795f06b623a451 + Author: Hewill Kang + Date: Tue Nov 19 16:41:00 2024 +0800 + + [flat.map.defn, flat.set.defn] Avoid naming the from_range_t tag + + commit 85de0af0e0af416f7e73ac096254641c31bf11cc + Author: Jens Maurer + Date: Tue Dec 17 23:19:21 2024 +0100 + + [basic.fundamental] Ensure consistency with [conv.ptr] + + commit 561a4d8cde9e434fe206b88489e95b0e5271f469 + Author: Mark Hoemmen + Date: Thu Dec 19 14:35:50 2024 -0700 + + [bibliography] Fix spelling and formatting (#7507) + + Fix spelling of one author's name. Add missing commas + and extra spaces after a period ending authors' abbreviated + first or middle names. + + commit 82153790d8904ea82bc57edc8885b02925e85e93 + Author: Mark Hoemmen + Date: Thu Dec 19 14:41:02 2024 -0700 + + [simd.general, bibliography] Add SIMD acronym explanation and bibliographic reference (#7504) + + To the existing Note at the beginning of [simd.general], + add text that unpacks the SIMD acronym and refers to Flynn 1966. + + Add bibliography entry for Flynn 1966, the paper that introduced what + later became known as "Flynn's Taxonomy." This classifies parallel + computer hardware as SISD, SIMD, MISD, or MIMD. + + commit e1a368bc157f824cee7702e87a2cca1951e60f98 + Author: Jonathan Wakely + Date: Thu Dec 19 11:02:38 2024 +0000 + + [mdspan.sub] Change to "unit-stride slice for mapping" + + This was the wording requested by LWG and approved in P3355R2, but I + mistakenly put P3355R1 in the straw polls. + + commit 2d3ac367d8605d7172151726e873daea295a573a + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Dec 20 10:15:46 2024 +0100 + + [diff.cpp03.library] Correct \effect to \change + + - Correct \effect to \change. + - Add period at end. + - Add \tcode for swap. + + commit a2429a5944b71e3563dc09730426af43fb4b53e1 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Dec 26 01:37:34 2024 +0000 + + [class.expl.init] Fix incorrect note + + commit 1411cf56fcb41f9fd000406185f17ef47235d26a + Author: Bronek Kozicki + Date: Wed Jan 1 17:00:14 2025 +0000 + + [expected.bad.void] Fix syntax error in bad_expected_access (#7529) + + Introduced by commit 8c997445c176c81a334e77f9344b91abc72b2772 + + commit a137940ac9c807e3ea809c3ff0b3a863795bf742 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Wed Jan 1 22:18:37 2025 +0100 + + [filebuf.members,fs.path.req] Fix indefinite article (#7530) + + commit d2b48043fcc219b2a141af39dae2eb85934c0847 + Author: Jens Maurer + Date: Thu Jan 2 10:49:14 2025 +0100 + + [expr.const] Properly merge P2686R5 + + P2686R5 (applied by commit e220906b71df01f09fe60921e8fac39b80558f78) + accidentally reverted a change considering erroneous values made by + P2795R5. + + commit 22937c04da139226c186973eda2cdb79df640b5b + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Jan 2 15:14:06 2025 +0100 + + [format.arg] Fix indefinite article (#7536) + + commit 75af9f7f8cd816e1908eb2a3917eb7749c11471a + Author: Alisdair Meredith + Date: Sat Jan 4 02:18:53 2025 +0700 + + [tuple.helper] Remove redundant 'public' in base-specifier of struct (#7539) + + commit 6ff55d533f72b7222e022513dcb80982f4e887a0 + Author: Jens Maurer + Date: Mon Dec 30 16:34:49 2024 +0100 + + [lex.icon,depr.locale.category] Remove duplicate 'table' in front of table references + + commit 70df8aa8f4a30a7d54a604cbe01ebe13f5973043 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Wed Jan 8 13:51:13 2025 +0100 + + [linalg.algs.blas2.gemv] Fix singular/plural mismatch (#7546) + + commit 0164098f821ae002469c6f23cd03fc66a0a2f7ca + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Jan 9 10:01:36 2025 +0000 + + [basic.def.odr] Fix typo and reference the correct subclause + + commit 2734ddeb05115f3fddf09c9c15b843083575e9df + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Jan 10 13:13:28 2025 +0100 + + [exec.async.ops] Remove stray closing parenthesis (#7555) + + commit 77171de904e6008f31717615d5baabf604baeea8 + Author: S. B. Tam + Date: Fri Jan 10 23:05:58 2025 +0800 + + [locale.time.put.members] Remove incorrect footnote (#7553) + + commit 6ecd1be67c71001db37883ee45b76cc66ef4101f + Author: Jens Maurer + Date: Mon Jan 13 22:34:47 2025 +0100 + + [exec.getcomplsigs] Add missing LaTeX escaping of braces (#7541) + + commit 1b1914ed868b0b29e63d0d1e4b872daf07b50740 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Jan 14 14:31:09 2025 +0100 + + [simd.traits] Remove stray closing parenthesis (#7563) + + commit 0ac6f9d7e94a70b48457f289bcbeb069a4662c28 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Wed Jan 15 14:10:57 2025 +0100 + + [locale.moneypunct.general] Insert period at end (#7564) + + commit 96fad4cf7ff48c8a4ae5442580d55008fb56ca43 + Author: Alisdair Meredith + Date: Wed Jan 15 10:06:49 2025 -0500 + + [inplace.vector.overview] Remove spurious semicolon closing namespace std (#7566) + + commit 1c398ffc71845163ca50b712f1edd9e1b2a87772 + Author: Jonathan Wakely + Date: Fri Jan 17 17:11:02 2025 +0000 + + [type.info] Remove comments explaining deleted members + + The standard is not a tutorial. + + commit 569e2a38cf1aa6d185b4c4d1817d9496ebd087e5 + Author: Jens Maurer + Date: Sat Jan 18 09:18:53 2025 +0100 + + [exec.snd.expos] Move write-env paragraph into itemdescr (#7571) + + commit 93aa7cb89b375280cb2d5f385fb0c5a5874e9243 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Jan 18 23:32:20 2025 +0100 + + [re.err,re.alg.match,re.tokiter.incr] Add period at end for consistency (#7574) + + commit ce5fd62b98d822228f46319f4516e34c492fa257 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Wed Jan 22 16:15:57 2025 +0100 + + [string.view.io,string.insert] Add period at end of "Returns" (#7579) + + commit 5c4823a05b83a67f7550fdcc1476f8000c29514c + Author: A. Jiang + Date: Thu Jan 23 11:31:05 2025 +0800 + + [expr.const] Re-apply CWG2909 + + commit db563eecdfb63cb24f10afb30f001a0bc6213997 + Author: Alisdair Meredith + Date: Wed Jan 15 07:59:51 2025 -0500 + + [lex.phases] Update implementation defined text + + Since C++23 we no longer have physical source files, but rather + input files. Update the two implementation-defined references + to the mapping from input file to translation character set + using the same phrasing so that they provide the same entry + in the index of implementation-defined behavior, just as they + did in C++20, before getting out of sync when the terminology + changed. + + commit a39cca2e9c009766da1e205daf5d7bf8cbdccaa3 + Author: Jonathan Wakely + Date: Thu Jan 23 07:28:40 2025 -0500 + + [linalg.conj.conjugated] Rearrange to match P3050R3 (#7506) + + This was the wording requested by LWG and approved in P3050R3, but I + mistakenly put P3050R2 in the straw polls. + + commit 6583c4ac9c2d3bbfb7daac0c79c902a30417c50f + Author: cor3ntin + Date: Sat Jan 25 14:11:30 2025 +0100 + + [std] Use template-parameter and template parameter more consistently (#7460) + + Try to use template-parameter only when we refer to a + grammar construct, and to 'template parameter' everywhere else. + + Adopt the same logic to template-argument/template argument. + + This change might not be exhaustive. + + The aim is to editorially adopt some of the wording changes + made in P2841R5 to ease its review in core. + + commit 696dcd809ceed3fc10502161963f8ce13505ec1a + Author: Jens Maurer + Date: Sat Jan 25 21:25:32 2025 +0100 + + [format.string.general,format.formatter.spec] Fix unparenthesized cross-references + + commit 47cf5a67357543b0d45d0072f42fdd29fa028cca + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Wed Jan 29 09:29:54 2025 +0100 + + [alg.rand.generate] Add period at end of "Returns" (#7595) + + commit b2b266e7b67eb583c50c34a9eceffe44f72ea2f6 + Author: Ivan Lazarić + Date: Sat Feb 1 09:56:42 2025 +0100 + + [temp.res.general] Fix nesting for \terminal{\opt{...}} (#7599) + + commit d51e6bedd991d55b7f7fb7f41e1f08083cfd1b1d + Author: Eric Niebler + Date: Mon Feb 3 12:05:48 2025 -0800 + + [range.view] Change incorrect uses of "which" to "that" (#7606) + + commit 1d49b05d1b48a2daa2a88d854e2367e6648c3cb6 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Feb 3 21:14:45 2025 +0100 + + [tuple.assign] Remove incorrect comma at end (#7609) + + commit 2e1b856b6187fe9a5c74782948982eefd128ecbf + Author: Alisdair Meredith + Date: Mon Feb 3 16:17:48 2025 -0500 + + [diff.cpp.library] Add new C23 headers to list of new headers + + commit cae9b2a645d5bb91caffc061325f107605e85a0d + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Feb 4 09:30:49 2025 +0100 + + [container.alloc.reqmts,sequence.reqmts] Add period at end (#7614) + + commit 003506a2779c519d4929cce75c7adeb1b7a76955 + Author: Alisdair Meredith + Date: Wed Jan 1 18:45:19 2025 +0700 + + [macros] Add LaTeX macros to index library macros + + The immediate idea is to support using the new macros directly + in header synopses when defining each library macro. This will + ensure that no macros are accidentally not indexed. + + A follow-up plan is that this separation of library macros will + make it easier to create a separate index of macros, or apply + other macro-specific renderings, in the future. To this end, + all indexed uses of a macro, not just those in header files, + should be replaced by use of these new macros. Similarly, + these LaTeX macros can be used in-place in regular text to + index cross-references where standard library macros are used + throughout the standard. + + commit d7618b4d20a24b37677b92c2fbd80dcee4565bc3 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Feb 7 09:37:37 2025 +0100 + + [diff.lex] Add period at end (#7618) + + commit 040ff41df1d0e0e4d31bd6c76f084fbc84239e7f + Author: Jonathan Wakely + Date: Sat Feb 8 07:56:45 2025 +0000 + + [fs.op.current.path] Remove note discussing design choices (#7620) + + commit dfdc64cbdc842f0f7d2a060440ea907b41ce78e6 + Author: Vlad Serebrennikov + Date: Sun Feb 9 20:12:44 2025 +0400 + + [basic.scope.scope] Update the note about special cases (#7594) + + commit 8948fd9bd8f799d50fc9cbff34b349b9d59157f1 + Author: André Brand + Date: Sun Feb 9 17:18:12 2025 +0100 + + [temp.mem.enum] Remove instantiation in example [temp.inst] (#7558) + + The example is inconsistent with [temp.inst]p3. Since the implicit instantiation + does not contribute to the point of [temp.mem.enum], the inconsistency + can be resolved by omitting the instantiation. + + commit 0d0ea5582082f85fa707c680634044209c2e343d + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Nov 18 13:47:37 2024 +0000 + + [defns.argument] Mention braced-init-list + + commit 7566675c778f95ef966c4fea058a895def98e6d1 + Author: Alisdair Meredith + Date: Sun Feb 9 11:23:22 2025 -0500 + + [lex.phases] Use preprocessing token consistently (#7361) + + Prior to converting preprocessing tokens to tokens in phase 7, + all tokens are strictly preprocessing tokens. + + commit b9f054b0cba3a36f9c8eff0c190f85996597dc3d + Author: cor3ntin + Date: Mon Feb 10 07:47:58 2025 +0100 + + [std] Rename "non-type" to "constant" template parameter/argument (#7587) + + Note that not all instances of "non-type" have been mechanically replaced, + as [dcl] and [diff] use the term to refer to anything that is not a type + in the context of lookup. + + commit 45eb50507a1b6477dea6106c3c26654b96feae4a + Author: Alisdair Meredith + Date: Fri Jan 31 14:04:53 2025 -0500 + + [cmath.syn] Consolidate std namespaces + + There is no ordering dependency between the two typedefs + in namespace std, the macros that follow, and teh next + opening of namespace std, so move the two typedefs to + avoid repeatedly opening an closing the namespace. + + Note that we could have done this without moving + the typedefs as macros are not bound by namespaces, + but our convention very sensibly avoids confusing + readers by keeping macro definitions outside of + namespaces. + + commit 5eab5c6b456db2424b04becb791b23dbf4de356a + Author: Axel Naumann + Date: Mon Jan 27 15:50:24 2025 +0100 + + [class.prop] add ref to actual layout spec in [expr.rel] + + commit 2f42a31044cc1ec8cf119b0fd595fdcc1d625c59 + Author: A. Jiang + Date: Thu Jan 23 11:37:15 2025 +0800 + + [util.smartptr.atomic.{shared,weak}] Fix wording for initialization + + By using more conventional "value-initializes". + + commit 4e026ec784007b492eb3d904663cfdc4bf905fd3 + Author: Jonathan Wakely + Date: Tue Feb 4 11:09:05 2025 +0000 + + [fs.op.funcs] Remove empty parens when referring to functions by name + + As per the Specification Style Guidelines. + + https://github.com/cplusplus/draft/wiki/Specification-Style-Guidelines#describing-function-calls + + commit 7f00883b8f65307b7e0df0ad2e55182d699d2804 + Author: Jens Maurer + Date: Mon Jan 13 22:33:34 2025 +0100 + + [xrefdelta] Restore cross-references since C++17 + + commit 7fbdb79d99338d9aa91f382760ff6e1cb0353c71 + Author: Alisdair Meredith + Date: Tue Oct 1 09:20:10 2024 -0400 + + [except.uncaught] Tidy the specification for uncaught exceptions + + Several concurrent fixes. First include the normative wording + that 'uncaught_exceptions' returns the number of uncaught + exceptions *on the current thread*. This wording is present + in the core language. + + Then move the core wording for when an exception is uncaught + directly into the text that talks about caught and uncaught + exceptions. In the process, turn the reference to into a note, + so that there is only one normative specification. + + Finally, remove [except.uncaught] as it is now empty. + + commit 70abf300ddbb1074cd16e9a5febe7f7c88bdff3d + Author: Alisdair Meredith + Date: Wed Nov 20 02:07:51 2024 +0100 + + [except.special.general] Complete the set of clause 17 references + + commit 888b0510da303e367f7421ac34607a158ddfc453 + Author: Alisdair Meredith + Date: Tue Jan 21 04:31:34 2025 -0500 + + [basic.pre] Defragment specification of names and entities + + The current contents of [basic.pre] jump between specifying + different things. This PR moves all the specification of + names to the front, followed by the specification of entities. + + There are two main benefits: (1) the specification for when + two names are the same is a list of 4 rules that correspond + to the 4 things than can form a name --- the connection is + much clearer when the paragraphs are adjacent and the list + is sorted to the same order; (2) in this form, even though + all the words are the same, the reordering and merging of + paragraphs a fit on a single page. The very last paragraph + was forced over a page-break in the original layout. + + commit 5be40a6b59527e82b13a29722c623635065759bf + Author: Thomas Köppe + Date: Tue Feb 11 21:42:20 2025 +0100 + + [expr.lval] Update cross reference for "invalid pointer value" + + commit 83530f54892686c9ba055434d02dfadc00bbb290 + Author: A. Jiang + Date: Thu Aug 3 00:54:57 2023 +0800 + + [basic.extended.fp] Use "declared" for typedef-names + + commit 1542d983b3f690876720d69a44dff2c5574617b3 + Author: A. Jiang + Date: Thu Aug 3 01:00:16 2023 +0800 + + [expr.{add,alignof,sizeof}] Use "typedef-name", avoid "defined" + + commit 152693b46648ea99493aecedbc8051aa2ab7542f + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Wed Feb 12 17:58:51 2025 +0000 + + [temp.param, temp.constr.normal] Use \dotsc for a non-code ellipsis (#7397) + + commit 930b8f97b0ab7bd9442bd0faf10f7302da5fc89a + Author: Alisdair Meredith + Date: Wed Feb 12 19:22:47 2025 +0100 + + [diff.cpp03.library] Fix cross-reference to restriction on macro names + + commit 2cfc175a01d2bff1daf084d5c776017c5c049872 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Feb 13 22:28:24 2025 +0000 + + [linalg.general] Remove extraneous dot (#7637) + + commit 422ded52d1876578f4eeb3bc30d583a193b94f42 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Feb 14 19:13:02 2025 +0100 + + [conv.rank] Fix typo + + commit 10468bf63eee8926b84b76a10abb2a7d05b43c02 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sun Feb 16 12:13:43 2025 +0100 + + [map.overview] Fix punctuation (#7677) + + commit a103bf3ea67a731189a8f1453d3e9ab88d589eba + Author: Alisdair Meredith + Date: Mon Feb 24 07:46:22 2025 -0500 + + [xrefdelta] Consolidate restored entries (#7631) + + Several entries in the restored larger delta referred + to stable labels that have since moved again, or have been + removed. This commit updates their cross-references + accordingly, or marks them as removed if appropriate. + + commit 9854e729ba5ade9a41bf047b6a5fe6f4bbe038e0 + Author: Hubert Tong + Date: Thu Feb 13 17:01:13 2025 -0500 + + [basic.types.general] Change ordering to "non-variant non-static" + + The definition of literal type is the only place where "non-static + non-variant data member" is used as opposed to "non-variant non-static + data member". + + Change to use the canonical ordering. + + commit c31b8f4111dfa9dd598220b9c6f8c1cf9d4a9b34 + Author: Jonathan Wakely + Date: Tue Feb 25 09:54:40 2025 +0000 + + [support.srcloc.cons] Update xref to [class.mem.general] + + The cross-reference to [class.mem] was referring to a hanging paragraph + that was fixed by 2850139be6285ba10a64fb718125a80ca967c631 so we should + be referring to [class.mem.general] now. + + commit 912e5cab7565be0daa9c0c6d7c178600b3cd38e6 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sat Mar 15 20:23:43 2025 +0000 + + [functional.{syn,bind.place}] Use \vdots; add missing \placeholder (#7723) + + commit 0dda8468be890adf880afddc37e449cbc40607cb + Author: A. Jiang + Date: Sun Mar 16 04:26:10 2025 +0800 + + [expr.const] Change "value" to "result object" (of a prvalue) (#6267) + + commit 4552a92a01a2d1b032264cd6568a860a5244918b + Author: Jens Maurer + Date: Sun Nov 7 22:35:21 2021 +0100 + + [lex.string] Clarify size of string-literal + + commit ec10aaec4e6daac66b7b28426abcc765494194c9 + Author: Hubert Tong + Date: Sat Mar 15 16:41:54 2025 -0400 + + [debugging.utility] Clarify wording in notes + + The previous wording in the notes in `breakpoint` and `is_debugger_present` + read as statements of fact about the implementation-defined behaviour. + The statements are actually ones of intent. + + The specific claim in `breakpoint` that the debugger resumes execution of the program + as if the function was not invoked is confusing considering that the debugger may effect + side-effects or cause execution to resume from a different evaluation. + + Instead, the idea is that `breakpoint` is not responsible for causing the translation process + to make special accomodations for resumption of execution other than in cases + where the debugger was strictly used for observation only. + + In `is_debugger_present`, the functionality ascribed to POSIX by the wording + ("ptrace") is not present in POSIX. Update to reference the LSB and to use + the corresponding terminology ("tracing process"). + + The wording implies a preference to return `true` in case it is unknown + whether a debugger is present. Add a critical "only" to fix that. + + commit 598910dc970bc0bc840ba797983e9bc131cd826e + Author: A. Jiang + Date: Tue Feb 25 07:51:44 2025 +0800 + + [ifstream.members] Remove mistakenly added `@` + + commit 4b5a0080230ed74d796a3ee909bdde66e2f2b395 + Author: A. Jiang + Date: Wed Aug 7 18:45:41 2024 +0800 + + [func.wrap.func] Drop Lvalue-Callable + + Replace its usages with `is_invocable_r_v` and remove an unnecessary index. + + commit f9847af90413adb0436aae9f6895b4a2e0e173ec + Author: A. Jiang + Date: Mon Feb 17 11:44:11 2025 +0800 + + [containers, strings, algorithms, re] Use \range where appropriate + + Currently, there are several cases where `\tcode{[i, j)}` is used for + specifying left-closed right-open intervals, where `\range{i}{j}` is proper. + + Co-authored-by: Eelis van der Weegen + + commit 73699cf37d247a7c1f3a6879197c730a14666b90 + Author: languagelawyer <38548419+languagelawyer@users.noreply.github.com> + Date: Fri Feb 26 02:55:52 2021 +0300 + + [class.cdtor] Only objects of scalar type can be accessed + diff --git a/papers/n5015.html b/papers/n5015.html new file mode 100644 index 0000000000..045c98dcae --- /dev/null +++ b/papers/n5015.html @@ -0,0 +1,1926 @@ + + + + + +N5015 + + +

N5015 Editors’ Report:
Programming Languages — C++

+ +

Date: 2025-08-14

+ +

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, +to those who have provided pull requests with fixes, +and to everyone who drafted motion applications. +Special thanks to Alisdair Meredith and Jan Schultke +for drafting a lot of motion applications, +to Andreas Krug for ongoing careful reviews, +and to the review committee for finding and fixing many transcription errors +in this rather large amount of added text.

+ +

New papers

+ +
    +
  • N5013 is the C++26 Committee Draft.
  • +
  • N5014 is the +current working draft for C++26. It replaces +N5008.
  • +
  • N5015 is this Editors' Report.
  • +
+ + +

Motions incorporated into working draft

+ +

Notes on motions

+ +

All motions were applied cleanly.

+ +

In CWG Motion 11, +P2843R3 +(“Preprocessing is never undefined”), the text has been reconciled with +earlier changes coming from CWG Motion 1, Issue +CWG3015.

+ +

In LWG Motion 35, +P1317R2 +(“Remove return type deduction in std::apply”), the feature test macro +__cpp_lib_apply was bumped and marked as also being in <type_traits>.

+ +

Several minor phrasing and punctuation improvements have been applied +in subsequent reviews, and some minor errors and oversights in the approved +texts have been fixed in consultation with authors and wording group chairs.

+ +

Core working group polls

+ +

CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues except issues 3013, 3014 and 3020 in +P3752R0 +(Core Language Working Group “ready” Issues for the June, 2025 meeting) to the C++ Working Paper.

+ +

CWG Poll 2. Apply the proposed resolutions of issues 3013, 3014 and 3020 in +P3752R0 +(Core Language Working Group “ready” Issues for the June, 2025 meeting) to the C++ Working Paper.

+ +

CWG Poll 3. Accept as a Defect Report and apply the changes in +P3618R0 +(Allow attaching main to the global module) to the C++ Working Paper.

+ +

CWG Poll 4. Apply the changes in P2996R13 +(Reflection for C++26) to the C++ Working Paper and accept as Defect Reports core issues 2701 and 3026 resolved thereby.

+ +

CWG Poll 5. Apply the changes in P3394R4 +(Annotations for Reflection) to the C++ Working Paper.

+ +

CWG Poll 6. Apply the changes in P3293R3 +(Splicing a base class subobject) to the C++ Working Paper.

+ +

CWG Poll 7. Apply the changes in P3491R3 +(define_static_{string,object,array}) to the C++ Working Paper.

+ +

CWG Poll 8. Apply the changes in P1306R5 +(Expansion Statements) to the C++ Working Paper.

+ +

CWG Poll 9. Apply the changes in P3096R12 +(Function Parameter Reflection in Reflection for C++26) to the C++ Working Paper.

+ +

CWG Poll 10. Apply the changes in +P3533R2 +(constexpr virtual inheritance) to the C++ Working Paper.

+ +

CWG Poll 11. Apply the changes in P2843R3 +(Preprocessing is never undefined) to the C++ Working Paper.

+ +

Library working group polls

+ +

LWG Poll 1. Apply the changes in P3742R0 +(C++ Standard Library Issues to be moved in Sofia, Jun. 2025) to the C++ working paper.

+ +

LWG Poll 2. Apply the changes in P2988R12 +(std::optional<‍T&‍>) to the C++ working paper.

+ +

LWG Poll 3. Apply the changes in P3348R4 +(C++26 should refer to C23 not C17) to the C++ working paper.

+ +

LWG Poll 4. Apply the changes in P3037R6 +(constexpr std::shared_ptr and friends) to the C++ working paper.

+ +

LWG Poll 5. Apply the changes in P3284R4 +(write_env and unstoppable Sender Adaptors) to the C++ working paper.

+ +

LWG Poll 6. Apply the changes in P3179R9 +(Parallel Range Algorithms) to the C++ working paper.

+ +

LWG Poll 7. Apply the changes in P3709R2 +(Reconsider parallel ranges::rotate_copy and ranges::reverse_copy) to the C++ working paper.

+ +

LWG Poll 8. Apply the changes in P3641R0 +(Rename std::observable to std::observable_checkpoint, and add a feature-test macro) to the C++ working paper.

+ +

LWG Poll 9. Apply the changes in P3044R2 +(sub-string_view from string) to the C++ working paper.

+ +

LWG Poll 10. Apply the changes in P2876R3 +(Proposal to extend std::simd with more constructors and accessors) to the C++ working paper.

+ +

LWG Poll 11. Apply the changes in P3480R6 +(std::simd is a range) to the C++ working paper.

+ +

LWG Poll 12. Apply the changes in P2664R11 +(Extend std::simd with permutation API) to the C++ working paper.

+ +

LWG Poll 13. Apply the changes in P3691R1 +(Reconsider naming of the namespace for “std::simd”) to the C++ working paper.

+ +

LWG Poll 14. Apply the changes in P3383R3 +(mdspan.at()) to the C++ working paper.

+ +

LWG Poll 15. Apply the changes in P2927R3 +(Inspecting exception_ptr) to the C++ working paper.

+ +

LWG Poll 16. Apply the changes in P3748R0 +(Inspecting exception_ptr should be constexpr) to the C++ working paper.

+ +

LWG Poll 17. Apply the changes in P2830R10 +(Standardized Constexpr Type Ordering) to the C++ working paper.

+ +

LWG Poll 18. Apply the changes in P3570R2 +(optional variants in sender/receiver) to the C++ working paper.

+ +

LWG Poll 19. Apply the changes in P3481R5 +(std::execution::bulk() issues) to the C++ working paper.

+ +

LWG Poll 20. Apply the changes in P3433R1 +(Allocator Support for Operation States) to the C++ working paper.

+ +

LWG Poll 21. Apply the changes in P3149R11 +(async_scope - Creating scopes for non-sequential concurrency) to the C++ working paper.

+ +

LWG Poll 22. Apply the changes in P3682R0 +(Remove std::execution::split) to the C++ working paper.

+ +

LWG Poll 23. Apply the changes in P2079R10 +(Parallel scheduler) to the C++ working paper.

+ +

LWG Poll 24. Apply the changes in P3557R3 +(High-Quality Sender Diagnostics with Constexpr Exceptions) to the C++ working paper.

+ +

LWG Poll 25. Apply the changes in P3560R2 +(Error Handling in Reflection) to the C++ working paper.

+ +

LWG Poll 26. Apply the changes in P3503R3 +(Make type-erased allocator use in promise and packaged_task consistent) to the C++ working paper.

+ +

LWG Poll 27. Apply the changes in P3008R6 +(Atomic floating-point min/max) to the C++ working paper.

+ +

LWG Poll 28. Apply the changes in P3111R8 +(Atomic Reduction Operations) to the C++ working paper.

+ +

LWG Poll 29. Apply the changes in P3060R3 +(Add std::views::indices(n)) to the C++ working paper.

+ +

LWG Poll 30. Apply the changes in P2319R5 +(Prevent path presentation problems) to the C++ working paper.

+ +

LWG Poll 31. Apply the changes in P3223R2 +(Making std::istream::ignore less surprising) to the C++ working paper.

+ +

LWG Poll 32. Apply the changes in P2781R9 +(std::constant_wrapper) to the C++ working paper.

+ +

LWG Poll 33. Apply the changes in P3697R1 +(Minor additions to C++26 standard library hardening) to the C++ working paper.

+ +

LWG Poll 34. Apply the changes in P3552R3 +(Add a Coroutine Task Type) to the C++ working paper.

+ +

LWG Poll 35. Apply the changes in P1317R2 +(Remove return type deduction in std::apply) to the C++ working paper.

+ +

Editorial changes

+ +

Major editorial changes

+ +

There have not been any major editorial changes.

+ +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N5008 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 2a74dc7bc587c2c64d8886faebc91d68c83626c1
+Author: Vlad Serebrennikov <serebrennikov.vladislav@gmail.com>
+Date:   Mon Mar 17 15:33:35 2025 +0400
+
+    [expr.sub] Add missing cross-references (#7688)
+
+commit cdf6502ac7bf942f6ad32a27254db890c7ae8d3a
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Mar 18 09:35:16 2025 -0400
+
+    [sequences.general] std::hive is a sequence container (#7746)
+
+commit 2a71697913a853b62b8aeda5b68afbdfca756bf2
+Author: salonsro <lucyengine@gmail.com>
+Date:   Tue Mar 18 13:37:49 2025 +0000
+
+    [defns.access] Add cross-reference (#7743)
+
+commit b3f45725c6cb088e26b02a36c51c6e19ce61351e
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Wed Mar 19 13:18:56 2025 +0100
+
+    [basic.contract.eval] Fix typo (#7749)
+
+commit 0bd8d94cc6b693cc3dd25bd32157928b6e02ac8e
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Mar 19 18:43:01 2025 +0100
+
+    [lex.digraph] Swap alternative token representations in table (#7750)
+
+commit 958532b7042b0c12af783a0a2f9e5c8fafc8702c
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Mar 21 09:22:26 2025 +0100
+
+    [hive.operations] Move closing curly bracket in front of comma (#7757)
+
+commit 719601dcb890bf2dbc2330af5846c30a2ef84830
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sun Oct 27 10:43:51 2024 +0100
+
+    [dcl.init], [depr.atomics.types.operations] Say "with static storage duration"
+
+commit 8b753114c3fe1602e04ca9d1015c14c4a54544af
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sun Oct 27 10:47:27 2024 +0100
+
+    [thread.condition.nonmember], [futures.promise], [futures.task.members] Say "with thread storage duration"
+
+commit 78bec38978bce1c680ea0a2dd2f8791967148bb8
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sun Oct 27 10:49:12 2024 +0100
+
+    [expr.prim.id.unqual], [support.start.term] Say "with automatic storage duration"
+
+commit 1dd46d8b87a1a7918d07966d7ef04c0118bee73e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Mar 21 13:02:50 2025 +0000
+
+    [tools] Catch exception of polymorphic type by reference
+
+commit 9caa0dc05cb525c433f7889e190946a325f752ed
+Author: Matthias Kretz <M.Kretz@gsi.de>
+Date:   Sat Mar 22 19:48:08 2025 +0100
+
+    [exec.schedule.from, simd.ctor] Remove incorrect @ escapes (#7759)
+
+commit 2d59c792e2a0228e77a0316d39bde9e51f31d146
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sat Mar 22 22:37:08 2025 +0100
+
+    [cpp.embed.gen] Fix typo in example
+
+commit 9b8a5e51752efe9edd7a447e96ffab0f3313accc
+Author: Eelis <github.com@contacts.eelis.net>
+Date:   Sun Mar 23 10:06:28 2025 +0100
+
+    [range.zip.transform.iterator] Fix typo in index entry. (#7762)
+
+commit 6a4c11e137509beed40ce93dd9d92b7b24e0cbda
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Mon Mar 24 08:45:47 2025 +0100
+
+    [stopsource.general] Restore accidentally deleted members in class definition (#7766)
+
+    These were removed in error in the application of P2300R10.
+
+commit d51cc9b757a0bbb343244c3aecd546783d08ba83
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Mon Mar 24 16:00:39 2025 +0800
+
+    [range.to.input.view] Add \ref for to_input_view​::​iterator (#7767)
+
+commit 879d51544872d6b8b6f0a845328db26ef5f2ddcb
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Mon Mar 24 16:01:34 2025 +0800
+
+    [range.drop.view] Fix typo (#7768)
+
+commit c4a89e3ca4e34c82f6525a342f08dab1dce63d8c
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Mon Mar 24 22:07:58 2025 +0100
+
+    [alg.rand.generate] Add generate_random to index (#7774)
+
+commit dd233b52569edc8598d575d57ee4634729228acf
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Wed Mar 26 15:26:06 2025 +0800
+
+    [simd.ctor] Fix typos (#7779)
+
+commit ae030b95169a0c828917b72085ac99427c12f0d4
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Wed Mar 26 20:16:02 2025 +0800
+
+    [range.to.input.view] Add namespace wrapping (#7782)
+
+commit 4dd513d0096900ac82090875e2568a971909b2b3
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Mar 26 20:48:23 2025 +0100
+
+    [lex.phases] Add cross-reference to [lex.header] (#7763)
+
+commit 3b4c353d381e07b4648671c592b82a1e487425d9
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Mar 27 19:51:39 2025 +0000
+
+    [temp.constr.general] Reorder constraint kinds to match subclause order (#7788)
+
+commit 5ecd4e9e00f64dfc73a75ce667bbaeba2b3b9b61
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Mar 27 20:40:32 2025 +0000
+
+    [temp.variadic] Consistently order template parameter kinds (#7796)
+
+commit 9798c7afb488414dd7e51fbc70dc9182ebafa668
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Mar 27 20:42:50 2025 +0000
+
+    [temp.deduct.type] Consistently order template argument kinds (#7798)
+
+commit 38a0bd47f42bf8c880df1a17e90110ac6a070944
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Mar 28 22:25:40 2025 +0000
+
+    [alg.copy, alg.move] Rename ExecutionPolicy parameters for consistency (#7803)
+
+    This makes them consistent with all other parallel algorithms.
+
+commit ddb98da95204fbd033e4e809e05634513187afb9
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Mar 30 17:53:53 2025 +0200
+
+    [expr.const] Add reference to [dcl.constexpr] for "constexpr destructor" (#7629)
+
+commit d40449a0e50e126a35c555683dc7805f72efa7ef
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Sun Mar 30 16:24:39 2025 +0200
+
+    [range.approximately.sized] Move to before [range.sized]
+
+    This is an unfortunate application of P2846R6.
+
+commit ab81b357785fc5a48df60cbe9a372af4f281a25b
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Sun Mar 23 18:20:35 2025 -0500
+
+    [cpp.predefined] Place the __STDC_EMBED macros in the unconditionally defined paragraph
+
+    The incoming paper did not explicitly specify their placement,
+    but they are clearly meant to be defined unconditionally.
+
+commit 06ffe74abf088e275e4233d2891cc3ebc4664cea
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Mar 31 11:28:14 2025 +0000
+
+    [temp.constr.normal] Rephrase comment in example (#7793)
+
+commit 5b6307e337d50045c3b4109429f4912fe352bce4
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Mar 27 11:26:43 2025 +0000
+
+    [temp.over.link] Remove redundant wording
+
+commit 12b6153dccd2fc2f9ec6a8469d907b47bca57963
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Mar 27 11:26:40 2025 +0000
+
+    [temp.constr.normal] Use "contains (a pack)" instead of "names"
+
+commit 24c7d63df6144f0d718acb882c2c36ec97cd6212
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Mar 31 14:09:51 2025 +0200
+
+    [set.overview] Fix punctuation (#7808)
+
+commit bf5c701a23bcc7f79a459f474455cf0dc9c58de5
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Tue Apr 1 02:28:47 2025 +0800
+
+    [list.erasure, list.erasure] Move long code into codeblock (#7809)
+
+commit 743914c23ff20286507c1c8b201dc040a6f8f178
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Apr 1 15:08:12 2025 +0000
+
+    [temp.dep.constexpr] Fix broken formatting (#7811)
+
+commit 9fd6664ea97cd889cdf529f2d020e6fa6ea13d58
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Apr 4 17:48:11 2025 +0100
+
+    [optional.monadic] Remove stray angle brackets on concept name (#7817)
+
+commit a989431c5a893f9106dc21e9b2dd0a670356d890
+Author: Geng Cheng <xmcgcg@qq.com>
+Date:   Thu Apr 10 17:32:28 2025 +0800
+
+    [polymorphic.general] Fix garbled expression (#7820)
+
+    The applied paper P3019R14 had truncated text.
+
+commit f79a0f6981def4868fc365fb906a8a0551359c7d
+Author: Geng Cheng <xmcgcg@qq.com>
+Date:   Thu Apr 10 18:40:44 2025 +0800
+
+    [polymorphic.asgn] Remove superfluous greater-than sign (#7821)
+
+commit 7f1000d2eca113824d6ac734c5348f332a2d3e1c
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Apr 11 14:10:48 2025 +0200
+
+    [func.bind.partial] Add backslash for throws
+
+commit 8792e5544498d262a821b2175c1fe52fd3a15156
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Sun Apr 13 13:33:06 2025 -0400
+
+    [meta.unary.prop] Comma should be a period (#7832)
+
+commit 317ae891f25d4875651495780b5238869cce825b
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Mon Apr 14 23:20:57 2025 +0800
+
+    [mdspan.layout.left.obs] Add missing noexcept (#7831)
+
+commit 5ec615184220e01fd8f6a817cf6050f3ce039f91
+Author: Geng Cheng <xmcgcg@qq.com>
+Date:   Mon Apr 14 23:25:37 2025 +0800
+
+    [vector.modifiers] Old concepts cannot be “modeled” (#7836)
+
+commit 08b6e70e2c469a4a2d85d5ab49b14f75d57c0d36
+Author: OndrejPopp <50676516+OndrejPopp@users.noreply.github.com>
+Date:   Mon Apr 14 17:27:34 2025 +0200
+
+    [dcl.contract.func] Add missing \br in grammar (#7838)
+
+commit 52c7080115598baddd61b050c707d2a05a5fa2f7
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Apr 22 23:37:19 2025 +0800
+
+    [iterator.synopsis] Apply changes of P2538R1 to the synopsis of `<iterator>` (#7841)
+
+    Remove `incrementable_traits<projected>` and update `projected`.
+
+commit 05300d78dc4fb6ee346d93b381d6a15ed51406f7
+Author: Tsche <2440422+Tsche@users.noreply.github.com>
+Date:   Wed Apr 23 07:21:16 2025 +0200
+
+    [tuple.syn] Fix return type of ignore-type::operator= (#7840)
+
+    This fixes a misapplication of P2968R2, in commit 225eadc4f3676472836397c9c0449f3203ae0a6d.
+
+commit a136094254936f2ae4e8bf1d5c59fff1afca03c7
+Author: A. Jiang <de34@live.cn>
+Date:   Thu May 8 02:58:03 2025 +0800
+
+    [container.adaptors] Avoid naming sorted_{equivalent,unique}_t tag parameters (#7867)
+
+commit b99e22bb3f4e27eae65028aa011d3db08a0793cf
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu May 8 20:53:45 2025 +0200
+
+    [basic.contract.eval] Remove stray closing parenthesis (#7868)
+
+commit 4b1283ba5fabb5392b0faabe9682abc43d449614
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon May 12 22:32:34 2025 +0200
+
+    [sequence.reqmts] Fix application of P2846R6 for `assign_range`
+
+commit 74a6eed8a7b12041dbdb0dd9c39c433363211894
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue May 13 19:45:22 2025 +0200
+
+    [expr.call] Move period to end end of sentence (#7871)
+
+commit e8a5d8b83a91a0606883042fa3beb3e7b4423d9c
+Author: Geng Cheng <xmcgcg@qq.com>
+Date:   Thu May 15 02:25:17 2025 +0800
+
+    [associative.reqmts.general] Replace undefined "multiple keys" with "equivalent keys" (#7874)
+
+commit 69f81d2bc71ae28694ded6f03a5a2670e916c7d8
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu May 15 08:09:59 2025 +0200
+
+    [dcl.contract.res] Add period to end of sentence
+
+commit 78ea6062c043cc640fe5e72985eb36c279b1e976
+Author: Luc Grosheintz <luc.grosheintz@gmail.com>
+Date:   Thu May 15 23:46:56 2025 +0200
+
+    [mdspan.layout.right.obs] Add missing constexpr to required_span_size (#7872)
+
+commit 6c20db7e4a3300a0274e4ba9eb8c35371d6bc276
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri May 16 15:29:51 2025 +0200
+
+    [class.prop] Remove stray closing parenthesis (#7879)
+
+commit c4a2d197bb3c52d3e84a645bb756b3606e8408fc
+Author: A. Jiang <de34@live.cn>
+Date:   Sat May 17 03:07:18 2025 +0800
+
+    [algorithm.syn] Fix synopsis entries for `ranges::find_last` (#7805)
+
+    P3217R0 updated ranges::find_last, but the synopsis was accidentally left unchanged.
+
+commit d8ab7083603ad16eb74fade44c757760b1f9e9dc
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat May 17 08:57:50 2025 +0200
+
+    [class.mem.general] Remove stray closing parenthesis (#7880)
+
+commit eb112f887bc541c5a21b302ac7d2476c7b5fa5e3
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Mon May 19 09:28:23 2025 +0200
+
+    [hive.operations] Add missing paragraph number (#7882)
+
+commit 0fd10bfb6ca13a61dd1bb77cad3b070d500e1cbc
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue May 20 13:42:28 2025 +0200
+
+    [dcl.fct.def.replace] Remove stray closing parenthesis (#7883)
+
+commit 1abf0915e3aa24ad48a1c2e74d60975a30fa93da
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri May 23 09:13:02 2025 +0200
+
+    [simd.bit] Add period to end of sentence (#7887)
+
+commit cc5b90512ac3deecfcc4e47f5da1910e54d661f9
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Wed May 28 00:18:32 2025 +0800
+
+    [locale.money.put.members] Fix typo (#7896)
+
+commit 782c81f8dfd714f34dced2de882b57d102dbde4c
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Tue May 27 18:35:39 2025 +0200
+
+    [simd.creation] Add commas and improve semantic linebreaks (#7895)
+
+commit a770261ed7dc83ea269e07f4e5936ca65337ddff
+Author: A. Jiang <de34@live.cn>
+Date:   Wed May 28 17:59:55 2025 +0800
+
+    [text.encoding.id] Sort enumerators in ascending order (#7899)
+
+commit cb25f9b182c89e442687fed176150693debc6970
+Author: A. Jiang <de34@live.cn>
+Date:   Sat May 31 04:16:52 2025 +0800
+
+    [projected] `projected` is an alias template after P2538R1 (#7901)
+
+commit b210471e21197f2e0f1655969c2adb9f04f30e02
+Author: Eric Niebler <eniebler@boost.org>
+Date:   Sun Jun 1 09:20:30 2025 -0700
+
+    [execution.syn] Rename template parameter of `schedule_result_t` (#7906)
+
+commit d18bd92fda9c02e3518910824f041ab49fbc1a4b
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Jun 2 05:47:51 2025 +0800
+
+    [tab:headers.cpp.fs] Fix header name for `is_execution_policy(_v)` (#7849)
+
+commit 25e95f5296e2b3c0f378ac5d3ddfdca1e867e9b0
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Jun 2 17:52:21 2025 +0200
+
+    [simd.unary] Add \ref for simd.unary (#7908)
+
+commit a3b9cb5bdbec5e2fbf964561ea10dc19a4b042d5
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Mon Jun 2 22:36:05 2025 +0200
+
+    [container.requirements] Simplify Returns specification for try_emplace (#7892)
+
+commit 660ab848b97640764a270220f038f911b1057dfe
+Author: Daniel Krügler <daniel.kruegler@gmail.com>
+Date:   Fri Jun 13 23:44:10 2025 +0200
+
+    [expected.object.cons] Reorder arguments of is_same_v for consistency (#7915)
+
+commit ee9b5bf124495f1473e246f223756a164d42aed9
+Author: Hubert Tong <hubert.reinterpretcast@gmail.com>
+Date:   Sat Jun 14 02:32:38 2025 -0400
+
+    [meta.trans.other] Fix off-by-one references to [meta.rqmts] (#7914)
+
+commit 57e185f4bde5309d98e22f514d4434a1feea1911
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Mar 24 00:24:04 2025 +0800
+
+    [assertions.assert] Add ISO C reference for standard error stream
+
+commit 4f3e967cdc0befd71b1101e996c22db602ff0fd3
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat May 3 10:25:33 2025 +0200
+
+    [class.temporary] Define "temporary object"
+
+commit 4aa14fe19a9060360436e9ab56d361101212e961
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu May 1 15:56:42 2025 +0100
+
+    [polymorphic.ctor] Owned object must have cv-unqualified object type
+
+commit 6f18c6b9e3634cf2ac40ab0f4d7c9e2e68acee2c
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Mon Jun 16 08:42:48 2025 -0700
+
+    [value.error.codes] Remove redundant std qualifications (#7918)
+
+commit 59b1a8ada534fb1491ef3a134e05262baa0b516c
+Author: Eric Niebler <eniebler@boost.org>
+Date:   Tue Jun 17 05:56:42 2025 -0700
+
+    [exec.snd] Fix spelling of exposition-only `query-with-default` function (#7905)
+
+commit 04f4a62af51c7b3e8dad223051dc95a7942194c3
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Mon Jun 2 22:54:34 2025 +0200
+
+    [basic.def.odr] Rephrase sentence to avoid double-negative
+
+commit ca3694ecf8fd82d896d5bcf011bae7640d5335de
+Author: Eric Niebler <eniebler@boost.org>
+Date:   Tue Jun 17 06:04:08 2025 -0700
+
+    [exec.let] Fix function type name (#7907)
+
+    The specification of `let_value(sndr,fn)` and friends refers to the type of `fn` as "`Fn`". But when introducing the types, we give it the name "`F`". This fixes the inconsistency.
+
+commit dfcc6dd19c0efd93bff47d501fdf6e2d52160a5c
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Mar 27 11:34:57 2025 +0000
+
+    [expr.type] Remove redundant \cvqual
+
+commit 9d20a320e1662deff9abb65b4f7e6e52e66ed732
+Author: Geng Cheng <xmcgcg@qq.com>
+Date:   Tue Jun 17 21:51:41 2025 +0800
+
+    [indirect.asgn] Change "contained value" to "owned object" (#7822)
+
+commit 06e649b10e2d1af29eee739ea0998cb45e65fadc
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Apr 8 17:19:29 2025 +0800
+
+    [string.view] Exposition-only formatting for `data_` and `size_`
+
+commit 9dfb02a3222eed8a02d74c7d80714eeaf3aba10b
+Author: Geng Cheng <xmcgcg@qq.com>
+Date:   Tue Jun 17 21:59:52 2025 +0800
+
+    [time.format] Add commas and clarifying "unless otherwise" (#7697)
+
+    See LWG 4124, which added wording before the text in question that motivates adding "unless otherwise specified".
+
+commit 1f79f7a919432e8eccc90c9ffd21baeb9ea0563c
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Apr 24 15:08:28 2025 +0800
+
+    [exec.util.cmplsig.trans] Drop verbose `add_lvalue_reference_t`
+
+commit 32ec75ea890301b100eac4a63e986a55cd08ea13
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jun 17 17:07:41 2025 +0300
+
+    [indirect, polymorphic] Rename stable lables "asgn" to "assign"
+
+commit da436f8325d978b76eaa18be46e987decc9117c5
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Jun 18 00:47:57 2025 +0800
+
+    [defns.dynamic.type] Say "most derived object" in the example (#6203)
+
+commit 66e15a609b8bec7b4b976b17a5aaf3d65893d31c
+Author: languagelawyer <38548419+languagelawyer@users.noreply.github.com>
+Date:   Tue Jun 17 21:48:26 2025 +0500
+
+    [intro.multithread.general] Say "use", not "access" functions (#6503)
+
+commit 7a90fddca19918e03bc10a7a6ef22a970ca381a3
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Jun 18 22:13:59 2025 +0800
+
+    [tab:meta.trans.cv] Simplify wording for add_{const,volatile}
+
+    Wording about reference, function, or top-level cv-qualified types
+    moves to notes, as it is redundant since at least C++11.
+
+commit c156822435acd59433b7fb7f28e83a5765af7e64
+Author: A. Jiang <de34@live.cn>
+Date:   Sun Sep 29 09:11:10 2024 +0800
+
+    [complex.numbers.general] Clarify that the template is primary
+
+    The difference between between "the `complex` template" and "the template named `complex`" (which including program-defined specializations) is obscure. It seems better to cleary say that [complex.numbers.general] only covers the primary template.
+
+commit f457f12ffe04df1af8e6a28e174a5ca2dc59ddaa
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Jun 19 17:32:03 2025 +0800
+
+    [execpol.type] Remove "see below" definition from "is_execution_policy" itemdecl (#7909)
+
+    We already say that it is a Cpp17UnaryTypeTrait with a base characteristic of either true_type or false_type.
+
+commit 446ec2e959f38281786c3f61e83f077459763f92
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Fri Jun 20 02:19:07 2025 -0400
+
+    [inplace.vector] Move reserve, shrink_to_fit from "modifiers" to "capacity" (#7321)
+
+commit c355072152d7c9e364e2a8acf265fdf068942002
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Jun 20 07:50:59 2025 +0200
+
+    [valarray.cassign] Add period at end of "Returns"
+
+commit 3bce8f7f15164dc455240e53acce596eeba97d45
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Fri Jun 20 08:01:43 2025 +0100
+
+    [diff.cpp23.strings] Move Clause 27 changes after Clause 23 changes
+
+    The 'Strings' clause was moved before the new 'Text processing' clause,
+    so it's now after the 'Containers' clause. The order of the [diff.cpp23]
+    subclauses should reflect that.
+
+commit ac78ae76c579883a32a9eb5b00346150a41e8e47
+Author: timsong-cpp <rs2740@gmail.com>
+Date:   Fri Jun 20 21:02:18 2025 +0100
+
+    [atomics.ref.float] Fix spelling of placeholder
+
+commit a8f807b14c33ca76c790df97ca7d0ddf9746abef
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sun Jun 22 09:12:52 2025 +0200
+
+    [out.ptr] Add period at end of "Returns"
+
+commit 346c6d0dfd608764d697f1a33ef739a4762e0d40
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sat Mar 11 20:53:05 2023 +0000
+
+    [conv.qual] Remove unused definition of 'cv-qualification signature'
+
+commit 0b41c12760d8079ee4c460df6ddecaf220f2dfb6
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Jun 22 19:59:47 2025 +0300
+
+    [intro] Special page header before Clause 1 (#6070)
+
+commit 4726d67bf8f22f15dd7f3dcae7b54832dcbbbb91
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Sun Jun 22 17:27:15 2025 +0000
+
+    [dcl.type.auto.deduct] Change "occurrences" to "occurrence" (#7644)
+
+    This appears to be a misapplication of N1984, which contains the wording "Obtain `P` from `T`
+    by replacing the occurrence of `auto` with a new invented type template parameter `U`."
+
+commit a8d96185e4bba7f738e4c2e1f3593a6e55fbbbd8
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Jun 23 08:07:06 2025 +0200
+
+    [basic.ios.members] Add period at end of "Returns"
+
+commit 2e12f5e71e56af0ffae0b5a7cd9086d24b72df20
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jun 23 12:48:46 2025 +0100
+
+    [stmt] Move start of subclause-spanning index entries up to \rSec1
+
+    I expect that we forgot to move this when we added the "general"
+    subclauses to remove hanging paragraphs, and thus accidentally caused
+    the index entries to be "misnested".
+
+commit 4f925714c37ed1fe6a5692adcc3ef5fa37964056
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Jun 26 13:25:36 2025 +0200
+
+    [atomics.ref.float] Apply missing changes from P3323R1
+
+    Paper P3323R1 cv-qualified types in atomic and atomic_ref
+    was incompletely applied in commit cd4dbcf2aa6df895a25dbf8c0773dd0fa67ef45d.
+
+commit f9100076b21e277644a793624db7dc96bff29594
+Author: Matthias Kretz <M.Kretz@gsi.de>
+Date:   Fri Jun 27 13:11:39 2025 +0200
+
+    [simd.expos.defn] Fix missing paragraph break (#8028)
+
+commit abe616528d5ff19d25983af7497bcedf0b3d44bb
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Jun 27 13:12:54 2025 +0200
+
+    [iostate.flags] Add period at end of "Returns" (#8026)
+
+Author: Andrew Rogers <32688592+adr26@users.noreply.github.com>
+Date:   Sun Jun 29 11:20:31 2025 +0100
+
+    [container.insert.return] Fix description of insert-return-type (#8030)
+
+    Use the usual phrasing "X is for exposition only" when X is an exposition-only construct.
+
+commit be34ebfac39484ff96f68b46c2418b6fc49c66f4
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Wed Jul 2 07:58:52 2025 +0200
+
+    [istream.unformatted] Add period at end of "Returns"
+
+commit f6cd0dcbd082cfd85f87addec007680949cb1de9
+Author: Hewill Kang <hewillk@gmail.com>
+Date:   Fri Jul 4 04:27:11 2025 +0800
+
+    [range.join.iterator] Remove spurious return (#8038)
+
+commit 6f2e658a6c5ceaf577480d656bda0417fc98cc1d
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Sat Jul 5 08:42:54 2025 +0200
+
+    [mem.poly.allocator.mem] Fix typo
+
+commit ce78eced98e3e4dfe99eb409398267e5f00126aa
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Wed Jun 25 12:35:16 2025 +0200
+
+    [std,check] Ensure proper placement of \iref
+
+commit ff592bd14ff3abecff33669bda91b658bf9f1023
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 15 09:15:08 2025 +0100
+
+    [diff.cpp23.lex] Fix capitalisation in heading
+
+commit 00102f1c03f81c6004d4d14e50f45e7084eafed0
+Author: Hana Dusíková <hanicka@hanicka.net>
+Date:   Mon Jul 14 11:50:06 2025 +0200
+
+    [container] unify to `friend constexpr` (there were few `constexpr friend`)
+
+commit 502465fc1b2676d1cf2e8565942f6d0446fc6d14
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Jul 14 19:46:00 2025 +0200
+
+    [meta.syn] Fix typo
+
+commit c4c5bddac9e7e294c2685e5ae0d294b01d2b1572
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Jul 14 20:11:49 2025 +0200
+
+    [meta.reflection.member.queries] Fix typos
+
+commit d3aaeb9da74e029199a3c4fb2c125e3fa8a6273c
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Jul 14 19:59:51 2025 +0200
+
+    [meta.reflection.queries] Fix typos
+
+commit 9797d6936ddbb39b89fbfa31ab0bf57c213f8476
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Jul 14 20:26:21 2025 +0200
+
+    [meta.reflection.traits] Fix typos
+
+commit a295d0ed2ebb68e3930d208ec5958efd51c6b225
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Wed Jul 16 20:23:54 2025 +0200
+
+    [meta.reflection.exception] Fix typo
+
+commit 08e1d9e30210983b2745ebff9b1002ecbf235bbd
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Jul 14 20:42:53 2025 +0200
+
+    [meta.reflection.define.aggregate] Fix typos
+
+commit eb0529b7154823f39f1c86ffdfdc1f7f3bcebfaa
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Jul 15 08:48:12 2025 +0200
+
+    [meta.reflection.queries] Fix typo
+
+commit 51904cdf92ea7a8eb5f7f60cfe65233429d9c365
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Jul 14 22:13:57 2025 +0200
+
+    [meta.reflection.queries] Add period to end of sentence
+
+commit d25f7d0b0449ffa3d89a4a3270dba8af2fd88719
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Jul 15 11:19:45 2025 +0200
+
+    [optional.ref.ctor] Fix punctuation
+
+commit 916d4f4d78509dced64f02c2616261b588c16941
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Mon Jul 14 21:55:02 2025 +0200
+
+    [over.call.func] Add period to end of sentence
+
+commit 7ca1adbf7367735b3657830798132b2fe2539cf7
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Jul 17 15:03:01 2025 +0200
+
+    [alg.partitions] Replace non-existent concept "copy_assignable" concept with "copyable"
+
+commit 5047d04a825a7fc72381ba5596da8c6062f65107
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Tue Jul 15 22:59:04 2025 +0200
+
+    [alg.copy] Add period to end of sentence
+
+commit a5b2951c975588df8652ebc779784cbc84267c22
+Author: Luc Grosheintz <luc.grosheintz@gmail.com>
+Date:   Wed Jun 25 07:19:40 2025 +0200
+
+    [mdspan.layout.leftpad.cons] Add \expected.
+
+    The description of
+
+        template<class LayoutLeftPaddedMapping>
+          constexpr explicit(see below )
+            mapping(const LayoutLeftPaddedMapping& other);
+
+    didn't separate Mandates and Preconditions. This commit adds an
+    \expects to separate the two.
+
+commit e5a30fec15d4a9e6f4425edcf3c6898cc67fe0a3
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Thu Jul 3 12:04:48 2025 +0000
+
+    [temp.constr.concept] Fix example
+
+    * Give all template parameters a unique name for clarity
+    * Replace use a of a reserved identifier
+    * Fix the example's accompanying text, in particular the parameter
+      mapping of the normal form of the concept-id after substitution
+
+commit 103dddccf3a965899c4bcaedab98154792573f24
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Jul 17 15:21:44 2025 +0200
+
+    [exec.task.scheduler] Fix typo
+
+commit 2974816e0b56f79c169f7eee3b24572e0092cd35
+Author: Daniel M. Katz <katzdm@gmail.com>
+Date:   Thu Jul 17 09:39:07 2025 -0400
+
+    [meta.reflection.access.context] Fix typo
+
+commit bd2412ce3b94f7ae3bf9c9e78a97e31181e7c01d
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Thu Jul 17 15:15:16 2025 +0200
+
+    [exec.affine.on, task.promise] Fix typos
+
+commit 1acddcece95e2d7c83db3d8aee89fd4d4689fcd3
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Jul 15 05:05:03 2025 -0400
+
+    [lex.separate] Remove last reference to instantation units
+
+    The term instantiation unit was removed by the reflection paper, P2996.
+
+commit 42e68bf40e4ab7fc8b4a102f6c1d0ba4f6b63faa
+Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com>
+Date:   Fri Jul 18 09:12:16 2025 +0200
+
+    [task.promise] Move period to end of sentence
+
+commit c76496316acc434ac06e23191b45b0c228f7331f
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Fri Jul 18 13:09:41 2025 +0200
+
+    [simd.syn] Fix capitalization and code fonts in synopsis comments; reflow declarations (#8093)
+
+commit cdffb3687e537d19197fc9bd24dca0e63ae6c744
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sat Jul 19 06:02:19 2025 -0400
+
+    [cpp.error] Recommended practice should start it own paragraph
+
+commit ad971231094740ae637c70c468c6e96f3a98a5d3
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Jul 20 00:24:52 2025 +0100
+
+    [expr.const] Improve punctuation in list items.
+
+    Striking "and" was a missed edit from P2996R13.
+
+commit 67a20d351cd370def6dede93e1c3703de4b32b70
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Jul 20 01:46:41 2025 +0100
+
+    [temp.res.commit] Add introduction of definition of "type-only context".
+
+    This avoids having to style either of the two subsequent
+    sub-definitions as the main definition.
+
+commit c07c130af2014ee374be9754e9aeba43e564c614
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Jul 20 02:00:56 2025 +0100
+
+    [temp.dep.type] Fix list item continuation after recent addition.
+
+    This edit was missed in the application of P2996R13. The deletion of
+    the original "or" was not indicated in the paper (but is clearly
+    necessary).
+
+commit 0efc6648509b380573345101037eac96f1320645
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 18:07:37 2025 +0100
+
+    [tab:meta.unary.cat] "is_reflection": add xref to [basic.fundamental]
+
+commit 7ceef7e16c3314b178122762184d3d142262de00
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 18:13:32 2025 +0100
+
+    [meta.{syn, reflection.traits}] Rename "swappable_with_type" parameters to type1, type2.
+
+    These functions are symmetric and don't have a "src" and "dst".
+
+commit 12ad8bcaa490d7851cb2ffaff8ac219cd746e039
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 18:22:28 2025 +0100
+
+    [meta.syn] Add missing paragraph 4.
+
+    This was omitted in the application of P2996R13 by accident.
+
+commit 746811a19a222ffb5e9d03008d752bcb10967ce3
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 18:27:25 2025 +0100
+
+    [tab:meta.reflection.operators] Fix some operator spellings
+
+commit 6b71747fdd3f38e20ef4bb4257aae64c0f1ec147
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 18:34:11 2025 +0100
+
+    [meta.reflection.names] "below" is "above"
+
+commit 2567873ea47b7f888f45aa4e8264c9cd3310183d
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 18:41:04 2025 +0100
+
+    [meta.reflection.queries] Add missing paragraph in is_{const,volatile}.
+
+    This was omitted in the application of P2996R13 by accident.
+
+commit cbc4a1fb6853656f43c962a68396160e07663166
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 18:46:40 2025 +0100
+
+    [meta.reflection.queries] Add missing comma in "function, type".
+
+    This seems to have been a mistake during application of P2996R13.
+
+commit c27dd93b5aee5e3936f56cdf886b2a8f6af77ac5
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 18:50:57 2025 +0100
+
+    [meta.reflection.queries] Add missing "operator function template".
+
+    This seems to have been a mistake during application of P2996R13.
+
+commit b679e4be282c9303dfb41522e16cfe22931b37a0
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 21:45:55 2025 +0100
+
+    [meta.reflection.queries] Add missing "Constant When" element of "dealias", converted to "Throws".
+
+    This seems to have been omitted during application of P2996R13 by
+    accident.
+
+commit 0ff0e096921ad25c9133b27ac30d727d0bfd5bc1
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 21:30:11 2025 +0100
+
+    [meta.reflection.queries] Fix example
+
+    This seems to have been a mistake during application of P2996R13.
+
+commit 4021cdb12a314b8c3953feb5841342a4ff2b8993
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 21:33:06 2025 +0100
+
+    [meta.reflection.access.context] Fix typos
+
+commit 42a93030c64a87610aa0abb09290a0a11f563c96
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 21:53:08 2025 +0100
+
+    [meta.reflection.member.queries] Fixed font, typo
+
+commit bd0dee79f341012c8b4f12cff8235d874251f45b
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 22:10:38 2025 +0100
+
+    [meta.reflection.layout] Delete unintended "value".
+
+    This seems to have been copy-pasted erroneously.
+
+commit 7488f055b98b56bfe598bbd2dd46a4eae4e8171a
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 21 22:34:53 2025 +0100
+
+    [expr.ref] Delete extraneous "the".
+
+    Accidentally misapplied from P3293R3.
+
+commit e546fb55893220e63e79a7db777c6af9598dce27
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 22 10:48:03 2025 +0100
+
+    [expr.ref] Add "Otherwise, " to beginning of list items.
+
+    This was requested by P2996R13, but seems to have been missed.
+
+    This edit also covers the new item added by P3293R3.
+
+commit 5a191509d702a6e53947493ac4bc119c6a935c49
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 22 13:18:13 2025 +0100
+
+    [stmt.expand] Add comma before "or" to list item
+
+commit 580a5f6d378f17067749166ca68b2a04c9fdc2de
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Wed Dec 25 16:38:25 2024 +0000
+
+    [temp.deduct.call] Add missing words
+
+commit f8e0a6539254574f7984ff6a8afa1d61daab20c0
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Fri Jul 18 18:37:20 2025 -0400
+
+    [lex.separate] Redistribute second comment
+
+    The second comment in [lex.separate] is both too specific, and not specific
+    enough.  Move the last sentence about use of separately translated TUs to
+    the end of the first note, where it seems most appropriate.  Move the rest
+    to just after the definition of translation unit in phase 7 of translation.
+
+commit 3ce793a1a76e6c1b0ec599ab2d7d1696726c2253
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 22 13:24:01 2025 +0100
+
+    [lex.pptoken] Reorder list items to avoid "or" and "and" at same level
+
+commit 7e6519ecfeffe06254c088259f4e83d36bbd20bd
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 25 00:22:44 2025 +0100
+
+    [meta.reflection.layout] Spell variable "T", not "TR".
+
+    It's unclear whether this was just a typo or an attempt to avoid
+    ambiguity, but there does not seem to be a risk of confusion, and the
+    spelling of the paper ("T") seems fine.
+
+commit 454ba171cb14531639e641cb1200617fbf8d943f
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 25 14:31:22 2025 +0100
+
+    [meta.reflection.queries] Delete mistaken "Throws:" element.
+
+    This was added accidentally in
+    b679e4be282c9303dfb41522e16cfe22931b37a0 because I misread the paper.
+
+commit 0922eeef80ee7f80e3edca688686e771a2d510bb
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 25 15:08:25 2025 +0100
+
+    [meta.reflection.extract] Fix typo
+
+commit 5396d899f281c99ee1d9df4ab7eca68d4acfa810
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 25 15:13:58 2025 +0100
+
+    [meta.reflection.extract] Fix mistaken "C" that should be "X C::*".
+
+    This seems to have been a mistake during application of P2996R13.
+
+commit c9e7524ce95bd5e0e659419d7ea3137c7cf464e4
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 25 15:31:37 2025 +0100
+
+    [meta.reflection.result] Reorder and reword paragraphs for clarity.
+
+    After the "Constant When" => "Throws" reordering, the definition of
+    the invented variable TCls had moved far from where it was being
+    referenced. This reordering moves it closer, adds a "defined below",
+    and moves the example to the end.
+
+commit d64e4580f78350b635d403602e5064d96979fa55
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 25 15:37:25 2025 +0100
+
+    [meta.reflection.result] Fix "variable" => "template"
+
+    This seems to have been a mistake during application of P2996R13.
+
+commit b36bff07d7f810295e448f7b23f898d2966f5583
+Author: Matthias Kretz <m.kretz@gsi.de>
+Date:   Fri Jul 25 16:39:30 2025 +0200
+
+    [simd.mask.overview] Fix markup; add two missing closing @
+
+commit f5d3c63e7ffa2a7ba1811ab5f2202131379690f8
+Author: A. Jiang <de34@live.cn>
+Date:   Fri Jul 25 23:55:42 2025 +0800
+
+    [xrefdelta] Fix typo in the entry for [re.def] (#8112)
+
+    The contents were moved to [intro.defs], not [intro.refs]. The latter is a typo.
+
+commit 27370ee1e0794bdd2b63c816860ed9c607bddc2a
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 25 17:42:27 2025 +0100
+
+    [meta.reflection.define.aggregate] Fix note text and !=/==.
+
+    This seems to have been a mistake during application of P2996R13.
+
+commit 23e63d82a502b483781fc15eb7108d9ed86e16d0
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 25 17:44:36 2025 +0100
+
+    [meta.reflection.define.aggregate] Fix typo ("C" should be "D").
+
+    This seems to have been a mistake during application of P2996R13.
+
+commit 1947b90539c268192d6e461208b6b278b3577ec9
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Jul 25 17:45:46 2025 +0100
+
+    [meta.reflection.define.aggregate] Fix typos
+
+commit 540773996f700115662dedbf4f315fb7b5c5e947
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sun Mar 3 13:47:13 2024 +0100
+
+    [handler.functions] Replace 'shall synchronize with' with 'synchronizes with'
+
+commit a75a8de957bc727e29a997f8e447b8b5e6d604ac
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sun Mar 3 13:49:42 2024 +0100
+
+    [mem.res.global] Replace 'shall synchronize with'; add reference
+
+commit 416219e1bc003e9aaacfbcf5507b7111d3862e9e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Jul 26 00:38:50 2025 +0100
+
+    [tab:meta.reflection.traits] Fix some table entries
+
+commit 150caecf30a1ee455a02310a75d58224821e0220
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Jul 26 01:02:09 2025 +0100
+
+    [tab:meta.reflection.traits] Use subscripts for maths T_1, T_2
+
+commit c6dfde71726d3ac6c14e9c9075aa4037245c40d4
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Jul 26 01:02:52 2025 +0100
+
+    [meta.reflection.traits] Use maths variables consistently
+
+    Also removes a comma that should not have been added.
+
+commit 6ef473941e8541c06bde7fda78a58bb7a2ac5d4a
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Jul 26 01:08:28 2025 +0100
+
+    [meta.reflection.array] Mended minor mistranscriptions
+
+commit a1283d5704724f202273f9bd5b3311b8e1a1af4a
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Jul 26 01:18:26 2025 +0100
+
+    [meta.reflection.queries] Add missing word "unless"
+
+commit 4e6d501c8cf6735b67005124e3eac23907d7222e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Jul 26 01:57:05 2025 +0100
+
+    [meta.reflection.layout] Fix wording of alignment_of.
+
+    The original transcription used some older wording that was not in the
+    most recent (approved) revision of paper (P2996R13).
+
+commit 1e931b0137e3c63977ddf1d98ae43a327b408003
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Jul 26 11:00:47 2025 +0100
+
+    [meta.reflection.queries] Add missing words "function or".
+
+    Those were accidentally omitted in the application of P3096R12.
+
+commit 14c0cdd94516cbea2dd088cdd971a98564591c89
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Jul 26 11:20:12 2025 +0100
+
+    [cfloat.syn] Fix macro definition to be long, not int.
+
+    This was a misapplication of P3348R4.
+    Checked that the C standard also uses long.
+
+commit 9e75be6a40e9fd6dfb3a7683553d1764b1a99c41
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sat Jul 26 11:25:01 2025 +0100
+
+    [cstdio.syn, cwctype.syn] Fix cross references to C
+
+commit b74580a2faf2e71591e13ad7e1e4671d1c8b640d
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Sun Jul 27 01:47:13 2025 +0200
+
+    [linalg.conj.conjugatedaccessor] Fix incorrect return type of nested_accessor() (#8105)
+
+commit 4eb527d7c35e309391b2d92019410c83a2ed9993
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Sun Jul 27 11:02:53 2025 -0400
+
+    [basic.link] All names have linkage
+
+    Given that the last option is "no linkage", the list is exhaustive
+    and should not open readers to questioning what other options
+    might be available if a name merely "can have" linkage.
+
+commit a8d02a9d5da364d3f47f39ba809ac486d4693897
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Jul 27 01:03:21 2025 +0100
+
+    [exec.snd.expos] Remove itemdecl "write-env".
+
+    An omission in the application of P3284R4.
+
+commit 3dcc932d3b28717f5995f26afe9eb851258cf58c
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Jul 27 23:43:31 2025 +0100
+
+    [algorithm.syn] Fixed transcription errors in various types
+
+commit 48e73b8d1260317ed0518454f9dbb573aab41a66
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Jul 27 23:52:10 2025 +0100
+
+    [alg.contains] Use codeblock for long return expression
+
+commit b7d39b2974d4861153b2d60dda56fe6c87c5f206
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Jul 27 23:53:30 2025 +0100
+
+    [alg.foreach] Delete mistaken Complexity: element on for_each_n
+
+    This was presumably added via accidental copy-paste in the application
+    of P3179R9.
+
+commit ec837bba81851453902a23f7410faf32ebfd3eda
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Jul 27 23:58:39 2025 +0100
+
+    [alg.searc] Fixed transcription error in template head
+
+commit 4d7eb66ddbd76312d213efad7f997b87ad11a299
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 00:01:53 2025 +0100
+
+    [alg.ends.with] Fixed transcription error in defns of N1 and N2
+
+commit c2e12a963104a77acb7ac0f8573e6116cbb28e92
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 10:40:42 2025 +0100
+
+    [alg.copy] Add missing words.
+
+    Those were accidentally omitted in the application of P3179R9.
+
+commit d764e4f90540d65d5dac01e62ac6ddac81118fda
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 10:44:34 2025 +0100
+
+    [alg.replace] Fixed transcription error in template head
+
+commit e99cd72eca0e0906464506105cc531ad199ed240
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 12:42:02 2025 +0100
+
+    [alg.rotate] Move declaration to the correct itemdecl.
+
+    This was a mistake in the application of P3179R9.
+
+commit d2ed4f73fcdf7af6d8a8207388793ea34e3fa5f2
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 12:49:22 2025 +0100
+
+    [alg.partitions] Fixed some transcription errors
+
+commit 65fe94b7dbf63727cf3633bdc663f90c56bad031
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 13:39:30 2025 +0100
+
+    [alg.merge] Make "E(e1, e2)" explicitly depend on "e1", "e2".
+
+commit 7b25ed6c5f5bb58739b9f0902b4ab3b8a54ca1f4
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 13:41:56 2025 +0100
+
+    [set.{union,intersection,difference}] Add missing "of".
+
+    This was mistakenly omitted in the application of P3179R9.
+
+commit 338e6b4647d5ecd42e09e3585213181897982602
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 13:46:21 2025 +0100
+
+    [set.intersection] Fixed transcription errors in return types.
+
+    Declaration error corresponds to 3dcc932d3b28717f5995f26afe9eb851258cf58c.
+
+    The errors in the Returns: follow.
+
+commit 2d72d926277e2e9abb7caec2a0b8018a98bb99e6
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 14:00:09 2025 +0100
+
+    [algorithm] Remove unnecessary linebreaks for "requires mergeable"
+
+commit 8421019c09a46f2a76070131bb9b8dbac4e5b962
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 14:00:46 2025 +0100
+
+    [memory.syn] Delete unintended synopsis entry for "destroy_at".
+
+    This seems to have been a mistake in applying P3179R9.
+
+commit b5d77f4458e8ed83dd0968c54651c23c4cb0f68a
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 14:39:12 2025 +0100
+
+    [exec.await.as] Delete stray "}"
+
+    Left over from transforming \tcode into codeblock.
+
+commit d91106b48d6b8453694a64bce5a0ef84306b82bf
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 15:04:45 2025 +0100
+
+    [exec.par.scheduler] Fix extent of definitions
+
+    As per P2079R10.
+
+commit b9a314f2d8cac8e1df5f2f828b223faaa413f4ab
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 15:08:11 2025 +0100
+
+    [exec.snd.expos] Fix typo
+
+commit 791ff12c615275f6eb1bd5ccaf0f58a2d0f54031
+Author: Giuseppe D'Angelo <dangelog@users.noreply.github.com>
+Date:   Mon Jul 28 22:14:31 2025 +0200
+
+    [expr.unary.op] Add a note about dereferencing a dangling pointer (#8130)
+
+    Dereferencing a dangling pointer to an object is valid; the resulting
+    lvalue can be used in limited ways as per [basic.life] p8.
+
+    Add a non-normative note linking the two sections.
+
+commit 4e79eb8816aa34b19efcdaeef416ed9850127658
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 22:26:28 2025 +0100
+
+    [exec.schedule.from] Fix placement of declaration of "check-types"
+
+    A misapplication of P3557R3.
+
+commit 511eaa16f93680875878ea7bc74a6c2172237832
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 22:29:12 2025 +0100
+
+    [exec.sync.wait.var] Fix wording
+
+    A misapplication of P3557R3.
+
+commit 9e25d17d0c62cad16531dd752df75e46552412f5
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 22:33:05 2025 +0100
+
+    [meta.reflection.exception] Fix spelling of "u8what"
+
+    A misapplication of P3560R2.
+
+commit 8e05e24e431b4706f2ad3e49731ab0b8d7a52459
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 22:36:58 2025 +0100
+
+    [meta.reflection.traits] Missed edit
+
+    A misapplication of P3560R2.
+
+commit 09a9a4174a1c2fada5e8af38eaa78deaeac9e9cd
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 22:45:18 2025 +0100
+
+    [meta.reflection.layout] Turn "Throws:" element into an "all of the following are required" list.
+
+    This restores the meaning of the multiple sentences, which had become
+    unclear after the "Constant When"-to-"Throws" change.
+
+commit 884d39bd3539dc837d4869144d677697b7247191
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 23:37:01 2025 +0100
+
+    [future.syn] Remove uses_allocator also from header synopsis.
+
+    P3503R3 didn't actually say this, but it is clearly necessary.
+
+commit 38ffbee80ca5a0bf5f83cb134697429797d87d9c
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Jul 28 23:39:37 2025 +0100
+
+    [atomics.ref.float] Fix typo
+
+commit fc6df2dbba6ac42837e42c6ce0ea53cd55ac0e2a
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 29 00:42:00 2025 +0100
+
+    [macros] Add "see above" macros
+
+commit aaeb987ed4bd09d5d992b20f814f206d63d1c022
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 29 00:42:40 2025 +0100
+
+    [atomics.types.pointer] Fix parameter type (should be "see above")
+
+    A misapplication of P3111R8.
+
+commit 102de3e47d27e47421aefc030a8d7facb0568324
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 29 00:47:08 2025 +0100
+
+    [fs.path.{generic,native}.obs] Escape braces
+
+commit 0c75091a4a5589455c9d18108b8de56c97336985
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 29 00:52:40 2025 +0100
+
+    [version.syn] Add missing "freestanding" to feature-test macro
+
+    A misapplication of P2781R9.
+
+commit d299950f8d2f55f6cde7c43c22eeb3109ff1704c
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 29 00:57:04 2025 +0100
+
+    [meta.rel] Move new paragraph to the correct subclause
+
+    A misapplication of P1317R2.
+
+commit df1f3f31d8a5f43ec4cfc235753ddceb4e26353f
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Jul 29 12:06:27 2025 +0100
+
+    [task.members] Change template parameter name from "R" to "Rcvr".
+
+    This makes it the same as in the header synopsis.
+
+commit ce7cc9c4b02476489bbfebcd9d9037ccc79e0125
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Jul 30 15:18:25 2025 +0100
+
+    [task.state] Fix misplaced \end{itemize}
+
+commit 77ca407d56faafd591638b11102f33ba1b12aec8
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Jul 30 15:41:55 2025 +0100
+
+    [basic.splice] The template argument is a parenthesized expression
+
+commit e15c0955b8c8b129000bc99d848fc54eeb82f74f
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Jul 30 15:33:56 2025 +0100
+
+    [task.promise] Fixes and clarifications in "operator new" spec
+
+    * Change erroneous "Allocator" to "allocator_type". This was
+      a mistake in the paper (a leftover from a previous revision).
+    * Locally defined variables are just typeset as normal code,
+      not as placeholders.
+    * Some commas inserted to separate coordinate subclauses.
+    * Replaced "(if any)" with leading "Oherwise", which seems better
+      in order to avoid seemingly providing two conflicting definitions
+      of alloc.
+    * Replaced "Then PAlloc is ..." with "Let PAlloc be ...", which
+      replaces the (causal vs temporal) ambiguous "then" with the
+      far more common "let" expression.
+
+commit e4a7f6da57891013ed378672c470970d95ea190e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Jul 31 15:13:38 2025 +0100
+
+    [basic.fundamental] Delete repeated cross reference.
+
+    We don't seem to make any cross reference more than once per
+    subclause. We can revisit this policy, but for now the change
+    makes the text more consistent in this regard.
+
+commit 718777332db5157c39cbab50148eeb56a02330f3
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Aug 1 11:11:24 2025 +0100
+
+    [expr.reflect] Better cross-reference (for "namespace")
+
+commit c521311f5d61d8558a9c141f7a481196299833a4
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Aug 1 11:13:48 2025 +0100
+
+    [expr.reflect] Move text out of list item to intended position.
+
+    A mistake in the application of P2996R13.
+
+commit 5d29e6ddde83dcaebb69e5a215d8956dc399f0d7
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Aug 1 11:24:47 2025 +0100
+
+    [dcl.typedef] Fix: change semicolon to full stop.
+
+    A miss-edit in the application of P2996R13.
+
+commit b58eef6e11ff142d083979d6a652d56ab20d4ec1
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Aug 1 11:28:15 2025 +0100
+
+    [dcl.fct] Fix list continuation.
+
+    A miss-edit in the application of P2996R13.
+
+commit 6f718357e72f5f5e78dd2f212e66f5b0064a179d
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Fri Aug 1 11:45:52 2025 +0100
+
+    [dcl.init.general] Insert comma before "or array thereof".
+
+    The comma improves the clarity of the binding of "or array thereof",
+    and was shown in P2996R13, but apparently mistakenly so; it did not
+    exist in the prior wording. But it is clearly important.
+
+commit d2654b6dcf8b30a0546d7afb411cd79c66129a24
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Aug 4 10:21:31 2025 +0100
+
+    [alg.transform] Fix comma that should be a full stop.
+
+commit 6f496bf27bfdf5e48da3cc288c1c538ab993131e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Aug 4 10:44:07 2025 +0100
+
+    [alg.partition] Fix "true" that should be "false".
+
+    A misapplication of P3179R9.
+
+commit 91b4bf8f7a1fb15010b348f3e1552491e01eb396
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Aug 4 10:49:20 2025 +0100
+
+    [alg.merge] Fix some misapplications of P3179R9.
+
+commit 8ff31fafa7a3ec0d9ecc991cb3a98ce2abdd9574
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Aug 5 10:26:58 2025 +0100
+
+    [memory.syn] Fixed misspelled "nothrow-sized-sentinel-for".
+
+    This was a misapplication of P3179R9.
+
+commit e534fb2676e191b4396184abd81e9882f4437e7c
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Aug 5 10:30:31 2025 +0100
+
+    [special.mem.concepts] Fixed misspelled "sized_sentinel_for".
+
+    This was a misapplication of P3179R9.
+
+commit c4dd6c83ead14c0081e3009019308c93d5dba55e
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Aug 5 12:29:06 2025 +0100
+
+    [exec.sysctxrepl.psb] Fix typo in range expression
+
+    A misapplication of P2079R10.
+
+commit f7361435f9909fd260b775a6346c068d50234d16
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Aug 5 12:31:46 2025 +0100
+
+    [meta.syn] Fix typo "type_underlying_type" => "underlying_type"
+
+    This was an error in P2996R13.
+
+commit 40101948e00579dd6d551d5383303f37cf1eb9a9
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Aug 5 12:34:08 2025 +0100
+
+    [tab:meta.reflection.operators] Fix another operator spelling
+
+    Similar to 746811a19a222ffb5e9d03008d752bcb10967ce3,
+    which missed this one.
+
+commit ed5362ea20c80d18be106549267a93dba3b3a7c9
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Aug 5 12:37:59 2025 +0100
+
+    [meta.reflection.queries] Fix "r" that should be "T".
+
+    This is a follow-up to 2567873ea47b7f888f45aa4e8264c9cd3310183d,
+    which fixed a missing paragraph, but forgot to make this change.
+
+commit 28c495bef17c305fb8ef6f56b88ae11c6115ccf0
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Aug 5 12:42:24 2025 +0100
+
+    [meta.reflection.access.context] Fix mistaken qualifier
+
+    A misapplication of P2079R10.
+
+commit 895e938cfb55d729d016086551f4472621d1722b
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Aug 5 12:46:50 2025 +0100
+
+    [meta.reflection.extract] Reinstate "Constant When" wording from P2996R13 regarding similar and function pointer types
+
+    I'm not sure if the mention of function pointer types was dropped
+    in a misguided editorial simplification, but this is not an editorial
+    change. (But we retain the cross-reference which was not in the paper.)
+
+commit c3bd02a2e44c53c8fe7ba5b48a94bacc9186235d
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Aug 5 12:55:17 2025 +0100
+
+    [meta.reflection.result] Fix function parameter name
+
+    A misapplication of P2996R13.
+
+ + diff --git a/papers/n5015.md b/papers/n5015.md new file mode 100644 index 0000000000..0cdc3948ec --- /dev/null +++ b/papers/n5015.md @@ -0,0 +1,1784 @@ +# N5015 Editors' Report -- Programming Languages -- C++ + +Date: 2025-08-14 + +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), +to those who have provided pull requests with fixes, +and to everyone who drafted motion applications. +Special thanks to Alisdair Meredith and Jan Schultke +for drafting a lot of motion applications, +to Andreas Krug for ongoing careful reviews, +and to the review committee for finding and fixing many transcription errors +in this rather large amount of added text. + +## New papers + + * N5013 is the C++26 Committee Draft. + * [N5014](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5014.pdf) is the + current working draft for C++26. It replaces + [N5008](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5008.pdf). + * N5015 is this Editors' Report. + +## Motions incorporated into working draft + +### Notes on motions + +All motions were applied cleanly. + +In CWG Motion 11, +[P2843R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2843r3.pdf) +("Preprocessing is never undefined"), the text has been reconciled with +earlier changes coming from CWG Motion 1, Issue +[CWG3015](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3752r0.html#3015). + +In LWG Motion 35, +[P1317R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p1317r2.pdf) +("Remove return type deduction in `std::apply`"), the feature test macro +`__cpp_lib_apply` was bumped and marked as also being in ``. + +Several minor phrasing and punctuation improvements have been applied +in subsequent reviews, and some minor errors and oversights in the approved +texts have been fixed in consultation with authors and wording group chairs. + +### Core working group polls + +CWG Poll 1. Accept as Defect Reports and apply the proposed resolutions of all issues except issues 3013, 3014 and 3020 in +[P3752R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3752r0.html) +(Core Language Working Group "ready" Issues for the June, 2025 meeting) to the C++ Working Paper. + +CWG Poll 2. Apply the proposed resolutions of issues 3013, 3014 and 3020 in +[P3752R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3752r0.html) +(Core Language Working Group "ready" Issues for the June, 2025 meeting) to the C++ Working Paper. + +CWG Poll 3. Accept as a Defect Report and apply the changes in +[P3618R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3618r0.html) +(Allow attaching main to the global module) to the C++ Working Paper. + +CWG Poll 4. Apply the changes in [P2996R13](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2996r13.html) +(Reflection for C++26) to the C++ Working Paper and accept as Defect Reports core issues 2701 and 3026 resolved thereby. + +CWG Poll 5. Apply the changes in [P3394R4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3394r4.html) +(Annotations for Reflection) to the C++ Working Paper. + +CWG Poll 6. Apply the changes in [P3293R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3293r3.html) +(Splicing a base class subobject) to the C++ Working Paper. + +CWG Poll 7. Apply the changes in [P3491R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3491r3.html) +(`define_static_{string,object,array}`) to the C++ Working Paper. + +CWG Poll 8. Apply the changes in [P1306R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p1306r5.html) +(Expansion Statements) to the C++ Working Paper. + +CWG Poll 9. Apply the changes in [P3096R12](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3096r12.pdf) +(Function Parameter Reflection in Reflection for C++26) to the C++ Working Paper. + +CWG Poll 10. Apply the changes in +[P3533R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3533r2.html) +(constexpr virtual inheritance) to the C++ Working Paper. + +CWG Poll 11. Apply the changes in [P2843R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2843r3.pdf) +(Preprocessing is never undefined) to the C++ Working Paper. + +### Library working group polls + +LWG Poll 1. Apply the changes in [P3742R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3742r0.html) +(C++ Standard Library Issues to be moved in Sofia, Jun. 2025) to the C++ working paper. + +LWG Poll 2. Apply the changes in [P2988R12](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2988r12.pdf) +(`std::optional<‍T&‍>`) to the C++ working paper. + +LWG Poll 3. Apply the changes in [P3348R4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3348r4.pdf) +(C++26 should refer to C23 not C17) to the C++ working paper. + +LWG Poll 4. Apply the changes in [P3037R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3037r6.pdf) +`(constexpr std::shared_ptr` and friends) to the C++ working paper. + +LWG Poll 5. Apply the changes in [P3284R4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3284r4.html) +(`write_env` and `unstoppable` Sender Adaptors) to the C++ working paper. + +LWG Poll 6. Apply the changes in [P3179R9](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3179r9.html) +(Parallel Range Algorithms) to the C++ working paper. + +LWG Poll 7. Apply the changes in [P3709R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3709r2.html) +(Reconsider parallel `ranges::rotate_copy` and `ranges::reverse_copy`) to the C++ working paper. + +LWG Poll 8. Apply the changes in [P3641R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3641r0.html) +(Rename `std::observable` to `std::observable_checkpoint`, and add a feature-test macro) to the C++ working paper. + +LWG Poll 9. Apply the changes in [P3044R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3044r2.pdf) +(sub-`string_view` from `string`) to the C++ working paper. + +LWG Poll 10. Apply the changes in [P2876R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2876r3.html) +(Proposal to extend `std::simd` with more constructors and accessors) to the C++ working paper. + +LWG Poll 11. Apply the changes in [P3480R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3480r6.pdf) +(`std::simd` is a range) to the C++ working paper. + +LWG Poll 12. Apply the changes in [P2664R11](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2664r11.html) +(Extend `std::simd` with permutation API) to the C++ working paper. + +LWG Poll 13. Apply the changes in [P3691R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3691r1.pdf) +(Reconsider naming of the namespace for "`std::simd`") to the C++ working paper. + +LWG Poll 14. Apply the changes in [P3383R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3383r3.html) +(mdspan.at()) to the C++ working paper. + +LWG Poll 15. Apply the changes in [P2927R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2927r3.html) +(Inspecting `exception_ptr`) to the C++ working paper. + +LWG Poll 16. Apply the changes in [P3748R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3748r0.html) +(Inspecting `exception_ptr` should be constexpr) to the C++ working paper. + +LWG Poll 17. Apply the changes in [P2830R10](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2830r10.html) +(Standardized Constexpr Type Ordering) to the C++ working paper. + +LWG Poll 18. Apply the changes in [P3570R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3570r2.html) +(optional variants in sender/receiver) to the C++ working paper. + +LWG Poll 19. Apply the changes in [P3481R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3481r5.html) +(`std::execution::bulk()` issues) to the C++ working paper. + +LWG Poll 20. Apply the changes in [P3433R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3433r1.pdf) +(Allocator Support for Operation States) to the C++ working paper. + +LWG Poll 21. Apply the changes in [P3149R11](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3149r11.html) +(`async_scope` - Creating scopes for non-sequential concurrency) to the C++ working paper. + +LWG Poll 22. Apply the changes in [P3682R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3682r0.pdf) +(Remove `std::execution::split`) to the C++ working paper. + +LWG Poll 23. Apply the changes in [P2079R10](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2079r10.html) +(Parallel scheduler) to the C++ working paper. + +LWG Poll 24. Apply the changes in [P3557R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3557r3.html) +(High-Quality Sender Diagnostics with Constexpr Exceptions) to the C++ working paper. + +LWG Poll 25. Apply the changes in [P3560R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3560r2.html) +(Error Handling in Reflection) to the C++ working paper. + +LWG Poll 26. Apply the changes in [P3503R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3503r3.html) +(Make type-erased allocator use in `promise` and `packaged_task` consistent) to the C++ working paper. + +LWG Poll 27. Apply the changes in [P3008R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3008r6.html) +(Atomic floating-point min/max) to the C++ working paper. + +LWG Poll 28. Apply the changes in [P3111R8](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3111r8.html) +(Atomic Reduction Operations) to the C++ working paper. + +LWG Poll 29. Apply the changes in [P3060R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3060r3.html) +(Add `std::views::indices(n)`) to the C++ working paper. + +LWG Poll 30. Apply the changes in [P2319R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2319r5.html) +(Prevent path presentation problems) to the C++ working paper. + +LWG Poll 31. Apply the changes in [P3223R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3223r2.html) +(Making `std::istream::ignore` less surprising) to the C++ working paper. + +LWG Poll 32. Apply the changes in [P2781R9](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2781r9.html) +(`std::constant_wrapper`) to the C++ working paper. + +LWG Poll 33. Apply the changes in [P3697R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3697r1.html) +(Minor additions to C++26 standard library hardening) to the C++ working paper. + +LWG Poll 34. Apply the changes in [P3552R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3552r3.html) +(Add a Coroutine Task Type) to the C++ working paper. + +LWG Poll 35. Apply the changes in [P1317R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p1317r2.pdf) +(Remove return type deduction in `std::apply`) to the C++ working paper. + +## Editorial changes + +### Major editorial changes + +There have not been any major editorial changes. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N5008 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/n5008...n5014). + + commit 2a74dc7bc587c2c64d8886faebc91d68c83626c1 + Author: Vlad Serebrennikov + Date: Mon Mar 17 15:33:35 2025 +0400 + + [expr.sub] Add missing cross-references (#7688) + + commit cdf6502ac7bf942f6ad32a27254db890c7ae8d3a + Author: Alisdair Meredith + Date: Tue Mar 18 09:35:16 2025 -0400 + + [sequences.general] std::hive is a sequence container (#7746) + + commit 2a71697913a853b62b8aeda5b68afbdfca756bf2 + Author: salonsro + Date: Tue Mar 18 13:37:49 2025 +0000 + + [defns.access] Add cross-reference (#7743) + + commit b3f45725c6cb088e26b02a36c51c6e19ce61351e + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Wed Mar 19 13:18:56 2025 +0100 + + [basic.contract.eval] Fix typo (#7749) + + commit 0bd8d94cc6b693cc3dd25bd32157928b6e02ac8e + Author: Jan Schultke + Date: Wed Mar 19 18:43:01 2025 +0100 + + [lex.digraph] Swap alternative token representations in table (#7750) + + commit 958532b7042b0c12af783a0a2f9e5c8fafc8702c + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Mar 21 09:22:26 2025 +0100 + + [hive.operations] Move closing curly bracket in front of comma (#7757) + + commit 719601dcb890bf2dbc2330af5846c30a2ef84830 + Author: Eisenwave + Date: Sun Oct 27 10:43:51 2024 +0100 + + [dcl.init], [depr.atomics.types.operations] Say "with static storage duration" + + commit 8b753114c3fe1602e04ca9d1015c14c4a54544af + Author: Eisenwave + Date: Sun Oct 27 10:47:27 2024 +0100 + + [thread.condition.nonmember], [futures.promise], [futures.task.members] Say "with thread storage duration" + + commit 78bec38978bce1c680ea0a2dd2f8791967148bb8 + Author: Eisenwave + Date: Sun Oct 27 10:49:12 2024 +0100 + + [expr.prim.id.unqual], [support.start.term] Say "with automatic storage duration" + + commit 1dd46d8b87a1a7918d07966d7ef04c0118bee73e + Author: Thomas Köppe + Date: Fri Mar 21 13:02:50 2025 +0000 + + [tools] Catch exception of polymorphic type by reference + + commit 9caa0dc05cb525c433f7889e190946a325f752ed + Author: Matthias Kretz + Date: Sat Mar 22 19:48:08 2025 +0100 + + [exec.schedule.from, simd.ctor] Remove incorrect @ escapes (#7759) + + commit 2d59c792e2a0228e77a0316d39bde9e51f31d146 + Author: Jens Maurer + Date: Sat Mar 22 22:37:08 2025 +0100 + + [cpp.embed.gen] Fix typo in example + + commit 9b8a5e51752efe9edd7a447e96ffab0f3313accc + Author: Eelis + Date: Sun Mar 23 10:06:28 2025 +0100 + + [range.zip.transform.iterator] Fix typo in index entry. (#7762) + + commit 6a4c11e137509beed40ce93dd9d92b7b24e0cbda + Author: timsong-cpp + Date: Mon Mar 24 08:45:47 2025 +0100 + + [stopsource.general] Restore accidentally deleted members in class definition (#7766) + + These were removed in error in the application of P2300R10. + + commit d51cc9b757a0bbb343244c3aecd546783d08ba83 + Author: Hewill Kang + Date: Mon Mar 24 16:00:39 2025 +0800 + + [range.to.input.view] Add \ref for to_input_view​::​iterator (#7767) + + commit 879d51544872d6b8b6f0a845328db26ef5f2ddcb + Author: Hewill Kang + Date: Mon Mar 24 16:01:34 2025 +0800 + + [range.drop.view] Fix typo (#7768) + + commit c4a89e3ca4e34c82f6525a342f08dab1dce63d8c + Author: Jan Schultke + Date: Mon Mar 24 22:07:58 2025 +0100 + + [alg.rand.generate] Add generate_random to index (#7774) + + commit dd233b52569edc8598d575d57ee4634729228acf + Author: Hewill Kang + Date: Wed Mar 26 15:26:06 2025 +0800 + + [simd.ctor] Fix typos (#7779) + + commit ae030b95169a0c828917b72085ac99427c12f0d4 + Author: Hewill Kang + Date: Wed Mar 26 20:16:02 2025 +0800 + + [range.to.input.view] Add namespace wrapping (#7782) + + commit 4dd513d0096900ac82090875e2568a971909b2b3 + Author: Jens Maurer + Date: Wed Mar 26 20:48:23 2025 +0100 + + [lex.phases] Add cross-reference to [lex.header] (#7763) + + commit 3b4c353d381e07b4648671c592b82a1e487425d9 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Mar 27 19:51:39 2025 +0000 + + [temp.constr.general] Reorder constraint kinds to match subclause order (#7788) + + commit 5ecd4e9e00f64dfc73a75ce667bbaeba2b3b9b61 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Mar 27 20:40:32 2025 +0000 + + [temp.variadic] Consistently order template parameter kinds (#7796) + + commit 9798c7afb488414dd7e51fbc70dc9182ebafa668 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Mar 27 20:42:50 2025 +0000 + + [temp.deduct.type] Consistently order template argument kinds (#7798) + + commit 38a0bd47f42bf8c880df1a17e90110ac6a070944 + Author: Jonathan Wakely + Date: Fri Mar 28 22:25:40 2025 +0000 + + [alg.copy, alg.move] Rename ExecutionPolicy parameters for consistency (#7803) + + This makes them consistent with all other parallel algorithms. + + commit ddb98da95204fbd033e4e809e05634513187afb9 + Author: Jan Schultke + Date: Sun Mar 30 17:53:53 2025 +0200 + + [expr.const] Add reference to [dcl.constexpr] for "constexpr destructor" (#7629) + + commit d40449a0e50e126a35c555683dc7805f72efa7ef + Author: Jens Maurer + Date: Sun Mar 30 16:24:39 2025 +0200 + + [range.approximately.sized] Move to before [range.sized] + + This is an unfortunate application of P2846R6. + + commit ab81b357785fc5a48df60cbe9a372af4f281a25b + Author: timsong-cpp + Date: Sun Mar 23 18:20:35 2025 -0500 + + [cpp.predefined] Place the __STDC_EMBED macros in the unconditionally defined paragraph + + The incoming paper did not explicitly specify their placement, + but they are clearly meant to be defined unconditionally. + + commit 06ffe74abf088e275e4233d2891cc3ebc4664cea + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Mar 31 11:28:14 2025 +0000 + + [temp.constr.normal] Rephrase comment in example (#7793) + + commit 5b6307e337d50045c3b4109429f4912fe352bce4 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Mar 27 11:26:43 2025 +0000 + + [temp.over.link] Remove redundant wording + + commit 12b6153dccd2fc2f9ec6a8469d907b47bca57963 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Mar 27 11:26:40 2025 +0000 + + [temp.constr.normal] Use "contains (a pack)" instead of "names" + + commit 24c7d63df6144f0d718acb882c2c36ec97cd6212 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Mar 31 14:09:51 2025 +0200 + + [set.overview] Fix punctuation (#7808) + + commit bf5c701a23bcc7f79a459f474455cf0dc9c58de5 + Author: Hewill Kang + Date: Tue Apr 1 02:28:47 2025 +0800 + + [list.erasure, list.erasure] Move long code into codeblock (#7809) + + commit 743914c23ff20286507c1c8b201dc040a6f8f178 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Apr 1 15:08:12 2025 +0000 + + [temp.dep.constexpr] Fix broken formatting (#7811) + + commit 9fd6664ea97cd889cdf529f2d020e6fa6ea13d58 + Author: Jonathan Wakely + Date: Fri Apr 4 17:48:11 2025 +0100 + + [optional.monadic] Remove stray angle brackets on concept name (#7817) + + commit a989431c5a893f9106dc21e9b2dd0a670356d890 + Author: Geng Cheng + Date: Thu Apr 10 17:32:28 2025 +0800 + + [polymorphic.general] Fix garbled expression (#7820) + + The applied paper P3019R14 had truncated text. + + commit f79a0f6981def4868fc365fb906a8a0551359c7d + Author: Geng Cheng + Date: Thu Apr 10 18:40:44 2025 +0800 + + [polymorphic.asgn] Remove superfluous greater-than sign (#7821) + + commit 7f1000d2eca113824d6ac734c5348f332a2d3e1c + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Apr 11 14:10:48 2025 +0200 + + [func.bind.partial] Add backslash for throws + + commit 8792e5544498d262a821b2175c1fe52fd3a15156 + Author: Arthur O'Dwyer + Date: Sun Apr 13 13:33:06 2025 -0400 + + [meta.unary.prop] Comma should be a period (#7832) + + commit 317ae891f25d4875651495780b5238869cce825b + Author: Hewill Kang + Date: Mon Apr 14 23:20:57 2025 +0800 + + [mdspan.layout.left.obs] Add missing noexcept (#7831) + + commit 5ec615184220e01fd8f6a817cf6050f3ce039f91 + Author: Geng Cheng + Date: Mon Apr 14 23:25:37 2025 +0800 + + [vector.modifiers] Old concepts cannot be “modeled” (#7836) + + commit 08b6e70e2c469a4a2d85d5ab49b14f75d57c0d36 + Author: OndrejPopp <50676516+OndrejPopp@users.noreply.github.com> + Date: Mon Apr 14 17:27:34 2025 +0200 + + [dcl.contract.func] Add missing \br in grammar (#7838) + + commit 52c7080115598baddd61b050c707d2a05a5fa2f7 + Author: A. Jiang + Date: Tue Apr 22 23:37:19 2025 +0800 + + [iterator.synopsis] Apply changes of P2538R1 to the synopsis of `` (#7841) + + Remove `incrementable_traits` and update `projected`. + + commit 05300d78dc4fb6ee346d93b381d6a15ed51406f7 + Author: Tsche <2440422+Tsche@users.noreply.github.com> + Date: Wed Apr 23 07:21:16 2025 +0200 + + [tuple.syn] Fix return type of ignore-type::operator= (#7840) + + This fixes a misapplication of P2968R2, in commit 225eadc4f3676472836397c9c0449f3203ae0a6d. + + commit a136094254936f2ae4e8bf1d5c59fff1afca03c7 + Author: A. Jiang + Date: Thu May 8 02:58:03 2025 +0800 + + [container.adaptors] Avoid naming sorted_{equivalent,unique}_t tag parameters (#7867) + + commit b99e22bb3f4e27eae65028aa011d3db08a0793cf + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu May 8 20:53:45 2025 +0200 + + [basic.contract.eval] Remove stray closing parenthesis (#7868) + + commit 4b1283ba5fabb5392b0faabe9682abc43d449614 + Author: Jens Maurer + Date: Mon May 12 22:32:34 2025 +0200 + + [sequence.reqmts] Fix application of P2846R6 for `assign_range` + + commit 74a6eed8a7b12041dbdb0dd9c39c433363211894 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue May 13 19:45:22 2025 +0200 + + [expr.call] Move period to end end of sentence (#7871) + + commit e8a5d8b83a91a0606883042fa3beb3e7b4423d9c + Author: Geng Cheng + Date: Thu May 15 02:25:17 2025 +0800 + + [associative.reqmts.general] Replace undefined "multiple keys" with "equivalent keys" (#7874) + + commit 69f81d2bc71ae28694ded6f03a5a2670e916c7d8 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu May 15 08:09:59 2025 +0200 + + [dcl.contract.res] Add period to end of sentence + + commit 78ea6062c043cc640fe5e72985eb36c279b1e976 + Author: Luc Grosheintz + Date: Thu May 15 23:46:56 2025 +0200 + + [mdspan.layout.right.obs] Add missing constexpr to required_span_size (#7872) + + commit 6c20db7e4a3300a0274e4ba9eb8c35371d6bc276 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri May 16 15:29:51 2025 +0200 + + [class.prop] Remove stray closing parenthesis (#7879) + + commit c4a2d197bb3c52d3e84a645bb756b3606e8408fc + Author: A. Jiang + Date: Sat May 17 03:07:18 2025 +0800 + + [algorithm.syn] Fix synopsis entries for `ranges::find_last` (#7805) + + P3217R0 updated ranges::find_last, but the synopsis was accidentally left unchanged. + + commit d8ab7083603ad16eb74fade44c757760b1f9e9dc + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat May 17 08:57:50 2025 +0200 + + [class.mem.general] Remove stray closing parenthesis (#7880) + + commit eb112f887bc541c5a21b302ac7d2476c7b5fa5e3 + Author: Jan Schultke + Date: Mon May 19 09:28:23 2025 +0200 + + [hive.operations] Add missing paragraph number (#7882) + + commit 0fd10bfb6ca13a61dd1bb77cad3b070d500e1cbc + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue May 20 13:42:28 2025 +0200 + + [dcl.fct.def.replace] Remove stray closing parenthesis (#7883) + + commit 1abf0915e3aa24ad48a1c2e74d60975a30fa93da + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri May 23 09:13:02 2025 +0200 + + [simd.bit] Add period to end of sentence (#7887) + + commit cc5b90512ac3deecfcc4e47f5da1910e54d661f9 + Author: S. B. Tam + Date: Wed May 28 00:18:32 2025 +0800 + + [locale.money.put.members] Fix typo (#7896) + + commit 782c81f8dfd714f34dced2de882b57d102dbde4c + Author: Jan Schultke + Date: Tue May 27 18:35:39 2025 +0200 + + [simd.creation] Add commas and improve semantic linebreaks (#7895) + + commit a770261ed7dc83ea269e07f4e5936ca65337ddff + Author: A. Jiang + Date: Wed May 28 17:59:55 2025 +0800 + + [text.encoding.id] Sort enumerators in ascending order (#7899) + + commit cb25f9b182c89e442687fed176150693debc6970 + Author: A. Jiang + Date: Sat May 31 04:16:52 2025 +0800 + + [projected] `projected` is an alias template after P2538R1 (#7901) + + commit b210471e21197f2e0f1655969c2adb9f04f30e02 + Author: Eric Niebler + Date: Sun Jun 1 09:20:30 2025 -0700 + + [execution.syn] Rename template parameter of `schedule_result_t` (#7906) + + commit d18bd92fda9c02e3518910824f041ab49fbc1a4b + Author: A. Jiang + Date: Mon Jun 2 05:47:51 2025 +0800 + + [tab:headers.cpp.fs] Fix header name for `is_execution_policy(_v)` (#7849) + + commit 25e95f5296e2b3c0f378ac5d3ddfdca1e867e9b0 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Jun 2 17:52:21 2025 +0200 + + [simd.unary] Add \ref for simd.unary (#7908) + + commit a3b9cb5bdbec5e2fbf964561ea10dc19a4b042d5 + Author: Jan Schultke + Date: Mon Jun 2 22:36:05 2025 +0200 + + [container.requirements] Simplify Returns specification for try_emplace (#7892) + + commit 660ab848b97640764a270220f038f911b1057dfe + Author: Daniel Krügler + Date: Fri Jun 13 23:44:10 2025 +0200 + + [expected.object.cons] Reorder arguments of is_same_v for consistency (#7915) + + commit ee9b5bf124495f1473e246f223756a164d42aed9 + Author: Hubert Tong + Date: Sat Jun 14 02:32:38 2025 -0400 + + [meta.trans.other] Fix off-by-one references to [meta.rqmts] (#7914) + + commit 57e185f4bde5309d98e22f514d4434a1feea1911 + Author: A. Jiang + Date: Mon Mar 24 00:24:04 2025 +0800 + + [assertions.assert] Add ISO C reference for standard error stream + + commit 4f3e967cdc0befd71b1101e996c22db602ff0fd3 + Author: Eisenwave + Date: Sat May 3 10:25:33 2025 +0200 + + [class.temporary] Define "temporary object" + + commit 4aa14fe19a9060360436e9ab56d361101212e961 + Author: Jonathan Wakely + Date: Thu May 1 15:56:42 2025 +0100 + + [polymorphic.ctor] Owned object must have cv-unqualified object type + + commit 6f18c6b9e3634cf2ac40ab0f4d7c9e2e68acee2c + Author: Jonathan Wakely + Date: Mon Jun 16 08:42:48 2025 -0700 + + [value.error.codes] Remove redundant std qualifications (#7918) + + commit 59b1a8ada534fb1491ef3a134e05262baa0b516c + Author: Eric Niebler + Date: Tue Jun 17 05:56:42 2025 -0700 + + [exec.snd] Fix spelling of exposition-only `query-with-default` function (#7905) + + commit 04f4a62af51c7b3e8dad223051dc95a7942194c3 + Author: Jens Maurer + Date: Mon Jun 2 22:54:34 2025 +0200 + + [basic.def.odr] Rephrase sentence to avoid double-negative + + commit ca3694ecf8fd82d896d5bcf011bae7640d5335de + Author: Eric Niebler + Date: Tue Jun 17 06:04:08 2025 -0700 + + [exec.let] Fix function type name (#7907) + + The specification of `let_value(sndr,fn)` and friends refers to the type of `fn` as "`Fn`". But when introducing the types, we give it the name "`F`". This fixes the inconsistency. + + commit dfcc6dd19c0efd93bff47d501fdf6e2d52160a5c + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Mar 27 11:34:57 2025 +0000 + + [expr.type] Remove redundant \cvqual + + commit 9d20a320e1662deff9abb65b4f7e6e52e66ed732 + Author: Geng Cheng + Date: Tue Jun 17 21:51:41 2025 +0800 + + [indirect.asgn] Change "contained value" to "owned object" (#7822) + + commit 06e649b10e2d1af29eee739ea0998cb45e65fadc + Author: A. Jiang + Date: Tue Apr 8 17:19:29 2025 +0800 + + [string.view] Exposition-only formatting for `data_` and `size_` + + commit 9dfb02a3222eed8a02d74c7d80714eeaf3aba10b + Author: Geng Cheng + Date: Tue Jun 17 21:59:52 2025 +0800 + + [time.format] Add commas and clarifying "unless otherwise" (#7697) + + See LWG 4124, which added wording before the text in question that motivates adding "unless otherwise specified". + + commit 1f79f7a919432e8eccc90c9ffd21baeb9ea0563c + Author: A. Jiang + Date: Thu Apr 24 15:08:28 2025 +0800 + + [exec.util.cmplsig.trans] Drop verbose `add_lvalue_reference_t` + + commit 32ec75ea890301b100eac4a63e986a55cd08ea13 + Author: Thomas Köppe + Date: Tue Jun 17 17:07:41 2025 +0300 + + [indirect, polymorphic] Rename stable lables "asgn" to "assign" + + commit da436f8325d978b76eaa18be46e987decc9117c5 + Author: A. Jiang + Date: Wed Jun 18 00:47:57 2025 +0800 + + [defns.dynamic.type] Say "most derived object" in the example (#6203) + + commit 66e15a609b8bec7b4b976b17a5aaf3d65893d31c + Author: languagelawyer <38548419+languagelawyer@users.noreply.github.com> + Date: Tue Jun 17 21:48:26 2025 +0500 + + [intro.multithread.general] Say "use", not "access" functions (#6503) + + commit 7a90fddca19918e03bc10a7a6ef22a970ca381a3 + Author: A. Jiang + Date: Wed Jun 18 22:13:59 2025 +0800 + + [tab:meta.trans.cv] Simplify wording for add_{const,volatile} + + Wording about reference, function, or top-level cv-qualified types + moves to notes, as it is redundant since at least C++11. + + commit c156822435acd59433b7fb7f28e83a5765af7e64 + Author: A. Jiang + Date: Sun Sep 29 09:11:10 2024 +0800 + + [complex.numbers.general] Clarify that the template is primary + + The difference between between "the `complex` template" and "the template named `complex`" (which including program-defined specializations) is obscure. It seems better to cleary say that [complex.numbers.general] only covers the primary template. + + commit f457f12ffe04df1af8e6a28e174a5ca2dc59ddaa + Author: A. Jiang + Date: Thu Jun 19 17:32:03 2025 +0800 + + [execpol.type] Remove "see below" definition from "is_execution_policy" itemdecl (#7909) + + We already say that it is a Cpp17UnaryTypeTrait with a base characteristic of either true_type or false_type. + + commit 446ec2e959f38281786c3f61e83f077459763f92 + Author: Arthur O'Dwyer + Date: Fri Jun 20 02:19:07 2025 -0400 + + [inplace.vector] Move reserve, shrink_to_fit from "modifiers" to "capacity" (#7321) + + commit c355072152d7c9e364e2a8acf265fdf068942002 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Jun 20 07:50:59 2025 +0200 + + [valarray.cassign] Add period at end of "Returns" + + commit 3bce8f7f15164dc455240e53acce596eeba97d45 + Author: Jonathan Wakely + Date: Fri Jun 20 08:01:43 2025 +0100 + + [diff.cpp23.strings] Move Clause 27 changes after Clause 23 changes + + The 'Strings' clause was moved before the new 'Text processing' clause, + so it's now after the 'Containers' clause. The order of the [diff.cpp23] + subclauses should reflect that. + + commit ac78ae76c579883a32a9eb5b00346150a41e8e47 + Author: timsong-cpp + Date: Fri Jun 20 21:02:18 2025 +0100 + + [atomics.ref.float] Fix spelling of placeholder + + commit a8f807b14c33ca76c790df97ca7d0ddf9746abef + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sun Jun 22 09:12:52 2025 +0200 + + [out.ptr] Add period at end of "Returns" + + commit 346c6d0dfd608764d697f1a33ef739a4762e0d40 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sat Mar 11 20:53:05 2023 +0000 + + [conv.qual] Remove unused definition of 'cv-qualification signature' + + commit 0b41c12760d8079ee4c460df6ddecaf220f2dfb6 + Author: Thomas Köppe + Date: Sun Jun 22 19:59:47 2025 +0300 + + [intro] Special page header before Clause 1 (#6070) + + commit 4726d67bf8f22f15dd7f3dcae7b54832dcbbbb91 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Sun Jun 22 17:27:15 2025 +0000 + + [dcl.type.auto.deduct] Change "occurrences" to "occurrence" (#7644) + + This appears to be a misapplication of N1984, which contains the wording "Obtain `P` from `T` + by replacing the occurrence of `auto` with a new invented type template parameter `U`." + + commit a8d96185e4bba7f738e4c2e1f3593a6e55fbbbd8 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Jun 23 08:07:06 2025 +0200 + + [basic.ios.members] Add period at end of "Returns" + + commit 2e12f5e71e56af0ffae0b5a7cd9086d24b72df20 + Author: Thomas Köppe + Date: Mon Jun 23 12:48:46 2025 +0100 + + [stmt] Move start of subclause-spanning index entries up to \rSec1 + + I expect that we forgot to move this when we added the "general" + subclauses to remove hanging paragraphs, and thus accidentally caused + the index entries to be "misnested". + + commit 4f925714c37ed1fe6a5692adcc3ef5fa37964056 + Author: Jens Maurer + Date: Thu Jun 26 13:25:36 2025 +0200 + + [atomics.ref.float] Apply missing changes from P3323R1 + + Paper P3323R1 cv-qualified types in atomic and atomic_ref + was incompletely applied in commit cd4dbcf2aa6df895a25dbf8c0773dd0fa67ef45d. + + commit f9100076b21e277644a793624db7dc96bff29594 + Author: Matthias Kretz + Date: Fri Jun 27 13:11:39 2025 +0200 + + [simd.expos.defn] Fix missing paragraph break (#8028) + + commit abe616528d5ff19d25983af7497bcedf0b3d44bb + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Jun 27 13:12:54 2025 +0200 + + [iostate.flags] Add period at end of "Returns" (#8026) + + Author: Andrew Rogers <32688592+adr26@users.noreply.github.com> + Date: Sun Jun 29 11:20:31 2025 +0100 + + [container.insert.return] Fix description of insert-return-type (#8030) + + Use the usual phrasing "X is for exposition only" when X is an exposition-only construct. + + commit be34ebfac39484ff96f68b46c2418b6fc49c66f4 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Wed Jul 2 07:58:52 2025 +0200 + + [istream.unformatted] Add period at end of "Returns" + + commit f6cd0dcbd082cfd85f87addec007680949cb1de9 + Author: Hewill Kang + Date: Fri Jul 4 04:27:11 2025 +0800 + + [range.join.iterator] Remove spurious return (#8038) + + commit 6f2e658a6c5ceaf577480d656bda0417fc98cc1d + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Sat Jul 5 08:42:54 2025 +0200 + + [mem.poly.allocator.mem] Fix typo + + commit ce78eced98e3e4dfe99eb409398267e5f00126aa + Author: Jens Maurer + Date: Wed Jun 25 12:35:16 2025 +0200 + + [std,check] Ensure proper placement of \iref + + commit ff592bd14ff3abecff33669bda91b658bf9f1023 + Author: Thomas Köppe + Date: Tue Jul 15 09:15:08 2025 +0100 + + [diff.cpp23.lex] Fix capitalisation in heading + + commit 00102f1c03f81c6004d4d14e50f45e7084eafed0 + Author: Hana Dusíková + Date: Mon Jul 14 11:50:06 2025 +0200 + + [container] unify to `friend constexpr` (there were few `constexpr friend`) + + commit 502465fc1b2676d1cf2e8565942f6d0446fc6d14 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Jul 14 19:46:00 2025 +0200 + + [meta.syn] Fix typo + + commit c4c5bddac9e7e294c2685e5ae0d294b01d2b1572 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Jul 14 20:11:49 2025 +0200 + + [meta.reflection.member.queries] Fix typos + + commit d3aaeb9da74e029199a3c4fb2c125e3fa8a6273c + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Jul 14 19:59:51 2025 +0200 + + [meta.reflection.queries] Fix typos + + commit 9797d6936ddbb39b89fbfa31ab0bf57c213f8476 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Jul 14 20:26:21 2025 +0200 + + [meta.reflection.traits] Fix typos + + commit a295d0ed2ebb68e3930d208ec5958efd51c6b225 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Wed Jul 16 20:23:54 2025 +0200 + + [meta.reflection.exception] Fix typo + + commit 08e1d9e30210983b2745ebff9b1002ecbf235bbd + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Jul 14 20:42:53 2025 +0200 + + [meta.reflection.define.aggregate] Fix typos + + commit eb0529b7154823f39f1c86ffdfdc1f7f3bcebfaa + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Jul 15 08:48:12 2025 +0200 + + [meta.reflection.queries] Fix typo + + commit 51904cdf92ea7a8eb5f7f60cfe65233429d9c365 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Jul 14 22:13:57 2025 +0200 + + [meta.reflection.queries] Add period to end of sentence + + commit d25f7d0b0449ffa3d89a4a3270dba8af2fd88719 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Jul 15 11:19:45 2025 +0200 + + [optional.ref.ctor] Fix punctuation + + commit 916d4f4d78509dced64f02c2616261b588c16941 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Mon Jul 14 21:55:02 2025 +0200 + + [over.call.func] Add period to end of sentence + + commit 7ca1adbf7367735b3657830798132b2fe2539cf7 + Author: Jan Schultke + Date: Thu Jul 17 15:03:01 2025 +0200 + + [alg.partitions] Replace non-existent concept "copy_assignable" concept with "copyable" + + commit 5047d04a825a7fc72381ba5596da8c6062f65107 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Tue Jul 15 22:59:04 2025 +0200 + + [alg.copy] Add period to end of sentence + + commit a5b2951c975588df8652ebc779784cbc84267c22 + Author: Luc Grosheintz + Date: Wed Jun 25 07:19:40 2025 +0200 + + [mdspan.layout.leftpad.cons] Add \expected. + + The description of + + template + constexpr explicit(see below ) + mapping(const LayoutLeftPaddedMapping& other); + + didn't separate Mandates and Preconditions. This commit adds an + \expects to separate the two. + + commit e5a30fec15d4a9e6f4425edcf3c6898cc67fe0a3 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Thu Jul 3 12:04:48 2025 +0000 + + [temp.constr.concept] Fix example + + * Give all template parameters a unique name for clarity + * Replace use a of a reserved identifier + * Fix the example's accompanying text, in particular the parameter + mapping of the normal form of the concept-id after substitution + + commit 103dddccf3a965899c4bcaedab98154792573f24 + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Jul 17 15:21:44 2025 +0200 + + [exec.task.scheduler] Fix typo + + commit 2974816e0b56f79c169f7eee3b24572e0092cd35 + Author: Daniel M. Katz + Date: Thu Jul 17 09:39:07 2025 -0400 + + [meta.reflection.access.context] Fix typo + + commit bd2412ce3b94f7ae3bf9c9e78a97e31181e7c01d + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Thu Jul 17 15:15:16 2025 +0200 + + [exec.affine.on, task.promise] Fix typos + + commit 1acddcece95e2d7c83db3d8aee89fd4d4689fcd3 + Author: Alisdair Meredith + Date: Tue Jul 15 05:05:03 2025 -0400 + + [lex.separate] Remove last reference to instantation units + + The term instantiation unit was removed by the reflection paper, P2996. + + commit 42e68bf40e4ab7fc8b4a102f6c1d0ba4f6b63faa + Author: Andreas Krug <153394595+Andreas-Krug@users.noreply.github.com> + Date: Fri Jul 18 09:12:16 2025 +0200 + + [task.promise] Move period to end of sentence + + commit c76496316acc434ac06e23191b45b0c228f7331f + Author: Jan Schultke + Date: Fri Jul 18 13:09:41 2025 +0200 + + [simd.syn] Fix capitalization and code fonts in synopsis comments; reflow declarations (#8093) + + commit cdffb3687e537d19197fc9bd24dca0e63ae6c744 + Author: Alisdair Meredith + Date: Sat Jul 19 06:02:19 2025 -0400 + + [cpp.error] Recommended practice should start it own paragraph + + commit ad971231094740ae637c70c468c6e96f3a98a5d3 + Author: Thomas Köppe + Date: Sun Jul 20 00:24:52 2025 +0100 + + [expr.const] Improve punctuation in list items. + + Striking "and" was a missed edit from P2996R13. + + commit 67a20d351cd370def6dede93e1c3703de4b32b70 + Author: Thomas Köppe + Date: Sun Jul 20 01:46:41 2025 +0100 + + [temp.res.commit] Add introduction of definition of "type-only context". + + This avoids having to style either of the two subsequent + sub-definitions as the main definition. + + commit c07c130af2014ee374be9754e9aeba43e564c614 + Author: Thomas Köppe + Date: Sun Jul 20 02:00:56 2025 +0100 + + [temp.dep.type] Fix list item continuation after recent addition. + + This edit was missed in the application of P2996R13. The deletion of + the original "or" was not indicated in the paper (but is clearly + necessary). + + commit 0efc6648509b380573345101037eac96f1320645 + Author: Thomas Köppe + Date: Mon Jul 21 18:07:37 2025 +0100 + + [tab:meta.unary.cat] "is_reflection": add xref to [basic.fundamental] + + commit 7ceef7e16c3314b178122762184d3d142262de00 + Author: Thomas Köppe + Date: Mon Jul 21 18:13:32 2025 +0100 + + [meta.{syn, reflection.traits}] Rename "swappable_with_type" parameters to type1, type2. + + These functions are symmetric and don't have a "src" and "dst". + + commit 12ad8bcaa490d7851cb2ffaff8ac219cd746e039 + Author: Thomas Köppe + Date: Mon Jul 21 18:22:28 2025 +0100 + + [meta.syn] Add missing paragraph 4. + + This was omitted in the application of P2996R13 by accident. + + commit 746811a19a222ffb5e9d03008d752bcb10967ce3 + Author: Thomas Köppe + Date: Mon Jul 21 18:27:25 2025 +0100 + + [tab:meta.reflection.operators] Fix some operator spellings + + commit 6b71747fdd3f38e20ef4bb4257aae64c0f1ec147 + Author: Thomas Köppe + Date: Mon Jul 21 18:34:11 2025 +0100 + + [meta.reflection.names] "below" is "above" + + commit 2567873ea47b7f888f45aa4e8264c9cd3310183d + Author: Thomas Köppe + Date: Mon Jul 21 18:41:04 2025 +0100 + + [meta.reflection.queries] Add missing paragraph in is_{const,volatile}. + + This was omitted in the application of P2996R13 by accident. + + commit cbc4a1fb6853656f43c962a68396160e07663166 + Author: Thomas Köppe + Date: Mon Jul 21 18:46:40 2025 +0100 + + [meta.reflection.queries] Add missing comma in "function, type". + + This seems to have been a mistake during application of P2996R13. + + commit c27dd93b5aee5e3936f56cdf886b2a8f6af77ac5 + Author: Thomas Köppe + Date: Mon Jul 21 18:50:57 2025 +0100 + + [meta.reflection.queries] Add missing "operator function template". + + This seems to have been a mistake during application of P2996R13. + + commit b679e4be282c9303dfb41522e16cfe22931b37a0 + Author: Thomas Köppe + Date: Mon Jul 21 21:45:55 2025 +0100 + + [meta.reflection.queries] Add missing "Constant When" element of "dealias", converted to "Throws". + + This seems to have been omitted during application of P2996R13 by + accident. + + commit 0ff0e096921ad25c9133b27ac30d727d0bfd5bc1 + Author: Thomas Köppe + Date: Mon Jul 21 21:30:11 2025 +0100 + + [meta.reflection.queries] Fix example + + This seems to have been a mistake during application of P2996R13. + + commit 4021cdb12a314b8c3953feb5841342a4ff2b8993 + Author: Thomas Köppe + Date: Mon Jul 21 21:33:06 2025 +0100 + + [meta.reflection.access.context] Fix typos + + commit 42a93030c64a87610aa0abb09290a0a11f563c96 + Author: Thomas Köppe + Date: Mon Jul 21 21:53:08 2025 +0100 + + [meta.reflection.member.queries] Fixed font, typo + + commit bd0dee79f341012c8b4f12cff8235d874251f45b + Author: Thomas Köppe + Date: Mon Jul 21 22:10:38 2025 +0100 + + [meta.reflection.layout] Delete unintended "value". + + This seems to have been copy-pasted erroneously. + + commit 7488f055b98b56bfe598bbd2dd46a4eae4e8171a + Author: Thomas Köppe + Date: Mon Jul 21 22:34:53 2025 +0100 + + [expr.ref] Delete extraneous "the". + + Accidentally misapplied from P3293R3. + + commit e546fb55893220e63e79a7db777c6af9598dce27 + Author: Thomas Köppe + Date: Tue Jul 22 10:48:03 2025 +0100 + + [expr.ref] Add "Otherwise, " to beginning of list items. + + This was requested by P2996R13, but seems to have been missed. + + This edit also covers the new item added by P3293R3. + + commit 5a191509d702a6e53947493ac4bc119c6a935c49 + Author: Thomas Köppe + Date: Tue Jul 22 13:18:13 2025 +0100 + + [stmt.expand] Add comma before "or" to list item + + commit 580a5f6d378f17067749166ca68b2a04c9fdc2de + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Wed Dec 25 16:38:25 2024 +0000 + + [temp.deduct.call] Add missing words + + commit f8e0a6539254574f7984ff6a8afa1d61daab20c0 + Author: Alisdair Meredith + Date: Fri Jul 18 18:37:20 2025 -0400 + + [lex.separate] Redistribute second comment + + The second comment in [lex.separate] is both too specific, and not specific + enough. Move the last sentence about use of separately translated TUs to + the end of the first note, where it seems most appropriate. Move the rest + to just after the definition of translation unit in phase 7 of translation. + + commit 3ce793a1a76e6c1b0ec599ab2d7d1696726c2253 + Author: Thomas Köppe + Date: Tue Jul 22 13:24:01 2025 +0100 + + [lex.pptoken] Reorder list items to avoid "or" and "and" at same level + + commit 7e6519ecfeffe06254c088259f4e83d36bbd20bd + Author: Thomas Köppe + Date: Fri Jul 25 00:22:44 2025 +0100 + + [meta.reflection.layout] Spell variable "T", not "TR". + + It's unclear whether this was just a typo or an attempt to avoid + ambiguity, but there does not seem to be a risk of confusion, and the + spelling of the paper ("T") seems fine. + + commit 454ba171cb14531639e641cb1200617fbf8d943f + Author: Thomas Köppe + Date: Fri Jul 25 14:31:22 2025 +0100 + + [meta.reflection.queries] Delete mistaken "Throws:" element. + + This was added accidentally in + b679e4be282c9303dfb41522e16cfe22931b37a0 because I misread the paper. + + commit 0922eeef80ee7f80e3edca688686e771a2d510bb + Author: Thomas Köppe + Date: Fri Jul 25 15:08:25 2025 +0100 + + [meta.reflection.extract] Fix typo + + commit 5396d899f281c99ee1d9df4ab7eca68d4acfa810 + Author: Thomas Köppe + Date: Fri Jul 25 15:13:58 2025 +0100 + + [meta.reflection.extract] Fix mistaken "C" that should be "X C::*". + + This seems to have been a mistake during application of P2996R13. + + commit c9e7524ce95bd5e0e659419d7ea3137c7cf464e4 + Author: Thomas Köppe + Date: Fri Jul 25 15:31:37 2025 +0100 + + [meta.reflection.result] Reorder and reword paragraphs for clarity. + + After the "Constant When" => "Throws" reordering, the definition of + the invented variable TCls had moved far from where it was being + referenced. This reordering moves it closer, adds a "defined below", + and moves the example to the end. + + commit d64e4580f78350b635d403602e5064d96979fa55 + Author: Thomas Köppe + Date: Fri Jul 25 15:37:25 2025 +0100 + + [meta.reflection.result] Fix "variable" => "template" + + This seems to have been a mistake during application of P2996R13. + + commit b36bff07d7f810295e448f7b23f898d2966f5583 + Author: Matthias Kretz + Date: Fri Jul 25 16:39:30 2025 +0200 + + [simd.mask.overview] Fix markup; add two missing closing @ + + commit f5d3c63e7ffa2a7ba1811ab5f2202131379690f8 + Author: A. Jiang + Date: Fri Jul 25 23:55:42 2025 +0800 + + [xrefdelta] Fix typo in the entry for [re.def] (#8112) + + The contents were moved to [intro.defs], not [intro.refs]. The latter is a typo. + + commit 27370ee1e0794bdd2b63c816860ed9c607bddc2a + Author: Thomas Köppe + Date: Fri Jul 25 17:42:27 2025 +0100 + + [meta.reflection.define.aggregate] Fix note text and !=/==. + + This seems to have been a mistake during application of P2996R13. + + commit 23e63d82a502b483781fc15eb7108d9ed86e16d0 + Author: Thomas Köppe + Date: Fri Jul 25 17:44:36 2025 +0100 + + [meta.reflection.define.aggregate] Fix typo ("C" should be "D"). + + This seems to have been a mistake during application of P2996R13. + + commit 1947b90539c268192d6e461208b6b278b3577ec9 + Author: Thomas Köppe + Date: Fri Jul 25 17:45:46 2025 +0100 + + [meta.reflection.define.aggregate] Fix typos + + commit 540773996f700115662dedbf4f315fb7b5c5e947 + Author: Eisenwave + Date: Sun Mar 3 13:47:13 2024 +0100 + + [handler.functions] Replace 'shall synchronize with' with 'synchronizes with' + + commit a75a8de957bc727e29a997f8e447b8b5e6d604ac + Author: Eisenwave + Date: Sun Mar 3 13:49:42 2024 +0100 + + [mem.res.global] Replace 'shall synchronize with'; add reference + + commit 416219e1bc003e9aaacfbcf5507b7111d3862e9e + Author: Thomas Köppe + Date: Sat Jul 26 00:38:50 2025 +0100 + + [tab:meta.reflection.traits] Fix some table entries + + commit 150caecf30a1ee455a02310a75d58224821e0220 + Author: Thomas Köppe + Date: Sat Jul 26 01:02:09 2025 +0100 + + [tab:meta.reflection.traits] Use subscripts for maths T_1, T_2 + + commit c6dfde71726d3ac6c14e9c9075aa4037245c40d4 + Author: Thomas Köppe + Date: Sat Jul 26 01:02:52 2025 +0100 + + [meta.reflection.traits] Use maths variables consistently + + Also removes a comma that should not have been added. + + commit 6ef473941e8541c06bde7fda78a58bb7a2ac5d4a + Author: Thomas Köppe + Date: Sat Jul 26 01:08:28 2025 +0100 + + [meta.reflection.array] Mended minor mistranscriptions + + commit a1283d5704724f202273f9bd5b3311b8e1a1af4a + Author: Thomas Köppe + Date: Sat Jul 26 01:18:26 2025 +0100 + + [meta.reflection.queries] Add missing word "unless" + + commit 4e6d501c8cf6735b67005124e3eac23907d7222e + Author: Thomas Köppe + Date: Sat Jul 26 01:57:05 2025 +0100 + + [meta.reflection.layout] Fix wording of alignment_of. + + The original transcription used some older wording that was not in the + most recent (approved) revision of paper (P2996R13). + + commit 1e931b0137e3c63977ddf1d98ae43a327b408003 + Author: Thomas Köppe + Date: Sat Jul 26 11:00:47 2025 +0100 + + [meta.reflection.queries] Add missing words "function or". + + Those were accidentally omitted in the application of P3096R12. + + commit 14c0cdd94516cbea2dd088cdd971a98564591c89 + Author: Thomas Köppe + Date: Sat Jul 26 11:20:12 2025 +0100 + + [cfloat.syn] Fix macro definition to be long, not int. + + This was a misapplication of P3348R4. + Checked that the C standard also uses long. + + commit 9e75be6a40e9fd6dfb3a7683553d1764b1a99c41 + Author: Thomas Köppe + Date: Sat Jul 26 11:25:01 2025 +0100 + + [cstdio.syn, cwctype.syn] Fix cross references to C + + commit b74580a2faf2e71591e13ad7e1e4671d1c8b640d + Author: Jan Schultke + Date: Sun Jul 27 01:47:13 2025 +0200 + + [linalg.conj.conjugatedaccessor] Fix incorrect return type of nested_accessor() (#8105) + + commit 4eb527d7c35e309391b2d92019410c83a2ed9993 + Author: Alisdair Meredith + Date: Sun Jul 27 11:02:53 2025 -0400 + + [basic.link] All names have linkage + + Given that the last option is "no linkage", the list is exhaustive + and should not open readers to questioning what other options + might be available if a name merely "can have" linkage. + + commit a8d02a9d5da364d3f47f39ba809ac486d4693897 + Author: Thomas Köppe + Date: Sun Jul 27 01:03:21 2025 +0100 + + [exec.snd.expos] Remove itemdecl "write-env". + + An omission in the application of P3284R4. + + commit 3dcc932d3b28717f5995f26afe9eb851258cf58c + Author: Thomas Köppe + Date: Sun Jul 27 23:43:31 2025 +0100 + + [algorithm.syn] Fixed transcription errors in various types + + commit 48e73b8d1260317ed0518454f9dbb573aab41a66 + Author: Thomas Köppe + Date: Sun Jul 27 23:52:10 2025 +0100 + + [alg.contains] Use codeblock for long return expression + + commit b7d39b2974d4861153b2d60dda56fe6c87c5f206 + Author: Thomas Köppe + Date: Sun Jul 27 23:53:30 2025 +0100 + + [alg.foreach] Delete mistaken Complexity: element on for_each_n + + This was presumably added via accidental copy-paste in the application + of P3179R9. + + commit ec837bba81851453902a23f7410faf32ebfd3eda + Author: Thomas Köppe + Date: Sun Jul 27 23:58:39 2025 +0100 + + [alg.searc] Fixed transcription error in template head + + commit 4d7eb66ddbd76312d213efad7f997b87ad11a299 + Author: Thomas Köppe + Date: Mon Jul 28 00:01:53 2025 +0100 + + [alg.ends.with] Fixed transcription error in defns of N1 and N2 + + commit c2e12a963104a77acb7ac0f8573e6116cbb28e92 + Author: Thomas Köppe + Date: Mon Jul 28 10:40:42 2025 +0100 + + [alg.copy] Add missing words. + + Those were accidentally omitted in the application of P3179R9. + + commit d764e4f90540d65d5dac01e62ac6ddac81118fda + Author: Thomas Köppe + Date: Mon Jul 28 10:44:34 2025 +0100 + + [alg.replace] Fixed transcription error in template head + + commit e99cd72eca0e0906464506105cc531ad199ed240 + Author: Thomas Köppe + Date: Mon Jul 28 12:42:02 2025 +0100 + + [alg.rotate] Move declaration to the correct itemdecl. + + This was a mistake in the application of P3179R9. + + commit d2ed4f73fcdf7af6d8a8207388793ea34e3fa5f2 + Author: Thomas Köppe + Date: Mon Jul 28 12:49:22 2025 +0100 + + [alg.partitions] Fixed some transcription errors + + commit 65fe94b7dbf63727cf3633bdc663f90c56bad031 + Author: Thomas Köppe + Date: Mon Jul 28 13:39:30 2025 +0100 + + [alg.merge] Make "E(e1, e2)" explicitly depend on "e1", "e2". + + commit 7b25ed6c5f5bb58739b9f0902b4ab3b8a54ca1f4 + Author: Thomas Köppe + Date: Mon Jul 28 13:41:56 2025 +0100 + + [set.{union,intersection,difference}] Add missing "of". + + This was mistakenly omitted in the application of P3179R9. + + commit 338e6b4647d5ecd42e09e3585213181897982602 + Author: Thomas Köppe + Date: Mon Jul 28 13:46:21 2025 +0100 + + [set.intersection] Fixed transcription errors in return types. + + Declaration error corresponds to 3dcc932d3b28717f5995f26afe9eb851258cf58c. + + The errors in the Returns: follow. + + commit 2d72d926277e2e9abb7caec2a0b8018a98bb99e6 + Author: Thomas Köppe + Date: Mon Jul 28 14:00:09 2025 +0100 + + [algorithm] Remove unnecessary linebreaks for "requires mergeable" + + commit 8421019c09a46f2a76070131bb9b8dbac4e5b962 + Author: Thomas Köppe + Date: Mon Jul 28 14:00:46 2025 +0100 + + [memory.syn] Delete unintended synopsis entry for "destroy_at". + + This seems to have been a mistake in applying P3179R9. + + commit b5d77f4458e8ed83dd0968c54651c23c4cb0f68a + Author: Thomas Köppe + Date: Mon Jul 28 14:39:12 2025 +0100 + + [exec.await.as] Delete stray "}" + + Left over from transforming \tcode into codeblock. + + commit d91106b48d6b8453694a64bce5a0ef84306b82bf + Author: Thomas Köppe + Date: Mon Jul 28 15:04:45 2025 +0100 + + [exec.par.scheduler] Fix extent of definitions + + As per P2079R10. + + commit b9a314f2d8cac8e1df5f2f828b223faaa413f4ab + Author: Thomas Köppe + Date: Mon Jul 28 15:08:11 2025 +0100 + + [exec.snd.expos] Fix typo + + commit 791ff12c615275f6eb1bd5ccaf0f58a2d0f54031 + Author: Giuseppe D'Angelo + Date: Mon Jul 28 22:14:31 2025 +0200 + + [expr.unary.op] Add a note about dereferencing a dangling pointer (#8130) + + Dereferencing a dangling pointer to an object is valid; the resulting + lvalue can be used in limited ways as per [basic.life] p8. + + Add a non-normative note linking the two sections. + + commit 4e79eb8816aa34b19efcdaeef416ed9850127658 + Author: Thomas Köppe + Date: Mon Jul 28 22:26:28 2025 +0100 + + [exec.schedule.from] Fix placement of declaration of "check-types" + + A misapplication of P3557R3. + + commit 511eaa16f93680875878ea7bc74a6c2172237832 + Author: Thomas Köppe + Date: Mon Jul 28 22:29:12 2025 +0100 + + [exec.sync.wait.var] Fix wording + + A misapplication of P3557R3. + + commit 9e25d17d0c62cad16531dd752df75e46552412f5 + Author: Thomas Köppe + Date: Mon Jul 28 22:33:05 2025 +0100 + + [meta.reflection.exception] Fix spelling of "u8what" + + A misapplication of P3560R2. + + commit 8e05e24e431b4706f2ad3e49731ab0b8d7a52459 + Author: Thomas Köppe + Date: Mon Jul 28 22:36:58 2025 +0100 + + [meta.reflection.traits] Missed edit + + A misapplication of P3560R2. + + commit 09a9a4174a1c2fada5e8af38eaa78deaeac9e9cd + Author: Thomas Köppe + Date: Mon Jul 28 22:45:18 2025 +0100 + + [meta.reflection.layout] Turn "Throws:" element into an "all of the following are required" list. + + This restores the meaning of the multiple sentences, which had become + unclear after the "Constant When"-to-"Throws" change. + + commit 884d39bd3539dc837d4869144d677697b7247191 + Author: Thomas Köppe + Date: Mon Jul 28 23:37:01 2025 +0100 + + [future.syn] Remove uses_allocator also from header synopsis. + + P3503R3 didn't actually say this, but it is clearly necessary. + + commit 38ffbee80ca5a0bf5f83cb134697429797d87d9c + Author: Thomas Köppe + Date: Mon Jul 28 23:39:37 2025 +0100 + + [atomics.ref.float] Fix typo + + commit fc6df2dbba6ac42837e42c6ce0ea53cd55ac0e2a + Author: Thomas Köppe + Date: Tue Jul 29 00:42:00 2025 +0100 + + [macros] Add "see above" macros + + commit aaeb987ed4bd09d5d992b20f814f206d63d1c022 + Author: Thomas Köppe + Date: Tue Jul 29 00:42:40 2025 +0100 + + [atomics.types.pointer] Fix parameter type (should be "see above") + + A misapplication of P3111R8. + + commit 102de3e47d27e47421aefc030a8d7facb0568324 + Author: Thomas Köppe + Date: Tue Jul 29 00:47:08 2025 +0100 + + [fs.path.{generic,native}.obs] Escape braces + + commit 0c75091a4a5589455c9d18108b8de56c97336985 + Author: Thomas Köppe + Date: Tue Jul 29 00:52:40 2025 +0100 + + [version.syn] Add missing "freestanding" to feature-test macro + + A misapplication of P2781R9. + + commit d299950f8d2f55f6cde7c43c22eeb3109ff1704c + Author: Thomas Köppe + Date: Tue Jul 29 00:57:04 2025 +0100 + + [meta.rel] Move new paragraph to the correct subclause + + A misapplication of P1317R2. + + commit df1f3f31d8a5f43ec4cfc235753ddceb4e26353f + Author: Thomas Köppe + Date: Tue Jul 29 12:06:27 2025 +0100 + + [task.members] Change template parameter name from "R" to "Rcvr". + + This makes it the same as in the header synopsis. + + commit ce7cc9c4b02476489bbfebcd9d9037ccc79e0125 + Author: Thomas Köppe + Date: Wed Jul 30 15:18:25 2025 +0100 + + [task.state] Fix misplaced \end{itemize} + + commit 77ca407d56faafd591638b11102f33ba1b12aec8 + Author: Thomas Köppe + Date: Wed Jul 30 15:41:55 2025 +0100 + + [basic.splice] The template argument is a parenthesized expression + + commit e15c0955b8c8b129000bc99d848fc54eeb82f74f + Author: Thomas Köppe + Date: Wed Jul 30 15:33:56 2025 +0100 + + [task.promise] Fixes and clarifications in "operator new" spec + + * Change erroneous "Allocator" to "allocator_type". This was + a mistake in the paper (a leftover from a previous revision). + * Locally defined variables are just typeset as normal code, + not as placeholders. + * Some commas inserted to separate coordinate subclauses. + * Replaced "(if any)" with leading "Oherwise", which seems better + in order to avoid seemingly providing two conflicting definitions + of alloc. + * Replaced "Then PAlloc is ..." with "Let PAlloc be ...", which + replaces the (causal vs temporal) ambiguous "then" with the + far more common "let" expression. + + commit e4a7f6da57891013ed378672c470970d95ea190e + Author: Thomas Köppe + Date: Thu Jul 31 15:13:38 2025 +0100 + + [basic.fundamental] Delete repeated cross reference. + + We don't seem to make any cross reference more than once per + subclause. We can revisit this policy, but for now the change + makes the text more consistent in this regard. + + commit 718777332db5157c39cbab50148eeb56a02330f3 + Author: Thomas Köppe + Date: Fri Aug 1 11:11:24 2025 +0100 + + [expr.reflect] Better cross-reference (for "namespace") + + commit c521311f5d61d8558a9c141f7a481196299833a4 + Author: Thomas Köppe + Date: Fri Aug 1 11:13:48 2025 +0100 + + [expr.reflect] Move text out of list item to intended position. + + A mistake in the application of P2996R13. + + commit 5d29e6ddde83dcaebb69e5a215d8956dc399f0d7 + Author: Thomas Köppe + Date: Fri Aug 1 11:24:47 2025 +0100 + + [dcl.typedef] Fix: change semicolon to full stop. + + A miss-edit in the application of P2996R13. + + commit b58eef6e11ff142d083979d6a652d56ab20d4ec1 + Author: Thomas Köppe + Date: Fri Aug 1 11:28:15 2025 +0100 + + [dcl.fct] Fix list continuation. + + A miss-edit in the application of P2996R13. + + commit 6f718357e72f5f5e78dd2f212e66f5b0064a179d + Author: Thomas Köppe + Date: Fri Aug 1 11:45:52 2025 +0100 + + [dcl.init.general] Insert comma before "or array thereof". + + The comma improves the clarity of the binding of "or array thereof", + and was shown in P2996R13, but apparently mistakenly so; it did not + exist in the prior wording. But it is clearly important. + + commit d2654b6dcf8b30a0546d7afb411cd79c66129a24 + Author: Thomas Köppe + Date: Mon Aug 4 10:21:31 2025 +0100 + + [alg.transform] Fix comma that should be a full stop. + + commit 6f496bf27bfdf5e48da3cc288c1c538ab993131e + Author: Thomas Köppe + Date: Mon Aug 4 10:44:07 2025 +0100 + + [alg.partition] Fix "true" that should be "false". + + A misapplication of P3179R9. + + commit 91b4bf8f7a1fb15010b348f3e1552491e01eb396 + Author: Thomas Köppe + Date: Mon Aug 4 10:49:20 2025 +0100 + + [alg.merge] Fix some misapplications of P3179R9. + + commit 8ff31fafa7a3ec0d9ecc991cb3a98ce2abdd9574 + Author: Thomas Köppe + Date: Tue Aug 5 10:26:58 2025 +0100 + + [memory.syn] Fixed misspelled "nothrow-sized-sentinel-for". + + This was a misapplication of P3179R9. + + commit e534fb2676e191b4396184abd81e9882f4437e7c + Author: Thomas Köppe + Date: Tue Aug 5 10:30:31 2025 +0100 + + [special.mem.concepts] Fixed misspelled "sized_sentinel_for". + + This was a misapplication of P3179R9. + + commit c4dd6c83ead14c0081e3009019308c93d5dba55e + Author: Thomas Köppe + Date: Tue Aug 5 12:29:06 2025 +0100 + + [exec.sysctxrepl.psb] Fix typo in range expression + + A misapplication of P2079R10. + + commit f7361435f9909fd260b775a6346c068d50234d16 + Author: Thomas Köppe + Date: Tue Aug 5 12:31:46 2025 +0100 + + [meta.syn] Fix typo "type_underlying_type" => "underlying_type" + + This was an error in P2996R13. + + commit 40101948e00579dd6d551d5383303f37cf1eb9a9 + Author: Thomas Köppe + Date: Tue Aug 5 12:34:08 2025 +0100 + + [tab:meta.reflection.operators] Fix another operator spelling + + Similar to 746811a19a222ffb5e9d03008d752bcb10967ce3, + which missed this one. + + commit ed5362ea20c80d18be106549267a93dba3b3a7c9 + Author: Thomas Köppe + Date: Tue Aug 5 12:37:59 2025 +0100 + + [meta.reflection.queries] Fix "r" that should be "T". + + This is a follow-up to 2567873ea47b7f888f45aa4e8264c9cd3310183d, + which fixed a missing paragraph, but forgot to make this change. + + commit 28c495bef17c305fb8ef6f56b88ae11c6115ccf0 + Author: Thomas Köppe + Date: Tue Aug 5 12:42:24 2025 +0100 + + [meta.reflection.access.context] Fix mistaken qualifier + + A misapplication of P2079R10. + + commit 895e938cfb55d729d016086551f4472621d1722b + Author: Thomas Köppe + Date: Tue Aug 5 12:46:50 2025 +0100 + + [meta.reflection.extract] Reinstate "Constant When" wording from P2996R13 regarding similar and function pointer types + + I'm not sure if the mention of function pointer types was dropped + in a misguided editorial simplification, but this is not an editorial + change. (But we retain the cross-reference which was not in the paper.) + + commit c3bd02a2e44c53c8fe7ba5b48a94bacc9186235d + Author: Thomas Köppe + Date: Tue Aug 5 12:55:17 2025 +0100 + + [meta.reflection.result] Fix function parameter name + + A misapplication of P2996R13. diff --git a/papers/wd-index.md b/papers/wd-index.md index 5ea3d75a59..92100a86b8 100644 --- a/papers/wd-index.md +++ b/papers/wd-index.md @@ -48,3 +48,9 @@ * [N4958](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4958.pdf) 2023-08 C++ Working Draft * [N4964](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4964.pdf) 2023-10 C++ Working Draft * [N4971](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4971.pdf) 2023-12 C++ Working Draft + * [N4981](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4981.pdf) 2024-03 C++ Working Draft + * [N4986](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4986.pdf) 2024-06 C++ Working Draft + * [N4988](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4988.pdf) 2024-08 C++ Working Draft + * [N4993](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4993.pdf) 2024-10 C++ Working Draft + * [N5001](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n5001.pdf) 2024-12 C++ Working Draft + * [N5008](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5008.pdf) 2025-03 C++ Working Draft diff --git a/source/Makefile b/source/Makefile index d4a2ff4064..25fdcf505c 100644 --- a/source/Makefile +++ b/source/Makefile @@ -30,3 +30,12 @@ clean-examples: rm -f $(EXAMPLES) examples: $(EXAMPLES) + +check: .check.stamp + +.check.stamp: ../tools/check-source.sh *.tex + @echo "Running tools/check-source.sh" + @../tools/check-source.sh + @touch $@ + +.PHONY: default refresh refresh full quiet clean-figures figures clean-examples examples check diff --git a/source/algorithms.tex b/source/algorithms.tex index ff4c3b38ed..3867b7cd58 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -12,19 +12,20 @@ non-modifying sequence operations, mutating sequence operations, sorting and related operations, -and algorithms from the ISO C library, +and algorithms from the C library, as summarized in \tref{algorithms.summary}. \begin{libsumtab}{Algorithms library summary}{algorithms.summary} \ref{algorithms.requirements} & Algorithms requirements & \\ -\ref{algorithms.parallel} & Parallel algorithms & \\ \rowsep -\ref{algorithms.results} & Algorithm result types & \tcode{} \\ +\ref{algorithms.parallel} & Parallel algorithms & \tcode{} \\ \rowsep +\ref{algorithms.results} & Algorithm result types & \tcode{} \\ \ref{alg.nonmodifying} & Non-modifying sequence operations & \\ \ref{alg.modifying.operations} & Mutating sequence operations & \\ \ref{alg.sorting} & Sorting and related operations & \\ \rowsep -\ref{numeric.ops} & Generalized numeric operations & \tcode{} \\ \rowsep +\ref{numeric.ops} & Generalized numeric operations & \tcode{} \\ \rowsep \ref{specialized.algorithms} & Specialized \tcode{} algorithms & \tcode{} \\ \rowsep -\ref{alg.c.library} & C library algorithms & \tcode{} \\ +\ref{alg.rand} & Specialized \tcode{} algorithms & \tcode{} \\ \rowsep +\ref{alg.c.library} & C library algorithms & \tcode{} \\ \end{libsumtab} \rSec1[algorithms.requirements]{Algorithms requirements} @@ -37,28 +38,9 @@ satisfying the assumptions on the algorithms. \pnum -The entities defined in the \tcode{std::ranges} namespace in this Clause -are not found by argument-dependent name lookup\iref{basic.lookup.argdep}. -When found by unqualified\iref{basic.lookup.unqual} name lookup -for the \grammarterm{postfix-expression} in a function call\iref{expr.call}, -they inhibit argument-dependent name lookup. - -\begin{example} -\begin{codeblock} -void foo() { - using namespace std::ranges; - std::vector vec{1,2,3}; - find(begin(vec), end(vec), 2); // \#1 -} -\end{codeblock} -The function call expression at \tcode{\#1} invokes \tcode{std::ranges::find}, -not \tcode{std::find}, despite that -(a) the iterator type returned from \tcode{begin(vec)} and \tcode{end(vec)} -may be associated with namespace \tcode{std} and -(b) \tcode{std::find} is more specialized\iref{temp.func.order} than -\tcode{std::ranges::find} since the former requires -its first two parameters to have the same type. -\end{example} +The entities defined in the \tcode{std::ranges} namespace in this Clause and +specified as function templates are +algorithm function objects\iref{alg.func.obj}. \pnum For purposes of determining the existence of data races, @@ -249,6 +231,15 @@ for (auto tmp = b; tmp != a; ++tmp) --n; return n; \end{codeblock} +For each iterator \tcode{i} and sentinel \tcode{s} +produced from a range \tcode{r}, +the semantics of \tcode{s - i} has the same type, value, and value category +as \tcode{ranges::distance(i, s)}. +\begin{note} +The implementation can use \tcode{ranges::distance(r)} +when that produces the same value as \tcode{ranges::\-distance(i, s)}. +This can be more efficient for sized ranges. +\end{note} \pnum In the description of the algorithms, @@ -267,10 +258,19 @@ \pnum Overloads of algorithms that take \libconcept{range} arguments\iref{range.range} -behave as if they are implemented by calling \tcode{ranges::begin} and -\tcode{ranges::end} on the \libconcept{range}(s) and +behave as if they are implemented by dispatching to the overload in namespace \tcode{ranges} -that takes separate iterator and sentinel arguments. +that takes separate iterator and sentinel arguments, +where for each range argument \tcode{r} +\begin{itemize} +\item + a corresponding iterator argument is initialized with \tcode{ranges::begin(r)} and +\item + a corresponding sentinel argument is initialized with \tcode{ranges::end(r)}, + or \tcode{ranges::next(ranges::\brk{}begin(r), ranges::end(r))} + if the type of \tcode{r} models \libconcept{forward_range} + and computing \tcode{ranges::next} meets the specified complexity requirements. +\end{itemize} \pnum The well-formedness and behavior of a call to an algorithm with @@ -290,23 +290,29 @@ \pnum A \defn{parallel algorithm} is a function template listed in this document -with a template parameter named \tcode{ExecutionPolicy}. +with a template parameter named \tcode{ExecutionPolicy} +or constrained by the following exposition-only concept: +\begin{codeblock} +template + concept @\defexposconcept{execution-policy}@ = is_execution_policy_v>; // \expos +\end{codeblock} +Such a template parameter is termed an \defnadj{execution policy}{template parameter}. \pnum -Parallel algorithms access objects indirectly accessible via their arguments +A parallel algorithm accesses objects indirectly accessible via its arguments by invoking the following functions: \begin{itemize} \item - All operations of the categories of the iterators or \tcode{mdspan} types + All operations of the categories of the iterators, sentinels, or \tcode{mdspan} types that the algorithm is instantiated with. \item Operations on those sequence elements that are required by its specification. \item - User-provided function objects + User-provided invocable objects to be applied during the execution of the algorithm, if required by the specification. \item - Operations on those function objects required by the specification. + Operations on those invocable objects required by the specification. \begin{note} See~\ref{algorithms.requirements}. \end{note} @@ -333,7 +339,8 @@ A standard library function is \defn{vectorization-unsafe} if it is specified to synchronize with another function invocation, or another function invocation is specified to synchronize with it, -and if it is not a memory allocation or deallocation function. +and if it is not a memory allocation or deallocation function +or lock-free atomic modify-write operation\iref{atomics.order}. \begin{note} Implementations must ensure that internal synchronization inside standard library functions does not prevent forward progress @@ -362,7 +369,8 @@ \pnum Unless otherwise specified, -function objects passed into parallel algorithms as objects of type +invocable objects passed into parallel algorithms as objects of a type +denoted by a template parameter named \tcode{Predicate}, \tcode{BinaryPredicate}, \tcode{Compare}, @@ -370,8 +378,9 @@ \tcode{BinaryOperation}, \tcode{BinaryOperation1}, \tcode{BinaryOperation2}, -\tcode{BinaryDivideOp}, and -the operators used by the analogous overloads to these parallel algorithms +\tcode{BinaryDivideOp}, or +constrained by a concept that subsumes \libconcept{regular_invocable} +and the operators used by the analogous overloads to these parallel algorithms that are formed by an invocation with the specified default predicate or operation (where applicable) shall not directly or indirectly modify objects via their arguments, @@ -380,10 +389,9 @@ \rSec2[algorithms.parallel.exec]{Effect of execution policies on algorithm execution} \pnum -Parallel algorithms have -template parameters named \tcode{ExecutionPolicy}\iref{execpol} -which describe the manner in which the execution of these algorithms may be -parallelized and the manner in which they apply the element access functions. +An execution policy template parameter describes +the manner in which the execution of a parallel algorithm may be +parallelized and the manner in which it applies the element access functions. \pnum If an object is modified by an element access function, @@ -583,31 +591,31 @@ \pnum During the execution of a parallel algorithm, if the invocation of an element access function exits via an uncaught exception, -the behavior is determined by the \tcode{ExecutionPolicy}. +the behavior is determined by the execution policy. \rSec2[algorithms.parallel.overloads]{\tcode{ExecutionPolicy} algorithm overloads} \pnum Parallel algorithms are algorithm overloads. Each parallel algorithm overload -has an additional template type parameter named \tcode{ExecutionPolicy}, -which is the first template parameter. -Additionally, each parallel algorithm overload -has an additional function parameter of type \tcode{ExecutionPolicy\&\&}, -which is the first function parameter. +has an additional function parameter $P$ of type \tcode{T\&\&} +as the first function parameter, +where \tcode{T} is the execution policy template parameter. \begin{note} Not all algorithms have parallel algorithm overloads. \end{note} \pnum Unless otherwise specified, -the semantics of \tcode{ExecutionPolicy} algorithm overloads -are identical to their overloads without. +the semantics of calling a parallel algorithm overload are identical to +calling the corresponding algorithm overload without the parameter $P$, +using all but the first argument. \pnum Unless otherwise specified, -the complexity requirements of \tcode{ExecutionPolicy} algorithm overloads -are relaxed from the complexity requirements of the overloads without +the complexity requirements of a parallel algorithm overload +are relaxed from the complexity requirements of the corresponding overload +without the parameter $P$ as follows: when the guarantee says ``at most \placeholder{expr}'' or ``exactly \placeholder{expr}'' @@ -616,13 +624,183 @@ the complexity of the algorithm shall be \bigoh{\placeholder{expr}}. \pnum -Parallel algorithms shall not participate in overload resolution unless -\tcode{is_execution_policy_v>} is \tcode{true}. +A parallel algorithm +with a template parameter named \tcode{ExecutionPolicy} +shall not participate in overload resolution unless +that template parameter satisfies \exposconcept{execution-policy}. + +\rSec2[execpol]{Execution policies} + +\rSec3[execpol.general]{General} + +\pnum +Subclause~\ref{execpol} describes classes that are \defn{execution policy} types. An +object of an execution policy type indicates the kinds of parallelism allowed +in the execution of an algorithm and expresses the consequent requirements on +the element access functions. +Execution policy types are declared in header \libheaderref{execution}. +\begin{example} +\begin{codeblock} +using namespace std; +vector v = @\commentellip@; + +// standard sequential sort +sort(v.begin(), v.end()); + +// explicitly sequential sort +sort(execution::seq, v.begin(), v.end()); + +// permitting parallel execution +sort(execution::par, v.begin(), v.end()); + +// permitting vectorization as well +sort(execution::par_unseq, v.begin(), v.end()); +\end{codeblock} +\end{example} +\begin{note} +Implementations can provide additional execution policies +to those described in this document as extensions +to address parallel architectures that require idiosyncratic +parameters for efficient execution. +\end{note} + +\rSec3[execpol.type]{Execution policy type trait} + +\indexlibraryglobal{is_execution_policy}% +\begin{itemdecl} +template struct is_execution_policy; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{is_execution_policy} can be used to detect execution policies for the +purpose of excluding function signatures from otherwise ambiguous overload +resolution participation. + +\pnum +\tcode{is_execution_policy} is a \oldconcept{UnaryTypeTrait} with a +base characteristic of \tcode{true_type} if \tcode{T} is the type of a standard +or \impldef{additional execution policies supported by parallel algorithms} +execution policy, otherwise \tcode{false_type}. + +\begin{note} +This provision reserves the privilege of creating non-standard execution +policies to the library implementation. +\end{note} + +\pnum +The behavior of a program that adds specializations for +\tcode{is_execution_policy} is undefined. +\end{itemdescr} + +\rSec3[execpol.seq]{Sequenced execution policy} + +\indexlibraryglobal{execution::sequenced_policy}% +\begin{itemdecl} +class execution::sequenced_policy { @\unspec@ }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The class \tcode{execution::sequenced_policy} is an execution policy type used +as a unique type to disambiguate parallel algorithm overloading and require +that a parallel algorithm's execution may not be parallelized. + +\pnum +During the execution of a parallel algorithm with +the \tcode{execution::sequenced_policy} policy, +if the invocation of an element access function exits via an exception, +\tcode{terminate} is invoked\iref{except.terminate}. +\end{itemdescr} + +\rSec3[execpol.par]{Parallel execution policy} + +\indexlibraryglobal{execution::parallel_policy}% +\begin{itemdecl} +class execution::parallel_policy { @\unspec@ }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The class \tcode{execution::parallel_policy} is an execution policy type used as +a unique type to disambiguate parallel algorithm overloading and indicate that +a parallel algorithm's execution may be parallelized. + +\pnum +During the execution of a parallel algorithm with +the \tcode{execution::parallel_policy} policy, +if the invocation of an element access function exits via an exception, +\tcode{terminate} is invoked\iref{except.terminate}. +\end{itemdescr} + +\rSec3[execpol.parunseq]{Parallel and unsequenced execution policy} + +\indexlibraryglobal{execution::parallel_unsequenced_policy}% +\begin{itemdecl} +class execution::parallel_unsequenced_policy { @\unspec@ }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The class \tcode{execution::parallel_unsequenced_policy} is an execution policy type +used as a unique type to disambiguate parallel algorithm overloading and +indicate that a parallel algorithm's execution may be parallelized and +vectorized. + +\pnum +During the execution of a parallel algorithm with +the \tcode{execution::parallel_unsequenced_policy} policy, +if the invocation of an element access function exits via an exception, +\tcode{terminate} is invoked\iref{except.terminate}. +\end{itemdescr} + +\rSec3[execpol.unseq]{Unsequenced execution policy} + +\indexlibraryglobal{execution::unsequenced_policy}% +\begin{itemdecl} +class execution::unsequenced_policy { @\unspec@ }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The class \tcode{unsequenced_policy} is an execution policy type +used as a unique type to disambiguate parallel algorithm overloading and +indicate that a parallel algorithm's execution may be vectorized, +e.g., executed on a single thread using instructions +that operate on multiple data items. + +\pnum +During the execution of a parallel algorithm with +the \tcode{execution::unsequenced_policy} policy, +if the invocation of an element access function exits via an exception, +\tcode{terminate} is invoked\iref{except.terminate}. +\end{itemdescr} + +\rSec3[execpol.objects]{Execution policy objects} + +\indexlibraryglobal{seq}% +\indexlibraryglobal{par}% +\indexlibraryglobal{par_unseq}% +\indexlibrarymember{execution}{seq}% +\indexlibrarymember{execution}{par}% +\indexlibrarymember{execution}{par_unseq}% +\begin{itemdecl} +inline constexpr execution::sequenced_policy execution::seq{ @\unspec@ }; +inline constexpr execution::parallel_policy execution::par{ @\unspec@ }; +inline constexpr execution::parallel_unsequenced_policy execution::par_unseq{ @\unspec@ }; +inline constexpr execution::unsequenced_policy execution::unseq{ @\unspec@ }; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The header \libheaderref{execution} declares global objects associated with each type of execution policy. +\end{itemdescr} \rSec1[algorithm.syn]{Header \tcode{} synopsis} \indexheader{algorithm}% \begin{codeblock} +// mostly freestanding #include // see \ref{initializer.list.syn} namespace std { @@ -661,7 +839,7 @@ template constexpr bool all_of(InputIterator first, InputIterator last, Predicate pred); template - bool all_of(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool all_of(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { @@ -671,13 +849,20 @@ template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr bool all_of(R&& r, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + bool all_of(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + bool all_of(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // freestanding-deleted } // \ref{alg.any.of}, any of template constexpr bool any_of(InputIterator first, InputIterator last, Predicate pred); template - bool any_of(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool any_of(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { @@ -687,13 +872,20 @@ template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr bool any_of(R&& r, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + bool any_of(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + bool any_of(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // freestanding-deleted } // \ref{alg.none.of}, none of template constexpr bool none_of(InputIterator first, InputIterator last, Predicate pred); template - bool none_of(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool none_of(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { @@ -703,18 +895,38 @@ template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr bool none_of(R&& r, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + bool none_of(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + bool none_of(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // freestanding-deleted } // \ref{alg.contains}, contains namespace ranges { - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr bool contains(I first, S last, const T& value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T, class Proj = identity> + template<@\libconcept{input_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr bool contains(R&& r, const T& value, Proj proj = {}); + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T = projected_value_t> + requires @\libconcept{indirect_binary_predicate}@, const T*> + bool contains(Ep&& exec, I first, S last, const T& value, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> + requires + @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + bool contains(Ep&& exec, R&& r, const T& value, Proj proj = {}); // freestanding-deleted + template<@\libconcept{forward_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{forward_iterator}@ I2, @\libconcept{sentinel_for}@ S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> @@ -726,18 +938,30 @@ requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> constexpr bool contains_subrange(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + bool contains_subrange(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + bool contains_subrange(Ep&& exec, R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, + Proj2 proj2 = {}); // freestanding-deleted } // \ref{alg.foreach}, for each template constexpr Function for_each(InputIterator first, InputIterator last, Function f); template - void for_each(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + void for_each(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Function f); namespace ranges { template - using for_each_result = in_fun_result; + using @\libglobal{for_each_result}@ = in_fun_result; template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirectly_unary_invocable}@> Fun> @@ -747,56 +971,85 @@ @\libconcept{indirectly_unary_invocable}@, Proj>> Fun> constexpr for_each_result, Fun> for_each(R&& r, Fun f, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirectly_unary_invocable}@> Fun> + I for_each(Ep&& exec, I first, S last, Fun f, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirectly_unary_invocable}@, Proj>> Fun> + borrowed_iterator_t + for_each(Ep&& exec, R&& r, Fun f, Proj proj = {}); // freestanding-deleted } template constexpr InputIterator for_each_n(InputIterator first, Size n, Function f); template - ForwardIterator for_each_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator for_each_n(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, Size n, Function f); namespace ranges { template - using for_each_n_result = in_fun_result; + using @\libglobal{for_each_n_result}@ = in_fun_result; template<@\libconcept{input_iterator}@ I, class Proj = identity, @\libconcept{indirectly_unary_invocable}@> Fun> constexpr for_each_n_result for_each_n(I first, iter_difference_t n, Fun f, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, class Proj = identity, + @\libconcept{indirectly_unary_invocable}@> Fun> + I for_each_n(Ep&& exec, I first, iter_difference_t n, Fun f, + Proj proj = {}); // freestanding-deleted } // \ref{alg.find}, find - template + template::value_type> constexpr InputIterator find(InputIterator first, InputIterator last, const T& value); - template - ForwardIterator find(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + template::value_type> + ForwardIterator find(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, const T& value); template constexpr InputIterator find_if(InputIterator first, InputIterator last, Predicate pred); template - ForwardIterator find_if(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator find_if(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Predicate pred); template constexpr InputIterator find_if_not(InputIterator first, InputIterator last, Predicate pred); template - ForwardIterator find_if_not(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator find_if_not(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr I find(I first, S last, const T& value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T, class Proj = identity> + template<@\libconcept{input_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr borrowed_iterator_t find(R&& r, const T& value, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T = projected_value_t> + requires @\libconcept{indirect_binary_predicate}@, const T*> + I find(Ep&& exec, I first, S last, const T& value, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> + requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + borrowed_iterator_t + find(Ep&& exec, R&& r, const T& value, Proj proj = {}); // freestanding-deleted + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> constexpr I find_if(I first, S last, Pred pred, Proj proj = {}); @@ -804,6 +1057,15 @@ @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr borrowed_iterator_t find_if(R&& r, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + I find_if(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + borrowed_iterator_t + find_if(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // freestanding-deleted + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> constexpr I find_if_not(I first, S last, Pred pred, Proj proj = {}); @@ -811,29 +1073,76 @@ @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr borrowed_iterator_t find_if_not(R&& r, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + I find_if_not(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + borrowed_iterator_t + find_if_not(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // freestanding-deleted } // \ref{alg.find.last}, find last namespace ranges { - template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr subrange find_last(I first, S last, const T& value, Proj proj = {}); - template<@\libconcept{forward_range}@ R, class T, class Proj = identity> + template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr borrowed_subrange_t find_last(R&& r, const T& value, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T = projected_value_t> + requires @\libconcept{indirect_binary_predicate}@, const T*> + subrange + find_last(Ep&& exec, I first, S last, const T& value, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> + requires + @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + borrowed_subrange_t + find_last(Ep&& exec, R&& r, const T& value, Proj proj = {}); // freestanding-deleted + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> constexpr subrange find_last_if(I first, S last, Pred pred, Proj proj = {}); template<@\libconcept{forward_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr borrowed_subrange_t find_last_if(R&& r, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + subrange + find_last_if(Ep&& exec, I first, S last, Pred pred, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, + class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + borrowed_subrange_t + find_last_if(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // freestanding-deleted + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> constexpr subrange find_last_if_not(I first, S last, Pred pred, Proj proj = {}); template<@\libconcept{forward_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr borrowed_subrange_t find_last_if_not(R&& r, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_unary_predicate}@> Pred> + subrange + find_last_if_not(Ep&& exec, I first, S last, Pred pred, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + borrowed_subrange_t + find_last_if_not(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // freestanding-deleted } // \ref{alg.find.end}, find end @@ -848,13 +1157,13 @@ BinaryPredicate pred); template ForwardIterator1 - find_end(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + find_end(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template ForwardIterator1 - find_end(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + find_end(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); @@ -872,6 +1181,20 @@ constexpr borrowed_subrange_t find_end(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + subrange + find_end(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + borrowed_subrange_t + find_end(Ep&& exec, R1&& r1, R2&& r2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } // \ref{alg.find.first.of}, find first @@ -886,13 +1209,13 @@ BinaryPredicate pred); template ForwardIterator1 - find_first_of(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + find_first_of(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template ForwardIterator1 - find_first_of(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + find_first_of(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); @@ -909,6 +1232,19 @@ constexpr borrowed_iterator_t find_first_of(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + I1 find_first_of(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + borrowed_iterator_t + find_first_of(Ep&& exec, R1&& r1, R2&& r2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } // \ref{alg.adjacent.find}, adjacent find @@ -921,11 +1257,11 @@ BinaryPredicate pred); template ForwardIterator - adjacent_find(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + adjacent_find(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last); template ForwardIterator - adjacent_find(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + adjacent_find(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, BinaryPredicate pred); @@ -940,34 +1276,62 @@ projected, Proj>> Pred = ranges::equal_to> constexpr borrowed_iterator_t adjacent_find(R&& r, Pred pred = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_binary_predicate}@, + projected> Pred = ranges::equal_to> + I adjacent_find(Ep&& exec, I first, S last, Pred pred = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_binary_predicate}@, Proj>, + projected, Proj>> Pred = ranges::equal_to> + borrowed_iterator_t + adjacent_find(Ep&& exec, R&& r, Pred pred = {}, Proj proj = {}); // freestanding-deleted } // \ref{alg.count}, count - template + template::value_type> constexpr typename iterator_traits::difference_type count(InputIterator first, InputIterator last, const T& value); - template + template::value_type> typename iterator_traits::difference_type - count(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + count(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, const T& value); template constexpr typename iterator_traits::difference_type count_if(InputIterator first, InputIterator last, Predicate pred); template typename iterator_traits::difference_type - count_if(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + count_if(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr iter_difference_t count(I first, S last, const T& value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T, class Proj = identity> + template<@\libconcept{input_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr range_difference_t count(R&& r, const T& value, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T = projected_value_t> + requires @\libconcept{indirect_binary_predicate}@, const T*> + iter_difference_t + count(Ep&& exec, I first, S last, const T& value, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> + requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + range_difference_t + count(Ep&& exec, R&& r, const T& value, Proj proj = {}); // freestanding-deleted + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> constexpr iter_difference_t @@ -976,6 +1340,15 @@ @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr range_difference_t count_if(R&& r, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + iter_difference_t + count_if(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + range_difference_t + count_if(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // freestanding-deleted } // \ref{alg.mismatch}, mismatch @@ -998,31 +1371,31 @@ BinaryPredicate pred); template pair - mismatch(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + mismatch(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template pair - mismatch(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + mismatch(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred); template pair - mismatch(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + mismatch(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template pair - mismatch(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + mismatch(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); namespace ranges { template - using mismatch_result = in_in_result; + using @\libglobal{mismatch_result}@ = in_in_result; template<@\libconcept{input_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{input_iterator}@ I2, @\libconcept{sentinel_for}@ S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> @@ -1036,6 +1409,20 @@ constexpr mismatch_result, borrowed_iterator_t> mismatch(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + mismatch_result + mismatch(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + mismatch_result, borrowed_iterator_t> + mismatch(Ep&& exec, R1&& r1, R2&& r2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } // \ref{alg.equal}, equal @@ -1053,21 +1440,21 @@ InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred); template - bool equal(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool equal(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template - bool equal(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool equal(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred); template - bool equal(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool equal(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template - bool equal(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool equal(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); @@ -1084,6 +1471,18 @@ requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> constexpr bool equal(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + bool equal(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + bool equal(Ep&& exec, R1&& r1, R2&& r2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } // \ref{alg.is.permutation}, is permutation @@ -1130,13 +1529,13 @@ BinaryPredicate pred); template ForwardIterator1 - search(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + search(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template ForwardIterator1 - search(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + search(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); @@ -1155,42 +1554,74 @@ constexpr borrowed_subrange_t search(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + subrange + search(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + borrowed_subrange_t + search(Ep&& exec, R1&& r1, R2&& r2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } - template + template::value_type> constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value); - template + template::value_type, class BinaryPredicate> constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred); - template + template::value_type> ForwardIterator - search_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + search_n(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Size count, const T& value); - template + template::value_type, class BinaryPredicate> ForwardIterator - search_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + search_n(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred); namespace ranges { - template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, - class Pred = ranges::equal_to, class Proj = identity> + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, + class Pred = ranges::equal_to, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirectly_comparable}@ constexpr subrange search_n(I first, S last, iter_difference_t count, const T& value, Pred pred = {}, Proj proj = {}); - template<@\libconcept{forward_range}@ R, class T, class Pred = ranges::equal_to, - class Proj = identity> + template<@\libconcept{forward_range}@ R, class Pred = ranges::equal_to, + class Proj = identity, class T = projected_value_t> requires @\libconcept{indirectly_comparable}@, const T*, Pred, Proj> constexpr borrowed_subrange_t search_n(R&& r, range_difference_t count, const T& value, Pred pred = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Pred = ranges::equal_to, class Proj = identity, + class T = projected_value_t> + requires @\libconcept{indirectly_comparable}@ + subrange + search_n(Ep&& exec, I first, S last, iter_difference_t count, + const T& value, Pred pred = {}, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Pred = ranges::equal_to, + class Proj = identity, class T = projected_value_t, Proj>> + requires @\libconcept{indirectly_comparable}@, const T*, Pred, Proj> + borrowed_subrange_t + search_n(Ep&& exec, R&& r, range_difference_t count, + const T& value, Pred pred = {}, Proj proj = {}); // freestanding-deleted } template @@ -1210,6 +1641,19 @@ constexpr bool starts_with(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + bool starts_with(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, + @\exposconcept{sized-random-access-range}@ R2, class Pred = ranges::equal_to, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + bool starts_with(Ep&& exec, R1&& r1, R2&& r2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + // \ref{alg.ends.with}, ends with template<@\libconcept{input_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{input_iterator}@ I2, @\libconcept{sentinel_for}@ S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> @@ -1226,6 +1670,19 @@ constexpr bool ends_with(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + bool ends_with(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, + @\exposconcept{sized-random-access-range}@ R2, class Pred = ranges::equal_to, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + bool ends_with(Ep&& exec, R1&& r1, R2&& r2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + // \ref{alg.fold}, fold template class @\exposid{flipped}@ { // \expos @@ -1255,11 +1712,12 @@ concept @\defexposconcept{indirectly-binary-right-foldable}@ = // \expos @\exposconcept{indirectly-binary-left-foldable}@<@\exposid{flipped}@, T, I>; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T = iter_value_t, @\exposconcept{indirectly-binary-left-foldable}@ F> constexpr auto fold_left(I first, S last, T init, F f); - template<@\libconcept{input_range}@ R, class T, @\exposconcept{indirectly-binary-left-foldable}@> F> + template<@\libconcept{input_range}@ R, class T = range_value_t, + @\exposconcept{indirectly-binary-left-foldable}@> F> constexpr auto fold_left(R&& r, T init, F f); template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @@ -1271,18 +1729,18 @@ requires @\libconcept{constructible_from}@, range_reference_t> constexpr auto fold_left_first(R&& r, F f); - template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, + template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class T = iter_value_t, @\exposconcept{indirectly-binary-right-foldable}@ F> constexpr auto fold_right(I first, S last, T init, F f); - template<@\libconcept{bidirectional_range}@ R, class T, + template<@\libconcept{bidirectional_range}@ R, class T = range_value_t, @\exposconcept{indirectly-binary-right-foldable}@> F> constexpr auto fold_right(R&& r, T init, F f); template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, @\exposconcept{indirectly-binary-right-foldable}@, I> F> requires @\libconcept{constructible_from}@, iter_reference_t> - constexpr auto fold_right_last(I first, S last, F f); + constexpr auto fold_right_last(I first, S last, F f); template<@\libconcept{bidirectional_range}@ R, @\exposconcept{indirectly-binary-right-foldable}@, iterator_t> F> @@ -1290,15 +1748,16 @@ constexpr auto fold_right_last(R&& r, F f); template - using fold_left_with_iter_result = in_value_result; + using @\libglobal{fold_left_with_iter_result}@ = in_value_result; template - using fold_left_first_with_iter_result = in_value_result; + using @\libglobal{fold_left_first_with_iter_result}@ = in_value_result; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T = iter_value_t, @\exposconcept{indirectly-binary-left-foldable}@ F> constexpr @\seebelow@ fold_left_with_iter(I first, S last, T init, F f); - template<@\libconcept{input_range}@ R, class T, @\exposconcept{indirectly-binary-left-foldable}@> F> + template<@\libconcept{input_range}@ R, class T = range_value_t, + @\exposconcept{indirectly-binary-left-foldable}@> F> constexpr @\seebelow@ fold_left_with_iter(R&& r, T init, F f); template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @@ -1318,13 +1777,13 @@ constexpr OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result); template - ForwardIterator2 copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator2 copy(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); namespace ranges { template - using copy_result = in_out_result; + using @\libglobal{copy_result}@ = in_out_result; template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O> requires @\libconcept{indirectly_copyable}@ @@ -1334,6 +1793,16 @@ requires @\libconcept{indirectly_copyable}@, O> constexpr copy_result, O> copy(R&& r, O result); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS> + requires @\libconcept{indirectly_copyable}@ + copy_result + copy(Ep&& exec, I first, S last, O result, OutS result_last); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR> + requires @\libconcept{indirectly_copyable}@, iterator_t> + copy_result, borrowed_iterator_t> + copy(Ep&& exec, R&& r, OutR&& result_r); // freestanding-deleted } template @@ -1341,18 +1810,25 @@ OutputIterator result); template - ForwardIterator2 copy_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator2 copy_n(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, Size n, ForwardIterator2 result); namespace ranges { template - using copy_n_result = in_out_result; + using @\libglobal{copy_n_result}@ = in_out_result; template<@\libconcept{input_iterator}@ I, @\libconcept{weakly_incrementable}@ O> requires @\libconcept{indirectly_copyable}@ constexpr copy_n_result copy_n(I first, iter_difference_t n, O result); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{random_access_iterator}@ O, + @\libconcept{sized_sentinel_for}@ OutS> + requires @\libconcept{indirectly_copyable}@ + copy_n_result + copy_n(Ep&& exec, I first, iter_difference_t n, O result, + OutS result_last); // freestanding-deleted } template @@ -1360,13 +1836,13 @@ OutputIterator result, Predicate pred); template - ForwardIterator2 copy_if(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator2 copy_if(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred); namespace ranges { template - using copy_if_result = in_out_result; + using @\libglobal{copy_if_result}@ = in_out_result; template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> @@ -1378,6 +1854,21 @@ requires @\libconcept{indirectly_copyable}@, O> constexpr copy_if_result, O> copy_if(R&& r, O result, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{indirectly_copyable}@ + copy_if_result + copy_if(Ep&& exec, I first, S last, O result, OutS result_last, + Pred pred, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{indirectly_copyable}@, iterator_t> + copy_if_result, borrowed_iterator_t> + copy_if(Ep&& exec, R&& r, OutR&& result_r, Pred pred, + Proj proj = {}); // freestanding-deleted } template @@ -1387,7 +1878,7 @@ namespace ranges { template - using copy_backward_result = in_out_result; + using @\libglobal{copy_backward_result}@ = in_out_result; template<@\libconcept{bidirectional_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{bidirectional_iterator}@ I2> requires @\libconcept{indirectly_copyable}@ @@ -1405,13 +1896,13 @@ OutputIterator result); template - ForwardIterator2 move(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator2 move(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); namespace ranges { template - using move_result = in_out_result; + using @\libglobal{move_result}@ = in_out_result; template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O> requires @\libconcept{indirectly_movable}@ @@ -1421,6 +1912,16 @@ requires @\libconcept{indirectly_movable}@, O> constexpr move_result, O> move(R&& r, O result); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS> + requires @\libconcept{indirectly_movable}@ + move_result + move(Ep&& exec, I first, S last, O result, OutS result_last); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR> + requires @\libconcept{indirectly_movable}@, iterator_t> + move_result, borrowed_iterator_t> + move(Ep&& exec, R&& r, OutR&& result_r); // freestanding-deleted } template @@ -1430,7 +1931,7 @@ namespace ranges { template - using move_backward_result = in_out_result; + using @\libglobal{move_backward_result}@ = in_out_result; template<@\libconcept{bidirectional_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{bidirectional_iterator}@ I2> requires @\libconcept{indirectly_movable}@ @@ -1447,13 +1948,13 @@ constexpr ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template - ForwardIterator2 swap_ranges(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator2 swap_ranges(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); namespace ranges { template - using swap_ranges_result = in_in_result; + using @\libglobal{swap_ranges_result}@ = in_in_result; template<@\libconcept{input_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{input_iterator}@ I2, @\libconcept{sentinel_for}@ S2> requires @\libconcept{indirectly_swappable}@ @@ -1463,6 +1964,16 @@ requires @\libconcept{indirectly_swappable}@, iterator_t> constexpr swap_ranges_result, borrowed_iterator_t> swap_ranges(R1&& r1, R2&& r2); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2> + requires @\libconcept{indirectly_swappable}@ + swap_ranges_result + swap_ranges(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2> + requires @\libconcept{indirectly_swappable}@, iterator_t> + swap_ranges_result, borrowed_iterator_t> + swap_ranges(Ep&& exec, R1&& r1, R2&& r2); // freestanding-deleted } template @@ -1482,20 +1993,20 @@ template ForwardIterator2 - transform(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + transform(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 result, UnaryOperation op); template ForwardIterator - transform(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + transform(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator result, BinaryOperation binary_op); namespace ranges { template - using unary_transform_result = in_out_result; + using @\libglobal{unary_transform_result}@ = in_out_result; template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O, @\libconcept{copy_constructible}@ F, class Proj = identity> @@ -1508,63 +2019,134 @@ constexpr unary_transform_result, O> transform(R&& r, O result, F op, Proj proj = {}); + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, + @\libconcept{copy_constructible}@ F, class Proj = identity> + requires @\libconcept{indirectly_writable}@>> + unary_transform_result + transform(Ep&& exec, I first1, S last1, O result, OutS result_last, + F op, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + @\libconcept{copy_constructible}@ F, class Proj = identity> + requires @\libconcept{indirectly_writable}@, + indirect_result_t, Proj>>> + unary_transform_result, borrowed_iterator_t> + transform(Ep&& exec, R&& r, OutR&& result_r, F op, Proj proj = {}); // freestanding-deleted + template - using binary_transform_result = in_in_out_result; + using @\libglobal{binary_transform_result}@ = in_in_out_result; template<@\libconcept{input_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{input_iterator}@ I2, @\libconcept{sentinel_for}@ S2, @\libconcept{weakly_incrementable}@ O, @\libconcept{copy_constructible}@ F, class Proj1 = identity, class Proj2 = identity> requires @\libconcept{indirectly_writable}@, - projected>> + projected>> constexpr binary_transform_result transform(I1 first1, S1 last1, I2 first2, S2 last2, O result, F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); template<@\libconcept{input_range}@ R1, @\libconcept{input_range}@ R2, @\libconcept{weakly_incrementable}@ O, @\libconcept{copy_constructible}@ F, class Proj1 = identity, class Proj2 = identity> requires @\libconcept{indirectly_writable}@, Proj1>, - projected, Proj2>>> + projected, Proj2>>> constexpr binary_transform_result, borrowed_iterator_t, O> transform(R1&& r1, R2&& r2, O result, F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, + @\libconcept{copy_constructible}@ F, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_writable}@, + projected>> + binary_transform_result + transform(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + O result, OutS result_last, + F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + @\exposconcept{sized-random-access-range}@ OutR, @\libconcept{copy_constructible}@ F, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_writable}@, + indirect_result_t, Proj1>, + projected, Proj2>>> + binary_transform_result, borrowed_iterator_t, + borrowed_iterator_t> + transform(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, + F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } // \ref{alg.replace}, replace template constexpr void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); - template - void replace(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + template::value_type> + void replace(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); - template + template::value_type> constexpr void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); - template - void replace_if(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + template::value_type> + void replace_if(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); namespace ranges { - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T1, class T2, class Proj = identity> + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T1 = projected_value_t, class T2 = T1> requires @\libconcept{indirectly_writable}@ && @\libconcept{indirect_binary_predicate}@, const T1*> constexpr I replace(I first, S last, const T1& old_value, const T2& new_value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T1, class T2, class Proj = identity> + template<@\libconcept{input_range}@ R, class Proj = identity, + class T1 = projected_value_t, Proj>, class T2 = T1> requires @\libconcept{indirectly_writable}@, const T2&> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> constexpr borrowed_iterator_t replace(R&& r, const T1& old_value, const T2& new_value, Proj proj = {}); - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T1 = projected_value_t, class T2 = T1> + requires @\libconcept{indirectly_writable}@ && + @\libconcept{indirect_binary_predicate}@, const T1*> + I replace(Ep&& exec, I first, S last, + const T1& old_value, const T2& new_value, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T1 = projected_value_t, Proj>, class T2 = T1> + requires @\libconcept{indirectly_writable}@, const T2&> && + @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> + borrowed_iterator_t + replace(Ep&& exec, R&& r, const T1& old_value, const T2& new_value, + Proj proj = {}); // freestanding-deleted + + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{indirectly_writable}@ constexpr I replace_if(I first, S last, Pred pred, const T& new_value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T, class Proj = identity, + template<@\libconcept{input_range}@ R, class Proj = identity, class T = projected_value_t, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_writable}@, const T&> constexpr borrowed_iterator_t replace_if(R&& r, Pred pred, const T& new_value, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T = projected_value_t, + @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{indirectly_writable}@ + I replace_if(Ep&& exec, I first, S last, Pred pred, + const T& new_value, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{indirectly_writable}@, const T&> + borrowed_iterator_t + replace_if(Ep&& exec, R&& r, Pred pred, const T& new_value, + Proj proj = {}); // freestanding-deleted } template @@ -1572,78 +2154,135 @@ OutputIterator result, const T& old_value, const T& new_value); template - ForwardIterator2 replace_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator2 replace_copy(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& old_value, const T& new_value); - template + template::value_type> constexpr OutputIterator replace_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred, const T& new_value); template - ForwardIterator2 replace_copy_if(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + class Predicate, class T = iterator_traits::value_type> + ForwardIterator2 replace_copy_if(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred, const T& new_value); namespace ranges { template - using replace_copy_result = in_out_result; + using @\libglobal{replace_copy_result}@ = in_out_result; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T1, class T2, - @\libconcept{output_iterator}@ O, class Proj = identity> + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class O, + class Proj = identity, + class T1 = projected_value_t, class T2 = iter_value_t> requires @\libconcept{indirectly_copyable}@ && - @\libconcept{indirect_binary_predicate}@, const T1*> + @\libconcept{indirect_binary_predicate}@, const T1*> && + @\libconcept{output_iterator}@ constexpr replace_copy_result replace_copy(I first, S last, O result, const T1& old_value, const T2& new_value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T1, class T2, @\libconcept{output_iterator}@ O, - class Proj = identity> + template<@\libconcept{input_range}@ R, class O, class Proj = identity, + class T1 = projected_value_t, Proj>, class T2 = iter_value_t> requires @\libconcept{indirectly_copyable}@, O> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> + projected, Proj>, const T1*> && + @\libconcept{output_iterator}@ constexpr replace_copy_result, O> replace_copy(R&& r, O result, const T1& old_value, const T2& new_value, Proj proj = {}); + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, + class Proj = identity, + class T1 = projected_value_t, class T2 = iter_value_t> + requires @\libconcept{indirectly_copyable}@ && + @\libconcept{indirect_binary_predicate}@, const T1*> && + @\libconcept{indirectly_writable}@ + replace_copy_result + replace_copy(Ep&& exec, I first, S last, O result, OutS result_last, const T1& old_value, + const T2& new_value, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + class Proj = identity, class T1 = projected_value_t, Proj>, + class T2 = range_value_t> + requires @\libconcept{indirectly_copyable}@, iterator_t> && + @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> && + @\libconcept{indirectly_writable}@, const T2&> + replace_copy_result, borrowed_iterator_t> + replace_copy(Ep&& exec, R&& r, OutR&& result_r, const T1& old_value, const T2& new_value, + Proj proj = {}); // freestanding-deleted + template - using replace_copy_if_result = in_out_result; + using @\libglobal{replace_copy_if_result}@ = in_out_result; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, @\libconcept{output_iterator}@ O, + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class O, class T = iter_value_t class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> - requires @\libconcept{indirectly_copyable}@ + requires @\libconcept{indirectly_copyable}@ && @\libconcept{output_iterator}@ constexpr replace_copy_if_result replace_copy_if(I first, S last, O result, Pred pred, const T& new_value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class T, @\libconcept{output_iterator}@ O, class Proj = identity, + template<@\libconcept{input_range}@ R, class O, class T = iter_value_t, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> - requires @\libconcept{indirectly_copyable}@, O> + requires @\libconcept{indirectly_copyable}@, O> && @\libconcept{output_iterator}@ constexpr replace_copy_if_result, O> replace_copy_if(R&& r, O result, Pred pred, const T& new_value, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class T = iter_value_t, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{indirectly_copyable}@ && @\libconcept{indirectly_writable}@ + replace_copy_if_result + replace_copy_if(Ep&& exec, I first, S last, O result, OutS result_last, + Pred pred, const T& new_value, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + class T = range_value_t, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{indirectly_copyable}@, iterator_t> && + @\libconcept{indirectly_writable}@, const T&> + replace_copy_if_result, borrowed_iterator_t> + replace_copy_if(Ep&& exec, R&& r, OutR&& result_r, Pred pred, const T& new_value, + Proj proj = {}); // freestanding-deleted } // \ref{alg.fill}, fill - template + template::value_type> constexpr void fill(ForwardIterator first, ForwardIterator last, const T& value); - template - void fill(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + template::value_type> + void fill(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, const T& value); - template - constexpr OutputIterator fill_n(OutputIterator first, Size n, const T& value); // freestanding + template::value_type> + constexpr OutputIterator fill_n(OutputIterator first, Size n, const T& value) template - ForwardIterator fill_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + class Size, class T = iterator_traits::value_type> + ForwardIterator fill_n(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, Size n, const T& value); namespace ranges { - template O, @\libconcept{sentinel_for}@ S> + template S, class T = iter_value_t> + requires @\libconcept{output_iterator}@ constexpr O fill(O first, S last, const T& value); - template R> + template> + requires @\libconcept{output_range}@ constexpr borrowed_iterator_t fill(R&& r, const T& value); - template O> + template> + requires @\libconcept{output_iterator}@ constexpr O fill_n(O first, iter_difference_t n, const T& value); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ S, + class T = iter_value_t> + requires @\libconcept{indirectly_writable}@ + O fill(Ep&& exec, O first, S last, const T& value); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class T = range_value_t> + requires @\libconcept{indirectly_writable}@, const T&> + borrowed_iterator_t fill(Ep&& exec, R&& r, const T& value); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ O, class T = iter_value_t> + requires @\libconcept{indirectly_writable}@ + O fill_n(Ep&& exec, O first, iter_difference_t n, const T& value); // freestanding-deleted } // \ref{alg.generate}, generate @@ -1651,13 +2290,13 @@ constexpr void generate(ForwardIterator first, ForwardIterator last, Generator gen); template - void generate(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + void generate(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Generator gen); template constexpr OutputIterator generate_n(OutputIterator first, Size n, Generator gen); template - ForwardIterator generate_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator generate_n(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, Size n, Generator gen); namespace ranges { @@ -1670,34 +2309,61 @@ template<@\libconcept{input_or_output_iterator}@ O, @\libconcept{copy_constructible}@ F> requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@> constexpr O generate_n(O first, iter_difference_t n, F gen); + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{copy_constructible}@ F> + requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@> + O generate(Ep&& exec, O first, S last, F gen); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\libconcept{copy_constructible}@ F> + requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@, invoke_result_t> + borrowed_iterator_t generate(Ep&& exec, R&& r, F gen); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ O, @\libconcept{copy_constructible}@ F> + requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@> + O generate_n(Ep&& exec, O first, iter_difference_t n, F gen); // freestanding-deleted } // \ref{alg.remove}, remove - template + template::value_type> constexpr ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value); - template - ForwardIterator remove(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + template::value_type> + ForwardIterator remove(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, const T& value); template constexpr ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, Predicate pred); template - ForwardIterator remove_if(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator remove_if(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { - template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> + template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr subrange remove(I first, S last, const T& value, Proj proj = {}); - template<@\libconcept{forward_range}@ R, class T, class Proj = identity> + template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{permutable}@> && @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr borrowed_subrange_t remove(R&& r, const T& value, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T = projected_value_t> + requires @\libconcept{indirect_binary_predicate}@, const T*> + subrange remove(Ep&& exec, I first, S last, const T& value, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> + requires @\libconcept{permutable}@> && + @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + borrowed_subrange_t + remove(Ep&& exec, R&& r, const T& value, Proj proj = {}); // freestanding-deleted + template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> constexpr subrange remove_if(I first, S last, Pred pred, Proj proj = {}); @@ -1706,16 +2372,27 @@ requires @\libconcept{permutable}@> constexpr borrowed_subrange_t remove_if(R&& r, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + subrange + remove_if(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{permutable}@> + borrowed_subrange_t + remove_if(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // freestanding-deleted } - template + template::value_type> constexpr OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value); template + class T = iterator_traits::value_type> ForwardIterator2 - remove_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + remove_copy(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& value); template @@ -1725,29 +2402,47 @@ template ForwardIterator2 - remove_copy_if(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + remove_copy_if(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred); namespace ranges { template - using remove_copy_result = in_out_result; + using @\libglobal{remove_copy_result}@ = in_out_result; - template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O, class T, - class Proj = identity> + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O, + class Proj = identity, class T = projected_value_t> requires @\libconcept{indirectly_copyable}@ && @\libconcept{indirect_binary_predicate}@, const T*> constexpr remove_copy_result remove_copy(I first, S last, O result, const T& value, Proj proj = {}); - template<@\libconcept{input_range}@ R, @\libconcept{weakly_incrementable}@ O, class T, class Proj = identity> + template<@\libconcept{input_range}@ R, @\libconcept{weakly_incrementable}@ O, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{indirectly_copyable}@, O> && @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr remove_copy_result, O> remove_copy(R&& r, O result, const T& value, Proj proj = {}); + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, + class Proj = identity, class T = projected_value_t> + requires @\libconcept{indirectly_copyable}@ && + @\libconcept{indirect_binary_predicate}@, const T*> + remove_copy_result + remove_copy(Ep&& exec, I first, S last, O result, OutS result_last, const T& value, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + class Proj = identity, class T = projected_value_t, Proj>> + requires @\libconcept{indirectly_copyable}@, iterator_t> && + @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + remove_copy_result, borrowed_iterator_t> + remove_copy(Ep&& exec, R&& r, OutR&& result_r, const T& value, + Proj proj = {}); // freestanding-deleted + template - using remove_copy_if_result = in_out_result; + using @\libglobal{remove_copy_if_result}@ = in_out_result; template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> @@ -1759,6 +2454,21 @@ requires @\libconcept{indirectly_copyable}@, O> constexpr remove_copy_if_result, O> remove_copy_if(R&& r, O result, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{indirectly_copyable}@ + remove_copy_if_result + remove_copy_if(Ep&& exec, I first, S last, O result, OutS result_last, Pred pred, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{indirectly_copyable}@, iterator_t> + remove_copy_if_result, borrowed_iterator_t> + remove_copy_if(Ep&& exec, R&& r, OutR&& result_r, Pred pred, + Proj proj = {}); // freestanding-deleted } // \ref{alg.unique}, unique @@ -1768,10 +2478,10 @@ constexpr ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred); template - ForwardIterator unique(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator unique(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last); template - ForwardIterator unique(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator unique(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, BinaryPredicate pred); @@ -1784,6 +2494,18 @@ requires @\libconcept{permutable}@> constexpr borrowed_subrange_t unique(R&& r, C comp = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_equivalence_relation}@> C = ranges::equal_to> + requires @\libconcept{permutable}@ + subrange unique(Ep&& exec, I first, S last, C comp = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_equivalence_relation}@, Proj>> C = ranges::equal_to> + requires @\libconcept{permutable}@> + borrowed_subrange_t + unique(Ep&& exec, R&& r, C comp = {}, Proj proj = {}); // freestanding-deleted } template @@ -1796,19 +2518,19 @@ OutputIterator result, BinaryPredicate pred); template ForwardIterator2 - unique_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + unique_copy(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); template ForwardIterator2 - unique_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + unique_copy(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryPredicate pred); namespace ranges { template - using unique_copy_result = in_out_result; + using @\libglobal{unique_copy_result}@ = in_out_result; template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O, class Proj = identity, @\libconcept{indirect_equivalence_relation}@> C = ranges::equal_to> @@ -1826,13 +2548,28 @@ @\libconcept{indirectly_copyable_storable}@, O>) constexpr unique_copy_result, O> unique_copy(R&& r, O result, C comp = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Proj = identity, + @\libconcept{indirect_equivalence_relation}@> C = ranges::equal_to> + requires @\libconcept{indirectly_copyable}@ + unique_copy_result + unique_copy(Ep&& exec, I first, S last, O result, OutS result_last, C comp = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + class Proj = identity, + @\libconcept{indirect_equivalence_relation}@, Proj>> C = ranges::equal_to> + requires @\libconcept{indirectly_copyable}@, iterator_t> + unique_copy_result, borrowed_iterator_t> + unique_copy(Ep&& exec, R&& r, OutR&& result_r, C comp = {}, + Proj proj = {}); // freestanding-deleted } // \ref{alg.reverse}, reverse template constexpr void reverse(BidirectionalIterator first, BidirectionalIterator last); template - void reverse(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + void reverse(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} BidirectionalIterator first, BidirectionalIterator last); namespace ranges { @@ -1842,6 +2579,13 @@ template<@\libconcept{bidirectional_range}@ R> requires @\libconcept{permutable}@> constexpr borrowed_iterator_t reverse(R&& r); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S> + requires @\libconcept{permutable}@ + I reverse(Ep&& exec, I first, S last); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R> + requires @\libconcept{permutable}@> + borrowed_iterator_t reverse(Ep&& exec, R&& r); // freestanding-deleted } template @@ -1850,13 +2594,15 @@ OutputIterator result); template ForwardIterator - reverse_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + reverse_copy(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} BidirectionalIterator first, BidirectionalIterator last, ForwardIterator result); namespace ranges { template - using reverse_copy_result = in_out_result; + using @\libglobal{reverse_copy_result}@ = in_out_result; + template + using @\libglobal{reverse_copy_truncated_result}@ = in_in_out_result; template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O> requires @\libconcept{indirectly_copyable}@ @@ -1866,6 +2612,17 @@ requires @\libconcept{indirectly_copyable}@, O> constexpr reverse_copy_result, O> reverse_copy(R&& r, O result); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS> + requires @\libconcept{indirectly_copyable}@ + reverse_copy_truncated_result + reverse_copy(Ep&& exec, I first, S last, O result, + OutS result_last); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR> + requires @\libconcept{indirectly_copyable}@, iterator_t> + reverse_copy_truncated_result, borrowed_iterator_t> + reverse_copy(Ep&& exec, R&& r, OutR&& result_r); // freestanding-deleted } // \ref{alg.rotate}, rotate @@ -1874,7 +2631,7 @@ ForwardIterator middle, ForwardIterator last); template - ForwardIterator rotate(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator rotate(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator middle, ForwardIterator last); @@ -1885,6 +2642,15 @@ template<@\libconcept{forward_range}@ R> requires @\libconcept{permutable}@> constexpr borrowed_subrange_t rotate(R&& r, iterator_t middle); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S> + requires @\libconcept{permutable}@ + subrange + rotate(Ep&& exec, I first, I middle, S last); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R> + requires @\libconcept{permutable}@> + borrowed_subrange_t + rotate(Ep&& exec, R&& r, iterator_t middle); // freestanding-deleted } template @@ -1893,13 +2659,15 @@ ForwardIterator last, OutputIterator result); template ForwardIterator2 - rotate_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + rotate_copy(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 middle, ForwardIterator1 last, ForwardIterator2 result); namespace ranges { template - using rotate_copy_result = in_out_result; + using @\libglobal{rotate_copy_result}@ = in_out_result; + template + using @\libglobal{rotate_copy_truncated_result}@ = in_in_out_result; template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O> requires @\libconcept{indirectly_copyable}@ @@ -1909,6 +2677,18 @@ requires @\libconcept{indirectly_copyable}@, O> constexpr rotate_copy_result, O> rotate_copy(R&& r, iterator_t middle, O result); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS> + requires @\libconcept{indirectly_copyable}@ + rotate_copy_truncated_result + rotate_copy(Ep&& exec, I first, I middle, S last, O result, // freestanding-deleted + OutS result_last); + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR> + requires @\libconcept{indirectly_copyable}@, iterator_t> + rotate_copy_truncated_result, borrowed_iterator_t> + rotate_copy(Ep&& exec, R&& r, iterator_t middle, // freestanding-deleted + OutR&& result_r); } // \ref{alg.random.sample}, sample @@ -1956,7 +2736,7 @@ typename iterator_traits::difference_type n); template ForwardIterator - shift_left(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + shift_left(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, typename iterator_traits::difference_type n); @@ -1966,6 +2746,15 @@ template<@\libconcept{forward_range}@ R> requires @\libconcept{permutable}@> constexpr borrowed_subrange_t shift_left(R&& r, range_difference_t n); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S> + requires @\libconcept{permutable}@ + subrange + shift_left(Ep&& exec, I first, S last, iter_difference_t n); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R> + requires @\libconcept{permutable}@> + borrowed_subrange_t + shift_left(Ep&& exec, R&& r, range_difference_t n); // freestanding-deleted } template @@ -1974,7 +2763,7 @@ typename iterator_traits::difference_type n); template ForwardIterator - shift_right(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + shift_right(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, typename iterator_traits::difference_type n); @@ -1984,6 +2773,15 @@ template<@\libconcept{forward_range}@ R> requires @\libconcept{permutable}@> constexpr borrowed_subrange_t shift_right(R&& r, range_difference_t n); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S> + requires @\libconcept{permutable}@ + subrange + shift_right(Ep&& exec, I first, S last, iter_difference_t n); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R> + requires @\libconcept{permutable}@> + borrowed_subrange_t + shift_right(Ep&& exec, R&& r, range_difference_t n); // freestanding-deleted } // \ref{alg.sorting}, sorting and related operations @@ -1994,10 +2792,10 @@ constexpr void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template - void sort(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + void sort(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} RandomAccessIterator first, RandomAccessIterator last); template - void sort(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + void sort(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} RandomAccessIterator first, RandomAccessIterator last, Compare comp); @@ -2011,18 +2809,28 @@ requires @\libconcept{sortable}@, Comp, Proj> constexpr borrowed_iterator_t sort(R&& r, Comp comp = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Comp = ranges::less, class Proj = identity> + requires @\libconcept{sortable}@ + I sort(Ep&& exec, I first, S last, Comp comp = {}, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Comp = ranges::less, + class Proj = identity> + requires @\libconcept{sortable}@, Comp, Proj> + borrowed_iterator_t + sort(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // freestanding-deleted } template - constexpr void stable_sort(RandomAccessIterator first, RandomAccessIterator last); + constexpr void stable_sort(RandomAccessIterator first, RandomAccessIterator last); // hosted template - constexpr void stable_sort(RandomAccessIterator first, RandomAccessIterator last, - Compare comp); + constexpr void stable_sort(RandomAccessIterator first, RandomAccessIterator last, // hosted + Compare comp); template - void stable_sort(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + void stable_sort(ExecutionPolicy&& exec, // hosted, see \ref{algorithms.parallel.overloads} RandomAccessIterator first, RandomAccessIterator last); template - void stable_sort(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + void stable_sort(ExecutionPolicy&& exec, // hosted, see \ref{algorithms.parallel.overloads} RandomAccessIterator first, RandomAccessIterator last, Compare comp); @@ -2030,11 +2838,22 @@ template<@\libconcept{random_access_iterator}@ I, @\libconcept{sentinel_for}@ S, class Comp = ranges::less, class Proj = identity> requires @\libconcept{sortable}@ - constexpr I stable_sort(I first, S last, Comp comp = {}, Proj proj = {}); + constexpr I stable_sort(I first, S last, Comp comp = {}, Proj proj = {}); // hosted template<@\libconcept{random_access_range}@ R, class Comp = ranges::less, class Proj = identity> requires @\libconcept{sortable}@, Comp, Proj> constexpr borrowed_iterator_t - stable_sort(R&& r, Comp comp = {}, Proj proj = {}); + stable_sort(R&& r, Comp comp = {}, Proj proj = {}); // hosted + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Comp = ranges::less, class Proj = identity> + requires @\libconcept{sortable}@ + I stable_sort(Ep&& exec, I first, S last, Comp comp = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Comp = ranges::less, + class Proj = identity> + requires @\libconcept{sortable}@, Comp, Proj> + borrowed_iterator_t + stable_sort(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // freestanding-deleted } template @@ -2044,11 +2863,11 @@ constexpr void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp); template - void partial_sort(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + void partial_sort(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last); template - void partial_sort(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + void partial_sort(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp); @@ -2063,6 +2882,18 @@ constexpr borrowed_iterator_t partial_sort(R&& r, iterator_t middle, Comp comp = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Comp = ranges::less, class Proj = identity> + requires @\libconcept{sortable}@ + I partial_sort(Ep&& exec, I first, I middle, S last, Comp comp = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, + class Comp = ranges::less, class Proj = identity> + requires @\libconcept{sortable}@, Comp, Proj> + borrowed_iterator_t + partial_sort(Ep&& exec, R&& r, iterator_t middle, Comp comp = {}, + Proj proj = {}); // freestanding-deleted } template @@ -2078,14 +2909,14 @@ Compare comp); template RandomAccessIterator - partial_sort_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + partial_sort_copy(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last); template RandomAccessIterator - partial_sort_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + partial_sort_copy(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, @@ -2093,7 +2924,7 @@ namespace ranges { template - using partial_sort_copy_result = in_out_result; + using @\libglobal{partial_sort_copy_result}@ = in_out_result; template<@\libconcept{input_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{random_access_iterator}@ I2, @\libconcept{sentinel_for}@ S2, @@ -2112,6 +2943,25 @@ constexpr partial_sort_copy_result, borrowed_iterator_t> partial_sort_copy(R1&& r, R2&& result_r, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_copyable}@ && @\libconcept{sortable}@ && + @\libconcept{indirect_strict_weak_order}@, projected> + partial_sort_copy_result + partial_sort_copy(Ep&& exec, I1 first, S1 last, I2 result_first, S2 result_last, + Comp comp = {}, Proj1 proj1 = {}, + Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_copyable}@, iterator_t> && + @\libconcept{sortable}@, Comp, Proj2> && + @\libconcept{indirect_strict_weak_order}@, Proj1>, + projected, Proj2>> + partial_sort_copy_result, borrowed_iterator_t> + partial_sort_copy(Ep&& exec, R1&& r, R2&& result_r, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } template @@ -2120,10 +2970,10 @@ constexpr bool is_sorted(ForwardIterator first, ForwardIterator last, Compare comp); template - bool is_sorted(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool is_sorted(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last); template - bool is_sorted(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool is_sorted(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Compare comp); @@ -2134,6 +2984,15 @@ template<@\libconcept{forward_range}@ R, class Proj = identity, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr bool is_sorted(R&& r, Comp comp = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + bool is_sorted(Ep&& exec, I first, S last, Comp comp = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + bool is_sorted(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // freestanding-deleted } template @@ -2145,11 +3004,11 @@ Compare comp); template ForwardIterator - is_sorted_until(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + is_sorted_until(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last); template ForwardIterator - is_sorted_until(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + is_sorted_until(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Compare comp); @@ -2161,6 +3020,16 @@ @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t is_sorted_until(R&& r, Comp comp = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + I is_sorted_until(Ep&& exec, I first, S last, Comp comp = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + borrowed_iterator_t + is_sorted_until(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // freestanding-deleted } // \ref{alg.nth.element}, Nth element @@ -2171,11 +3040,11 @@ constexpr void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp); template - void nth_element(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + void nth_element(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last); template - void nth_element(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + void nth_element(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp); @@ -2189,86 +3058,110 @@ requires @\libconcept{sortable}@, Comp, Proj> constexpr borrowed_iterator_t nth_element(R&& r, iterator_t nth, Comp comp = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Comp = ranges::less, class Proj = identity> + requires @\libconcept{sortable}@ + I nth_element(Ep&& exec, I first, I nth, S last, Comp comp = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Comp = ranges::less, + class Proj = identity> + requires @\libconcept{sortable}@, Comp, Proj> + borrowed_iterator_t + nth_element(Ep&& exec, R&& r, iterator_t nth, Comp comp = {}, + Proj proj = {}); // freestanding-deleted } // \ref{alg.binary.search}, binary search - template + template::value_type> constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value); - template + template::value_type, + class Compare> constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); namespace ranges { - template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr I lower_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); - template<@\libconcept{forward_range}@ R, class T, class Proj = identity, + template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t lower_bound(R&& r, const T& value, Comp comp = {}, Proj proj = {}); } - template + template::value_type> constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value); - template + template::value_type, + class Compare> constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); namespace ranges { - template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr I upper_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); - template<@\libconcept{forward_range}@ R, class T, class Proj = identity, + template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t upper_bound(R&& r, const T& value, Comp comp = {}, Proj proj = {}); } - template + template::value_type> constexpr pair equal_range(ForwardIterator first, ForwardIterator last, const T& value); - template + template::value_type, + class Compare> constexpr pair equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); namespace ranges { - template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> Comp = ranges::less> constexpr subrange equal_range(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); - template<@\libconcept{forward_range}@ R, class T, class Proj = identity, + template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_subrange_t equal_range(R&& r, const T& value, Comp comp = {}, Proj proj = {}); } - template + template::value_type> constexpr bool binary_search(ForwardIterator first, ForwardIterator last, const T& value); - template + template::value_type, + class Compare> constexpr bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); namespace ranges { - template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr bool binary_search(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); - template<@\libconcept{forward_range}@ R, class T, class Proj = identity, + template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr bool binary_search(R&& r, const T& value, Comp comp = {}, @@ -2279,7 +3172,7 @@ template constexpr bool is_partitioned(InputIterator first, InputIterator last, Predicate pred); template - bool is_partitioned(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool is_partitioned(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { @@ -2289,6 +3182,14 @@ template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr bool is_partitioned(R&& r, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + bool is_partitioned(Ep&& exec, I first, S last, Pred pred, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + bool is_partitioned(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // freestanding-deleted } template @@ -2296,7 +3197,7 @@ ForwardIterator last, Predicate pred); template - ForwardIterator partition(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator partition(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Predicate pred); @@ -2311,15 +3212,25 @@ requires @\libconcept{permutable}@> constexpr borrowed_subrange_t partition(R&& r, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + subrange + partition(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{permutable}@> + borrowed_subrange_t + partition(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // freestanding-deleted } template - constexpr BidirectionalIterator stable_partition(BidirectionalIterator first, + constexpr BidirectionalIterator stable_partition(BidirectionalIterator first, // hosted BidirectionalIterator last, Predicate pred); template - BidirectionalIterator stable_partition(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - BidirectionalIterator first, + BidirectionalIterator stable_partition(ExecutionPolicy&& exec, // hosted, + BidirectionalIterator first, // see \ref{algorithms.parallel.overloads} BidirectionalIterator last, Predicate pred); @@ -2327,11 +3238,25 @@ template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{permutable}@ - constexpr subrange stable_partition(I first, S last, Pred pred, Proj proj = {}); + constexpr subrange stable_partition(I first, S last, Pred pred, // hosted + Proj proj = {}); template<@\libconcept{bidirectional_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{permutable}@> - constexpr borrowed_subrange_t stable_partition(R&& r, Pred pred, Proj proj = {}); + constexpr borrowed_subrange_t stable_partition(R&& r, Pred pred, // hosted + Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{permutable}@ + subrange + stable_partition(Ep&& exec, I first, S last, Pred pred, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{permutable}@> + borrowed_subrange_t + stable_partition(Ep&& exec, R&& r, Pred pred, Proj proj = {}); // freestanding-deleted } template pair - partition_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + partition_copy(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, ForwardIterator1 out_true, ForwardIterator2 out_false, Predicate pred); namespace ranges { template - using partition_copy_result = in_out_out_result; + using @\libglobal{partition_copy_result}@ = in_out_out_result; template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O1, @\libconcept{weakly_incrementable}@ O2, @@ -2366,6 +3291,26 @@ @\libconcept{indirectly_copyable}@, O2> constexpr partition_copy_result, O1, O2> partition_copy(R&& r, O1 out_true, O2 out_false, Pred pred, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O1, @\libconcept{sized_sentinel_for}@ OutS1, + @\libconcept{random_access_iterator}@ O2, @\libconcept{sized_sentinel_for}@ OutS2, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{indirectly_copyable}@ && @\libconcept{indirectly_copyable}@ + partition_copy_result + partition_copy(Ep&& exec, I first, S last, O1 out_true, OutS1 last_true, + O2 out_false, OutS2 last_false, Pred pred, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, + @\exposconcept{sized-random-access-range}@ OutR1, @\exposconcept{sized-random-access-range}@ OutR2, + class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{indirectly_copyable}@, iterator_t> && + @\libconcept{indirectly_copyable}@, iterator_t> + partition_copy_result, borrowed_iterator_t, + borrowed_iterator_t> + partition_copy(Ep&& exec, R&& r, OutR1&& out_true_r, OutR2&& out_false_r, Pred pred, + Proj proj = {}); // freestanding-deleted } template @@ -2398,21 +3343,21 @@ template ForwardIterator - merge(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + merge(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template ForwardIterator - merge(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + merge(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); namespace ranges { template - using merge_result = in_in_out_result; + using @\libglobal{merge_result}@ = in_in_out_result; template<@\libconcept{input_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{input_iterator}@ I2, @\libconcept{sentinel_for}@ S2, @\libconcept{weakly_incrementable}@ O, class Comp = ranges::less, class Proj1 = identity, @@ -2427,23 +3372,39 @@ constexpr merge_result, borrowed_iterator_t, O> merge(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@ + merge_result + merge(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, O result, OutS result_last, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + @\exposconcept{sized-random-access-range}@ OutR, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@, iterator_t, iterator_t, Comp, Proj1, Proj2> + merge_result, borrowed_iterator_t, borrowed_iterator_t> + merge(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } template - constexpr void inplace_merge(BidirectionalIterator first, + constexpr void inplace_merge(BidirectionalIterator first, // hosted BidirectionalIterator middle, BidirectionalIterator last); template - constexpr void inplace_merge(BidirectionalIterator first, + constexpr void inplace_merge(BidirectionalIterator first, // hosted BidirectionalIterator middle, BidirectionalIterator last, Compare comp); template - void inplace_merge(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + void inplace_merge(ExecutionPolicy&& exec, // hosted, see \ref{algorithms.parallel.overloads} BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last); template - void inplace_merge(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + void inplace_merge(ExecutionPolicy&& exec, // hosted, see \ref{algorithms.parallel.overloads} BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp); @@ -2452,12 +3413,24 @@ template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class Comp = ranges::less, class Proj = identity> requires @\libconcept{sortable}@ - constexpr I inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); + constexpr I + inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // hosted template<@\libconcept{bidirectional_range}@ R, class Comp = ranges::less, class Proj = identity> requires @\libconcept{sortable}@, Comp, Proj> constexpr borrowed_iterator_t - inplace_merge(R&& r, iterator_t middle, Comp comp = {}, - Proj proj = {}); + inplace_merge(R&& r, iterator_t middle, Comp comp = {}, Proj proj = {}); // hosted + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Comp = ranges::less, class Proj = identity> + requires @\libconcept{sortable}@ + I inplace_merge(Ep&& exec, I first, I middle, S last, Comp comp = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Comp = ranges::less, + class Proj = identity> + requires @\libconcept{sortable}@, Comp, Proj> + borrowed_iterator_t + inplace_merge(Ep&& exec, R&& r, iterator_t middle, Comp comp = {}, + Proj proj = {}); // freestanding-deleted } // \ref{alg.set.operations}, set operations @@ -2469,12 +3442,12 @@ InputIterator2 first2, InputIterator2 last2, Compare comp); template - bool includes(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool includes(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template - bool includes(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool includes(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, Compare comp); @@ -2492,6 +3465,20 @@ projected, Proj2>> Comp = ranges::less> constexpr bool includes(R1&& r1, R2&& r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Proj1 = identity, class Proj2 = identity, + @\libconcept{indirect_strict_weak_order}@, projected> Comp = + ranges::less> + bool includes(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Proj1 = identity, class Proj2 = identity, + @\libconcept{indirect_strict_weak_order}@, Proj1>, + projected, Proj2>> Comp = ranges::less> + bool includes(Ep&& exec, R1&& r1, R2&& r2, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } template @@ -2501,27 +3488,27 @@ OutputIterator result); template constexpr OutputIterator - set_union(InputIterator1 first1, InputIterator1 last1, + set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template ForwardIterator - set_union(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + set_union(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template ForwardIterator - set_union(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + set_union(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); namespace ranges { template - using set_union_result = in_in_out_result; + using @\libglobal{set_union_result}@ = in_in_out_result; template<@\libconcept{input_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{input_iterator}@ I2, @\libconcept{sentinel_for}@ S2, @\libconcept{weakly_incrementable}@ O, class Comp = ranges::less, @@ -2536,6 +3523,24 @@ constexpr set_union_result, borrowed_iterator_t, O> set_union(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@ + set_union_result + set_union(Ep&& exec, I1 first1, S1 last1, + I2 first2, S2 last2, O result, OutS result_last, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + @\exposconcept{sized-random-access-range}@ OutR, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@, iterator_t, iterator_t, Comp, Proj1, Proj2> + set_union_result, borrowed_iterator_t, + borrowed_iterator_t> + set_union(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } template @@ -2551,21 +3556,21 @@ template ForwardIterator - set_intersection(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + set_intersection(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template ForwardIterator - set_intersection(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + set_intersection(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); namespace ranges { template - using set_intersection_result = in_in_out_result; + using @\libglobal{set_intersection_result}@ = in_in_out_result; template<@\libconcept{input_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{input_iterator}@ I2, @\libconcept{sentinel_for}@ S2, @\libconcept{weakly_incrementable}@ O, class Comp = ranges::less, @@ -2580,6 +3585,24 @@ constexpr set_intersection_result, borrowed_iterator_t, O> set_intersection(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@ + set_intersection_result + set_intersection(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + O result, OutS result_last, Comp comp = {}, Proj1 proj1 = {}, + Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + @\exposconcept{sized-random-access-range}@ OutR, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@, iterator_t, iterator_t, Comp, Proj1, Proj2> + set_intersection_result, borrowed_iterator_t, + borrowed_iterator_t> + set_intersection(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } template @@ -2595,21 +3618,21 @@ template ForwardIterator - set_difference(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + set_difference(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template ForwardIterator - set_difference(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + set_difference(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); namespace ranges { template - using set_difference_result = in_out_result; + using @\libglobal{set_difference_result}@ = in_out_result; template<@\libconcept{input_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{input_iterator}@ I2, @\libconcept{sentinel_for}@ S2, @\libconcept{weakly_incrementable}@ O, class Comp = ranges::less, @@ -2624,6 +3647,23 @@ constexpr set_difference_result, O> set_difference(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@ + set_difference_result + set_difference(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + O result, OutS result_last, Comp comp = {}, Proj1 proj1 = {}, + Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + @\exposconcept{sized-random-access-range}@ OutR, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@, iterator_t, iterator_t, Comp, Proj1, Proj2> + set_difference_result, borrowed_iterator_t> + set_difference(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } template @@ -2639,21 +3679,21 @@ template ForwardIterator - set_symmetric_difference(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + set_symmetric_difference(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template ForwardIterator - set_symmetric_difference(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + set_symmetric_difference(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); namespace ranges { template - using set_symmetric_difference_result = in_in_out_result; + using @\libglobal{set_symmetric_difference_result}@ = in_in_out_result; template<@\libconcept{input_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{input_iterator}@ I2, @\libconcept{sentinel_for}@ S2, @\libconcept{weakly_incrementable}@ O, class Comp = ranges::less, @@ -2670,6 +3710,24 @@ borrowed_iterator_t, O> set_symmetric_difference(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@ + set_symmetric_difference_result + set_symmetric_difference(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + O result, OutS result_last, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + @\exposconcept{sized-random-access-range}@ OutR, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@, iterator_t, iterator_t, Comp, Proj1, Proj2> + set_symmetric_difference_result, borrowed_iterator_t, + borrowed_iterator_t> + set_symmetric_difference(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } // \ref{alg.heap.operations}, heap operations @@ -2751,10 +3809,10 @@ constexpr bool is_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template - bool is_heap(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool is_heap(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} RandomAccessIterator first, RandomAccessIterator last); template - bool is_heap(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + bool is_heap(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} RandomAccessIterator first, RandomAccessIterator last, Compare comp); @@ -2765,6 +3823,15 @@ template<@\libconcept{random_access_range}@ R, class Proj = identity, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr bool is_heap(R&& r, Comp comp = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + bool is_heap(Ep&& exec, I first, S last, Comp comp = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + bool is_heap(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // freestanding-deleted } template @@ -2776,11 +3843,11 @@ Compare comp); template RandomAccessIterator - is_heap_until(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + is_heap_until(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} RandomAccessIterator first, RandomAccessIterator last); template RandomAccessIterator - is_heap_until(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + is_heap_until(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} RandomAccessIterator first, RandomAccessIterator last, Compare comp); @@ -2792,6 +3859,16 @@ @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t is_heap_until(R&& r, Comp comp = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + I is_heap_until(Ep&& exec, I first, S last, Comp comp = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + borrowed_iterator_t + is_heap_until(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // freestanding-deleted } // \ref{alg.min.max}, minimum and maximum @@ -2815,6 +3892,11 @@ requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr range_value_t min(R&& r, Comp comp = {}, Proj proj = {}); + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> + range_value_t + min(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // freestanding-deleted } template constexpr const T& max(const T& a, const T& b); @@ -2837,6 +3919,11 @@ requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr range_value_t max(R&& r, Comp comp = {}, Proj proj = {}); + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> + range_value_t + max(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // freestanding-deleted } template constexpr pair minmax(const T& a, const T& b); @@ -2849,7 +3936,7 @@ namespace ranges { template - using minmax_result = min_max_result; + using @\libglobal{minmax_result}@ = min_max_result; template> Comp = ranges::less> @@ -2864,6 +3951,11 @@ requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr minmax_result> minmax(R&& r, Comp comp = {}, Proj proj = {}); + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> + minmax_result> + minmax(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // freestanding-deleted } template @@ -2872,10 +3964,10 @@ constexpr ForwardIterator min_element(ForwardIterator first, ForwardIterator last, Compare comp); template - ForwardIterator min_element(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator min_element(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last); template - ForwardIterator min_element(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator min_element(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Compare comp); @@ -2887,6 +3979,17 @@ @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t min_element(R&& r, Comp comp = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + I min_element(Ep&& exec, I first, S last, Comp comp = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + borrowed_iterator_t + min_element(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // freestanding-deleted } template @@ -2895,10 +3998,10 @@ constexpr ForwardIterator max_element(ForwardIterator first, ForwardIterator last, Compare comp); template - ForwardIterator max_element(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator max_element(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last); template - ForwardIterator max_element(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + ForwardIterator max_element(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Compare comp); @@ -2910,6 +4013,17 @@ @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t max_element(R&& r, Comp comp = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + I max_element(Ep&& exec, I first, S last, Comp comp = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + borrowed_iterator_t + max_element(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // freestanding-deleted } template @@ -2920,16 +4034,16 @@ minmax_element(ForwardIterator first, ForwardIterator last, Compare comp); template pair - minmax_element(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + minmax_element(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last); template pair - minmax_element(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + minmax_element(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, Compare comp); namespace ranges { template - using minmax_element_result = min_max_result; + using @\libglobal{minmax_element_result}@ = min_max_result; template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> @@ -2939,6 +4053,17 @@ @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr minmax_element_result> minmax_element(R&& r, Comp comp = {}, Proj proj = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + minmax_element_result + minmax_element(Ep&& exec, I first, S last, Comp comp = {}, + Proj proj = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + minmax_element_result> + minmax_element(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); // freestanding-deleted } // \ref{alg.clamp}, bounded value @@ -2966,13 +4091,13 @@ Compare comp); template bool - lexicographical_compare(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + lexicographical_compare(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template bool - lexicographical_compare(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + lexicographical_compare(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, Compare comp); @@ -2992,6 +4117,21 @@ constexpr bool lexicographical_compare(R1&& r1, R2&& r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Proj1 = identity, class Proj2 = identity, + @\libconcept{indirect_strict_weak_order}@, + projected> Comp = ranges::less> + bool lexicographical_compare(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + Comp comp = {}, Proj1 proj1 = {}, + Proj2 proj2 = {}); // freestanding-deleted + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Proj1 = identity, class Proj2 = identity, + @\libconcept{indirect_strict_weak_order}@, Proj1>, + projected, Proj2>> Comp = ranges::less> + bool lexicographical_compare(Ep&& exec, R1&& r1, R2&& r2, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // freestanding-deleted } // \ref{alg.three.way}, three-way comparison algorithms @@ -3016,7 +4156,7 @@ namespace ranges { template - using next_permutation_result = in_found_result; + using @\libglobal{next_permutation_result}@ = in_found_result; template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class Comp = ranges::less, class Proj = identity> @@ -3039,7 +4179,7 @@ namespace ranges { template - using prev_permutation_result = in_found_result; + using @\libglobal{prev_permutation_result}@ = in_found_result; template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class Comp = ranges::less, class Proj = identity> @@ -3065,9 +4205,9 @@ \begin{codeblock} namespace std::ranges { template - struct in_fun_result { - [[no_unique_address]] I in; - [[no_unique_address]] F fun; + struct @\libglobal{in_fun_result}@ { + [[no_unique_address]] I @\libmember{in}{in_fun_result}@; + [[no_unique_address]] F @\libmember{fun}{in_fun_result}@; template requires @\libconcept{convertible_to}@ && @\libconcept{convertible_to}@ @@ -3083,9 +4223,9 @@ }; template - struct in_in_result { - [[no_unique_address]] I1 in1; - [[no_unique_address]] I2 in2; + struct @\libglobal{in_in_result}@ { + [[no_unique_address]] I1 @\libmember{in1}{in_in_result}@; + [[no_unique_address]] I2 @\libmember{in2}{in_in_result}@; template requires @\libconcept{convertible_to}@ && @\libconcept{convertible_to}@ @@ -3101,9 +4241,9 @@ }; template - struct in_out_result { - [[no_unique_address]] I in; - [[no_unique_address]] O out; + struct @\libglobal{in_out_result}@ { + [[no_unique_address]] I @\libmember{in}{in_out_result}@; + [[no_unique_address]] O @\libmember{out}{in_out_result}@; template requires @\libconcept{convertible_to}@ && @\libconcept{convertible_to}@ @@ -3119,10 +4259,10 @@ }; template - struct in_in_out_result { - [[no_unique_address]] I1 in1; - [[no_unique_address]] I2 in2; - [[no_unique_address]] O out; + struct @\libglobal{in_in_out_result}@ { + [[no_unique_address]] I1 @\libmember{in1}{in_in_out_result}@; + [[no_unique_address]] I2 @\libmember{in2}{in_in_out_result}@; + [[no_unique_address]] O @\libmember{out}{in_in_out_result}@; template requires @\libconcept{convertible_to}@ && @@ -3142,10 +4282,10 @@ }; template - struct in_out_out_result { - [[no_unique_address]] I in; - [[no_unique_address]] O1 out1; - [[no_unique_address]] O2 out2; + struct @\libglobal{in_out_out_result}@ { + [[no_unique_address]] I @\libmember{in}{in_out_out_result}@; + [[no_unique_address]] O1 @\libmember{out1}{in_out_out_result}@; + [[no_unique_address]] O2 @\libmember{out2}{in_out_out_result}@; template requires @\libconcept{convertible_to}@ && @@ -3165,9 +4305,9 @@ }; template - struct min_max_result { - [[no_unique_address]] T min; - [[no_unique_address]] T max; + struct @\libglobal{min_max_result}@ { + [[no_unique_address]] T @\libmember{min}{min_max_result}@; + [[no_unique_address]] T @\libmember{max}{min_max_result}@; template requires @\libconcept{convertible_to}@ @@ -3183,9 +4323,9 @@ }; template - struct in_found_result { - [[no_unique_address]] I in; - bool found; + struct @\libglobal{in_found_result}@ { + [[no_unique_address]] I @\libmember{in}{in_found_result}@; + bool @\libmember{found}{in_found_result}@; template requires @\libconcept{convertible_to}@ @@ -3200,9 +4340,9 @@ }; template - struct in_value_result { - [[no_unique_address]] I in; - [[no_unique_address]] T value; + struct @\libglobal{in_value_result}@ { + [[no_unique_address]] I @\libmember{in}{in_value_result}@; + [[no_unique_address]] T @\libmember{value}{in_value_result}@; template requires @\libconcept{convertible_to}@ && @\libconcept{convertible_to}@ @@ -3218,9 +4358,9 @@ }; template - struct out_value_result { - [[no_unique_address]] O out; - [[no_unique_address]] T value; + struct @\libglobal{out_value_result}@ { + [[no_unique_address]] O @\libmember{out}{out_value_result}@; + [[no_unique_address]] T @\libmember{value}{out_value_result}@; template requires @\libconcept{convertible_to}@ && @\libconcept{convertible_to}@ @@ -3255,6 +4395,13 @@ template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr bool ranges::all_of(R&& r, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + bool ranges::all_of(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + bool ranges::all_of(Ep&& exec, R&& r, Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -3295,6 +4442,13 @@ template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr bool ranges::any_of(R&& r, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + bool ranges::any_of(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + bool ranges::any_of(Ep&& exec, R&& r, Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -3335,6 +4489,13 @@ template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr bool ranges::none_of(R&& r, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + bool ranges::none_of(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + bool ranges::none_of(Ep&& exec, R&& r, Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -3363,10 +4524,11 @@ \indexlibraryglobal{contains}% \begin{itemdecl} -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr bool ranges::contains(I first, S last, const T& value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T, class Proj = identity> +template<@\libconcept{input_range}@ R, class Proj = identity, class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr bool ranges::contains(R&& r, const T& value, Proj proj = {}); \end{itemdecl} @@ -3377,6 +4539,24 @@ \tcode{ranges::find(std::move(first), last, value, proj) != last}. \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T = projected_value_t> + requires @\libconcept{indirect_binary_predicate}@, const T*> + bool ranges::contains(Ep&& exec, I first, S last, const T& value, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> + requires + @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + bool ranges::contains(Ep&& exec, R&& r, const T& value, Proj proj = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{ranges::find(std::forward(exec), first, last, value, proj) != last}. +\end{itemdescr} + \indexlibraryglobal{contains_subrange}% \begin{itemdecl} template<@\libconcept{forward_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @@ -3395,7 +4575,33 @@ \begin{itemdescr} \pnum \returns -\tcode{first2 == last2 || !ranges::search(first1, last1, first2, last2, pred, proj1, proj2).empty()}. +\begin{codeblock} +first2 == last2 || !ranges::search(first1, last1, first2, last2, + pred, proj1, proj2).empty() +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + bool ranges::contains_subrange(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + bool ranges::contains_subrange(Ep&& exec, R1&& r1, R2&& r2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +first2 == last2 || !ranges::search(std::forward(exec), first1, last1, + first2, last2, pred, proj1, proj2).empty() +\end{codeblock} \end{itemdescr} \rSec2[alg.foreach]{For each} @@ -3521,21 +4727,69 @@ \end{note} \end{itemdescr} -\indexlibraryglobal{for_each_n}% \begin{itemdecl} -template - constexpr InputIterator for_each_n(InputIterator first, Size n, Function f); +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirectly_unary_invocable}@> Fun> + I ranges::for_each(Ep&& exec, I first, S last, Fun f, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirectly_unary_invocable}@, Proj>> Fun> + borrowed_iterator_t + ranges::for_each(Ep&& exec, R&& r, Fun f, Proj proj = {}); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The type \tcode{Size} is convertible -to an integral type\iref{conv.integral,class.conv}. +\effects +Calls \tcode{invoke(f, invoke(proj, *i))} +for every iterator \tcode{i} +in the range \range{first}{last}. +\begin{note} +If the result of \tcode{invoke(proj, *i)} is a mutable reference, +\tcode{f} can apply non-constant functions. +\end{note} \pnum -\expects -\tcode{n >= 0} is \tcode{true}. +\returns +\tcode{last}. + +\pnum +\complexity +Applies \tcode{f} and \tcode{proj} exactly \tcode{last - first} times. + +\pnum +\remarks +\begin{itemize} +\item + If \tcode{f} returns a result, the result is ignored. +\item + Implementations do not have the freedom granted under \ref{algorithms.parallel.exec} + to make arbitrary copies of elements from the input sequence. +\item + \tcode{f} may modify objects via its arguments\iref{algorithms.parallel.user}. +\end{itemize} +\begin{note} +Does not return a copy of its \tcode{Fun} parameter, +since parallelization often does not permit +efficient state accumulation. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{for_each_n}% +\begin{itemdecl} +template + constexpr InputIterator for_each_n(InputIterator first, Size n, Function f); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The type \tcode{Size} is convertible +to an integral type\iref{conv.integral,class.conv}. + +\pnum +\expects +\tcode{n >= 0} is \tcode{true}. \tcode{Function} meets the \oldconcept{MoveConstructible} requirements. \begin{note} \tcode{Function} need not meet @@ -3637,16 +4891,60 @@ \end{note} \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, class Proj = identity, + @\libconcept{indirectly_unary_invocable}@> Fun> + I ranges::for_each_n(Ep&& exec, I first, iter_difference_t n, Fun f, Proj proj = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{n >= 0} is \tcode{true}. + +\pnum +\effects +Calls \tcode{invoke(f, invoke(proj, *i))} +for every iterator \tcode{i} +in the range \range{first}{first + n}. +\begin{note} +If the result of \tcode{invoke(proj, *i)} is a mutable reference, +\tcode{f} can apply non-constant functions. +\end{note} + +\pnum +\returns +\tcode{first + n}. + +\pnum +\remarks +\begin{itemize} +\item + If \tcode{f} returns a result, the result is ignored. +\item + Implementations do not have the freedom granted under \ref{algorithms.parallel.exec} + to make arbitrary copies of elements from the input sequence. +\item + \tcode{f} may modify objects via its arguments\iref{algorithms.parallel.user}. +\end{itemize} +\begin{note} +Does not return a copy of its \tcode{Fun} parameter, +since parallelization often does not permit +efficient state accumulation. +\end{note} +\end{itemdescr} + \rSec2[alg.find]{Find} \indexlibraryglobal{find}% \indexlibraryglobal{find_if}% \indexlibraryglobal{find_if_not}% \begin{itemdecl} -template +template::value_type> constexpr InputIterator find(InputIterator first, InputIterator last, const T& value); -template +template::value_type> ForwardIterator find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); @@ -3665,13 +4963,25 @@ ForwardIterator first, ForwardIterator last, Predicate pred); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr I ranges::find(I first, S last, const T& value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T, class Proj = identity> +template<@\libconcept{input_range}@ R, class Proj = identity, class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr borrowed_iterator_t ranges::find(R&& r, const T& value, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T = projected_value_t> + requires @\libconcept{indirect_binary_predicate}@, const T*> + I ranges::find(Ep&& exec, I first, S last, const T& value, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> + requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + borrowed_iterator_t ranges::find(Ep&& exec, R&& r, const T& value, Proj proj = {}); + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> constexpr I ranges::find_if(I first, S last, Pred pred, Proj proj = {}); @@ -3679,6 +4989,14 @@ @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr borrowed_iterator_t ranges::find_if(R&& r, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + I ranges::find_if(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + borrowed_iterator_t ranges::find_if(Ep&& exec, R&& r, Pred pred, Proj proj = {}); + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> constexpr I ranges::find_if_not(I first, S last, Pred pred, Proj proj = {}); @@ -3686,6 +5004,13 @@ @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr borrowed_iterator_t ranges::find_if_not(R&& r, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + I ranges::find_if_not(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + borrowed_iterator_t ranges::find_if_not(Ep&& exec, R&& r, Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -3716,24 +5041,54 @@ \indexlibraryglobal{find_last}% \begin{itemdecl} -template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> +template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr subrange ranges::find_last(I first, S last, const T& value, Proj proj = {}); -template<@\libconcept{forward_range}@ R, class T, class Proj = identity> +template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr borrowed_subrange_t ranges::find_last(R&& r, const T& value, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T = projected_value_t> + requires @\libconcept{indirect_binary_predicate}@, const T*> + subrange ranges::find_last(Ep&& exec, I first, S last, const T& value, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> + requires + @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + borrowed_subrange_t ranges::find_last(Ep&& exec, R&& r, const T& value, Proj proj = {}); + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> constexpr subrange ranges::find_last_if(I first, S last, Pred pred, Proj proj = {}); template<@\libconcept{forward_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr borrowed_subrange_t ranges::find_last_if(R&& r, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + subrange ranges::find_last_if(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, + class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + borrowed_subrange_t ranges::find_last_if(Ep&& exec, R&& r, Pred pred, Proj proj = {}); + template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> constexpr subrange ranges::find_last_if_not(I first, S last, Pred pred, Proj proj = {}); template<@\libconcept{forward_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr borrowed_subrange_t ranges::find_last_if_not(R&& r, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_unary_predicate}@> Pred> + subrange ranges::find_last_if_not(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + borrowed_subrange_t ranges::find_last_if_not(Ep&& exec, R&& r, Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -3801,6 +5156,20 @@ constexpr borrowed_subrange_t ranges::find_end(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + subrange + ranges::find_end(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + borrowed_subrange_t + ranges::find_end(Ep&& exec, R1&& r1, R2&& r2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} @@ -3887,6 +5256,19 @@ ranges::find_first_of(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + I1 ranges::find_first_of(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + borrowed_iterator_t + ranges::find_first_of(Ep&& exec, R1&& r1, R2&& r2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} @@ -3913,7 +5295,7 @@ \pnum \complexity -At most \tcode{(last1-first1) * (last2-first2)} applications +At most \tcode{(last1 - first1) * (last2 - first2)} applications of the corresponding predicate and any projections. \end{itemdescr} @@ -3947,6 +5329,17 @@ @\libconcept{indirect_binary_predicate}@, Proj>, projected, Proj>> Pred = ranges::equal_to> constexpr borrowed_iterator_t ranges::adjacent_find(R&& r, Pred pred = {}, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_binary_predicate}@, + projected> Pred = ranges::equal_to> + I ranges::adjacent_find(Ep&& exec, I first, S last, Pred pred = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_binary_predicate}@, Proj>, + projected, Proj>> Pred = ranges::equal_to> + borrowed_iterator_t + ranges::adjacent_find(Ep&& exec, R&& r, Pred pred = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -3968,13 +5361,13 @@ \pnum \complexity -For the overloads with no \tcode{ExecutionPolicy}, +For the non-parallel algorithm overloads, exactly \[ \min(\tcode{(i - first) + 1}, \ \tcode{(last - first) - 1}) \] applications of the corresponding predicate, where \tcode{i} is \tcode{adjacent_find}'s return value. -For the overloads with an \tcode{ExecutionPolicy}, -\bigoh{\tcode{last - first}} applications of the corresponding predicate, -and no more than twice as many applications of any projection. +For the parallel algorithm overloads, +\bigoh{\tcode{last - first}} applications of the corresponding predicate. +No more than twice as many applications of any projection. \end{itemdescr} \rSec2[alg.count]{Count} @@ -3982,10 +5375,11 @@ \indexlibraryglobal{count}% \indexlibraryglobal{count_if}% \begin{itemdecl} -template +template::value_type> constexpr typename iterator_traits::difference_type count(InputIterator first, InputIterator last, const T& value); -template +template::value_type> typename iterator_traits::difference_type count(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); @@ -3998,14 +5392,27 @@ count_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr iter_difference_t ranges::count(I first, S last, const T& value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T, class Proj = identity> +template<@\libconcept{input_range}@ R, class Proj = identity, class T = projected_value_t, Proj>> requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr range_difference_t ranges::count(R&& r, const T& value, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T = projected_value_t> + requires @\libconcept{indirect_binary_predicate}@, const T*> + iter_difference_t + ranges::count(Ep&& exec, I first, S last, const T& value, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> + requires @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + range_difference_t ranges::count(Ep&& exec, R&& r, const T& value, Proj proj = {}); + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> constexpr iter_difference_t @@ -4014,6 +5421,15 @@ @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr range_difference_t ranges::count_if(R&& r, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + iter_difference_t + ranges::count_if(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + range_difference_t + ranges::count_if(Ep&& exec, R&& r, Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -4107,12 +5523,26 @@ constexpr ranges::mismatch_result, borrowed_iterator_t> ranges::mismatch(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + ranges::mismatch_result + ranges::mismatch(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + ranges::mismatch_result, borrowed_iterator_t> + ranges::mismatch(Ep&& exec, R1&& r1, R2&& r2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} \pnum Let \tcode{last2} be \tcode{first2 + (last1 - first1)} -for the overloads with no parameter \tcode{last2} or \tcode{r2}. +for the overloads in namespace \tcode{std} with no parameter \tcode{last2}. \pnum Let $E$ be: @@ -4197,6 +5627,18 @@ requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> constexpr bool ranges::equal(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + bool ranges::equal(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + bool ranges::equal(Ep&& exec, R1&& r1, R2&& r2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} @@ -4205,7 +5647,7 @@ \begin{itemize} \item \tcode{last2} be \tcode{first2 + (last1 - first1)} - for the overloads with no parameter \tcode{last2} or \tcode{r2}; + for the overloads in namespace \tcode{std} with no parameter \tcode{last2}; \item \tcode{pred} be \tcode{equal_to\{\}} for the overloads with no parameter \tcode{pred}; @@ -4240,27 +5682,19 @@ and \tcode{last1 - first1 != last2 - first2} for the overloads in namespace \tcode{std}; \item - the types of \tcode{first1}, \tcode{last1}, \tcode{first2}, and \tcode{last2} - pairwise model \libconcept{sized_sentinel_for}\iref{iterator.concept.sizedsentinel} + the types of \tcode{first1}, \tcode{last1}, \tcode{first2}, and \tcode{last2} + pairwise model \libconcept{sized_sentinel_for}\iref{iterator.concept.sizedsentinel} and \tcode{last1 - first1 != last2 - first2} - for the first overload in namespace \tcode{ranges}, + for the first and third overloads in namespace \tcode{ranges}, or \item \tcode{R1} and \tcode{R2} each model \libconcept{sized_range} and \tcode{ranges::distance(r1) != ranges::distance(r2)} - for the second overload in namespace \tcode{ranges}, + for the second and fourth overloads in namespace \tcode{ranges}, \end{itemize} then no applications of the corresponding predicate and each projection; -otherwise, -\begin{itemize} -\item - For the overloads with no \tcode{ExecutionPolicy}, - at most $\min(\tcode{last1 - first1}, \ \tcode{last2 - first2})$ - applications of the corresponding predicate and any projections. -\item - For the overloads with an \tcode{ExecutionPolicy}, - \bigoh{\min(\tcode{last1 - first1}, \ \tcode{last2 - first2})} - applications of the corresponding predicate. -\end{itemize} +otherwise, at most +\[ \min(\tcode{last1 - first1}, \ \tcode{last2 - first2}) \] +applications of the corresponding predicate and any projections. \end{itemdescr} \rSec2[alg.is.permutation]{Is permutation} @@ -4351,7 +5785,7 @@ \pnum \complexity -No applications of the corresponding predicate and projections if: +No applications of the corresponding predicate and projections if \begin{itemize} \item for the first overload, @@ -4404,7 +5838,7 @@ \begin{itemdescr} \pnum \returns -The first iterator \tcode{i} in the range \range{first1}{last1 - (last2-first2)} +The first iterator \tcode{i} in the range \crange{first1}{last1 - (last2 - first2)} such that for every non-negative integer \tcode{n} less than \tcode{last2 - first2} the following corresponding conditions hold: @@ -4433,6 +5867,20 @@ constexpr borrowed_subrange_t ranges::search(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + subrange + ranges::search(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + borrowed_subrange_t + ranges::search(Ep&& exec, R1&& r1, R2&& r2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} @@ -4442,7 +5890,7 @@ \item \tcode{\{i, i + (last2 - first2)\}}, where \tcode{i} is - the first iterator in the range \range{first1}{last1 - (last2 - first2)} + the first iterator in the range \crange{first1}{last1 - (last2 - first2)} such that for every non-negative integer \tcode{n} less than \tcode{last2 - first2} the condition @@ -4462,23 +5910,25 @@ \indexlibraryglobal{search_n}% \begin{itemdecl} -template +template::value_type> constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value); -template +template::value_type> ForwardIterator search_n(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Size count, const T& value); -template::value_type, class BinaryPredicate> constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred); -template::value_type, class BinaryPredicate> ForwardIterator search_n(ExecutionPolicy&& exec, @@ -4494,12 +5944,16 @@ The type \tcode{Size} is convertible to an integral type\iref{conv.integral,class.conv}. +\pnum +Let $E$ be \tcode{pred(*(i + n), value) != false} +for the overloads with a parameter \tcode{pred}, +and \tcode{*(i + n) == value} otherwise. + \pnum \returns -The first iterator \tcode{i} in the range \range{first}{last-count} +The first iterator \tcode{i} in the range \crange{first}{last - count} such that for every non-negative integer \tcode{n} less than \tcode{count} -the following corresponding conditions hold: -\tcode{*(i + n) == value, pred(*(i + n), value) != false}. +the condition $E$ is \tcode{true}. Returns \tcode{last} if no such iterator is found. \pnum @@ -4509,25 +5963,40 @@ \indexlibraryglobal{search_n}% \begin{itemdecl} -template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, - class Pred = ranges::equal_to, class Proj = identity> +template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, + class Pred = ranges::equal_to, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirectly_comparable}@ constexpr subrange ranges::search_n(I first, S last, iter_difference_t count, const T& value, Pred pred = {}, Proj proj = {}); -template<@\libconcept{forward_range}@ R, class T, class Pred = ranges::equal_to, - class Proj = identity> +template<@\libconcept{forward_range}@ R, class Pred = ranges::equal_to, + class Proj = identity, class T = projected_value_t, Proj>> requires @\libconcept{indirectly_comparable}@, const T*, Pred, Proj> constexpr borrowed_subrange_t ranges::search_n(R&& r, range_difference_t count, const T& value, Pred pred = {}, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Pred = ranges::equal_to, class Proj = identity, + class T = projected_value_t> + requires @\libconcept{indirectly_comparable}@ + subrange + ranges::search_n(Ep&& exec, I first, S last, iter_difference_t count, + const T& value, Pred pred = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Pred = ranges::equal_to, + class Proj = identity, class T = projected_value_t, Proj>> + requires @\libconcept{indirectly_comparable}@, const T*, Pred, Proj> + borrowed_subrange_t + ranges::search_n(Ep&& exec, R&& r, range_difference_t count, + const T& value, Pred pred = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} \pnum \returns \tcode{\{i, i + count\}} -where \tcode{i} is the first iterator in the range \range{first}{last - count} +where \tcode{i} is the first iterator in the range \crange{first}{last - count} such that for every non-negative integer \tcode{n} less than \tcode{count}, the following condition holds: \tcode{invoke(pred, invoke(proj, *(i + n)), value)}. @@ -4581,6 +6050,30 @@ \end{codeblock} \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + bool ranges::starts_with(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, + @\exposconcept{sized-random-access-range}@ R2, class Pred = ranges::equal_to, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + bool ranges::starts_with(Ep&& exec, R1&& r1, R2&& r2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +ranges::mismatch(std::forward(exec), std::move(first1), last1, std::move(first2), + last2, pred, proj1, proj2).in2 == last2 +\end{codeblock} +\end{itemdescr} + \rSec2[alg.ends.with]{Ends with} \indexlibraryglobal{ends_with}% @@ -4601,13 +6094,36 @@ \pnum \returns -\tcode{false} if $\tcode{N1} < \tcode{N2}$, otherwise +\tcode{false} if $\tcode{N1} < \tcode{N2}$, otherwise: \begin{codeblock} ranges::equal(std::move(first1) + (N1 - N2), last1, std::move(first2), last2, pred, proj1, proj2) \end{codeblock} \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@ + bool ranges::ends_with(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{N1} be \tcode{last1 - first1} and +\tcode{N2} be \tcode{last2 - first2}. + +\pnum +\returns +\tcode{false} if $\tcode{N1} < \tcode{N2}$, otherwise: +\begin{codeblock} +ranges::equal(std::forward(exec), std::move(first1) + (N1 - N2), last1, + std::move(first2), last2, pred, proj1, proj2) +\end{codeblock} +\end{itemdescr} + \begin{itemdecl} template<@\libconcept{input_range}@ R1, @\libconcept{input_range}@ R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> @@ -4625,9 +6141,34 @@ \pnum \returns -\tcode{false} if $\tcode{N1} < \tcode{N2}$, otherwise +\tcode{false} if $\tcode{N1} < \tcode{N2}$, otherwise: \begin{codeblock} -ranges::equal(ranges::drop_view(ranges::ref_view(r1), N1 - N2), r2, pred, proj1, proj2) +ranges::equal(views::drop(ranges::ref_view(r1), N1 - static_cast(N2)), + r2, pred, proj1, proj2) +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, + @\exposconcept{sized-random-access-range}@ R2, class Pred = ranges::equal_to, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_comparable}@, iterator_t, Pred, Proj1, Proj2> + bool ranges::ends_with(Ep&& exec, R1&& r1, R2&& r2, + Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{N1} be \tcode{ranges::distance(r1)} and +\tcode{N2} be \tcode{ranges::distance(r2)}. + +\pnum +\returns +\tcode{false} if $\tcode{N1} < \tcode{N2}$, otherwise: +\begin{codeblock} +ranges::equal(std::forward(exec), + views::drop(ranges::ref_view(r1), N1 - static_cast(N2)), + r2, pred, proj1, proj2) \end{codeblock} \end{itemdescr} @@ -4635,9 +6176,11 @@ \indexlibraryglobal{fold_left}% \begin{itemdecl} -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, @\exposconcept{indirectly-binary-left-foldable}@ F> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T = iter_value_t, + @\exposconcept{indirectly-binary-left-foldable}@ F> constexpr auto ranges::fold_left(I first, S last, T init, F f); -template<@\libconcept{input_range}@ R, class T, @\exposconcept{indirectly-binary-left-foldable}@> F> +template<@\libconcept{input_range}@ R, class T = range_value_t, + @\exposconcept{indirectly-binary-left-foldable}@> F> constexpr auto ranges::fold_left(R&& r, T init, F f); \end{itemdecl} @@ -4670,10 +6213,10 @@ \indexlibraryglobal{fold_right}% \begin{itemdecl} -template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, +template<@\libconcept{bidirectional_iterator}@ I, @\libconcept{sentinel_for}@ S, class T = iter_value_t, @\exposconcept{indirectly-binary-right-foldable}@ F> constexpr auto ranges::fold_right(I first, S last, T init, F f); -template<@\libconcept{bidirectional_range}@ R, class T, +template<@\libconcept{bidirectional_range}@ R, class T = range_value_t, @\exposconcept{indirectly-binary-right-foldable}@> F> constexpr auto ranges::fold_right(R&& r, T init, F f); \end{itemdecl} @@ -4725,10 +6268,11 @@ \indexlibraryglobal{fold_left_with_iter}% \begin{itemdecl} -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T = iter_value_t, @\exposconcept{indirectly-binary-left-foldable}@ F> constexpr @\seebelow@ ranges::fold_left_with_iter(I first, S last, T init, F f); -template<@\libconcept{input_range}@ R, class T, @\exposconcept{indirectly-binary-left-foldable}@> F> +template<@\libconcept{input_range}@ R, class T = range_value_t, + @\exposconcept{indirectly-binary-left-foldable}@> F> constexpr @\seebelow@ ranges::fold_left_with_iter(R&& r, T init, F f); \end{itemdecl} @@ -4846,31 +6390,53 @@ \indexlibraryglobal{copy}% \begin{itemdecl} template - ForwardIterator2 copy(ExecutionPolicy&& policy, + ForwardIterator2 copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS> + requires @\libconcept{indirectly_copyable}@ + ranges::copy_result + ranges::copy(Ep&& exec, I first, S last, O result, OutS result_last); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR> + requires @\libconcept{indirectly_copyable}@, iterator_t> + ranges::copy_result, borrowed_iterator_t> + ranges::copy(Ep&& exec, R&& r, OutR&& result_r); \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{result_last} be \tcode{result + (last - first)} +for the overload in namespace \tcode{std}. + +\pnum +Let $N$ be $\min(\tcode{last - first}, \ \tcode{result_last - result})$. + \pnum \expects -The ranges \range{first}{last} and \range{result}{result + (last - first)} +The ranges \range{first}{last} and \range{result}{result + $N$} do not overlap. \pnum \effects -Copies elements in the range \range{first}{last} -into the range \range{result}{result + (last - first)}. -For each non-negative integer \tcode{n < (last - first)}, -performs \tcode{*(result + n) = *(first + n)}. +Copies elements in the range \range{first}{first + $N$} +into the range \range{result}{result + $N$}. +For each non-negative integer $n < N$, +performs \tcode{*(result + $n$) = *(first + $n$)}. \pnum \returns -\tcode{result + (last - first)}. +\begin{itemize} +\item + \tcode{result + $N$} for the overload in namespace \tcode{std}. +\item + \tcode{\{first + $N$, result + $N$\}} for the overloads in namespace \tcode{ranges}. +\end{itemize} \pnum \complexity -Exactly \tcode{last - first} assignments. +Exactly $N$ assignments. \end{itemdescr} \indexlibraryglobal{copy_n}% @@ -4887,11 +6453,24 @@ requires @\libconcept{indirectly_copyable}@ constexpr ranges::copy_n_result ranges::copy_n(I first, iter_difference_t n, O result); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{random_access_iterator}@ O, + @\libconcept{sized_sentinel_for}@ OutS> + requires @\libconcept{indirectly_copyable}@ + ranges::copy_n_result + ranges::copy_n(Ep&& exec, I first, iter_difference_t n, O result, OutS result_last); \end{itemdecl} \begin{itemdescr} \pnum -Let $N$ be $\max(0, \tcode{n})$. +Let $M$ be $\max(0, \ \tcode{n})$. + +\pnum +Let \tcode{result_last} be \tcode{result + $M$} +for the overloads with no parameter \tcode{result_last}. + +\pnum +Let $N$ be $\min(\tcode{result_last - result}, M)$. \pnum \mandates @@ -4940,38 +6519,67 @@ requires @\libconcept{indirectly_copyable}@, O> constexpr ranges::copy_if_result, O> ranges::copy_if(R&& r, O result, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{indirectly_copyable}@ + ranges::copy_if_result + ranges::copy_if(Ep&& exec, I first, S last, O result, OutS result_last, + Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{indirectly_copyable}@, iterator_t> + ranges::copy_if_result, borrowed_iterator_t> + ranges::copy_if(Ep&& exec, R&& r, OutR&& result_r, Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} \pnum -Let $E$ be: +Let $E(\tcode{i})$ be: \begin{itemize} \item \tcode{bool(pred(*i))} for the overloads in namespace \tcode{std}; \item \tcode{bool(invoke(pred, invoke(proj, *i)))} - for the overloads in namespace \tcode{ranges}, + for the overloads in namespace \tcode{ranges}. +\end{itemize} + +\pnum +Let: +\begin{itemize} +\item + $M$ be the number of iterators \tcode{i} in the range \range{first}{last} + for which the condition $E(\tcode{i})$ holds; +\item + \tcode{result_last} be \tcode{result + $M$} + for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; +\item + $N$ be $\min(M, \ \tcode{result_last - result})$. \end{itemize} -and $N$ be the number of iterators \tcode{i} in the range \range{first}{last} -for which the condition $E$ holds. \pnum \expects -The ranges \range{first}{last} and \range{result}{result + (last - first)} +The ranges \range{first}{last} and \range{result}{result + $N$} do not overlap. \begin{note} -For the overload with an \tcode{ExecutionPolicy}, -there might be a performance cost +For the parallel algorithm overload in namespace \tcode{std}, +there can be a performance cost if \tcode{iterator_traits::value_type} -is not \oldconcept{\-Move\-Constructible} (\tref{cpp17.moveconstructible}). +does not meet the \oldconcept{\-Move\-Constructible} (\tref{cpp17.moveconstructible}) requirements. +For the parallel algorithm overloads in namespace \tcode{ranges}, +there can be a performance cost +if \tcode{iter_value_t} does not model \libconcept{move_constructible}. \end{note} \pnum \effects -Copies all of the elements referred to +Copies the first $N$ elements referred to by the iterator \tcode{i} in the range \range{first}{last} -for which $E$ is \tcode{true}. +for which $E(\tcode{i})$ is \tcode{true} +into the range \range{result}{result + $N$}. \pnum \returns @@ -4981,12 +6589,19 @@ for the overloads in namespace \tcode{std}. \item \tcode{\{last, result + $N$\}} - for the overloads in namespace \tcode{ranges}. + for the overloads in namespace \tcode{ranges}, if $N$ is equal to $M$. +\item + Otherwise, \tcode{\{j, result_last\}} + for the overloads in namespace \tcode{ranges}, + where \tcode{j} is the iterator in \range{first}{last} + for which $E(\tcode{j})$ holds + and there are exactly $N$ iterators \tcode{i} + in \range{first}{j} for which $E(\tcode{i})$ holds. \end{itemize} \pnum \complexity -Exactly \tcode{last - first} applications +At most \tcode{last - first} applications of the corresponding predicate and any projection. \pnum @@ -5068,7 +6683,7 @@ \begin{itemdescr} \pnum -Let $E$ be +Let $E(n)$ be \begin{itemize} \item \tcode{std::move(*(first + $n$))} @@ -5088,7 +6703,7 @@ Moves elements in the range \range{first}{last} into the range \range{result}{result + $N$} starting from \tcode{first} and proceeding to \tcode{last}. -For each non-negative integer $n < N$, performs \tcode{*(result + $n$) = $E$}. +For each non-negative integer $n < N$, performs \tcode{*(result + $n$) = $E(n)$}. \pnum \returns @@ -5109,14 +6724,39 @@ \indexlibrary{\idxcode{move}!algorithm}% \begin{itemdecl} template - ForwardIterator2 move(ExecutionPolicy&& policy, + ForwardIterator2 move(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS> + requires @\libconcept{indirectly_movable}@ + ranges::move_result + ranges::move(Ep&& exec, I first, S last, O result, OutS result_last); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR> + requires @\libconcept{indirectly_movable}@, iterator_t> + ranges::move_result, borrowed_iterator_t> + ranges::move(Ep&& exec, R&& r, OutR&& result_r); \end{itemdecl} \begin{itemdescr} \pnum -Let $N$ be \tcode{last - first}. +Let $E(n)$ be: +\begin{itemize} +\item + \tcode{std::move(*(first + $n$))} + for the overload in namespace \tcode{std}; +\item + \tcode{ranges::iter_move(first + $n$)} + for the overloads in namespace \tcode{ranges}. +\end{itemize} + +\pnum +Let \tcode{result_last} be \tcode{result + (last - first)} +for the overloads in namespace \tcode{std}. + +\pnum +Let $N$ be $\min(\tcode{last - first}, \ \tcode{result_last - result})$. \pnum \expects @@ -5125,14 +6765,21 @@ \pnum \effects -Moves elements in the range \range{first}{last} +Moves elements in the range \range{first}{first + $N$} into the range \range{result}{result + $N$}. For each non-negative integer $n < N$, -performs \tcode{*(result + $n$) = std::\brk{}move(*(first + $n$))}. +performs \tcode{*(result + $n$) = $E(n)$}. \pnum \returns -\tcode{result + $N$}. +\begin{itemize} +\item + \tcode{result + $N$} + for the overload in namespace \tcode{std}. +\item + \tcode{\{first + $N$, result + $N$\}} + for the overloads in namespace \tcode{ranges}. +\end{itemize} \pnum \complexity @@ -5158,7 +6805,7 @@ \begin{itemdescr} \pnum -Let $E$ be +Let $E(n)$ be \begin{itemize} \item \tcode{std::move(*(last - $n$))} @@ -5183,7 +6830,7 @@ when \tcode{last} is in the range \range{result - $N$}{result}. \end{footnote} For each positive integer $n \le N$, -performs \tcode{*(result - $n$) = $E$}. +performs \tcode{*(result - $n$) = $E(n)$}. \pnum \returns @@ -5208,7 +6855,7 @@ template constexpr ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, - ForwardIterator2 first2); // freestanding + ForwardIterator2 first2); template ForwardIterator2 swap_ranges(ExecutionPolicy&& exec, @@ -5223,6 +6870,16 @@ requires @\libconcept{indirectly_swappable}@, iterator_t> constexpr ranges::swap_ranges_result, borrowed_iterator_t> ranges::swap_ranges(R1&& r1, R2&& r2); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2> + requires @\libconcept{indirectly_swappable}@ + ranges::swap_ranges_result + ranges::swap_ranges(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2> + requires @\libconcept{indirectly_swappable}@, iterator_t> + ranges::swap_ranges_result, borrowed_iterator_t> + ranges::swap_ranges(Ep&& exec, R1&& r1, R2&& r2); \end{itemdecl} \begin{itemdescr} @@ -5231,7 +6888,8 @@ \begin{itemize} \item \tcode{last2} be \tcode{first2 + (last1 - first1)} - for the overloads with no parameter named \tcode{last2}; + for the overloads in namespace \tcode{std} + with no parameter named \tcode{last2}; \item $M$ be $\min(\tcode{last1 - first1}, \ \tcode{last2 - first2})$. \end{itemize} @@ -5328,21 +6986,57 @@ requires @\libconcept{indirectly_writable}@, Proj>>> constexpr ranges::unary_transform_result, O> ranges::transform(R&& r, O result, F op, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, + @\libconcept{copy_constructible}@ F, class Proj = identity> + requires @\libconcept{indirectly_writable}@>> + ranges::unary_transform_result + ranges::transform(Ep&& exec, I first1, S last1, O result, OutS result_last, + F op, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + @\libconcept{copy_constructible}@ F, class Proj = identity> + requires @\libconcept{indirectly_writable}@, + indirect_result_t, Proj>>> + ranges::unary_transform_result, borrowed_iterator_t> + ranges::transform(Ep&& exec, R&& r, OutR&& result_r, F op, Proj proj = {}); + template<@\libconcept{input_iterator}@ I1, @\libconcept{sentinel_for}@ S1, @\libconcept{input_iterator}@ I2, @\libconcept{sentinel_for}@ S2, @\libconcept{weakly_incrementable}@ O, @\libconcept{copy_constructible}@ F, class Proj1 = identity, class Proj2 = identity> requires @\libconcept{indirectly_writable}@, - projected>> + projected>> constexpr ranges::binary_transform_result ranges::transform(I1 first1, S1 last1, I2 first2, S2 last2, O result, F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); template<@\libconcept{input_range}@ R1, @\libconcept{input_range}@ R2, @\libconcept{weakly_incrementable}@ O, @\libconcept{copy_constructible}@ F, class Proj1 = identity, class Proj2 = identity> requires @\libconcept{indirectly_writable}@, Proj1>, - projected, Proj2>>> + projected, Proj2>>> constexpr ranges::binary_transform_result, borrowed_iterator_t, O> ranges::transform(R1&& r1, R2&& r2, O result, F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, + @\libconcept{copy_constructible}@ F, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_writable}@, + projected>> + ranges::binary_transform_result + ranges::transform(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + O result, OutS result_last, + F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + @\exposconcept{sized-random-access-range}@ OutR, @\libconcept{copy_constructible}@ F, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_writable}@, + indirect_result_t, Proj1>, + projected, Proj2>>> + ranges::binary_transform_result, borrowed_iterator_t, + borrowed_iterator_t> + ranges::transform(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, + F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} @@ -5352,13 +7046,19 @@ \setlength{\emergencystretch}{1em} \item \tcode{last2} be \tcode{first2 + (last1 - first1)} - for the overloads with parameter \tcode{first2} + for the overloads in namespace \tcode{std} + with parameter \tcode{first2} but no parameter \tcode{last2}; \item - $N$ be \tcode{last1 - first1} for unary transforms, or + $M$ be \tcode{last1 - first1} for unary transforms, or $\min(\tcode{last1 - first1}, \ \tcode{last2 - first2})$ for binary transforms; \item - $E$ be + \tcode{result_last} be \tcode{result + $M$} + for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; +\item + $N$ be $\min(M, \ \tcode{result_last - result})$; +\item + $E(\tcode{i})$ be \begin{itemize} \item \tcode{op(*(first1 + (i - result)))} @@ -5377,6 +7077,9 @@ \pnum \expects +For parallel algorithm overloads +\tcode{op} and \tcode{binary_op} satisfy the requirements +specified in \ref{algorithms.parallel.user}. \tcode{op} and \tcode{binary_op} do not invalidate iterators or subranges, nor modify elements in the ranges \begin{itemize} @@ -5392,7 +7095,7 @@ \effects Assigns through every iterator \tcode{i} in the range \range{result}{result + $N$} -a new corresponding value equal to $E$. +a new corresponding value equal to $E(\tcode{i})$. \pnum \returns @@ -5412,7 +7115,7 @@ \complexity Exactly $N$ applications of \tcode{op} or \tcode{binary_op}, and any projections. -This requirement also applies to the overload with an \tcode{ExecutionPolicy}. +This requirement also applies to the parallel algorithm overloads. \pnum \remarks @@ -5424,46 +7127,81 @@ \indexlibraryglobal{replace}% \indexlibraryglobal{replace_if}% \begin{itemdecl} -template +template::value_type> constexpr void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); -template +template::value_type> void replace(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); -template +template::value_type> constexpr void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); -template +template::value_type> void replace_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T1, class T2, class Proj = identity> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T1 = projected_value_t, class T2 = T1> requires @\libconcept{indirectly_writable}@ && @\libconcept{indirect_binary_predicate}@, const T1*> constexpr I ranges::replace(I first, S last, const T1& old_value, const T2& new_value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T1, class T2, class Proj = identity> +template<@\libconcept{input_range}@ R, class Proj = identity, + class T1 = projected_value_t, Proj>, class T2 = T1> requires @\libconcept{indirectly_writable}@, const T2&> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> constexpr borrowed_iterator_t ranges::replace(R&& r, const T1& old_value, const T2& new_value, Proj proj = {}); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T1 = projected_value_t, class T2 = T1> + requires @\libconcept{indirectly_writable}@ && + @\libconcept{indirect_binary_predicate}@, const T1*> + I ranges::replace(Ep&& exec, I first, S last, + const T1& old_value, const T2& new_value, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T1 = projected_value_t, Proj>, class T2 = T1> + requires @\libconcept{indirectly_writable}@, const T2&> && + @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> + borrowed_iterator_t + ranges::replace(Ep&& exec, R&& r, const T1& old_value, const T2& new_value, + Proj proj = {}); + +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{indirectly_writable}@ constexpr I ranges::replace_if(I first, S last, Pred pred, const T& new_value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T, class Proj = identity, +template<@\libconcept{input_range}@ R, class Proj = identity, class T = projected_value_t, Proj>, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_writable}@, const T&> constexpr borrowed_iterator_t ranges::replace_if(R&& r, Pred pred, const T& new_value, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T = projected_value_t, + @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{indirectly_writable}@ + I ranges::replace_if(Ep&& exec, I first, S last, Pred pred, + const T& new_value, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{indirectly_writable}@, const T&> + borrowed_iterator_t + ranges::replace_if(Ep&& exec, R&& r, Pred pred, const T& new_value, Proj proj = {}); \end{itemdecl} \begin{itemdescr} \pnum -Let $E$ be +Let $E(\tcode{i})$ be \begin{itemize} \item \tcode{bool(*i == old_value)} for \tcode{replace}; \item \tcode{bool(pred(*i))} for \tcode{replace_if}; @@ -5471,7 +7209,6 @@ \item \tcode{bool(invoke(pred, invoke(proj, *i)))} for \tcode{ranges::replace_if}. \end{itemize} - \pnum \mandates \tcode{new_value} is writable\iref{iterator.requirements.general} to \tcode{first}. @@ -5480,7 +7217,7 @@ \effects Substitutes elements referred by the iterator \tcode{i} in the range \range{first}{last} with \tcode{new_value}, -when $E$ is \tcode{true}. +when $E(\tcode{i})$ is \tcode{true}. \pnum \returns @@ -5520,39 +7257,78 @@ ForwardIterator2 result, Predicate pred, const T& new_value); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T1, class T2, @\libconcept{output_iterator}@ O, - class Proj = identity> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class O, + class Proj = identity, class T1 = projected_value_t, class T2 = iter_value_t> requires @\libconcept{indirectly_copyable}@ && - @\libconcept{indirect_binary_predicate}@, const T1*> + @\libconcept{indirect_binary_predicate}@, const T1*> && + @\libconcept{output_iterator}@ constexpr ranges::replace_copy_result ranges::replace_copy(I first, S last, O result, const T1& old_value, const T2& new_value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T1, class T2, @\libconcept{output_iterator}@ O, - class Proj = identity> +template<@\libconcept{input_range}@ R, class O, class Proj = identity, + class T1 = projected_value_t, Proj>, class T2 = iter_value_t> requires @\libconcept{indirectly_copyable}@, O> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> + && @\libconcept{output_iterator}@ constexpr ranges::replace_copy_result, O> ranges::replace_copy(R&& r, O result, const T1& old_value, const T2& new_value, Proj proj = {}); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, @\libconcept{output_iterator}@ O, +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, + class Proj = identity, + class T1 = projected_value_t, class T2 = iter_value_t> + requires @\libconcept{indirectly_copyable}@ && + @\libconcept{indirect_binary_predicate}@, const T1*> && + @\libconcept{indirectly_writable}@ + ranges::replace_copy_result + ranges::replace_copy(Ep&& exec, I first, S last, O result, OutS result_last, + const T1& old_value, const T2& new_value, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + class Proj = identity, class T1 = projected_value_t, Proj>, + class T2 = range_value_t> + requires @\libconcept{indirectly_copyable}@, iterator_t> && + @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> && + @\libconcept{indirectly_writable}@, const T2&> + ranges::replace_copy_result, borrowed_iterator_t> + ranges::replace_copy(Ep&& exec, R&& r, OutR&& result_r, const T1& old_value, + const T2& new_value, Proj proj = {}); + +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S,class O, class T = iter_value_t, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> - requires @\libconcept{indirectly_copyable}@ + requires @\libconcept{indirectly_copyable}@ && @\libconcept{output_iterator}@ constexpr ranges::replace_copy_if_result ranges::replace_copy_if(I first, S last, O result, Pred pred, const T& new_value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class T, @\libconcept{output_iterator}@ O, class Proj = identity, +template<@\libconcept{input_range}@ R, class O, class T = iter_value_t, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> - requires @\libconcept{indirectly_copyable}@, O> + requires @\libconcept{indirectly_copyable}@, O> && @\libconcept{output_iterator}@ constexpr ranges::replace_copy_if_result, O> ranges::replace_copy_if(R&& r, O result, Pred pred, const T& new_value, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class T = iter_value_t, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{indirectly_copyable}@ && @\libconcept{indirectly_writable}@ + ranges::replace_copy_if_result + ranges::replace_copy_if(Ep&& exec, I first, S last, O result, OutS result_last, + Pred pred, const T& new_value, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + class T = range_value_t, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{indirectly_copyable}@, iterator_t> && + @\libconcept{indirectly_writable}@ + ranges::replace_copy_if_result, borrowed_iterator_t> + ranges::replace_copy_if(Ep&& exec, R&& r, OutR&& result_r, Pred pred, const T& new_value, + Proj proj = {}); \end{itemdecl} \begin{itemdescr} \setlength{\emergencystretch}{1.5em} \pnum -Let $E$ be +Let $E(\tcode{i})$ be \begin{itemize} \item \tcode{bool(*(first + (i - result)) == old_value)} for \tcode{replace_copy}; @@ -5564,6 +7340,16 @@ for \tcode{ranges::replace_\-copy_if}. \end{itemize} +\pnum +Let: +\begin{itemize} +\item + \tcode{result_last} be \tcode{result + (last - first)} + for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; +\item + $N$ be $\min(\tcode{last - first}, \ \tcode{result_last - result})$. +\end{itemize} + \pnum \mandates The results of the expressions \tcode{*first} and \tcode{new_value} @@ -5571,16 +7357,16 @@ \pnum \expects -The ranges \range{first}{last} and \range{result}{result + (last - first)} +The ranges \range{first}{last} and \range{result}{result + $N$} do not overlap. \pnum \effects Assigns through every iterator \tcode{i} -in the range \range{result}{result + (last - first)} +in the range \range{result}{result + $N$} a new corresponding value \begin{itemize} -\item \tcode{new_value} if $E$ is \tcode{true} or +\item \tcode{new_value} if $E(\tcode{i})$ is \tcode{true} or \item \tcode{*(first + (i - result))} otherwise. \end{itemize} @@ -5588,16 +7374,16 @@ \returns \begin{itemize} \item - \tcode{result + (last - first)} + \tcode{result + $N$} for the overloads in namespace \tcode{std}. \item - \tcode{\{last, result + (last - first)\}} + \tcode{\{first + $N$, result + $N$\}} for the overloads in namespace \tcode{ranges}. \end{itemize} \pnum \complexity -Exactly \tcode{last - first} applications +Exactly $N$ applications of the corresponding predicate and any projection. \end{itemdescr} @@ -5606,24 +7392,40 @@ \indexlibraryglobal{fill}% \indexlibraryglobal{fill_n}% \begin{itemdecl} -template +template::value_type> constexpr void fill(ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type> void fill(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type> constexpr OutputIterator fill_n(OutputIterator first, Size n, const T& value); -template +template::value_type> ForwardIterator fill_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, const T& value); -template O, @\libconcept{sentinel_for}@ S> +template S, class T = iter_value_t> + requires @\libconcept{output_iterator}@ constexpr O ranges::fill(O first, S last, const T& value); -template R> +template> + requires @\libconcept{output_range}@ constexpr borrowed_iterator_t ranges::fill(R&& r, const T& value); -template O> +template> + requires @\libconcept{output_iterator}@ constexpr O ranges::fill_n(O first, iter_difference_t n, const T& value); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ S, + class T = iter_value_t> + requires @\libconcept{indirectly_writable}@ + O ranges::fill(Ep&& exec, O first, S last, const T& value); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class T = range_value_t> + requires @\libconcept{indirectly_writable}@, const T&> + borrowed_iterator_t fill(Ep&& exec, R&& r, const T& value); +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ O, class T = iter_value_t> + requires @\libconcept{indirectly_writable}@ + O ranges::fill_n(Ep&& exec, O first, iter_difference_t n, const T& value); \end{itemdecl} \begin{itemdescr} @@ -5680,6 +7482,17 @@ template<@\libconcept{input_or_output_iterator}@ O, @\libconcept{copy_constructible}@ F> requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@> constexpr O ranges::generate_n(O first, iter_difference_t n, F gen); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{copy_constructible}@ F> + requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@> + O ranges::generate(Ep&& exec, O first, S last, F gen); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\libconcept{copy_constructible}@ F> + requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@, invoke_result_t> + borrowed_iterator_t ranges::generate(Ep&& exec, R&& r, F gen); +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ O, @\libconcept{copy_constructible}@ F> + requires @\libconcept{invocable}@ && @\libconcept{indirectly_writable}@> + O ranges::generate_n(Ep&& exec, O first, iter_difference_t n, F gen); \end{itemdecl} \begin{itemdescr} @@ -5704,6 +7517,11 @@ \pnum \complexity Exactly $N$ evaluations of \tcode{gen()} and assignments. + +\pnum +\remarks +\tcode{gen} may modify objects via its arguments +for parallel algorithm overloads\iref{algorithms.parallel.user}. \end{itemdescr} \rSec2[alg.remove]{Remove} @@ -5711,10 +7529,11 @@ \indexlibraryglobal{remove}% \indexlibraryglobal{remove_if}% \begin{itemdecl} -template +template::value_type> constexpr ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type> ForwardIterator remove(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); @@ -5727,14 +7546,30 @@ ForwardIterator first, ForwardIterator last, Predicate pred); -template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity> +template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t> requires @\libconcept{indirect_binary_predicate}@, const T*> constexpr subrange ranges::remove(I first, S last, const T& value, Proj proj = {}); -template<@\libconcept{forward_range}@ R, class T, class Proj = identity> +template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{permutable}@> && @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr borrowed_subrange_t ranges::remove(R&& r, const T& value, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, class T = projected_value_t> + requires @\libconcept{indirect_binary_predicate}@, const T*> + subrange + ranges::remove(Ep&& exec, I first, S last, const T& value, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + class T = projected_value_t, Proj>> + requires @\libconcept{permutable}@> && + @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + borrowed_subrange_t + ranges::remove(Ep&& exec, R&& r, const T& value, Proj proj = {}); + template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> constexpr subrange ranges::remove_if(I first, S last, Pred pred, Proj proj = {}); @@ -5743,6 +7578,16 @@ requires @\libconcept{permutable}@> constexpr borrowed_subrange_t ranges::remove_if(R&& r, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + subrange + ranges::remove_if(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{permutable}@> + borrowed_subrange_t + ranges::remove_if(Ep&& exec, R&& r, Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -5796,12 +7641,13 @@ \indexlibraryglobal{remove_copy}% \indexlibraryglobal{remove_copy_if}% \begin{itemdecl} -template +template::value_type> constexpr OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value); template + class T = iterator_traits::value_type> ForwardIterator2 remove_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, @@ -5818,17 +7664,35 @@ ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred); -template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O, class T, - class Proj = identity> +template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O, + class Proj = identity, class T = projected_value_t> requires @\libconcept{indirectly_copyable}@ && @\libconcept{indirect_binary_predicate}@, const T*> constexpr ranges::remove_copy_result ranges::remove_copy(I first, S last, O result, const T& value, Proj proj = {}); -template<@\libconcept{input_range}@ R, @\libconcept{weakly_incrementable}@ O, class T, class Proj = identity> +template<@\libconcept{input_range}@ R, @\libconcept{weakly_incrementable}@ O, class Proj = identity, + class T = projected_value_t, Proj>> requires @\libconcept{indirectly_copyable}@, O> && @\libconcept{indirect_binary_predicate}@, Proj>, const T*> constexpr ranges::remove_copy_result, O> ranges::remove_copy(R&& r, O result, const T& value, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, + class Proj = identity, class T = projected_value_t> + requires @\libconcept{indirectly_copyable}@ && + @\libconcept{indirect_binary_predicate}@, const T*> + ranges::remove_copy_result + ranges::remove_copy(Ep&& exec, I first, S last, O result, OutS result_last, + const T& value, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + class Proj = identity, class T = projected_value_t, Proj>> + requires @\libconcept{indirectly_copyable}@, iterator_t> && + @\libconcept{indirect_binary_predicate}@, Proj>, const T*> + ranges::remove_copy_result, borrowed_iterator_t> + ranges::remove_copy(Ep&& exec, R&& r, OutR&& result_r, const T& value, Proj proj = {}); + template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ O, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{indirectly_copyable}@ @@ -5839,11 +7703,25 @@ requires @\libconcept{indirectly_copyable}@, O> constexpr ranges::remove_copy_if_result, O> ranges::remove_copy_if(R&& r, O result, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{indirectly_copyable}@ + ranges::remove_copy_if_result + ranges::remove_copy_if(Ep&& exec, I first, S last, O result, OutS result_last, + Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{indirectly_copyable}@, iterator_t> + ranges::remove_copy_if_result, borrowed_iterator_t> + ranges::remove_copy_if(Ep&& exec, R&& r, OutR&& result_r, Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} \pnum -Let $E$ be +Let $E(\tcode{i})$ be \begin{itemize} \item \tcode{bool(*i == value)} for \tcode{remove_copy}; \item \tcode{bool(pred(*i))} for \tcode{remove_copy_if}; @@ -5852,8 +7730,17 @@ \end{itemize} \pnum -Let $N$ be the number of elements in \range{first}{last} -for which $E$ is \tcode{false}. +Let: +\begin{itemize} +\item + $M$ be the number of iterators \tcode{i} in \range{first}{last} + for which $E(\tcode{i})$ is \tcode{false}; +\item + \tcode{result_last} be \tcode{result + $M$} + for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; +\item + $N$ be $\min(M, \ \tcode{result_last - result})$. +\end{itemize} \pnum \mandates @@ -5861,30 +7748,46 @@ \pnum \expects -The ranges \range{first}{last} and \range{result}{result + (last - first)} +The ranges \range{first}{last} and \range{result}{result + $N$} do not overlap. \begin{note} -For the overloads with an \tcode{ExecutionPolicy}, -there might be a performance cost +For the parallel algorithm overloads in namespace \tcode{std}, +there can be a performance cost if \tcode{iterator_traits::value_type} does not meet the \oldconcept{\-Move\-Constructible} (\tref{cpp17.moveconstructible}) requirements. +For the parallel algorithm overloads in namespace \tcode{ranges}, +there can be a performance cost +if \tcode{iter_value_t} does not model \libconcept{move_constructible}. \end{note} \pnum \effects -Copies all the elements referred to by the iterator \tcode{i} -in the range \range{first}{last} for which $E$ is \tcode{false}. +Copies the first $N$ elements referred to by the iterator \tcode{i} +in the range \range{first}{last} for which $E(\tcode{i})$ is \tcode{false} +into the range \range{result}{result + $N$}. \pnum \returns \begin{itemize} -\item \tcode{result + $N$}, for the algorithms in namespace \tcode{std}. -\item \tcode{\{last, result + $N$\}}, for the algorithms in namespace \tcode{ranges}. +\item + \tcode{result + $N$}, + for the algorithms in namespace \tcode{std}. +\item + \tcode{\{last, result + $N$\}}, + for the algorithms in namespace \tcode{ranges}, + if $N$ is equal to $M$. +\item + Otherwise, \tcode{\{j, result_last\}}, + for the algorithms in namespace \tcode{ranges}, + where \tcode{j} is the iterator in \range{first}{last} + for which $E(\tcode{j})$ is \tcode{false} + and there are exactly $N$ iterators \tcode{i} in \range{first}{j} + for which $E(\tcode{i})$ is \tcode{false}. \end{itemize} \pnum \complexity -Exactly \tcode{last - first} applications +At most \tcode{last - first} applications of the corresponding predicate and any projection. \pnum @@ -5918,6 +7821,16 @@ requires @\libconcept{permutable}@> constexpr borrowed_subrange_t ranges::unique(R&& r, C comp = {}, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_equivalence_relation}@> C = ranges::equal_to> + requires @\libconcept{permutable}@ + subrange ranges::unique(Ep&& exec, I first, S last, C comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_equivalence_relation}@, Proj>> C = ranges::equal_to> + requires @\libconcept{permutable}@> + borrowed_subrange_t ranges::unique(Ep&& exec, R&& r, C comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -6004,13 +7917,27 @@ @\libconcept{indirectly_copyable_storable}@, O>) constexpr ranges::unique_copy_result, O> ranges::unique_copy(R&& r, O result, C comp = {}, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Proj = identity, + @\libconcept{indirect_equivalence_relation}@> C = ranges::equal_to> + requires @\libconcept{indirectly_copyable}@ + ranges::unique_copy_result + ranges::unique_copy(Ep&& exec, I first, S last, O result, OutS result_last, + C comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR, + class Proj = identity, + @\libconcept{indirect_equivalence_relation}@, Proj>> C = ranges::equal_to> + requires @\libconcept{indirectly_copyable}@, iterator_t> + ranges::unique_copy_result, borrowed_iterator_t> + ranges::unique_copy(Ep&& exec, R&& r, OutR&& result_r, C comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} \pnum Let \tcode{pred} be \tcode{equal_to\{\}} for the overloads in namespace \tcode{std} with no parameter \tcode{pred}, and -let $E$ be +let $E(\tcode{i})$ be \begin{itemize} \setlength{\emergencystretch}{1em} \item @@ -6021,6 +7948,19 @@ for the overloads in namespace \tcode{ranges}. \end{itemize} +\pnum +Let: +\begin{itemize} +\item + $M$ be the number of iterators \tcode{i} in the range \range{first + 1}{last} + for which $E(\tcode{i})$ is \tcode{false}; +\item + \tcode{result_last} be \tcode{result + $M$ + 1} + for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; +\item + $N$ be $\min(M + 1, \ \tcode{result_last - result})$. +\end{itemize} + \pnum \mandates \tcode{*first} is writable\iref{iterator.requirements.general} to \tcode{result}. @@ -6029,7 +7969,7 @@ \expects \begin{itemize} \item - The ranges \range{first}{last} and \range{result}{result+(last-first)} + The ranges \range{first}{last} and \range{result}{result + $N$} do not overlap. \item For the overloads in namespace \tcode{std}: @@ -6050,31 +7990,47 @@ Otherwise, \tcode{T} meets both the \oldconcept{CopyConstructible} (\tref{cpp17.copyconstructible}) and \oldconcept{CopyAssignable} requirements. - \begin{note} - For the overloads with an \tcode{ExecutionPolicy}, - there might be a performance cost - if the value type of \tcode{ForwardIterator1} does not meet both the - \oldconcept{CopyConstructible} and \oldconcept{CopyAssignable} requirements. - \end{note} \end{itemize} \end{itemize} +\begin{note} +For the parallel algorithm overloads in namespace \tcode{std}, +there can be a performance cost +if the value type of \tcode{ForwardIterator1} does not meet both the +\oldconcept{CopyConstructible} and \oldconcept{CopyAssignable} requirements. +For the parallel algorithm overloads in namespace \tcode{ranges}, +there can be a performance cost if \tcode{iter_value_t} +does not model \libconcept{copyable}. +\end{note} \pnum \effects -Copies only the first element from every consecutive group of equal elements -referred to by the iterator \tcode{i} in the range \range{first}{last} -for which $E$ holds. +Copies only the first element from $N$ consecutive groups of equivalent elements +referred to by the iterator \tcode{i} in the range \range{first + 1}{last} +for which $E(\tcode{i})$ holds +into the range \range{result}{result + $N$}. \pnum \returns \begin{itemize} -\item \tcode{result + $N$} for the overloads in namespace \tcode{std}. -\item \tcode{\{last, result + $N$\}} for the overloads in namespace \tcode{ranges}. +\item + \tcode{result + $N$} + for the overloads in namespace \tcode{std}. +\item + \tcode{\{last, result + $N$\}} + for the overloads in namespace \tcode{ranges}, + if $N$ is equal to $M + 1$. +\item + Otherwise, \tcode{\{j, result_last\}} + for the overloads in namespace \tcode{ranges}, + where \tcode{j} is the iterator in \range{first + 1}{last} + for which $E(\tcode{j})$ is \tcode{false} + and there are exactly $N - 1$ iterators \tcode{i} in \range{first + 1}{j} + for which $E(\tcode{i})$ is \tcode{false}. \end{itemize} \pnum \complexity -Exactly \tcode{last - first - 1} applications +At most \tcode{last - first - 1} applications of the corresponding predicate and no more than twice as many applications of any projection. \end{itemdescr} @@ -6095,6 +8051,13 @@ template<@\libconcept{bidirectional_range}@ R> requires @\libconcept{permutable}@> constexpr borrowed_iterator_t ranges::reverse(R&& r); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S> + requires @\libconcept{permutable}@ + I ranges::reverse(Ep&& exec, I first, S last); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R> + requires @\libconcept{permutable}@> + borrowed_iterator_t ranges::reverse(Ep&& exec, R&& r); \end{itemdecl} \begin{itemdescr} @@ -6172,6 +8135,46 @@ Exactly $N$ assignments. \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS> + requires @\libconcept{indirectly_copyable}@ + ranges::reverse_copy_truncated_result + ranges::reverse_copy(Ep&& exec, I first, S last, O result, + OutS result_last); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR> + requires @\libconcept{indirectly_copyable}@, iterator_t> + ranges::reverse_copy_truncated_result, borrowed_iterator_t> + ranges::reverse_copy(Ep&& exec, R&& r, OutR&& result_r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $N$ be $\min(\tcode{last - first}, \ \tcode{result_last - result})$, +and let \exposid{NEW_FIRST} be \tcode{first + (last - first) - $N$}. + +\pnum +\expects +The ranges \range{first}{last} and \range{result}{result + $N$} +do not overlap. + +\pnum +\effects +Copies the range \range{\exposid{NEW_FIRST}}{last} +to the range \range{result}{result + $N$} +such that for every non-negative integer $i < N$ +the following assignment takes place: +\tcode{*(result + $N$ - 1 - $i$) = *(\exposid{NEW_FIRST} + $i$)}. + +\pnum +\returns +\tcode{\{last, \exposid{NEW_FIRST}, result + $N$\}}. + +\pnum +\complexity +Exactly $N$ assignments. +\end{itemdescr} + \rSec2[alg.rotate]{Rotate} \indexlibraryglobal{rotate}% @@ -6186,6 +8189,9 @@ template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S> constexpr subrange ranges::rotate(I first, I middle, S last); +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S> + requires @\libconcept{permutable}@ + subrange ranges::rotate(Ep&& exec, I first, I middle, S last); \end{itemdecl} \begin{itemdescr} @@ -6237,6 +8243,21 @@ \tcode{return ranges::rotate(ranges::begin(r), middle, ranges::end(r));} \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R> + requires @\libconcept{permutable}@> + borrowed_subrange_t ranges::rotate(Ep&& exec, R&& r, iterator_t middle); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return ranges::rotate(std::forward(exec), ranges::begin(r), middle, ranges::end(r)); +\end{codeblock} +\end{itemdescr} + \indexlibraryglobal{rotate_copy}% \begin{itemdecl} template @@ -6286,6 +8307,50 @@ Exactly $N$ assignments. \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS> + requires @\libconcept{indirectly_copyable}@ + ranges::rotate_copy_truncated_result + ranges::rotate_copy(Ep&& exec, I first, I middle, S last, O result, OutS result_last); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $M$ be \tcode{last - first} +and $N$ be $\min(M, \ \tcode{result_last - result})$. + +\pnum +\expects +\range{first}{middle} and \range{middle}{last} +are valid ranges. +The ranges \range{first}{last} and \range{result}{result + $N$} +do not overlap. + +\pnum +\effects +Copies the range \range{first}{last} +to the range \range{result}{result + $N$} +such that for each non-negative integer $i < N$ +the following assignment takes place: +\tcode{*(result + $i$) = *(first + ($i$ + (middle - first)) \% $M$)}. + +\pnum +\returns +\begin{itemize} +\item + \tcode{\{middle + $N$, first, result + $N$\}} + if $N$ is less than \tcode{last - middle}. +\item + Otherwise, + \tcode{\{last, first + ($N$ + (middle - first)) \% $M$, result + $N$\}}. +\end{itemize} + +\pnum +\complexity +Exactly $N$ assignments. +\end{itemdescr} + \begin{itemdecl} template<@\libconcept{forward_range}@ R, @\libconcept{weakly_incrementable}@ O> requires @\libconcept{indirectly_copyable}@, O> @@ -6302,6 +8367,23 @@ \end{codeblock} \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, @\exposconcept{sized-random-access-range}@ OutR> + requires @\libconcept{indirectly_copyable}@, iterator_t> + ranges::rotate_copy_truncated_result, borrowed_iterator_t> + ranges::rotate_copy(Ep&& exec, R&& r, iterator_t middle, OutR&& result_r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return ranges::rotate_copy(std::forward(exec), ranges::begin(r), middle, ranges::end(r), + ranges::begin(result_r), ranges::end(result_r)); +\end{codeblock} +\end{itemdescr} + \rSec2[alg.random.sample]{Sample} \indexlibraryglobal{sample}% @@ -6456,7 +8538,16 @@ 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) + constexpr borrowed_subrange_t ranges::shift_left(R&& r, range_difference_t n); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S> + requires @\libconcept{permutable}@ + subrange + ranges::shift_left(Ep&& exec, I first, S last, iter_difference_t n); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R> + requires @\libconcept{permutable}@> + borrowed_subrange_t + ranges::shift_left(Ep&& exec, R&& r, range_difference_t n); \end{itemdecl} \begin{itemdescr} @@ -6473,7 +8564,7 @@ from position \tcode{first + n + i} into position \tcode{first + i} for each non-negative integer \tcode{i < (last - first) - n}. -For the overloads without an \tcode{ExecutionPolicy} template parameter, +For the non-parallel algorithm overloads, does so in order starting from \tcode{i = 0} and proceeding to \tcode{i = (last - first) - n - 1}. @@ -6482,6 +8573,7 @@ Let \exposid{NEW_LAST} be \tcode{first + (last - first - n)} if \tcode{n < last - first}, otherwise \tcode{first}. +Returns: \begin{itemize} \item \exposid{NEW_LAST} for the overloads in namespace \tcode{std}. @@ -6511,6 +8603,15 @@ template<@\libconcept{forward_range}@ R> requires @\libconcept{permutable}@> constexpr borrowed_subrange_t ranges::shift_right(R&& r, range_difference_t n); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S> + requires @\libconcept{permutable}@ + subrange + ranges::shift_right(Ep&& exec, I first, S last, iter_difference_t n); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R> + requires @\libconcept{permutable}@> + borrowed_subrange_t + ranges::shift_right(Ep&& exec, R&& r, range_difference_t n); \end{itemdecl} \begin{itemdescr} @@ -6530,14 +8631,13 @@ from position \tcode{first + i} into position \tcode{first + n + i} for each non-negative integer \tcode{i < (last - first) - n}. Does so in order starting -from \tcode{i = (last - first) - n - 1} and proceeding to \tcode{i = 0} if: +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, +for the non-parallel algorithm overload in namespace \tcode{std}, +\tcode{Forward\-Iterator} meets the \oldconcept{\-Bi\-directional\-Iterator} requirements, \item -for the overloads in namespace \tcode{ranges}, +for the non-parallel algorithm overloads in namespace \tcode{ranges}, \tcode{I} models \libconcept{bidirectional_iterator}. \end{itemize} @@ -6545,6 +8645,7 @@ \returns Let \exposid{NEW_FIRST} be \tcode{first + n} if \tcode{n < last - first}, otherwise \tcode{last}. +Returns: \begin{itemize} \item \exposid{NEW_FIRST} for the overloads in namespace \tcode{std}. @@ -6680,6 +8781,15 @@ requires @\libconcept{sortable}@, Comp, Proj> constexpr borrowed_iterator_t ranges::sort(R&& r, Comp comp = {}, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Comp = ranges::less, class Proj = identity> + requires @\libconcept{sortable}@ + I ranges::sort(Ep&& exec, I first, S last, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Comp = ranges::less, + class Proj = identity> + requires @\libconcept{sortable}@, Comp, Proj> + borrowed_iterator_t ranges::sort(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -6738,6 +8848,16 @@ requires @\libconcept{sortable}@, Comp, Proj> constexpr borrowed_iterator_t ranges::stable_sort(R&& r, Comp comp = {}, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Comp = ranges::less, class Proj = identity> + requires @\libconcept{sortable}@ + I ranges::stable_sort(Ep&& exec, I first, S last, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Comp = ranges::less, + class Proj = identity> + requires @\libconcept{sortable}@, Comp, Proj> + borrowed_iterator_t + ranges::stable_sort(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -6807,6 +8927,10 @@ requires @\libconcept{sortable}@ constexpr I ranges::partial_sort(I first, I middle, S last, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Comp = ranges::less, class Proj = identity> + requires @\libconcept{sortable}@ + I ranges::partial_sort(Ep&& exec, I first, I middle, S last, Comp comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -6861,6 +8985,25 @@ \end{codeblock} \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, + class Comp = ranges::less, class Proj = identity> + requires @\libconcept{sortable}@, Comp, Proj> + borrowed_iterator_t + ranges::partial_sort(Ep&& exec, R&& r, iterator_t middle, Comp comp = {}, + Proj proj = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return ranges::partial_sort(std::forward(exec), ranges::begin(r), middle, + ranges::end(r), comp, proj); +\end{codeblock} +\end{itemdescr} + \rSec3[partial.sort.copy]{\tcode{partial_sort_copy}} \indexlibraryglobal{partial_sort_copy}% @@ -6909,6 +9052,25 @@ constexpr ranges::partial_sort_copy_result, borrowed_iterator_t> ranges::partial_sort_copy(R1&& r, R2&& result_r, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_copyable}@ && @\libconcept{sortable}@ && + @\libconcept{indirect_strict_weak_order}@, projected> + ranges::partial_sort_copy_result + ranges::partial_sort_copy(Ep&& exec, I1 first, S1 last, I2 result_first, S2 result_last, + Comp comp = {}, Proj1 proj1 = {}, + Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{indirectly_copyable}@, iterator_t> && + @\libconcept{sortable}@, Comp, Proj2> && + @\libconcept{indirect_strict_weak_order}@, Proj1>, + projected, Proj2>> + ranges::partial_sort_copy_result, borrowed_iterator_t> + ranges::partial_sort_copy(Ep&& exec, R1&& r, R2&& result_r, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} @@ -7049,6 +9211,25 @@ \tcode{return ranges::is_sorted_until(first, last, comp, proj) == last;} \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + bool ranges::is_sorted(Ep&& exec, I first, S last, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + bool ranges::is_sorted(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return ranges::is_sorted_until(std::forward(exec), first, last, comp, proj) == last; +\end{codeblock} +\end{itemdescr} + \indexlibraryglobal{is_sorted_until}% \begin{itemdecl} template @@ -7076,6 +9257,16 @@ @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t ranges::is_sorted_until(R&& r, Comp comp = {}, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + I ranges::is_sorted_until(Ep&& exec, I first, S last, Comp comp = {}, + Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + borrowed_iterator_t + ranges::is_sorted_until(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -7120,6 +9311,10 @@ requires @\libconcept{sortable}@ constexpr I ranges::nth_element(I first, I nth, S last, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Comp = ranges::less, class Proj = identity> + requires @\libconcept{sortable}@ + I ranges::nth_element(Ep&& exec, I first, I nth, S last, Comp comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -7155,8 +9350,8 @@ \pnum \complexity -For the overloads with no \tcode{ExecutionPolicy}, linear on average. -For the overloads with an \tcode{ExecutionPolicy}, \bigoh{N} applications of +For the non-parallel algorithm overloads, linear on average. +For the parallel algorithm overloads, \bigoh{N} applications of the predicate, and \bigoh{N \log N} swaps, where $N = \tcode{last - first}$. \end{itemdescr} @@ -7176,6 +9371,24 @@ \end{codeblock} \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Comp = ranges::less, + class Proj = identity> + requires @\libconcept{sortable}@, Comp, Proj> + borrowed_iterator_t + ranges::nth_element(Ep&& exec, R&& r, iterator_t nth, Comp comp = {}, Proj proj = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return ranges::nth_element(std::forward(exec), ranges::begin(r), nth, ranges::end(r), + comp, proj); +\end{codeblock} +\end{itemdescr} + \rSec2[alg.binary.search]{Binary search} \rSec3[alg.binary.search.general]{General} @@ -7196,21 +9409,24 @@ \indexlibraryglobal{lower_bound}% \begin{itemdecl} -template +template::value_type> constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type, + class Compare> constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); -template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, +template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr I ranges::lower_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); -template<@\libconcept{forward_range}@ R, class T, class Proj = identity, +template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t @@ -7244,20 +9460,23 @@ \indexlibraryglobal{upper_bound}% \begin{itemdecl} -template +template::value_type> constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type, + class Compare> constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); -template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, +template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr I ranges::upper_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); -template<@\libconcept{forward_range}@ R, class T, class Proj = identity, +template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t @@ -7291,22 +9510,25 @@ \indexlibraryglobal{equal_range}% \begin{itemdecl} -template +template::value_type> constexpr pair equal_range(ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type, + class Compare> constexpr pair equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); -template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, +template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr subrange ranges::equal_range(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); -template<@\libconcept{forward_range}@ R, class T, class Proj = identity, +template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_subrange_t @@ -7325,7 +9547,7 @@ are partitioned with respect to the expressions \tcode{bool(invoke(comp, invoke(proj, e), value))} and \tcode{!bool(invoke(comp, value, invoke(proj, e)))}. -Also, for all elements \tcode{e} of \tcode{[first, last)}, +Also, for all elements \tcode{e} of \range{first}{last}, \tcode{bool(comp(e, value))} implies \tcode{!bool(comp(\brk{}value, e))} for the overloads in namespace \tcode{std}. @@ -7356,21 +9578,24 @@ \indexlibraryglobal{binary_search}% \begin{itemdecl} -template +template::value_type> constexpr bool binary_search(ForwardIterator first, ForwardIterator last, const T& value); -template +template::value_type, + class Compare> constexpr bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); -template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class T, class Proj = identity, +template<@\libconcept{forward_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, + class T = projected_value_t, @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> constexpr bool ranges::binary_search(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); -template<@\libconcept{forward_range}@ R, class T, class Proj = identity, +template<@\libconcept{forward_range}@ R, class Proj = identity, + class T = projected_value_t, Proj>, @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr bool ranges::binary_search(R&& r, const T& value, Comp comp = {}, @@ -7389,7 +9614,7 @@ are partitioned with respect to the expressions \tcode{bool(invoke(comp, invoke(proj, e), value))} and \tcode{!bool(invoke(comp, value, invoke(proj, e)))}. -Also, for all elements \tcode{e} of \tcode{[first, last)}, +Also, for all elements \tcode{e} of \range{first}{last}, \tcode{bool(comp(e, value))} implies \tcode{!bool(comp(\brk{}value, e))} for the overloads in namespace \tcode{std}. @@ -7422,6 +9647,13 @@ template<@\libconcept{input_range}@ R, class Proj = identity, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> constexpr bool ranges::is_partitioned(R&& r, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + bool ranges::is_partitioned(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + bool ranges::is_partitioned(Ep&& exec, R&& r, Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -7448,8 +9680,7 @@ partition(ForwardIterator first, ForwardIterator last, Predicate pred); template ForwardIterator - partition(ExecutionPolicy&& exec, - ForwardIterator first, ForwardIterator last, Predicate pred); + partition(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); template<@\libconcept{permutable}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> @@ -7460,6 +9691,14 @@ requires @\libconcept{permutable}@> constexpr borrowed_subrange_t ranges::partition(R&& r, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + subrange ranges::partition(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{permutable}@> + borrowed_subrange_t ranges::partition(Ep&& exec, R&& r, Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -7496,7 +9735,7 @@ Let $N = \tcode{last - first}$: \begin{itemize} \item - For the overload with no \tcode{ExecutionPolicy}, + For the non-parallel algorithm overloads, exactly $N$ applications of the predicate and projection. At most $N / 2$ swaps if the type of \tcode{first} meets the \oldconcept{BidirectionalIterator} requirements @@ -7505,7 +9744,7 @@ for the overloads in namespace \tcode{ranges}, and at most $N$ swaps otherwise. \item - For the overload with an \tcode{ExecutionPolicy}, + For the parallel algorithm overloads, \bigoh{N \log N} swaps and \bigoh{N} applications of the predicate. \end{itemize} @@ -7530,6 +9769,17 @@ @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{permutable}@> constexpr borrowed_subrange_t ranges::stable_partition(R&& r, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{permutable}@ + subrange + ranges::stable_partition(Ep&& exec, I first, S last, Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{permutable}@> + borrowed_subrange_t + ranges::stable_partition(Ep&& exec, R&& r, Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -7571,11 +9821,12 @@ Let $N$ = \tcode{last - first}: \begin{itemize} \item - For the overloads with no \tcode{ExecutionPolicy}, at most $N \log_2 N$ swaps, + For the non-parallel algorithm overloads, + at most $N \log_2 N$ swaps, but only \bigoh{N} swaps if there is enough extra memory. Exactly $N$ applications of the predicate and projection. \item - For the overload with an \tcode{ExecutionPolicy}, + For the parallel algorithm overloads, \bigoh{N \log N} swaps and \bigoh{N} applications of the predicate. \end{itemize} \end{itemdescr} @@ -7606,6 +9857,25 @@ @\libconcept{indirectly_copyable}@, O2> constexpr ranges::partition_copy_result, O1, O2> ranges::partition_copy(R&& r, O1 out_true, O2 out_false, Pred pred, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + @\libconcept{random_access_iterator}@ O1, @\libconcept{sized_sentinel_for}@ OutS1, + @\libconcept{random_access_iterator}@ O2, @\libconcept{sized_sentinel_for}@ OutS2, + class Proj = identity, @\libconcept{indirect_unary_predicate}@> Pred> + requires @\libconcept{indirectly_copyable}@ && @\libconcept{indirectly_copyable}@ + ranges::partition_copy_result + ranges::partition_copy(Ep&& exec, I first, S last, O1 out_true, OutS1 last_true, + O2 out_false, OutS2 last_false, Pred pred, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, + @\exposconcept{sized-random-access-range}@ OutR1, @\exposconcept{sized-random-access-range}@ OutR2, + class Proj = identity, + @\libconcept{indirect_unary_predicate}@, Proj>> Pred> + requires @\libconcept{indirectly_copyable}@, iterator_t> && + @\libconcept{indirectly_copyable}@, iterator_t> + ranges::partition_copy_result, borrowed_iterator_t, + borrowed_iterator_t> + ranges::partition_copy(Ep&& exec, R&& r, OutR1&& out_true_r, OutR2&& out_false_r, + Pred pred, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -7614,6 +9884,45 @@ for the overloads with no parameter named \tcode{proj} and let $E(x)$ be \tcode{bool(invoke(\brk{}pred, invoke(proj, $x$)))}. +\pnum +For the overloads with no parameters +\tcode{last_true}, \tcode{last_false}, \tcode{out_true_r}, or \tcode{out_false_r}, +let +\begin{itemize} +\item + $M$ be the number of iterators \tcode{i} in \range{first}{last} + for which $E(\tcode{*i})$ is \tcode{true}, + and $K$ be \tcode{last - first - $M$}; +\item + \tcode{last_true} be \tcode{out_true + $M$}, and + \tcode{last_false} be \tcode{out_false + $K$}. +\end{itemize} + +\pnum +For the overloads with parameters +\tcode{last_true}, \tcode{last_false}, \tcode{out_true_r}, or \tcode{out_false_r}, +let $M$ be \tcode{last_true - out_true} +and $K$ be \tcode{last_false - out_false}. + +\pnum +Let: +\begin{itemize} +\item + \tcode{i1} be the iterator in \range{first}{last} + for which $E(\tcode{*i1})$ is \tcode{true} + and there are exactly $M$ iterators \tcode{j} in \range{first}{\tcode{i1}} + for which $E(\tcode{*j})$ is \tcode{true}, + or \tcode{last} if no such iterator exists; +\item + \tcode{i2} be the iterator in \range{first}{last} + for which $E(\tcode{*i2})$ is \tcode{false} + and there are exactly $K$ iterators \tcode{j} in \range{first}{\tcode{i2}} + for which $E(\tcode{*j})$ is \tcode{false}, + or \tcode{last} if no such iterator exists; +\item + $N$ be $\min(\tcode{i1 - first}, \ \tcode{i2 - first})$. +\end{itemize} + \pnum \mandates For the overloads in namespace \tcode{std}, @@ -7626,31 +9935,36 @@ The input range and output ranges do not overlap. \begin{note} -For the overload with an \tcode{ExecutionPolicy}, -there might be a performance cost if \tcode{first}'s value type +For the parallel algorithm overload in namespace \tcode{std}, +there can be a performance cost if \tcode{first}'s value type does not meet the \oldconcept{CopyConstructible} requirements. +For the parallel algorithm overloads in namespace \tcode{ranges}, +there can be a performance cost if \tcode{first}'s value type +does not model \libconcept{copy_constructible}. \end{note} \pnum \effects -For each iterator \tcode{i} in \range{first}{last}, -copies \tcode{*i} to the output range beginning with \tcode{out_true} +For each iterator \tcode{i} in \range{first}{first + $N$}, +copies \tcode{*i} to the output range \range{out_true}{last_true} if \tcode{$E(\tcode{*i})$} is \tcode{true}, or -to the output range beginning with \tcode{out_false} otherwise. +to the output range \range{out_false}{last_false} otherwise. \pnum \returns -Let \tcode{o1} be the end of the output range beginning at \tcode{out_true}, -and \tcode{o2} the end of the output range beginning at \tcode{out_false}. -Returns +Let \tcode{o1} be the iterator past the last copied element +in the output range \range{out_true}{last_true}, +and \tcode{o2} be the iterator past the last copied element +in the output range \range{out_false}{last_false}. +Returns: \begin{itemize} \item \tcode{\{o1, o2\}} for the overloads in namespace \tcode{std}. -\item \tcode{\{last, o1, o2\}} for the overloads in namespace \tcode{ranges}. +\item \tcode{\{first + $N$, o1, o2\}} for the overloads in namespace \tcode{ranges}. \end{itemize} \pnum \complexity -Exactly \tcode{last - first} applications of \tcode{pred} and \tcode{proj}. +At most \tcode{last - first} applications of \tcode{pred} and \tcode{proj}. \end{itemdescr} \indexlibraryglobal{partition_point}% @@ -7737,15 +10051,56 @@ constexpr ranges::merge_result, borrowed_iterator_t, O> ranges::merge(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@ + ranges::merge_result + ranges::merge(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, O result, OutS result_last, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + @\exposconcept{sized-random-access-range}@ OutR, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@, iterator_t, iterator_t, Comp, Proj1, Proj2> + ranges::merge_result, borrowed_iterator_t, borrowed_iterator_t> + ranges::merge(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} \pnum -Let $N$ be \tcode{(last1 - first1) + (last2 - first2)}. -Let \tcode{comp} be \tcode{less\{\}}, -\tcode{proj1} be \tcode{identity\{\}}, and -\tcode{proj2} be \tcode{identity\{\}}, -for the overloads with no parameters by those names. +Let: +\begin{itemize} +\item + $N$ be: + \begin{itemize} + \item + \tcode{(last1 - first1) + (last2 - first2)} + for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; + \item + $\min(\tcode{(last1 - first1) + (last2 - first2)}, \ \tcode{result_last - result})$ + for the overloads with parameters \tcode{result_last} or \tcode{result_r}; + \end{itemize} +\item + \tcode{comp} be \tcode{less\{\}}, + \tcode{proj1} be \tcode{identity\{\}}, and + \tcode{proj2} be \tcode{identity\{\}}, + for the overloads with no parameters by those names; +\item + $E(\tcode{e1}, \tcode{e1})$ be \tcode{bool(invoke(comp, invoke(proj2, e2), invoke(proj1, e1)))}; +\item + $K$ be the smallest integer in \range{0}{last1 - first1} + such that for the element \tcode{e1} in the position \tcode{first1 + $K$} + there are at least $N - K$ elements \tcode{e2} + in \range{first2}{last2} for which $E(\tcode{e1}, \tcode{e1})$ holds, + and be equal to \tcode{last1 - first1} + if no such integer exists. + \begin{note} + \tcode{first1 + $K$} points to the position past the last element to be copied. + \end{note} +\end{itemize} \pnum \expects @@ -7756,25 +10111,24 @@ \pnum \effects -Copies all the elements of the two ranges \range{first1}{last1} and -\range{first2}{last2} into the range \range{result}{result_last}, -where \tcode{result_last} is \tcode{result + $N$}. +Copies the first $K$ elements of the range \range{first1}{last1} +and the first $N - K$ elements of the range \range{first2}{last2} +into the range \range{result}{result + $N$}. If an element \tcode{a} precedes \tcode{b} in an input range, \tcode{a} is copied into the output range before \tcode{b}. If \tcode{e1} is an element of \range{first1}{last1} and \tcode{e2} of \range{first2}{last2}, -\tcode{e2} is copied into the output range before \tcode{e1} if and only if -\tcode{bool(invoke(comp, invoke(proj2, e2), invoke(proj1, e1)))} -is \tcode{true}. +\tcode{e2} is copied into the output range before \tcode{e1} +if and only if $E(\tcode{e1}, \tcode{e1})$ is \tcode{true}. \pnum \returns \begin{itemize} \item - \tcode{result_last} + \tcode{result + $N$} for the overloads in namespace \tcode{std}. \item - \tcode{\{last1, last2, result_last\}} + \tcode{\{first1 + $K$, first2 + $N$ - $K$, result + $N$\}} for the overloads in namespace \tcode{ranges}. \end{itemize} @@ -7782,10 +10136,11 @@ \complexity \begin{itemize} \item - For the overloads with no \tcode{ExecutionPolicy}, + For the non-parallel algorithm overloads, at most $N - 1$ comparisons and applications of each projection. \item - For the overloads with an \tcode{ExecutionPolicy}, \bigoh{N} comparisons. + For the parallel algorithm overloads, + \bigoh{N} comparisons and applications of each projection. \end{itemize} \pnum @@ -7819,6 +10174,10 @@ class Proj = identity> requires @\libconcept{sortable}@ constexpr I ranges::inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Comp = ranges::less, class Proj = identity> + requires @\libconcept{sortable}@ + I ranges::inplace_merge(Ep&& exec, I first, I middle, S last, Comp comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -7854,8 +10213,8 @@ Let $N = \tcode{last - first}$: \begin{itemize} \item - For the overloads with no \tcode{ExecutionPolicy}, and - if enough additional memory is available, exactly $N - 1$ comparisons. + For the non-parallel algorithm overloads, and + if enough additional memory is available, at most $N - 1$ comparisons. \item Otherwise, \bigoh{N \log N} comparisons. \end{itemize} @@ -7882,6 +10241,25 @@ \end{codeblock} \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Comp = ranges::less, + class Proj = identity> + requires @\libconcept{sortable}@, Comp, Proj> + borrowed_iterator_t + ranges::inplace_merge(Ep&& exec, R&& r, iterator_t middle, Comp comp = {}, + Proj proj = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return ranges::inplace_merge(std::forward(exec), ranges::begin(r), middle, + ranges::end(r), comp, proj); +\end{codeblock} +\end{itemdescr} + \rSec2[alg.set.operations]{Set operations on sorted structures} \rSec3[alg.set.operations.general]{General} @@ -7929,6 +10307,20 @@ projected, Proj2>> Comp = ranges::less> constexpr bool ranges::includes(R1&& r1, R2&& r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Proj1 = identity, class Proj2 = identity, + @\libconcept{indirect_strict_weak_order}@, projected> Comp = + ranges::less> + bool ranges::includes(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Proj1 = identity, class Proj2 = identity, + @\libconcept{indirect_strict_weak_order}@, Proj1>, + projected, Proj2>> Comp = ranges::less> + bool ranges::includes(Ep&& exec, R1&& r1, R2&& r2, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} @@ -8002,13 +10394,43 @@ constexpr ranges::set_union_result, borrowed_iterator_t, O> ranges::set_union(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@ + ranges::set_union_result + ranges::set_union(Ep&& exec, I1 first1, S1 last1, + I2 first2, S2 last2, O result, OutS result_last, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + @\exposconcept{sized-random-access-range}@ OutR, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@, iterator_t, iterator_t, Comp, Proj1, Proj2> + ranges::set_union_result, borrowed_iterator_t, + borrowed_iterator_t> + ranges::set_union(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{comp} be \tcode{less\{\}}, -and \tcode{proj1} and \tcode{proj2} be \tcode{identity\{\}} -for the overloads with no parameters by those names. +Let: +\begin{itemize} +\item + \tcode{comp} be \tcode{less\{\}}, + and \tcode{proj1} and \tcode{proj2} be \tcode{identity\{\}} + for the overloads with no parameters by those names; +\item + $M$ be \tcode{last1 - first1} plus the number of elements in \range{first2}{last2} + that are not present in \range{first1}{last1}; +\item + \tcode{result_last} be \tcode{result + $M$} + for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; +\item + $N$ be $\min(M, \ \tcode{result_last - result})$. +\end{itemize} \pnum \expects @@ -8018,20 +10440,25 @@ \pnum \effects -Constructs a sorted union of the elements from the two ranges; +Constructs a sorted union of $N$ elements from the two ranges; that is, the set of elements that are present in one or both of the ranges. \pnum \returns -Let \tcode{result_last} be the end of the constructed range. -Returns \begin{itemize} \item \tcode{result_last} for the overloads in namespace \tcode{std}. \item - \tcode{\{last1, last2, result_last\}} - for the overloads in namespace \tcode{ranges}. + \tcode{\{last1, last2, result + $N$\}} + for the overloads in namespace \tcode{ranges}, + if $N$ is equal to $M$. +\item + Otherwise, \tcode{\{j1, j2, result_last\}} + for the overloads in namespace \tcode{ranges}, + where the iterators \tcode{j1} and \tcode{j2} + point to positions past the last copied or skipped elements + in \range{first1}{last1} and \range{first2}{last2}, respectively. \end{itemize} \pnum @@ -8097,13 +10524,43 @@ constexpr ranges::set_intersection_result, borrowed_iterator_t, O> ranges::set_intersection(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@ + ranges::set_intersection_result + ranges::set_intersection(Ep&& exec, I1 first1, S1 last1, + I2 first2, S2 last2, O result, OutS result_last, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + @\exposconcept{sized-random-access-range}@ OutR, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@, iterator_t, iterator_t, Comp, Proj1, Proj2> + ranges::set_intersection_result, borrowed_iterator_t, + borrowed_iterator_t> + ranges::set_intersection(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{comp} be \tcode{less\{\}}, -and \tcode{proj1} and \tcode{proj2} be \tcode{identity\{\}} -for the overloads with no parameters by those names. +Let: +\begin{itemize} +\item + \tcode{comp} be \tcode{less\{\}}, + and \tcode{proj1} and \tcode{proj2} be \tcode{identity\{\}} + for the overloads with no parameters by those names; +\item + $M$ be the number of elements in \range{first1}{last1} + that are present in \range{first2}{last2}; +\item + \tcode{result_last} be \tcode{result + $M$} + for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; +\item + $N$ be $\min(M, \ \tcode{result_last - result})$. +\end{itemize} \pnum \expects @@ -8113,20 +10570,25 @@ \pnum \effects -Constructs a sorted intersection of the elements from the two ranges; +Constructs a sorted intersection of $N$ elements from the two ranges; that is, the set of elements that are present in both of the ranges. \pnum \returns -Let \tcode{result_last} be the end of the constructed range. -Returns \begin{itemize} \item \tcode{result_last} for the overloads in namespace \tcode{std}. \item - \tcode{\{last1, last2, result_last\}} - for the overloads in namespace \tcode{ranges}. + \tcode{\{last1, last2, result + $N$\}} + for the overloads in namespace \tcode{ranges}, + if $N$ is equal to $M$. +\item + Otherwise, \tcode{\{j1, j2, result_last\}} + for the overloads in namespace \tcode{ranges}, + where the iterators \tcode{j1} and \tcode{j2} + point to positions past the last copied or skipped elements + in \range{first1}{last1} and \range{first2}{last2}, respectively. \end{itemize} \pnum @@ -8190,13 +10652,42 @@ constexpr ranges::set_difference_result, O> ranges::set_difference(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@ + ranges::set_difference_result + ranges::set_difference(Ep&& exec, I1 first1, S1 last1, + I2 first2, S2 last2, O result, OutS result_last, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + @\exposconcept{sized-random-access-range}@ OutR, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@, iterator_t, iterator_t, Comp, Proj1, Proj2> + ranges::set_difference_result, borrowed_iterator_t> + ranges::set_difference(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{comp} be \tcode{less\{\}}, -and \tcode{proj1} and \tcode{proj2} be \tcode{identity\{\}} -for the overloads with no parameters by those names. +Let: +\begin{itemize} +\item + \tcode{comp} be \tcode{less\{\}}, + and \tcode{proj1} and \tcode{proj2} be \tcode{identity\{\}} + for the overloads with no parameters by those names; +\item + $M$ be the number of elements in \range{first1}{last1} + that are not present in \range{first2}{last2}; +\item + \tcode{result_last} be \tcode{result + $M$} + for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; +\item + $N$ be $\min(M, \ \tcode{result_last - result})$. +\end{itemize} \pnum \expects @@ -8206,22 +10697,27 @@ \pnum \effects -Copies the elements of the range \range{first1}{last1} +Copies $N$ elements of the range \range{first1}{last1} which are not present in the range \range{first2}{last2} -to the range beginning at \tcode{result}. +to the range \range{result}{result + $N$}. The elements in the constructed range are sorted. \pnum \returns -Let \tcode{result_last} be the end of the constructed range. -Returns \begin{itemize} \item \tcode{result_last} for the overloads in namespace \tcode{std}. \item - \tcode{\{last1, result_last\}} - for the overloads in namespace \tcode{ranges}. + \tcode{\{last1, result + $N$\}} + for the overloads in namespace \tcode{ranges}, + if $N$ is equal to $M$. +\item + Otherwise, \tcode{\{j1, result_last\}} + for the overloads in namespace \tcode{ranges}, + where the iterator \tcode{j1} + points to positions past the last copied or skipped elements + in \range{first1}{last1} and \range{first2}{last2}, respectively. \end{itemize} \pnum @@ -8286,13 +10782,44 @@ borrowed_iterator_t, O> ranges::set_symmetric_difference(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + @\libconcept{random_access_iterator}@ O, @\libconcept{sized_sentinel_for}@ OutS, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@ + ranges::set_symmetric_difference_result + ranges::set_symmetric_difference(Ep&& exec, I1 first1, S1 last1, + I2 first2, S2 last2, O result, OutS result_last, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + @\exposconcept{sized-random-access-range}@ OutR, class Comp = ranges::less, + class Proj1 = identity, class Proj2 = identity> + requires @\libconcept{mergeable}@, iterator_t, iterator_t, Comp, Proj1, Proj2> + ranges::set_symmetric_difference_result, borrowed_iterator_t, + borrowed_iterator_t> + ranges::set_symmetric_difference(Ep&& exec, R1&& r1, R2&& r2, OutR&& result_r, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{comp} be \tcode{less\{\}}, -and \tcode{proj1} and \tcode{proj2} be \tcode{identity\{\}} -for the overloads with no parameters by those names. +Let: +\begin{itemize} +\item + \tcode{comp} be \tcode{less\{\}}, + and \tcode{proj1} and \tcode{proj2} be \tcode{identity\{\}} + for the overloads with no parameters by those names; +\item + $K$ be the number of elements in \range{first1}{last1} that are not present in \range{first2}{last2}. +\item + $M$ be the number of elements in \range{first2}{last2} that are not present in \range{first1}{last1}. +\item + \tcode{result_last} be \tcode{result + $M$ + $K$} + for the overloads with no parameter \tcode{result_last} or \tcode{result_r}; +\item + $N$ be $\min(K + M, \ \tcode{result_last - result})$. +\end{itemize} \pnum \expects @@ -8306,20 +10833,25 @@ that are not present in the range \range{first2}{last2}, and the elements of the range \range{first2}{last2} that are not present in the range \range{first1}{last1} -to the range beginning at \tcode{result}. +to the range \range{result}{result + $N$}. The elements in the constructed range are sorted. \pnum \returns -Let \tcode{result_last} be the end of the constructed range. -Returns \begin{itemize} \item \tcode{result_last} for the overloads in namespace \tcode{std}. \item - \tcode{\{last1, last2, result_last\}} - for the overloads in namespace \tcode{ranges}. + \tcode{\{last1, last2, result + $N$\}} + for the overloads in namespace \tcode{ranges}, + if $N$ is equal to $M + K$. +\item + Otherwise, \tcode{\{j1, j2, result_last\}} + for the overloads in namespace \tcode{ranges}, + where the iterators \tcode{j1} and \tcode{j2} + point to positions past the last copied or skipped elements + in \range{first1}{last1} and \range{first2}{last2}, respectively. \end{itemize} \pnum @@ -8662,6 +11194,25 @@ \tcode{return ranges::is_heap_until(first, last, comp, proj) == last;} \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + bool ranges::is_heap(Ep&& exec, I first, S last, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + bool ranges::is_heap(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return ranges::is_heap_until(std::forward(exec), first, last, comp, proj) == last; +\end{codeblock} +\end{itemdescr} + \indexlibraryglobal{is_heap_until}% \begin{itemdecl} template @@ -8689,6 +11240,15 @@ @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t ranges::is_heap_until(R&& r, Comp comp = {}, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + I ranges::is_heap_until(Ep&& exec, I first, S last, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + borrowed_iterator_t + ranges::is_heap_until(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -8760,6 +11320,11 @@ requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr range_value_t ranges::min(R&& r, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> + range_value_t + ranges::min(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -8838,6 +11403,11 @@ requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr range_value_t ranges::max(R&& r, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> + range_value_t + ranges::max(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -8919,6 +11489,11 @@ requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> constexpr ranges::minmax_result> ranges::minmax(R&& r, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + requires @\libconcept{indirectly_copyable_storable}@, range_value_t*> + ranges::minmax_result> + ranges::minmax(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -8974,6 +11549,16 @@ @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t ranges::min_element(R&& r, Comp comp = {}, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + I ranges::min_element(Ep&& exec, I first, S last, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + borrowed_iterator_t + ranges::min_element(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -9021,6 +11606,16 @@ @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t ranges::max_element(R&& r, Comp comp = {}, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + I ranges::max_element(Ep&& exec, I first, S last, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + borrowed_iterator_t + ranges::max_element(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); \end{itemdecl} \begin{itemdescr} @@ -9071,6 +11666,16 @@ @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> constexpr ranges::minmax_element_result> ranges::minmax_element(R&& r, Comp comp = {}, Proj proj = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, + class Proj = identity, + @\libconcept{indirect_strict_weak_order}@> Comp = ranges::less> + ranges::minmax_element_result + ranges::minmax_element(Ep&& exec, I first, S last, Comp comp = {}, Proj proj = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, + @\libconcept{indirect_strict_weak_order}@, Proj>> Comp = ranges::less> + ranges::minmax_element_result> + ranges::minmax_element(Ep&& exec, R&& r, Comp comp = {}, Proj proj = {}); \end{itemdecl} @@ -9179,6 +11784,20 @@ constexpr bool ranges::lexicographical_compare(R1&& r1, R2&& r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); + +template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I1, @\libconcept{sized_sentinel_for}@ S1, + @\libconcept{random_access_iterator}@ I2, @\libconcept{sized_sentinel_for}@ S2, + class Proj1 = identity, class Proj2 = identity, + @\libconcept{indirect_strict_weak_order}@, + projected> Comp = ranges::less> + bool ranges::lexicographical_compare(Ep&& exec, I1 first1, S1 last1, I2 first2, S2 last2, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); +template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R1, @\exposconcept{sized-random-access-range}@ R2, + class Proj1 = identity, class Proj2 = identity, + @\libconcept{indirect_strict_weak_order}@, Proj1>, + projected, Proj2>> Comp = ranges::less> + bool ranges::lexicographical_compare(Ep&& exec, R1&& r1, R2&& r2, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); \end{itemdecl} \begin{itemdescr} @@ -9210,7 +11829,7 @@ \tcode{ranges::lexicographical_compare(I1, S1, I2, S2, Comp, Proj1, Proj2)} can be implemented as: \begin{codeblock} -for ( ; first1 != last1 && first2 != last2 ; ++first1, (void) ++first2) { +for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) { if (invoke(comp, invoke(proj1, *first1), invoke(proj2, *first2))) return true; if (invoke(comp, invoke(proj2, *first2), invoke(proj1, *first1))) return false; } @@ -9398,6 +12017,7 @@ \indexheader{numeric}% \begin{codeblock} +// mostly freestanding namespace std { // \ref{accumulate}, accumulate template @@ -9417,13 +12037,13 @@ BinaryOperation binary_op); template typename iterator_traits::value_type - reduce(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + reduce(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last); template - T reduce(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + T reduce(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, T init); template - T reduce(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + T reduce(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, T init, BinaryOperation binary_op); // \ref{inner.product}, inner product @@ -9451,19 +12071,19 @@ BinaryOperation binary_op, UnaryOperation unary_op); template - T transform_reduce(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + T transform_reduce(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, T init); template - T transform_reduce(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + T transform_reduce(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2); template - T transform_reduce(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + T transform_reduce(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, T init, BinaryOperation binary_op, UnaryOperation unary_op); @@ -9488,13 +12108,13 @@ OutputIterator result, T init, BinaryOperation binary_op); template ForwardIterator2 - exclusive_scan(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + exclusive_scan(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init); template ForwardIterator2 - exclusive_scan(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + exclusive_scan(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init, BinaryOperation binary_op); @@ -9513,19 +12133,19 @@ OutputIterator result, BinaryOperation binary_op, T init); template ForwardIterator2 - inclusive_scan(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + inclusive_scan(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); template ForwardIterator2 - inclusive_scan(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + inclusive_scan(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op); template ForwardIterator2 - inclusive_scan(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + inclusive_scan(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, T init); @@ -9539,7 +12159,7 @@ template ForwardIterator2 - transform_exclusive_scan(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + transform_exclusive_scan(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init, BinaryOperation binary_op, UnaryOperation unary_op); @@ -9560,14 +12180,14 @@ template ForwardIterator2 - transform_inclusive_scan(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + transform_inclusive_scan(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, UnaryOperation unary_op); template ForwardIterator2 - transform_inclusive_scan(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + transform_inclusive_scan(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, UnaryOperation unary_op, T init); @@ -9583,13 +12203,13 @@ OutputIterator result, BinaryOperation binary_op); template ForwardIterator2 - adjacent_difference(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + adjacent_difference(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); template ForwardIterator2 - adjacent_difference(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} + adjacent_difference(ExecutionPolicy&& exec, // freestanding-deleted, see \ref{algorithms.parallel.overloads} ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op); @@ -9599,7 +12219,7 @@ namespace ranges { template - using iota_result = out_value_result; + using @\libglobal{iota_result}@ = out_value_result; template<@\libconcept{input_or_output_iterator}@ O, @\libconcept{sentinel_for}@ S, @\libconcept{weakly_incrementable}@ T> requires @\libconcept{indirectly_writable}@ @@ -9625,15 +12245,15 @@ // \ref{numeric.sat}, saturation arithmetic template - constexpr T add_sat(T x, T y) noexcept; // freestanding + constexpr T add_sat(T x, T y) noexcept; template - constexpr T sub_sat(T x, T y) noexcept; // freestanding + constexpr T sub_sat(T x, T y) noexcept; template - constexpr T mul_sat(T x, T y) noexcept; // freestanding + constexpr T mul_sat(T x, T y) noexcept; template - constexpr T div_sat(T x, T y) noexcept; // freestanding + constexpr T div_sat(T x, T y) noexcept; template - constexpr T saturate_cast(U x) noexcept; // freestanding + constexpr T saturate_cast(U x) noexcept; } \end{codeblock} @@ -9651,24 +12271,24 @@ \indexlibrary{generalized_noncommutative_sum@\tcode{\placeholder{GENERALIZED_NONCOMMUTATIVE_SUM}}}% \pnum -Define \tcode{\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(op, a1, ..., aN)} +Define \tcode{\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(op, a1, $\dotsc$, aN)} as follows: \begin{itemize} \item \tcode{a1} when \tcode{N} is \tcode{1}, otherwise \item -\tcode{op(\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(op, a1, ..., aK),} \\ -\tcode{\phantom{op(}\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(op, aM, ..., aN))} +\tcode{op(\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(op, a1, $\dotsc$, aK),} \\ +\tcode{\phantom{op(}\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(op, aM, $\dotsc$, aN))} for any \tcode{K} where $1 < \mathtt{K}+1 = \mathtt{M} \leq \mathtt{N}$. \end{itemize} \indexlibrary{generalized_sum@\tcode{\placeholder{GENERALIZED_SUM}}}% \pnum -Define \tcode{\placeholdernc{GENERALIZED_SUM}(op, a1, ..., aN)} as -\tcode{\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(op, b1, ..., bN)}, -where -\tcode{b1, ..., bN} may be any permutation of \tcode{a1, ..., aN}. +Define \tcode{\placeholdernc{GENERALIZED_SUM}(op, a1, $\dotsc$, aN)} as +\tcode{\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(op, b1, $\dotsc$, bN)}, +\linebreak{}where +\tcode{b1, $\dotsc$, bN} may be any permutation of \tcode{a1, $\dotsc$, aN}. \rSec2[accumulate]{Accumulate} @@ -9816,7 +12436,7 @@ \pnum \returns -\tcode{\placeholdernc{GENERALIZED_SUM}(binary_op, init, *i, ...)} +\tcode{\placeholdernc{GENERALIZED_SUM}(binary_op, init, *i, $\dotsc$)} for every \tcode{i} in \range{first}{last}. \pnum @@ -9958,7 +12578,7 @@ \pnum \returns \begin{codeblock} -@\placeholdernc{GENERALIZED_SUM}@(binary_op1, init, binary_op2(*i, *(first2 + (i - first1))), ...) +@\placeholdernc{GENERALIZED_SUM}@(binary_op1, init, binary_op2(*i, *(first2 + (i - first1))), @$\dotsc$@) \end{codeblock} for every iterator \tcode{i} in \range{first1}{last1}. @@ -10007,7 +12627,7 @@ \pnum \returns \begin{codeblock} -@\placeholdernc{GENERALIZED_SUM}@(binary_op, init, unary_op(*i), ...) +@\placeholdernc{GENERALIZED_SUM}@(binary_op, init, unary_op(*i), @$\dotsc$@) \end{codeblock} for every iterator \tcode{i} in \range{first}{last}. @@ -10160,7 +12780,7 @@ assigns through \tcode{result + K} the value of: \begin{codeblock} @\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}@( - binary_op, init, *(first + 0), *(first + 1), ..., *(first + K - 1)) + binary_op, init, *(first + 0), *(first + 1), @$\dotsc$@, *(first + K - 1)) \end{codeblock} \pnum @@ -10284,10 +12904,10 @@ \begin{itemize} \item \tcode{\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(\\\phantom{\tcode{\ \ \ \ }}binary_op, - init, *(first + 0), *(first + 1), ..., *(first + K))}\\if \tcode{init} is provided, or + init, *(first + 0), *(first + 1), $\dotsc$, *(first + K))}\\if \tcode{init} is provided, or \item \tcode{\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(\\\phantom{\tcode{\ \ \ \ }}binary_op, - *(first + 0), *(first + 1), ..., *(first + K))}\\otherwise. + *(first + 0), *(first + 1), $\dotsc$, *(first + K))}\\otherwise. \end{itemize} \pnum @@ -10361,7 +12981,7 @@ \begin{codeblock} @\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}@( binary_op, init, - unary_op(*(first + 0)), unary_op(*(first + 1)), ..., unary_op(*(first + K - 1))) + unary_op(*(first + 0)), unary_op(*(first + 1)), @$\dotsc$@, unary_op(*(first + K - 1))) \end{codeblock} \pnum @@ -10461,10 +13081,10 @@ assigns through \tcode{result + K} the value of \begin{itemize} \item - \tcode{\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(\\\phantom{\tcode{\ \ \ \ }}binary_op, init,\\\phantom{\tcode{\ \ \ \ }}unary_op(*(first + 0)), unary_op(*(first + 1)), ..., unary_op(*(first + K)))}\\ + \tcode{\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(\\\phantom{\tcode{\ \ \ \ }}binary_op, init,\\\phantom{\tcode{\ \ \ \ }}unary_op(*(first + 0)), unary_op(*(first + 1)), $\dotsc$, unary_op(*(first + K)))}\\ if \tcode{init} is provided, or \item - \tcode{\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(\\\phantom{\tcode{\ \ \ \ }}binary_op,\\\phantom{\tcode{\ \ \ \ }}unary_op(*(first + 0)), unary_op(*(first + 1)), ..., unary_op(*(first + K)))}\\ + \tcode{\placeholdernc{GENERALIZED_NONCOMMUTATIVE_SUM}(\\\phantom{\tcode{\ \ \ \ }}binary_op,\\\phantom{\tcode{\ \ \ \ }}unary_op(*(first + 0)), unary_op(*(first + 1)), $\dotsc$, unary_op(*(first + K)))}\\ otherwise. \end{itemize} @@ -10575,7 +13195,7 @@ \pnum For the overloads with an \tcode{ExecutionPolicy} and a non-empty range, performs \tcode{*result = *first}. -Then, for every \tcode{d} in \tcode{[1, last - first - 1]}, +Then, for every \tcode{d} in \crange{1}{last - first - 1}, performs \tcode{*(result + d) = binary_op(*(first + d), *(first + (d - 1)))}. \pnum @@ -10773,11 +13393,9 @@ \rSec3[numeric.sat.func]{Arithmetic functions} \pnum -\begin{note} In the following descriptions, an arithmetic operation is performed as a mathematical operation with infinite range and then it is determined whether the mathematical result fits into the result type. -\end{note} \indexlibraryglobal{add_sat}% \begin{itemdecl} @@ -10896,15 +13514,31 @@ are destroyed in an unspecified order before allowing the exception to propagate. +\pnum +\begin{note} +When new objects are created by +the algorithms specified in \ref{specialized.algorithms}, +the lifetime ends for any existing objects +(including potentially-overlapping subobjects \ref{intro.object}) +in storage that is reused \ref{basic.life}. +\end{note} + \pnum Some algorithms specified in \ref{specialized.algorithms} -make use of the exposition-only function template -\tcode{\placeholdernc{voidify}}: +make use of the following exposition-only function templates: \begin{codeblock} template constexpr void* @\placeholdernc{voidify}@(T& obj) noexcept { return addressof(obj); } + +template + decltype(auto) @\exposid{deref-move}@(I& it) { + if constexpr (is_lvalue_reference_v) + return std::move(*it); + else + return *it; + } \end{codeblock} \rSec2[special.mem.concepts]{Special memory concepts} @@ -10955,6 +13589,26 @@ \end{note} \end{itemdescr} +\begin{itemdecl} +template +concept @\defexposconcept{nothrow-sized-sentinel-for}@ = // \expos + @\exposconcept{nothrow-sentinel-for}@ && + @\libconcept{sized_sentinel_for}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Types \tcode{S} and \tcode{I} model \exposconcept{nothrow-sized-sentinel-for} +only if no exceptions are thrown from the \tcode{-} operator +for valid values of type \tcode{I} and \tcode{S}. + +\pnum +\begin{note} +This concept allows some \libconcept{sized_sentinel_for}\iref{iterator.concept.sizedsentinel} +operations to throw exceptions. +\end{note} +\end{itemdescr} + \begin{itemdecl} template concept @\defexposconcept{nothrow-input-range}@ = // \expos @@ -10993,12 +13647,75 @@ @\exposconcept{nothrow-forward-iterator}@>; \end{itemdecl} +\begin{itemdecl} +template +concept @\defexposconcept{nothrow-bidirectional-iterator}@ = // \expos + @\exposconcept{nothrow-forward-iterator}@ && + @\libconcept{bidirectional_iterator}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +A type \tcode{I} models \exposconcept{nothrow-bidirectional-iterator} +only if no exceptions are thrown from decrementing valid iterators. +\begin{note} +This concept allows some \libconcept{bidirectional_iterator}\iref{iterator.concept.bidir} +operations to throw exceptions. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +template +concept @\defexposconcept{nothrow-bidirectional-range}@ = // \expos + @\exposconcept{nothrow-forward-range}@ && + @\exposconcept{nothrow-bidirectional-iterator}@>; +\end{itemdecl} + +\begin{itemdecl} +template +concept @\defexposconcept{nothrow-random-access-iterator}@ = // \expos + @\exposconcept{nothrow-bidirectional-iterator}@ && + @\libconcept{random_access_iterator}@ && + @\exposconcept{nothrow-sized-sentinel-for}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +A type \tcode{I} models \exposconcept{nothrow-random-access-iterator} +only if no exceptions are thrown from comparisons of valid iterators, +or the \tcode{-}, \tcode{+}, \tcode{-=}, \tcode{+=}, \tcode{[]} operators +on valid values of type \tcode{I} and \tcode{iter_difference_t}. +\begin{note} +This concept allows some \libconcept{random_access_iterator}\iref{iterator.concept.random.access} +operations to throw exceptions. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +template +concept @\defexposconcept{nothrow-random-access-range}@ = // \expos + @\exposconcept{nothrow-bidirectional-range}@ && + @\exposconcept{nothrow-random-access-iterator}@>; + +template +concept @\defexposconcept{nothrow-sized-random-access-range}@ = // \expos + @\exposconcept{nothrow-random-access-range}@ && @\libconcept{sized_range}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +A type \tcode{R} models \exposconcept{nothrow-sized-random-access-range} +only if no exceptions are thrown from the call to \tcode{ranges::size} +on an object of type \tcode{R}. +\end{itemdescr} + \rSec2[uninitialized.construct.default]{\tcode{uninitialized_default_construct}} \indexlibraryglobal{uninitialized_default_construct}% \begin{itemdecl} template - void uninitialized_default_construct(NoThrowForwardIterator first, NoThrowForwardIterator last); + constexpr void uninitialized_default_construct(NoThrowForwardIterator first, + NoThrowForwardIterator last); \end{itemdecl} \begin{itemdescr} @@ -11017,10 +13734,10 @@ 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); + constexpr 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); + constexpr borrowed_iterator_t uninitialized_default_construct(R&& r); } \end{itemdecl} @@ -11038,7 +13755,8 @@ \indexlibraryglobal{uninitialized_default_construct_n}% \begin{itemdecl} template - NoThrowForwardIterator uninitialized_default_construct_n(NoThrowForwardIterator first, Size n); + constexpr NoThrowForwardIterator + uninitialized_default_construct_n(NoThrowForwardIterator first, Size n); \end{itemdecl} \begin{itemdescr} @@ -11058,7 +13776,7 @@ namespace ranges { template<@\exposconcept{nothrow-forward-iterator}@ I> requires @\libconcept{default_initializable}@> - I uninitialized_default_construct_n(I first, iter_difference_t n); + constexpr I uninitialized_default_construct_n(I first, iter_difference_t n); } \end{itemdecl} @@ -11077,7 +13795,8 @@ \indexlibraryglobal{uninitialized_value_construct}% \begin{itemdecl} template - void uninitialized_value_construct(NoThrowForwardIterator first, NoThrowForwardIterator last); + constexpr void uninitialized_value_construct(NoThrowForwardIterator first, + NoThrowForwardIterator last); \end{itemdecl} \begin{itemdescr} @@ -11096,10 +13815,10 @@ 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); + constexpr 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); + constexpr borrowed_iterator_t uninitialized_value_construct(R&& r); } \end{itemdecl} @@ -11117,7 +13836,8 @@ \indexlibraryglobal{uninitialized_value_construct_n}% \begin{itemdecl} template - NoThrowForwardIterator uninitialized_value_construct_n(NoThrowForwardIterator first, Size n); + constexpr NoThrowForwardIterator + uninitialized_value_construct_n(NoThrowForwardIterator first, Size n); \end{itemdecl} \begin{itemdescr} @@ -11137,7 +13857,7 @@ namespace ranges { template<@\exposconcept{nothrow-forward-iterator}@ I> requires @\libconcept{default_initializable}@> - I uninitialized_value_construct_n(I first, iter_difference_t n); + constexpr I uninitialized_value_construct_n(I first, iter_difference_t n); } \end{itemdecl} @@ -11156,8 +13876,8 @@ \indexlibraryglobal{uninitialized_copy}% \begin{itemdecl} template - NoThrowForwardIterator uninitialized_copy(InputIterator first, InputIterator last, - NoThrowForwardIterator result); + constexpr NoThrowForwardIterator uninitialized_copy(InputIterator first, InputIterator last, + NoThrowForwardIterator result); \end{itemdecl} \begin{itemdescr} @@ -11169,7 +13889,7 @@ \effects Equivalent to: \begin{codeblock} -for (; first != last; ++result, (void) ++first) +for (; first != last; ++result, (void)++first) ::new (@\placeholdernc{voidify}@(*result)) typename iterator_traits::value_type(*first); \end{codeblock} @@ -11185,11 +13905,11 @@ 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 + constexpr 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> + constexpr uninitialized_copy_result, borrowed_iterator_t> uninitialized_copy(IR&& in_range, OR&& out_range); } \end{itemdecl} @@ -11212,8 +13932,8 @@ \indexlibraryglobal{uninitialized_copy_n}% \begin{itemdecl} template - NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n, - NoThrowForwardIterator result); + constexpr NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n, + NoThrowForwardIterator result); \end{itemdecl} \begin{itemdescr} @@ -11225,7 +13945,7 @@ \effects Equivalent to: \begin{codeblock} -for ( ; n > 0; ++result, (void) ++first, --n) +for (; n > 0; ++result, (void)++first, --n) ::new (@\placeholdernc{voidify}@(*result)) typename iterator_traits::value_type(*first); \end{codeblock} @@ -11240,7 +13960,7 @@ namespace ranges { 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 + constexpr uninitialized_copy_n_result uninitialized_copy_n(I ifirst, iter_difference_t n, O ofirst, S olast); } \end{itemdecl} @@ -11266,8 +13986,8 @@ \indexlibraryglobal{uninitialized_move}% \begin{itemdecl} template - NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last, - NoThrowForwardIterator result); + constexpr NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last, + NoThrowForwardIterator result); \end{itemdecl} \begin{itemdescr} @@ -11281,7 +14001,7 @@ \begin{codeblock} for (; first != last; (void)++result, ++first) ::new (@\placeholdernc{voidify}@(*result)) - typename iterator_traits::value_type(std::move(*first)); + typename iterator_traits::value_type(@\exposid{deref-move}@(first)); return result; \end{codeblock} \end{itemdescr} @@ -11292,11 +14012,11 @@ 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 + constexpr 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> + constexpr uninitialized_move_result, borrowed_iterator_t> uninitialized_move(IR&& in_range, OR&& out_range); } \end{itemdecl} @@ -11326,7 +14046,7 @@ \indexlibraryglobal{uninitialized_move_n}% \begin{itemdecl} template - pair + constexpr pair uninitialized_move_n(InputIterator first, Size n, NoThrowForwardIterator result); \end{itemdecl} @@ -11339,9 +14059,9 @@ \effects Equivalent to: \begin{codeblock} -for (; n > 0; ++result, (void) ++first, --n) +for (; n > 0; ++result, (void)++first, --n) ::new (@\placeholdernc{voidify}@(*result)) - typename iterator_traits::value_type(std::move(*first)); + typename iterator_traits::value_type(@\exposid{deref-move}@(first)); return {first, result}; \end{codeblock} \end{itemdescr} @@ -11351,7 +14071,7 @@ namespace ranges { 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 + constexpr uninitialized_move_n_result uninitialized_move_n(I ifirst, iter_difference_t n, O ofirst, S olast); } \end{itemdecl} @@ -11383,7 +14103,8 @@ \indexlibraryglobal{uninitialized_fill}% \begin{itemdecl} template - void uninitialized_fill(NoThrowForwardIterator first, NoThrowForwardIterator last, const T& x); + constexpr void uninitialized_fill(NoThrowForwardIterator first, + NoThrowForwardIterator last, const T& x); \end{itemdecl} \begin{itemdescr} @@ -11402,10 +14123,10 @@ 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); + constexpr 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); + constexpr borrowed_iterator_t uninitialized_fill(R&& r, const T& x); } \end{itemdecl} @@ -11423,7 +14144,8 @@ \indexlibraryglobal{uninitialized_fill_n}% \begin{itemdecl} template - NoThrowForwardIterator uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); + constexpr NoThrowForwardIterator + uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); \end{itemdecl} \begin{itemdescr} @@ -11443,7 +14165,7 @@ namespace ranges { 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); + constexpr I uninitialized_fill_n(I first, iter_difference_t n, const T& x); } \end{itemdecl} @@ -11472,14 +14194,22 @@ \begin{itemdescr} \pnum \constraints -The expression \tcode{::new (declval()) T(declval()...)} +\tcode{is_unbounded_array_v} is \tcode{false}. +The expression \tcode{::new (declval()) T(\linebreak{}declval()...)} is well-formed when treated as an unevaluated operand\iref{term.unevaluated.operand}. +\pnum +\mandates +If \tcode{is_array_v} is \tcode{true}, \tcode{sizeof...(Args)} is zero. + \pnum \effects Equivalent to: \begin{codeblock} -return ::new (@\placeholdernc{voidify}@(*location)) T(std::forward(args)...); +if constexpr (is_array_v) + return ::new (@\placeholdernc{voidify}@(*location)) T[1](); +else + return ::new (@\placeholdernc{voidify}@(*location)) T(std::forward(args)...); \end{codeblock} \end{itemdescr} @@ -11580,6 +14310,144 @@ \end{codeblock} \end{itemdescr} +\rSec1[alg.rand]{Specialized \tcode{} algorithms} + +\rSec2[alg.rand.general]{General} + +\pnum +The contents specified in \ref{alg.rand} +are declared in the header \libheaderrefx{random}{rand.synopsis}. + +\rSec2[alg.rand.generate]{\tcode{generate_random}} + +\indexlibraryglobal{generate_random}% +\begin{itemdecl} +template + requires @\libconcept{output_range}@> && @\libconcept{uniform_random_bit_generator}@> +constexpr borrowed_iterator_t ranges::generate_random(R&& r, G&& g); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +Calls \tcode{g.generate_random(std::forward(r))} +if this expression is well-formed. +\item +Otherwise, if \tcode{R} models \libconcept{sized_range}, +fills \tcode{r} with \tcode{ranges::size(r)} values of +type \tcode{invoke_result_t} by performing +an unspecified number of invocations of +the form \tcode{g()} or \tcode{g.generate_random(s)}, +if such an expression is well-formed for a value \tcode{N} and +an object \tcode{s} of type \tcode{span, N>}. +\begin{note} +Values of \tcode{N} can differ between invocations. +\end{note} +\item +Otherwise, calls \tcode{ranges::generate(std::forward(r), ref(g))}. +\end{itemize} + +\pnum +\returns +\tcode{ranges::end(r)}. + +\pnum +\remarks +The effects of \tcode{generate_random(r, g)} shall be equivalent to +\tcode{ranges::generate(std::for\-ward(r), ref(g))}. +\begin{note} +This implies that \tcode{g.generate_random(a)} fills \tcode{a} +with the same values as produced by invocation of \tcode{g()}. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{generate_random}% +\begin{itemdecl} +template> O, @\libconcept{sentinel_for}@ S> + requires @\libconcept{uniform_random_bit_generator}@> +constexpr O ranges::generate_random(O first, S last, G&& g); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return generate_random(subrange(std::move(first), last), g); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{generate_random}% +\begin{itemdecl} +template + requires @\libconcept{output_range}@> && @\libconcept{invocable}@ && + @\libconcept{uniform_random_bit_generator}@> && + is_arithmetic_v> +constexpr borrowed_iterator_t ranges::generate_random(R&& r, G&& g, D&& d); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +Calls \tcode{d.generate_random(std::forward(r), g)} +if this expression is well-formed. +\item +Otherwise, if \tcode{R} models \libconcept{sized_range}, +fills \tcode{r} with \tcode{ranges::size(r)} values of +type \tcode{invoke_result_t} +by performing an unspecified number of invocations of +the form \tcode{invoke(d, g)} or \tcode{d.generate_random(s, g)}, +if such an expression is well-formed +for a value \tcode{N} and +an object \tcode{s} of type \tcode{span, N>}. +\begin{note} +Values of N can differ between invocations. +\end{note} +\item +Otherwise, calls +\begin{codeblock} +ranges::generate(std::forward(r), [&d, &g] { return invoke(d, g); }); +\end{codeblock} +\end{itemize} + +\pnum +\returns +\tcode{ranges::end(r)}. + +\pnum +\remarks +The effects of \tcode{generate_random(r, g, d)} shall be equivalent to +\begin{codeblock} +ranges::generate(std::forward(r), [&d, &g] { return invoke(d, g); }) +\end{codeblock} +\begin{note} +This implies that \tcode{d.generate_random(a, g)} +fills \tcode{a} with the values with the same random distribution +as produced by invocation of \tcode{invoke(d, g)}. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{generate_random}% +\begin{itemdecl} +template> O, @\libconcept{sentinel_for}@ S> + requires @\libconcept{invocable}@ && @\libconcept{uniform_random_bit_generator}@> && + is_arithmetic_v> +constexpr O ranges::generate_random(O first, S last, G&& g, D&& d); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return generate_random(subrange(std::move(first), last), g, d); +\end{codeblock} +\end{itemdescr} + \rSec1[alg.c.library]{C library algorithms} \pnum @@ -11591,10 +14459,14 @@ \indexlibraryglobal{bsearch}% \indexlibraryglobal{qsort}% \begin{itemdecl} -void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, +void* bsearch(const void* key, void* base, size_t nmemb, size_t size, @\placeholder{c-compare-pred}@* compar); -void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, +void* bsearch(const void* key, void* base, size_t nmemb, size_t size, @\placeholder{compare-pred}@* compar); +const void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, + @\placeholder{c-compare-pred}@* compar); +const void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, + @\placeholder{compare-pred}@* compar); void qsort(void* base, size_t nmemb, size_t size, @\placeholder{c-compare-pred}@* compar); void qsort(void* base, size_t nmemb, size_t size, @\placeholder{compare-pred}@* compar); \end{itemdecl} @@ -11614,4 +14486,4 @@ Any exception thrown by \tcode{compar}\iref{res.on.exception.handling}. \end{itemdescr} -\xrefc{7.22.5} +\xrefc{7.24.5} diff --git a/source/assets/iso-logo-caution.png b/source/assets/iso-logo-caution.png new file mode 100644 index 0000000000..49b12792b8 Binary files /dev/null and b/source/assets/iso-logo-caution.png differ diff --git a/source/back.tex b/source/back.tex index 4d9a27a1ec..da31760918 100644 --- a/source/back.tex +++ b/source/back.tex @@ -1,5 +1,7 @@ %!TEX root = std.tex +\renewcommand{\leftmark}{\bibname} + \begin{thebibliography}{99} % ISO documents in numerical order. \bibitem{iso4217} @@ -9,6 +11,24 @@ ISO/IEC 10967-1:2012, \doccite{Information technology --- Language independent arithmetic --- Part 1: Integer and floating point arithmetic} +\bibitem{iso14882:2023} + ISO/IEC 14882:2023, + \doccite{Programming Languages --- \Cpp{}} +\bibitem{iso14882:2020} + ISO/IEC 14882:2020, + \doccite{Programming Languages --- \Cpp{}} +\bibitem{iso14882:2017} + ISO/IEC 14882:2017, + \doccite{Programming Languages --- \Cpp{}} +\bibitem{iso14882:2014} + ISO/IEC 14882:2014, + \doccite{Information technology --- Programming Languages --- \Cpp{}} +\bibitem{iso14882:2011} + ISO/IEC 14882:2011, + \doccite{Information technology --- Programming Languages --- \Cpp{}} +\bibitem{iso14882:2003} + ISO/IEC 14882:2003, + \doccite{Programming Languages --- \Cpp{}} \bibitem{iso18661-3} ISO/IEC TS 18661-3:2015, \doccite{Information Technology --- @@ -32,13 +52,13 @@ \doccite{The \Cpp{} Programming Language, second edition}, Chapter R\@. Addison-Wesley Publishing Company, ISBN 0-201-53992-6, copyright \copyright 1991 AT\&T \bibitem{kr} - Brian W.\ Kernighan and Dennis M. Ritchie, + Brian W.\ Kernighan and Dennis M.\ Ritchie, \doccite{The C Programming Language}, Appendix A\@. Prentice-Hall, 1978, ISBN 0-13-110163-3, copyright \copyright 1978 AT\&T \bibitem{cpp-lib} - P.J.\ Plauger, + P.\,J.\ Plauger, \doccite{The Draft Standard \Cpp{} Library}. - Prentice-Hall, ISBN 0-13-117003-1, copyright \copyright 1995 P.J.\ Plauger + Prentice-Hall, ISBN 0-13-117003-1, copyright \copyright 1995 P.\,J.\ Plauger \bibitem{linalg-stable} J.\ Demmel, I.\ Dumitriu, and O.\ Holtz, \doccite{Fast linear algebra is stable}, @@ -48,7 +68,7 @@ \doccite{Basic linear algebra subprograms for Fortran usage}. ACM Trans.\ Math.\ Soft., Vol.\ 5, pp.\ 308--323, 1979. \bibitem{blas2} - Jack J.\ Dongarra, Jeremy Du Croz, Sven Hammarling, and Richard J. Hanson, + Jack J.\ Dongarra, Jeremy Du Croz, Sven Hammarling, and Richard J.\ Hanson, \doccite{An Extended Set of FORTRAN Basic Linear Algebra Subprograms}. ACM Trans.\ Math.\ Soft., Vol.\ 14, No.\ 1, pp.\ 1--17, Mar.\ 1988. \bibitem{blas3} @@ -57,20 +77,21 @@ ACM Trans.\ Math.\ Soft., Vol.\ 16, No.\ 1, pp.\ 1--17, Mar.\ 1990. \bibitem{lapack} E.\ Anderson, Z.\ Bai, C.\ Bischof, S.\ Blackford, J.\ Demmel, J.\ Dongarra, - J.\ Du Croz, A.\ Greenbaum, S.\ Hammarling, A.\ McKenney, D.\ Sorensen + J.\ Du Croz, A.\ Greenbaum, S.\ Hammarling, A.\ McKenney, and D.\ Sorensen, \doccite{LAPACK Users' Guide, Third Edition}. SIAM, Philadelphia, PA, USA, 1999. \bibitem{blas-std} - L. Susan Blackford, Ames Demmel, Jack Dongarra, Iain Duff, Sven Hammarling, + L.\ Susan Blackford, James Demmel, Jack Dongarra, Iain Duff, Sven Hammarling, Greg Henry, Michael Heroux, Linda Kaufman, Andrew Lumbsdaine, Antoine Petitet, - Roldan Pozo, Karin Remington, R. Client Whaley + Roldan Pozo, Karin Remington, and R.\ Clint Whaley, \doccite{An Updated Set of Basic Linear Algebra Subprograms (BLAS)}. - ACM Trans.\ Math.\ Soft., Vol.\ 28, Issue 2, 2002. + ACM Trans.\ Math.\ Soft., Vol.\ 28, Issue 2, pp.\ 135--151, 2002. +\bibitem{flynn-taxonomy} + Michael J.\ Flynn, + \doccite{Very High-Speed Computing Systems}. + Proceedings of the IEEE, Vol.\ 54, Issue 12, pp.\ 1901--1909, 1966. \end{thebibliography} -The arithmetic specification described in ISO/IEC 10967-1:2012 is -called \defn{LIA-1} in this document. - % FIXME: For unknown reasons, hanging paragraphs are not indented within our % glossaries by default. \let\realglossitem\glossitem @@ -89,9 +110,9 @@ \clearpage \input{xrefdelta} -\renewcommand{\glossaryname}{Cross-references from ISO \CppXXIII{}} +\renewcommand{\glossaryname}{Cross-references from ISO \CppXVII{}} \renewcommand{\preglossaryhook}{All clause and subclause labels from -ISO \CppXXIII{} (ISO/IEC 14882:2023, \doccite{Programming Languages --- \Cpp{}}) +ISO \CppXVII{} (ISO/IEC 14882:2017, \doccite{Programming Languages --- \Cpp{}}) are present in this document, with the exceptions described below.\\} \renewcommand{\leftmark}{\glossaryname} { @@ -144,7 +165,6 @@ \clearpage \renewcommand{\preindexhook}{The entries in this index are rough descriptions; exact specifications are at the indicated page in the general text.\\} -\renewcommand{\leftmark}{Index of impl.-def. behavior} { \raggedright \printindex[impldefindex] diff --git a/source/basic.tex b/source/basic.tex index a6d708976f..c4540cb050 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4,6 +4,11 @@ \gramSec[gram.basic]{Basics} \rSec1[basic.pre]{Preamble} +\indextext{type}% +\indextext{object}% +\indextext{storage class}% +\indextext{scope}% +\indextext{linkage}% \pnum \begin{note} @@ -27,22 +32,22 @@ \end{note} \pnum -\indextext{type}% -\indextext{object}% -\indextext{storage class}% -\indextext{scope}% -\indextext{linkage}% -An \defn{entity} is a value, object, reference, -structured binding, -function, enumerator, type, -class member, bit-field, template, template specialization, namespace, or -pack. +A \defn{name} is an \grammarterm{identifier}\iref{lex.name}, +\grammarterm{conversion-function-id}\iref{class.conv.fct}, +\grammarterm{operator-function-id}\iref{over.oper}, or +\grammarterm{literal-operator-id}\iref{over.literal}. \pnum -A \defn{name} is an \grammarterm{identifier}\iref{lex.name}, -\grammarterm{operator-function-id}\iref{over.oper}, -\grammarterm{literal-operator-id}\iref{over.literal}, or -\grammarterm{conversion-function-id}\iref{class.conv.fct}. +Two names are \defnx{the same}{name!same} if +\begin{itemize} +\item they are \grammarterm{identifier}{s} composed of the same character sequence, or +\item they are \grammarterm{conversion-function-id}{s} formed with +equivalent\iref{temp.over.link} types, or +\item they are \grammarterm{operator-function-id}{s} formed with +the same operator, or +\item they are \grammarterm{literal-operator-id}{s} formed with +the same literal suffix identifier. +\end{itemize} \pnum Every name is introduced by a \defn{declaration}, which is a @@ -57,6 +62,10 @@ \grammarterm{identifier} in a structured binding declaration\iref{dcl.struct.bind}, \item +\grammarterm{identifier} +in a \grammarterm{result-name-introducer} +in a postcondition assertion\iref{dcl.contract.res}, +\item \grammarterm{init-capture}\iref{expr.prim.lambda.capture}, \item \grammarterm{condition} with a \grammarterm{declarator}\iref{stmt.pre}, @@ -65,10 +74,16 @@ \item \grammarterm{using-declarator}\iref{namespace.udecl}, \item -\grammarterm{parameter-declaration}\iref{dcl.fct}, +\grammarterm{parameter-declaration}\iref{dcl.fct,temp.param}, \item \grammarterm{type-parameter}\iref{temp.param}, \item +\grammarterm{type-tt-parameter}\iref{temp.param}, +\item +\grammarterm{variable-tt-parameter}\iref{temp.param}, +\item +\grammarterm{concept-tt-parameter}\iref{temp.param}, +\item \grammarterm{elaborated-type-specifier} that introduces a name\iref{dcl.type.elab}, \item @@ -82,45 +97,62 @@ implicit declaration of an injected-class-name\iref{class.pre}. \end{itemize} \begin{note} +The term declaration is not a synonym for the grammar non-terminal \grammarterm{declaration}\iref{dcl.pre}. +\end{note} +\begin{note} The interpretation of a \grammarterm{for-range-declaration} produces one or more of the above\iref{stmt.ranged}. \end{note} -An entity $E$ is denoted by the name (if any) -that is introduced by a declaration of $E$ or -by a \grammarterm{typedef-name} introduced by a declaration specifying $E$. + +\pnum +\begin{note} +Some names denote types or templates. +In general, whenever a name is encountered +it is necessary to look it up\iref{basic.lookup} +to determine whether that name denotes one of these entities +before continuing to parse the program that contains it. +\end{note} \pnum A \defn{variable} is introduced by the declaration of a reference other than a non-static data member or of -an object. The variable's name, if any, denotes the reference or object. +an object. + +\pnum +An \defn{entity} is a +variable, +structured binding, +result binding, +function, +enumerator, +type, +type alias, +non-static data member, +bit-field, +template, +namespace, +namespace alias, +template parameter, +function parameter, or +\grammarterm{init-capture}. +The \defnadj{underlying}{entity} of an entity is that entity +unless otherwise specified. +A name \defnx{denotes}{denote} the underlying entity of +the entity declared by each declaration that introduces the name. +\begin{note} +Type aliases and namespace aliases have underlying entities +that are distinct from themselves. +\end{note} \pnum A \defnadj{local}{entity} is a variable with automatic storage duration\iref{basic.stc.auto}, a structured binding\iref{dcl.struct.bind} whose corresponding variable is such an entity, +a result binding\iref{dcl.contract.res}, or the \tcode{*\keyword{this}} object\iref{expr.prim.this}. -\pnum -Some names denote types or templates. In general, -whenever a name is encountered it is necessary to determine whether that name denotes -one of these entities before continuing to parse the program that contains it. The -process that determines this is called -\defnx{name lookup}{lookup!name}\iref{basic.lookup}. - -\pnum -Two names are \defnx{the same}{name!same} if -\begin{itemize} -\item they are \grammarterm{identifier}{s} composed of the same character sequence, or -\item they are \grammarterm{operator-function-id}{s} formed with -the same operator, or -\item they are \grammarterm{conversion-function-id}{s} formed -with equivalent\iref{temp.over.link} types, or -\item they are \grammarterm{literal-operator-id}{s}\iref{over.literal} formed with -the same literal suffix identifier. -\end{itemize} - \pnum \indextext{translation unit!name and}% \indextext{linkage}% @@ -135,14 +167,15 @@ \indextext{declaration!definition versus}% \indextext{declaration}% \indextext{declaration!name}% -A declaration\iref{dcl.dcl} may (re)introduce +A declaration\iref{basic.pre} may (re)introduce one or more names and/or entities into a translation unit. If so, the declaration specifies the interpretation and semantic properties of these names. -A declaration of an entity or \grammarterm{typedef-name} $X$ is +A declaration of an entity $X$ is a redeclaration of $X$ -if another declaration of $X$ is reachable from it\iref{module.reach}. +if another declaration of $X$ is reachable from it\iref{module.reach}; +otherwise, it is a \defnadj{first}{declaration}. A declaration may also have effects including: \begin{itemize} \item a static assertion\iref{dcl.pre}, @@ -171,8 +204,7 @@ Appearing inside the brace-enclosed \grammarterm{declaration-seq} in a \grammarterm{linkage-specification} does not affect whether a declaration is a definition. -\end{footnote} -\iref{dcl.link} +\end{footnote}\iref{dcl.link} and neither an \grammarterm{initializer} nor a \grammarterm{function-body}, \item @@ -208,12 +240,15 @@ \item it is an \grammarterm{alias-declaration}\iref{dcl.typedef}, \item it is -a -\grammarterm{using-declaration}\iref{namespace.udecl}, +a \grammarterm{namespace-alias-definition}\iref{namespace.alias}, +\item it is +a \grammarterm{using-declaration}\iref{namespace.udecl}, \item it is a \grammarterm{deduction-guide}\iref{temp.deduct.guide}, \item it is a \grammarterm{static_assert-declaration}\iref{dcl.pre}, +\item it is +a \grammarterm{consteval-block-declaration}, \item it is an \grammarterm{attribute-declaration}\iref{dcl.pre}, @@ -251,7 +286,6 @@ int X::y = 1; // defines \tcode{X::y} enum { up, down }; // defines \tcode{up} and \tcode{down} namespace N { int d; } // defines \tcode{N} and \tcode{N::d} -namespace N1 = N; // defines \tcode{N1} X anX; // defines \tcode{anX} \end{codeblock} @@ -262,6 +296,7 @@ int f(int); // declares \tcode{f} struct S; // declares \tcode{S} typedef int Int; // declares \tcode{Int} +namespace N1 = N; // declares \tcode{N1} extern X anotherX; // declares \tcode{anotherX} using N::d; // declares \tcode{d} \end{codeblock} @@ -299,10 +334,10 @@ C() : s() { } C(const C& x): s(x.s) { } C(C&& x): s(static_cast(x.s)) { } - @\rlap{\normalfont\itshape //}@ : s(std::move(x.s)) { } + @\rlap{\textnormal{\textit{//}}}@ : s(std::move(x.s)) { } C& operator=(const C& x) { s = x.s; return *this; } C& operator=(C&& x) { s = static_cast(x.s); return *this; } - @\rlap{\normalfont\itshape //}@ { s = std::move(x.s); return *this; } + @\rlap{\textnormal{\textit{//}}}@ { s = std::move(x.s); return *this; } ~C() { } }; \end{codeblock} @@ -355,8 +390,9 @@ The set of \defn{potential results} of an expression $E$ is defined as follows: \begin{itemize} -\item If $E$ is an -\grammarterm{id-expression}\iref{expr.prim.id}, the set +\item If $E$ is +an \grammarterm{id-expression}\iref{expr.prim.id} or +a \grammarterm{splice-expression}\iref{expr.prim.splice}, the set contains only $E$. \item If $E$ is a subscripting operation\iref{expr.sub} with an array operand, the set contains the potential results of that operand. @@ -382,17 +418,21 @@ \item Otherwise, the set is empty. \end{itemize} \begin{note} -This set is a (possibly-empty) set of \grammarterm{id-expression}{s}, +This set is a (possibly-empty) set of +\grammarterm{id-expression}{s} and \grammarterm{splice-expression}s, each of which is either $E$ or a subexpression of $E$. \begin{example} In the following example, the set of potential results of the initializer of \tcode{n} contains the first \tcode{S::x} subexpression, but not the second \tcode{S::x} subexpression. +The set of potential results of the initializer of \tcode{o} contains +the subexpression \tcode{[:\caret\caret S::x:]}. \begin{codeblock} struct S { static const int x = 0; }; const int &f(const int &r); int n = b ? (1, S::x) // \tcode{S::x} is not odr-used here : f(S::x); // \tcode{S::x} is odr-used here, so a definition is required +int o = [:^^S::x:]; \end{codeblock} \end{example} \end{note} @@ -407,10 +447,11 @@ 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 - the expression is not an \grammarterm{id-expression} naming the function with - an explicitly qualified name or - the expression forms a pointer to member\iref{expr.unary.op}. + and either + it is not a pure virtual function or + the expression is an \grammarterm{id-expression} naming the function with + an explicitly qualified name + that does not form a pointer to member\iref{expr.unary.op}. \begin{note} This covers taking the address of functions\iref{conv.func,expr.unary.op}, @@ -439,34 +480,76 @@ \pnum \label{term.odr.use}% A variable is named by an expression -if the expression is an \grammarterm{id-expression} that denotes it. +if the expression is an \grammarterm{id-expression} or +\grammarterm{splice-expression}\iref{expr.prim.splice} +that designates it. A variable \tcode{x} that is named by a -potentially-evaluated expression $E$ -is \defnx{odr-used}{odr-use} by $E$ unless +potentially-evaluated expression $N$ +that appears at a point $P$ +is \defnx{odr-used}{odr-use} by $N$ unless +\begin{itemize} +\item +\tcode{x} is a reference +that is usable in constant expressions at $P$\iref{expr.const} or +\item +$N$ is an element of the set of potential results of an expression $E$, where \begin{itemize} \item - \tcode{x} is a reference that is - usable in constant expressions\iref{expr.const}, or +$E$ is a discarded-value expression\iref{expr.context} +to which the lvalue-to-rvalue conversion is not applied or +\item +\tcode{x} is a non-volatile object +that is usable in constant expressions at $P$ and +has no mutable subobjects and +\begin{itemize} \item - \tcode{x} is a variable of non-reference type that is - usable in constant expressions and has no mutable subobjects, and - $E$ is an element of the set of potential results of an expression - of non-volatile-qualified non-class type - to which the lvalue-to-rvalue conversion\iref{conv.lval} is applied, or +$E$ is a class member access expression\iref{expr.ref} +naming a non-static data member of reference type and +whose object expression has non-volatile-qualified type or \item - \tcode{x} is a variable of non-reference type, and - $E$ is an element of the set of potential results - of a discarded-value expression\iref{expr.context} - to which the lvalue-to-rvalue conversion is not applied. +the lvalue-to-rvalue conversion\iref{conv.lval} is applied to $E$ and +$E$ has non-volatile-qualified non-class type \end{itemize} +\end{itemize} +\end{itemize} +\begin{example} +\begin{codeblock} +int f(int); +int g(int&); +struct A { + int x; +}; +struct B { + int& r; +}; +int h(bool cond) { + constexpr A a = {1}; + constexpr const volatile A& r = a; // odr-uses \tcode{a} + int _ = f(cond ? a.x : r.x); // does not odr-use \tcode{a} or \tcode{r} + int x, y; + constexpr B b1 = {x}, b2 = {y}; // odr-uses \tcode{x} and \tcode{y} + int _ = g(cond ? b1.r : b2.r); // does not odr-use \tcode{b1} or \tcode{b2} + int _ = ((cond ? x : y), 0); // does not odr-use \tcode{x} or \tcode{y} + return [] { + return b1.r; // error: \tcode{b1} is odr-used here because the object + // referred to by \tcode{b1.r} is not constexpr-referenceable here + }(); +} +\end{codeblock} +\end{example} \pnum -A structured binding is odr-used if it appears as a potentially-evaluated expression. +A structured binding is named by an expression +if that expression is either an \grammarterm{id-expression} or +a \grammarterm{splice-expression} +that designates that structured binding. +A structured binding is odr-used +if it is named by a potentially-evaluated expression. \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\iref{class.mfct.non.static}). +(including as the result of any implicit transformation to +a class member access expression\iref{expr.prim.id.general}). \pnum A virtual member @@ -497,7 +580,7 @@ \pnum A local entity\iref{basic.pre} -is \defn{odr-usable} in a scope\iref{basic.scope.scope} if: +is \defn{odr-usable} in a scope\iref{basic.scope.scope} if \begin{itemize} \item either the local entity is not \tcode{*\keyword{this}}, or an enclosing class or non-lambda function parameter scope exists and, @@ -508,10 +591,14 @@ between the point at which the entity is introduced and the scope (where \tcode{*\keyword{this}} is considered to be introduced within the innermost enclosing class or non-lambda function definition scope), -either: +either \begin{itemize} -\item the intervening scope is a block scope, or -\item the intervening scope is the function parameter scope of a \grammarterm{lambda-expression} +\item the intervening scope is a block scope, +\item the intervening scope is a contract-assertion scope\iref{basic.scope.contract}, +\item the intervening scope is the function parameter scope of +a \grammarterm{lambda-expression} or \grammarterm{requires-expression}, or +\item the intervening scope is the lambda scope of +a \grammarterm{lambda-expression} that has a \grammarterm{simple-capture} naming the entity or has a \grammarterm{capture-default}, and the block scope of the \grammarterm{lambda-expression} @@ -537,6 +624,27 @@ \end{codeblock} \end{example} +\pnum +\begin{example} +\begin{codeblock} +void g() { + constexpr int x = 1; + auto lambda = [] {}; // OK + lambda.operator()(); // OK, does not consider \tcode{x} at all + lambda.operator()(); // OK, does not odr-use \tcode{x} + lambda.operator()(); // error: odr-uses \tcode{x} from a context where \tcode{x} is not odr-usable +} + +void h() { + constexpr int x = 1; + auto lambda = [] { (T)x; }; // OK + lambda.operator()(); // OK, does not odr-use \tcode{x} + lambda.operator()(); // OK, does not odr-use \tcode{x} + lambda.operator()(); // error: odr-uses \tcode{x} from a context where \tcode{x} is not odr-usable +} +\end{codeblock} +\end{example} + \pnum Every program shall contain at least one definition of every function or variable that is odr-used in that program @@ -586,7 +694,7 @@ \begin{note} The rules for declarations and expressions describe in which contexts complete class types are required. A class -type \tcode{T} must be complete if: +type \tcode{T} must be complete if \begin{itemize} \item an object of type \tcode{T} is defined\iref{basic.def}, or \item a non-static class data member of type \tcode{T} is @@ -613,7 +721,7 @@ is defined\iref{basic.def} or called\iref{expr.call}, or \item a class with a base class of type \tcode{T} is defined\iref{class.derived}, or -\item an lvalue of type \tcode{T} is assigned to\iref{expr.ass}, or +\item an lvalue of type \tcode{T} is assigned to\iref{expr.assign}, or \item the type \tcode{T} is the subject of an \keyword{alignof} expression\iref{expr.alignof}, or \item an \grammarterm{exception-declaration} has type \tcode{T}, reference to @@ -622,7 +730,16 @@ \end{note} \pnum -For any definable item \tcode{D} with definitions in multiple translation units, +If a definable item \tcode{D} is defined in a translation unit +by an injected declaration $X$\iref{expr.const} and +another translation unit contains a definition of \tcode{D}, +that definition shall be an injected declaration +having the same characteristic sequence as $X$; +a diagnostic is required only if \tcode{D} is attached to a named module and +a prior definition is reachable at the point where a later definition occurs. + +\pnum +For any other definable item \tcode{D} with definitions in multiple translation units, \begin{itemize} \item if \tcode{D} is a non-inline non-templated function or variable, or @@ -648,9 +765,9 @@ is considered to consist of the sequence of tokens of the corresponding \grammarterm{lambda-expression}. \item In each such definition, corresponding names, looked up -according to~\ref{basic.lookup}, shall refer to the same entity, after +according to~\ref{basic.lookup}, shall denote the same entity, after overload resolution\iref{over.match} and after matching of partial -template specialization\iref{temp.over}, except that a name can refer to +template specializations\iref{temp.spec.partial.match}, except that a name can refer to \begin{itemize} \item a non-volatile const object with internal or no linkage if the object @@ -664,7 +781,7 @@ \item a reference with internal or no linkage initialized with a constant expression such that -the reference refers to the same entity in all definitions of \tcode{D}. +the reference refers to the same object or function in all definitions of \tcode{D}. \end{itemize} \item In each such definition, except within @@ -693,11 +810,17 @@ \item In each such definition, a default argument used by an (implicit or explicit) function call or a default template argument used by an (implicit or explicit) -\grammarterm{template-id} or \grammarterm{simple-template-id} +\grammarterm{template-id}, +\grammarterm{simple-template-id}, or +\grammarterm{splice-specialization-specifier} is treated as if its token sequence were present in the definition of \tcode{D}; that is, the default argument or default template argument is subject to the requirements described in this paragraph (recursively). + +\item In each such definition, +corresponding \grammarterm{reflect-expression}s\iref{expr.reflect} +compute equivalent values\iref{expr.eq}. \end{itemize} \pnum @@ -823,9 +946,11 @@ every other scope $S$ is introduced by a declaration, \grammarterm{parameter-declaration-clause}, -\grammarterm{statement}, or \grammarterm{handler} +\grammarterm{statement}, +\grammarterm{handler}, or +contract assertion (as described in the following subclauses of \ref{basic.scope}) -appearing in another scope which thereby contains $S$. +appearing in another scope, which thereby contains $S$. An \defnadj{enclosing}{scope} at a program point is any scope that contains it; the smallest such scope is said to be the \defnadj{immediate}{scope} at that point. @@ -850,6 +975,9 @@ Any names (re)introduced by a declaration are \defnx{bound}{name!bound} to it in its target scope. \end{itemize} +The \defnadj{host}{scope} of a declaration is +the inhabited scope if that scope is a block scope and +the target scope otherwise. An entity \defnx{belongs}{entity!belong} to a scope $S$ if $S$ is the target scope of a declaration of the entity. \begin{note} @@ -866,15 +994,14 @@ inhabits the same scope as the \grammarterm{template-declaration}. \item Friend declarations and -declarations of qualified names and -template specializations do not bind names\iref{dcl.meaning}; +declarations of template specializations do not bind names\iref{dcl.meaning}; those with qualified names target a specified scope, and other friend declarations and certain \grammarterm{elaborated-type-specifier}s\iref{dcl.type.elab} target a larger enclosing scope. \item -Block-scope extern declarations target a larger enclosing scope -but bind a name in their immediate scope. +Block-scope extern or function declarations target a larger enclosing scope +but bind a name in their immediate scope\iref{dcl.meaning.general}. \item The names of unscoped enumerators are bound in the two innermost enclosing scopes\iref{dcl.enum}. @@ -888,20 +1015,20 @@ \pnum Two non-static member functions have -\defnadjx{corresponding}{object parameters}{object parameter} if: +\defnadjx{corresponding}{object parameters}{object parameter} if \begin{itemize} \item exactly one is an implicit object member function with no \grammarterm{ref-qualifier} and the types of their object parameters\iref{dcl.fct}, -after removing top-level references, +after removing references, are the same, or \item their object parameters have the same type. \end{itemize} \indextext{template!function!corresponding object parameter}% Two non-static member function templates have -\defnadjx{corresponding}{object parameters}{object parameter} if: +\defnadjx{corresponding}{object parameters}{object parameter} if \begin{itemize} \item exactly one is an implicit object member function @@ -931,7 +1058,7 @@ \item either is a \grammarterm{using-declarator}, or \item -one declares a type (not a \grammarterm{typedef-name}) and the other declares a +one declares a type (not a type alias) and the other declares a variable, non-static data member other than of an anonymous union\iref{class.union.anon}, enumerator, @@ -942,7 +1069,7 @@ and they do not declare corresponding overloads. \end{itemize} Two function or function template declarations declare -\defn{corresponding overloads} if: +\defn{corresponding overloads} if \begin{itemize} \item both declare functions with the same non-object-parameter-type-list, @@ -1011,6 +1138,8 @@ with no \grammarterm{storage-class-specifier} and not inhabiting a namespace scope, \item +a result binding\iref{dcl.contract.res}, +\item the variable introduced by an \grammarterm{init-capture}, or \item %FIXME: "of" is strange below; remove it? @@ -1203,6 +1332,9 @@ The locus of a \grammarterm{for-range-declaration} of a range-based \keyword{for} statement\iref{stmt.ranged} is immediately after the \grammarterm{for-range-initializer}. +The locus of a \grammarterm{for-range-declaration} +of an expansion statement\iref{stmt.expand} +is immediately after the \grammarterm{expansion-initializer}. \pnum The locus of a \grammarterm{template-parameter} is immediately after it. @@ -1216,6 +1348,10 @@ \end{codeblock} \end{example} +\pnum +The locus of a \grammarterm{result-name-introducer}\iref{dcl.contract.res} +is immediately after it. + \pnum The locus of a \grammarterm{concept-definition} is immediately after its \grammarterm{concept-name}\iref{temp.concept}. @@ -1259,7 +1395,7 @@ Each \begin{itemize} \item -selection or iteration statement\iref{stmt.select,stmt.iter}, +selection, iteration, or expansion statement\iref{stmt.select,stmt.iter,stmt.expand}, \item substatement of such a statement, \item @@ -1431,7 +1567,11 @@ \rSec2[basic.scope.temp]{Template parameter scope}% \pnum -Each template \grammarterm{template-parameter} introduces +Each +\grammarterm{type-tt-parameter}, +\grammarterm{variable-tt-parameter}, and +\grammarterm{concept-tt-parameter} +introduces a \defnadj{template parameter}{scope} that includes the \grammarterm{template-head} of the \grammarterm{template-parameter}. @@ -1451,6 +1591,30 @@ a template parameter scope as a parent scope. \end{note} +\rSec2[basic.scope.contract]{Contract-assertion scope}% + +\pnum +Each contract assertion\iref{basic.contract} +$C$ introduces a \defnadj{contract-assertion}{scope} +that includes $C$. + +\pnum +If a \grammarterm{result-name-introducer}\iref{dcl.contract.res} +that is not name-independent\iref{basic.scope.scope} +and whose enclosing postcondition assertion +is associated with a function \tcode{F} +potentially conflicts with +a declaration whose target scope is +\begin{itemize} +\item +the function parameter scope of \tcode{F} or +\item +if associated with a \grammarterm{lambda-declarator}, +the nearest enclosing lambda scope +of the precondition assertion\iref{expr.prim.lambda}, +\end{itemize} +the program is ill-formed. + \indextext{scope|)} \rSec1[basic.lookup]{Name lookup}% @@ -1461,13 +1625,13 @@ \indextext{scope!name lookup and|see{lookup, name}}% \pnum +\defnx{Name lookup}{lookup!name} associates the use of a name +with a set of declarations\iref{basic.def} of that name. The name lookup rules apply uniformly to all names (including \grammarterm{typedef-name}{s}\iref{dcl.typedef}, \grammarterm{namespace-name}{s}\iref{basic.namespace}, and \grammarterm{class-name}{s}\iref{class.name}) wherever the grammar allows -such names in the context discussed by a particular rule. Name lookup -associates the use of a name with a set of declarations\iref{basic.def} of -that name. +such names in the context discussed by a particular rule. Unless otherwise specified, the program is ill-formed if no declarations are found. If the declarations found by name lookup @@ -1554,7 +1718,7 @@ In certain contexts, only certain kinds of declarations are included. After any such restriction, any declarations of classes or enumerations are discarded if any other declarations are found. \begin{note} -A type (but not a \grammarterm{typedef-name} or template) +A type (but not a type alias or template) is therefore hidden by any other entity in its scope. \end{note} \indextext{type-only!lookup|see{lookup, type-only}}% @@ -1562,8 +1726,8 @@ only declarations of types and templates whose specializations are types are considered; furthermore, if declarations -of a \grammarterm{typedef-name} and of the type to which it refers are found, -the declaration of the \grammarterm{typedef-name} is discarded +of a type alias and of its underlying entity are found, +the declaration of the type alias is discarded instead of the type declaration. \rSec2[class.member.lookup]{Member name lookup}% @@ -1952,7 +2116,7 @@ then lookup for the name also includes the result of \defnadj{argument-dependent}{lookup} in a set of associated namespaces that depends on the types of the arguments -(and for template template arguments, the namespace of the template argument), +(and for type template template arguments, the namespace of the template argument), as specified below. \begin{example} \begin{codeblock} @@ -2020,31 +2184,43 @@ to be considered. The set of entities is determined entirely by the types of the function arguments -(and any template template arguments). +(and any type template template arguments). Any \grammarterm{typedef-name}s and \grammarterm{using-declaration}{s} used to specify the types do not contribute to this set. The set of entities is determined in the following way: \begin{itemize} -\item If \tcode{T} is a fundamental type, its associated set of +\item If \tcode{T} is \tcode{std::meta::info}\iref{meta.syn}, +its associated set of entities is the singleton containing +the enumeration type \tcode{std::meta::operators}\iref{meta.reflection.operators}. +\begin{note} +The \tcode{std::meta::info} type is a type alias, +so an explicit rule is needed to associate calls +whose arguments are reflections with the namespace \tcode{std::meta}. +\end{note} + +\item If \tcode{T} is any other fundamental type, its associated set of entities is empty. \item If \tcode{T} is a class type (including unions), its associated entities are: the class itself; the class of which it is a member, if any; -and its direct and indirect base classes. +and, if it is a complete type, its direct and indirect base classes. Furthermore, if \tcode{T} is a class template specialization, its associated entities also include: the entities associated with the types of the template arguments provided for template type parameters; -the templates used as template template arguments; and -the classes of which any member templates used as template template +the templates used as type template template arguments; and +the classes of which any member templates used as type template template arguments are members. \begin{note} -Non-type template arguments do not +Constant template arguments, +variable template template arguments, and +concept template arguments +do not contribute to the set of associated entities. \end{note} @@ -2075,8 +2251,8 @@ parameter types and return type. Additionally, if the aforementioned overload set is named with a \grammarterm{template-id}, its associated entities also include -its template \grammarterm{template-argument}{s} and -those associated with its type \grammarterm{template-argument}s. +its template template arguments and +those associated with its type template arguments. \pnum The \term{associated namespaces} for a call are @@ -2182,8 +2358,14 @@ followed by a \tcode{::} scope resolution operator considers only namespaces, types, and templates whose specializations are types. -If a name, \grammarterm{template-id}, or \grammarterm{computed-type-specifier} +If a +name, +\grammarterm{template-id}, +\grammarterm{splice-scope-specifier}, or +\grammarterm{computed-type-specifier} is followed by a \tcode{::}, +it shall either be +a dependent \grammarterm{splice-scope-specifier}\iref{temp.dep.splice} or it shall designate a namespace, class, enumeration, or dependent type, and the \tcode{::} is never interpreted as a complete \grammarterm{nested-name-specifier}. @@ -2232,6 +2414,7 @@ \item a \grammarterm{typename-specifier}, \item a \grammarterm{qualified-namespace-specifier}, or \item a \grammarterm{nested-name-specifier}, +\grammarterm{reflection-name}, \grammarterm{elaborated-type-specifier}, or \grammarterm{class-or-decltype} that has a \grammarterm{nested-name-specifier}\iref{expr.prim.id.qual}. @@ -2626,11 +2809,76 @@ only namespace names are considered.% \indextext{lookup!name|)}% +\rSec1[basic.splice]{Splice specifiers} +\indextext{splice|(}% + +\begin{bnf} +\nontermdef{splice-specifier}\br + \terminal{[:} constant-expression \terminal{:]} +\end{bnf} + +\begin{bnf} +\nontermdef{splice-specialization-specifier}\br + splice-specifier \terminal{<} \opt{template-argument-list} \terminal{>} +\end{bnf} + +\pnum +The \grammarterm{constant-expression} of a \grammarterm{splice-specifier} +shall be a converted constant expression of +type \tcode{std::meta::info}\iref{expr.const}. +A \grammarterm{splice-specifier} +whose converted \grammarterm{constant-expression} represents +a construct $X$ is said to \defn{designate} either +\begin{itemize} +\item the underlying entity of $X$ if $X$ is an entity\iref{basic.pre}, or +\item $X$ otherwise. +\end{itemize} +\begin{note} +A \grammarterm{splice-specifier} is dependent +if the converted \grammarterm{constant-expression} is +value-dependent\iref{temp.dep.splice}. +\end{note} + +\pnum +A non-dependent \grammarterm{splice-specifier} of +a \grammarterm{splice-specialization-specifier} shall designate a template. + +\pnum +\begin{note} +A \tcode{<} following a \grammarterm{splice-specifier} is interpreted as +the delimiter of a \grammarterm{template-argument-list} +when the \grammarterm{splice-specifier} is preceded by +the keyword \keyword{template} or the keyword \keyword{typename}, or +when it appears in a type-only context\iref{temp.names}. +\begin{example} +\begin{codeblock} +constexpr int v = 1; +template struct TCls { + static constexpr int s = V + 1; +}; + +using alias = [:^^TCls:]<([:^^v:])>; + // OK, a \grammarterm{splice-specialization-specifier} with a parenthesized \grammarterm{splice-expression} as a template argument + +static_assert(alias::s == 2); + +auto o1 = [:^^TCls:]<([:^^v:])>(); // error: < means less than +auto o2 = typename [:^^TCls:]<([:^^v:])>(); // OK, \tcode{o2} is an object of type \tcode{TCls<1>} + +consteval int bad_splice(std::meta::info v) { + return [:v:]; // error: \tcode{v} is not constant +} +\end{codeblock} +\end{example} +\end{note} +\indextext{splice|)} + \rSec1[basic.link]{Program and linkage}% \indextext{linkage|(} \pnum \indextext{program}% +\indextext{linking}% A \defn{program} consists of one or more translation units\iref{lex.separate} linked together. A translation unit consists of a sequence of declarations. @@ -2643,28 +2891,18 @@ \pnum \indextext{translation unit}% -A name is said to have \defn{linkage} when it can denote the same -object, reference, function, type, template, namespace or value as a -name introduced by a declaration in another scope: -\begin{itemize} -\item When a name has \defnadj{external}{linkage}, -the entity it denotes -can be referred to by names from scopes of other translation units or -from other scopes of the same translation unit. - -\item When a name has \defnx{module linkage}{linkage!module}, -the entity it denotes -can be referred to by names from other scopes of the same module unit\iref{module.unit} or -from scopes of other module units of that same module. - -\item When a name has \defnadj{internal}{linkage}, -the entity it denotes -can be referred to by names from other scopes in the same translation -unit. - -\item When a name has \indextext{linkage!no}\defn{no linkage}, the entity it denotes -cannot be referred to by names from other scopes. -\end{itemize} +A name has +\defnadj{external}{linkage}, +\defnadj{module}{linkage}, +\defnadj{internal}{linkage}, or +\defnadj{no}{linkage}, +as determined by the rules below. +\begin{note} +All declarations of an entity with a name with internal linkage +appear in the same translation unit. +All declarations of an entity with module linkage +are attached to the same module. +\end{note} \pnum \indextext{linkage!\idxcode{static} and}% @@ -2702,8 +2940,8 @@ \pnum An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage. -The name of an entity that belongs to a namespace scope -that has not been given internal linkage above +The name of an entity that belongs to a namespace scope, +that has not been given internal linkage above, and that is the name of \begin{itemize} \item a variable; or @@ -2725,6 +2963,24 @@ has its linkage determined as follows: \begin{itemize} \item +\indextext{friend function!linkage of}% +if the entity is a function or function template +first declared in a friend declaration and +that declaration is a definition and +the enclosing class is defined within an \grammarterm{export-declaration}, +the name has the same linkage, if any, +as the name of the enclosing class\iref{class.friend}; +\item +otherwise, +\indextext{friend function!linkage of}% +if the entity is a function or function template +declared in a friend declaration and +a corresponding non-friend declaration is reachable, +%FIXME: Which declaration is "that prior declaration"? +%FIXME: "prior" with respect to what? And what about dependent lookup? +the name has the linkage determined from that prior declaration, +\item +otherwise, if the enclosing namespace has internal linkage, the name has internal linkage; \item @@ -2788,13 +3044,15 @@ \item they appear in the same translation unit, or \item +they both declare type aliases or namespace aliases that have the same underlying entity, or +\item they both declare names with module linkage and are attached to the same module, or \item they both declare names with external linkage. \end{itemize} \begin{note} -There are other circumstances in which declarations declare the same entity% -\iref{dcl.link,temp.type,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 @@ -2900,6 +3158,16 @@ \item $D$ contains a \grammarterm{lambda-expression} whose closure type is $E$, \item +$D$ contains +a \grammarterm{reflect-expression} or a \grammarterm{splice-specifier} +that, respectively, represents or designates $E$, +\item +$D$ is an injected declaration\iref{expr.const} +whose characteristic sequence contains a reflection +that represents +a data member description ($T$, $N$, $A$, $W$, $\mathit{NUA}$)\iref{class.mem.general} +for which $T$ is $E$, +\item $E$ is not a function or function template and $D$ contains an \grammarterm{id-expression}, \grammarterm{type-specifier}, @@ -2948,7 +3216,7 @@ An entity is \defnx{TU-local}{TU-local!entity} if it is \begin{itemize} \item -a type, function, variable, or template that +a type, type alias, namespace, namespace alias, function, variable, or template that \begin{itemize} \item has a name with internal linkage, or @@ -2980,14 +3248,28 @@ A value or object is \defnx{TU-local}{TU-local!value or object} if either \begin{itemize} \item +it is of TU-local type, +\item it is, or is a pointer to, -a TU-local function or the object associated with a TU-local variable, or +a TU-local function or the object associated with a TU-local variable, \item it is an object of class or array type and any of its subobjects or any of the objects or functions to which its non-static data members of reference type refer -is TU-local and is usable in constant expressions. +is TU-local and is usable in constant expressions, or +\item +it is a reflection value\iref{basic.fundamental} that represents +\begin{itemize} +\item +an entity, value, or object that is TU-local, +\item +a direct base class relationship (\tcode{D}, \tcode{B})\iref{class.derived.general} +for which either \tcode{D} or \tcode{B} is TU-local, or +\item +a data member description ($T$, $N$, $A$, $W$, $\mathit{NUA}$)\iref{class.mem.general} +for which $T$ is TU-local. +\end{itemize} \end{itemize} \pnum @@ -3037,6 +3319,16 @@ void adl(double); inline void h(auto x) { adl(x); } // OK, but certain specializations are exposures + +constexpr std::meta::info r1 = ^^g<0>; // OK +namespace N2 { + static constexpr std::meta::info r2 = ^^g<1>; // OK, \tcode{r2} is TU-local +} +constexpr std::meta::info r3 = ^^f; // error: \tcode{r3} is an exposure of \tcode{f} + +constexpr auto ctx = std::meta::access_context::current(); +constexpr std::meta::info r4 = + std::meta::members_of(^^N2, ctx)[0]; // error: \tcode{r4} is an exposure of \tcode{N2::r2} \end{codeblocktu} \begin{codeblocktu}{Translation unit \#2} module A; @@ -3065,11 +3357,6 @@ \indextext{character set!basic literal}% literal character set\iref{lex.charset} and the eight-bit code units of the Unicode -\begin{footnote} -Unicode\textregistered\ is a registered trademark of Unicode, Inc. -This information is given for the convenience of users of this document and -does not constitute an endorsement by ISO or IEC of this product. -\end{footnote} \indextext{UTF-8}% UTF-8 encoding form and is composed of a contiguous sequence of @@ -3078,11 +3365,10 @@ The number of bits in a byte is reported by the macro \tcode{CHAR_BIT} in the header \libheaderref{climits}. \end{footnote} -the number of which is \impldef{bits in a byte}. The least -significant bit is called the \defn{low-order bit}; the most -significant bit is called the \defn{high-order bit}. The memory -available to a \Cpp{} program consists of one or more sequences of -contiguous bytes. Every byte has a unique address. +the number of which is \impldef{bits in a byte}. +The memory available to a \Cpp{} program consists of one or more sequences of +contiguous bytes. +Every byte has a unique address. \pnum \begin{note} @@ -3091,7 +3377,9 @@ \end{note} \pnum -A \defn{memory location} is either an object of scalar type that is not a bit-field +A \defn{memory location} is +the storage occupied by the object representation of +either an object of scalar type that is not a bit-field or a maximal sequence of adjacent bit-fields all having nonzero width. \begin{note} Various @@ -3185,7 +3473,7 @@ in storage associated with a member subobject or array element \placeholder{e} (which may or may not be within its lifetime), the created object -is a subobject of \placeholder{e}'s containing object if: +is a subobject of \placeholder{e}'s containing object if \begin{itemize} \item the lifetime of \placeholder{e}'s containing object has begun and not ended, and @@ -3202,7 +3490,7 @@ of type ``array of $N$ \tcode{\keyword{unsigned} \keyword{char}}'' or of type ``array of $N$ \tcode{std::byte}''\iref{cstddef.syn}, that array \defn{provides storage} -for the created object if: +for the created object if \begin{itemize} \item the lifetime of \placeholder{e} has begun and not ended, and @@ -3245,7 +3533,7 @@ \pnum \indextext{object!nested within}% -An object \placeholder{a} is \defn{nested within} another object \placeholder{b} if: +An object \placeholder{a} is \defn{nested within} another object \placeholder{b} if \begin{itemize} \item \placeholder{a} is a subobject of \placeholder{b}, or @@ -3314,9 +3602,17 @@ \pnum An object is a \defnadj{potentially non-unique}{object} if it is -a string literal object\iref{lex.string}, -the backing array of an initializer list\iref{dcl.init.ref}, or -a subobject thereof. +\begin{itemize} +\item + a string literal object\iref{lex.string}, +\item + the backing array of an initializer list\iref{dcl.init.ref}, or +\item + the object introduced by a call to \tcode{std::meta::reflect_constant_array} + or \tcode{std::meta::\brk{}reflect_con\-stant_string}\iref{meta.reflection.array}, or +\item + a subobject thereof. +\end{itemize} \pnum \indextext{most derived object!bit-field}% @@ -3411,91 +3707,192 @@ \end{example} \pnum -An operation that begins the lifetime of +Except during constant evaluation, +an operation that begins the lifetime of an array of \tcode{unsigned char} or \tcode{std::byte} implicitly creates objects within the region of storage occupied by the array. \begin{note} The array object provides storage for these objects. \end{note} -Any implicit or explicit invocation of a function +Except during constant evaluation, +any implicit or explicit invocation of a function named \tcode{\keyword{operator} \keyword{new}} or \tcode{\keyword{operator} \keyword{new}[]} 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% -\iref{obj.lifetime,c.malloc,mem.res.public,bit.cast,cstring.syn}. +Some functions in the \Cpp{} standard library implicitly create +objects\iref{obj.lifetime,c.malloc,mem.res.public,bit.cast,cstring.syn}. \end{note} \indextext{object model|)} -\rSec2[basic.life]{Lifetime} +\rSec2[basic.align]{Alignment} \pnum -\indextext{object lifetime|(}% -The \defn{lifetime} of an object or reference is a runtime property of the -object or reference. -A variable is said to have \defnadj{vacuous}{initialization} -if it is default-initialized and, -if it is of class type or a (possibly multidimensional) array thereof, -that class type has a trivial default constructor. -The lifetime of an object of type \tcode{T} begins when: -\begin{itemize} -\item storage with the proper alignment and size - for type \tcode{T} is obtained, and -\item its initialization (if any) is complete - (including vacuous initialization)\iref{dcl.init}, -\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\iref{dcl.init.aggr,class.base.init}, -or as described in -\ref{class.union}, \ref{class.copy.ctor}, and \ref{class.copy.assign}, -and except as described in \ref{allocator.members}. -The lifetime of an object \placeholder{o} of type \tcode{T} ends when: -\begin{itemize} -\item if \tcode{T} is a non-class type, the object is destroyed, or -\item if \tcode{T} is a class type, the destructor call starts, or -\item the storage which the object occupies is released, -or is reused by an object that is not nested within \placeholder{o}\iref{intro.object}. -\end{itemize} -When evaluating a \grammarterm{new-expression}, -storage is considered reused after it is returned from the allocation function, -but before the evaluation of the \grammarterm{new-initializer}\iref{expr.new}. +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 +at which a given object can be allocated. An object type imposes an alignment +requirement on every object of that type; stricter alignment can be requested +using the alignment specifier\iref{dcl.align}. +Attempting to create an object\iref{intro.object} in storage that +does not meet the alignment requirements of the object's type +is undefined behavior. + +\pnum +A \defnadj{fundamental}{alignment} is represented by an alignment +less than or equal to the greatest alignment supported by the implementation in +all contexts, which is equal to +\tcode{\keyword{alignof}(std::max_align_t)}\iref{support.types}. +The alignment required for a type may be different when it is used as the type +of a complete object and when it is used as the type of a subobject. \begin{example} \begin{codeblock} -struct S { - int m; -}; - -void f() { - S x{1}; - new(&x) S(x.m); // undefined behavior -} +struct B { long double d; }; +struct D : virtual B { char c; }; \end{codeblock} -\end{example} -\pnum -\indextext{reference lifetime}% -The lifetime of a reference begins when its initialization is complete. -The lifetime of a reference ends as if it were a scalar object requiring storage. +When \tcode{D} is the type of a complete object, it will have a subobject of +type \tcode{B}, so it must be aligned appropriately for a \tcode{\keyword{long} \keyword{double}}. +If \tcode{D} appears as a subobject of another object that also has \tcode{B} +as a virtual base class, the \tcode{B} subobject might be part of a different +subobject, reducing the alignment requirements on the \tcode{D} subobject. +\end{example} +The result of the \keyword{alignof} operator reflects the alignment +requirement of the type in the complete-object case. \pnum +An \defnadj{extended}{alignment} is represented by an alignment +greater than \tcode{\keyword{alignof}(std::max_align_t)}. It is \impldef{support for extended alignments} +whether any extended alignments are supported and the contexts in which they are +supported\iref{dcl.align}. A type having an extended alignment +requirement is an \defnadj{over-aligned}{type}. \begin{note} -\ref{class.base.init} -describes the lifetime of base and member subobjects. +Every over-aligned type is or contains a class type +to which extended alignment applies (possibly through a non-static data member). \end{note} +A \defnadj{new-extended}{alignment} is represented by +an alignment greater than \mname{STDCPP_DEFAULT_NEW_ALIGNMENT}\iref{cpp.predefined}. \pnum -The properties ascribed to objects and references throughout this document -apply for a given object or reference only during its lifetime. -\begin{note} -In particular, before the lifetime of an object starts and after its -lifetime ends there are significant restrictions on the use of the -object, as described below, in~\ref{class.base.init}, and -in~\ref{class.cdtor}. Also, the behavior of an object under construction -and destruction can differ from the behavior of an object whose -lifetime has started and not ended. \ref{class.base.init} -and~\ref{class.cdtor} describe the behavior of an object during its periods -of construction and destruction. +Alignments are represented as values of the type \tcode{std::size_t}. +Valid alignments include only those values returned by an \keyword{alignof} +expression for the fundamental types plus an additional \impldef{alignment additional +values} +set of values, which may be empty. +Every alignment value shall be a non-negative integral power of two. + +\pnum +Alignments have an order from \defnx{weaker}{alignment!weaker} to +\defnx{stronger}{alignment!stronger} or \defnx{stricter}{alignment!stricter} alignments. Stricter +alignments have larger alignment values. An address that satisfies an alignment +requirement also satisfies any weaker valid alignment requirement. + +\pnum +The alignment requirement of a complete type can be queried using an +\keyword{alignof} expression\iref{expr.alignof}. Furthermore, +the narrow character types\iref{basic.fundamental} shall have the weakest +alignment requirement. +\begin{note} +This enables the ordinary character types to be used as the +underlying type for an aligned memory area\iref{dcl.align}. +\end{note} + +\pnum +Comparing alignments is meaningful and provides the obvious results: + +\begin{itemize} +\item Two alignments are equal when their numeric values are equal. +\item Two alignments are different when their numeric values are not equal. +\item When an alignment is larger than another it represents a stricter alignment. +\end{itemize} + +\pnum +\begin{note} +The runtime pointer alignment function\iref{ptr.align} +can be used to obtain an aligned pointer within a buffer; +an \grammarterm{alignment-specifier}\iref{dcl.align} +can be used to align storage explicitly. +\end{note} + +\pnum +If a request for a specific extended alignment in a specific context is not +supported by an implementation, the program is ill-formed. + +\rSec2[basic.life]{Lifetime} + +\pnum +In this subclause, ``before'' and ``after'' refer to the ``happens before'' +relation\iref{intro.multithread}. + +\pnum +\indextext{object lifetime|(}% +The \defn{lifetime} of an object or reference is a runtime property of the +object or reference. +A variable is said to have \defnadj{vacuous}{initialization} +if it is default-initialized, no other initialization is performed, and, +if it is of class type or a (possibly multidimensional) array thereof, +a trivial constructor of that class type is selected for +the default-initialization. +The lifetime of an object of type \tcode{T} begins when: +\begin{itemize} +\item storage with the proper alignment and size + for type \tcode{T} is obtained, and +\item its initialization (if any) is complete + (including vacuous initialization)\iref{dcl.init}, +\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\iref{dcl.init.aggr,class.base.init}, +or as described in +\ref{class.union}, \ref{class.copy.ctor}, and \ref{class.copy.assign}, +and except as described in \ref{allocator.members}. +The lifetime of an object \placeholder{o} of type \tcode{T} ends when: +\begin{itemize} +\item if \tcode{T} is a non-class type, the object is destroyed, or +\item if \tcode{T} is a class type, the destructor call starts, or +\item the storage which the object occupies is released, +or is reused by an object that is not nested within \placeholder{o}\iref{intro.object}. +\end{itemize} +When evaluating a \grammarterm{new-expression}, +storage is considered reused after it is returned from the allocation function, +but before the evaluation of the \grammarterm{new-initializer}\iref{expr.new}. +\begin{example} +\begin{codeblock} +struct S { + int m; +}; + +void f() { + S x{1}; + new(&x) S(x.m); // undefined behavior +} +\end{codeblock} +\end{example} + +\pnum +\indextext{reference lifetime}% +The lifetime of a reference begins when its initialization is complete. +The lifetime of a reference ends as if it were a scalar object requiring storage. + +\pnum +\begin{note} +\ref{class.base.init} +describes the lifetime of base and member subobjects. +\end{note} + +\pnum +The properties ascribed to objects and references throughout this document +apply for a given object or reference only during its lifetime. +\begin{note} +In particular, before the lifetime of an object starts and after its +lifetime ends there are significant restrictions on the use of the +object, as described below, in~\ref{class.base.init}, and +in~\ref{class.cdtor}. Also, the behavior of an object under construction +and destruction can differ from the behavior of an object whose +lifetime has started and not ended. \ref{class.base.init} +and~\ref{class.cdtor} describe the behavior of an object during its periods +of construction and destruction. \end{note} \pnum @@ -3530,7 +3927,7 @@ if the pointer were of type \tcode{\keyword{void}*} is well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only be used in limited ways, as described below. The -program has undefined behavior if: +program has undefined behavior if \begin{itemize} \item the pointer is used as the operand of a \grammarterm{delete-expression}, @@ -3593,7 +3990,7 @@ a glvalue refers to allocated storage\iref{basic.stc.dynamic.allocation}, and using the properties of the glvalue that do not depend on its value is -well-defined. The program has undefined behavior if: +well-defined. The program has undefined behavior if \begin{itemize} \item the glvalue is used to access the object, or \item the glvalue is used to call a non-static member function of the object, or @@ -3603,18 +4000,14 @@ \keyword{typeid}. \end{itemize} +\begin{note} +Therefore, undefined behavior results +if an object that is being constructed in one thread is referenced from another +thread without adequate synchronization. +\end{note} + \pnum -If, after the lifetime of an object has ended and before the storage -which the object occupied is reused or released, a new object is created -at the storage location which the original object occupied, a pointer -that pointed to the original object, a reference that referred to the -original object, or the name of the original object will automatically -refer to the new object and, once the lifetime of the new object has -started, can be used to manipulate the new object, if -the original object is transparently replaceable (see below) -by the new object. -An object $o_1$ is \defn{transparently replaceable} -by an object $o_2$ if: +An object $o_1$ is \defn{transparently replaceable} by an object $o_2$ if \begin{itemize} \item the storage that $o_2$ occupies exactly overlays the storage that $o_1$ occupied, and @@ -3631,6 +4024,17 @@ $o_1$ and $o_2$ are direct subobjects of objects $p_1$ and $p_2$, respectively, and $p_1$ is transparently replaceable by $p_2$. \end{itemize} + +\pnum +After the lifetime of an object has ended and before the storage which the +object occupied is reused or released, if a new object is created at the +storage location which the original object occupied and the original object was +transparently replaceable by the new object, a pointer that pointed to the +original object, a reference that referred to the original object, or the name +of the original object will automatically refer to the new object and, once the +lifetime of the new object has started, can be used to manipulate the new +object. + \begin{example} \begin{codeblock} struct C { @@ -3712,37 +4116,49 @@ } \end{codeblock} \end{example} - -\pnum -In this subclause, ``before'' and ``after'' refer to the ``happens before'' -relation\iref{intro.multithread}. -\begin{note} -Therefore, undefined behavior results -if an object that is being constructed in one thread is referenced from another -thread without adequate synchronization. -\end{note} \indextext{object lifetime|)} -\rSec2[basic.indet]{Indeterminate values} +\rSec2[basic.indet]{Indeterminate and erroneous values} \pnum -\indextext{value!indeterminate}% -\indextext{indeterminate value}% When storage for an object with automatic or dynamic storage duration -is obtained, the object has an \defnadj{indeterminate}{value}, and if -no initialization is performed for the object, that object retains an -indeterminate value until that value is replaced\iref{expr.ass}. +is obtained, +the bytes comprising the storage for the object +have the following initial value: +\begin{itemize} +\item +If the object has dynamic storage duration, or +is the object associated with a variable or function parameter +whose first declaration is marked with +the \tcode{[[indeterminate]]} attribute\iref{dcl.attr.indet}, +the bytes have \defnadjx{indeterminate}{values}{value}; +\item +otherwise, the bytes have \defnadjx{erroneous}{values}{value}, +where each value is determined by the implementation +independently of the state of the program. +\end{itemize} +If no initialization is performed for an object (including subobjects), +such a byte retains its initial value +until that value is replaced\iref{dcl.init.general,expr.assign}. +If any bit in the value representation has an indeterminate value, +the object has an indeterminate value; +otherwise, if any bit in the value representation has an erroneous value, +the object has an erroneous value\iref{conv.lval}. \begin{note} Objects with static or thread storage duration are zero-initialized, see~\ref{basic.start.static}. \end{note} \pnum -If an indeterminate value is produced by an evaluation, -the behavior is undefined except in the following cases: +Except in the following cases, +if an indeterminate value is produced by an evaluation, +the behavior is undefined, and +if an erroneous value is produced by an evaluation, +the behavior is erroneous and +the result of the evaluation is the value so produced but is not erroneous: \begin{itemize} \item - If an indeterminate value of + If an indeterminate or erroneous value of unsigned ordinary character type\iref{basic.fundamental} or \tcode{std::byte} type\iref{cstddef.syn} is produced by the evaluation of: @@ -3759,37 +4175,69 @@ \item a discarded-value expression\iref{expr.context}, \end{itemize} - then the result of the operation is an indeterminate value. + then the result of the operation is an indeterminate value or + that erroneous value, respectively. \item - If an indeterminate value of + If an indeterminate or erroneous value of unsigned ordinary character type or \tcode{std::byte} type is produced by the evaluation of - the right operand of a simple assignment operator\iref{expr.ass} + the right operand of a simple assignment operator\iref{expr.assign} whose first operand is an lvalue of unsigned ordinary character type or \tcode{std::byte} type, - an indeterminate value replaces + an indeterminate value or that erroneous value, respectively, replaces the value of the object referred to by the left operand. \item - If an indeterminate value of unsigned ordinary character type + If an indeterminate or erroneous value of unsigned ordinary character type is produced by the evaluation of the initialization expression when initializing an object of unsigned ordinary character type, that object is initialized to an indeterminate - value. + value or that erroneous value, respectively. \item If an indeterminate value of unsigned ordinary character type or \tcode{std::byte} type is produced by the evaluation of the initialization expression when initializing an object of \tcode{std::byte} type, - that object is initialized to an indeterminate value. + that object is initialized to an indeterminate value or + that erroneous value, respectively. \end{itemize} +Converting an indeterminate or erroneous value of +unsigned ordinary character type or \tcode{std::byte} type +produces an indeterminate or erroneous value, respectively. +In the latter case, +the result of the conversion is the value of the converted operand. \begin{example} \begin{codeblock} int f(bool b) { - unsigned char c; - unsigned char d = c; // OK, \tcode{d} has an indeterminate value + unsigned char *c = new unsigned char; + unsigned char d = *c; // OK, \tcode{d} has an indeterminate value int e = d; // undefined behavior return b ? d : 0; // undefined behavior if \tcode{b} is \tcode{true} } + +int g(bool b) { + unsigned char c; + unsigned char d = c; // no erroneous behavior, but \tcode{d} has an erroneous value + + assert(c == d); // holds, both integral promotions have erroneous behavior + + int e = d; // erroneous behavior + return b ? d : 0; // erroneous behavior if \tcode{b} is \tcode{true} +} + +void h() { + int d1, d2; + + int e1 = d1; // erroneous behavior + int e2 = d1; // erroneous behavior + + assert(e1 == e2); // holds + assert(e1 == d1); // holds, erroneous behavior + assert(e2 == d1); // holds, erroneous behavior + + std::memcpy(&d2, &d1, sizeof(int)); // no erroneous behavior, but \tcode{d2} has an erroneous value + assert(e1 == d2); // holds, erroneous behavior + assert(e2 == d2); // holds, erroneous behavior +} \end{codeblock} \end{example} @@ -3809,6 +4257,10 @@ \item automatic storage duration \item dynamic storage duration \end{itemize} +\begin{note} +After the duration of a region of storage has ended, +the use of pointers to that region of storage is limited\iref{basic.compound}. +\end{note} \pnum \indextext{storage duration!static}% @@ -3816,30 +4268,21 @@ \indextext{storage duration!automatic}% \indextext{storage duration!dynamic}% Static, thread, and automatic storage durations are associated with objects -introduced by declarations\iref{basic.def} and implicitly created by -the implementation\iref{class.temporary}. The dynamic storage duration +introduced by declarations\iref{basic.def} and +with temporary objects\iref{class.temporary}. +The dynamic storage duration is associated with objects created by a -\grammarterm{new-expression}\iref{expr.new}. +\grammarterm{new-expression}\iref{expr.new} or +with implicitly created objects\iref{intro.object}. \pnum The storage duration categories apply to references as well. \pnum -When the end of the duration of a region of storage is reached, -the values of all pointers -representing the address of any part of that region of storage -become invalid pointer values\iref{basic.compound}. -Indirection through an invalid pointer value and -passing an invalid pointer value to a deallocation function -have undefined behavior. -Any other use of an invalid pointer value has -\impldef{any use of an invalid pointer other than to perform indirection or deallocate} -behavior. -\begin{footnote} -Some implementations might define that -copying an invalid pointer value -causes a system-generated runtime fault. -\end{footnote} +\indextext{storage duration!class member}% +The storage duration of subobjects and reference members +is that of their complete object\iref{intro.object}. +\indextext{storage duration|)}% \rSec3[basic.stc.static]{Static storage duration} @@ -3897,15 +4340,16 @@ \pnum \indextext{storage duration!local object}% -Variables that belong to a block or parameter scope and are +Variables that belong to a block scope and are not explicitly declared \keyword{static}, \keyword{thread_local}, or \keyword{extern} have \defnadj{automatic}{storage duration}. The storage -for these entities lasts until the block in which they are created exits. - -\pnum +for such variables lasts until the block in which they are created exits. \begin{note} These variables are initialized and destroyed as described in~\ref{stmt.dcl}. \end{note} +Variables that belong to a parameter scope also have automatic storage duration. +The storage for a function parameter lasts until +immediately after its destruction\iref{expr.call}. \pnum If a variable with automatic storage duration has initialization or a destructor with side @@ -3941,27 +4385,22 @@ \pnum The library provides default definitions for the global allocation and deallocation functions. Some global allocation and deallocation -functions are replaceable\iref{new.delete}; -these are attached to the global module\iref{module.unit}. -A \Cpp{} program shall -provide at most one definition of a replaceable allocation or -deallocation function. Any such function definition replaces the default -version provided in the library\iref{replacement.functions}. The -following allocation and deallocation functions\iref{support.dynamic} +functions are replaceable\iref{dcl.fct.def.replace}. +The following allocation and deallocation functions\iref{support.dynamic} are implicitly declared in global scope in each translation unit of a program. \begin{codeblock} -[[nodiscard]] void* operator new(std::size_t); -[[nodiscard]] void* operator new(std::size_t, std::align_val_t); +void* operator new(std::size_t); +void* operator new(std::size_t, std::align_val_t); void operator delete(void*) noexcept; void operator delete(void*, std::size_t) noexcept; void operator delete(void*, std::align_val_t) noexcept; void operator delete(void*, std::size_t, std::align_val_t) noexcept; -[[nodiscard]] void* operator new[](std::size_t); -[[nodiscard]] void* operator new[](std::size_t, std::align_val_t); +void* operator new[](std::size_t); +void* operator new[](std::size_t, std::align_val_t); void operator delete[](void*) noexcept; void operator delete[](void*, std::size_t) noexcept; @@ -4098,11 +4537,13 @@ functions in the \Cpp{} standard library. \begin{note} In particular, a -global allocation function is not called to allocate storage for objects -with static storage duration\iref{basic.stc.static}, for objects or references -with thread storage duration\iref{basic.stc.thread}, for objects of -type \tcode{std::type_info}\iref{expr.typeid}, or for an -exception object\iref{except.throw}. +global allocation function is not called to allocate storage +for objects with static storage duration\iref{basic.stc.static}, +for objects or references with thread storage duration\iref{basic.stc.thread}, +for objects of type \tcode{std::type_info}\iref{expr.typeid}, +for an object of type \tcode{std::contracts::contract_violation} +when a contract violation occurs\iref{basic.contract.eval}, or +for an exception object\iref{except.throw}. \end{note} \rSec4[basic.stc.dynamic.deallocation]{Deallocation functions} @@ -4172,128 +4613,19 @@ deallocation function shall deallocate the storage referenced by the pointer, ending the duration of the region of storage. -\rSec3[basic.stc.inherit]{Duration of subobjects} - -\pnum -\indextext{storage duration!class member}% -The storage duration of subobjects and reference members -is that of their complete object\iref{intro.object}. -\indextext{storage duration|)}% - -\rSec2[basic.align]{Alignment} - -\pnum -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 -at which a given object can be allocated. An object type imposes an alignment -requirement on every object of that type; stricter alignment can be requested -using the alignment specifier\iref{dcl.align}. -Attempting to create an object\iref{intro.object} in storage that -does not meet the alignment requirements of the object's type -is undefined behavior. - -\pnum -A \defnadj{fundamental}{alignment} is represented by an alignment -less than or equal to the greatest alignment supported by the implementation in -all contexts, which is equal to -\tcode{\keyword{alignof}(std::max_align_t)}\iref{support.types}. -The alignment required for a type may be different when it is used as the type -of a complete object and when it is used as the type of a subobject. -\begin{example} -\begin{codeblock} -struct B { long double d; }; -struct D : virtual B { char c; }; -\end{codeblock} - -When \tcode{D} is the type of a complete object, it will have a subobject of -type \tcode{B}, so it must be aligned appropriately for a \tcode{\keyword{long} \keyword{double}}. -If \tcode{D} appears as a subobject of another object that also has \tcode{B} -as a virtual base class, the \tcode{B} subobject might be part of a different -subobject, reducing the alignment requirements on the \tcode{D} subobject. -\end{example} -The result of the \keyword{alignof} operator reflects the alignment -requirement of the type in the complete-object case. - -\pnum -An \defnadj{extended}{alignment} is represented by an alignment -greater than \tcode{\keyword{alignof}(std::max_align_t)}. It is \impldef{support for extended alignments} -whether any extended alignments are supported and the contexts in which they are -supported\iref{dcl.align}. A type having an extended alignment -requirement is an \defnadj{over-aligned}{type}. -\begin{note} -Every over-aligned type is or contains a class type -to which extended alignment applies (possibly through a non-static data member). -\end{note} -A \defnadj{new-extended}{alignment} is represented by -an alignment greater than \mname{STDCPP_DEFAULT_NEW_ALIGNMENT}\iref{cpp.predefined}. - -\pnum -Alignments are represented as values of the type \tcode{std::size_t}. -Valid alignments include only those values returned by an \keyword{alignof} -expression for the fundamental types plus an additional \impldef{alignment additional -values} -set of values, which may be empty. -Every alignment value shall be a non-negative integral power of two. - -\pnum -Alignments have an order from \defnx{weaker}{alignment!weaker} to -\defnx{stronger}{alignment!stronger} or \defnx{stricter}{alignment!stricter} alignments. Stricter -alignments have larger alignment values. An address that satisfies an alignment -requirement also satisfies any weaker valid alignment requirement. - -\pnum -The alignment requirement of a complete type can be queried using an -\keyword{alignof} expression\iref{expr.alignof}. Furthermore, -the narrow character types\iref{basic.fundamental} shall have the weakest -alignment requirement. -\begin{note} -This enables the ordinary character types to be used as the -underlying type for an aligned memory area\iref{dcl.align}. -\end{note} - -\pnum -Comparing alignments is meaningful and provides the obvious results: - -\begin{itemize} -\item Two alignments are equal when their numeric values are equal. -\item Two alignments are different when their numeric values are not equal. -\item When an alignment is larger than another it represents a stricter alignment. -\end{itemize} - -\pnum -\begin{note} -The runtime pointer alignment function\iref{ptr.align} -can be used to obtain an aligned pointer within a buffer; -an \grammarterm{alignment-specifier}\iref{dcl.align} -can be used to align storage explicitly. -\end{note} - -\pnum -If a request for a specific extended alignment in a specific context is not -supported by an implementation, the program is ill-formed. - \rSec2[class.temporary]{Temporary objects} \pnum -\indextext{object temporary|see{temporary}}% \indextext{temporary}% \indextext{optimization of temporary|see{temporary, elimination of}}% \indextext{temporary!elimination of}% \indextext{temporary!implementation-defined generation of}% -Temporary objects are created +A \defnadj{temporary}{object} is an object created \begin{itemize} \item -when a prvalue is converted to an xvalue\iref{conv.rval}, +when a prvalue is converted to an xvalue\iref{conv.rval} and \item -when needed by the implementation to pass or return an object of trivially copyable type (see below), -and -\item -when throwing an exception\iref{except.throw}. -\begin{note} -The lifetime of exception objects is described in~\ref{except.throw}. -\end{note} +when needed by the implementation to pass or return an object of suitable type (see below). \end{itemize} Even when the creation of the temporary object is unevaluated\iref{expr.context}, @@ -4318,7 +4650,9 @@ 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\iref{expr.ref,expr.mptr.oper}, +when performing certain member accesses on a class prvalue\iref{expr.ref,expr.mptr.oper}, +\item +when invoking an implicit object member function on a class prvalue\iref{expr.call}, \item when performing an array-to-pointer conversion or subscripting on an array prvalue\iref{conv.array,expr.sub}, \item @@ -4375,34 +4709,49 @@ \pnum When an object of class type \tcode{X} -is passed to or returned from a function, -if \tcode{X} has at least one eligible copy or move constructor\iref{special}, -each such constructor is trivial, +is passed to or returned from a potentially-evaluated function call, +if \tcode{X} is +\begin{itemize} +\item +a scalar type or +\item +a class type that +has at least one eligible copy or move constructor\iref{special}, +where each such constructor is trivial, and the destructor of \tcode{X} is either trivial or deleted, +\end{itemize} implementations are permitted -to create a temporary object -to hold the function parameter or result object. -The temporary object is constructed -from the function argument or return value, respectively, -and the function's parameter or return object -is initialized as if by -using the eligible trivial constructor to copy the temporary -(even if that constructor is inaccessible +to create temporary objects +to hold the function parameter or result object, +as follows: +\begin{itemize} +\item +The first such temporary object +is constructed from the function argument or return value, respectively. +\item +Each successive temporary object +is initialized from the previous one +as if by direct-initialization if \tcode{X} is a scalar type, +otherwise by using an eligible trivial constructor. +\item +The function parameter or return object is initialized +from the final temporary +as if by direct-initialization if \tcode{X} is a scalar type, +otherwise by using an eligible trivial constructor. +\end{itemize} +(In all cases, the eligible constructor is used +even if that constructor is inaccessible or would not be selected by overload resolution to perform a copy or move of the object). \begin{note} -This latitude is granted to allow objects of class type to be passed to or returned from functions in registers. +This latitude is granted to allow objects +to be passed to or returned from functions in registers. \end{note} \pnum \indextext{temporary!constructor for}% \indextext{temporary!destructor for}% \indextext{temporary!destruction of}% -When an implementation introduces a temporary object of a class that has a -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}. Temporary objects are destroyed as the last step in evaluating the full-expression\iref{intro.execution} @@ -4420,7 +4769,7 @@ \pnum \indextext{initializer!temporary and declarator}% \indextext{temporary!order of destruction of}% -There are four contexts in which temporaries are destroyed at a different +There are several contexts in which temporaries are destroyed at a different point than the end of the full-expression. The first context is when a default constructor is called to initialize an element of an array with no corresponding initializer\iref{dcl.init}. @@ -4525,8 +4874,6 @@ persists until the completion of the full-expression containing the \grammarterm{expression-list}. -\item The lifetime of a temporary bound to the returned value in a function \tcode{return} statement\iref{stmt.return} is not extended; the temporary is destroyed at the end of the full-expression in the \tcode{return} statement. - \item A temporary bound to a reference in a \grammarterm{new-initializer}\iref{expr.new} persists until the completion of the full-expression containing the \grammarterm{new-initializer}. \begin{note} This might introduce a dangling reference. @@ -4541,18 +4888,40 @@ \end{itemize} \pnum -The fourth context is when a temporary object other than a function parameter object -is created in the \grammarterm{for-range-initializer} of a range-based \keyword{for} statement. +The fourth context is when a temporary object +is created in the \grammarterm{for-range-initializer} of +either a range-based \keyword{for} statement +or an enumerating expansion statement\iref{stmt.expand}. +If such a temporary object would otherwise be destroyed +at the end of the \grammarterm{for-range-initializer} full-expression, +the object persists for the lifetime of the reference +initialized by the \grammarterm{for-range-initializer}. + +\pnum +The fifth context is when a temporary object is created +in the \grammarterm{expansion-initializer} +of an iterating or destructuring expansion statement. If such a temporary object would otherwise be destroyed -at the end of the \grammarterm{for-range-initializer} full-expression, +at the end of that \grammarterm{expansion-initializer}, the object persists for the lifetime of the reference -initialized by the \grammarterm{for-range-initializer}. +initialized by the \grammarterm{expansion-initializer}, if any. + +\pnum +The sixth context is when a temporary object +is created in a structured binding declaration\iref{dcl.struct.bind}. +Any temporary objects introduced by +the \grammarterm{initializer}{s} for the variables +with unique names +are destroyed at the end of the structured binding declaration. \pnum -The destruction of a temporary whose lifetime is not extended -beyond the full-expression in which it was created -is sequenced before the destruction of every -temporary which is constructed earlier in the same full-expression. +Let \tcode{x} and \tcode{y} each be either +a temporary object whose lifetime is not extended, or +a function parameter. +If the lifetimes of \tcode{x} and \tcode{y} end at +the end of the same full-expression, and +\tcode{x} is initialized before \tcode{y}, then +the destruction of \tcode{y} is sequenced before that of \tcode{x}. If the lifetime of two or more temporaries with lifetimes extending beyond the full-expressions in which they were created ends at the same point, @@ -4842,7 +5211,7 @@ \label{term.scalar.type}% Arithmetic types\iref{basic.fundamental}, enumeration types, pointer types, pointer-to-member types\iref{basic.compound}, -\tcode{std::nullptr_t}, +\tcode{std::meta::\brk{}info}, \tcode{std::nullptr_t}, and cv-qualified\iref{basic.type.qualifier} versions of these types are collectively called @@ -4851,11 +5220,14 @@ 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}, +\label{term.trivially.relocatable.type}% +Scalar types, trivially relocatable class types\iref{class.prop}, arrays of such types, and cv-qualified versions of these -types are collectively called -\defnadjx{trivial}{types}{type}. +types are collectively called \defnadjx{trivially relocatable}{types}{type}. +\label{term.replaceable.type}% +Cv-unqualified scalar types, replaceable class types\iref{class.prop}, and +arrays of such types are collectively called +\defnadjx{replaceable}{types}{type}. \label{term.standard.layout.type}% Scalar types, standard-layout class types\iref{class.prop}, arrays of such types, and @@ -4878,7 +5250,7 @@ has all of the following properties: \begin{itemize} \item it has a constexpr destructor\iref{dcl.constexpr}, -\item all of its non-static non-variant data members and base classes are of non-volatile literal types, and +\item all of its non-variant non-static data members and base classes are of non-volatile literal types, and \item it \begin{itemize} \item is a closure type\iref{expr.prim.lambda.closure}, @@ -4911,6 +5283,21 @@ layout-compatible enumerations\iref{dcl.enum}, or layout-compatible standard-layout class types\iref{class.mem}. +\pnum +A type is \defn{consteval-only} if it is either +\tcode{std::meta::info} or +a type compounded from a consteval-only type\iref{basic.compound}. +Every object of consteval-only type shall be +\begin{itemize} +\item +the object associated with a constexpr variable or a subobject thereof, +\item +a template parameter object\iref{temp.param} or a subobject thereof, or +\item +an object whose lifetime begins and ends +during the evaluation of a core constant expression. +\end{itemize} + \rSec2[basic.fundamental]{Fundamental types} \pnum @@ -4931,7 +5318,7 @@ \defnadjx{signed integer}{types}{type}. The range of representable values for a signed integer type is $-2^{N-1}$ to $2^{N-1}-1$ (inclusive), -where \placeholder{N} is called the \defn{width} of the type. +where $N$ is called the \defn{width} of the type. \indextext{integral type!implementation-defined \tcode{sizeof}}% \begin{note} Plain \tcode{int}s are intended to have @@ -4987,7 +5374,7 @@ the largest value of the corresponding unsigned type. \end{example} -\begin{floattable}{Minimum width}{basic.fundamental.width}{ll} +\begin{floattable}{Minimum width}{basic.fundamental.width}{lc} \topline \lhdr{Type} & \rhdr{Minimum width $N$} \\ \capsep @@ -5008,11 +5395,11 @@ alternative representations of the value specified by the value representation. \begin{note} Padding bits have unspecified value, but cannot cause traps. -In contrast, see ISO C 6.2.6.2. +In contrast, see \IsoC{} 6.2.6.2. \end{note} \begin{note} The signed and unsigned integer types satisfy -the constraints given in ISO C 5.2.4.2.1. +the constraints given in \IsoC{} 5.2.4.2.1. \end{note} Except as specified above, the width of a signed or unsigned integer type is @@ -5172,9 +5559,9 @@ the range of that type is extended to all positive real numbers. \begin{note} Since negative and positive infinity are representable -in ISO/IEC/IEEE 60559 formats, +in \IsoFloatUndated{} formats, all real numbers lie within the range of representable values of -a floating-point type adhering to ISO/IEC/IEEE 60559. +a floating-point type adhering to \IsoFloatUndated{}. \end{note} \pnum @@ -5194,24 +5581,119 @@ A type \cv{}~\keyword{void} 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}\iref{expr.type.conv,expr.static.cast,expr.cast}. +type for functions that do not return a value. 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 -of \tcode{?:}\iref{expr.cond}, as the operand of -\keyword{typeid}, \keyword{noexcept}, or \keyword{decltype}, as -the expression in a \keyword{return} statement\iref{stmt.return} for a function -with the return type \cv{}~\keyword{void}, or as the operand of an explicit conversion -to type \cv{}~\keyword{void}. +be used only as +\begin{itemize} +\item an expression statement\iref{stmt.expr}, +\item the expression in a \keyword{return} statement\iref{stmt.return} +for a function with the return type \cv{}~\keyword{void}, +\item an operand of a comma expression\iref{expr.comma}, +\item the second or third operand of \tcode{?:}\iref{expr.cond}, +\item the operand of a \keyword{typeid} expression\iref{expr.typeid}, +\item the operand of a \keyword{noexcept} operator\iref{expr.unary.noexcept}, +\item the operand of a \keyword{decltype} specifier\iref{dcl.type.decltype}, or +\item the operand of an explicit conversion to type +\cv{}~\keyword{void}\iref{expr.type.conv,expr.static.cast,expr.cast}. +\end{itemize} \pnum -A value of type \tcode{std::nullptr_t} is a null pointer +The types denoted by \cv~\tcode{std::nullptr_t} are distinct types. +A prvalue 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\iref{conv.ptr,conv.mem}. \tcode{\keyword{sizeof}(std::nullptr_t)} shall be equal to \tcode{\keyword{sizeof}(\keyword{void}*)}. +\pnum +A value of type \tcode{std::meta::info} is called a \defn{reflection}. +There exists a unique \defnadj{null}{reflection}; +every other reflection is a representation of +\begin{itemize} +\item a value of scalar type\iref{temp.param}, +\item an object with static storage duration\iref{basic.stc}, +\item a variable\iref{basic.pre}, +\item a structured binding\iref{dcl.struct.bind}, +\item a function\iref{dcl.fct}, +\item a function parameter, +\item an enumerator\iref{dcl.enum}, +\item an annotation\iref{dcl.attr.grammar}, +\item a type alias\iref{dcl.typedef}, +\item a type\iref{basic.types}, +\item a class member\iref{class.mem}, +\item an unnamed bit-field\iref{class.bit}, +\item a class template\iref{temp.pre}, +\item a function template, +\item a variable template, +\item an alias template\iref{temp.alias}, +\item a concept\iref{temp.concept}, +\item a namespace alias\iref{namespace.alias}, +\item a namespace\iref{basic.namespace.general}, +\item a direct base class relationship\iref{class.derived.general}, or +\item a data member description\iref{class.mem.general}. +\end{itemize} +A reflection is said to \defn{represent} the corresponding construct. +\begin{note} +A reflection of a value can be produced by library functions such as +\tcode{std::meta::constant_of} and \tcode{std::meta::reflect_constant}. +\end{note} +\begin{example} +\begin{codeblock} +int arr[] = {1, 2, 3}; +auto [a1, a2, a3] = arr; +void fn(); +enum Enum { A }; +using Alias = int; +struct B {}; +struct S : B { + int mem; + int : 0; +}; +template struct TCls {}; +template void TFn(); +template int TVar; +template concept Concept = requires { true; }; +namespace NS {}; +namespace NSAlias = NS; + +constexpr auto ctx = std::meta::access_context::current(); + +constexpr auto r1 = std::meta::reflect_constant(42); // represents \tcode{int} value of \tcode{42} +constexpr auto r2 = std::meta::reflect_object(arr[1]); // represents \tcode{int} object +constexpr auto r3 = ^^arr; // represents a variable +constexpr auto r4 = ^^a3; // represents a structured binding +constexpr auto r5 = ^^fn; // represents a function +constexpr auto r6 = ^^Enum::A; // represents an enumerator +constexpr auto r7 = ^^Alias; // represents a type alias +constexpr auto r8 = ^^S; // represents a type +constexpr auto r9 = ^^S::mem; // represents a class member +constexpr auto r10 = std::meta::members_of(^^S, ctx)[1]; // represents an unnamed bit-field +constexpr auto r11 = ^^TCls; // represents a class template +constexpr auto r12 = ^^TFn; // represents a function template +constexpr auto r13 = ^^TVar; // represents a variable template +constexpr auto r14 = ^^Concept; // represents a concept +constexpr auto r15 = ^^NSAlias; // represents a namespace alias +constexpr auto r16 = ^^NS; // represents a namespace +constexpr auto r17 = std::meta::bases_of(^^S, ctx)[0]; // represents a direct base class relationship +constexpr auto r18 = + std::meta::data_member_spec(^^int, {.name="member"}); // represents a data member description +\end{codeblock} +\end{example} + +\pnum +\recommended +Implementations should not represent other constructs +specified in this document, such as +\grammarterm{using-declarator}s, +partial template specializations, +attributes, placeholder types, +statements, or +expressions, +as values of type \tcode{std::meta::info}. +\begin{note} +Future revisions of this document can specify semantics for reflections +representing any such constructs. +\end{note} + \pnum \indextext{type!fundamental}% The types described in this subclause @@ -5226,9 +5708,9 @@ \pnum If the implementation supports an extended floating-point type\iref{basic.fundamental} whose properties are specified by -the ISO/IEC/IEEE 60559 floating-point interchange format binary16, +the \IsoFloatUndated{} floating-point interchange format binary16, then the \grammarterm{typedef-name} \tcode{std::float16_t} -is defined in the header \libheaderref{stdfloat} and names such a type, +is declared in the header \libheaderref{stdfloat} and names such a type, the macro \mname{STDCPP_FLOAT16_T} is defined\iref{cpp.predefined}, and the floating-point literal suffixes \tcode{f16} and \tcode{F16} are supported\iref{lex.fcon}. @@ -5236,40 +5718,40 @@ \pnum If the implementation supports an extended floating-point type whose properties are specified by -the ISO/IEC/IEEE 60559 floating-point interchange format binary32, +the \IsoFloatUndated{} floating-point interchange format binary32, then the \grammarterm{typedef-name} \tcode{std::float32_t} -is defined in the header \libheader{stdfloat} and names such a type, +is declared in the header \libheader{stdfloat} and names such a type, the macro \mname{STDCPP_FLOAT32_T} is defined, and the floating-point literal suffixes \tcode{f32} and \tcode{F32} are supported. \pnum If the implementation supports an extended floating-point type whose properties are specified by -the ISO/IEC/IEEE 60559 floating-point interchange format binary64, +the \IsoFloatUndated{} floating-point interchange format binary64, then the \grammarterm{typedef-name} \tcode{std::float64_t} -is defined in the header \libheader{stdfloat} and names such a type, +is declared in the header \libheader{stdfloat} and names such a type, the macro \mname{STDCPP_FLOAT64_T} is defined, and the floating-point literal suffixes \tcode{f64} and \tcode{F64} are supported. \pnum If the implementation supports an extended floating-point type whose properties are specified by -the ISO/IEC/IEEE 60559 floating-point interchange format binary128, +the \IsoFloatUndated{} floating-point interchange format binary128, then the \grammarterm{typedef-name} \tcode{std::float128_t} -is defined in the header \libheader{stdfloat} and names such a type, +is declared in the header \libheader{stdfloat} and names such a type, the macro \mname{STDCPP_FLOAT128_T} is defined, and the floating-point literal suffixes \tcode{f128} and \tcode{F128} are supported. \pnum If the implementation supports an extended floating-point type -with the properties, as specified by ISO/IEC/IEEE 60559, of +with the properties, as specified by \IsoFloatUndated{}, of radix ($b$) of 2, storage width in bits ($k$) of 16, precision in bits ($p$) of 8, maximum exponent ($emax$) of 127, and exponent field width in bits ($w$) of 8, then the \grammarterm{typedef-name} \tcode{std::bfloat16_t} -is defined in the header \libheader{stdfloat} and names such a type, +is declared in the header \libheader{stdfloat} and names such a type, the macro \mname{STDCPP_BFLOAT16_T} is defined, and the floating-point literal suffixes \tcode{bf16} and \tcode{BF16} are supported. @@ -5278,7 +5760,7 @@ A summary of the parameters for each type is given in \tref{basic.extended.fp}. The precision $p$ includes the implicit 1 bit at the beginning of the significand, so the storage used for the significand is $p-1$ bits. -ISO/IEC/IEEE 60559 does not assign a name for a type +\IsoFloatUndated{} does not assign a name for a type having the parameters specified for \tcode{std::bfloat16_t}. \end{note} \begin{floattable} @@ -5288,7 +5770,7 @@ \chdr{\tcode{float64_t}} & \chdr{\tcode{float128_t}} & \rhdr{\tcode{bfloat16_t}} \\ \capsep -ISO/IEC/IEEE 60559 name & binary16 & binary32 & binary64 & binary128 & \\ +\IsoFloatUndated{} name & binary16 & binary32 & binary64 & binary128 & \\ $k$, storage width in bits & 16 & 32 & 64 & 128 & 16 \\ $p$, precision in bits & 11 & 24 & 53 & 113 & 8 \\ $emax$, maximum exponent & 15 & 127 & 1023 & 16383 & 127 \\ @@ -5299,7 +5781,7 @@ \recommended Any names that the implementation provides for the extended floating-point types described in this subsection -that are in addition to the names defined in the \libheader{stdfloat} header +that are in addition to the names declared in the \libheader{stdfloat} header should be chosen to increase compatibility and interoperability with the interchange types \tcode{_Float16}, \tcode{_Float32}, \tcode{_Float64}, and \tcode{_Float128} @@ -5314,7 +5796,7 @@ \item \defnx{arrays}{type!array} of objects of a given type, \ref{dcl.array}; \item \defnx{functions}{type!function}, which have parameters of given types and return -\keyword{void} or references or objects of a given type, \ref{dcl.fct}; +\keyword{void} or a result of a given type, \ref{dcl.fct}; \item \defnx{pointers}{type!pointer} to \cv{}~\keyword{void} or objects or functions (including static members of classes) of a given type, \ref{dcl.ptr}; @@ -5330,9 +5812,8 @@ \end{itemize} \item -\defnx{classes}{class} containing a sequence of objects of various types\iref{class}, -a set of types, enumerations and functions for -manipulating these objects\iref{class.mfct}, and a set of restrictions +\defnx{classes}{class} containing a sequence of class members\iref{class,class.mem}, +and a set of restrictions on the access to these entities\iref{class.access}; \item @@ -5416,17 +5897,13 @@ is not considered to point to an unrelated object of the object's type, even if the unrelated object is located at that address. -A pointer value becomes invalid -when the storage it denotes -reaches the end of its storage duration; -see \ref{basic.stc}. \end{note} For purposes of pointer arithmetic\iref{expr.add} 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 -a pointer to a hypothetical array element $n$ of \tcode{x} and +a pointer to a hypothetical array element $n$ of \tcode{x}, and an object of type \tcode{T} that is not an array element is considered to belong to an array with one element of type \tcode{T}. The value representation of @@ -5441,7 +5918,32 @@ \end{note} \pnum -Two objects \placeholder{a} and \placeholder{b} are \defn{pointer-interconvertible} if: +A pointer value $P$ is +\indextext{value!valid in the context of an evaluation}% +\defn{valid in the context of} an evaluation $E$ +if $P$ is a pointer to function or a null pointer value, or +if it is a pointer to or past the end of an object $O$ and +$E$ happens before the end of the duration of the region of storage for $O$. +If a pointer value $P$ is used in an evaluation $E$ and +$P$ is not valid in the context of $E$, +then the behavior is undefined if $E$ is +an indirection\iref{expr.unary.op} or +an invocation of a deallocation function\iref{basic.stc.dynamic.deallocation}, +and \impldef{invalid pointer value in the context of an evaluation} otherwise. +\begin{footnote} +Some implementations might define that +copying such a pointer value causes a system-generated runtime fault. +\end{footnote} +\begin{note} +$P$ can be valid in the context of $E$ even +if it points to a type unrelated to that of $O$ or +if $O$ is not within its lifetime, +although further restrictions apply +to such pointer values\iref{basic.life, basic.lval, expr.add}. +\end{note} + +\pnum +Two objects \placeholder{a} and \placeholder{b} are \defn{pointer-interconvertible} if \begin{itemize} \item they are the same object, or @@ -5681,6 +6183,15 @@ An extended floating-point type with the same set of values as more than one cv-unqualified standard floating-point type has a rank equal to the rank of \keyword{double}. +\begin{tailnote} +The treatment of \tcode{std::float64_t} differs from +that of the analogous \tcode{_Float64} in C, +for example on platforms where all of +\tcode{\keyword{long} \keyword{double}}, +\keyword{double}, and +\tcode{std::float64_t} +have the same set of values (see \IsoCUndated{}:2024 H.4.2). +\end{tailnote} \end{itemize} \begin{note} The conversion ranks of floating-point types \tcode{T1} and \tcode{T2} @@ -5799,13 +6310,16 @@ \item an immediate invocation\iref{expr.const}, \item -an \grammarterm{init-declarator}\iref{dcl.decl} or +an \grammarterm{init-declarator}\iref{dcl.decl} +(including such introduced by a structured binding\iref{dcl.struct.bind}) or a \grammarterm{mem-initializer}\iref{class.base.init}, including the constituent expressions of the initializer, \item an invocation of a destructor generated at the end of the lifetime of an object other than a temporary object\iref{class.temporary} -whose lifetime has not been extended, or +whose lifetime has not been extended, +\item +the predicate of a contract assertion\iref{basic.contract}, or \item an expression that is not a subexpression of another expression and that is not otherwise part of a full-expression. @@ -5859,17 +6373,19 @@ \pnum \indextext{value computation|(}% -Reading an object designated by a \keyword{volatile} -glvalue\iref{basic.lval}, modifying an object, calling a library I/O -function, or calling a function that does any of those operations are -all -\defn{side effects}, which are changes in the state of the execution -environment. \defnx{Evaluation}{evaluation} of an expression (or a +Reading an object designated by a \keyword{volatile} glvalue\iref{basic.lval}, +modifying an object, +producing an injected declaration\iref{expr.const}, +calling a library I/O function, or +calling a function that does any of those operations +are all \defn{side effects}, +which are changes in the state of the execution or translation environment. +\defnx{Evaluation}{evaluation} of an expression (or a subexpression) in general includes both value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and initiation of side effects. When a call to a library I/O function -returns or an access through a volatile glvalue is evaluated the side +returns or an access through a volatile glvalue is evaluated, the side effect is considered complete, even though some external actions implied by the call (such as the I/O itself) or by the \keyword{volatile} access may not have completed yet. @@ -5931,13 +6447,30 @@ \end{note} The value computations of the operands of an operator are sequenced before the value computation of the result of the -operator. If a +operator. +The behavior is undefined if +\begin{itemize} +\item \indextext{side effects}% -side effect on a memory location\iref{intro.memory} is unsequenced -relative to either another side effect on the same memory location or +a side effect on a memory location\iref{intro.memory} or +\item +starting or ending the lifetime of an object in a memory location +\end{itemize} +is unsequenced relative to +\begin{itemize} +\item +another side effect on the same memory location, +\item +starting or ending the lifetime of an object occupying storage that +overlaps with the memory location, or +\item a value computation using the value of any object in the same memory location, -and they are not potentially concurrent\iref{intro.multithread}, -the behavior is undefined. +\end{itemize} +and the two evaluations are not potentially concurrent\iref{intro.multithread}. +\begin{note} +Starting the lifetime of an object in a memory location can end the lifetime of +objects in other memory locations\iref{basic.life}. +\end{note} \begin{note} The next subclause imposes similar, but more complex restrictions on potentially concurrent computations. @@ -5951,20 +6484,35 @@ i = i++ + 1; // the value of \tcode{i} is incremented i = i++ + i; // undefined behavior i = i + 1; // the value of \tcode{i} is incremented + + union U { int x, y; } u; + (u.x = 1, 0) + (u.y = 2, 0); // undefined behavior } \end{codeblock} \end{example} \pnum -When invoking a function (whether or not the function is inline), +When invoking a function \placeholder{f} (whether or not the function is inline), every argument expression and -the postfix expression designating the called function -are sequenced before every expression or statement -in the body of the called function. -For each function invocation or -evaluation of an \grammarterm{await-expression} \placeholder{F}, -each evaluation that does not occur within \placeholder{F} but -is evaluated on the same thread and as part of the same signal handler (if any) +the postfix expression designating \placeholder{f} +are sequenced before +every precondition assertion of \placeholder{f}\iref{dcl.contract.func}, +which in turn are sequenced before +every expression or statement +in the body of \placeholder{f}, +which in turn are sequenced before +every postcondition assertion of \placeholder{f}. + +\pnum +For each +\begin{itemize} +\item function invocation, +\item evaluation of an \grammarterm{await-expression}\iref{expr.await}, or +\item evaluation of a \grammarterm{throw-expression}\iref{expr.throw} +\end{itemize} +\placeholder{F}, +each evaluation that does not occur within \placeholder{F} +but is evaluated on the same thread and as part of the same signal handler (if any) is either sequenced before all evaluations that occur within \placeholder{F} or sequenced after all evaluations that occur within \placeholder{F}; \begin{footnote} @@ -5977,6 +6525,7 @@ prior to the next suspension (if any) are considered to occur within \placeholder{F}. +\pnum Several contexts in \Cpp{} cause evaluation of a function call, even though no corresponding function call syntax appears in the translation unit. @@ -5986,6 +6535,8 @@ invocation of a conversion function\iref{class.conv.fct} can arise in contexts in which no function call syntax appears. \end{example} + +\pnum The sequencing constraints on the execution of the called function (as described above) are features of the function calls as evaluated, regardless of the syntax of the expression that calls the function.% @@ -6002,6 +6553,14 @@ signal handler is usually unsequenced with respect to the rest of the program. \end{note} +\pnum +During the evaluation of an expression +as a core constant expression\iref{expr.const}, +evaluations of operands of individual operators and +of subexpressions of individual expressions +that are otherwise either unsequenced or indeterminately sequenced +are evaluated in lexical order. + \rSec2[intro.multithread]{Multi-threaded executions and data races} \rSec3[intro.multithread.general]{General} @@ -6019,7 +6578,7 @@ new thread, not by the creating thread. \end{note} Every thread in a program can -potentially access every object and function in a program. +potentially use every object and function in a program. \begin{footnote} An object with automatic or thread storage duration\iref{basic.stc} is associated with @@ -6061,16 +6620,32 @@ \end{note} \pnum -Two expression evaluations \defn{conflict} if one of them modifies a memory -location\iref{intro.memory} and the other one reads or modifies the same -memory location. +Two expression evaluations \defn{conflict} if one of them +\begin{itemize} +\item +modifies\iref{defns.access} a memory location\iref{intro.memory} or +\item +starts or ends the lifetime of an object in a memory location +\end{itemize} +and the other one +\begin{itemize} +\item +reads or modifies the same memory location or +\item +starts or ends the lifetime of an object occupying storage that +overlaps with the memory location. +\end{itemize} +\begin{note} +A modification can still conflict +even if it does not alter the value of any bits. +\end{note} \pnum The library defines a number of atomic operations\iref{atomics} and operations on mutexes\iref{thread} that are specially identified as synchronization operations. These operations play a special role in making assignments in one thread visible to another. A synchronization operation on one -or more memory locations is either a consume operation, an acquire operation, a +or more memory locations is either an acquire operation, a release operation, or both an acquire and release operation. A synchronization operation without an associated memory location is a fence and can be either an acquire fence, a release fence, or both an acquire and release fence. In @@ -6126,122 +6701,17 @@ the value written'' by the last mutex release. \end{note} -\pnum -An evaluation $A$ \defn{carries a dependency} to an evaluation $B$ if -\begin{itemize} -\item -the value of $A$ is used as an operand of $B$, unless: -\begin{itemize} -\item -$B$ is an invocation of any specialization of -\tcode{std::kill_dependency}\iref{atomics.order}, or -\item -$A$ is the left operand of a built-in logical \logop{and} (\tcode{\&\&}, -see~\ref{expr.log.and}) or logical \logop{or} (\tcode{||}, see~\ref{expr.log.or}) -operator, or -\item -$A$ is the left operand of a conditional (\tcode{?:}, see~\ref{expr.cond}) -operator, or -\item -$A$ is the left operand of the built-in comma (\tcode{,}) -operator\iref{expr.comma}; \end{itemize} or -\item -$A$ writes a scalar object or bit-field $M$, $B$ reads the value -written by $A$ from $M$, and $A$ is sequenced before $B$, or -\item -for some evaluation $X$, $A$ carries a dependency to $X$, and -$X$ carries a dependency to $B$. -\end{itemize} -\begin{note} -``Carries a dependency to'' is a subset of ``is sequenced before'', -and is similarly strictly intra-thread. -\end{note} - -\pnum -An evaluation $A$ is \defn{dependency-ordered before} an evaluation -$B$ if -\begin{itemize} -\item -$A$ performs a release operation on an atomic object $M$, and, in -another thread, $B$ performs a consume operation on $M$ and reads -the value written by $A$, or - -\item -for some evaluation $X$, $A$ is dependency-ordered before $X$ and -$X$ carries a dependency to $B$. - -\end{itemize} -\begin{note} -The relation ``is dependency-ordered before'' is analogous to -``synchronizes with'', but uses release/consume in place of release/acquire. -\end{note} - -\pnum -An evaluation $A$ \defn{inter-thread happens before} an evaluation $B$ -if -\begin{itemize} -\item - $A$ synchronizes with $B$, or -\item - $A$ is dependency-ordered before $B$, or -\item - for some evaluation $X$ - \begin{itemize} - \item - $A$ synchronizes with $X$ and $X$ - is sequenced before $B$, or - \item - $A$ is sequenced before $X$ and $X$ - inter-thread happens before $B$, or - \item - $A$ inter-thread happens before $X$ and $X$ - inter-thread happens before $B$. - \end{itemize} -\end{itemize} -\begin{note} -The ``inter-thread happens before'' relation describes arbitrary -concatenations of ``sequenced before'', ``synchronizes with'' and -``dependency-ordered before'' relationships, with two exceptions. The first -exception is that a concatenation never ends with -``dependency-ordered before'' followed by ``sequenced before''. The reason for -this limitation is that a consume operation participating in a -``dependency-ordered before'' relationship provides ordering only with respect -to operations to which this consume operation actually carries a dependency. The -reason that this limitation applies only to the end of such a concatenation is -that any subsequent release operation will provide the required ordering for a -prior consume operation. The second exception is that a concatenation never -consist entirely of ``sequenced before''. The reasons for this -limitation are (1) to permit ``inter-thread happens before'' to be transitively -closed and (2) the ``happens before'' relation, defined below, provides for -relationships consisting entirely of ``sequenced before''. -\end{note} - \pnum An evaluation $A$ \defn{happens before} an evaluation $B$ -(or, equivalently, $B$ \defn{happens after} $A$) if: -\begin{itemize} -\item $A$ is sequenced before $B$, or -\item $A$ inter-thread happens before $B$. -\end{itemize} -The implementation shall ensure that no program execution demonstrates a cycle -in the ``happens before'' relation. -\begin{note} -This cycle would otherwise be -possible only through the use of consume operations. -\end{note} - -\pnum -An evaluation $A$ \defn{simply happens before} an evaluation $B$ +(or, equivalently, $B$ happens after $A$) if either \begin{itemize} \item $A$ is sequenced before $B$, or \item $A$ synchronizes with $B$, or -\item $A$ simply happens before $X$ and -$X$ simply happens before $B$. +\item $A$ happens before $X$ and $X$ happens before $B$. \end{itemize} \begin{note} -In the absence of consume operations, -the happens before and simply happens before relations are identical. +An evaluation does not happen before itself. \end{note} \pnum @@ -6254,7 +6724,7 @@ sequentially consistent atomic operations\iref{atomics.order}, or \item there are evaluations $B$ and $C$ such that $A$ is sequenced before $B$, -$B$ simply happens before $C$, and +$B$ happens before $C$, and $C$ is sequenced before $D$, or \item there is an evaluation $B$ such that $A$ strongly happens before $B$, and @@ -6263,7 +6733,7 @@ \begin{note} Informally, if $A$ strongly happens before $B$, then $A$ appears to be evaluated before $B$ -in all contexts. Strongly happens before excludes consume operations. +in all contexts. \end{note} \pnum @@ -6406,7 +6876,8 @@ \end{note} \pnum -Two accesses to the same object of type \tcode{\keyword{volatile} std::sig_atomic_t} do not +Two accesses to the same non-bit-field object +of type \tcode{\keyword{volatile} std::sig_atomic_t} do not result in a data race if both occur in the same thread, even if one or more occurs in a signal handler. For each signal handler invocation, evaluations performed by the thread invoking a signal handler can be divided into two @@ -6432,8 +6903,8 @@ \pnum \begin{note} -Transformations that introduce a speculative read of a potentially -shared memory location might not preserve the semantics of the \Cpp{} program as +It is possible that transformations that introduce a speculative read of a potentially +shared memory location do not preserve the semantics of the \Cpp{} program as defined in this document, since they potentially introduce a data race. However, they are typically valid in the context of an optimizing compiler that targets a specific machine with well-defined semantics for data races. They would be @@ -6448,13 +6919,19 @@ following: \begin{itemize} \item terminate, +\item invoke the function \tcode{std::this_thread::yield}\iref{thread.thread.this}, \item make a call to a library I/O function, -\item perform an access through a volatile glvalue, or -\item perform a synchronization operation or an atomic operation. +\item perform an access through a volatile glvalue, +\item perform an atomic or synchronization operation +other than an atomic modify-write operation\iref{atomics.order}, or +\item continue execution of a trivial infinite loop\iref{stmt.iter.general}. \end{itemize} \begin{note} -This is intended to allow compiler transformations such as removal of -empty loops, even when termination cannot be proven. +This is intended to allow compiler transformations +such as removal, merging, and reordering of empty loops, +even when termination cannot be proven. +An affordance is made for trivial infinite loops, +which cannot be removed nor reordered. \end{note} \pnum @@ -6503,9 +6980,10 @@ an \defn{execution step}: \begin{itemize} \item termination of the thread of execution, -\item performing an access through a volatile glvalue, or -\item completion of a call to a library I/O function, a - synchronization operation, or an atomic operation. +\item performing an access through a volatile glvalue, +\item completion of a call to a library I/O function, or +\item completion of an atomic or synchronization operation +other than an atomic modify-write operation\iref{atomics.order}. \end{itemize} \pnum @@ -6692,10 +7170,10 @@ arguments passed to the program from the environment in which the program is run. If \tcode{argc} is nonzero these arguments shall be supplied in -\tcode{argv[0]} through \tcode{argv[argc-1]} as pointers to the initial +\tcode{argv[0]} through \tcode{argv[argc - 1]} as pointers to the initial characters of null-terminated multibyte strings (\ntmbs{}s)\iref{multibyte.strings} and \tcode{argv[0]} shall be the pointer to -the initial character of a \ntmbs{} that represents the name used to +the initial character of an \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. @@ -6703,8 +7181,7 @@ Any further (optional) parameters should be added after \tcode{argv}. \pnum -The function \tcode{main} shall not be used within -a program. +The function \tcode{main} shall not be named by an expression. \indextext{\idxcode{main} function!implementation-defined linkage of}% The linkage\iref{basic.link} of \tcode{main} is \impldef{linkage of \tcode{main}}. A program that defines \tcode{main} as @@ -6712,7 +7189,7 @@ \keyword{inline}, \keyword{static}, \keyword{constexpr}, or \keyword{consteval} is ill-formed. The function \tcode{main} shall not be a coroutine\iref{dcl.fct.def.coroutine}. The \tcode{main} function shall not be declared with a -\grammarterm{linkage-specification}\iref{dcl.link}. +\grammarterm{linkage-specification}\iref{dcl.link} other than \tcode{"C++"}. A program that declares \begin{itemize} \item @@ -6750,9 +7227,10 @@ \pnum \indextext{termination!program}% \indextext{\idxcode{main} function!return from}% -A \keyword{return} statement\iref{stmt.return} in \tcode{main} has the effect of leaving the main -function (destroying any objects with automatic storage duration) and -calling \tcode{std::exit} with the return value as the argument. +A \keyword{return} statement\iref{stmt.return} in \tcode{main} has the effect of leaving the \tcode{main} +function (destroying any objects with automatic storage duration +and evaluating any postcondition assertions of \tcode{main}) +and calling \tcode{std::exit} with the return value as the argument. If control flows off the end of the \grammarterm{compound-statement} of \tcode{main}, the effect is equivalent to a \keyword{return} with operand \tcode{0} @@ -6772,7 +7250,7 @@ \pnum \indextext{initialization!constant}% \defnx{Constant initialization}{constant initialization} is performed -if a variable or temporary object with static or thread storage duration +if a variable with static or thread storage duration is constant-initialized\iref{expr.const}. \indextext{initialization!zero-initialization}% If constant initialization is not performed, a variable with static @@ -7084,3 +7562,442 @@ the functions passed to \tcode{std::atexit()} or \tcode{std::at_quick_exit()}.% \indextext{program!termination|)} \indextext{program execution|)} + +\rSec1[basic.contract]{Contract assertions}% +\indextext{contract assertion|(}% + +\rSec2[basic.contract.general]{General}% + +\pnum +\defnx{Contract assertions}{contract assertion} +allow the programmer to specify +properties of the state of the program +that are expected to hold at +certain points during execution. +Contract assertions are introduced by +\grammarterm{precondition-specifier}s, +\grammarterm{postcondition-specifier}s\iref{dcl.contract.func}, and +\grammarterm{assertion-statement}s\iref{stmt.contract.assert}. + +\pnum +Each contract assertion has a \defnadjx{contract-assertion}{predicate}{predicate}, +which is an expression of type \tcode{bool}. + +\begin{note} +The value of the predicate is used to identify program states that are +expected. +\end{note} + +\pnum +An invocation of the macro \tcode{va_start}\iref{cstdarg.syn} +shall not be a subexpression +of the predicate of a contract assertion, +no diagnostic required. + +\pnum +\begin{note} +Within the predicate of a contract assertion, +\grammarterm{id-expression}s referring to +variables declared outside the contract assertion +are \keyword{const}\iref{expr.prim.id.unqual}, +\tcode{this} is a pointer to \keyword{const}\iref{expr.prim.this}, +and the result object can be named +if a \grammarterm{result-name-introducer}\iref{dcl.contract.res} has been specified. +\end{note} + +\rSec2[basic.contract.eval]{Evaluation} + +\pnum +\indexdefn{evaluation semantics|see{contract evaluation semantics}}% +\indexdefn{checking semantics|see{contract evaluation semantics!checking}}% +\indexdefn{terminating semantics|see{contract evaluation semantics!terminating}}% +An evaluation of a contract assertion +uses one of the following four \defn{evaluation semantics}: +\defnx{ignore}{contract evaluation semantics!ignore}, +\defnx{observe}{contract evaluation semantics!observe}, +\defnx{enforce}{contract evaluation semantics!enforce}, or +\defnx{quick-enforce}{contract evaluation semantics!quick-enforce}. +Observe, enforce, and quick-enforce are \defnx{checking semantics}{contract evaluation semantics!checking}; +enforce and quick-enforce are \defnx{terminating semantics}{contract evaluation semantics!terminating}. + +\pnum +It is +\impldef{evaluation semantic used for the evaluation of a contract assertion} +which evaluation semantic is used +for any given evaluation of a contract assertion. +\begin{note} +The range and flexibility of available choices of +evaluation semantics depends on the implementation +and need not allow all four evaluation semantics as possibilities. +The evaluation semantics can differ +for different evaluations of the same contract assertion, +including evaluations during constant evaluation. +\end{note} + +\pnum +\recommended +An implementation should provide +the option to translate a program +such that all evaluations of contract assertions use the ignore semantic +as well as +the option to translate a program +such that all evaluations of contract assertions use the enforce semantic. +By default, +evaluations of contract assertions should use the enforce semantic. + +\pnum +The evaluation of a contract assertion using the ignore semantic has no effect. +\begin{note} +The predicate is potentially evaluated\iref{basic.def.odr}, +but not evaluated. +\end{note} + +\pnum +The evaluation $A$ of a contract assertion +using a checking semantic +determines the value of the predicate. +It is unspecified +whether the predicate is evaluated. +Let $B$ be the value that would result from evaluating the predicate. +\begin{note} +To determine whether a predicate would evaluate +to \keyword{true} or \keyword{false}, +an alternative evaluation +that produces the same value as the predicate +but has no side effects +can occur. +\begin{example} +\begin{codeblock} +struct S { + mutable int g = 5; +} s; +void f() + pre(( s.g++, false )); // \#1 +void g() +{ + f(); // Increment of \tcode{s.g} might not occur, even if \#1 uses a checking semantic. +} +\end{codeblock} +\end{example} +\end{note} + +\pnum +There is an observable checkpoint\iref{intro.abstract} $C$ +that happens before $A$ +such that any other operation $O$ +that happens before $A$ +also happens before $C$. + +\pnum +A \defn{contract violation} occurs when +\begin{itemize} +\item +$B$ is \keyword{false}, +\item +the evaluation of the predicate +exits via an exception, or +\item +the evaluation of the predicate +is performed in a context that is +manifestly constant-evaluated\iref{expr.const} +and the predicate +is not a core constant expression. +\end{itemize} + +\begin{note} +If $B$ is \keyword{true}, +no contract violation occurs and +control flow continues normally +after the point of evaluation of the contract assertion. +The evaluation of the predicate +can fail to produce a value +without causing a contract violation, +for example, +by calling \tcode{longjmp}\iref{csetjmp.syn} +or terminating the program. +\end{note} + +\pnum +\indexdefn{contract evaluation semantics!terminating}% +If a contract violation occurs +in a context that is manifestly constant-evaluated\iref{expr.const}, +and the evaluation semantic is +a terminating semantic, +the program is ill-formed. + +\begin{note} +A diagnostic is produced +if the evaluation semantic is observe\iref{intro.compliance}. +\end{note} + +\begin{note} +Different evaluation semantics +chosen for the same contract assertion +in different translation units +can result in +violations of the one-definition rule\iref{basic.def.odr} +when a contract assertion has side effects +that alter the value produced by a constant expression. +\begin{example} +\begin{codeblock} +constexpr int f(int i) +{ + contract_assert((++const_cast(i), true)); + return i; +} +inline void g() +{ + int a[f(1)]; // size dependent on the evaluation semantic of \tcode{contract_assert} above +} +\end{codeblock} +\end{example} +\end{note} + +\pnum +When the program is \defn{contract-terminated}, +it is +\impldef{method by which contract termination occurs} +(depending on context) whether +\begin{itemize} +\item +\tcode{std::terminate} is called, +\item +\tcode{std::abort} is called, or +\item +execution is terminated. + +\begin{note} +No further execution steps occur\iref{intro.progress}. +\end{note} +\end{itemize} + +\begin{note} +Performing the actions of +\tcode{std::terminate} or \tcode{std::abort} +without actually making a library call +is a conforming implementation of +contract-termination\iref{intro.abstract}. +\end{note} + +\pnum +\indextext{contract evaluation semantics!enforce}% +\indextext{contract evaluation semantics!quick-enforce}% +If a contract violation occurs +in a context that is not manifestly constant-evaluated +and the evaluation semantic is quick-enforce, +the program is contract-terminated. + +\pnum +\indextext{\idxcode{contract_violation}}% +\indextext{contract evaluation semantics!enforce}% +\indextext{contract evaluation semantics!observe}% +\indexlibraryglobal{contract_violation}% +If a contract violation occurs +in a context that is not manifestly constant-evaluated +and the evaluation semantic is enforce or observe, +the contract-violation handler\iref{basic.contract.handler} +is invoked with an lvalue referring to +an object \tcode{v} +of type \tcode{const std::contracts::contract_violation}\iref{support.contract.violation} +containing information about the contract violation. +Storage for \tcode{v} +is allocated in an unspecified manner +except as noted in \ref{basic.stc.dynamic.allocation}. +The lifetime of \tcode{v} +persists for the duration +of the invocation of the contract-violation handler. + +\pnum +If the contract violation occurred +because the evaluation of the predicate +exited via an exception, +the contract-violation handler is invoked +from within an active implicit handler +for that exception\iref{except.handle}. +If the contract-violation handler +returns normally +and the evaluation semantic is observe, +that implicit handler +is no longer considered active. + +\begin{note} +The exception can be inspected or rethrown within the contract-violation handler. +\end{note} + +\pnum +\indextext{contract evaluation semantics!enforce}% +If the contract-violation handler +returns normally +and the evaluation semantic is enforce, +the program is contract-terminated; +if violation occurred +as the result of an uncaught exception +from the evaluation of the predicate, +the implicit handler +remains active when contract termination occurs. + +\pnum +\indextext{contract evaluation semantics!observe}% +\begin{note} +If the contract-violation handler +returns normally +and the evaluation semantic is observe, +control flow continues normally +after the point of evaluation of the contract assertion. +\end{note} + +\pnum +There is an observable checkpoint\iref{intro.abstract} $C$ +that happens after the contract-violation handler returns normally +such that any other operation $O$ +that happens after the contract-violation handler returns +also happens after $C$. + +\pnum +\begin{note} +The terminating semantics terminate the program +if execution would otherwise continue normally +past a contract violation: +the enforce semantic provides the opportunity to +log information about the contract violation +before terminating the program +or to throw an exception to avoid termination, +and the quick-enforce semantic is intended +to terminate the program as soon as possible +as well as +to minimize the impact of contract checks +on the generated code size. +Conversely, +the observe semantic +provides the opportunity to +log information about the contract violation +without having to terminate the program. +\end{note} + +\pnum +If a contract-violation handler +invoked from the evaluation of a function contract assertion\iref{dcl.contract.func} +exits via an exception, +the behavior is as if +the function body exits via that same exception. +\begin{note} +A \grammarterm{function-try-block}\iref{except.pre} +is the function body when present +and thus does not +have an opportunity to catch the exception. +If the function +has a non-throwing exception specification, +the function \tcode{std::terminate} is invoked\iref{except.terminate}. +\end{note} + +\begin{note} +If a contract-violation handler +invoked from an \grammarterm{assertion-statement}\iref{stmt.contract.assert} +exits via an exception, +the search for a handler +continues from the execution of that statement. +\end{note} + +\pnum +To \defn{evaluate in sequence} a list $R$ of contract assertions: +\begin{itemize} +\item +Construct a list of contract assertions $S$ such that +\begin{itemize} +\item +all elements of $R$ are in $S$, +\item +each element of $R$ +may be repeated an +\impldef{maximum number of repeated evaluations of a contract assertion} +number of times +within $S$, and +\item +if a contract assertion $A$ +precedes another contract assertion $B$ +in $R$, +then the +first occurrence of $A$ +precedes the first occurrence of $B$ +in $S$. +\end{itemize} +\item +Evaluate each element of $S$ such that, +if a contract assertion $A$ +precedes a contract assertion $B$ +in $S$, +then the evaluation of $A$ +is sequenced before +the evaluation of $B$. +\end{itemize} + +\begin{example} +\begin{codeblock} +void f(int i) +{ + contract_assert(i > 0); // \#1 + contract_assert(i < 10); // \#2 + // valid sequence of evaluations: \#1 \#2 + // valid sequence of evaluations: \#1 \#1 \#2 \#2 + // valid sequence of evaluations: \#1 \#2 \#1 \#2 + // valid sequence of evaluations: \#1 \#2 \#2 \#1 + // invalid sequence of evaluations: \#2 \#1 +} +\end{codeblock} +\end{example} + +\pnum +\recommended +An implementation should +provide an option to perform +a specified number of repeated evaluations +for contract assertions. +By default, +no repeated evaluations should be performed. + +\rSec2[basic.contract.handler]{Contract-violation handler} + +\pnum +\indextext{\idxcode{contract_violation}}% +\indexlibraryglobal{contract_violation}% +The \defn{contract-violation handler} +of a program is a function named +\tcode{::handle_contract_violation}. +The contract-violation handler +shall have a single parameter +of type +``lvalue reference to \keyword{const} \tcode{std::\-contracts::\-contract_violation}'' +and shall return \tcode{void}. +The contract-violation handler +may have a non-throwing exception specification. +The implementation +shall provide a definition of the contract-violation handler, +called the \defnadj{default}{contract-violation handler}. +\begin{note} +No declaration +for the default contract-violation handler +is provided by +any standard library header. +\end{note} + +\pnum +\recommended +The default contract-violation handler +should produce diagnostic output +that suitably formats the most relevant contents +of the \tcode{std::contracts::contract_violation} object, +rate-limited for potentially repeated violations +of observed contract assertions, +and then return normally. + +\pnum +It is +\impldef{replaceability of the contract-violation handler} +whether the contract-violation handler +is replaceable\iref{dcl.fct.def.replace}. +If the contract-violation handler +is not replaceable, +a declaration of a replacement function for the contract-violation handler +is ill-formed, no diagnostic required. + +\indextext{contract assertion|)} diff --git a/source/classes.tex b/source/classes.tex index 6cf92daee0..a1287851d4 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -36,7 +36,7 @@ \begin{bnf} \nontermdef{class-head}\br - class-key \opt{attribute-specifier-seq} class-head-name \opt{class-virt-specifier} \opt{base-clause}\br + class-key \opt{attribute-specifier-seq} class-head-name \opt{class-property-specifier-seq} \opt{base-clause}\br class-key \opt{attribute-specifier-seq} \opt{base-clause} \end{bnf} @@ -46,8 +46,15 @@ \end{bnf} \begin{bnf} -\nontermdef{class-virt-specifier}\br - \keyword{final} +\nontermdef{class-property-specifier-seq}\br + class-property-specifier \opt{class-property-specifier-seq} +\end{bnf} + +\begin{bnf} +\nontermdef{class-property-specifier}\br + \keyword{final}\br + \keyword{trivially_relocatable_if_eligible}\br + \keyword{replaceable_if_eligible} \end{bnf} \begin{bnf} @@ -72,7 +79,8 @@ it is not looked up, and the \grammarterm{class-specifier} introduces it. \pnum -The +\indextext{component name}% +The component name of the \grammarterm{class-name} is also bound in the scope of the class (template) itself; this is known as the \defn{injected-class-name}. For purposes of access checking, the injected-class-name is treated as @@ -119,12 +127,13 @@ \end{note} \pnum -If a class is marked with the \grammarterm{class-virt-specifier} \tcode{final} and it appears -as a \grammarterm{class-or-decltype} in a \grammarterm{base-clause}\iref{class.derived}, -the program is ill-formed. Whenever a -\grammarterm{class-key} is followed by a \grammarterm{class-head-name}, the -\grammarterm{identifier} \tcode{final}, and a colon or left brace, \tcode{final} is -interpreted as a \grammarterm{class-virt-specifier}. +Each \grammarterm{class-property-specifier} shall appear at most once +within a single \grammarterm{class-property-specifier-seq}. +Whenever a \grammarterm{class-key} is followed +by a \grammarterm{class-head-name}, +the identifier \tcode{final}, \tcode{trivially_relocatable_if_eligible}, +or \tcode{replaceable_if_eligible}, and a colon or left brace, +the identifier is interpreted as a \grammarterm{class-property-specifier}. \begin{example} \begin{codeblock} struct A; @@ -133,12 +142,19 @@ struct X { struct C { constexpr operator int() { return 5; } }; - struct B final : C{}; // OK, definition of nested class \tcode{B}, - // not declaration of a bit-field member \tcode{final} + struct B trivially_relocatable_if_eligible : C{}; + // OK, definition of nested class \tcode{B}, + // not declaration of a bit-field member + // \tcode{trivially_relocatable_if_eligible} }; \end{codeblock} \end{example} +\pnum +If a class is marked with the \grammarterm{class-property-specifier} +\tcode{final} and that class appears as a \grammarterm{class-or-decltype} +in a \grammarterm{base-clause}\iref{class.derived}, the program is ill-formed. + \pnum \begin{note} Complete objects of class type have nonzero size. @@ -149,7 +165,7 @@ \pnum \begin{note} -Class objects can be assigned\iref{over.ass,class.copy.assign}, +Class objects can be assigned\iref{over.assign,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}). @@ -172,12 +188,84 @@ \end{itemize} \pnum -A \defnadj{trivial}{class} is a class that is trivially copyable and -has one or more eligible default constructors\iref{class.default.ctor}, -all of which are trivial. +A class \tcode{C} is \defn{default-movable} if + +\begin{itemize} +\item overload resolution for direct-initializing an object of type \tcode{C} +from an xvalue of type \tcode{C} selects a constructor that is a direct member +of \tcode{C} and is neither user-provided nor deleted, + +\item overload resolution for assigning to an lvalue of type \tcode{C} from an +xvalue of type \tcode{C} selects an assignment operator function that is a +direct member of \tcode{C} and is neither user-provided nor deleted, and + +\item \tcode{C} has a destructor that is neither user-provided nor deleted. +\end{itemize} + +\pnum +A class is \defn{eligible for trivial relocation} unless it +\begin{itemize} +\item has any virtual base classes, +\item has a base class that is not a trivially relocatable class, +\item has a non-static data member of an object type that is not of a +trivially relocatable type, or + +\item has a deleted destructor, +\end{itemize} +except that it is \impldef{whether an otherwise-eligible union having one or +more subobjects of polymorphic class type is eligible for trivial relocation} +whether an otherwise-eligible union having one or more subobjects of +polymorphic class type is eligible for trivial relocation. + +\pnum +A class \tcode{C} is a \defnadj{trivially relocatable}{class} +if it is eligible for trivial relocation and +\begin{itemize} +\item has the \tcode{trivially_relocatable_if_eligible} \grammarterm{class-property-specifier}, +\item is a union with no user-declared special member functions, or +\item is default-movable. +\end{itemize} + +\pnum +\begin{note} +A class with const-qualified or reference non-static data members can be +trivially relocatable. +\end{note} + +\pnum +A class \tcode{C} is \defn{eligible for replacement} unless +\begin{itemize} +\item it has a base class that is not a replaceable class, +\item it has a non-static data member that is not of a replaceable type, +\item overload resolution fails or selects a deleted constructor when +direct-initializing an object of type \tcode{C} from an xvalue of type +\tcode{C}\iref{dcl.init.general}, + +\item overload resolution fails or selects a deleted assignment operator +function when assigning to an lvalue of type \tcode{C} from an xvalue of type +\tcode{C}\iref{expr.assign,over.assign}, or + +\item it has a deleted destructor. +\end{itemize} + +\pnum +A class \tcode{C} is a \defnadj{replaceable}{class} if it is +eligible for replacement and +\begin{itemize} +\item has the \tcode{replaceable_if_eligible} \grammarterm{class-property-specifier}, +\item is a union with no user-declared special member functions, or +\item is default-movable. +\end{itemize} + +\pnum +\begin{note} +Accessibility of the special member functions is not considered when +establishing trivial relocatability or replaceability. +\end{note} + +\pnum \begin{note} -In particular, a trivially copyable or trivial class does not have -virtual functions or virtual base classes. +Not all trivially copyable classes are trivially relocatable or replaceable. \end{note} \pnum @@ -265,31 +353,31 @@ \begin{note} Standard-layout classes are useful for communicating with code written in other programming languages. Their layout is specified -in~\ref{class.mem}. +in~\ref{class.mem.general} and~\ref{expr.rel}. \end{note} \pnum \begin{example} \begin{codeblock} -struct N { // neither trivial nor standard-layout +struct N { // neither trivially copyable nor standard-layout int i; int j; virtual ~N(); }; -struct T { // trivial but not standard-layout +struct T { // trivially copyable but not standard-layout int i; private: int j; }; -struct SL { // standard-layout but not trivial +struct SL { // standard-layout but not trivially copyable int i; int j; ~SL(); }; -struct POD { // both trivial and standard-layout +struct POD { // both trivially copyable and standard-layout int i; int j; }; @@ -430,7 +518,8 @@ \begin{note} The declaration of a class name takes effect immediately after the \grammarterm{identifier} is seen in the class definition or -\grammarterm{elaborated-type-specifier}. For example, +\grammarterm{elaborated-type-specifier}. +\begin{example} \begin{codeblock} class A * A; \end{codeblock} @@ -438,6 +527,7 @@ it as the name of a pointer to an object of that class. This means that the elaborated form \keyword{class} \tcode{A} must be used to refer to the class. Such artistry with names can be confusing and is best avoided. +\end{example} \end{note} \pnum @@ -461,9 +551,11 @@ \nontermdef{member-declaration}\br \opt{attribute-specifier-seq} \opt{decl-specifier-seq} \opt{member-declarator-list} \terminal{;}\br function-definition\br + friend-type-declaration\br using-declaration\br using-enum-declaration\br static_assert-declaration\br + consteval-block-declaration\br template-declaration\br explicit-specialization\br deduction-guide\br @@ -480,16 +572,15 @@ \begin{bnf} \nontermdef{member-declarator}\br - declarator \opt{virt-specifier-seq} \opt{pure-specifier}\br - declarator requires-clause\br - declarator \opt{brace-or-equal-initializer}\br + declarator \opt{virt-specifier-seq} \opt{function-contract-specifier-seq} \opt{pure-specifier}\br + declarator requires-clause \opt{function-contract-specifier-seq}\br + declarator brace-or-equal-initializer\br \opt{identifier} \opt{attribute-specifier-seq} \terminal{:} constant-expression \opt{brace-or-equal-initializer} \end{bnf} \begin{bnf} \nontermdef{virt-specifier-seq}\br - virt-specifier\br - virt-specifier-seq virt-specifier + virt-specifier \opt{virt-specifier-seq} \end{bnf} \begin{bnf} @@ -503,6 +594,42 @@ \terminal{=} \terminal{0} \end{bnf} +\begin{bnf} +\nontermdef{friend-type-declaration}\br + \keyword{friend} friend-type-specifier-list \terminal{;} +\end{bnf} + +\begin{bnf} +\nontermdef{friend-type-specifier-list}\br + friend-type-specifier \opt{\terminal{...}}\br + friend-type-specifier-list \terminal{,} friend-type-specifier \opt{\terminal{...}} +\end{bnf} + +\begin{bnf} +\nontermdef{friend-type-specifier}\br + simple-type-specifier\br + elaborated-type-specifier\br + typename-specifier +\end{bnf} + +\pnum +In the absence of a \grammarterm{virt-specifier-seq}, +the token sequence \tcode{= 0} is treated as a \grammarterm{pure-specifier} +if the type of the \grammarterm{declarator-id}\iref{dcl.meaning.general} +is a function type, and +is otherwise treated as a \grammarterm{brace-or-equal-initializer}. +\begin{note} +If the member declaration acquires a function type through +template instantiation, +the program is ill-formed; see~\ref{temp.spec.general}. +\end{note} + +\pnum +The optional \grammarterm{function-contract-specifier-seq}\iref{dcl.contract.func} +in a \grammarterm{member-declarator} +shall be present only if +the \grammarterm{declarator} declares a function. + \pnum \indextext{definition!class}% The \grammarterm{member-specification} in a class definition declares the @@ -520,13 +647,14 @@ \end{note} \pnum -A \grammarterm{member-declaration} does not declare new members of the class +A \grammarterm{member-declaration} does not itself declare new members of the class if it is \begin{itemize} \item a friend declaration\iref{class.friend}, \item a \grammarterm{deduction-guide}\iref{temp.deduct.guide}, \item a \grammarterm{template-declaration} whose \grammarterm{declaration} is one of the above, \item a \grammarterm{static_assert-declaration}, +\item a \grammarterm{consteval-block-declaration}, \item a \grammarterm{using-declaration}\iref{namespace.udecl}, or \item an \grammarterm{empty-declaration}. \end{itemize} @@ -560,10 +688,21 @@ 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}\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}. -\end{note} + +\pnum +Every object of class type has a unique member subobject +corresponding to each of its direct non-static data members. +If any non-static data member of a class \tcode{C} is of reference type, +then let \tcode{D} be an invented class +that is identical to \tcode{C} +except that each non-static member of \tcode{D} corresponding to +a member of \tcode{C} of type ``reference to \tcode{T}'' +instead has type ``pointer to \tcode{T}''. +Every member subobject of a complete object of type \tcode{C} +has the same size, alignment, and offset +as that of the corresponding subobject of a complete object of type \tcode{D}. +The size and alignment of \tcode{C} are the same as +the size and alignment of \tcode{D}. \pnum A member shall not be declared twice in the @@ -594,7 +733,8 @@ \item function body\iref{dcl.fct.def.general}, \item default argument\iref{dcl.fct.default}, \item default template argument\iref{temp.param}, -\item \grammarterm{noexcept-specifier}\iref{except.spec}, or +\item \grammarterm{noexcept-specifier}\iref{except.spec}, +\item \grammarterm{function-contract-specifier}\iref{dcl.contract.func}, or \item default member initializer \end{itemize} within the \grammarterm{member-specification} of the class or class template. @@ -610,6 +750,11 @@ or if $P$ is in a complete-class context of \tcode{C}. Otherwise, \tcode{C} is incomplete at $P$. +\pnum +If a \grammarterm{member-declaration} matches +the syntactic requirements of \grammarterm{friend-type-declaration}, +it is a \grammarterm{friend-type-declaration}. + \pnum In a \grammarterm{member-declarator}, an \tcode{=} immediately following the \grammarterm{declarator} @@ -867,6 +1012,46 @@ pointer-interconvertible\iref{basic.compound,expr.static.cast}. \end{note} +\pnum +A \defnadj{data member}{description} is +a quintuple ($T$, $N$, $A$, $W$, $\mathit{NUA}$) +describing the potential declaration of a non-static data member where +\begin{itemize} +\item $T$ is a type, +\item $N$ is an \grammarterm{identifier} or $\bot$, +\item $A$ is an alignment or $\bot$, +\item $W$ is a bit-field width or $\bot$, and +\item $\mathit{NUA}$ is a boolean value. +\end{itemize} +Two data member descriptions are equal +if each of their respective components are the same entities, +are the same identifiers, have equal values, or are both $\bot$. +\begin{note} +The components of a data member description describe a data member such that +\begin{itemize} +\item +its type is specified using the type given by $T$, +\item +it is declared with the name given by $N$ +if $N$ is not $\bot$ and is otherwise unnamed, +\item +it is declared with the \grammarterm{alignment-specifier}\iref{dcl.align} +given by \tcode{alignas($A$)} +if $A$ is not $\bot$ and +is otherwise declared without an \grammarterm{alignment-specifier}, +\item +it is a bit-field\iref{class.bit} with the width given by $W$ +if $W$ is not $\bot$ and is otherwise not a bit-field, and +\item +it is declared with +the attribute \tcode{[[no_unique_address]]}\iref{dcl.attr.nouniqueaddr} +if $\mathit{NUA}$ is true and is otherwise declared without that attribute. +\end{itemize} +Data member descriptions are represented by reflections\iref{basic.fundamental} +returned by \tcode{std::meta::data_member_spec}\iref{meta.reflection.define.aggregate} and +can be reified as data members of a class using \tcode{std::meta::define_aggregate}. +\end{note} + \rSec2[class.mfct]{Member functions}% \indextext{member function!class} @@ -911,8 +1096,8 @@ A member function can be declared (but not defined) using a typedef for a function type. The resulting member function has exactly the same type as it would have if the function declarator were provided explicitly, -see~\ref{dcl.fct}. For example, - +see~\ref{dcl.fct} and \ref{temp.arg}. +\begin{example} \begin{codeblock} typedef void fv(); typedef void fvc() const; @@ -925,8 +1110,7 @@ fv S::* pmfv2 = &S::memfunc2; fvc S::* pmfv3 = &S::memfunc3; \end{codeblock} - -Also see~\ref{temp.arg}. +\end{example} \end{note} \rSec2[class.mfct.non.static]{Non-static member functions}% @@ -943,66 +1127,6 @@ its class or a class derived from its class, or a member thereof, as described below. -\pnum -When an \grammarterm{id-expression}\iref{expr.prim.id} that is -neither part of a class member access syntax\iref{expr.ref} -nor the unparenthesized operand of -the unary \tcode{\&} operator\iref{expr.unary.op} is used -where the current class is \tcode{X}\iref{expr.prim.this}, -if name -lookup\iref{basic.lookup} resolves the name in the -\grammarterm{id-expression} to a non-static non-type member of some class -\tcode{C}, -and if either the \grammarterm{id-expression} is potentially evaluated or -\tcode{C} is \tcode{X} or a base class of \tcode{X}, -the \grammarterm{id-expression} is transformed into a class -member access expression\iref{expr.ref} using -\tcode{(*this)} as the \grammarterm{postfix-expression} -to the left of the \tcode{.} operator. -\begin{note} -If \tcode{C} is not \tcode{X} or a base class of \tcode{X}, the class -member access expression is ill-formed. -\end{note} -This transformation does not apply in the -template definition context\iref{temp.dep.type}. -\begin{example} -\begin{codeblock} -struct tnode { - char tword[20]; - int count; - tnode* left; - tnode* right; - void set(const char*, tnode* l, tnode* r); -}; - -void tnode::set(const char* w, tnode* l, tnode* r) { - count = strlen(w)+1; - if (sizeof(tword)<=count) - perror("tnode string too long"); - strcpy(tword,w); - left = l; - right = r; -} - -void f(tnode n1, tnode n2) { - n1.set("abc",&n2,0); - n2.set("def",0,0); -} -\end{codeblock} - -In the body of the member function \tcode{tnode::set}, the member names -\tcode{tword}, \tcode{count}, \tcode{left}, and \tcode{right} refer to -members of the object for which the function is called. Thus, in the -call \tcode{n1.set("abc",\&n2,0)}, \tcode{tword} refers to -\tcode{n1.tword}, and in the call \tcode{n2.set("def",0,0)}, it refers -to \tcode{n2.tword}. The functions \tcode{strlen}, \tcode{perror}, and -\tcode{strcpy} are not members of the class \tcode{tnode} and should be -declared elsewhere. -\begin{footnote} -See, for example, \libheaderref{cstring}. -\end{footnote} -\end{example} - \pnum \indextext{member function!const}% \indextext{member function!volatile}% @@ -1081,7 +1205,7 @@ \end{example} \pnum -Two special member functions are of the same kind if: +Two special member functions are of the same kind if \begin{itemize} \item they are both default constructors, \item they are both copy or move constructors @@ -1239,7 +1363,7 @@ has a default argument (including the case of a constructor with no parameters). \indextext{implicitly-declared default constructor}% -If there is no user-declared constructor for class +If there is no user-declared constructor or constructor template for class \tcode{X}, a non-explicit constructor having no parameters is implicitly declared as defaulted\iref{dcl.fct.def}. @@ -1247,56 +1371,50 @@ inline public member of its class. \pnum -A defaulted default constructor for class \tcode{X} is defined as deleted if: +A defaulted default constructor for class \tcode{X} is defined as deleted if \begin{itemize} \item any non-static data member with no default member initializer\iref{class.mem} is of reference type, -\item any non-variant non-static data member of const-qualified type -(or possibly multi-dimensional array thereof) +\item \tcode{X} is a non-union class and +any non-variant non-static data member of const-qualified type +(or possibly multidimensional array thereof) with no \grammarterm{brace-or-equal-initializer} is not const-default-constructible\iref{dcl.init}, -\item \tcode{X} is a union and all of its variant members are of const-qualified -type (or possibly multi-dimensional array thereof), - -\item \tcode{X} is a non-union class and all members of any anonymous union member are -of const-qualified type (or possibly multi-dimensional array thereof), - -\item any potentially constructed subobject, except for a non-static data member -with a \grammarterm{brace-or-equal-initializer} -or a variant member of a union where another non-static data member -has a \grammarterm{brace-or-equal-initializer}, -has class type \tcode{M} (or possibly multi-dimensional array thereof) +\item any non-variant potentially constructed subobject, except for a non-static data member +with a \grammarterm{brace-or-equal-initializer}, +has class type \tcode{M} (or possibly multidimensional array thereof) and overload resolution\iref{over.match} as applied to find \tcode{M}'s corresponding constructor -either does not result in a usable candidate\iref{over.match.general} -or, in the case of a variant member, selects a non-trivial function, or +does not result in a usable candidate\iref{over.match.general}, or -\item any potentially constructed subobject has -class type \tcode{M} (or possibly multi-dimensional array thereof) and +\item any potentially constructed subobject $S$ has +class type \tcode{M} (or possibly multidimensional array thereof), \tcode{M} has a destructor that is deleted or inaccessible from the defaulted default -constructor. +constructor, and +either $S$ is non-variant or $S$ has a default member initializer. \end{itemize} \pnum -A default constructor is +A default constructor for a class \tcode{X} is \defnx{trivial}{constructor!default!trivial} -if it is not user-provided and if: +if it is not user-provided and if \begin{itemize} \item -its class has no virtual functions\iref{class.virtual} and no virtual base +\tcode{X} has no virtual functions\iref{class.virtual} and no virtual base classes\iref{class.mi}, and -\item no non-static data member of its class has +\item no non-static data member of \tcode{X} has a default member initializer\iref{class.mem}, and \item -all the direct base classes of its class have trivial default constructors, and +all the direct base classes of \tcode{X} have trivial default constructors, and \item -for all the non-static data members of its class that are of class +either \tcode{X} is a union or +for all the non-variant non-static data members of \tcode{X} that are of class type (or array thereof), each such class has a trivial default constructor. \end{itemize} @@ -1304,7 +1422,18 @@ \defnx{non-trivial}{constructor!default!non-trivial}. \pnum -An implicitly-defined\iref{dcl.fct.def.default} default constructor performs the set of +If a default constructor of a union-like class \tcode{X} is trivial, +then for each union \tcode{U} +that is either \tcode{X} or an anonymous union member of \tcode{X}, +if the first variant member, if any, of \tcode{U} +has implicit-lifetime type\iref{basic.types.general}, +the default constructor of \tcode{X} begins the lifetime of that member +if it is not the active member of its union. +\begin{note} +It is already the active member if \tcode{U} was value-initialized. +\end{note} +Otherwise, +an implicitly-defined\iref{dcl.fct.def.default} default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no \grammarterm{ctor-initializer}\iref{class.base.init} and an empty @@ -1472,7 +1601,7 @@ constructor is defined as deleted; otherwise, it is defaulted\iref{dcl.fct.def}. The latter case is deprecated if the class has a user-declared copy assignment -operator or a user-declared destructor \iref{depr.impldec}. +operator or a user-declared destructor\iref{depr.impldec}. \pnum The implicitly-declared copy constructor for a class @@ -1541,14 +1670,14 @@ \tcode{X} is defined as deleted\iref{dcl.fct.def.delete} if \tcode{X} has: \begin{itemize} \item a potentially constructed subobject of type - \tcode{M} (or possibly multi-dimensional array thereof) for which + \tcode{M} (or possibly multidimensional array thereof) for which overload resolution\iref{over.match}, as applied to find \tcode{M}'s corresponding constructor, either does not result in a usable candidate\iref{over.match.general} or, in the case of a variant member, selects a non-trivial function, \item any potentially constructed subobject of - class type \tcode{M} (or possibly multi-dimensional array thereof) + class type \tcode{M} (or possibly multidimensional array thereof) where \tcode{M} has a destructor that is deleted or inaccessible from the defaulted constructor, or, @@ -1570,7 +1699,7 @@ \tcode{X} is trivial -if it is not user-provided and if: +if it is not user-provided and if \begin{itemize} \item class @@ -1617,7 +1746,7 @@ \tcode{X} performs a memberwise copy/move of its bases and members. \begin{note} -Default member initializers of non-static data members are ignored. See also the example in~\ref{class.base.init}. +Default member initializers of non-static data members are ignored. \end{note} The order of initialization is the same as the order of initialization of bases and members in a user-defined constructor (see~\ref{class.base.init}). @@ -1711,7 +1840,7 @@ assignment operator is defined as deleted; otherwise, it is defaulted\iref{dcl.fct.def}. The latter case is deprecated if the class has a user-declared copy constructor -or a user-declared destructor \iref{depr.impldec}. +or a user-declared destructor\iref{depr.impldec}. The implicitly-declared copy assignment operator for a class \tcode{X} will have the form @@ -1811,16 +1940,15 @@ class \tcode{X} is defined as deleted if \tcode{X} has: \begin{itemize} \item a non-static data member of \keyword{const} non-class - type (or possibly multi-dimensional array thereof), or + type (or possibly multidimensional array thereof), or \item a non-static data member of reference type, or \item a direct non-static data member of class type \tcode{M} - (or possibly multi-dimensional array thereof) or + (or possibly multidimensional array thereof) or a direct base class \tcode{M} - that cannot be copied/moved because overload resolution - \iref{over.match}, as applied to find \tcode{M}'s corresponding - assignment operator, + that cannot be copied/moved because overload resolution\iref{over.match}, + as applied to find \tcode{M}'s corresponding assignment operator, either does not result in a usable candidate\iref{over.match.general} or, in the case of a variant member, selects a non-trivial function. \end{itemize} @@ -1836,7 +1964,7 @@ Because a copy/move assignment operator is implicitly declared for a class if not declared by the user, a base class copy/move assignment operator is always hidden -by the corresponding assignment operator of a derived class\iref{over.ass}. +by the corresponding assignment operator of a derived class\iref{over.assign}. \begin{note} A \grammarterm{using-declaration} in a derived class \tcode{C} that names an assignment operator from a base class @@ -1854,7 +1982,7 @@ \tcode{X} is trivial -if it is not user-provided and if: +if it is not user-provided and if \begin{itemize} \item class @@ -2052,27 +2180,42 @@ \pnum A defaulted destructor for a class - \tcode{X} is defined as deleted if: + \tcode{X} is defined as deleted if \begin{itemize} -\item any potentially constructed subobject has class type - \tcode{M} (or possibly multi-dimensional array thereof) and +\item \tcode{X} is a non-union class and + any non-variant potentially constructed subobject has class type + \tcode{M} (or possibly multidimensional array thereof) where \tcode{M} has a destructor that is deleted or - is inaccessible from the defaulted destructor or, - in the case of a variant member, is non-trivial, + is inaccessible from the defaulted destructor, -\item or, for a virtual destructor, lookup of the non-array deallocation +\item + \tcode{X} is a union and + \begin{itemize} + \item + overload resolution to select a constructor to + default-initialize an object of type \tcode{X} either fails or + selects a constructor that is either deleted or not trivial, or + \item + \tcode{X} has a variant member \tcode{V} of + class type \tcode{M} (or possibly multi-dimensional array thereof) + where \tcode{V} has a default member initializer and + \tcode{M} has a destructor that is non-trivial, or, + \end{itemize} + +\item for a virtual destructor, lookup of the non-array deallocation function results in an ambiguity or in a function that is deleted or inaccessible from the defaulted destructor. \end{itemize} \pnum -A destructor is trivial if it is not user-provided and if: +A destructor for a class \tcode{X} is trivial if it is not user-provided and if \begin{itemize} \item the destructor is not virtual, -\item all of the direct base classes of its class have trivial destructors, and +\item all of the direct base classes of \tcode{X} have trivial destructors, and -\item for all of the non-static data members of its class that are of class +\item either \tcode{X} is a union or +for all of the non-variant non-static data members of \tcode{X} that are of class type (or array thereof), each such class has a trivial destructor. \end{itemize} @@ -2244,7 +2387,7 @@ Such use of explicit placement and destruction of objects can be necessary to cope with dedicated hardware resources and for writing memory management facilities. -For example, +\begin{example} \begin{codeblock} void* operator new(std::size_t, void* p) { return p; } struct X { @@ -2260,6 +2403,7 @@ p->X::~X(); // cleanup } \end{codeblock} +\end{example} \end{note} \pnum @@ -2315,8 +2459,7 @@ \pnum \begin{note} -See~\ref{over.match} for a discussion of the use of conversions in function calls -as well as examples below. +See~\ref{over.match} for a discussion of the use of conversions in function calls. \end{note} \pnum @@ -2347,8 +2490,6 @@ specifies a conversion from the types of its parameters (if any) to the type of its class. -Such a constructor is called a -\defnadj{converting}{constructor}. \begin{example} \indextext{Jessie}% \begin{codeblock} @@ -2399,14 +2540,6 @@ \end{example} \end{note} -\pnum -A non-explicit copy/move constructor\iref{class.copy.ctor} is -a converting constructor. -\begin{note} -An implicitly-declared copy/move constructor is not an explicit constructor; -it can be called for implicit type conversions. -\end{note} - \rSec3[class.conv.fct]{Conversion functions}% \indextext{function!conversion}% \indextext{fundamental type conversion|see{conversion, user-defined}}% @@ -2435,10 +2568,9 @@ 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} \opt{noexcept-specifier} \opt{attribute-specifier-seq} +noptr-declarator parameters-and-qualifiers \end{ncsimplebnf} -where the \grammarterm{ptr-declarator} consists solely of +where the \grammarterm{noptr-declarator} consists solely of an \grammarterm{id-expression}, an optional \grammarterm{attribute-specifier-seq}, and optional surrounding parentheses, and @@ -2457,6 +2589,7 @@ \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}; +its declared return type is the \grammarterm{conversion-type-id} and 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}. @@ -2464,13 +2597,6 @@ 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 is -``\opt{\tcode{noexcept}} function taking no parameter -\opt{\grammarterm{cv-qualifier-seq}} \opt{\grammarterm{ref-qualifier}} -returning \grammarterm{conversion-type-id}''. - \pnum \begin{note} A conversion function is never invoked for @@ -2897,7 +3023,7 @@ 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{example} \begin{codeblock} struct B { virtual ~B(); @@ -2933,6 +3059,7 @@ and its storage is deallocated by \tcode{E::operator delete()}, due to the virtual destructor. +\end{example} \end{note} \begin{note} Virtual destructors have no effect on the deallocation function actually @@ -2941,7 +3068,7 @@ of a \grammarterm{delete-expression} refers to an array of objects of class type. -For example, +\begin{example} \begin{codeblock} struct B { virtual ~B(); @@ -2959,6 +3086,7 @@ delete[] bp; // undefined behavior } \end{codeblock} +\end{example} \end{note} \pnum @@ -3099,14 +3227,14 @@ base classes. A union shall not be used as a base class. \indextext{restriction!\idxcode{union}}% If a union contains a non-static data member of -reference type the program is ill-formed. -\begin{note} -Absent default member initializers\iref{class.mem}, -if any non-static data member of a union has a non-trivial -default constructor\iref{class.default.ctor}, -copy constructor, move constructor\iref{class.copy.ctor}, -copy assignment operator, move assignment operator\iref{class.copy.assign}, -or destructor\iref{class.dtor}, the corresponding member function +reference type, the program is ill-formed. +\begin{note} +If any non-static data member of a union has a non-trivial +copy constructor, +move constructor\iref{class.copy.ctor}, +copy assignment operator, or +move assignment operator\iref{class.copy.assign}, +the corresponding member function of the union must be user-provided or it will be implicitly deleted\iref{dcl.fct.def.delete} for the union. \begin{example} @@ -3119,11 +3247,11 @@ }; \end{codeblock} Since \tcode{std::string}\iref{string.classes} declares non-trivial versions of all of the special -member functions, \tcode{U} will have an implicitly deleted default constructor, -copy/move constructor, -copy/move assignment operator, and destructor. -To use \tcode{U}, some or all of these member functions -must be user-provided. +member functions, \tcode{U} will have an implicitly deleted +copy/move constructor and copy/move assignment operator. +The default constructor and destructor of \tcode{U} are both trivial +even though \tcode{std::string} has +a non-trivial default constructor and a non-trivial destructor. \end{example} \end{note} @@ -3155,7 +3283,7 @@ Otherwise, $S(\mathtt{E})$ is empty. \end{itemize} In an assignment expression of the form \tcode{E1 = E2} -that uses either the built-in assignment operator\iref{expr.ass} +that uses either the built-in assignment operator\iref{expr.assign} or a trivial assignment operator\iref{class.copy.assign}, for each element \tcode{X} of $S($\tcode{E1}$)$ and each anonymous union member \tcode{X}\iref{class.union.anon} that @@ -3358,13 +3486,13 @@ \pnum \indextext{nested class!local class}% -If class \tcode{X} is a local class, a nested class \tcode{Y} may be -declared in class \tcode{X} and later defined in the definition of class -\tcode{X} or be later defined in the same scope as the definition of -class \tcode{X}. \indextext{restriction!local class}% A class nested within a local class is a local class. +A member of a local class \tcode{X} shall be +declared only in the definition of \tcode{X} or, +if the member is a nested class, +in the nearest enclosing block scope of \tcode{X}. \pnum \indextext{restriction!static member local class}% @@ -3411,7 +3539,7 @@ \nontermdef{class-or-decltype}\br \opt{nested-name-specifier} type-name\br nested-name-specifier \keyword{template} simple-template-id\br - decltype-specifier + computed-type-specifier \end{bnf} \indextext{specifier access|see{access specifier}}% @@ -3439,7 +3567,12 @@ The class denoted by the \grammarterm{class-or-decltype} of a \grammarterm{base-specifier} is called a \defnadj{direct}{base class} -for the class being defined. +for the class being defined; +for each such \grammarterm{base-specifier}, +the corresponding \defnadj{direct base class}{relationship} +is the ordered pair (\tcode{D}, \tcode{B}) +where \tcode{D} is the class being defined and +\tcode{B} is the direct base class. \indextext{base class}% \indextext{derivation|see{inheritance}}% The lookup for the component name of @@ -3735,13 +3868,13 @@ determining overriding. \end{footnote} $F$. -For convenience we say that any virtual function overrides itself. +For convenience, we say that any virtual function overrides itself. \indextext{overrider!final}% A virtual member function $V$ of a class object $S$ is a \defn{final overrider} unless the most derived class\iref{intro.object} of which $S$ is a base class subobject (if any) has another member function that overrides $V$. In a derived class, if a virtual member function of a base class subobject -has more than one final overrider the program is ill-formed. +has more than one final overrider, the program is ill-formed. \begin{example} \begin{codeblock} struct A { @@ -4270,11 +4403,11 @@ \end{codeblock} \end{example} \begin{note} -Because access control applies to the declarations named, if access control is applied to a -\grammarterm{typedef-name}, only the accessibility of the typedef or alias declaration itself is considered. -The accessibility of the entity referred to by the \grammarterm{typedef-name} is not considered. -For example, - +Because access control applies to the declarations named, +if access control is applied to a type alias, +only the accessibility of the typedef or alias declaration itself is considered. +The accessibility of the underlying entity is not considered. +\begin{example} \begin{codeblock} class A { class B { }; @@ -4287,6 +4420,7 @@ A::B y; // access error, \tcode{A::B} is private } \end{codeblock} +\end{example} \end{note} \pnum @@ -4316,8 +4450,8 @@ \begin{codeblock} class A { typedef int I; // private member - I f(); - friend I g(I); + I f() pre(A::x > 0); + friend I g(I) post(A::x <= 0); static I x; template struct Q; template friend struct R; @@ -4325,8 +4459,8 @@ struct B { }; }; -A::I A::f() { return 0; } -A::I g(A::I p = A::x); +A::I A::f() pre(A::x > 0) { return 0; } +A::I g(A::I p = A::x) post(A::x <= 0); A::I g(A::I p) { return 0; } A::I A::x = 0; template struct A::Q { }; @@ -4551,8 +4685,7 @@ 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. -For example, - +\begin{example} \begin{codeblock} class B { public: @@ -4577,6 +4710,7 @@ bp2->mi = 3; // OK, access through a pointer to \tcode{B}. } \end{codeblock} +\end{example} \end{note} \pnum @@ -4663,10 +4797,18 @@ to a pointer to a private or protected immediate base class of \tcode{X}. \end{note} -The access to a member is affected by the class in which the member is -named. -This naming class is -the class in whose scope name lookup performed a search that found the member. +An expression $E$ that designates a member \tcode{m} +has a \defnadj{designating}{class} +that affects the access to \tcode{m}. +This designating class is either +\begin{itemize} +\item +the innermost class of which \tcode{m} is directly a member +if $E$ is a \grammarterm{splice-expression} or +\item +the class in whose scope name lookup performed a search +that found \tcode{m} otherwise. +\end{itemize} \begin{note} This class can be explicit, e.g., when a \grammarterm{qualified-id} @@ -4678,7 +4820,7 @@ \grammarterm{qualified-id} are used to name the member (as in \tcode{p->T::m}), -the class naming the member is the class denoted by the +the class designating the member is the class designated by the \grammarterm{nested-name-specifier} of the \grammarterm{qualified-id} @@ -4689,11 +4831,13 @@ \tcode{m} is accessible at the point \placeholder{R} -when named in class +when designated in class \tcode{N} if \begin{itemize} \item +\tcode{m} is designated by a \grammarterm{splice-expression}, or +\item \tcode{m} as a member of \tcode{N} @@ -4735,7 +4879,7 @@ \tcode{m} is accessible at \placeholder{R} -when named in class +when designated in class \tcode{B}. \begin{example} \begin{codeblock} @@ -4761,10 +4905,10 @@ left operand (considered as a pointer in the ``\tcode{.}'' operator case) cannot be implicitly converted to a -pointer to the naming class of the right operand. +pointer to the designating class of the right operand. \begin{note} This requirement is in addition to the requirement that -the member be accessible as named. +the member be accessible as designated. \end{note} \rSec2[class.friend]{Friends}% @@ -4841,27 +4985,22 @@ \pnum A friend declaration that does not declare a function -shall have one of the following forms: - -\begin{ncsimplebnf} -\keyword{friend} elaborated-type-specifier \terminal{;}\br -\keyword{friend} simple-type-specifier \terminal{;}\br -\keyword{friend} typename-specifier \terminal{;} -\end{ncsimplebnf} +shall be a \grammarterm{friend-type-declaration}. \begin{note} A friend declaration can be the \grammarterm{declaration} in a \grammarterm{template-declaration}\iref{temp.pre,temp.friend}. \end{note} -If the -type specifier in a friend declaration designates a (possibly +If a \grammarterm{friend-type-specifier} in a friend declaration +designates a (possibly cv-qualified) class type, that class is declared as a friend; otherwise, the -friend declaration is ignored. +\grammarterm{friend-type-specifier} is ignored. \begin{example} \begin{codeblock} class C; typedef C Ct; +class E; class X1 { friend C; // OK, \tcode{class C} is a friend @@ -4873,21 +5012,25 @@ friend class D; // OK, elaborated-type-specifier declares new class }; -template class R { - friend T; +template class R { + friend Ts...; +}; + +template +class R, R> { + friend Ts::Nested..., Us...; }; R rc; // \tcode{class C} is a friend of \tcode{R} -R Ri; // OK, \tcode{"friend int;"} is ignored +R rce; // classes \tcode{C} and \tcode{E} are friends of \tcode{R} +R Ri; // OK, ``\tcode{friend int;}'' is ignored + +struct E { struct Nested; }; + +R, R> rr; // \tcode{E::Nested} and \tcode{C} are friends of \tcode{R, R>} \end{codeblock} \end{example} -\pnum -\indextext{friend function!linkage of}% -A function first declared in a friend declaration -has the linkage of the namespace of which it is a member\iref{basic.link}. -Otherwise, the function retains its previous linkage\iref{dcl.stc}. - \pnum \indextext{declaration!overloaded name and \tcode{friend}}% \begin{note} @@ -5262,7 +5405,7 @@ \end{example} \begin{note} \indextext{initialization!overloaded assignment and}% -Overloading of the assignment operator\iref{over.ass} +Overloading of the assignment operator\iref{over.assign} has no effect on initialization. \end{note} @@ -5323,7 +5466,7 @@ If \tcode{T} is a class type with no default constructor, -any declaration of an object of type +any initializing declaration of an object of type \tcode{T} (or array thereof) is ill-formed if no \grammarterm{initializer} @@ -5559,7 +5702,7 @@ is neither initialized nor given a value during execution of the \grammarterm{compound-statement} of the body of the constructor, -the member has an indeterminate value. +the member has an indeterminate or erroneous value\iref{basic.indet}. \end{note} \begin{example} \begin{codeblock} @@ -5575,7 +5718,7 @@ C() { } // initializes members as follows: 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 i; // OK, \tcode{i} has indeterminate or erroneous value int j = 5; // OK, \tcode{j} has the value \tcode{5} }; \end{codeblock} @@ -5743,18 +5886,27 @@ \pnum \indextext{initialization!member function call during}% Member functions (including virtual member functions, \ref{class.virtual}) can be -called for an object under construction. -Similarly, an object under construction can be the operand of the +called for an object under construction or destruction. +Similarly, an object under construction or destruction can be the operand of the \tcode{typeid} operator\iref{expr.typeid} or of a \keyword{dynamic_cast}\iref{expr.dynamic.cast}. -However, if these operations are performed in a -\grammarterm{ctor-initializer} +However, if these operations are performed +during evaluation of +\begin{itemize} +\item +a \grammarterm{ctor-initializer} (or in a function called directly or indirectly from a \grammarterm{ctor-initializer}) before all the \grammarterm{mem-initializer}{s} -for base classes have completed, the program has undefined behavior. +for base classes have completed, +\item +a precondition assertion of a constructor, or +\item +a postcondition assertion of a destructor\iref{dcl.contract.func}, +\end{itemize} +the program has undefined behavior. \begin{example} \begin{codeblock} class A { @@ -5970,7 +6122,7 @@ B bobj; // definition of \tcode{bobj} extern X xobj; -int* p3 = &xobj.i; // OK, \tcode{X} is a trivial class +int* p3 = &xobj.i; // OK, all constructors of \tcode{X} are trivial X xobj; \end{codeblock} For another example, @@ -5988,11 +6140,12 @@ \pnum During the construction of an object, -if the value of the object or any of its subobjects is -accessed through a glvalue that is not obtained, directly or indirectly, from +if the value of any of its subobjects +or any element of its object representation +is accessed through a glvalue that is not obtained, directly or indirectly, from the constructor's \keyword{this} -pointer, the value of the object or subobject thus obtained is unspecified. +pointer, the value thus obtained is unspecified. \begin{example} \begin{codeblock} struct C; @@ -6077,6 +6230,9 @@ or from a destructor, including during the construction or destruction of the class's non-static data members, +or during the evaluation of +a postcondition assertion of a constructor or +a precondition assertion of a destructor\iref{dcl.contract.func}, and the object to which the call applies is the object (call it \tcode{x}) under construction or destruction, the function called is the @@ -6206,25 +6362,26 @@ \indextext{constructor!copy!elision}% \indextext{constructor!move!elision}% When certain criteria are met, an implementation is -allowed to omit the copy/move construction of a class object, -even if the constructor selected for the copy/move operation and/or the +allowed to omit the creation of a class object from +a source object of the same type (ignoring cv-qualification), +even if the selected constructor and/or the destructor for the object have \indextext{side effects}% side effects. In such cases, the implementation treats the source and target of the -omitted copy/move operation as simply two different ways of +omitted initialization as simply two different ways of referring to the same object. If the first parameter of the selected constructor is an rvalue reference to the object's type, the destruction of that object occurs when the target would have been destroyed; otherwise, the destruction occurs at the later of the times when the two objects would have been destroyed without the optimization. -\begin{footnote} +\begin{note} Because only one object is destroyed instead of two, -and one copy/move constructor -is not executed, there is still one object destroyed for each one constructed. -\end{footnote} -This elision of copy/move operations, called +and the creation of one object is omitted, +there is still one object destroyed for each one constructed. +\end{note} +This elision of object creation, called \indexdefn{copy elision|see{constructor, copy, elision}}% \indexdefn{elision!copy|see{constructor, copy, elision}}% \indexdefn{constructor!copy!elision}\indexdefn{constructor!move!elision}\term{copy elision}, @@ -6232,34 +6389,35 @@ following circumstances (which may be combined to eliminate multiple copies): \begin{itemize} -\item in a \tcode{return} statement in a function with a class return type, +\item in a \tcode{return} statement\iref{stmt.return} in +a function with a class return type, when the \grammarterm{expression} is the name of a non-volatile -object with automatic storage duration (other than a function parameter or a variable +object $o$ with automatic storage duration (other than a function parameter or a variable introduced by the \grammarterm{exception-declaration} of a -\grammarterm{handler}\iref{except.handle}) -with the same type (ignoring cv-qualification) as -the function return type, the copy/move operation can be -omitted by constructing the object directly -into the function call's return object +\grammarterm{handler}\iref{except.handle}), +the copy-initialization of the result object can be +omitted by constructing $o$ directly +into the function call's result object; \item in a \grammarterm{throw-expression}\iref{expr.throw}, when the operand -is the name of a non-volatile object with automatic storage duration -(other than a function or catch-clause parameter) +is the name of a non-volatile object $o$ with automatic storage duration +(other than a function parameter or +a variable introduced by +the \grammarterm{exception-declaration} of a \grammarterm{handler}) that belongs to a scope that does not contain the innermost enclosing \grammarterm{compound-statement} associated with a \grammarterm{try-block} (if there is one), -the copy/move operation can be omitted by -constructing the object directly into the exception object +the copy-initialization of the exception object can be omitted by +constructing $o$ directly into the exception object; \item in a coroutine\iref{dcl.fct.def.coroutine}, a copy of a coroutine parameter can be omitted and references to that copy replaced with references to the corresponding parameter if the meaning of the program will be unchanged except for -the execution of a constructor and destructor for the parameter copy object +the execution of a constructor and destructor for the parameter copy object; \item when the \grammarterm{exception-declaration} of a -\grammarterm{handler}\iref{except.handle} declares an object of the same -type (except for cv-qualification) as the exception -object\iref{except.throw}, the copy operation can be omitted by treating +\grammarterm{handler}\iref{except.handle} declares an object $o$, +the copy-initialization of $o$ can be omitted by treating the \grammarterm{exception-declaration} as an alias for the exception object if the meaning of the program will be unchanged except for the execution of constructors and destructors for the object declared by the @@ -6407,12 +6565,15 @@ \pnum A defaulted comparison operator function\iref{over.binary} -for some class \tcode{C} shall be a non-template function -that is +that \begin{itemize} \item -a non-static member or friend of \tcode{C} and +is a non-static member or friend of some class \tcode{C}, + +\item +is defined as defaulted in \tcode{C} or in +a context where \tcode{C} is complete, and \item either has @@ -6421,13 +6582,28 @@ where the implicit object parameter (if any) is considered to be the first parameter. \end{itemize} -Name lookups in the implicit definition\iref{dcl.fct.def.default} +Such a comparison operator function is termed +\indextext{operator!defaulted comparison operator function}% +a defaulted comparison operator function for class \tcode{C}. +Name lookups and access checks in +the implicit definition\iref{dcl.fct.def.default} of a comparison operator function are performed from a context equivalent to its \grammarterm{function-body}. A definition of a comparison operator as defaulted that appears in a class shall be the first declaration of that function. +\begin{example} +\begin{codeblock} +struct S; +bool operator==(S, S) = default; // error: \tcode{S} is not complete +struct S { + friend bool operator==(S, const S&) = default; // error: parameters of different types +}; +enum E { }; +bool operator==(E, E) = default; // error: not a member or friend of a class +\end{codeblock} +\end{example} \pnum A defaulted \tcode{<=>} or \tcode{==} operator function for class \tcode{C} @@ -6570,7 +6746,8 @@ \tcode{static_cast(a <=> b)}. \item -Otherwise, if overload resolution for \tcode{a <=> b} is performed and +Otherwise, if \tcode{a <=> b} is usable or +overload resolution for \tcode{a <=> b} is performed and finds at least one viable candidate, the synthesized three-way comparison is not defined. @@ -6695,18 +6872,29 @@ is defined as deleted if \begin{itemize} \item -overload resolution\iref{over.match}, +a first overload resolution\iref{over.match}, as applied to \tcode{x @ y}, +\begin{itemize} +\item does not result in a usable candidate, or - \item -the candidate selected by overload resolution -is not a rewritten candidate. +the selected candidate is not a rewritten candidate, or \end{itemize} +\item +a second overload resolution for +the expression resulting from the interpretation of \tcode{x @ y} +using the selected rewritten candidate\iref{over.match.oper} +does not result in a usable candidate +(for example, that expression might be \tcode{(x <=> y) @ 0}), or + +\item +\tcode{x @ y} cannot be implicitly converted to \tcode{bool}. +\end{itemize} +In any of the two overload resolutions above, +the defaulted operator function is not considered as +a candidate for the \tcode{@} operator. Otherwise, the operator function yields \tcode{x @ y}. -The defaulted operator function is not considered as a candidate -in the overload resolution for the \tcode{@} operator. \pnum \begin{example} diff --git a/source/compatibility.tex b/source/compatibility.tex index ccb63c3d6b..a46c9a71cc 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -8,9 +8,42 @@ \pnum \indextext{summary!compatibility with ISO \CppXXIII{}}% Subclause \ref{diff.cpp23} lists the differences between \Cpp{} and -ISO \CppXXIII{} (ISO/IEC 14882:2023, \doccite{Programming Languages --- \Cpp{}}), +ISO \CppXXIII{}, by the chapters of this document. +\rSec2[diff.cpp23.lex]{\ref{lex}: lexical conventions} + +\diffref{lex.operators} +\change +New operator \tcode{\caret\caret}. +\rationale +Required for new features. +\effect +Valid \CppXXIII{} code that contains two consecutive \tcode{\caret} tokens +can be ill-formed in this revision of \Cpp{}. +\begin{example} +\begin{codeblock} +struct C { int operator^(int); }; +int operator^(int (C::*p)(int), C); +int i = &C::operator^^C{}; // ill-formed; previously well-formed +\end{codeblock} +\end{example} + +\diffref{lex.key} +\change +New keywords. +\rationale +Required for new features. +\begin{itemize} +\item +The \keyword{contract_assert} keyword +is added to introduce a contract assertion +through an \grammarterm{assertion-statement}\iref{stmt.contract.assert}. +\end{itemize} +\effect +Valid \CppXXIII{} code using \keyword{contract_assert} as an identifier +is not valid in this revision of \Cpp{}. + \rSec2[diff.cpp23.expr]{\ref{expr}: expressions} \diffref{expr.arith.conv} @@ -23,7 +56,7 @@ A valid \CppXXIII{} program that performs operations mixing a value of an enumeration type and a value of a different enumeration type or of a floating-point type is ill-formed. -For example: +\begin{example} \begin{codeblock} enum E1 { e }; enum E2 { f }; @@ -31,8 +64,64 @@ int k = f - e; // ill-formed; previously well-formed auto x = true ? e : f; // ill-formed; previously well-formed \end{codeblock} +\end{example} -\rSec2[diff.cpp23.dcl.dcl]{\ref{dcl.dcl}: Declarations} +\diffref{expr.rel,expr.eq} +\change +Comparing two objects of array type is no longer valid. +\rationale +The old behavior was confusing since it compared not the contents of the two +arrays, but their addresses. +\effect +A valid \CppXXIII{} program directly comparing two array objects is rejected as +ill-formed in this document. +\begin{example} +\begin{codeblock} +int arr1[5]; +int arr2[5]; +bool same = arr1 == arr2; // ill-formed; previously well-formed +bool idem = arr1 == +arr2; // compare addresses +bool less = arr1 < +arr2; // compare addresses, unspecified result +\end{codeblock} +\end{example} + +\diffref{expr.delete} +\change +Calling \tcode{delete} on a pointer to an incomplete class is ill-formed. +\rationale +Reduce undefined behavior. +\effect +A valid \CppXXIII{} program that calls \tcode{delete} on an incomplete +class type is ill-formed. +\begin{example} +\begin{codeblock} +struct S; + +void f(S *p) { + delete p; // ill-formed; previously well-formed +} + +struct S {}; +\end{codeblock} +\end{example} + +\rSec2[diff.cpp23.dcl.dcl]{\ref{dcl}: declarations} + +\diffref{dcl.decl.general} +\change +Introduction of \tcode{trivially_relocatable_if_eligible} and +\tcode{replaceable_if_eligible} as identifiers with special meaning\iref{lex.name}. +\rationale +Support declaration of trivially relocatable and replaceable types\iref{class.prop}. +\effect +Valid \CppXXIII{} code can become ill-formed. +\begin{example} +\begin{codeblock} +struct C {}; +struct C replaceable_if_eligible {}; // was well-formed (new variable \tcode{replaceable_if_eligible}) + // now ill-formed (redefines \tcode{C}) +\end{codeblock} +\end{example} \diffref{dcl.init.list} \change @@ -44,13 +133,14 @@ Valid \CppXXIII{} code that relies on the result of pointer comparison between backing arrays may change behavior. -For example: +\begin{example} \begin{codeblock} bool ne(std::initializer_list a, std::initializer_list b) { return a.begin() != b.begin() + 1; } bool b = ne({2,3}, {1,2,3}); // unspecified result; previously \tcode{false} \end{codeblock} +\end{example} \diffref{dcl.array} \change @@ -61,7 +151,7 @@ \effect Valid \CppXXIII{} code that declares a pack of parameters without specifying a \grammarterm{declarator-id} becomes ill-formed. -For example: +\begin{example} \begin{codeblock} template void f(T... [1]); @@ -72,6 +162,81 @@ g(nullptr, nullptr); // ok } \end{codeblock} +\end{example} + +\diffref{dcl.attr.grammar} +\change +New token \tcode{:]}. +\rationale +Required for new features. +\effect +Valid \CppXXIII{} code that contained an \grammarterm{attribute-specifier} +with an \grammarterm{attribute-using-prefix} +but no attributes and no whitespace is ill-formed in this revision of \Cpp{}. +\begin{example} +\begin{codeblock} +struct [[using CC:]] C; // ill-formed; previously well-formed +struct [[using DD: ]] D; // OK +\end{codeblock} +\end{example} + +\rSec2[diff.cpp23.temp]{\ref{temp}: templates} + +\diffref{temp.constr} +\change +Some atomic constraints become fold expanded constraints. +\rationale +Permit the subsumption of fold expressions. +\effect +Valid \CppXXIII{} code may become ill-formed. +\begin{example} +\begin{codeblock} +template struct A; +struct S { + static constexpr int compare(const S&) { return 1; } +}; + +template +void f(A *, A *) +requires (T::compare(U{}) && ...); // was well-formed (atomic constraint of type \tcode{bool}), + // now ill-formed (results in an atomic constraint of type \tcode{int}) +void g(A *ap) { + f(ap, ap); +} +\end{codeblock} +\end{example} + +\diffref{temp.deduct.call} +\change +Template argument deduction from overload sets succeeds in more cases. +\rationale +Allow consideration of constraints to disambiguate overload sets +used as parameters in function calls. +\effect +Valid \CppXXIII{} code may become ill-formed. +\begin{example} +\begin{codeblock} +template +void f(T &&, void (*)(T &&)); + +void g(int &); // \#1 +inline namespace A { + void g(short &&); // \#2 +} +inline namespace B { + void g(short &&); // \#3 +} + +void q() { + int x; + f(x, g); // ill-formed; previously well-formed, deducing \tcode{T = int\&} +} +\end{codeblock} +There is no change to the applicable deduction rules for +the individual \tcode{g} candidates: +Type deduction from \#1 does not succeed; +type deductions from \#2 and \#3 both succeed. +\end{example} \rSec2[diff.cpp23.library]{\ref{library}: library introduction} @@ -82,31 +247,43 @@ New functionality. \effect The following \Cpp{} headers are new: +\libheaderrefx{contracts}{support.contract}, \libheaderref{debugging}, \libheaderrefx{hazard_pointer}{hazard.pointer.syn}, +\libheaderref{hive}, +\libheaderrefx{inplace_vector}{inplace.vector.syn}, \libheaderref{linalg}, -\libheaderref{rcu}, and +\libheaderref{meta}, +\libheaderref{rcu}, +\libheaderref{simd}, +\libheaderref{stdbit.h}, +\libheaderref{stdckdint.h}, and \libheaderrefx{text_encoding}{text.encoding.syn}. Valid \CppXXIII{} code that \tcode{\#include}{s} headers with these names may be invalid in this revision of \Cpp{}. -\rSec2[diff.cpp23.strings]{\ref{strings}: strings library} +\diffref{res.on.macro.definitions} +\change +Additional restrictions on macro names. +\rationale +Avoid hard to diagnose or non-portable constructs. +\effect +Names of special identifiers may not be used as macro names. +Valid \CppXXIII{} code that defines \tcode{replaceable_if_eligible} or +\tcode{trivially_relocatable_if_eligible} as macros is invalid +in this revision of \Cpp{}. -\diffref{string.conversions} +\rSec2[diff.cpp23.mem]{\ref{mem}: memory management library} + +\diffref{c.malloc} \change -Output of floating-point overloads of \tcode{to_string} and \tcode{to_wstring}. +Calling \tcode{realloc} with a non-null pointer and zero size +has erroneous behavior. \rationale -Prevent loss of information and improve consistency with other formatting -facilities. +The C standard library does not define this behavior. \effect -\tcode{to_string} and \tcode{to_wstring} function calls that take -floating-point arguments may produce a different output. -For example: -\begin{codeblock} -auto s = std::to_string(1e-7); // \tcode{"1e-07"} - // previously \tcode{"0.000000"} with \tcode{'.'} possibly - // changed according to the global C locale -\end{codeblock} +Valid \CppXXIII{} code that calls \tcode{realloc} +with a non-null pointer and a size of zero is erroneous and may change behavior. \rSec2[diff.cpp23.containers]{\ref{containers}: containers library} @@ -118,7 +295,7 @@ \effect Valid \CppXXIII{} code that relies on the lack of this constructor may refuse to compile, or change behavior in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} void one(pair); // \#1 void one(span); // \#2 @@ -132,6 +309,48 @@ any b[10]; int y = span{b, b + 10}.size(); // \tcode{y} is \tcode{2}; previously \tcode{10} \end{codeblock} +\end{example} + +\rSec2[diff.cpp23.strings]{\ref{strings}: strings library} + +\diffref{string.conversions} +\change +Output of floating-point overloads of \tcode{to_string} and \tcode{to_wstring}. +\rationale +Prevent loss of information and improve consistency with other formatting +facilities. +\effect +\tcode{to_string} and \tcode{to_wstring} function calls that take +floating-point arguments may produce a different output. +\begin{example} +\begin{codeblock} +auto s = std::to_string(1e-7); // \tcode{"1e-07"} + // previously \tcode{"0.000000"} with \tcode{'.'} possibly + // changed according to the global C locale +\end{codeblock} +\end{example} + +\rSec2[diff.cpp23.io]{\ref{input.output}: input/output library} + +\diffref{istream.unformatted} +\change +Overloaded \tcode{std::basic_istream::ignore}. +\rationale +Allow \tcode{char} values to be used as delimiters. +\effect +Calls to \tcode{istream::ignore} with a second argument of \tcode{char} type +can change behavior. +Calls to \tcode{istream::ignore} with a second argument that is neither +\tcode{int} nor \tcode{char} type can become ill-formed. +\begin{example} +\begin{codeblock} +std::istringstream in("\xF0\x9F\xA4\xA1 Clown Face"); +in.ignore(100, '\xA1'); // ignore up to \tcode{'\textbackslash{}xA1'} delimiter, + // previously might have ignored to EOF +in.ignore(100, -1L); // ambiguous overload, + // previously equivalent to \tcode{(int)-1L} +\end{codeblock} +\end{example} \rSec2[diff.cpp23.depr]{\ref{depr}: compatibility features} @@ -144,7 +363,8 @@ would not use the one from the allocator base class. \effect It is simpler to correctly define an allocator class with an allocator base -class. For example: +class. +\begin{example} \begin{codeblock} template struct MyAlloc : allocator { @@ -154,6 +374,19 @@ static_assert(!allocator_traits>::is_always_equal); // Error in \CppXXIII{}, // OK in \CppXXVI{} \end{codeblock} +\end{example} + +\nodiffref +\change +Removal of atomic access API for \tcode{shared_ptr} objects. +\rationale +The old behavior was brittle. \tcode{shared_ptr} objects using the old API were +not protected by the type system, and certain interactions with code not using +this API would, in some cases, silently produce undefined behavior. A complete +type-safe replacement is provided in the form of \tcode{atomic>}. +\effect +A valid \CppXXIII{} program that relies on the presence of the removed functions +may fail to compile. \nodiffref \change @@ -171,7 +404,7 @@ \change Remove header \libnoheader{codecvt} and all its contents. \rationale -The header has been deprecated for the previous three editions of this standard +The header has been deprecated for the previous three editions of this document and no longer implements the current Unicode standard, supporting only the obsolete UCS-2 encoding. Ongoing support is at implementer's discretion, @@ -190,6 +423,37 @@ \item \tcode{little_endian}. \end{itemize} +\nodiffref +\change +Remove header \libnoheader{strstream} and all its contents. +\rationale +The header has been deprecated since the original \Cpp{} standard; the +\libheader{spanstream} header provides an updated, safer facility. +Ongoing support is at implementer's discretion, +exercising freedoms granted by \ref{zombie.names}. +\effect +A valid \CppXXIII{} program \tcode{\#include}-ing the header or importing the +header unit may become ill-formed. Code that uses any of the following classes +by importing one of the standard library modules may become ill-formed: +\begin{itemize} +\item \tcode{istrstream} +\item \tcode{ostrstream} +\item \tcode{strstream} +\item \tcode{strstreambuf} +\end{itemize} + +\nodiffref +\change +Remove convenience interfaces \tcode{wstring_convert} and +\tcode{wbuffer_convert}. +\rationale +These features were underspecified with no clear error reporting mechanism and +were deprecated for the last three editions of this document. +Ongoing support is at implementer's discretion, +exercising freedoms granted by \ref{zombie.names}. +\effect +A valid \CppXXIII{} program using these interfaces may become ill-formed. + \rSec1[diff.cpp20]{\Cpp{} and ISO \CppXX{}} \rSec2[diff.cpp20.general]{General} @@ -197,12 +461,15 @@ \pnum \indextext{summary!compatibility with ISO \CppXX{}}% Subclause \ref{diff.cpp20} lists the differences between \Cpp{} and -ISO \CppXX{} (ISO/IEC 14882:2020, \doccite{Programming Languages --- \Cpp{}}), +ISO \CppXX{}, +in addition to those listed above, by the chapters of this document. \rSec2[diff.cpp20.lex]{\ref{lex}: lexical conventions} \diffref{lex.name} +\indextext{XID_Start}% +\indextext{XID_Continue}% \change Previously valid identifiers containing characters not present in \UAX{44} properties XID_Start or XID_Continue, or @@ -223,10 +490,11 @@ Concatenation of \grammarterm{string-literal}s with different \grammarterm{encoding-prefix}es is now ill-formed. -For example: +\begin{example} \begin{codeblock} auto c = L"a" U"b"; // was conditionally-supported; now ill-formed \end{codeblock} +\end{example} \rSec2[diff.cpp20.expr]{\ref{expr}: expressions} @@ -238,11 +506,12 @@ \effect Valid \CppXX{} code that relies on a returned \grammarterm{id-expression}'s being an lvalue may change behavior or fail to compile. -For example: +\begin{example} \begin{codeblock} decltype(auto) f(int&& x) { return (x); } // returns \tcode{int\&\&}; previously returned \tcode{int\&} int& g(int&& x) { return x; } // ill-formed; previously well-formed \end{codeblock} +\end{example} \diffref{expr.sub} \change @@ -252,13 +521,14 @@ \effect Valid \CppXX{} code that uses a comma expression within a subscript expression may fail to compile. -For example: +\begin{example} \begin{codeblock} arr[1, 2] // was equivalent to \tcode{arr[(1, 2)]}, // now equivalent to \tcode{arr.operator[](1, 2)} or ill-formed \end{codeblock} +\end{example} -\rSec2[diff.cpp20.stmt]{\ref{stmt.stmt}: statements} +\rSec2[diff.cpp20.stmt]{\ref{stmt}: statements} \diffref{stmt.ranged} \change @@ -268,7 +538,7 @@ Improve usability of the range-based \keyword{for} statement. \effect Destructors of some temporary objects are invoked later. -For example: +\begin{example} \begin{codeblock} void f() { std::vector v = { 42, 17, 13 }; @@ -280,8 +550,9 @@ } } \end{codeblock} +\end{example} -\rSec2[diff.cpp20.dcl]{\ref{dcl.dcl}: declarations} +\rSec2[diff.cpp20.dcl]{\ref{dcl}: declarations} \diffref{dcl.init.string} \change @@ -294,7 +565,7 @@ may now be initialized with a UTF-8 string literal. This can affect initialization that includes arrays that are directly initialized within class types, typically aggregates. -For example: +\begin{example} \begin{codeblock} struct A { char8_t s[10]; @@ -310,6 +581,7 @@ f({u8""}); // ambiguous } \end{codeblock} +\end{example} \rSec2[diff.cpp20.temp]{\ref{temp}: templates} @@ -320,7 +592,7 @@ Facilitate generic handling of throwing and non-throwing functions. \effect Valid ISO \CppXX{} code may be ill-formed in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} template struct A { }; template void f(void (*)(A) noexcept(B)); @@ -329,6 +601,7 @@ f(g); // ill-formed; previously well-formed } \end{codeblock} +\end{example} \rSec2[diff.cpp20.library]{\ref{library}: library introduction} @@ -365,7 +638,7 @@ Valid \CppXX{} code relying on subsumption with \tcode{common_reference_with} may fail to compile in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} template requires @\libconcept{equality_comparable_with}@ @@ -379,6 +652,7 @@ return attempted_equals(p, nullptr); // ill-formed; previously well-formed } \end{codeblock} +\end{example} \rSec2[diff.cpp20.memory]{\ref{mem}: memory management library} @@ -409,11 +683,12 @@ contained errors in format strings or relied on previous format string signatures or \tcode{format_args_t} may become ill-formed. -For example: +\begin{example} \begin{codeblock} auto s = std::format("{:d}", "I am not a number"); // ill-formed, // previously threw \tcode{format_error} \end{codeblock} +\end{example} \diffref{format} \change @@ -426,7 +701,7 @@ \effect Valid \CppXX{} code that passes bit-fields to formatting functions may become ill-formed. -For example: +\begin{example} \begin{codeblock} struct tiny { int bit: 1; @@ -435,6 +710,7 @@ auto t = tiny(); std::format("{}", t.bit); // ill-formed, previously returned \tcode{"0"} \end{codeblock} +\end{example} \diffref{format.string.std} \change @@ -447,12 +723,13 @@ \effect Valid \CppXX{} code that passes a boolean or character type as \fmtgrammarterm{arg-id} becomes invalid. -For example: +\begin{example} \begin{codeblock} std::format("{:*^{}}", "", true); // ill-formed, previously returned \tcode{"*"} std::format("{:*^{}}", "", '1'); // ill-formed, previously returned an // implementation-defined number of \tcode{'*'} characters \end{codeblock} +\end{example} \diffref{format.formatter.spec} \change @@ -481,7 +758,7 @@ on an xvalue expression with type \tcode{S} that is a specialization of \tcode{basic_string} may change meaning in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} std::string s1 = "some long string that forces allocation", s2 = s1; std::move(s1).substr(10, 5); @@ -489,6 +766,7 @@ std::string s3(std::move(s2), 10, 5); assert(s1 == s2); // unspecified, previously guaranteed to be \tcode{true} \end{codeblock} +\end{example} \rSec2[diff.cpp20.containers]{\ref{containers}: containers library} @@ -500,7 +778,7 @@ Improve efficiency of erasing elements from associative containers. \effect Valid \CppXX{} code may fail to compile in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} struct B { auto operator<=>(const B&) const = default; @@ -512,6 +790,7 @@ } }; \end{codeblock} +\end{example} \rSec2[diff.cpp20.thread]{\ref{thread}: concurrency support library} @@ -534,7 +813,7 @@ on a specific thread running the phase completion step, or on a completion function's side effects occurring without \tcode{wait} having been called. -For example: +\begin{example} \begin{codeblock} auto b0 = std::barrier(1); b0.arrive(); @@ -546,6 +825,7 @@ assert(data == 1); // implementation-defined; previously well-defined b1.arrive(); // implementation-defined; previously well-defined \end{codeblock} +\end{example} \rSec1[diff.cpp17]{\Cpp{} and ISO \CppXVII{}} @@ -554,7 +834,8 @@ \pnum \indextext{summary!compatibility with ISO \CppXVII{}}% Subclause \ref{diff.cpp17} lists the differences between \Cpp{} and -ISO \CppXVII{} (ISO/IEC 14882:2017, \doccite{Programming Languages --- \Cpp{}}), +ISO \CppXVII{}, +in addition to those listed above, by the chapters of this document. \rSec2[diff.cpp17.lex]{\ref{lex}: lexical conventions} @@ -569,7 +850,7 @@ \tcode{module} or \tcode{import} may be interpreted differently in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} class module {}; module m1; // was variable declaration; now \grammarterm{module-declaration} @@ -579,6 +860,7 @@ import j1; // was variable declaration; now \grammarterm{module-import-declaration} ::import j2; // variable declaration \end{codeblock} +\end{example} \diffref{lex.header} \change @@ -589,12 +871,13 @@ When the identifier \tcode{import} is followed by a \tcode{<} character, a \grammarterm{header-name} token may be formed. -For example: +\begin{example} \begin{codeblock} template class import {}; import f(); // ill-formed; previously well-formed ::import g(); // OK \end{codeblock} +\end{example} \diffref{lex.key} \change @@ -617,7 +900,7 @@ prevent unintended dynamic initialization\iref{dcl.constinit}. \item The \keyword{co_await}, \keyword{co_yield}, and \keyword{co_return} keywords are added -to enable the definition of coroutines \iref{dcl.fct.def.coroutine}. +to enable the definition of coroutines\iref{dcl.fct.def.coroutine}. \item The \tcode{requires} keyword is added to introduce constraints through a \grammarterm{requires-clause}\iref{temp.pre} @@ -642,7 +925,7 @@ Valid \CppXVII{} code that contains a \tcode{<=} token immediately followed by a \tcode{>} token may be ill-formed or have different semantics in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} namespace N { struct X {}; @@ -651,6 +934,7 @@ Y y; // ill-formed; previously well-formed } \end{codeblock} +\end{example} \diffref{lex.literal} \indextext{UTF-8}% @@ -665,7 +949,7 @@ UTF-8 string literals having type ``array of \tcode{const char}'' and UTF-8 character literals having type ``\tcode{char}'' is not valid in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} const auto *u8s = u8"text"; // \tcode{u8s} previously deduced as \tcode{const char*}; now deduced as \tcode{const char8_t*} const char *ps = u8s; // ill-formed; previously well-formed @@ -684,6 +968,7 @@ }; ct::type x; // ill-formed; previously well-formed. \end{codeblock} +\end{example} \rSec2[diff.cpp17.basic]{\ref{basic}: basics} @@ -696,7 +981,7 @@ \effect Valid ISO \CppXVII{} code may be ill-formed or have undefined behavior in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} int f() { int a = 123; @@ -705,6 +990,7 @@ return a; // undefined behavior; previously returned 123 } \end{codeblock} +\end{example} \diffref{intro.races} \change @@ -733,7 +1019,7 @@ if those entities are only referenced in contexts that do not result in an odr-use. -\rSec2[diff.cpp17.dcl.dcl]{\ref{dcl.dcl}: declarations} +\rSec2[diff.cpp17.dcl.dcl]{\ref{dcl}: declarations} \diffref{dcl.typedef} \change @@ -743,12 +1029,13 @@ Necessary for implementability. \effect Valid \CppXVII{} code may be ill-formed in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} typedef struct { void f() {} // ill-formed; previously well-formed } S; \end{codeblock} +\end{example} \diffref{dcl.fct.default} \change @@ -759,7 +1046,7 @@ \effect Valid \CppXVII{} code may be ill-formed in this revision of \Cpp{}, with no diagnostic required. -For example: +\begin{example} \begin{codeblock} // Translation unit 1 int f(int a = 42); @@ -770,6 +1057,7 @@ int g(); int main() { return g(); } // used to return 42 \end{codeblock} +\end{example} \diffref{dcl.init.aggr} \change @@ -782,7 +1070,7 @@ a type with a user-declared constructor may be ill-formed or have different semantics in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} struct A { // not an aggregate; previously an aggregate A() = delete; @@ -815,6 +1103,7 @@ Y y{X{}}; // copy constructor call; previously aggregate-initialization \end{codeblock} +\end{example} \diffref{dcl.init.list} \change @@ -825,10 +1114,11 @@ \effect Valid \CppXVII{} code may fail to compile in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} bool y[] = { "bc" }; // ill-formed; previously well-formed \end{codeblock} +\end{example} \rSec2[diff.cpp17.class]{\ref{class}: classes} @@ -845,7 +1135,7 @@ \effect Valid \CppXVII{} code may fail to compile in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} struct S { explicit (S)(const S&); // ill-formed; previously well-formed @@ -853,6 +1143,7 @@ explicit(true) (S)(int); // OK }; \end{codeblock} +\end{example} \diffref{class.ctor,class.dtor} \change @@ -863,7 +1154,7 @@ \effect Valid \CppXVII{} code may fail to compile in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} template struct A { @@ -872,6 +1163,7 @@ ~A(); // error: \grammarterm{simple-template-id} not allowed for destructor }; \end{codeblock} +\end{example} \diffref{class.copy.elision} \change @@ -885,7 +1177,7 @@ \effect Valid \CppXVII{} code may fail to compile or have different semantics in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} struct base { base(); @@ -917,6 +1209,7 @@ char c = *s.m; // undefined behavior; previously ok } \end{codeblock} +\end{example} \rSec2[diff.cpp17.over]{\ref{over}: overloading} @@ -933,7 +1226,7 @@ and an object of the other type invoke a different operator. Also, for certain types, equality or inequality expressions between two objects of that type become ambiguous. -For example: +\begin{example} \begin{codeblock} struct A { operator int() const; @@ -949,6 +1242,7 @@ (10 != x); // calls \#1, previously selected \#3 } \end{codeblock} +\end{example} \diffref{over.match.oper} \change @@ -958,7 +1252,7 @@ \effect Valid \CppXVII{} code that uses equality operators with conversion functions may be ill-formed or have different semantics in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} struct A { operator int() const { return 10; } @@ -974,6 +1268,7 @@ B b1; bool eq = (b1 == b1); // ambiguous; previously well-formed \end{codeblock} +\end{example} \rSec2[diff.cpp17.temp]{\ref{temp}: templates} @@ -995,7 +1290,7 @@ Previously valid code that uses a function name as the left operand of a \tcode{<} operator would become ill-formed. -For example: +\begin{example} \begin{codeblock} struct A {}; bool operator<(void (*fp)(), A); @@ -1006,6 +1301,7 @@ (f) < a; // still well-formed } \end{codeblock} +\end{example} \rSec2[diff.cpp17.except]{\ref{except}: exception handling} @@ -1135,13 +1431,14 @@ Increase safety via preventing buffer overflow at compile time. \effect Valid \CppXVII{} code may fail to compile in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} auto p = new char[100]; char q[100]; std::cin >> std::setw(20) >> p; // ill-formed; previously well-formed std::cin >> std::setw(20) >> q; // OK \end{codeblock} +\end{example} \diffref{ostream.inserters.character} \indextext{UTF-8}% @@ -1153,13 +1450,14 @@ Valid \CppXVII{} code that passes UTF-8 literals to \tcode{basic_ostream::operator<<} or \tcode{basic_ostream::operator<<} is now ill-formed. -For example: +\begin{example} \begin{codeblock} std::cout << u8"text"; // previously called \tcode{operator<<(const char*)} and printed a string; // now ill-formed std::cout << u8'X'; // previously called \tcode{operator<<(char)} and printed a character; // now ill-formed \end{codeblock} +\end{example} \diffref{ostream.inserters.character} \change @@ -1173,13 +1471,14 @@ to \tcode{basic_ostream::operator<<} or that passes \keyword{char16_t} or \keyword{char32_t} characters or strings to \tcode{basic_ostream::operator<<} is now ill-formed. -For example: +\begin{example} \begin{codeblock} std::cout << u"text"; // previously formatted the string as a pointer value; // now ill-formed std::cout << u'X'; // previously formatted the character as an integer value; // now ill-formed \end{codeblock} +\end{example} \diffref{fs.class.path} \change @@ -1190,12 +1489,13 @@ Valid \CppXVII{} code that depends on the \tcode{u8string()} and \tcode{generic_u8string()} member functions of \tcode{std::filesystem::path} returning \tcode{std::string} is not valid in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} std::filesystem::path p; std::string s1 = p.u8string(); // ill-formed; previously well-formed std::string s2 = p.generic_u8string(); // ill-formed; previously well-formed \end{codeblock} +\end{example} \rSec2[diff.cpp17.depr]{\ref{depr}: compatibility features} @@ -1294,7 +1594,7 @@ \pnum \indextext{summary!compatibility with ISO \CppXIV{}}% Subclause \ref{diff.cpp14} lists the differences between \Cpp{} and -ISO \CppXIV{} (ISO/IEC 14882:2014, \doccite{Programming Languages --- \Cpp{}}), +ISO \CppXIV{}, in addition to those listed above, by the chapters of this document. @@ -1310,8 +1610,9 @@ Valid \CppXIV{} code that uses trigraphs may not be valid or may have different semantics in this revision of \Cpp{}. Implementations may choose to translate trigraphs as specified in \CppXIV{} if they appear outside of a raw -string literal, as part of the \impldef{mapping input source file characters -to translation character set} mapping from input source file characters to +string literal, as part of the +\impldef{mapping input file characters to translation character set} +mapping from input source file characters to the translation character set. \diffref{lex.ppnumber} @@ -1325,11 +1626,12 @@ this revision of \Cpp{}. Specifically, character sequences like \tcode{0p+0} and \tcode{0e1_p+0} are three separate tokens each in \CppXIV{}, but one single token in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} #define F(a) b ## a int b0p = F(0p+0); // ill-formed; equivalent to ``\tcode{int b0p = b0p + 0;}\!'' in \CppXIV{} \end{codeblock} +\end{example} \rSec2[diff.cpp14.expr]{\ref{expr}: expressions} @@ -1357,7 +1659,7 @@ \tcode{::operator new(std::size_t, std::align_val_t)} is used instead. -\rSec2[diff.cpp14.dcl.dcl]{\ref{dcl.dcl}: declarations} +\rSec2[diff.cpp14.dcl.dcl]{\ref{dcl}: declarations} \diffref{dcl.stc} \indextext{\idxcode{register} storage class}% @@ -1378,11 +1680,12 @@ \effect Valid \CppXIV{} code may fail to compile or may change meaning in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} auto x1{1}; // was \tcode{std::initializer_list}, now \tcode{int} auto x2{1, 2}; // was \tcode{std::initializer_list}, now ill-formed \end{codeblock} +\end{example} \diffref{dcl.fct} \change @@ -1392,13 +1695,14 @@ \effect Valid \CppXIV{} code may fail to compile or change meaning in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} void g1() noexcept; void g2(); template int f(T *, T *); int x = f(g1, g2); // ill-formed; previously well-formed \end{codeblock} +\end{example} \diffref{dcl.init.aggr} \change @@ -1411,7 +1715,7 @@ revision of \Cpp{}; initialization from an empty initializer list will perform aggregate initialization instead of invoking a default constructor for the affected types. -For example: +\begin{example} \begin{codeblock} struct derived; struct base { @@ -1424,6 +1728,7 @@ derived d1{}; // error; the code was well-formed in \CppXIV{} derived d2; // still OK \end{codeblock} +\end{example} \rSec2[diff.cpp14.class]{\ref{class}: classes} @@ -1438,7 +1743,7 @@ that names a constructor now makes the corresponding base class constructors visible to initializations of the derived class rather than declaring additional derived class constructors. -For example: +\begin{example} \begin{codeblock} struct A { template A(T, typename T::type = 0); @@ -1452,21 +1757,22 @@ // which called \tcode{A(int)} due to substitution failure // in \tcode{A(long)}. \end{codeblock} +\end{example} \rSec2[diff.cpp14.temp]{\ref{temp}: templates} \diffref{temp.deduct.type} \change -Allowance to deduce from the type of a non-type template argument. +Allowance to deduce from the type of a constant template argument. \rationale In combination with the ability to declare -non-type template arguments with placeholder types, +constant template arguments with placeholder types, allows partial specializations to decompose -from the type deduced for the non-type template argument. +from the type deduced for the constant template argument. \effect Valid \CppXIV{} code may fail to compile or produce different results in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} template struct A; template int foo(A *) = delete; @@ -1475,6 +1781,7 @@ foo(p); // ill-formed; previously well-formed } \end{codeblock} +\end{example} \rSec2[diff.cpp14.except]{\ref{except}: exception handling} @@ -1555,12 +1862,13 @@ \effect Valid \CppXIV{} code may fail to compile or may change meaning in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} #include std::unique_ptr arr(new int[1]); std::shared_ptr ptr(std::move(arr)); // error: \tcode{int(*)[]} is not compatible with \tcode{int*} \end{codeblock} +\end{example} \rSec2[diff.cpp14.string]{\ref{strings}: strings library} @@ -1577,13 +1885,14 @@ will execute differently when called with a non-const string's \tcode{.data()} member in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} int f(char *) = delete; int f(const char *); string s; int x = f(s.data()); // ill-formed; previously well-formed \end{codeblock} +\end{example} \rSec2[diff.cpp14.containers]{\ref{containers}: containers library} @@ -1596,7 +1905,7 @@ Valid \CppXIV{} code that attempts to use associative containers having a comparison object with non-const function call operator may fail to compile in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} #include @@ -1613,6 +1922,7 @@ s.find(0); } \end{codeblock} +\end{example} \rSec2[diff.cpp14.depr]{\ref{depr}: compatibility features} @@ -1654,7 +1964,7 @@ \pnum \indextext{summary!compatibility with ISO \CppXI{}}% Subclause \ref{diff.cpp11} lists the differences between \Cpp{} and -ISO \CppXI{} (ISO/IEC 14882:2011, \doccite{Programming Languages --- \Cpp{}}), +ISO \CppXI{}, in addition to those listed above, by the chapters of this document. @@ -1671,13 +1981,14 @@ this revision of \Cpp{}, but the macro invocation produces different outcomes because the single quotes delimit a \grammarterm{character-literal} in \CppXI{}, whereas they are digit separators in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} #define M(x, ...) __VA_ARGS__ int x[2] = { M(1'2,3'4, 5) }; // \tcode{int x[2] = \{ 5 \};\ \ \ \ \ } --- \CppXI{} // \tcode{int x[2] = \{ 3'4, 5 \};} --- this revision of \Cpp{} \end{codeblock} +\end{example} \rSec2[diff.cpp11.basic]{\ref{basic}: basics} @@ -1713,7 +2024,7 @@ \effect Valid \CppXI{} code that relies on the conversions may behave differently in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} struct S { int x = 1; @@ -1732,8 +2043,9 @@ \end{codeblock} In \CppXI{}, the expression yields \tcode{sizeof(const char*)}. In this revision of \Cpp{}, it yields \tcode{sizeof(const char[1])}. +\end{example} -\rSec2[diff.cpp11.dcl.dcl]{\ref{dcl.dcl}: declarations} +\rSec2[diff.cpp11.dcl.dcl]{\ref{dcl}: declarations} \diffref{dcl.constexpr} \change @@ -1744,7 +2056,7 @@ the object. \effect Valid \CppXI{} code may fail to compile in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} struct S { constexpr const int &f(); @@ -1754,6 +2066,7 @@ This code is valid in \CppXI{} but invalid in this revision of \Cpp{} because it declares the same member function twice with different return types. +\end{example} \diffref{dcl.init.aggr} \change @@ -1763,7 +2076,7 @@ by aggregate initialization. \effect Valid \CppXI{} code may fail to compile or may change meaning in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} struct S { // Aggregate in \CppXIV{} onwards. int m = 1; @@ -1776,6 +2089,7 @@ S b{a}; // uses copy constructor in \CppXI{}, // performs aggregate initialization in this revision of \Cpp{} \end{codeblock} +\end{example} \rSec2[diff.cpp11.library]{\ref{library}: library introduction} @@ -1807,7 +2121,7 @@ \pnum \indextext{summary!compatibility with ISO \CppIII{}}% Subclause \ref{diff.cpp03} lists the differences between \Cpp{} and -ISO \CppIII{} (ISO/IEC 14882:2003, \doccite{Programming Languages --- \Cpp{}}), +ISO \CppIII{}, in addition to those listed above, by the chapters of this document. @@ -1824,11 +2138,12 @@ \tcode{u8R}, \tcode{u}, \tcode{uR}, \tcode{U}, \tcode{UR}, or \tcode{LR} will not be expanded when adjacent to a \grammarterm{string-literal} but will be interpreted as part of the \grammarterm{string-literal}. -For example: +\begin{example} \begin{codeblock} #define u8 "abc" const char* s = u8"def"; // Previously \tcode{"abcdef"}, now \tcode{"def"} \end{codeblock} +\end{example} \diffref{lex.pptoken} \change @@ -1838,7 +2153,7 @@ \effect Valid \CppIII{} code may fail to compile or produce different results in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} #define _x "there" "hello"_x // \#1 @@ -1847,6 +2162,7 @@ Previously, \#1 would have consisted of two separate preprocessing tokens and the macro \tcode{_x} would have been expanded. In this revision of \Cpp{}, \#1 consists of a single preprocessing token, so the macro is not expanded. +\end{example} \diffref{lex.key} \change @@ -1888,7 +2204,7 @@ \effect Valid \CppIII{} code may fail to compile or produce different results in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} void f(void *); // \#1 void f(...); // \#2 @@ -1896,6 +2212,29 @@ f(0*N); // calls \#2; used to call \#1 } \end{codeblock} +\end{example} + +\diffref{expr.typeid} +\change +Evaluation of operands in \keyword{typeid}. +\rationale +Introduce additional expression value categories. +\effect +Valid \CppIII{} code that uses xvalues as operands for \keyword{typeid} +may change behavior in this revision of \Cpp{}. +\begin{example} +\begin{codeblock} +void f() { + struct B { + B() {} + virtual ~B() { } + }; + + struct C { B b; }; + typeid(C().b); // unevaluated in \CppIII{}, evaluated in \CppXI{} +} +\end{codeblock} +\end{example} \diffref{expr.mul} \change @@ -1915,14 +2254,40 @@ \effect Valid \CppIII{} code may fail to compile or produce different results in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} bool b1 = new int && false; // previously \tcode{false}, now ill-formed struct S { operator int(); }; bool b2 = &S::operator int && false; // previously \tcode{false}, now ill-formed \end{codeblock} +\end{example} -\rSec2[diff.cpp03.dcl.dcl]{\ref{dcl.dcl}: declarations} +\diffref{expr.cond} +\change +Fewer copies in the conditional operator. +\rationale +Introduce additional expression value categories. +\effect +Valid \CppIII{} code that uses xvalues as operands for the conditional operator +may change behavior in this revision of \Cpp{}. +\begin{example} +\begin{codeblock} +void f() { + struct B { + B() {} + B(const B&) { } + }; + struct D : B {}; + + struct BB { B b; }; + struct DD { D d; }; + + true ? BB().b : DD().d; // additional copy in \CppIII{}, no copy or move in \CppXI{} +} +\end{codeblock} +\end{example} + +\rSec2[diff.cpp03.dcl.dcl]{\ref{dcl}: declarations} \diffref{dcl.spec} \change @@ -1944,13 +2309,14 @@ Catches bugs. \effect Valid \CppIII{} code may fail to compile in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} int x[] = { 2.0 }; \end{codeblock} This code is valid in \CppIII{} but invalid in this revision of \Cpp{} because \tcode{double} to \tcode{int} is a narrowing conversion. +\end{example} \diffref{dcl.link} \change @@ -1962,7 +2328,7 @@ \effect Valid \CppIII{} code may violate the one-definition rule\iref{basic.def.odr} in this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} namespace { extern "C" { extern int x; } } // \#1, previously external linkage and C language linkage, // now internal linkage and \Cpp{} language linkage @@ -1972,6 +2338,7 @@ This code is valid in \CppIII{}, but \tcode{\#2} is not a definition for \tcode{\#1} in this revision of \Cpp{}, violating the one-definition rule. +\end{example} \rSec2[diff.cpp03.class]{\ref{class}: classes} @@ -2019,7 +2386,7 @@ Change to semantics of well-defined expression. A valid \CppIII{} expression containing a right angle bracket (``\tcode{>}'') followed immediately by another right angle bracket may now be treated as closing two templates. -For example: +\begin{example} \begin{codeblock} template struct X { }; template struct Y { }; @@ -2028,6 +2395,7 @@ This code is valid in \CppIII{} because ``\tcode{>>}'' is a right-shift operator, but invalid in this revision of \Cpp{} because ``\tcode{>>}'' closes two templates. +\end{example} \diffref{temp.dep.candidate} \change @@ -2066,7 +2434,7 @@ \libheaderrefx{condition_variable}{condition.variable.syn}, \libheaderrefx{forward_list}{forward.list.syn}, \libheaderref{future}, -\libheaderrefx{initiali\-zer_list}{initializer.list.syn}, +\libheaderrefxx{initializer_list}{initiali\-zer_list}{initializer.list.syn}, \libheaderref{mutex}, \libheaderrefx{random}{rand.synopsis}, \libheaderref{ratio}, @@ -2075,7 +2443,7 @@ \libheaderrefx{system_error}{system.error.syn}, \libheaderref{thread}, \libheaderref{tuple}, -\libheaderrefx{type\-index}{type.index.synopsis}, +\libheaderrefxx{typeindex}{type\-index}{type.index.synopsis}, \libheaderrefx{type_traits}{meta.type.synop}, \libheaderrefx{unordered_map}{unord.map.syn}, and @@ -2090,12 +2458,12 @@ invalid in this revision of \Cpp{}. \diffref{swappable.requirements} -\effect -Function \tcode{swap} moved to a different header +\change +Function \tcode{swap} moved to a different header. \rationale Remove dependency on \libheaderref{algorithm} for \tcode{swap}. \effect -Valid \CppIII{} code that has been compiled expecting swap to be in +Valid \CppIII{} code that has been compiled expecting \tcode{swap} to be in \libheaderref{algorithm} may have to instead include \libheaderref{utility}. \diffref{namespace.posix} @@ -2108,15 +2476,15 @@ \CppIII{} code that uses a top-level namespace \tcode{posix} may be invalid in this revision of \Cpp{}. -\diffref{res.on.macro.definitions} +\diffref{macro.names} \change Additional restrictions on macro names. \rationale Avoid hard to diagnose or non-portable constructs. \effect Names of attribute identifiers may not be used as macro names. Valid \CppIII{} -code that defines \tcode{override}, \tcode{final}, -\tcode{carries_dependency}, or \tcode{noreturn} as macros is invalid in this +code that defines \tcode{override}, \tcode{final}, or +\tcode{noreturn} as macros is invalid in this revision of \Cpp{}. \rSec2[diff.cpp03.language.support]{\ref{support}: @@ -2354,7 +2722,7 @@ Valid \CppIII{} code that relies on \tcode{std::ios_base} flag types being represented as \tcode{std::bitset} or as an integer type may fail to compile with this revision of \Cpp{}. -For example: +\begin{example} \begin{codeblock} #include @@ -2363,14 +2731,15 @@ std::cout.setf(flag); // error: \tcode{setf} does not take argument of type \tcode{int} } \end{codeblock} +\end{example} -\rSec1[diff.iso]{\Cpp{} and ISO C} +\rSec1[diff.iso]{\Cpp{} and C} \rSec2[diff.iso.general]{General} \pnum -\indextext{summary!compatibility with ISO C}% -Subclause \ref{diff.iso} lists the differences between \Cpp{} and ISO C, +\indextext{summary!compatibility with C}% +Subclause \ref{diff.iso} lists the differences between \Cpp{} and C, in addition to those listed above, by the chapters of this document. @@ -2378,7 +2747,7 @@ \diffref{lex.key} \change -New Keywords\\ +New Keywords.\\ New keywords are added to \Cpp{}; see \ref{lex.key}. \rationale @@ -2386,7 +2755,7 @@ semantics of \Cpp{}. \effect Change to semantics of well-defined feature. -Any ISO C programs that used any of these keywords as identifiers +Any C programs that used any of these keywords as identifiers are not valid \Cpp{} programs. \difficulty Syntactic transformation. @@ -2401,7 +2770,8 @@ Type of \grammarterm{character-literal} is changed from \tcode{int} to \tcode{char}. \rationale This is needed for improved overloaded function argument type -matching. For example: +matching. +\begin{example} \begin{codeblock} int function( int i ); int function( char c ); @@ -2410,9 +2780,10 @@ \end{codeblock} It is preferable that this call match the second version of function rather than the first. +\end{example} \effect Change to semantics of well-defined feature. -ISO C programs which depend on +C programs which depend on \begin{codeblock} sizeof('x') == sizeof(int) \end{codeblock} @@ -2481,17 +2852,19 @@ \diffref{basic.def} \change -\Cpp{} does not have ``tentative definitions'' as in C.\\ -E.g., at file scope, +\Cpp{} does not have ``tentative definitions'' as in C. +\begin{example} +At file scope, \begin{codeblock} int i; int i; \end{codeblock} is valid in C, invalid in \Cpp{}. +\end{example} This makes it impossible to define mutually referential file-local objects with static storage duration, if initializers are restricted to the syntactic forms of C\@. -For example, +\begin{example} \begin{codeblock} struct X { int i; struct X* next; }; @@ -2499,6 +2872,7 @@ static struct X b = { 0, &a }; static struct X a = { 1, &b }; \end{codeblock} +\end{example} \rationale This avoids having different initialization rules for fundamental types and user-defined types. @@ -2516,7 +2890,7 @@ \diffref{basic.scope} \change A \keyword{struct} is a scope in \Cpp{}, not in C. -For example, +\begin{example} \begin{codeblock} struct X { struct Y { int a; } b; @@ -2524,6 +2898,7 @@ struct Y c; \end{codeblock} is valid in C but not in \Cpp{}, which would require \tcode{X::Y c;}. +\end{example} \rationale Class scope is crucial to \Cpp{}, and a struct is a class. \effect @@ -2593,6 +2968,7 @@ \diffref{conv.ptr} \change Converting \tcode{\keyword{void}*} to a pointer-to-object type requires casting. +\begin{example} \begin{codeblock} char a[10]; void* b=a; @@ -2601,9 +2977,10 @@ } \end{codeblock} -ISO C accepts this usage of pointer to \keyword{void} being assigned +C accepts this usage of pointer to \keyword{void} being assigned to a pointer to object type. \Cpp{} does not. +\end{example} \rationale \Cpp{} tries harder than C to enforce compile-time type safety. \effect @@ -2611,24 +2988,24 @@ \difficulty Can be automated. Violations will be diagnosed by the \Cpp{} translator. -The -fix is to add a cast. -For example: +The fix is to add a cast. +\begin{example} \begin{codeblock} char* c = (char*) b; \end{codeblock} +\end{example} \howwide This is fairly widely used but it is good programming practice to add the cast when assigning pointer-to-void to pointer-to-object. -Some ISO C translators will give a warning +Some C translators will give a warning if the cast is not used. \diffref{expr.arith.conv} \change Operations mixing a value of an enumeration type and a value of a different enumeration type or of a floating-point type are not valid. -For example: +\begin{example} \begin{codeblock} enum E1 { e }; enum E2 { f }; @@ -2636,6 +3013,7 @@ int k = f - e; // valid in C; ill-formed in \Cpp{} int x = 1 ? e : f; // valid in C; ill-formed in \Cpp{} \end{codeblock} +\end{example} \rationale Reinforcing type safety in \Cpp{}. \effect @@ -2643,13 +3021,14 @@ \difficulty Violations will be diagnosed by the \Cpp{} translator. The original behavior can be restored with a cast or integral promotion. -For example: +\begin{example} \begin{codeblock} enum E1 { e }; enum E2 { f }; int b = (int)e <= 3.7; int k = +f - e; \end{codeblock} +\end{example} \howwide Uncommon. @@ -2659,7 +3038,7 @@ \rationale Feature with surprising semantics. \effect -A valid ISO C expression utilizing the decrement operator on +A valid C expression utilizing the decrement operator on a \keyword{bool} lvalue (for instance, via the C typedef in \libheaderref{stdbool.h}) is ill-formed in \Cpp{}. @@ -2668,11 +3047,12 @@ \change In \Cpp{}, types can only be defined in declarations, not in expressions.\\ In C, a \keyword{sizeof} expression or cast expression may define a new type. -For example, +\begin{example} \begin{codeblock} p = (void*)(struct x {int i;} *)0; \end{codeblock} defines a new type, struct \tcode{x}. +\end{example} \rationale This prohibition helps to clarify the location of definitions in the source code. @@ -2683,7 +3063,31 @@ \howwide Seldom. -\diffref{expr.cond,expr.ass,expr.comma} +\diffref{expr.rel,expr.eq} +\change +C allows directly comparing two objects of array type; \Cpp{} does not. +\rationale +The behavior is confusing because it compares not the contents of the two +arrays, but their addresses. +\effect +Deletion of semantically well-defined feature that had unspecified behavior +in common use cases. +\difficulty +Violations will be diagnosed by the \Cpp{} translator. The original behavior +can be replicated by explicitly casting either array to a pointer, such as by +using a unary \tcode{+}. +\begin{example} +\begin{codeblock} +int arr1[5]; +int arr2[5]; +int same = arr1 == arr2; // valid C, ill-formed C++ +int idem = arr1 == +arr2; // valid in both C and C++ +\end{codeblock} +\end{example} +\howwide +Rare. + +\diffref{expr.cond,expr.assign,expr.comma} \indextext{conversion!lvalue-to-rvalue}% \indextext{rvalue!lvalue conversion to}% \indextext{lvalue}% @@ -2697,7 +3101,7 @@ Change to semantics of well-defined feature. Some C expressions that implicitly rely on lvalue-to-rvalue conversions will yield different results. -For example, +\begin{example} \begin{codeblock} char arr[100]; sizeof(0, arr) @@ -2707,12 +3111,13 @@ in \Cpp{} and \tcode{sizeof(char*)} in C. +\end{example} \difficulty Programs must add explicit casts to the appropriate rvalue. \howwide Rare. -\rSec2[diff.stat]{\ref{stmt.stmt}: statements} +\rSec2[diff.stat]{\ref{stmt}: statements} \diffref{stmt.switch,stmt.goto} \change @@ -2760,7 +3165,7 @@ For several years, many existing C implementations have produced warnings in this case. -\rSec2[diff.dcl]{\ref{dcl.dcl}: declarations} +\rSec2[diff.dcl]{\ref{dcl}: declarations} \diffref{dcl.stc} \change @@ -2768,12 +3173,13 @@ Using these specifiers with type declarations is illegal in \Cpp{}. In C, these specifiers are ignored when used on type declarations. -Example: +\begin{example} \begin{codeblock} static struct S { // valid C, invalid in \Cpp{} int i; }; \end{codeblock} +\end{example} \rationale Storage class specifiers don't have any meaning when associated @@ -2808,23 +3214,25 @@ same name). In C, a \grammarterm{typedef-name} and a struct tag name declared in the same scope can have the same name (because they have different name spaces). -Example: +\begin{example} \begin{codeblock} typedef struct name1 { @\commentellip@ } name1; // valid C and \Cpp{} struct name { @\commentellip@ }; typedef int name; // valid C, invalid \Cpp{} \end{codeblock} +\end{example} \rationale For ease of use, \Cpp{} doesn't require that a type name be prefixed with the keywords \keyword{class}, \keyword{struct} or \keyword{union} when used in object declarations or type casts. -Example: +\begin{example} \begin{codeblock} class name { @\commentellip@ }; name i; // \tcode{i} has type \tcode{class name} \end{codeblock} +\end{example} \effect Deletion of semantically well-defined feature. @@ -2851,12 +3259,13 @@ \change The keyword \keyword{auto} cannot be used as a storage class specifier. -Example: +\begin{example} \begin{codeblock} void f() { auto int x; // valid C, invalid \Cpp{} } \end{codeblock} +\end{example} \rationale Allowing the use of \keyword{auto} to deduce the type @@ -2874,15 +3283,16 @@ In \Cpp{}, a function declared with an empty parameter list takes no arguments. In C, an empty parameter list means that the number and type of the function arguments are unknown. -Example: +\begin{example} \begin{codeblock} int f(); // means \tcode{int f(void)} in \Cpp{} // \tcode{int f(} unknown \tcode{)} in C \end{codeblock} +\end{example} \rationale -This is to avoid erroneous function calls (i.e., function calls -with the wrong number or type of arguments). +This is to avoid function calls +with the wrong number or type of arguments. \effect Change to semantics of well-defined feature. This feature was marked as ``obsolescent'' in C. @@ -2901,11 +3311,12 @@ In \Cpp{}, types may not be defined in return or parameter types. In C, these type definitions are allowed. -Example: +\begin{example} \begin{codeblock} void f( struct S { int a; } arg ) {} // valid C, invalid \Cpp{} enum E { A, B, C } f() {} // valid C, invalid \Cpp{} \end{codeblock} +\end{example} \rationale When comparing types in different translation units, \Cpp{} relies @@ -2948,7 +3359,7 @@ designated and non-designated initializers cannot be mixed in the same initializer list. -Example: +\begin{example} \begin{codeblock} struct A { int x, y; }; struct B { struct A a; }; @@ -2957,6 +3368,7 @@ struct B b = {.a.x = 0}; // valid C, invalid \Cpp{} struct A c = {.x = 1, 2}; // valid C, invalid \Cpp{} \end{codeblock} +\end{example} \rationale In \Cpp{}, members are destroyed in reverse construction order and the elements of an initializer list are evaluated in lexical order, @@ -2978,10 +3390,11 @@ number of elements in the array. In C, an array can be initialized with a string even if the array is not large enough to contain the string-terminating \tcode{'\textbackslash 0'}. -Example: +\begin{example} \begin{codeblock} char array[4] = "abcd"; // valid C, invalid \Cpp{} \end{codeblock} +\end{example} \rationale When these non-terminated arrays are manipulated by standard string functions, there is potential for major catastrophe. @@ -3000,11 +3413,12 @@ \Cpp{} objects of enumeration type can only be assigned values of the same enumeration type. In C, objects of enumeration type can be assigned values of any integral type. -Example: +\begin{example} \begin{codeblock} enum color { red, blue, green }; enum color c = 1; // valid C, invalid \Cpp{} \end{codeblock} +\end{example} \rationale The type-safe nature of \Cpp{}. @@ -3021,13 +3435,14 @@ \change In \Cpp{}, the type of an enumerator is its enumeration. In C, the type of an enumerator is \keyword{int}. -Example: +\begin{example} \begin{codeblock} enum e { A }; sizeof(A) == sizeof(int) // in C sizeof(A) == sizeof(e) // in \Cpp{} /* and @sizeof(int)@ is not necessarily equal to @sizeof(e)@ */ \end{codeblock} +\end{example} \rationale In \Cpp{}, an enumeration is a distinct type. @@ -3048,12 +3463,14 @@ an \grammarterm{alignment-specifier} is an \grammarterm{attribute-specifier}. In C, an \grammarterm{alignment-specifier} is a \gterm{declaration-specifier}. -Example: +\begin{example} \begin{codeblock} #include unsigned alignas(8) int x; // valid C, invalid \Cpp{} unsigned int y alignas(8); // valid \Cpp{}, invalid C \end{codeblock} +\end{example} + \rationale \Cpp{} requires unambiguous placement of the \grammarterm{alignment-specifier}. \effect @@ -3072,7 +3489,7 @@ scope. In C, an inner scope declaration of a struct tag name never hides the name of an object or function in an outer scope. -Example: +\begin{example} \begin{codeblock} int x[99]; void f() { @@ -3081,6 +3498,7 @@ /* size of the struct in @\textit{\textrm{\Cpp{}}}@ */ } \end{codeblock} +\end{example} \rationale This is one of the few incompatibilities between C and \Cpp{} that can be attributed to the new \Cpp{} name space definition where a @@ -3111,7 +3529,8 @@ The implicitly-declared copy constructor and implicitly-declared copy assignment operator cannot make a copy of a volatile lvalue. -For example, the following is valid in ISO C: +\begin{example} +The following is valid in C: \begin{codeblock} struct X { int i; }; volatile struct X x1 = {0}; @@ -3119,6 +3538,7 @@ struct X x3; x3 = x1; // also invalid \Cpp{} \end{codeblock} +\end{example} \rationale Several alternatives were debated at length. @@ -3171,13 +3591,14 @@ In \Cpp{}, the name of a nested class is local to its enclosing class. In C the name of the nested class belongs to the same scope as the name of the outermost enclosing class. -Example: +\begin{example} \begin{codeblock} struct X { struct Y { @\commentellip@ } y; }; struct Y yy; // valid C, invalid \Cpp{} \end{codeblock} +\end{example} \rationale \Cpp{} classes have member functions which require that classes establish scopes. @@ -3195,13 +3616,14 @@ To make the struct type name visible in the scope of the enclosing struct, the struct tag can be declared in the scope of the enclosing struct, before the enclosing struct is defined. -Example: +\begin{example} \begin{codeblock} struct Y; // \tcode{struct Y} and \tcode{struct X} are at the same scope struct X { struct Y { @\commentellip@ } y; }; \end{codeblock} +\end{example} All the definitions of C struct types enclosed in other struct definitions and accessed outside the scope of the enclosing @@ -3215,7 +3637,7 @@ \change In \Cpp{}, a \grammarterm{typedef-name} may not be redeclared in a class definition after being used in that definition. -Example: +\begin{example} \begin{codeblock} typedef int I; struct S { @@ -3223,6 +3645,7 @@ int I; // valid C, invalid \Cpp{} }; \end{codeblock} +\end{example} \rationale When classes become complicated, allowing such a redefinition after the type has been used can create confusion for \Cpp{} @@ -3242,7 +3665,7 @@ Whether \mname{STDC} is defined and if so, what its value is, are \impldef{definition and meaning of \mname{STDC}}. \rationale -\Cpp{} is not identical to ISO C\@. +\Cpp{} is not identical to C\@. Mandating that \mname{STDC} be defined would require that translators make an incorrect claim. \effect @@ -3285,12 +3708,12 @@ \rSec2[diff.mods.to.definitions]{Modifications to definitions} -\rSec3[diff.char16]{Types \tcode{char16_t} and \tcode{char32_t}} +\rSec3[diff.char16]{Types \tcode{char8_t}, \tcode{char16_t}, and \tcode{char32_t}} \pnum -The types \keyword{char16_t} and \keyword{char32_t} +The types \keyword{char8_t}, \keyword{char16_t}, and \keyword{char32_t} are distinct types rather than typedefs to existing integral types. -The tokens \keyword{char16_t} and \keyword{char32_t} +The tokens \keyword{char8_t}, \keyword{char16_t}, and \keyword{char32_t} are keywords in \Cpp{}\iref{lex.key}. They do not appear as macro or type names defined in \libheaderref{cuchar}. @@ -3307,14 +3730,6 @@ \libheaderref{cstdlib}, or \libheaderref{cwchar}. -\rSec3[diff.header.assert.h]{Header \tcode{}} -\indexhdr{assert.h}% - -\pnum -The token \keyword{static_assert} is a keyword in \Cpp{}. -It does not appear as a macro name defined -in \libheaderref{cassert}. - \rSec3[diff.header.iso646.h]{Header \tcode{}} \pnum @@ -3335,23 +3750,6 @@ and are not introduced as macros by \libheaderref{iso646.h}. -\rSec3[diff.header.stdalign.h]{Header \tcode{}} -\indexhdr{stdalign.h}% - -\pnum -The token \keyword{alignas} is a keyword in \Cpp{}\iref{lex.key}, -and is not introduced as a macro -by \libheaderref{stdalign.h}. - -\rSec3[diff.header.stdbool.h]{Header \tcode{}} -\indexhdr{stdbool.h}% - -\pnum -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}. - \rSec3[diff.null]{Macro \tcode{NULL}} \pnum @@ -3401,7 +3799,7 @@ \pnum Header \libheaderref{cstddef} declares the names \tcode{nullptr_t}, \tcode{byte}, and \tcode{to_integer}, -and the operators and operator templates in \iref{support.types.byteops}, +and the operators and operator templates in~\ref{support.types.byteops}, in addition to the names declared in \libheaderrefx{stddef.h}{support.c.headers} in the C standard library. diff --git a/source/concepts.tex b/source/concepts.tex index 0508cb542b..4d848e8fd6 100644 --- a/source/concepts.tex +++ b/source/concepts.tex @@ -420,7 +420,7 @@ let \tcode{u1} and \tcode{u2} be equality-preserving expressions such that \tcode{decltype((u1))} and \tcode{decltype((u2))} are each \tcode{U}. \tcode{T} and \tcode{U} model \tcode{\libconcept{common_reference_with}} -only if: +only if \begin{itemize} \item \tcode{C(t1)} equals \tcode{C(t2)} if and only if \tcode{t1} equals \tcode{t2}, and @@ -473,7 +473,7 @@ let \tcode{u1} and \tcode{u2} be equality-preserving expressions such that \tcode{decltype((u1))} and \tcode{decltype((u2))} are each \tcode{U}. \tcode{T} and \tcode{U} model \tcode{\libconcept{common_with}} -only if: +only if \begin{itemize} \item \tcode{C(t1)} equals \tcode{C(t2)} if and only if \tcode{t1} equals \tcode{t2}, and @@ -881,7 +881,7 @@ \pnum Let \tcode{e} be an expression such that \tcode{decltype((e))} is \tcode{T}. -\tcode{T} models \exposconcept{boolean-testable-impl} only if: +\tcode{T} models \exposconcept{boolean-testable-impl} only if \begin{itemize} \item @@ -1024,7 +1024,7 @@ let \tcode{u1} and \tcode{u2} be equality-preserving expressions that are lvalues of type \tcode{remove_cvref_t}. \tcode{T} and \tcode{U} model -\tcode{\exposconcept{comparison-common-type-with}} only if: +\tcode{\exposconcept{comparison-common-type-with}} only if \begin{itemize} \item \tcode{\exposid{CONVERT_TO_LVALUE}(t1)} equals @@ -1222,7 +1222,7 @@ \rSec2[concepts.callable.general]{General} \pnum -The concepts in subclause \ref{concepts.callable} describe the requirements on function +The concepts in \ref{concepts.callable} describe the requirements on function objects\iref{function.objects} and their arguments. \rSec2[concept.invocable]{Concept \cname{invocable}} diff --git a/source/config.tex b/source/config.tex index 425883737d..5e244aad2b 100644 --- a/source/config.tex +++ b/source/config.tex @@ -2,12 +2,15 @@ %%-------------------------------------------------- %% Version numbers \newcommand{\docno}{Dxxxx} -\newcommand{\prevdocno}{N4971} +\newcommand{\prevdocno}{N5014} \newcommand{\cppver}{202302L} %% Release date \newcommand{\reldate}{\today} +%% Core chapters +\newcommand{\lastcorechapter}{cpp} + %% Library chapters \newcommand{\firstlibchapter}{support} -\newcommand{\lastlibchapter}{thread} +\newcommand{\lastlibchapter}{exec} diff --git a/source/containers.tex b/source/containers.tex index b483242c4f..ce6f248ab1 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -20,7 +20,8 @@ \ref{container.requirements} & Requirements & \\ \rowsep \ref{sequences} & Sequence containers & \tcode{}, \tcode{}, \tcode{}, - \tcode{}, \tcode{} \\ \rowsep + \tcode{}, \\ & & + \tcode{}, \tcode{}, \tcode{} \\ \rowsep \ref{associative} & Associative containers & \tcode{}, \tcode{} \\ \rowsep \ref{unord} & Unordered associative containers & @@ -74,7 +75,7 @@ \rSec3[container.intro.reqmts]{Introduction} \pnum -In subclause \ref{container.requirements.general}, +In \ref{container.requirements.general}, \begin{itemize} \item \tcode{X} denotes a container class containing objects of type \tcode{T}, @@ -111,6 +112,7 @@ \indexlibrarymemberx{array}{#1}% \indexlibrarymemberx{deque}{#1}% \indexlibrarymemberx{forward_list}{#1}% +\indexlibrarymemberx{hive}{#1}% \indexlibrarymemberx{list}{#1}% \indexlibrarymemberx{vector}{#1}% \indexlibrarymemberx{map}{#1}% @@ -121,6 +123,10 @@ \indexlibrarymemberx{unordered_set}{#1}% \indexlibrarymemberx{unordered_multiset}{#1}% \indexlibrarymemberx{unordered_multimap}{#1}% +\indexlibrarymemberx{flat_map}{#1}% +\indexlibrarymemberx{flat_set}{#1}% +\indexlibrarymemberx{flat_multiset}{#1}% +\indexlibrarymemberx{flat_multimap}{#1}% } \pnum @@ -262,7 +268,7 @@ \pnum \complexity -Linear for \tcode{array} and constant for all other standard containers. +Linear for \tcode{array} and \tcode{inplace_vector} and constant for all other standard containers. \end{itemdescr} \indexcont{operator=}% @@ -421,7 +427,25 @@ Constant. \end{itemdescr} -\indexcont{operator==}% +% hive is excluded here +\indexlibrarymisc{\idxcode{operator==}}{containers}% +\indexlibrarymemberx{array}{operator==}% +\indexlibrarymemberx{deque}{operator==}% +\indexlibrarymemberx{forward_list}{operator==}% +\indexlibrarymemberx{list}{operator==}% +\indexlibrarymemberx{vector}{operator==}% +\indexlibrarymemberx{map}{operator==}% +\indexlibrarymemberx{set}{operator==}% +\indexlibrarymemberx{multiset}{operator==}% +\indexlibrarymemberx{multimap}{operator==}% +\indexlibrarymemberx{unordered_map}{operator==}% +\indexlibrarymemberx{unordered_set}{operator==}% +\indexlibrarymemberx{unordered_multiset}{operator==}% +\indexlibrarymemberx{unordered_multimap}{operator==}% +\indexlibrarymemberx{flat_map}{operator==}% +\indexlibrarymemberx{flat_set}{operator==}% +\indexlibrarymemberx{flat_multiset}{operator==}% +\indexlibrarymemberx{flat_multimap}{operator==}% \begin{itemdecl} c == b \end{itemdecl} @@ -452,7 +476,25 @@ \tcode{==} is an equivalence relation. \end{itemdescr} -\indexcont{operator"!=}% +% hive is excluded here +\indexlibrarymisc{\idxcode{operator"!=}}{containers}% +\indexlibrarymemberx{array}{operator"!=}% +\indexlibrarymemberx{deque}{operator"!=}% +\indexlibrarymemberx{forward_list}{operator"!=}% +\indexlibrarymemberx{list}{operator"!=}% +\indexlibrarymemberx{vector}{operator"!=}% +\indexlibrarymemberx{map}{operator"!=}% +\indexlibrarymemberx{set}{operator"!=}% +\indexlibrarymemberx{multiset}{operator"!=}% +\indexlibrarymemberx{multimap}{operator"!=}% +\indexlibrarymemberx{unordered_map}{operator"!=}% +\indexlibrarymemberx{unordered_set}{operator"!=}% +\indexlibrarymemberx{unordered_multiset}{operator"!=}% +\indexlibrarymemberx{unordered_multimap}{operator"!=}% +\indexlibrarymemberx{flat_map}{operator"!=}% +\indexlibrarymemberx{flat_set}{operator"!=}% +\indexlibrarymemberx{flat_multiset}{operator"!=}% +\indexlibrarymemberx{flat_multimap}{operator"!=}% \begin{itemdecl} c != b \end{itemdecl} @@ -479,7 +521,8 @@ \pnum \complexity -Linear for \tcode{array} and constant for all other standard containers. +Linear for \tcode{array} and \tcode{inplace_vector}, and +constant for all other standard containers. \end{itemdescr} \begin{itemdecl} @@ -617,7 +660,8 @@ \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 +container type other than \tcode{array} and \tcode{inplace_vector}, +shall exchange the values of \tcode{a} and \tcode{b} without invoking any move, copy, or swap operations on the individual container elements. Any \tcode{Compare}, \tcode{Pred}, or \tcode{Hash} types @@ -637,7 +681,7 @@ swap. \pnum -Unless otherwise specified (see~\ref{associative.reqmts.except}, \ref{unord.req.except}, \ref{deque.modifiers}, and +Unless otherwise specified (see~\ref{associative.reqmts.except}, \ref{unord.req.except}, \ref{deque.modifiers}, \ref{inplace.vector.modifiers}, and \ref{vector.modifiers}) all container types defined in this Clause meet the following additional requirements: @@ -720,6 +764,7 @@ \indexlibrarymisc{\idxcode{#1}}{reversible containers}% \indexlibrarymemberx{array}{#1}% \indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{hive}{#1}% \indexlibrarymemberx{list}{#1}% \indexlibrarymemberx{vector}{#1}% \indexlibrarymemberx{map}{#1}% @@ -730,6 +775,10 @@ \indexlibrarymemberx{unordered_set}{#1}% \indexlibrarymemberx{unordered_multiset}{#1}% \indexlibrarymemberx{unordered_multimap}{#1}% +\indexlibrarymemberx{flat_map}{#1}% +\indexlibrarymemberx{flat_set}{#1}% +\indexlibrarymemberx{flat_multiset}{#1}% +\indexlibrarymemberx{flat_multimap}{#1}% } \pnum @@ -908,7 +957,8 @@ \rSec3[container.alloc.reqmts]{Allocator-aware containers} \pnum -Except for \tcode{array}, all of the containers defined in \ref{containers}, +Except for \tcode{array} and \tcode{inplace_vector}, +all of the containers defined in \ref{containers}, \ref{stacktrace.basic}, \ref{basic.string}, and \ref{re.results} meet the additional requirements of an \defnadj{allocator-aware}{container}, as described below. @@ -1026,6 +1076,7 @@ \indexlibrarymisc{\idxcode{#1}}{allocator-aware containers}% \indexlibrarymemberx{deque}{#1}% \indexlibrarymemberx{forward_list}{#1}% +\indexlibrarymemberx{hive}{#1}% \indexlibrarymemberx{list}{#1}% \indexlibrarymemberx{vector}{#1}% \indexlibrarymemberx{map}{#1}% @@ -1117,7 +1168,7 @@ \pnum \ensures -\tcode{u == t}, \tcode{u.get_allocator() == m} +\tcode{u == t}, \tcode{u.get_allocator() == m}. \pnum \complexity @@ -1263,10 +1314,15 @@ \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 +linear arrangement. The library provides the following basic kinds of sequence containers: +\tcode{vector}, \tcode{inplace_vector}, +\tcode{forward_list}, \tcode{list}, and \tcode{deque}. +In addition, +\tcode{array} and \tcode{hive} are provided as sequence containers +which provide limited sequence operations, +in \tcode{array}'s case because it has a fixed number of elements, and +in \tcode{hive}'s case because insertion order is unspecified. +The library also provides container adaptors that make it easy to construct abstract data types, such as \tcode{stack}s, \tcode{queue}s, @@ -1295,7 +1351,7 @@ 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, +\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}}, @@ -1308,7 +1364,7 @@ \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}, +\range{q1}{q2} denotes a valid range of constant iterators in \tcode{a}, \item \tcode{t} denotes an lvalue or a const rvalue of \tcode{X::value_type}, and \item @@ -1370,7 +1426,7 @@ \pnum \effects -Constructs a sequence container equal to the range \tcode{[i, j)}. +Constructs a sequence container equal to the range \range{i}{j}. Each iterator in the range \range{i}{j} is dereferenced exactly once. \pnum @@ -1389,7 +1445,10 @@ from \tcode{*ranges::begin(rg)}. For \tcode{vector}, if \tcode{R} models -neither \tcode{ranges::\libconcept{sized_range}} nor \tcode{ranges::\libconcept{forward_range}}, +\tcode{ranges::\libconcept{approximately_sized_range}} +but not \tcode{ranges::\libconcept{sized_range}} or models +\tcode{ranges::\libconcept{input_range}} +but not \tcode{ranges::\libconcept{forward_range}}, \tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}. \pnum @@ -1397,6 +1456,12 @@ Constructs a sequence container equal to the range \tcode{rg}. Each iterator in the range \tcode{rg} is dereferenced exactly once. +\pnum +\recommended +If \tcode{R} models \tcode{ranges::\libconcept{approximately_sized_range}} and +\tcode{ranges::distance(\linebreak{}rg) <= ranges::reserve_hint(rg)} is \tcode{true}, +an implementation should not perform more than a single reallocation. + \pnum \ensures \tcode{distance(begin(), end()) == ranges::distance(rg)} is \tcode{true}. @@ -1449,7 +1514,7 @@ \pnum \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. -For \tcode{vector} and \tcode{deque}, +For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque}, \tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X} and \oldconcept{MoveAssignable}. @@ -1464,8 +1529,7 @@ \pnum \returns -An iterator that points to -the new element constructed from \tcode{args} into \tcode{a}. +An iterator that points to the new element. \end{itemdescr} \indexcont{insert}% @@ -1481,7 +1545,7 @@ \pnum \expects \tcode{T} is \oldconcept{CopyInsertable} into \tcode{X}. -For \tcode{vector} and \tcode{deque}, +For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque}, \tcode{T} is also \oldconcept{CopyAssignable}. \pnum @@ -1505,7 +1569,7 @@ \pnum \expects \tcode{T} is \oldconcept{MoveInsertable} into \tcode{X}. -For \tcode{vector} and \tcode{deque}, +For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque}, \tcode{T} is also \oldconcept{MoveAssignable}. \pnum @@ -1554,18 +1618,18 @@ \pnum \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*i}. -For \tcode{vector} and \tcode{deque}, +For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque}, \tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}, and \tcode{T} meets the \oldconcept{MoveConstructible}, -\oldconcept{MoveAssignable}, and +\oldconcept{MoveAs\-signable}, and \oldconcept{Swappable}\iref{swappable.requirements} requirements. Neither \tcode{i} nor \tcode{j} are iterators into \tcode{a}. \pnum \effects -Inserts copies of elements in \tcode{[i, j)} before \tcode{p}. +Inserts copies of elements in \range{i}{j} before \tcode{p}. Each iterator in the range \range{i}{j} shall be dereferenced exactly once. \pnum @@ -1589,12 +1653,12 @@ \expects \tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{*ranges::begin(rg)}. -For \tcode{vector} and \tcode{deque}, +For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque}, \tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}, and \tcode{T} meets the -\oldconcept{MoveConstructible}, -\oldconcept{Move\-Assignable}, and +\oldconcept{Move\-Constructible}, +\oldconcept{MoveAssignable}, and \oldconcept{Swappable}\iref{swappable.requirements} requirements. \tcode{rg} and \tcode{a} do not overlap. @@ -1632,7 +1696,7 @@ \pnum \expects -For \tcode{vector} and \tcode{deque}, +For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque}, \tcode{T} is \oldconcept{MoveAssignable}. \pnum @@ -1657,11 +1721,12 @@ \pnum \expects -For \tcode{vector} and \tcode{deque}, \tcode{T} is \oldconcept{MoveAssignable}. +For \tcode{vector}, \tcode{inplace_vector}, and \tcode{deque}, +\tcode{T} is \oldconcept{MoveAssignable}. \pnum \effects -Erases the elements in the range \tcode{[q1, q2)}. +Erases the elements in the range \range{q1}{q2}. \pnum \returns @@ -1718,7 +1783,7 @@ \pnum \effects -Replaces elements in \tcode{a} with a copy of \tcode{[i, j)}. +Replaces elements in \tcode{a} with a copy of \range{i}{j}. Invalidates all references, pointers and iterators referring to the elements of \tcode{a}. For \tcode{vector} and \tcode{deque}, @@ -1747,7 +1812,10 @@ from \tcode{*ranges::begin(rg)}. For \tcode{vector}, if \tcode{R} models -neither \tcode{ranges::\libconcept{sized_range}} nor \tcode{ranges::\libconcept{forward_range}}, +\tcode{ranges::\libconcept{approximately_sized_range}} +but not \tcode{ranges::\libconcept{sized_range}} or models +\tcode{ranges::\libconcept{input_range}} +but not \tcode{ranges::\libconcept{forward_range}}, \tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}. \tcode{rg} and \tcode{a} do not overlap. @@ -1759,6 +1827,12 @@ For \tcode{vector} and \tcode{deque}, also invalidates the past-the-end iterator. Each iterator in the range \tcode{rg} is dereferenced exactly once. + +\pnum +\recommended +If \tcode{R} models \tcode{ranges::\libconcept{approximately_sized_range}} and +\tcode{ranges::distance(\linebreak{}rg) <= ranges::reserve_hint(rg)} is \tcode{true}, +an implementation should not perform any reallocation. \end{itemdescr} \begin{itemdecl} @@ -1847,6 +1921,10 @@ \result \tcode{reference; const_reference} for constant \tcode{a}. +\pnum +\hardexpects +\tcode{a.empty()} is \tcode{false}. + \pnum \returns \tcode{*a.begin()} @@ -1858,6 +1936,7 @@ \tcode{array}, \tcode{deque}, \tcode{forward_list}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -1871,6 +1950,10 @@ \result \tcode{reference; const_reference} for constant \tcode{a}. +\pnum +\hardexpects +\tcode{a.empty()} is \tcode{false}. + \pnum \effects Equivalent to: @@ -1886,6 +1969,7 @@ \tcode{basic_string}, \tcode{array}, \tcode{deque}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -1948,6 +2032,7 @@ \remarks Required for \tcode{deque}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -2060,6 +2145,7 @@ Required for \tcode{basic_string}, \tcode{deque}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -2086,6 +2172,7 @@ Required for \tcode{basic_string}, \tcode{deque}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -2116,6 +2203,7 @@ \remarks Required for \tcode{deque}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -2130,7 +2218,7 @@ \keyword{void} \pnum -\expects +\hardexpects \tcode{a.empty()} is \tcode{false}. \pnum @@ -2155,7 +2243,7 @@ \keyword{void} \pnum -\expects +\hardexpects \tcode{a.empty()} is \tcode{false}. \pnum @@ -2167,6 +2255,7 @@ Required for \tcode{basic_string}, \tcode{deque}, +\tcode{inplace_vector}, \tcode{list}, and \tcode{vector}. \end{itemdescr} @@ -2178,7 +2267,11 @@ \begin{itemdescr} \pnum \result -\tcode{reference; const_reference} for constant \tcode{a} +\tcode{reference; const_reference} for constant \tcode{a}. + +\pnum +\hardexpects +\tcode{n < a.size()} is \tcode{true}. \pnum \effects @@ -2189,7 +2282,8 @@ Required for \tcode{basic_string}, \tcode{array}, -\tcode{deque}, and +\tcode{deque}, +\tcode{inplace_vector}, and \tcode{vector}. \end{itemdescr} @@ -2200,7 +2294,7 @@ \begin{itemdescr} \pnum \result -\tcode{reference; const_reference} for constant \tcode{a} +\tcode{reference; const_reference} for constant \tcode{a}. \pnum \returns @@ -2215,7 +2309,8 @@ Required for \tcode{basic_string}, \tcode{array}, -\tcode{deque}, and +\tcode{deque}, +\tcode{inplace_vector}, and \tcode{vector}. \end{itemdescr} @@ -2288,27 +2383,27 @@ 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}@&&); + constexpr @\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&&) noexcept; + constexpr @\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&&); // \ref{container.node.dtor}, destructor - ~@\placeholdernc{node-handle}@(); + constexpr ~@\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 + constexpr value_type& value() const; // not present for map containers + key_type& key() const; // not present for set containers + constexpr mapped_type& mapped() const; // not present for set containers - allocator_type get_allocator() const; - explicit operator bool() const noexcept; - [[nodiscard]] bool empty() const noexcept; + constexpr allocator_type get_allocator() const; + constexpr explicit operator bool() const noexcept; + constexpr bool empty() const noexcept; // \ref{container.node.modifiers}, modifiers - void swap(@\placeholdernc{node-handle}@&) + constexpr 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))) { + friend constexpr void swap(@\placeholdernc{node-handle}@& x, @\placeholdernc{node-handle}@& y) noexcept(noexcept(x.swap(y))) { x.swap(y); } }; @@ -2317,7 +2412,7 @@ \rSec3[container.node.cons]{Constructors, copy, and assignment} \begin{itemdecl} -@\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&& nh) noexcept; +constexpr @\placeholdernc{node-handle}@(@\placeholdernc{node-handle}@&& nh) noexcept; \end{itemdecl} \begin{itemdescr} @@ -2330,7 +2425,7 @@ \end{itemdescr} \begin{itemdecl} -@\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&& nh); +constexpr @\placeholdernc{node-handle}@& operator=(@\placeholdernc{node-handle}@&& nh); \end{itemdecl} \begin{itemdescr} @@ -2372,7 +2467,7 @@ \rSec3[container.node.dtor]{Destructor} \begin{itemdecl} -~@\placeholdernc{node-handle}@(); +constexpr ~@\placeholdernc{node-handle}@(); \end{itemdecl} \begin{itemdescr} @@ -2387,7 +2482,7 @@ \rSec3[container.node.observers]{Observers} \begin{itemdecl} -value_type& value() const; +constexpr value_type& value() const; \end{itemdecl} \begin{itemdescr} @@ -2430,7 +2525,7 @@ \end{itemdescr} \begin{itemdecl} -mapped_type& mapped() const; +constexpr mapped_type& mapped() const; \end{itemdecl} \begin{itemdescr} @@ -2449,9 +2544,8 @@ Nothing. \end{itemdescr} - \begin{itemdecl} -allocator_type get_allocator() const; +constexpr allocator_type get_allocator() const; \end{itemdecl} \begin{itemdescr} @@ -2469,7 +2563,7 @@ \end{itemdescr} \begin{itemdecl} -explicit operator bool() const noexcept; +constexpr explicit operator bool() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -2479,7 +2573,7 @@ \end{itemdescr} \begin{itemdecl} -[[nodiscard]] bool empty() const noexcept; +constexpr bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -2491,7 +2585,7 @@ \rSec3[container.node.modifiers]{Modifiers} \begin{itemdecl} -void swap(@\placeholdernc{node-handle}@& nh) +constexpr void swap(@\placeholdernc{node-handle}@& nh) noexcept(ator_traits::propagate_on_container_swap::value || ator_traits::is_always_equal::value); \end{itemdecl} @@ -2528,7 +2622,7 @@ \end{codeblock} \pnum -The name \exposid{insert-return-type} is exposition only. +The name \exposid{insert-return-type} is for exposition only. \exposid{insert-return-type} has the template parameters, data members, and special members specified above. It has no base classes or members other than those specified. @@ -2636,7 +2730,7 @@ \tcode{a2} denotes a value of a type with nodes compatible with type \tcode{X} (\tref{container.node.compat}), \item -\tcode{b} denotes a value or type \tcode{X} or \tcode{const X}, +\tcode{b} denotes a value of type \tcode{X} or \tcode{const X}, \item \tcode{u} denotes the name of a variable being declared, \item @@ -2644,7 +2738,7 @@ when \tcode{X} supports unique keys, \item \tcode{a_eq} denotes a value of type \tcode{X} -when \tcode{X} supports multiple keys, +when \tcode{X} supports equivalent keys, \item \tcode{a_tran} denotes a value of type \tcode{X} or \tcode{const X} when the \grammarterm{qualified-id} @@ -2667,7 +2761,7 @@ \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}, +\range{q1}{q2} denotes a valid range of constant iterators in \tcode{a}, \item \tcode{il} designates an object of type \tcode{initializer_list}, \item @@ -2710,12 +2804,12 @@ \pnum A type \tcode{X} meets the \defnadj{associative}{container} requirements if \tcode{X} meets all the requirements of an allocator-aware -container\iref{container.reqmts} and +container\iref{container.alloc.reqmts} and the following types, statements, and expressions are well-formed and have the specified semantics, except that for \tcode{map} and \tcode{multimap}, the requirements placed on \tcode{value_type} -in \ref{container.alloc.reqmts} apply instead to \tcode{key_type} +in \ref{container.reqmts} apply instead to \tcode{key_type} and \tcode{mapped_type}. \begin{note} For example, in some cases \tcode{key_type} and \tcode{mapped_type} @@ -2731,6 +2825,10 @@ \indexlibrary{\idxcode{map}!\idxcode{#1}}% \indexlibrary{\idxcode{multiset}!\idxcode{#1}}% \indexlibrary{\idxcode{multimap}!\idxcode{#1}}% +\indexlibrary{\idxcode{flat_set}!\idxcode{#1}}% +\indexlibrary{\idxcode{flat_map}!\idxcode{#1}}% +\indexlibrary{\idxcode{flat_multiset}!\idxcode{#1}}% +\indexlibrary{\idxcode{flat_multimap}!\idxcode{#1}}% } \indexordmem{key_type}% @@ -3141,8 +3239,7 @@ \pnum \returns -An iterator pointing to the element -with the key equivalent to the newly inserted element. +The iterator returned by \tcode{emplace}. \pnum \complexity @@ -3508,7 +3605,7 @@ \pnum \expects -\tcode{a.get_allocator() == a2.get_allocator()}. +\tcode{a.get_allocator() == a2.get_allocator()} is \tcode{true}. \pnum \effects @@ -3523,7 +3620,8 @@ \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 +If \tcode{a.begin()} and \tcode{a2.begin()} have the same type, +iterators referring to the transferred elements will continue to refer to their elements, but they now behave as iterators into \tcode{a}, not into \tcode{a2}. @@ -3845,7 +3943,7 @@ \pnum \complexity -Logarithmic, +Logarithmic. \end{itemdescr} \indexordmem{upper_bound}% @@ -4152,7 +4250,7 @@ \tcode{i} and \tcode{j} denote input iterators that refer to \tcode{value_type}, \item -\tcode{[i, j)} denotes a valid range, +\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}}, @@ -4164,7 +4262,7 @@ \item \tcode{r} denotes a valid dereferenceable iterator to \tcode{a}, \item -\tcode{[q1, q2)} denotes a valid range in \tcode{a}, +\range{q1}{q2} denotes a valid range in \tcode{a}, \item \tcode{il} denotes a value of type \tcode{initializer_list}, \item @@ -4209,11 +4307,11 @@ A type \tcode{X} meets the \defnadj{unordered associative}{container} requirements if \tcode{X} meets all the requirements of -an allocator-aware container\iref{container.reqmts} and +an allocator-aware container\iref{container.alloc.reqmts} and the following types, statements, and expressions are well-formed and have the specified semantics, except that for \tcode{unordered_map} and \tcode{unordered_multimap}, -the requirements placed on \tcode{value_type} in \ref{container.alloc.reqmts} +the requirements placed on \tcode{value_type} in \ref{container.reqmts} apply instead to \tcode{key_type} and \tcode{mapped_type}. \begin{note} For example, \tcode{key_type} and \tcode{mapped_type} @@ -4842,26 +4940,16 @@ \result \tcode{iterator} -\pnum -\expects -\tcode{value_type} is -\oldconcept{EmplaceConstructible} into \tcode{X} from \tcode{args}. - \pnum \effects -Equivalent to \tcode{a.emplace(std::forward(args)...)}. - -\pnum -\returns -An iterator pointing to the element -with the key equivalent to the newly inserted element. -The \tcode{const_iterator} \tcode{p} is a hint +Equivalent to \tcode{a.emplace(std::forward(args)...)}, +except that the \tcode{const_iterator} \tcode{p} is a hint pointing to where the search should start. Implementations are permitted to ignore the hint. \pnum -\complexity -Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. +\returns +The iterator returned by \tcode{emplace}. \end{itemdescr} \indexunordmem{insert}% @@ -4976,7 +5064,7 @@ \pnum \effects -Equivalent to \tcode{a.insert(t)} for each element in \tcode{[i,j)}. +Equivalent to \tcode{a.insert(t)} for each element in \range{i}{j}. \pnum \complexity @@ -5339,7 +5427,7 @@ \pnum \effects -Erases all elements in the range \tcode{[q1, q2)}. +Erases all elements in the range \range{q1}{q2}. \pnum \returns @@ -5575,7 +5663,7 @@ 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())}. +The return value is in the range \range{0}{b.bucket_count()}. \pnum \complexity @@ -5598,7 +5686,7 @@ \pnum \ensures -The return value is in the range \tcode{[0, a_tran.bucket_count())}. +The return value is in the range \range{0}{a_tran.bucket_count()}. \pnum \returns @@ -5623,7 +5711,7 @@ \pnum \expects -\tcode{n} shall be in the range \tcode{[0, b.bucket_count())}. +\tcode{n} shall be in the range \range{0}{b.bucket_count()}. \pnum \returns @@ -5646,7 +5734,7 @@ \pnum \expects -\tcode{n} is in the range \tcode{[0, b.bucket_count())}. +\tcode{n} is in the range \range{0}{b.bucket_count()}. \pnum \returns @@ -5670,7 +5758,7 @@ \pnum \expects -\tcode{n} is in the range \tcode{[0, b.bucket_count())}. +\tcode{n} is in the range \range{0}{b.bucket_count()}. \pnum \returns @@ -5693,7 +5781,7 @@ \pnum \expects -\tcode{n} shall be in the range \tcode{[0, b.bucket_count())}. +\tcode{n} shall be in the range \range{0}{b.bucket_count()}. \pnum \returns @@ -5717,7 +5805,7 @@ \pnum \expects -\tcode{n} is in the range \tcode{[0, b.bucket_count())}. +\tcode{n} is in the range \range{0}{b.bucket_count()}. \pnum \returns @@ -5876,7 +5964,7 @@ \indextext{unordered associative containers!requirements}% The \tcode{insert}, \tcode{insert_range}, and \tcode{emplace} members shall not affect the validity of iterators if -\tcode{(N+n) <= z * B}, where \tcode{N} is the number of elements in +\tcode{(N + n) <= z * B}, where \tcode{N} is the number of elements in the container prior to the insert operation, \tcode{n} is the number of elements inserted, \tcode{B} is the container's bucket count, and \tcode{z} is the container's maximum load factor. @@ -5952,13 +6040,15 @@ \rSec1[sequences]{Sequence containers} -\rSec2[sequences.general]{In general} +\rSec2[sequences.general]{General} \pnum The headers \libheaderref{array}, \libheaderref{deque}, \libheaderrefx{forward_list}{forward.list.syn}, +\libheaderref{hive}, +\libheaderrefx{inplace_vector}{inplace.vector.syn}, \libheaderref{list}, and \libheaderref{vector} define class templates that meet the requirements for sequence containers. @@ -6017,166 +6107,6 @@ } \end{codeblock} -\rSec2[deque.syn]{Header \tcode{} synopsis} - -\indexheader{deque}% -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} - -namespace std { - // \ref{deque}, class template \tcode{deque} - template> class deque; - - template - bool operator==(const deque& x, const deque& y); - template - @\placeholder{synth-three-way-result}@ operator<=>(const deque& x, - @\itcorr@ const deque& y); - - template - void swap(deque& x, deque& y) - noexcept(noexcept(x.swap(y))); - - // \ref{deque.erasure}, erasure - template - typename deque::size_type - erase(deque& c, const U& value); - template - typename deque::size_type - erase_if(deque& c, Predicate pred); - - namespace pmr { - template - using deque = std::deque>; - } -} -\end{codeblock} - -\rSec2[forward.list.syn]{Header \tcode{} synopsis} - -\indexheader{forward_list}% -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} - -namespace std { - // \ref{forward.list}, class template \tcode{forward_list} - template> class forward_list; - - template - bool operator==(const forward_list& x, const forward_list& y); - template - @\placeholder{synth-three-way-result}@ operator<=>(const forward_list& x, - @\itcorr@ const forward_list& y); - - template - void swap(forward_list& x, forward_list& y) - noexcept(noexcept(x.swap(y))); - - // \ref{forward.list.erasure}, erasure - template - typename forward_list::size_type - erase(forward_list& c, const U& value); - template - typename forward_list::size_type - erase_if(forward_list& c, Predicate pred); - - namespace pmr { - template - using forward_list = std::forward_list>; - } -} -\end{codeblock} - -\rSec2[list.syn]{Header \tcode{} synopsis} - -\indexheader{list}% -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} - -namespace std { - // \ref{list}, class template \tcode{list} - template> class list; - - template - bool operator==(const list& x, const list& y); - template - @\placeholder{synth-three-way-result}@ operator<=>(const list& x, - @\itcorr@ const list& y); - - template - void swap(list& x, list& y) - noexcept(noexcept(x.swap(y))); - - // \ref{list.erasure}, erasure - template - typename list::size_type - erase(list& c, const U& value); - template - typename list::size_type - erase_if(list& c, Predicate pred); - - namespace pmr { - template - using list = std::list>; - } -} -\end{codeblock} - -\rSec2[vector.syn]{Header \tcode{} synopsis} - -\indexheader{vector}% -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} - -namespace std { - // \ref{vector}, class template \tcode{vector} - template> class vector; - - template - constexpr bool operator==(const vector& x, const vector& y); - template - constexpr @\placeholder{synth-three-way-result}@ operator<=>(const vector& x, - @\itcorr@ const vector& y); - - template - constexpr void swap(vector& x, vector& y) - noexcept(noexcept(x.swap(y))); - - // \ref{vector.erasure}, erasure - template - constexpr typename vector::size_type - erase(vector& c, const U& value); - template - constexpr typename vector::size_type - erase_if(vector& c, Predicate pred); - - namespace pmr { - template - using vector = std::vector>; - } - - // \ref{vector.bool}, specialization of \tcode{vector} for \tcode{bool} - // \ref{vector.bool.pspc}, partial class template specialization \tcode{vector} - template - class vector; - - template - constexpr bool @\exposid{is-vector-bool-reference}@ = @\seebelow@; // \expos - - // hash support - template struct hash; - template struct hash>; - - // \ref{vector.bool.fmt}, formatter specialization for \tcode{vector} - template requires @\exposid{is-vector-bool-reference}@ - struct formatter; -} -\end{codeblock} - \rSec2[array]{Class template \tcode{array}} \indexlibraryglobal{array}% @@ -6267,7 +6197,7 @@ constexpr const_reverse_iterator crend() const noexcept; // capacity - [[nodiscard]] constexpr bool empty() const noexcept; + constexpr bool empty() const noexcept; constexpr size_type size() const noexcept; constexpr size_type max_size() const noexcept; @@ -6281,8 +6211,8 @@ constexpr reference back(); constexpr const_reference back() const; - constexpr T * data() noexcept; - constexpr const T * data() const noexcept; + constexpr T* data() noexcept; + constexpr const T* data() const noexcept; }; template @@ -6295,12 +6225,11 @@ \pnum \indextext{\idxcode{array}!initialization}% \indextext{requirements!container}% -The conditions for an aggregate\iref{dcl.init.aggr} shall be -met. Class \tcode{array} relies on the implicitly-declared special +An \tcode{array} relies on the implicitly-declared special member functions\iref{class.default.ctor,class.dtor,class.copy.ctor} to conform to the container requirements table in~\ref{container.requirements}. In addition to the requirements specified in the container requirements table, -the implicit move constructor and move assignment operator for \tcode{array} +the implicitly-declared move constructor and move assignment operator for \tcode{array} require that \tcode{T} be \oldconcept{MoveConstructible} or \oldconcept{MoveAssignable}, respectively. @@ -6422,7 +6351,7 @@ \pnum \mandates \tcode{is_array_v} is \tcode{false} and -\tcode{is_constructible_v} is \tcode{true}. +\tcode{is_constructible_v, T\&>} is \tcode{true}. \pnum \expects @@ -6443,7 +6372,7 @@ \pnum \mandates \tcode{is_array_v} is \tcode{false} and -\tcode{is_move_constructible_v} is \tcode{true}. +\tcode{is_constructible_v, T>} is \tcode{true}. \pnum \expects @@ -6501,6 +6430,42 @@ where indexing is zero-based. \end{itemdescr} +\rSec2[deque.syn]{Header \tcode{} synopsis} + +\indexheader{deque}% +\begin{codeblock} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} + +namespace std { + // \ref{deque}, class template \tcode{deque} + template> class deque; + + template + constexpr bool operator==(const deque& x, const deque& y); + template + constexpr @\placeholder{synth-three-way-result}@ operator<=>(const deque& x, + @\itcorr@ const deque& y); + + template + constexpr void swap(deque& x, deque& y) + noexcept(noexcept(x.swap(y))); + + // \ref{deque.erasure}, erasure + template + constexpr typename deque::size_type + erase(deque& c, const U& value); + template + constexpr typename deque::size_type + erase_if(deque& c, Predicate pred); + + namespace pmr { + template + using deque = std::deque>; + } +} +\end{codeblock} + \rSec2[deque]{Class template \tcode{deque}} \rSec3[deque.overview]{Overview} @@ -6527,6 +6492,10 @@ that are not described in one of these tables or for operations where there is additional semantic information. +\pnum +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. + \begin{codeblock} namespace std { template> @@ -6547,97 +6516,98 @@ using const_reverse_iterator = std::reverse_iterator; // \ref{deque.cons}, construct/copy/destroy - deque() : deque(Allocator()) { } - explicit deque(const Allocator&); - explicit deque(size_type n, const Allocator& = Allocator()); - deque(size_type n, const T& value, const Allocator& = Allocator()); + constexpr deque() : deque(Allocator()) { } + constexpr explicit deque(const Allocator&); + constexpr explicit deque(size_type n, const Allocator& = Allocator()); + constexpr deque(size_type n, const T& value, const Allocator& = Allocator()); template - deque(InputIterator first, InputIterator last, const Allocator& = Allocator()); + constexpr 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&); - deque(deque&&, const type_identity_t&); - deque(initializer_list, const Allocator& = Allocator()); - - ~deque(); - deque& operator=(const deque& x); - deque& operator=(deque&& x) + constexpr deque(from_range_t, R&& rg, const Allocator& = Allocator()); + constexpr deque(const deque& x); + constexpr deque(deque&&); + constexpr deque(const deque&, const type_identity_t&); + constexpr deque(deque&&, const type_identity_t&); + constexpr deque(initializer_list, const Allocator& = Allocator()); + + constexpr ~deque(); + constexpr deque& operator=(const deque& x); + constexpr deque& operator=(deque&& x) noexcept(allocator_traits::is_always_equal::value); - deque& operator=(initializer_list); + constexpr deque& operator=(initializer_list); template - void assign(InputIterator first, InputIterator last); + constexpr 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; + constexpr void assign_range(R&& rg); + constexpr void assign(size_type n, const T& t); + constexpr void assign(initializer_list); + constexpr allocator_type get_allocator() const noexcept; // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; - - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; - // \ref{deque.capacity}, capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; - void resize(size_type sz); - void resize(size_type sz, const T& c); - void shrink_to_fit(); + 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; - // element access - reference operator[](size_type n); - const_reference operator[](size_type n) const; - reference at(size_type n); - const_reference at(size_type n) const; - reference front(); - const_reference front() const; - reference back(); - const_reference back() const; + // \ref{deque.capacity}, capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; + constexpr void resize(size_type sz); + constexpr void resize(size_type sz, const T& c); + constexpr void shrink_to_fit(); + + // element access + constexpr reference operator[](size_type n); + constexpr const_reference operator[](size_type n) const; + constexpr reference at(size_type n); + constexpr const_reference at(size_type n) const; + constexpr reference front(); + constexpr const_reference front() const; + constexpr reference back(); + constexpr const_reference back() const; // \ref{deque.modifiers}, modifiers - template reference emplace_front(Args&&... args); - template reference emplace_back(Args&&... args); - template iterator emplace(const_iterator position, Args&&... args); + template constexpr reference emplace_front(Args&&... args); + template constexpr reference emplace_back(Args&&... args); + template constexpr iterator emplace(const_iterator position, Args&&... args); - void push_front(const T& x); - void push_front(T&& x); + constexpr void push_front(const T& x); + constexpr 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); + constexpr void prepend_range(R&& rg); + constexpr void push_back(const T& x); + constexpr void push_back(T&& x); template<@\exposconcept{container-compatible-range}@ R> - void append_range(R&& rg); + constexpr 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); + constexpr iterator insert(const_iterator position, const T& x); + constexpr iterator insert(const_iterator position, T&& x); + constexpr iterator insert(const_iterator position, size_type n, const T& x); template - iterator insert(const_iterator position, InputIterator first, InputIterator last); + constexpr 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); + constexpr iterator insert_range(const_iterator position, R&& rg); + constexpr iterator insert(const_iterator position, initializer_list); - void pop_front(); - void pop_back(); + constexpr void pop_front(); + constexpr void pop_back(); - iterator erase(const_iterator position); - iterator erase(const_iterator first, const_iterator last); - void swap(deque&) + constexpr iterator erase(const_iterator position); + constexpr iterator erase(const_iterator first, const_iterator last); + constexpr void swap(deque&) noexcept(allocator_traits::is_always_equal::value); - void clear() noexcept; + constexpr void clear() noexcept; }; template>> @@ -6654,7 +6624,7 @@ \indexlibraryctor{deque}% \begin{itemdecl} -explicit deque(const Allocator&); +constexpr explicit deque(const Allocator&); \end{itemdecl} \begin{itemdescr} @@ -6671,13 +6641,13 @@ \indexlibraryctor{deque}% \begin{itemdecl} -explicit deque(size_type n, const Allocator& = Allocator()); +constexpr explicit deque(size_type n, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{deque}. \pnum \effects @@ -6691,13 +6661,13 @@ \indexlibraryctor{deque}% \begin{itemdecl} -deque(size_type n, const T& value, const Allocator& = Allocator()); +constexpr deque(size_type n, const T& value, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{CopyInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{deque}. \pnum \effects @@ -6714,7 +6684,7 @@ \indexlibraryctor{deque}% \begin{itemdecl} template - deque(InputIterator first, InputIterator last, const Allocator& = Allocator()); + constexpr deque(InputIterator first, InputIterator last, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} @@ -6734,7 +6704,7 @@ \indexlibraryctor{deque}% \begin{itemdecl} template<@\exposconcept{container-compatible-range}@ R> - deque(from_range_t, R&& rg, const Allocator& = Allocator()); + constexpr deque(from_range_t, R&& rg, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} @@ -6752,13 +6722,13 @@ \indexlibrarymember{resize}{deque}% \begin{itemdecl} -void resize(size_type sz); +constexpr void resize(size_type sz); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{MoveInsertable} and \oldconcept{DefaultInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{MoveInsertable} and \oldconcept{DefaultInsertable} into \tcode{deque}. \pnum \effects @@ -6769,13 +6739,13 @@ \indexlibrarymember{resize}{deque}% \begin{itemdecl} -void resize(size_type sz, const T& c); +constexpr void resize(size_type sz, const T& c); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{CopyInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{deque}. \pnum \effects @@ -6786,13 +6756,13 @@ \indexlibrarymember{shrink_to_fit}{deque}% \begin{itemdecl} -void shrink_to_fit(); +constexpr void shrink_to_fit(); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{MoveInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{deque}. \pnum \effects @@ -6828,27 +6798,27 @@ \indexlibrarymember{push_back}{deque}% \indexlibrarymember{emplace}{deque}% \begin{itemdecl} -iterator insert(const_iterator position, const T& x); -iterator insert(const_iterator position, T&& x); -iterator insert(const_iterator position, size_type n, const T& x); +constexpr iterator insert(const_iterator position, const T& x); +constexpr iterator insert(const_iterator position, T&& x); +constexpr iterator insert(const_iterator position, size_type n, const T& x); template - iterator insert(const_iterator position, - InputIterator first, InputIterator last); + constexpr 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); -template reference emplace_back(Args&&... args); -template iterator emplace(const_iterator position, Args&&... args); -void push_front(const T& x); -void push_front(T&& x); + constexpr iterator insert_range(const_iterator position, R&& rg); +constexpr iterator insert(const_iterator position, initializer_list); + +template constexpr reference emplace_front(Args&&... args); +template constexpr reference emplace_back(Args&&... args); +template constexpr iterator emplace(const_iterator position, Args&&... args); +constexpr void push_front(const T& x); +constexpr void push_front(T&& x); template<@\exposconcept{container-compatible-range}@ R> - void prepend_range(R&& rg); -void push_back(const T& x); -void push_back(T&& x); + constexpr void prepend_range(R&& rg); +constexpr void push_back(const T& x); +constexpr void push_back(T&& x); template<@\exposconcept{container-compatible-range}@ R> - void append_range(R&& rg); + constexpr void append_range(R&& rg); \end{itemdecl} \begin{itemdescr} @@ -6873,7 +6843,7 @@ If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of -\tcode{T} +\tcode{T}, there are no effects. If an exception is thrown while inserting a single element at either end, there are no effects. @@ -6884,10 +6854,10 @@ \indexlibrarymember{erase}{deque}% \begin{itemdecl} -iterator erase(const_iterator position); -iterator erase(const_iterator first, const_iterator last); -void pop_front(); -void pop_back(); +constexpr iterator erase(const_iterator position); +constexpr iterator erase(const_iterator first, const_iterator last); +constexpr void pop_front(); +constexpr void pop_back(); \end{itemdecl} \begin{itemdescr} @@ -6919,8 +6889,8 @@ \indexlibrarymember{erase}{deque}% \begin{itemdecl} -template - typename deque::size_type +template + constexpr typename deque::size_type erase(deque& c, const U& value); \end{itemdecl} @@ -6939,7 +6909,7 @@ \indexlibrarymember{erase_if}{deque}% \begin{itemdecl} template - typename deque::size_type + constexpr typename deque::size_type erase_if(deque& c, Predicate pred); \end{itemdecl} @@ -6955,6 +6925,43 @@ \end{codeblock} \end{itemdescr} +\rSec2[forward.list.syn]{Header \tcode{} synopsis} + +\indexheader{forward_list}% +\begin{codeblock} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} + +namespace std { + // \ref{forward.list}, class template \tcode{forward_list} + template> class forward_list; + + template + constexpr bool operator==(const forward_list& x, + const forward_list& y); + template + constexpr @\placeholder{synth-three-way-result}@ operator<=>(const forward_list& x, + @\itcorr@ const forward_list& y); + + template + constexpr void swap(forward_list& x, forward_list& y) + noexcept(noexcept(x.swap(y))); + + // \ref{forward.list.erasure}, erasure + template + constexpr typename forward_list::size_type + erase(forward_list& c, const U& value); + template + constexpr typename forward_list::size_type + erase_if(forward_list& c, Predicate pred); + + namespace pmr { + template + using forward_list = std::forward_list>; + } +} +\end{codeblock} + \rSec2[forward.list]{Class template \tcode{forward_list}} \rSec3[forward.list.overview]{Overview} @@ -6973,7 +6980,7 @@ 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, +\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} @@ -6992,6 +6999,10 @@ take fully-open ranges, not semi-open ranges. \end{note} +\pnum +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. + \begin{codeblock} namespace std { template> @@ -7010,105 +7021,108 @@ using const_iterator = @\impdefx{type of \tcode{forward_list::const_iterator}}@; // see \ref{container.requirements} // \ref{forward.list.cons}, construct/copy/destroy - forward_list() : forward_list(Allocator()) { } - explicit forward_list(const Allocator&); - explicit forward_list(size_type n, const Allocator& = Allocator()); - forward_list(size_type n, const T& value, const Allocator& = Allocator()); + constexpr forward_list() : forward_list(Allocator()) { } + constexpr explicit forward_list(const Allocator&); + constexpr explicit forward_list(size_type n, const Allocator& = Allocator()); + constexpr forward_list(size_type n, const T& value, const Allocator& = Allocator()); template - forward_list(InputIterator first, InputIterator last, const Allocator& = Allocator()); + constexpr 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&); - forward_list(forward_list&& x, const type_identity_t&); - forward_list(initializer_list, const Allocator& = Allocator()); - ~forward_list(); - forward_list& operator=(const forward_list& x); - forward_list& operator=(forward_list&& x) + constexpr forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); + constexpr forward_list(const forward_list& x); + constexpr forward_list(forward_list&& x); + constexpr forward_list(const forward_list& x, const type_identity_t&); + constexpr forward_list(forward_list&& x, const type_identity_t&); + constexpr forward_list(initializer_list, const Allocator& = Allocator()); + constexpr ~forward_list(); + constexpr forward_list& operator=(const forward_list& x); + constexpr forward_list& operator=(forward_list&& x) noexcept(allocator_traits::is_always_equal::value); - forward_list& operator=(initializer_list); + constexpr forward_list& operator=(initializer_list); template - void assign(InputIterator first, InputIterator last); + constexpr 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; + constexpr void assign_range(R&& rg); + constexpr void assign(size_type n, const T& t); + constexpr void assign(initializer_list); + constexpr allocator_type get_allocator() const noexcept; // \ref{forward.list.iter}, iterators - iterator before_begin() noexcept; - const_iterator before_begin() const noexcept; - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; + constexpr iterator before_begin() noexcept; + constexpr const_iterator before_begin() const noexcept; + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; - const_iterator cbegin() const noexcept; - const_iterator cbefore_begin() const noexcept; - const_iterator cend() const noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cbefore_begin() const noexcept; + constexpr const_iterator cend() const noexcept; // capacity - [[nodiscard]] bool empty() const noexcept; - size_type max_size() const noexcept; + constexpr bool empty() const noexcept; + constexpr size_type max_size() const noexcept; // \ref{forward.list.access}, element access - reference front(); - const_reference front() const; + constexpr reference front(); + constexpr const_reference front() const; // \ref{forward.list.modifiers}, modifiers - template reference emplace_front(Args&&... args); - void push_front(const T& x); - void push_front(T&& x); + template constexpr reference emplace_front(Args&&... args); + constexpr void push_front(const T& x); + constexpr void push_front(T&& x); template<@\exposconcept{container-compatible-range}@ R> - void prepend_range(R&& rg); - void pop_front(); + constexpr void prepend_range(R&& rg); + constexpr void pop_front(); - template iterator emplace_after(const_iterator position, Args&&... args); - iterator insert_after(const_iterator position, const T& x); - iterator insert_after(const_iterator position, T&& x); + template + constexpr iterator emplace_after(const_iterator position, Args&&... args); + constexpr iterator insert_after(const_iterator position, const T& x); + constexpr iterator insert_after(const_iterator position, T&& x); - iterator insert_after(const_iterator position, size_type n, const T& x); + constexpr iterator insert_after(const_iterator position, size_type n, const T& x); template - iterator insert_after(const_iterator position, InputIterator first, InputIterator last); - iterator insert_after(const_iterator position, initializer_list il); + constexpr iterator insert_after(const_iterator position, + InputIterator first, InputIterator last); + constexpr iterator insert_after(const_iterator position, initializer_list il); template<@\exposconcept{container-compatible-range}@ R> - iterator insert_range_after(const_iterator position, R&& rg); + constexpr iterator insert_range_after(const_iterator position, R&& rg); - iterator erase_after(const_iterator position); - iterator erase_after(const_iterator position, const_iterator last); - void swap(forward_list&) + constexpr iterator erase_after(const_iterator position); + constexpr iterator erase_after(const_iterator position, const_iterator last); + constexpr void swap(forward_list&) noexcept(allocator_traits::is_always_equal::value); - void resize(size_type sz); - void resize(size_type sz, const value_type& c); - void clear() noexcept; + constexpr void resize(size_type sz); + constexpr void resize(size_type sz, const value_type& c); + constexpr void clear() noexcept; // \ref{forward.list.ops}, \tcode{forward_list} operations - void splice_after(const_iterator position, forward_list& x); - void splice_after(const_iterator position, forward_list&& x); - void splice_after(const_iterator position, forward_list& x, const_iterator i); - void splice_after(const_iterator position, forward_list&& x, const_iterator i); - void splice_after(const_iterator position, forward_list& x, + constexpr void splice_after(const_iterator position, forward_list& x); + constexpr void splice_after(const_iterator position, forward_list&& x); + constexpr void splice_after(const_iterator position, forward_list& x, const_iterator i); + constexpr void splice_after(const_iterator position, forward_list&& x, const_iterator i); + constexpr void splice_after(const_iterator position, forward_list& x, const_iterator first, const_iterator last); - void splice_after(const_iterator position, forward_list&& x, + constexpr void splice_after(const_iterator position, forward_list&& x, const_iterator first, const_iterator last); - size_type remove(const T& value); - template size_type remove_if(Predicate pred); + constexpr size_type remove(const T& value); + template constexpr size_type remove_if(Predicate pred); size_type unique(); - template size_type unique(BinaryPredicate binary_pred); + template constexpr size_type unique(BinaryPredicate binary_pred); - void merge(forward_list& x); - void merge(forward_list&& x); - template void merge(forward_list& x, Compare comp); - template void merge(forward_list&& x, Compare comp); + constexpr void merge(forward_list& x); + constexpr void merge(forward_list&& x); + template constexpr void merge(forward_list& x, Compare comp); + template constexpr void merge(forward_list&& x, Compare comp); - void sort(); - template void sort(Compare comp); + constexpr void sort(); + template constexpr void sort(Compare comp); - void reverse() noexcept; + constexpr void reverse() noexcept; }; template>> @@ -7132,7 +7146,7 @@ \indexlibraryctor{forward_list}% \begin{itemdecl} -explicit forward_list(const Allocator&); +constexpr explicit forward_list(const Allocator&); \end{itemdecl} \begin{itemdescr} @@ -7147,13 +7161,13 @@ \indexlibraryctor{forward_list}% \begin{itemdecl} -explicit forward_list(size_type n, const Allocator& = Allocator()); +constexpr explicit forward_list(size_type n, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{forward_list}. \pnum \effects @@ -7167,13 +7181,13 @@ \indexlibraryctor{forward_list}% \begin{itemdecl} -forward_list(size_type n, const T& value, const Allocator& = Allocator()); +constexpr forward_list(size_type n, const T& value, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{CopyInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{forward_list}. \pnum \effects @@ -7187,7 +7201,7 @@ \indexlibraryctor{forward_list}% \begin{itemdecl} template - forward_list(InputIterator first, InputIterator last, const Allocator& = Allocator()); + constexpr forward_list(InputIterator first, InputIterator last, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} @@ -7203,7 +7217,7 @@ \indexlibraryctor{forward_list}% \begin{itemdecl} template<@\exposconcept{container-compatible-range}@ R> - forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); + constexpr forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} @@ -7222,9 +7236,9 @@ \indexlibrarymember{before_begin}{forward_list}% \indexlibrarymember{cbefore_begin}{forward_list}% \begin{itemdecl} -iterator before_begin() noexcept; -const_iterator before_begin() const noexcept; -const_iterator cbefore_begin() const noexcept; +constexpr iterator before_begin() noexcept; +constexpr const_iterator before_begin() const noexcept; +constexpr const_iterator cbefore_begin() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -7247,8 +7261,8 @@ \indexlibrarymember{front}{forward_list}% \begin{itemdecl} -reference front(); -const_reference front() const; +constexpr reference front(); +constexpr const_reference front() const; \end{itemdecl} \begin{itemdescr} @@ -7260,10 +7274,13 @@ \rSec3[forward.list.modifiers]{Modifiers} \pnum -None of the overloads of \tcode{insert_after} shall affect the validity of iterators and -references, and \tcode{erase_after} shall invalidate only iterators and references to -the erased elements. If an exception is thrown during \tcode{insert_after} there shall -be no effect. Inserting \tcode{n} elements into a \tcode{forward_list} is linear in +The member functions in this subclause +do not affect the validity of iterators and references +when inserting elements, and when erasing elements +invalidate iterators and references to the erased elements only. +If an exception is thrown by any of these member functions +there is no effect on the container. +Inserting \tcode{n} elements into a \tcode{forward_list} is linear in \tcode{n}, and the number of calls to the copy or move constructor of \tcode{T} is exactly equal to \tcode{n}. Erasing \tcode{n} elements from a \tcode{forward_list} is linear in \tcode{n} and the number of calls to the destructor of type \tcode{T} is @@ -7271,7 +7288,7 @@ \indexlibrarymember{emplace_front}{forward_list}% \begin{itemdecl} -template reference emplace_front(Args&&... args); +template constexpr reference emplace_front(Args&&... args); \end{itemdecl} \begin{itemdescr} @@ -7283,8 +7300,8 @@ \indexlibrarymember{push_front}{forward_list}% \begin{itemdecl} -void push_front(const T& x); -void push_front(T&& x); +constexpr void push_front(const T& x); +constexpr void push_front(T&& x); \end{itemdecl} \begin{itemdescr} @@ -7296,7 +7313,7 @@ \indexlibrarymember{prepend_range}{forward_list}% \begin{itemdecl} template<@\exposconcept{container-compatible-range}@ R> - void prepend_range(R&& rg); + constexpr void prepend_range(R&& rg); \end{itemdecl} \begin{itemdescr} @@ -7310,7 +7327,7 @@ \indexlibrarymember{pop}{forward_list}% \begin{itemdecl} -void pop_front(); +constexpr void pop_front(); \end{itemdecl} \begin{itemdescr} @@ -7321,7 +7338,7 @@ \indexlibrarymember{insert_after}{forward_list}% \begin{itemdecl} -iterator insert_after(const_iterator position, const T& x); +constexpr iterator insert_after(const_iterator position, const T& x); \end{itemdecl} \begin{itemdescr} @@ -7342,7 +7359,7 @@ \indexlibrarymember{insert_after}{forward_list}% \begin{itemdecl} -iterator insert_after(const_iterator position, T&& x); +constexpr iterator insert_after(const_iterator position, T&& x); \end{itemdecl} \begin{itemdescr} @@ -7363,7 +7380,7 @@ \indexlibrarymember{insert_after}{forward_list}% \begin{itemdecl} -iterator insert_after(const_iterator position, size_type n, const T& x); +constexpr iterator insert_after(const_iterator position, size_type n, const T& x); \end{itemdecl} \begin{itemdescr} @@ -7386,7 +7403,8 @@ \indexlibrarymember{insert_after}{forward_list}% \begin{itemdecl} template - iterator insert_after(const_iterator position, InputIterator first, InputIterator last); + constexpr iterator insert_after(const_iterator position, + InputIterator first, InputIterator last); \end{itemdecl} \begin{itemdescr} @@ -7411,7 +7429,7 @@ \indexlibrarymember{insert_range_after}{forward_list}% \begin{itemdecl} template<@\exposconcept{container-compatible-range}@ R> - iterator insert_range_after(const_iterator position, R&& rg); + constexpr iterator insert_range_after(const_iterator position, R&& rg); \end{itemdecl} \begin{itemdescr} @@ -7435,7 +7453,7 @@ \indexlibrarymember{insert_after}{forward_list}% \begin{itemdecl} -iterator insert_after(const_iterator position, initializer_list il); +constexpr iterator insert_after(const_iterator position, initializer_list il); \end{itemdecl} \begin{itemdescr} @@ -7448,7 +7466,7 @@ \indexlibrarymember{emplace_after}{forward_list}% \begin{itemdecl} template - iterator emplace_after(const_iterator position, Args&&... args); + constexpr iterator emplace_after(const_iterator position, Args&&... args); \end{itemdecl} \begin{itemdescr} @@ -7471,7 +7489,7 @@ \indexlibrarymember{erase_after}{forward_list}% \begin{itemdecl} -iterator erase_after(const_iterator position); +constexpr iterator erase_after(const_iterator position); \end{itemdecl} \begin{itemdescr} @@ -7494,7 +7512,7 @@ \end{itemdescr} \begin{itemdecl} -iterator erase_after(const_iterator position, const_iterator last); +constexpr iterator erase_after(const_iterator position, const_iterator last); \end{itemdecl} \begin{itemdescr} @@ -7517,13 +7535,13 @@ \indexlibrarymember{resize}{forward_list}% \begin{itemdecl} -void resize(size_type sz); +constexpr void resize(size_type sz); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{forward_list}. \pnum \effects @@ -7533,13 +7551,13 @@ \end{itemdescr} \begin{itemdecl} -void resize(size_type sz, const value_type& c); +constexpr void resize(size_type sz, const value_type& c); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{CopyInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{forward_list}. \pnum \effects @@ -7551,7 +7569,7 @@ \indexlibrarymember{clear}{forward_list}% \begin{itemdecl} -void clear() noexcept; +constexpr void clear() noexcept; \end{itemdecl} \begin{itemdescr} @@ -7582,8 +7600,8 @@ \indexlibrarymember{splice_after}{forward_list}% \begin{itemdecl} -void splice_after(const_iterator position, forward_list& x); -void splice_after(const_iterator position, forward_list&& x); +constexpr void splice_after(const_iterator position, forward_list& x); +constexpr void splice_after(const_iterator position, forward_list&& x); \end{itemdecl} \begin{itemdescr} @@ -7613,8 +7631,8 @@ \indexlibrarymember{splice_after}{forward_list}% \begin{itemdecl} -void splice_after(const_iterator position, forward_list& x, const_iterator i); -void splice_after(const_iterator position, forward_list&& x, const_iterator i); +constexpr void splice_after(const_iterator position, forward_list& x, const_iterator i); +constexpr void splice_after(const_iterator position, forward_list&& x, const_iterator i); \end{itemdecl} \begin{itemdescr} @@ -7645,10 +7663,10 @@ \indexlibrarymember{splice_after}{forward_list}% \begin{itemdecl} -void splice_after(const_iterator position, forward_list& x, - const_iterator first, const_iterator last); -void splice_after(const_iterator position, forward_list&& x, - const_iterator first, const_iterator last); +constexpr void splice_after(const_iterator position, forward_list& x, + const_iterator first, const_iterator last); +constexpr void splice_after(const_iterator position, forward_list&& x, + const_iterator first, const_iterator last); \end{itemdecl} \begin{itemdescr} @@ -7676,8 +7694,8 @@ \indexlibrarymember{remove}{forward_list}% \indexlibrarymember{remove_if}{forward_list}% \begin{itemdecl} -size_type remove(const T& value); -template size_type remove_if(Predicate pred); +constexpr size_type remove(const T& value); +template constexpr size_type remove_if(Predicate pred); \end{itemdecl} \begin{itemdescr} @@ -7709,8 +7727,8 @@ \indexlibrarymember{unique}{forward_list}% \begin{itemdecl} -size_type unique(); -template size_type unique(BinaryPredicate binary_pred); +constexpr size_type unique(); +template constexpr size_type unique(BinaryPredicate binary_pred); \end{itemdecl} \begin{itemdescr} @@ -7748,10 +7766,10 @@ \indexlibrarymember{merge}{forward_list}% \begin{itemdecl} -void merge(forward_list& x); -void merge(forward_list&& x); -template void merge(forward_list& x, Compare comp); -template void merge(forward_list&& x, Compare comp); +constexpr void merge(forward_list& x); +constexpr void merge(forward_list&& x); +template constexpr void merge(forward_list& x, Compare comp); +template constexpr void merge(forward_list&& x, Compare comp); \end{itemdecl} \begin{itemdescr} @@ -7792,8 +7810,8 @@ \indexlibrarymember{sort}{forward_list}% \begin{itemdecl} -void sort(); -template void sort(Compare comp); +constexpr void sort(); +template constexpr void sort(Compare comp); \end{itemdecl} \begin{itemdescr} @@ -7814,7 +7832,7 @@ \indexlibrarymember{reverse}{forward_list}% \begin{itemdecl} -void reverse() noexcept; +constexpr void reverse() noexcept; \end{itemdecl} \begin{itemdescr} @@ -7832,21 +7850,24 @@ \indexlibrarymember{erase}{forward_list}% \begin{itemdecl} -template - typename forward_list::size_type +template + constexpr typename forward_list::size_type erase(forward_list& c, const U& value); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return erase_if(c, [\&](auto\& elem) \{ return elem == value; \});} +Equivalent to: +\begin{codeblock} +return erase_if(c, [&](const auto& elem) -> bool { return elem == value; }); +\end{codeblock} \end{itemdescr} \indexlibrarymember{erase_if}{forward_list}% \begin{itemdecl} template - typename forward_list::size_type + constexpr typename forward_list::size_type erase_if(forward_list& c, Predicate pred); \end{itemdecl} @@ -7856,82 +7877,175 @@ Equivalent to: \tcode{return c.remove_if(pred);} \end{itemdescr} -\rSec2[list]{Class template \tcode{list}} +\rSec2[hive.syn]{Header \tcode{} synopsis} -\rSec3[list.overview]{Overview} +\indexheader{hive}% +\begin{codeblock} + +#include // see \ref{initializer.list.syn} +#include // see \ref{compare.syn} + +namespace std { + struct @\libglobal{hive_limits}@ { + size_t @\libmember{min}{hive_limits}@; + size_t @\libmember{max}{hive_limits}@; + constexpr hive_limits(size_t minimum, size_t maximum) noexcept + : min(minimum), max(maximum) {} + }; + + // \ref {hive}, class template \tcode{hive} + template> class hive; + + template + void swap(hive& x, hive& y) + noexcept(noexcept(x.swap(y))); + + template + typename hive::size_type + erase(hive& c, const U& value); + + template + typename hive::size_type + erase_if(hive& c, Predicate pred); + + namespace pmr { + template + using hive = std::hive>; + } +} +\end{codeblock} + +\rSec2[hive]{Class template \tcode{hive}} + +\rSec3[hive.overview]{Overview} \pnum -\indexlibraryglobal{list}% -A -\tcode{list} -is a sequence container that supports -bidirectional iterators and allows constant time insert and erase -operations anywhere within the sequence, with storage management handled -automatically. Unlike vectors\iref{vector} and deques\iref{deque}, -fast random access to list elements is not supported, but many -algorithms only need sequential access anyway. +A \tcode{hive} is a type of sequence container +that provides constant-time insertion and erasure operations. +Storage is automatically managed in multiple memory blocks, +referred to as \defnx{element blocks}{element block}. +Insertion position is determined by the container, and insertion +may re-use the memory locations of erased elements. \pnum -A \tcode{list} meets all of the requirements -of a container\iref{container.reqmts}, +Element blocks which contain elements are referred to +as \defnadjx{active}{blocks}{block}, +those which do not are referred to as \defnadjx{reserved}{blocks}{block}. +Active blocks which become empty of elements are +either deallocated or become reserved blocks. +Reserved blocks become active blocks when they are used to store elements. +A user can create additional reserved blocks by calling \tcode{reserve}. + +\pnum +Erasures use unspecified techniques of constant time complexity +to identify the memory locations of erased elements, +which are subsequently skipped during iteration, +as opposed to relocating subsequent elements during erasure. + +\pnum +Active block capacities have +an \impldef{growth factor of \tcode{hive} active block capacities} growth factor +(which need not be integral), +for example a new active block's capacity could be equal to +the summed capacities of the pre-existing active blocks. + +\pnum +Limits can be placed on +both the minimum and maximum element capacities of element blocks, +both by users and implementations. +\begin{itemize} +\item +The minimum limit shall be no larger than the maximum limit. +\item +When limits are not specified by a user during construction, +the implementation's default limits are used. +\item +The default limits of an implementation are not guaranteed to be the same as +the minimum and maximum possible capacities +for an implementation's element blocks. +\begin{note} +To allow latitude for +both implementation-specific and user-directed optimization. +\end{note} +The latter are defined as hard limits. +The maximum hard limit shall be no larger than +\tcode{std::allocator_traits::max_size()}. +\item +If user-specified limits are not within hard limits, or +if the specified minimum limit is greater than the specified maximum limit, +the behavior is undefined. +\item +An element block is said to be \defnx{within the bounds}{element block!bounds} +of a pair of minimum/maximum limits +when its capacity is greater-or-equal-to the minimum limit and +less-than-or-equal-to the maximum limit. +\end{itemize} + +\pnum +A \tcode{hive} conforms to +the requirements for containers\iref{container.reqmts}, +with the exception of operators \tcode{==} and \tcode{!=}. +A \tcode{hive} also meets the requirements of a reversible container\iref{container.rev.reqmts}, of an allocator-aware container\iref{container.alloc.reqmts}, and -of a sequence container, -including most of the optional sequence container -requirements\iref{sequence.reqmts}. -The exceptions are the -\tcode{operator[]} -and -\tcode{at} -member functions, which are not provided. -\begin{footnote} -These member functions -are only provided by containers whose iterators -are random access iterators. -\end{footnote} -Descriptions are provided here only for operations on -\tcode{list} -that are not described in one of these tables -or for operations where there is additional semantic information. +some of the requirements of a sequence container\iref{sequence.reqmts}. +Descriptions are provided here only for operations on \tcode{hive} +that are not described in that table or for operations +where there is additional semantic information. + +\pnum +The iterators of \tcode{hive} meet +the \oldconcept{BidirectionalIterator} requirements +but also model \tcode{\libconcept{three_way_comparable}}. \begin{codeblock} namespace std { template> - class list { + class @\libglobal{hive}@ { public: // types - using value_type = T; - using allocator_type = Allocator; - using pointer = typename allocator_traits::pointer; - using const_pointer = typename allocator_traits::const_pointer; - using reference = value_type&; - using const_reference = const value_type&; - using size_type = @\impdefx{type of \tcode{list::size_type}}@; // see \ref{container.requirements} - using difference_type = @\impdefx{type of \tcode{list::difference_type}}@; // see \ref{container.requirements} - using iterator = @\impdefx{type of \tcode{list::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{list::const_iterator}}@; // see \ref{container.requirements} - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - // \ref{list.cons}, construct/copy/destroy - list() : list(Allocator()) { } - explicit list(const Allocator&); - explicit list(size_type n, const Allocator& = Allocator()); - list(size_type n, const T& value, const Allocator& = Allocator()); + using value_type = T; + using allocator_type = Allocator; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = @\impdef@; // see \ref{container.requirements} + using difference_type = @\impdef@; // see \ref{container.requirements} + using iterator = @\impdef@; // see \ref{container.requirements} + using const_iterator = @\impdef@; // see \ref{container.requirements} + using reverse_iterator = std::reverse_iterator; // see \ref{container.requirements} + using const_reverse_iterator = std::reverse_iterator; // see \ref{container.requirements} + + // \ref{hive.cons}, construct/copy/destroy + constexpr hive() noexcept(noexcept(Allocator())) : hive(Allocator()) {} + constexpr explicit hive(const Allocator&) noexcept; + constexpr explicit hive(hive_limits block_limits) : hive(block_limits, Allocator()) {} + constexpr hive(hive_limits block_limits, const Allocator&); + explicit hive(size_type n, const Allocator& = Allocator()); + hive(size_type n, hive_limits block_limits, const Allocator& = Allocator()); + hive(size_type n, const T& value, const Allocator& = Allocator()); + hive(size_type n, const T& value, hive_limits block_limits, const Allocator& = Allocator()); template - list(InputIterator first, InputIterator last, const Allocator& = Allocator()); + hive(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template + hive(InputIterator first, InputIterator last, hive_limits block_limits, + 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&); - list(list&&, const type_identity_t&); - list(initializer_list, const Allocator& = Allocator()); - ~list(); - list& operator=(const list& x); - list& operator=(list&& x) - noexcept(allocator_traits::is_always_equal::value); - list& operator=(initializer_list); + hive(from_range_t, R&& rg, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + hive(from_range_t, R&& rg, hive_limits block_limits, const Allocator& = Allocator()); + hive(const hive& x); + hive(hive&&) noexcept; + hive(const hive& x, const type_identity_t& alloc); + hive(hive&&, const type_identity_t& alloc); + hive(initializer_list il, const Allocator& = Allocator()); + hive(initializer_list il, hive_limits block_limits, const Allocator& = Allocator()); + ~hive(); + + hive& operator=(const hive& x); + hive& operator=(hive&& x) noexcept(@\seebelow@); + hive& operator=(initializer_list); template void assign(InputIterator first, InputIterator last); template<@\exposconcept{container-compatible-range}@ R> @@ -7941,1332 +8055,1053 @@ allocator_type get_allocator() const noexcept; // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; - - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; - - // \ref{list.capacity}, capacity - [[nodiscard]] bool empty() const noexcept; + iterator begin() noexcept; + const_iterator begin() const noexcept; + iterator end() noexcept; + const_iterator end() const noexcept; + reverse_iterator rbegin() noexcept; + const_reverse_iterator rbegin() const noexcept; + reverse_iterator rend() noexcept; + const_reverse_iterator rend() const noexcept; + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + const_reverse_iterator crbegin() const noexcept; + const_reverse_iterator crend() const noexcept; + + // \ref{hive.capacity}, capacity + bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; - void resize(size_type sz); - void resize(size_type sz, const T& c); - - // element access - reference front(); - const_reference front() const; - reference back(); - const_reference back() const; - - // \ref{list.modifiers}, modifiers - template reference emplace_front(Args&&... args); - 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); + size_type capacity() const noexcept; + void reserve(size_type n); + void shrink_to_fit(); + void trim_capacity() noexcept; + void trim_capacity(size_type n) noexcept; + constexpr hive_limits block_capacity_limits() const noexcept; + static constexpr hive_limits block_capacity_default_limits() noexcept; + static constexpr hive_limits block_capacity_hard_limits() noexcept; + void reshape(hive_limits block_limits); + + // \ref{hive.modifiers}, modifiers + template iterator emplace(Args&&... args); + template iterator emplace_hint(const_iterator hint, Args&&... args); + iterator insert(const T& x); + iterator insert(T&& x); + iterator insert(const_iterator hint, const T& x); + iterator insert(const_iterator hint, T&& x); + void insert(initializer_list il); template<@\exposconcept{container-compatible-range}@ R> - void append_range(R&& rg); - void pop_back(); - - template iterator emplace(const_iterator position, Args&&... args); - iterator insert(const_iterator position, const T& x); - iterator insert(const_iterator position, T&& x); - iterator insert(const_iterator position, size_type n, const T& x); + void insert_range(R&& rg); 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); + void insert(InputIterator first, InputIterator last); + void insert(size_type n, const T& x); iterator erase(const_iterator position); - iterator erase(const_iterator position, const_iterator last); - void swap(list&) noexcept(allocator_traits::is_always_equal::value); - void clear() noexcept; + iterator erase(const_iterator first, const_iterator last); + void swap(hive&) noexcept(@\seebelow@); + void clear() noexcept; - // \ref{list.ops}, list operations - void splice(const_iterator position, list& x); - void splice(const_iterator position, list&& x); - void splice(const_iterator position, list& x, const_iterator i); - void splice(const_iterator position, list&& x, const_iterator i); - void splice(const_iterator position, list& x, const_iterator first, const_iterator last); - void splice(const_iterator position, list&& x, const_iterator first, const_iterator last); + // \ref{hive.operations}, hive operations + void splice(hive& x); + void splice(hive&& x); + template> + size_type unique(BinaryPredicate binary_pred = BinaryPredicate()); - size_type remove(const T& value); - template size_type remove_if(Predicate pred); + template> + void sort(Compare comp = Compare()); - size_type unique(); - template - size_type unique(BinaryPredicate binary_pred); + iterator get_iterator(const_pointer p) noexcept; + const_iterator get_iterator(const_pointer p) const noexcept; - void merge(list& x); - void merge(list&& x); - template void merge(list& x, Compare comp); - template void merge(list&& x, Compare comp); + private: + hive_limits @\exposid{current-limits}@ = @\impdef@; // \expos + }; - void sort(); - template void sort(Compare comp); + template>> + hive(InputIterator, InputIterator, Allocator = Allocator()) + -> hive<@\exposid{iter-value-type}@, Allocator>; - void reverse() noexcept; - }; + template>> + hive(InputIterator, InputIterator, hive_limits, Allocator = Allocator()) + -> hive<@\exposid{iter-value-type}@, Allocator>; - template>> - list(InputIterator, InputIterator, Allocator = Allocator()) - -> list<@\placeholder{iter-value-type}@, Allocator>; + template>> + hive(from_range_t, R&&, Allocator = Allocator()) + -> hive, Allocator>; template>> - list(from_range_t, R&&, Allocator = Allocator()) - -> list, Allocator>; + hive(from_range_t, R&&, hive_limits, Allocator = Allocator()) + -> hive, Allocator>; } \end{codeblock} +\rSec3[hive.cons]{Constructors, copy, and assignment} + +\indexlibraryctor{hive}% +\begin{itemdecl} +constexpr explicit hive(const Allocator&) noexcept; +\end{itemdecl} + +\begin{itemdescr} \pnum -An incomplete type \tcode{T} may be used when instantiating \tcode{list} -if the allocator meets the -allocator completeness requirements\iref{allocator.requirements.completeness}. -\tcode{T} shall be complete before any member of the resulting specialization -of \tcode{list} is referenced. +\effects +Constructs an empty \tcode{hive}, using the specified allocator. -\rSec3[list.cons]{Constructors, copy, and assignment} +\pnum +\complexity +Constant. +\end{itemdescr} -\indexlibraryctor{list}% +\indexlibraryctor{hive}% \begin{itemdecl} -explicit list(const Allocator&); +constexpr hive(hive_limits block_limits, const Allocator&); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs an empty list, using the specified allocator. +Constructs an empty \tcode{hive}, using the specified allocator. +Initializes \exposid{current-limits} with \tcode{block_limits}. \pnum \complexity Constant. \end{itemdescr} -\indexlibraryctor{list}% +\indexlibraryctor{hive}% \begin{itemdecl} -explicit list(size_type n, const Allocator& = Allocator()); +explicit hive(size_type n, const Allocator& = Allocator()); +hive(size_type n, hive_limits block_limits, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{hive}. \pnum \effects -Constructs a \tcode{list} with -\tcode{n} default-inserted elements using the specified allocator. +Constructs a \tcode{hive} with \tcode{n} default-inserted elements, +using the specified allocator. +If the second overload is called, +also initializes \exposid{current-limits} with \tcode{block_limits}. \pnum \complexity -Linear in -\tcode{n}. +Linear in \tcode{n}. \end{itemdescr} -\indexlibraryctor{list}% +\indexlibraryctor{hive}% \begin{itemdecl} -list(size_type n, const T& value, const Allocator& = Allocator()); +hive(size_type n, const T& value, const Allocator& = Allocator()); +hive(size_type n, const T& value, hive_limits block_limits, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{CopyInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{hive}. \pnum \effects -Constructs a -\tcode{list} -with -\tcode{n} -copies of -\tcode{value}, +Constructs a \tcode{hive} with \tcode{n} copies of \tcode{value}, using the specified allocator. +If the second overload is called, +also initializes \exposid{current-limits} with \tcode{block_limits}. \pnum \complexity -Linear in -\tcode{n}. +Linear in \tcode{n}. \end{itemdescr} -\indexlibraryctor{list}% +\indexlibraryctor{hive}% \begin{itemdecl} template - list(InputIterator first, InputIterator last, const Allocator& = Allocator()); + hive(InputIterator first, InputIterator last, const Allocator& = Allocator()); +template + hive(InputIterator first, InputIterator last, hive_limits block_limits, + const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs a -\tcode{list} -equal to the range -\range{first}{last}. +Constructs a \tcode{hive} equal to the range \range{first}{last}, +using the specified allocator. +If the second overload is called, +also initializes \exposid{current-limits} with \tcode{block_limits}. \pnum \complexity -Linear in -\tcode{distance(first, last)}. +Linear in \tcode{distance(first, last)}. \end{itemdescr} -\indexlibraryctor{list}% +\indexlibraryctor{hive}% \begin{itemdecl} template<@\exposconcept{container-compatible-range}@ R> - list(from_range_t, R&& rg, const Allocator& = Allocator()); + hive(from_range_t, R&& rg, const Allocator& = Allocator()); +template<@\exposconcept{container-compatible-range}@ R> + hive(from_range_t, R&& rg, hive_limits block_limits, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs a \tcode{list} object with the elements of the range \tcode{rg}. +Constructs a \tcode{hive} object with the elements of the range \tcode{rg}, +using the specified allocator. +If the second overload is called, +also initializes \exposid{current-limits} with \tcode{block_limits}. \pnum \complexity Linear in \tcode{ranges::distance(rg)}. \end{itemdescr} -\rSec3[list.capacity]{Capacity} - -\indexlibrarymember{resize}{list}% +\indexlibraryctor{hive}% \begin{itemdecl} -void resize(size_type sz); +hive(const hive& x); +hive(const hive& x, const type_identity_t& alloc); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{hive}. \pnum \effects -If \tcode{size() < sz}, -appends \tcode{sz - size()} default-inserted elements to the -sequence. -If \tcode{sz <= size()}, equivalent to: +Constructs a \tcode{hive} object with the elements of \tcode{x}. +If the second overload is called, uses \tcode{alloc}. +Initializes \exposid{current-limits} with \tcode{x.\exposid{current-limits}}. -\begin{codeblock} -list::iterator it = begin(); -advance(it, sz); -erase(it, end()); -\end{codeblock} +\pnum +\complexity +Linear in \tcode{x.size()}. \end{itemdescr} -\indexlibrarymember{resize}{list}% +\indexlibraryctor{hive}% \begin{itemdecl} -void resize(size_type sz, const T& c); +hive(hive&& x) noexcept; +hive(hive&& x, const type_identity_t& alloc); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{CopyInsertable} into \tcode{*this}. +For the second overload, +when \tcode{allocator_traits::is_always_equal::value} is \tcode{false}, +\tcode{T} meets the \oldconcept{MoveInsertable} requirements. \pnum \effects -As if by: -\begin{codeblock} -if (sz > size()) - insert(end(), sz-size(), c); -else if (sz < size()) { - iterator i = begin(); - advance(i, sz); - erase(i, end()); -} -else - ; // do nothing -\end{codeblock} -\end{itemdescr} - -\rSec3[list.modifiers]{Modifiers} +When the first overload is called, or +the second overload is called and +\tcode{alloc == x.get_allocator()} is \tcode{true}, +\exposid{current-limits} is set to \tcode{x.\exposid{current-limits}} and +each element block is moved from \tcode{x} into \tcode{*this}. +Pointers and references to the elements of \tcode{x} now refer to +those same elements but as members of \tcode{*this}. +Iterators referring to the elements of \tcode{x} +will continue to refer to their elements, +but they now behave as iterators into \tcode{*this}. -\indexlibrarymember{insert}{list}% -\begin{itemdecl} -iterator insert(const_iterator position, const T& x); -iterator insert(const_iterator position, T&& x); -iterator insert(const_iterator position, size_type n, const T& x); -template - 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); -template reference emplace_back(Args&&... args); -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} +If the second overload is called and +\tcode{alloc == x.get_allocator()} is \tcode{false}, +each element in \tcode{x} is moved into \tcode{*this}. +References, pointers and iterators referring to the elements of \tcode{x}, as well as the past-the-end iterator of \tcode{x}, are invalidated. -\begin{itemdescr} \pnum -\complexity -Insertion of a single element into a list takes constant time and -exactly one call to a constructor of -\tcode{T}. Insertion of multiple elements into a list is linear in the -number of elements inserted, and the number of calls to the copy -constructor or move constructor of \tcode{T} is exactly equal -to the number of elements inserted. +\ensures +\tcode{x.empty()} is \tcode{true}. \pnum -\remarks -Does not affect the validity of iterators and references. -If an exception is thrown there are no effects. +\complexity +If the second overload is called and +\tcode{alloc == x.get_allocator()} is \tcode{false}, linear in \tcode{x.size()}. +Otherwise constant. \end{itemdescr} -\indexlibrarymember{erase}{list}% +\indexlibraryctor{hive}% \begin{itemdecl} -iterator erase(const_iterator position); -iterator erase(const_iterator first, const_iterator last); - -void pop_front(); -void pop_back(); -void clear() noexcept; +hive(initializer_list il, const Allocator& = Allocator()); +hive(initializer_list il, hive_limits block_limits, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Invalidates only the iterators and references to the erased elements. +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{hive}. \pnum -\throws -Nothing. +\effects +Constructs a \tcode{hive} object with the elements of \tcode{il}, +using the specified allocator. +If the second overload is called, +also initializes \exposid{current-limits} with \tcode{block_limits}. \pnum \complexity -Erasing a single element is a constant time operation with a single call to the destructor of -\tcode{T}. -Erasing a range in a list is linear time in the -size of the range and the number of calls to the destructor of type -\tcode{T} -is exactly equal to the size of the range. +Linear in \tcode{il.size()}. \end{itemdescr} -\rSec3[list.ops]{Operations} - -\pnum -Since lists allow fast insertion and erasing from the middle of a list, certain -operations are provided specifically for them. -\begin{footnote} -As specified -in~\ref{allocator.requirements}, the requirements in this Clause apply only to -lists whose allocators compare equal. -\end{footnote} -In this subclause, -arguments for a template parameter -named \tcode{Predicate} or \tcode{BinaryPredicate} -shall meet the corresponding requirements in \ref{algorithms.requirements}. -The semantics of \tcode{i + n} and \tcode{i - n}, -where \tcode{i} is an iterator into the list and \tcode{n} is an integer, -are the same as those of \tcode{next(i, n)} and \tcode{prev(i, n)}, -respectively. -For \tcode{merge} and \tcode{sort}, -the definitions and requirements in \ref{alg.sorting} apply. - -\pnum -\tcode{list} provides three splice operations that destructively move elements from one list to -another. The behavior of splice operations is undefined if \tcode{get_allocator() != -x.get_allocator()}. - -\indexlibrarymember{splice}{list}% +\indexlibrarymember{operator=}{hive}% \begin{itemdecl} -void splice(const_iterator position, list& x); -void splice(const_iterator position, list&& x); +hive& operator=(const hive& x); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{addressof(x) != this} is \tcode{true}. +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{hive} and +\oldconcept{CopyAssignable}. \pnum \effects -Inserts the contents of -\tcode{x} -before -\tcode{position} -and -\tcode{x} -becomes empty. -Pointers and references to the moved elements of -\tcode{x} -now refer to those same elements but as members of -\tcode{*this}. -Iterators referring to the moved elements will continue to refer to their -elements, but they now behave as iterators into -\tcode{*this}, -not into -\tcode{x}. - -\pnum -\throws -Nothing. +All elements in \tcode{*this} are either copy-assigned to, or destroyed. +All elements in \tcode{x} are copied into \tcode{*this}. +\begin{note} +\exposid{current-limits} is unchanged. +\end{note} \pnum \complexity -Constant time. +Linear in \tcode{size() + x.size()}. \end{itemdescr} -\indexlibrarymember{splice}{list}% +\indexlibrarymember{operator=}{hive}% \begin{itemdecl} -void splice(const_iterator position, list& x, const_iterator i); -void splice(const_iterator position, list&& x, const_iterator i); +hive& operator=(hive&& x) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{i} is a valid dereferenceable iterator of \tcode{x}. +When +\begin{codeblock} +(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value) +\end{codeblock} +is \tcode{false}, +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{hive} and +\oldconcept{MoveAssignable}. \pnum \effects -Inserts an element pointed to by -\tcode{i} -from list -\tcode{x} -before \tcode{position} and removes the element from -\tcode{x}. -The result is unchanged if -\tcode{position == i} -or -\tcode{position == ++i}. -Pointers and references to -\tcode{*i} -continue to refer to this same element but as a member of -\tcode{*this}. -Iterators -to -\tcode{*i} -(including -\tcode{i} -itself) continue to refer to the same element, but now behave as iterators into -\tcode{*this}, -not into -\tcode{x}. +Each element in \tcode{*this} is either move-assigned to, or destroyed. +When +\begin{codeblock} +(allocator_traits::propagate_on_container_move_assignment::value || + get_allocator() == x.get_allocator()) +\end{codeblock} +is \tcode{true}, +\exposid{current-limits} is set to \tcode{x.\exposid{current-limits}} and +each element block is moved from \tcode{x} into \tcode{*this}. +Pointers and references to the elements of \tcode{x} +now refer to those same elements but as members of \tcode{*this}. +Iterators referring to the elements of \tcode{x} +will continue to refer to their elements, +but they now behave as iterators into \tcode{*this}, not into \tcode{x}. + +When +\begin{codeblock} +(allocator_traits::propagate_on_container_move_assignment::value || + get_allocator() == x.get_allocator()) +\end{codeblock} +is \tcode{false}, +each element in \tcode{x} is moved into \tcode{*this}. +References, pointers and iterators referring to the elements of \tcode{x}, +as well as the past-the-end iterator of \tcode{x}, are invalidated. \pnum -\throws -Nothing. +\ensures +\tcode{x.empty()} is \tcode{true}. \pnum \complexity -Constant time. +Linear in \tcode{size()}. +If +\begin{codeblock} +(allocator_traits::propagate_on_container_move_assignment::value || + get_allocator() == x.get_allocator()) +\end{codeblock} +is \tcode{false}, also linear in \tcode{x.size()}. \end{itemdescr} -\indexlibrarymember{splice}{list}% +\rSec3[hive.capacity]{Capacity} + +\indexlibrarymember{capacity}{hive}% \begin{itemdecl} -void splice(const_iterator position, list& x, const_iterator first, - const_iterator last); -void splice(const_iterator position, list&& x, const_iterator first, - const_iterator last); +size_type capacity() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{[first, last)} is a valid range in \tcode{x}. -\tcode{position} is not an iterator in the range \range{first}{last}. - -\pnum -\effects -Inserts elements in the range -\range{first}{last} -before -\tcode{position} -and removes the elements from -\tcode{x}. -Pointers and references to the moved elements of -\tcode{x} -now refer to those same elements but as members of -\tcode{*this}. -Iterators referring to the moved elements will continue to refer to their -elements, but they now behave as iterators into -\tcode{*this}, -not into -\tcode{x}. - -\pnum -\throws -Nothing. +\returns +The total number of elements that \tcode{*this} can hold +without requiring allocation of more element blocks. \pnum \complexity -Constant time if -\tcode{addressof(x) == this}; -otherwise, linear time. +Constant. \end{itemdescr} -\indexlibrarymember{remove}{list}% +\indexlibrarymember{reserve}{hive}% \begin{itemdecl} -size_type remove(const T& value); -template size_type remove_if(Predicate pred); +void reserve(size_type n); \end{itemdecl} \begin{itemdescr} \pnum \effects -Erases all the elements in the list referred to by a list iterator \tcode{i} for which the -following conditions hold: \tcode{*i == value}, \tcode{pred(*i) != false}. -Invalidates only the iterators and references to the erased elements. +If \tcode{n <= capacity()} is \tcode{true}, there are no effects. +Otherwise increases \tcode{capacity()} by allocating reserved blocks. \pnum -\returns -The number of elements erased. +\ensures +\tcode{capacity() >= n} is \tcode{true}. \pnum \throws -Nothing unless an exception is thrown by -\tcode{*i == value} -or -\tcode{pred(*i) != false}. +\tcode{length_error} if \tcode{n > max_size()}, +as well as any exceptions thrown by the allocator. \pnum \complexity -Exactly -\tcode{size()} -applications of the corresponding predicate. +It does not change the size of the sequence and +takes at most linear time in the number of reserved blocks allocated. \pnum \remarks -Stable\iref{algorithm.stable}. +All references, pointers, and iterators referring to elements in \tcode{*this}, +as well as the past-the-end iterator, remain valid. \end{itemdescr} -\indexlibrarymember{unique}{list}% +\indexlibrarymember{shrink_to_fit}{hive}% \begin{itemdecl} -size_type unique(); -template size_type unique(BinaryPredicate binary_pred); +void shrink_to_fit(); \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{binary_pred} be \tcode{equal_to<>\{\}} for the first overload. - \pnum \expects -\tcode{binary_pred} is an equivalence relation. +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{hive}. \pnum \effects -Erases all but the first element from every -consecutive group of equivalent elements. -That is, for a nonempty list, erases all elements referred to -by the iterator \tcode{i} in the range \range{begin() + 1}{end()} -for which \tcode{binary_pred(*i, *(i - 1))} is \tcode{true}. -Invalidates only the iterators and references to the erased elements. +\tcode{shrink_to_fit} is a non-binding request +to reduce \tcode{capacity()} to be closer to \tcode{size()}. +\begin{note} +The request is non-binding +to allow latitude for implementation-specific optimizations. +\end{note} +It does not increase \tcode{capacity()}, but may reduce \tcode{capacity()}. +It may reallocate elements. +If \tcode{capacity()} is already equal to \tcode{size()}, there are no effects. +If an exception is thrown during allocation of a new element block, +\tcode{capacity()} may be reduced and reallocation may occur. +Otherwise if an exception is thrown, the effects are unspecified. \pnum -\returns -The number of elements erased. +\complexity +If reallocation happens, linear in the size of the sequence. \pnum -\throws -Nothing unless an exception is thrown by the predicate. +\remarks +If reallocation happens, +the order of the elements in \tcode{*this} may change and +all references, pointers, and iterators +referring to the elements in \tcode{*this}, +as well as the past-the-end iterator, are invalidated. +\end{itemdescr} -\pnum +\indexlibrarymember{trim_capacity}{hive}% +\begin{itemdecl} +void trim_capacity() noexcept; +void trim_capacity(size_type n) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +For the first overload, all reserved blocks are deallocated, and +\tcode{capacity()} is reduced accordingly. +For the second overload, \tcode{capacity()} is reduced to no less than \tcode{n}. + +\pnum \complexity -If \tcode{empty()} is \tcode{false}, -exactly \tcode{size() - 1} applications of the corresponding predicate, -otherwise no applications of the predicate. +Linear in the number of reserved blocks deallocated. + +\pnum +\remarks +All references, pointers, and iterators referring to elements in \tcode{*this}, +as well as the past-the-end iterator, remain valid. \end{itemdescr} -\indexlibrarymember{merge}{list}% +\indexlibrarymember{block_capacity_limits}{hive}% \begin{itemdecl} -void merge(list& x); -void merge(list&& x); -template void merge(list& x, Compare comp); -template void merge(list&& x, Compare comp); +constexpr hive_limits block_capacity_limits() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{comp} be \tcode{less<>{}} for the first two overloads. +\returns +\exposid{current-limits}. \pnum -\expects -\tcode{*this} and \tcode{x} are both sorted -with respect to the comparator \tcode{comp}, and -\tcode{get_allocator() == x.get_allocator()} is \tcode{true}. +\complexity +Constant. +\end{itemdescr} -\pnum -\effects -If \tcode{addressof(x) == this}, there are no effects. -Otherwise, merges -the two sorted ranges \range{begin()}{end()} and \range{x.begin()}{x.end()}. -The result is a range -that is sorted with respect to the comparator \tcode{comp}. -Pointers and references to the moved elements of \tcode{x} now refer to those same elements -but as members of \tcode{*this}. Iterators referring to the moved elements will continue to -refer to their elements, but they now behave as iterators into \tcode{*this}, not into -\tcode{x}. +\indexlibrarymember{block_capacity_default_limits}{hive}% +\begin{itemdecl} +static constexpr hive_limits block_capacity_default_limits() noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -At most \tcode{size() + x.size() - 1} comparisons -if \tcode{addressof(x) != this}; -otherwise, no comparisons are performed. +\returns +A \tcode{hive_limits} struct +with the \tcode{min} and \tcode{max} members set to +the implementation's default limits. \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. +\complexity +Constant. \end{itemdescr} -\indexlibrarymember{reverse}{list}% +\indexlibrarymember{block_capacity_hard_limits}{hive}% \begin{itemdecl} -void reverse() noexcept; +static constexpr hive_limits block_capacity_hard_limits() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Reverses the order of the elements in the list. -Does not affect the validity of iterators and references. +\returns +A \tcode{hive_limits} struct +with the \tcode{min} and \tcode{max} members set to +the implementation's hard limits. \pnum \complexity -Linear time. +Constant. \end{itemdescr} -\indexlibrarymember{sort}{list}% +\indexlibrarymember{reshape}{hive}% \begin{itemdecl} -void sort(); -template void sort(Compare comp); +void reshape(hive_limits block_limits); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{hive}. + \pnum \effects -Sorts the list according to the \tcode{operator<} or a \tcode{Compare} function object. -If an exception is thrown, -the order of the elements in \tcode{*this} is unspecified. -Does not affect the validity of iterators and references. +For any active blocks not within the bounds of \tcode{block_limits}, +the elements within those active blocks are reallocated +to new or existing element blocks which are within the bounds. +Any element blocks not within the bounds of \tcode{block_limits} +are deallocated. +If an exception is thrown during allocation of a new element block, +\tcode{capacity()} may be reduced, +reallocation may occur, and +\exposid{current-limits} may be assigned +a value other than \tcode{block_limits}. +Otherwise \tcode{block_limits} is assigned to \exposid{current-limits}. +If any other exception is thrown the effects are unspecified. + +\pnum +\ensures +\tcode{size()} is unchanged. \pnum \complexity -Approximately -$N \log N$ -comparisons, where -\tcode{N == size()}. +Linear in the number of element blocks in \tcode{*this}. +If reallocation happens, also linear in the number of elements reallocated. \pnum \remarks -Stable\iref{algorithm.stable}. +This operation may change \tcode{capacity()}. +If reallocation happens, the order of the elements in \tcode{*this} may change. +Reallocation invalidates all references, pointers, and iterators +referring to the elements in \tcode{*this}, +as well as the past-the-end iterator. +\begin{note} +If no reallocation happens, they remain valid. +\end{note} \end{itemdescr} -\rSec3[list.erasure]{Erasure} +\rSec3[hive.modifiers]{Modifiers} -\indexlibrarymember{erase}{list}% +\indexlibrarymember{emplace}{hive}% \begin{itemdecl} -template - typename list::size_type - erase(list& c, const U& value); +template iterator emplace(Args&&... args); +template iterator emplace_hint(const_iterator hint, Args&&... args); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{hive} from \tcode{args}. + \pnum \effects -Equivalent to: \tcode{return erase_if(c, [\&](auto\& elem) \{ return elem == value; \});} +Inserts an object of type \tcode{T} +constructed with \tcode{std::forward(args)...}. +The \tcode{hint} parameter is ignored. +If an exception is thrown, there are no effects. +\begin{note} +\tcode{args} can directly or indirectly refer to a value in \tcode{*this}. +\end{note} + +\pnum +\returns +An iterator that points to the new element. + +\pnum +\complexity +Constant. Exactly one object of type \tcode{T} is constructed. + +\pnum +\remarks +Invalidates the past-the-end iterator. \end{itemdescr} -\indexlibrarymember{erase_if}{list}% +\indexlibrarymember{insert}{hive}% \begin{itemdecl} -template - typename list::size_type - erase_if(list& c, Predicate pred); +iterator insert(const T& x); +iterator insert(const_iterator hint, const T& x); +iterator insert(T&& x); +iterator insert(const_iterator hint, T&& x); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return c.remove_if(pred);} +Equivalent to: \tcode{return emplace(std::forward(x));} +\begin{note} +The \tcode{hint} parameter is ignored. +\end{note} \end{itemdescr} -\rSec2[vector]{Class template \tcode{vector}} +\indexlibrarymember{insert}{hive}% +\begin{itemdecl} +void insert(initializer_list rg); +template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); +\end{itemdecl} -\rSec3[vector.overview]{Overview} +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceInsertable} into \tcode{hive} +from \tcode{*ranges::begin(rg)}. +\tcode{rg} and \tcode{*this} do not overlap. \pnum -\indexlibraryglobal{vector}% -A -\tcode{vector} -is a sequence container that supports -(amortized) constant time insert and erase operations at the end; -insert and erase in the middle take linear time. -Storage management is handled automatically, though hints can be given -to improve efficiency. +\effects +Inserts copies of elements in \tcode{rg}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. \pnum -A \tcode{vector} meets all of the requirements -of a container\iref{container.reqmts}, -of a reversible container\iref{container.rev.reqmts}, -of an allocator-aware container\iref{container.alloc.reqmts}, -of a sequence container, including most of the optional sequence container -requirements\iref{sequence.reqmts}, -and, for an element type other than \tcode{bool}, -of a contiguous container\iref{container.reqmts}. -The exceptions are the -\tcode{push_front}, \tcode{prepend_range}, \tcode{pop_front}, and \tcode{emplace_front} member functions, which are not -provided. Descriptions are provided here only for operations on \tcode{vector} -that are not described in one of these tables or for operations where there is -additional semantic information. +\complexity +Linear in the number of elements inserted. +Exactly one object of type \tcode{T} is constructed for each element inserted. \pnum -The types \tcode{iterator} and \tcode{const_iterator} meet -the constexpr iterator requirements\iref{iterator.requirements.general}. +\remarks +If an element is inserted, invalidates the past-the-end iterator. +\end{itemdescr} -\begin{codeblock} -namespace std { - template> - class vector { - public: - // types - using value_type = T; - using allocator_type = Allocator; - using pointer = typename allocator_traits::pointer; - using const_pointer = typename allocator_traits::const_pointer; - using reference = value_type&; - using const_reference = const value_type&; - using size_type = @\impdefx{type of \tcode{vector::size_type}}@; // see \ref{container.requirements} - using difference_type = @\impdefx{type of \tcode{vector::difference_type}}@; // see \ref{container.requirements} - using iterator = @\impdefx{type of \tcode{vector::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{vector::const_iterator}}@; // see \ref{container.requirements} - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; +\indexlibrarymember{insert}{hive}% +\begin{itemdecl} +void insert(size_type n, const T& x); +\end{itemdecl} - // \ref{vector.cons}, construct/copy/destroy - constexpr vector() noexcept(noexcept(Allocator())) : vector(Allocator()) { } - constexpr explicit vector(const Allocator&) noexcept; - constexpr explicit vector(size_type n, const Allocator& = Allocator()); - constexpr vector(size_type n, const T& value, const Allocator& = Allocator()); - template - 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&); - constexpr vector(vector&&, const type_identity_t&); - constexpr vector(initializer_list, const Allocator& = Allocator()); - constexpr ~vector(); - constexpr vector& operator=(const vector& x); - constexpr vector& operator=(vector&& x) - noexcept(allocator_traits::propagate_on_container_move_assignment::value || - allocator_traits::is_always_equal::value); - 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; +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{hive}. - // iterators - constexpr iterator begin() noexcept; - constexpr const_iterator begin() const noexcept; - constexpr iterator end() noexcept; - constexpr const_iterator end() const noexcept; - constexpr reverse_iterator rbegin() noexcept; - constexpr const_reverse_iterator rbegin() const noexcept; - constexpr reverse_iterator rend() noexcept; - constexpr const_reverse_iterator rend() const noexcept; +\pnum +\effects +Inserts \tcode{n} copies of \tcode{x}. - 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 +\complexity +Linear in \tcode{n}. +Exactly one object of type \tcode{T} is constructed for each element inserted. - // \ref{vector.capacity}, capacity - [[nodiscard]] constexpr bool empty() const noexcept; - constexpr size_type size() const noexcept; - constexpr size_type max_size() const noexcept; - constexpr size_type capacity() const noexcept; - constexpr void resize(size_type sz); - constexpr void resize(size_type sz, const T& c); - constexpr void reserve(size_type n); - constexpr void shrink_to_fit(); +\pnum +\remarks +If an element is inserted, invalidates the past-the-end iterator. +\end{itemdescr} - // element access - constexpr reference operator[](size_type n); - constexpr const_reference operator[](size_type n) const; - constexpr const_reference at(size_type n) const; - constexpr reference at(size_type n); - constexpr reference front(); - constexpr const_reference front() const; - constexpr reference back(); - constexpr const_reference back() const; +\indexlibrarymember{insert}{hive}% +\begin{itemdecl} +template + void insert(InputIterator first, InputIterator last); +\end{itemdecl} - // \ref{vector.data}, data access - constexpr T* data() noexcept; - constexpr const T* data() const noexcept; +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{insert_range(ranges::subrange(first, last))}. +\end{itemdescr} - // \ref{vector.modifiers}, modifiers - 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); - constexpr iterator insert(const_iterator position, const T& x); - constexpr iterator insert(const_iterator position, T&& x); - constexpr iterator insert(const_iterator position, size_type n, const T& x); - template - 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); - constexpr void swap(vector&) - noexcept(allocator_traits::propagate_on_container_swap::value || - allocator_traits::is_always_equal::value); - constexpr void clear() noexcept; - }; - - 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==}% -\indexlibrarymember{vector}{operator<} - -\pnum -An incomplete type \tcode{T} may be used when instantiating \tcode{vector} -if the allocator meets the -allocator completeness requirements\iref{allocator.requirements.completeness}. -\tcode{T} shall be complete before any member of the resulting specialization -of \tcode{vector} is referenced. - -\rSec3[vector.cons]{Constructors} - -\indexlibraryctor{vector} -\begin{itemdecl} -constexpr explicit vector(const Allocator&) noexcept; -\end{itemdecl} +\indexlibrarymember{erase}{hive}% +\begin{itemdecl} +iterator erase(const_iterator position); +iterator erase(const_iterator first, const_iterator last); +\end{itemdecl} \begin{itemdescr} \pnum -\effects -Constructs an empty \tcode{vector}, using the -specified allocator. +\complexity +Linear in the number of elements erased. +Additionally, if any active blocks become empty of elements +as a result of the function call, +at worst linear in the number of element blocks. \pnum -\complexity -Constant. +\remarks +Invalidates references, pointers and iterators +referring to the erased elements. +An erase operation that erases the last element in \tcode{*this} +also invalidates the past-the-end iterator. \end{itemdescr} -\indexlibraryctor{vector} +\indexlibrarymember{swap}{hive}% \begin{itemdecl} -constexpr explicit vector(size_type n, const Allocator& = Allocator()); +void swap(hive& x) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{*this}. - \pnum \effects -Constructs a \tcode{vector} with \tcode{n} -default-inserted elements using the specified allocator. +Exchanges the contents, \tcode{capacity()}, and \exposid{current-limits} +of \tcode{*this} with that of \tcode{x}. \pnum \complexity -Linear in \tcode{n}. +Constant. \end{itemdescr} -\indexlibraryctor{vector} -\begin{itemdecl} -constexpr vector(size_type n, const T& value, - const Allocator& = Allocator()); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{T} is -\oldconcept{CopyInsertable} into \tcode{*this}. - -\pnum -\effects -Constructs a \tcode{vector} with \tcode{n} -copies of \tcode{value}, using the specified allocator. +\rSec3[hive.operations]{Operations} \pnum -\complexity -Linear in \tcode{n}. -\end{itemdescr} +In this subclause, +arguments for a template parameter +named \tcode{Predicate} or \tcode{BinaryPredicate} +shall meet the corresponding requirements in \ref{algorithms.requirements}. +The semantics of \tcode{i + n} and \tcode{i - n}, +where \tcode{i} is an iterator into the \tcode{hive} and \tcode{n} is an integer, +are the same as those of \tcode{next(i, n)} and \tcode{prev(i, n)}, respectively. +For \tcode{sort}, the definitions and requirements in \ref{alg.sorting} apply. -\indexlibraryctor{vector} +\indexlibrarymember{splice}{hive}% \begin{itemdecl} -template - constexpr vector(InputIterator first, InputIterator last, - const Allocator& = Allocator()); +void splice(hive& x); +void splice(hive&& x); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Constructs a \tcode{vector} equal to the -range \range{first}{last}, using the specified allocator. - -\pnum -\complexity -Makes only $N$ -calls to the copy constructor of -\tcode{T} -(where $N$ -is the distance between -\tcode{first} -and -\tcode{last}) -and no reallocations if iterators \tcode{first} and \tcode{last} are of forward, bidirectional, or random access categories. -It makes order -$N$ -calls to the copy constructor of -\tcode{T} -and order -$\log N$ -reallocations if they are just input iterators. -\end{itemdescr} - -\indexlibraryctor{vector}% -\begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); -\end{itemdecl} +\expects +\tcode{get_allocator() == x.get_allocator()} is \tcode{true}. -\begin{itemdescr} \pnum \effects -Constructs a \tcode{vector} object with the elements of the range \tcode{rg}, -using the specified allocator. +If \tcode{addressof(x) == this} is \tcode{true}, +the behavior is erroneous and there are no effects. +Otherwise, inserts the contents of \tcode{x} into \tcode{*this} and +\tcode{x} becomes empty. +Pointers and references to the moved elements of \tcode{x} +now refer to those same elements but as members of \tcode{*this}. +Iterators referring to the moved elements continue to refer to their elements, +but they now behave as iterators into \tcode{*this}, not into \tcode{x}. \pnum -\complexity -Initializes exactly $N$ elements -from the results of dereferencing successive iterators of \tcode{rg}, -where $N$ is \tcode{ranges::distance(rg)}. -Performs no reallocations if \tcode{R} models -\tcode{ranges::\libconcept{forward_range}} or \tcode{ranges::\libconcept{sized_range}}; -otherwise, performs order $\log N$ reallocations and -order $N$ calls to the copy or move constructor of \tcode{T}. -\end{itemdescr} - -\rSec3[vector.capacity]{Capacity} - -\indexlibrarymember{capacity}{vector}% -\begin{itemdecl} -constexpr size_type capacity() const noexcept; -\end{itemdecl} +\throws +\tcode{length_error} if any of \tcode{x}'s active blocks +are not within the bounds of \exposid{current-limits}. -\begin{itemdescr} \pnum -\returns -The total number of elements that the vector can hold -without requiring reallocation. +\complexity +Linear in the sum of +all element blocks in \tcode{x} plus all element blocks in \tcode{*this}. \pnum -\complexity -Constant time. +\remarks +Reserved blocks in \tcode{x} are not transferred into \tcode{*this}. +If \tcode{addressof(x) == this} is \tcode{false}, +invalidates the past-the-end iterator for both \tcode{x} and \tcode{*this}. \end{itemdescr} -\indexlibrarymember{reserve}{vector}% +\indexlibrarymember{unique}{hive}% \begin{itemdecl} -constexpr void reserve(size_type n); +template> + size_type unique(BinaryPredicate binary_pred = BinaryPredicate()); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{MoveInsertable} into \tcode{*this}. +\tcode{binary_pred} is an equivalence relation. \pnum \effects -A directive that informs a -\tcode{vector} -of a planned change in size, so that it can manage the storage allocation accordingly. -After -\tcode{reserve()}, -\tcode{capacity()} -is greater or equal to the argument of -\tcode{reserve} -if reallocation happens; and equal to the previous value of -\tcode{capacity()} -otherwise. -Reallocation happens at this point if and only if the current capacity is less than the -argument of -\tcode{reserve()}. If an exception is thrown -other than by the move constructor of a non-\oldconcept{CopyInsertable} type, -there are no effects. +Erases all but the first element +from every consecutive group of equivalent elements. +That is, for a nonempty \tcode{hive}, +erases all elements referred to by the iterator \tcode{i} +in the range \range{begin() + 1}{end()} +for which \tcode{binary_pred(*i, *(i - 1))} is \tcode{true}. + +\pnum +\returns +The number of elements erased. \pnum \throws -\tcode{length_error} if \tcode{n > -max_size()}. -\begin{footnote} -\tcode{reserve()} uses \tcode{Allocator::allocate()} which -can throw an appropriate exception. -\end{footnote} +Nothing unless an exception is thrown by the predicate. \pnum \complexity -It does not change the size of the sequence and takes at most linear -time in the size of the sequence. +If \tcode{empty()} is \tcode{false}, +exactly \tcode{size() - 1} applications of the corresponding predicate, +otherwise no applications of the predicate. \pnum \remarks -Reallocation invalidates all the references, pointers, and iterators -referring to the elements in the sequence, as well as the past-the-end iterator. -\begin{note} -If no reallocation happens, they remain valid. -\end{note} -No reallocation shall take place during insertions that happen -after a call to \tcode{reserve()} -until an insertion would make the size of the vector -greater than the value of \tcode{capacity()}. +Invalidates references, pointers, and iterators +referring to the erased elements. +If the last element in \tcode{*this} is erased, +also invalidates the past-the-end iterator. \end{itemdescr} -\indexlibrarymember{shrink_to_fit}{vector}% +\indexlibrarymember{sort}{hive}% \begin{itemdecl} -constexpr void shrink_to_fit(); +template> + void sort(Compare comp = Compare()); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is \oldconcept{MoveInsertable} into \tcode{*this}. +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{hive}, +\oldconcept{MoveAssignable}, and \oldconcept{Swappable}. \pnum \effects -\tcode{shrink_to_fit} is a non-binding request to reduce -\tcode{capacity()} to \tcode{size()}. -\begin{note} -The request is non-binding to allow latitude for -implementation-specific optimizations. -\end{note} -It does not increase \tcode{capacity()}, but may reduce \tcode{capacity()} -by causing reallocation. -If an exception is thrown other than by the move constructor -of a non-\oldconcept{CopyInsertable} \tcode{T} there are no effects. +Sorts \tcode{*this} according to the \tcode{comp} function object. +If an exception is thrown, +the order of the elements in \tcode{*this} is unspecified. \pnum \complexity -If reallocation happens, -linear in the size of the sequence. +\bigoh{N \log N} comparisons, where $N$ is \tcode{size()}. \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. +May allocate. +References, pointers, and iterators referring to elements in \tcode{*this}, +as well as the past-the-end iterator, may be invalidated. \begin{note} -If no reallocation happens, they remain valid. +Not required to be stable\ref{algorithm.stable}. \end{note} \end{itemdescr} -\indexlibrarymember{swap}{vector}% -\begin{itemdecl} -constexpr void swap(vector& x) - noexcept(allocator_traits::propagate_on_container_swap::value || - allocator_traits::is_always_equal::value); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Exchanges the contents and -\tcode{capacity()} -of -\tcode{*this} -with that of \tcode{x}. - -\pnum -\complexity -Constant time. -\end{itemdescr} - -\indexlibrarymember{resize}{vector}% +\indexlibrarymember{get_iterator}{hive}% \begin{itemdecl} -constexpr void resize(size_type sz); +iterator get_iterator(const_pointer p) noexcept; +const_iterator get_iterator(const_pointer p) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{T} is -\oldconcept{MoveInsertable} and \oldconcept{DefaultInsertable} into \tcode{*this}. +\tcode{p} points to an element in \tcode{*this}. \pnum -\effects -If \tcode{sz < size()}, erases the last \tcode{size() - sz} elements -from the sequence. Otherwise, -appends \tcode{sz - size()} default-inserted elements to the sequence. +\returns +An \tcode{iterator} or \tcode{const_iterator} +pointing to the same element as \tcode{p}. \pnum -\remarks -If an exception is thrown other than by the move constructor of a non-\oldconcept{CopyInsertable} -\tcode{T} there are no effects. +\complexity +Linear in the number of active blocks in \tcode{*this}. \end{itemdescr} -\indexlibrarymember{resize}{vector}% +\rSec3[hive.erasure]{Erasure} + +\indexlibrarymember{erase}{hive}% \begin{itemdecl} -constexpr void resize(size_type sz, const T& c); +template + typename hive::size_type + erase(hive& c, const U& value); \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{T} is -\oldconcept{CopyInsertable} into \tcode{*this}. - \pnum \effects -If \tcode{sz < size()}, erases the last \tcode{size() - sz} elements -from the sequence. Otherwise, -appends \tcode{sz - size()} copies of \tcode{c} to the sequence. - -\pnum -\remarks -If an exception is thrown there are no effects. +Equivalent to: +\begin{codeblock} +return erase_if(c, [&](const auto& elem) -> bool { return elem == value; }); +\end{codeblock} \end{itemdescr} -\rSec3[vector.data]{Data} - -\indexlibrarymember{data}{vector}% +\indexlibrarymember{erase_if}{hive}% \begin{itemdecl} -constexpr T* data() noexcept; -constexpr const T* data() const noexcept; +template + typename hive::size_type + erase_if(hive& c, Predicate pred); \end{itemdecl} \begin{itemdescr} \pnum -\returns -A pointer such that \range{data()}{data() + size()} is a valid range. For a -non-empty vector, \tcode{data() == addressof(front())} is \keyword{true}. - -\pnum -\complexity -Constant time. +\effects +Equivalent to: +\begin{codeblock} +auto original_size = c.size(); +for (auto i = c.begin(), last = c.end(); i != last; ) { + if (pred(*i)) { + i = c.erase(i); + } else { + ++i; + } +} +return original_size - c.size(); +\end{codeblock} \end{itemdescr} -\rSec3[vector.modifiers]{Modifiers} - -\indexlibrarymember{insert}{vector}% -\begin{itemdecl} -constexpr iterator insert(const_iterator position, const T& x); -constexpr iterator insert(const_iterator position, T&& x); -constexpr iterator insert(const_iterator position, size_type n, const T& x); -template - 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} +\rSec2[list.syn]{Header \tcode{} synopsis} -\begin{itemdescr} -\pnum -\complexity -If reallocation happens, -linear in the number of elements of the resulting vector; -otherwise, -linear in the number of elements inserted plus the distance -to the end of the vector. +\indexheader{list}% +\begin{codeblock} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} -\pnum -\remarks -Causes reallocation if the new size is greater than the old capacity. -Reallocation invalidates all the references, pointers, and iterators -referring to the elements in the sequence, as well as the past-the-end iterator. -If no reallocation happens, then -references, pointers, and iterators -before the insertion point remain valid -but those at or after the insertion point, -including the past-the-end iterator, -are invalidated. -If an exception is thrown other than by -the copy constructor, move constructor, -assignment operator, or move assignment operator of -\tcode{T} or by any \tcode{InputIterator} operation -there are no effects. -If an exception is thrown while inserting a single element at the end and -\tcode{T} is \oldconcept{CopyInsertable} or \tcode{is_nothrow_move_constructible_v} -is \tcode{true}, there are no effects. -Otherwise, if an exception is thrown by the move constructor of a non-\oldconcept{CopyInsertable} -\tcode{T}, the effects are unspecified. -\end{itemdescr} +namespace std { + // \ref{list}, class template \tcode{list} + template> class list; -\indexlibrarymember{erase}{vector}% -\begin{itemdecl} -constexpr iterator erase(const_iterator position); -constexpr iterator erase(const_iterator first, const_iterator last); -constexpr void pop_back(); -\end{itemdecl} + template + constexpr bool operator==(const list& x, const list& y); + template + constexpr @\placeholder{synth-three-way-result}@ operator<=>(const list& x, + @\itcorr@ const list& y); -\begin{itemdescr} -\pnum -\effects -Invalidates iterators and references at or after the point of the erase. + template + constexpr void swap(list& x, list& y) + noexcept(noexcept(x.swap(y))); -\pnum -\throws -Nothing unless an exception is thrown by the -assignment operator or move assignment operator of -\tcode{T}. + // \ref{list.erasure}, erasure + template + constexpr typename list::size_type + erase(list& c, const U& value); + template + constexpr typename list::size_type + erase_if(list& c, Predicate pred); -\pnum -\complexity -The destructor of \tcode{T} is called the number of times equal to the -number of the elements erased, but the assignment operator -of \tcode{T} is called the number of times equal to the number of -elements in the vector after the erased elements. -\end{itemdescr} + namespace pmr { + template + using list = std::list>; + } +} +\end{codeblock} -\rSec3[vector.erasure]{Erasure} +\rSec2[list]{Class template \tcode{list}} -\indexlibrarymember{erase}{vector}% -\begin{itemdecl} -template - constexpr typename vector::size_type - erase(vector& c, const U& value); -\end{itemdecl} +\rSec3[list.overview]{Overview} -\begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -auto it = remove(c.begin(), c.end(), value); -auto r = distance(it, c.end()); -c.erase(it, c.end()); -return r; -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{erase_if}{vector}% -\begin{itemdecl} -template - constexpr typename vector::size_type - erase_if(vector& c, Predicate pred); -\end{itemdecl} +\indexlibraryglobal{list}% +A +\tcode{list} +is a sequence container that supports +bidirectional iterators and allows constant time insert and erase +operations anywhere within the sequence, with storage management handled +automatically. Unlike vectors\iref{vector} and deques\iref{deque}, +fast random access to list elements is not supported, but many +algorithms only need sequential access anyway. -\begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -auto it = remove_if(c.begin(), c.end(), pred); -auto r = distance(it, c.end()); -c.erase(it, c.end()); -return r; -\end{codeblock} -\end{itemdescr} - -\rSec2[vector.bool]{Specialization of \tcode{vector} for \tcode{bool}} - -\rSec3[vector.bool.pspc]{Partial class template specialization \tcode{vector}} +A \tcode{list} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of a sequence container, +including most of the optional sequence container +requirements\iref{sequence.reqmts}. +The exceptions are the +\tcode{operator[]} +and +\tcode{at} +member functions, which are not provided. +\begin{footnote} +These member functions +are only provided by containers whose iterators +are random access iterators. +\end{footnote} +Descriptions are provided here only for operations on +\tcode{list} +that are not described in one of these tables +or for operations where there is additional semantic information. \pnum -\indexlibraryglobal{vector}% -To optimize space allocation, a partial specialization of \tcode{vector} for -\tcode{bool} elements is provided: +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\ref{iterator.requirements.general}. + \begin{codeblock} namespace std { - template - class vector { + template> + class list { public: // types - using value_type = bool; + using value_type = T; using allocator_type = Allocator; - using pointer = @\impdefx{type of \tcode{vector::pointer}}@; - using const_pointer = @\impdefx{type of \tcode{vector::const_pointer}}@; - using const_reference = bool; - using size_type = @\impdefx{type of \tcode{vector::size_type}}@; // see \ref{container.requirements} - using difference_type = @\impdefx{type of \tcode{vector::difference_type}}@; // see \ref{container.requirements} - using iterator = @\impdefx{type of \tcode{vector::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{vector::const_iterator}}@; // see \ref{container.requirements} + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = @\impdefx{type of \tcode{list::size_type}}@; // see \ref{container.requirements} + using difference_type = @\impdefx{type of \tcode{list::difference_type}}@; // see \ref{container.requirements} + using iterator = @\impdefx{type of \tcode{list::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{list::const_iterator}}@; // see \ref{container.requirements} using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - // bit reference - class @\libmember{reference}{vector}@ { - friend class vector; - constexpr reference() noexcept; - - public: - constexpr reference(const reference&) = default; - constexpr ~reference(); - constexpr operator bool() const noexcept; - constexpr reference& operator=(bool x) noexcept; - constexpr reference& operator=(const reference& x) noexcept; - constexpr const reference& operator=(bool x) const noexcept; - constexpr void flip() noexcept; // flips the bit - }; - - // construct/copy/destroy - constexpr vector() noexcept(noexcept(Allocator())) : vector(Allocator()) { } - constexpr explicit vector(const Allocator&) noexcept; - constexpr explicit vector(size_type n, const Allocator& = Allocator()); - constexpr vector(size_type n, const bool& value, const Allocator& = Allocator()); + // \ref{list.cons}, construct/copy/destroy + constexpr list() : list(Allocator()) { } + constexpr explicit list(const Allocator&); + constexpr explicit list(size_type n, const Allocator& = Allocator()); + constexpr list(size_type n, const T& value, const Allocator& = Allocator()); template - 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) noexcept; - constexpr vector(const vector&, const type_identity_t&); - constexpr vector(vector&&, const type_identity_t&); - constexpr vector(initializer_list, const Allocator& = Allocator()); - constexpr ~vector(); - constexpr vector& operator=(const vector& x); - constexpr vector& operator=(vector&& x) - noexcept(allocator_traits::propagate_on_container_move_assignment::value || - allocator_traits::is_always_equal::value); - constexpr vector& operator=(initializer_list); + constexpr list(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr list(from_range_t, R&& rg, const Allocator& = Allocator()); + constexpr list(const list& x); + constexpr list(list&& x); + constexpr list(const list&, const type_identity_t&); + constexpr list(list&&, const type_identity_t&); + constexpr list(initializer_list, const Allocator& = Allocator()); + constexpr ~list(); + constexpr list& operator=(const list& x); + constexpr list& operator=(list&& x) + noexcept(allocator_traits::is_always_equal::value); + constexpr list& operator=(initializer_list); template constexpr void assign(InputIterator first, InputIterator last); - template<@\exposconcept{container-compatible-range}@ R> + 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 void assign(size_type n, const T& t); + constexpr void assign(initializer_list); constexpr allocator_type get_allocator() const noexcept; // iterators @@ -9284,1726 +9119,5072 @@ constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; - // capacity - [[nodiscard]] constexpr bool empty() const noexcept; + // \ref{list.capacity}, capacity + constexpr bool empty() const noexcept; constexpr size_type size() const noexcept; constexpr size_type max_size() const noexcept; - constexpr size_type capacity() const noexcept; - constexpr void resize(size_type sz, bool c = false); - constexpr void reserve(size_type n); - constexpr void shrink_to_fit(); - + constexpr void resize(size_type sz); + constexpr void resize(size_type sz, const T& c); + // element access - constexpr reference operator[](size_type n); - constexpr const_reference operator[](size_type n) const; - constexpr const_reference at(size_type n) const; - constexpr reference at(size_type n); constexpr reference front(); constexpr const_reference front() const; constexpr reference back(); constexpr const_reference back() const; - // modifiers + // \ref{list.modifiers}, modifiers + template constexpr reference emplace_front(Args&&... args); template constexpr reference emplace_back(Args&&... args); - constexpr void push_back(const bool& x); - template<@\exposconcept{container-compatible-range}@ R> + constexpr void push_front(const T& x); + constexpr void push_front(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void prepend_range(R&& rg); + constexpr void pop_front(); + constexpr void push_back(const T& x); + constexpr void push_back(T&& x); + template<@\exposconcept{container-compatible-range}@ 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); - constexpr iterator insert(const_iterator position, size_type n, const bool& x); + constexpr iterator insert(const_iterator position, const T& x); + constexpr iterator insert(const_iterator position, T&& x); + constexpr iterator insert(const_iterator position, size_type n, const T& x); template constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); - template<@\exposconcept{container-compatible-range}@ R> + 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 insert(const_iterator position, initializer_list il); constexpr iterator erase(const_iterator position); - constexpr iterator erase(const_iterator first, const_iterator last); - constexpr void swap(vector&) - noexcept(allocator_traits::propagate_on_container_swap::value || - allocator_traits::is_always_equal::value); - static constexpr void swap(reference x, reference y) noexcept; - constexpr void flip() noexcept; // flips all bits - constexpr void clear() noexcept; + constexpr iterator erase(const_iterator position, const_iterator last); + constexpr void swap(list&) noexcept(allocator_traits::is_always_equal::value); + constexpr void clear() noexcept; + + // \ref{list.ops}, list operations + constexpr void splice(const_iterator position, list& x); + constexpr void splice(const_iterator position, list&& x); + constexpr void splice(const_iterator position, list& x, const_iterator i); + constexpr void splice(const_iterator position, list&& x, const_iterator i); + constexpr void splice(const_iterator position, list& x, + const_iterator first, const_iterator last); + constexpr void splice(const_iterator position, list&& x, + const_iterator first, const_iterator last); + + constexpr size_type remove(const T& value); + template constexpr size_type remove_if(Predicate pred); + + constexpr size_type unique(); + template + constexpr size_type unique(BinaryPredicate binary_pred); + + constexpr void merge(list& x); + constexpr void merge(list&& x); + template constexpr void merge(list& x, Compare comp); + template constexpr void merge(list&& x, Compare comp); + + constexpr void sort(); + template constexpr void sort(Compare comp); + + constexpr void reverse() noexcept; }; + + template>> + list(InputIterator, InputIterator, Allocator = Allocator()) + -> list<@\placeholder{iter-value-type}@, Allocator>; + + template>> + list(from_range_t, R&&, Allocator = Allocator()) + -> list, Allocator>; } -\end{codeblock}% +\end{codeblock} \pnum -Unless described below, all operations have the same requirements and -semantics as the primary \tcode{vector} template, except that operations -dealing with the \tcode{bool} value type map to bit values in the -container storage and -\tcode{allocator_traits::construct}\iref{allocator.traits.members} -is not used to construct these values. +An incomplete type \tcode{T} may be used when instantiating \tcode{list} +if the allocator meets the +allocator completeness requirements\iref{allocator.requirements.completeness}. +\tcode{T} shall be complete before any member of the resulting specialization +of \tcode{list} is referenced. + +\rSec3[list.cons]{Constructors, copy, and assignment} + +\indexlibraryctor{list}% +\begin{itemdecl} +constexpr explicit list(const Allocator&); +\end{itemdecl} +\begin{itemdescr} \pnum -There is no requirement that the data be stored as a contiguous allocation -of \tcode{bool} values. A space-optimized representation of bits is -recommended instead. +\effects +Constructs an empty list, using the specified allocator. \pnum -\tcode{reference} -is a class that simulates the behavior of references of a single bit in -\tcode{vector}. The conversion function returns \tcode{true} -when the bit is set, and \tcode{false} otherwise. The assignment operators -set the bit when the argument is (convertible to) \tcode{true} and -clear it otherwise. \tcode{flip} reverses the state of the bit. +\complexity +Constant. +\end{itemdescr} -\indexlibrarymember{flip}{vector}% +\indexlibraryctor{list}% \begin{itemdecl} -constexpr void flip() noexcept; +constexpr explicit list(size_type n, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{list}. + \pnum \effects -Replaces each element in the container with its complement. +Constructs a \tcode{list} with +\tcode{n} default-inserted elements using the specified allocator. + +\pnum +\complexity +Linear in +\tcode{n}. \end{itemdescr} -\indexlibrarymember{swap}{vector}% +\indexlibraryctor{list}% \begin{itemdecl} -static constexpr void swap(reference x, reference y) noexcept; +constexpr list(size_type n, const T& value, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Exchanges the contents of \tcode{x} and \tcode{y} as if by: +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{list}. -\begin{codeblock} -bool b = x; -x = y; -y = b; -\end{codeblock} +\pnum +\effects +Constructs a +\tcode{list} +with +\tcode{n} +copies of +\tcode{value}, +using the specified allocator. +\pnum +\complexity +Linear in +\tcode{n}. \end{itemdescr} +\indexlibraryctor{list}% \begin{itemdecl} -template struct hash>; +template + constexpr list(InputIterator first, InputIterator last, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum -The specialization is enabled\iref{unord.hash}. +\effects +Constructs a +\tcode{list} +equal to the range +\range{first}{last}. + +\pnum +\complexity +Linear in +\tcode{distance(first, last)}. \end{itemdescr} -\indexlibrary{is-vector-bool-reference@\exposid{is-vector-bool-reference}}% +\indexlibraryctor{list}% \begin{itemdecl} -template - constexpr bool @\exposid{is-vector-bool-reference}@ = @\seebelow@; +template<@\exposconcept{container-compatible-range}@ R> + constexpr list(from_range_t, R&& rg, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum -The expression -\tcode{\exposid{is-vector-bool-reference}} is \tcode{true} -if \tcode{T} denotes the type \tcode{vector::\linebreak{}reference} -for some type \tcode{Alloc} and -\tcode{vector} is not a program-defined specialization. +\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[vector.bool.fmt]{Formatter specialization for \tcode{vector}} +\rSec3[list.capacity]{Capacity} -\indexlibraryglobal{formatter}% -\begin{codeblock} -namespace std { - template - requires @\exposid{is-vector-bool-reference}@ - struct formatter { - private: - formatter @\exposid{underlying_}@; // \expos +\indexlibrarymember{resize}{list}% +\begin{itemdecl} +constexpr void resize(size_type sz); +\end{itemdecl} - public: - template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{list}. - template - typename FormatContext::iterator - format(const T& ref, FormatContext& ctx) const; - }; -} +\pnum +\effects +If \tcode{size() < sz}, +appends \tcode{sz - size()} default-inserted elements to the +sequence. +If \tcode{sz <= size()}, equivalent to: + +\begin{codeblock} +list::iterator it = begin(); +advance(it, sz); +erase(it, end()); \end{codeblock} +\end{itemdescr} -\indexlibrarymember{parse}{formatter}% +\indexlibrarymember{resize}{list}% \begin{itemdecl} -template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); +constexpr void resize(size_type sz, const T& c); \end{itemdecl} \begin{itemdescr} \pnum -Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{list}. + +\pnum +\effects +As if by: +\begin{codeblock} +if (sz > size()) + insert(end(), sz-size(), c); +else if (sz < size()) { + iterator i = begin(); + advance(i, sz); + erase(i, end()); +} +else + ; // do nothing +\end{codeblock} \end{itemdescr} -\indexlibrarymember{format}{formatter}% +\rSec3[list.modifiers]{Modifiers} + +\indexlibrarymember{insert}{list}% \begin{itemdecl} -template - typename FormatContext::iterator - format(const T& ref, FormatContext& ctx) const; +constexpr iterator insert(const_iterator position, const T& x); +constexpr iterator insert(const_iterator position, T&& x); +constexpr iterator insert(const_iterator position, size_type n, const T& x); +template + 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_front(Args&&... args); +template constexpr reference emplace_back(Args&&... args); +template constexpr iterator emplace(const_iterator position, Args&&... args); +constexpr void push_front(const T& x); +constexpr void push_front(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + constexpr void prepend_range(R&& rg); +constexpr void push_back(const T& x); +constexpr void push_back(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + constexpr void append_range(R&& rg); \end{itemdecl} \begin{itemdescr} \pnum -Equivalent to: \tcode{return \exposid{underlying_}.format(ref, ctx);} -\end{itemdescr} +\complexity +Insertion of a single element into a list takes constant time and +exactly one call to a constructor of +\tcode{T}. Insertion of multiple elements into a list is linear in the +number of elements inserted, and the number of calls to the copy +constructor or move constructor of \tcode{T} is exactly equal +to the number of elements inserted. -\rSec1[associative]{Associative containers} +\pnum +\remarks +Does not affect the validity of iterators and references. +If an exception is thrown, there are no effects. +\end{itemdescr} -\rSec2[associative.general]{In general} +\indexlibrarymember{erase}{list}% +\begin{itemdecl} +constexpr iterator erase(const_iterator position); +constexpr iterator erase(const_iterator first, const_iterator last); +constexpr void pop_front(); +constexpr void pop_back(); +constexpr void clear() noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -The header \libheader{map} defines the class templates \tcode{map} and -\tcode{multimap}; the header \libheader{set} defines the class templates -\tcode{set} and \tcode{multiset}. +\effects +Invalidates only the iterators and references to the erased elements. \pnum -The following exposition-only alias templates may appear in deduction guides for associative containers: -\begin{codeblock} -template - using @\placeholder{iter-value-type}@ = - typename iterator_traits::value_type; // \expos -template - using @\placeholder{iter-key-type}@ = remove_const_t< - tuple_element_t<0, @\exposid{iter-value-type}@>>; // \expos -template - using @\placeholder{iter-mapped-type}@ = - tuple_element_t<1, @\exposid{iter-value-type}@>; // \expos -template - using @\placeholder{iter-to-alloc-type}@ = pair< - add_const_t>>, - tuple_element_t<1, @\exposid{iter-value-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} +\throws +Nothing. -\rSec2[associative.map.syn]{Header \tcode{} synopsis} +\pnum +\complexity +Erasing a single element is a constant time operation with a single call to the destructor of +\tcode{T}. +Erasing a range in a list is linear time in the +size of the range and the number of calls to the destructor of type +\tcode{T} +is exactly equal to the size of the range. +\end{itemdescr} -\indexheader{map}% -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} +\rSec3[list.ops]{Operations} -namespace std { - // \ref{map}, class template \tcode{map} - template, - class Allocator = allocator>> - class map; +\pnum +Since lists allow fast insertion and erasing from the middle of a list, certain +operations are provided specifically for them. +\begin{footnote} +As specified +in~\ref{allocator.requirements}, the requirements in this Clause apply only to +lists whose allocators compare equal. +\end{footnote} +In this subclause, +arguments for a template parameter +named \tcode{Predicate} or \tcode{BinaryPredicate} +shall meet the corresponding requirements in \ref{algorithms.requirements}. +The semantics of \tcode{i + n} and \tcode{i - n}, +where \tcode{i} is an iterator into the list and \tcode{n} is an integer, +are the same as those of \tcode{next(i, n)} and \tcode{prev(i, n)}, +respectively. +For \tcode{merge} and \tcode{sort}, +the definitions and requirements in \ref{alg.sorting} apply. - template - bool operator==(const map& x, - const map& y); - template - @\placeholder{synth-three-way-result}@> - operator<=>(const map& x, - const map& y); +\pnum +\tcode{list} provides three splice operations that destructively move elements from one list to +another. The behavior of splice operations is undefined if \tcode{get_allocator() != +x.get_allocator()}. - template - void swap(map& x, - map& y) - noexcept(noexcept(x.swap(y))); +\indexlibrarymember{splice}{list}% +\begin{itemdecl} +constexpr void splice(const_iterator position, list& x); +constexpr void splice(const_iterator position, list&& x); +\end{itemdecl} - // \ref{map.erasure}, erasure for \tcode{map} - template - typename map::size_type - erase_if(map& c, Predicate pred); +\begin{itemdescr} +\pnum +\expects +\tcode{addressof(x) != this} is \tcode{true}. - // \ref{multimap}, class template \tcode{multimap} - template, - class Allocator = allocator>> - class multimap; +\pnum +\effects +Inserts the contents of +\tcode{x} +before +\tcode{position} +and +\tcode{x} +becomes empty. +Pointers and references to the moved elements of +\tcode{x} +now refer to those same elements but as members of +\tcode{*this}. +Iterators referring to the moved elements will continue to refer to their +elements, but they now behave as iterators into +\tcode{*this}, +not into +\tcode{x}. - template - bool operator==(const multimap& x, - const multimap& y); - template - @\placeholder{synth-three-way-result}@> - operator<=>(const multimap& x, - const multimap& y); +\pnum +\throws +Nothing. - template - void swap(multimap& x, - multimap& y) - noexcept(noexcept(x.swap(y))); +\pnum +\complexity +Constant time. +\end{itemdescr} - // \ref{multimap.erasure}, erasure for \tcode{multimap} - template - typename multimap::size_type - erase_if(multimap& c, Predicate pred); +\indexlibrarymember{splice}{list}% +\begin{itemdecl} +constexpr void splice(const_iterator position, list& x, const_iterator i); +constexpr void splice(const_iterator position, list&& x, const_iterator i); +\end{itemdecl} - namespace pmr { - template> - using map = std::map>>; +\begin{itemdescr} +\pnum +\expects +\tcode{i} is a valid dereferenceable iterator of \tcode{x}. - template> - using multimap = std::multimap>>; - } -} -\end{codeblock} +\pnum +\effects +Inserts an element pointed to by +\tcode{i} +from list +\tcode{x} +before \tcode{position} and removes the element from +\tcode{x}. +The result is unchanged if +\tcode{position == i} +or +\tcode{position == ++i}. +Pointers and references to +\tcode{*i} +continue to refer to this same element but as a member of +\tcode{*this}. +Iterators +to +\tcode{*i} +(including +\tcode{i} +itself) continue to refer to the same element, but now behave as iterators into +\tcode{*this}, +not into +\tcode{x}. -\rSec2[associative.set.syn]{Header \tcode{} synopsis}% +\pnum +\throws +Nothing. -\indexheader{set}% -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} +\pnum +\complexity +Constant time. +\end{itemdescr} -namespace std { - // \ref{set}, class template \tcode{set} - template, class Allocator = allocator> - class set; +\indexlibrarymember{splice}{list}% +\begin{itemdecl} +constexpr void splice(const_iterator position, list& x, + const_iterator first, const_iterator last); +constexpr void splice(const_iterator position, list&& x, + const_iterator first, const_iterator last); +\end{itemdecl} - template - bool operator==(const set& x, - const set& y); - template - @\placeholder{synth-three-way-result}@ operator<=>(const set& x, - @\itcorr@ const set& y); +\begin{itemdescr} +\pnum +\expects +\range{first}{last} is a valid range in \tcode{x}. +\tcode{position} is not an iterator in the range \range{first}{last}. - template - void swap(set& x, - set& y) - noexcept(noexcept(x.swap(y))); +\pnum +\effects +Inserts elements in the range +\range{first}{last} +before +\tcode{position} +and removes the elements from +\tcode{x}. +Pointers and references to the moved elements of +\tcode{x} +now refer to those same elements but as members of +\tcode{*this}. +Iterators referring to the moved elements will continue to refer to their +elements, but they now behave as iterators into +\tcode{*this}, +not into +\tcode{x}. - // \ref{set.erasure}, erasure for \tcode{set} - template - typename set::size_type - erase_if(set& c, Predicate pred); +\pnum +\throws +Nothing. - // \ref{multiset}, class template \tcode{multiset} - template, class Allocator = allocator> - class multiset; +\pnum +\complexity +Constant time if +\tcode{addressof(x) == this}; +otherwise, linear time. +\end{itemdescr} - template - bool operator==(const multiset& x, - const multiset& y); - template - @\placeholder{synth-three-way-result}@ operator<=>(const multiset& x, - @\itcorr@ const multiset& y); +\indexlibrarymember{remove}{list}% +\begin{itemdecl} +constexpr size_type remove(const T& value); +template constexpr size_type remove_if(Predicate pred); +\end{itemdecl} - template - void swap(multiset& x, - multiset& y) - noexcept(noexcept(x.swap(y))); +\begin{itemdescr} +\pnum +\effects +Erases all the elements in the list referred to by a list iterator \tcode{i} for which the +following conditions hold: \tcode{*i == value}, \tcode{pred(*i) != false}. +Invalidates only the iterators and references to the erased elements. - // \ref{multiset.erasure}, erasure for \tcode{multiset} - template - typename multiset::size_type - erase_if(multiset& c, Predicate pred); +\pnum +\returns +The number of elements erased. - namespace pmr { - template> - using set = std::set>; +\pnum +\throws +Nothing unless an exception is thrown by +\tcode{*i == value} +or +\tcode{pred(*i) != false}. - template> - using multiset = std::multiset>; - } -} -\end{codeblock} - -\rSec2[map]{Class template \tcode{map}} - -\rSec3[map.overview]{Overview} - -\indexlibraryglobal{map}% \pnum -A \tcode{map} is an associative container that -supports unique keys (i.e., contains at most one of each key value) and -provides for fast retrieval of values of another type \tcode{T} based -on the keys. The \tcode{map} class supports bidirectional iterators. +\complexity +Exactly +\tcode{size()} +applications of the corresponding predicate. \pnum -A \tcode{map} meets all of the requirements of -a container\iref{container.reqmts}, -of a reversible container\iref{container.rev.reqmts}, -of an allocator-aware container\iref{container.alloc.reqmts}. and -of an associative container\iref{associative.reqmts}. -A -\tcode{map} -also provides most operations described in~\ref{associative.reqmts} -for unique keys. -This means that a -\tcode{map} -supports the -\tcode{a_uniq} -operations in~\ref{associative.reqmts} -but not the -\tcode{a_eq} -operations. -For a -\tcode{map} -the -\tcode{key_type} -is -\tcode{Key} -and the -\tcode{value_type} -is -\tcode{pair}. -Descriptions are provided here only for operations on -\tcode{map} -that are not described in one of those tables -or for operations where there is additional semantic information. - -\indexlibrarymember{comp}{map::value_compare}% -\indexlibrarymember{operator()}{map::value_compare}% -\begin{codeblock} -namespace std { - template, - class Allocator = allocator>> - class map { - public: - // types - using key_type = Key; - using mapped_type = T; - using value_type = pair; - using key_compare = Compare; - using allocator_type = Allocator; - using pointer = typename allocator_traits::pointer; - using const_pointer = typename allocator_traits::const_pointer; - using reference = value_type&; - using const_reference = const value_type&; - using size_type = @\impdefx{type of \tcode{map::size_type}}@; // see \ref{container.requirements} - using difference_type = @\impdefx{type of \tcode{map::difference_type}}@; // see \ref{container.requirements} - using iterator = @\impdefx{type of \tcode{map::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{map::const_iterator}}@; // see \ref{container.requirements} - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - using node_type = @\unspec@; - using insert_return_type = @\placeholdernc{insert-return-type}@; - - class value_compare { - friend class map; - protected: - Compare comp; - value_compare(Compare c) : comp(c) {} - - public: - bool operator()(const value_type& x, const value_type& y) const { - return comp(x.first, y.first); - } - }; - - // \ref{map.cons}, construct/copy/destroy - map() : map(Compare()) { } - explicit map(const Compare& comp, const Allocator& = Allocator()); - template - 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&); - map(const map&, const type_identity_t&); - map(map&&, const type_identity_t&); - map(initializer_list, - const Compare& = Compare(), - const Allocator& = Allocator()); - 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(); - map& operator=(const map& x); - map& operator=(map&& x) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_move_assignable_v); - map& operator=(initializer_list); - allocator_type get_allocator() const noexcept; - - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; - - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; - - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; - - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; - - // \ref{map.access}, element access - mapped_type& operator[](const key_type& x); - mapped_type& operator[](key_type&& x); - template mapped_type& operator[](K&& x); - mapped_type& at(const key_type& x); - const mapped_type& at(const key_type& x) const; - template mapped_type& at(const K& x); - template const mapped_type& at(const K& x) const; - - // \ref{map.modifiers}, modifiers - template pair emplace(Args&&... args); - template iterator emplace_hint(const_iterator position, Args&&... args); - pair insert(const value_type& x); - pair insert(value_type&& x); - template pair insert(P&& x); - iterator insert(const_iterator position, const value_type& x); - iterator insert(const_iterator position, value_type&& x); - template - 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); - node_type extract(const key_type& x); - template node_type extract(K&& x); - insert_return_type insert(node_type&& nh); - iterator insert(const_iterator hint, node_type&& nh); - - template - pair try_emplace(const key_type& k, Args&&... args); - template - pair try_emplace(key_type&& k, Args&&... args); - template - pair try_emplace(K&& k, Args&&... args); - template - iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); - template - iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); - template - iterator try_emplace(const_iterator hint, K&& k, Args&&... args); - template - pair insert_or_assign(const key_type& k, M&& obj); - template - pair insert_or_assign(key_type&& k, M&& obj); - template - pair insert_or_assign(K&& k, M&& obj); - template - iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); - template - iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); - template - iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); - - iterator erase(iterator position); - iterator erase(const_iterator position); - size_type erase(const key_type& x); - template size_type erase(K&& x); - iterator erase(const_iterator first, const_iterator last); - void swap(map&) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_swappable_v); - void clear() noexcept; - - template - void merge(map& source); - template - void merge(map&& source); - template - void merge(multimap& source); - template - void merge(multimap&& source); - - // observers - key_compare key_comp() const; - value_compare value_comp() const; - - // map operations - iterator find(const key_type& x); - const_iterator find(const key_type& x) const; - template iterator find(const K& x); - template const_iterator find(const K& x) const; +\remarks +Stable\iref{algorithm.stable}. +\end{itemdescr} - size_type count(const key_type& x) const; - template size_type count(const K& x) const; +\indexlibrarymember{unique}{list}% +\begin{itemdecl} +constexpr size_type unique(); +template constexpr size_type unique(BinaryPredicate binary_pred); +\end{itemdecl} - bool contains(const key_type& x) const; - template bool contains(const K& x) const; +\begin{itemdescr} +\pnum +Let \tcode{binary_pred} be \tcode{equal_to<>\{\}} for the first overload. - iterator lower_bound(const key_type& x); - const_iterator lower_bound(const key_type& x) const; - template iterator lower_bound(const K& x); - template const_iterator lower_bound(const K& x) const; +\pnum +\expects +\tcode{binary_pred} is an equivalence relation. - iterator upper_bound(const key_type& x); - const_iterator upper_bound(const key_type& x) const; - template iterator upper_bound(const K& x); - template const_iterator upper_bound(const K& x) const; +\pnum +\effects +Erases all but the first element from every +consecutive group of equivalent elements. +That is, for a nonempty list, erases all elements referred to +by the iterator \tcode{i} in the range \range{begin() + 1}{end()} +for which \tcode{binary_pred(*i, *(i - 1))} is \tcode{true}. +Invalidates only the iterators and references to the erased elements. - pair equal_range(const key_type& x); - pair equal_range(const key_type& x) const; - template - pair equal_range(const K& x); - template - pair equal_range(const K& x) const; - }; +\pnum +\returns +The number of elements erased. - template>, - class Allocator = allocator<@\placeholder{iter-to-alloc-type}@>> - map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) - -> map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Compare, Allocator>; +\pnum +\throws +Nothing unless an exception is thrown by the predicate. - 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>; +\pnum +\complexity +If \tcode{empty()} is \tcode{false}, +exactly \tcode{size() - 1} applications of the corresponding predicate, +otherwise no applications of the predicate. +\end{itemdescr} - template, - class Allocator = allocator>> - map(initializer_list>, Compare = Compare(), Allocator = Allocator()) - -> map; +\indexlibrarymember{merge}{list}% +\begin{itemdecl} +constexpr void merge(list& x); +constexpr void merge(list&& x); +template constexpr void merge(list& x, Compare comp); +template constexpr void merge(list&& x, Compare comp); +\end{itemdecl} - template - map(InputIterator, InputIterator, Allocator) - -> map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, - less<@\placeholder{iter-key-type}@>, Allocator>; +\begin{itemdescr} +\pnum +Let \tcode{comp} be \tcode{less<>{}} for the first two overloads. - template - map(from_range_t, R&&, Allocator) - -> map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, less<@\exposid{range-key-type}@>, Allocator>; +\pnum +\expects +\tcode{*this} and \tcode{x} are both sorted +with respect to the comparator \tcode{comp}, and +\tcode{get_allocator() == x.get_allocator()} is \tcode{true}. - template - map(initializer_list>, Allocator) -> map, Allocator>; -} -\end{codeblock} +\pnum +\effects +If \tcode{addressof(x) == this}, there are no effects. +Otherwise, merges +the two sorted ranges \range{begin()}{end()} and \range{x.begin()}{x.end()}. +The result is a range +that is sorted with respect to the comparator \tcode{comp}. +Pointers and references to the moved elements of \tcode{x} now refer to those same elements +but as members of \tcode{*this}. Iterators referring to the moved elements will continue to +refer to their elements, but they now behave as iterators into \tcode{*this}, not into +\tcode{x}. +\pnum +\complexity +At most \tcode{size() + x.size() - 1} comparisons +if \tcode{addressof(x) != this}; +otherwise, no comparisons are performed. -\rSec3[map.cons]{Constructors, copy, and assignment}% -\indexlibrarymember{map}{operator==}% -\indexlibrarymember{map}{operator<} +\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} -\indexlibraryctor{map}% +\indexlibrarymember{reverse}{list}% \begin{itemdecl} -explicit map(const Compare& comp, const Allocator& = Allocator()); +constexpr void reverse() noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs an empty -\tcode{map} -using the specified comparison object and allocator. +Reverses the order of the elements in the list. +Does not affect the validity of iterators and references. \pnum \complexity -Constant. +Linear time. \end{itemdescr} -\indexlibraryctor{map}% +\indexlibrarymember{sort}{list}% \begin{itemdecl} -template - map(InputIterator first, InputIterator last, - const Compare& comp = Compare(), const Allocator& = Allocator()); +void sort(); +template void sort(Compare comp); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs an empty -\tcode{map} -using the specified comparison object and allocator, -and inserts elements from the range -\range{first}{last}. - -\pnum -\complexity -Linear in $N$ if the range -\range{first}{last} -is already sorted with respect to \tcode{comp} -and otherwise $N \log N$, where $N$ -is \tcode{last - first}. -\end{itemdescr} - -\indexlibraryctor{map}% -\begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ 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}. +Sorts the list according to the \tcode{operator<} or a \tcode{Compare} function object. +If an exception is thrown, +the order of the elements in \tcode{*this} is unspecified. +Does not affect the validity of iterators and references. \pnum \complexity -Linear in $N$ if \tcode{rg} is already sorted with respect to \tcode{comp} and -otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. -\end{itemdescr} - -\rSec3[map.access]{Element access} - -\indexlibrary{\idxcode{operator[]}!\idxcode{map}}% -\begin{itemdecl} -mapped_type& operator[](const key_type& x); -\end{itemdecl} +Approximately +$N \log N$ +comparisons, where $N$ is \tcode{size()}. -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return try_emplace(x).first->second;} +\remarks +Stable\iref{algorithm.stable}. \end{itemdescr} -\indexlibrary{\idxcode{operator[]}!\idxcode{map}}% +\rSec3[list.erasure]{Erasure} + +\indexlibrarymember{erase}{list}% \begin{itemdecl} -mapped_type& operator[](key_type&& x); +template + typename list::size_type + constexpr erase(list& c, const U& value); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return try_emplace(std::move(x)).first->second;} +Equivalent to: +\begin{codeblock} +return erase_if(c, [&](const auto& elem) -> bool { return elem == value; }); +\end{codeblock} \end{itemdescr} -\indexlibrary{\idxcode{operator[]}!\idxcode{map}}% +\indexlibrarymember{erase_if}{list}% \begin{itemdecl} -template mapped_type& operator[](K&& x); +template + typename list::size_type + constexpr erase_if(list& c, Predicate pred); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -The \grammarterm{qualified-id} \tcode{Compare::is_transparent} -is valid and denotes a type. - \pnum \effects -Equivalent to: \tcode{return try_emplace(std::forward(x)).first->second;} +Equivalent to: \tcode{return c.remove_if(pred);} \end{itemdescr} -\indexlibrarymember{at}{map}% -\begin{itemdecl} -mapped_type& at(const key_type& x); -const mapped_type& at(const key_type& x) const; -\end{itemdecl} +\rSec2[vector.syn]{Header \tcode{} synopsis} -\begin{itemdescr} -\pnum -\returns -A reference to the \tcode{mapped_type} corresponding to \tcode{x} in \tcode{*this}. +\indexheader{vector}% +\begin{codeblock} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} -\pnum -\throws -An exception object of type \tcode{out_of_range} if -no such element is present. +namespace std { + // \ref{vector}, class template \tcode{vector} + template> class vector; -\pnum -\complexity -Logarithmic. -\end{itemdescr} + template + constexpr bool operator==(const vector& x, const vector& y); + template + constexpr @\placeholder{synth-three-way-result}@ operator<=>(const vector& x, + @\itcorr@ const vector& y); -\indexlibrarymember{at}{map}% -\begin{itemdecl} -template mapped_type& at(const K& x); -template const mapped_type& at(const K& x) const; -\end{itemdecl} + template + constexpr void swap(vector& x, vector& y) + noexcept(noexcept(x.swap(y))); -\begin{itemdescr} -\pnum -\constraints -The \grammarterm{qualified-id} \tcode{Compare::is_transparent} -is valid and denotes a type. + // \ref{vector.erasure}, erasure + template + constexpr typename vector::size_type + erase(vector& c, const U& value); + template + constexpr typename vector::size_type + erase_if(vector& c, Predicate pred); -\pnum -\expects -The expression \tcode{find(x)} is well-formed and has well-defined behavior. + namespace pmr { + template + using vector = std::vector>; + } -\pnum -\returns -A reference to \tcode{find(x)->second}. + // \ref{vector.bool}, specialization of \tcode{vector} for \tcode{bool} + // \ref{vector.bool.pspc}, partial class template specialization \tcode{vector} + template + class vector; -\pnum -\throws -An exception object of type \tcode{out_of_range} if -\tcode{find(x) == end()} is \tcode{true}. + template + constexpr bool @\exposid{is-vector-bool-reference}@ = @\seebelow@; // \expos -\pnum -\complexity -Logarithmic. -\end{itemdescr} + // hash support + template struct hash; + template struct hash>; -\rSec3[map.modifiers]{Modifiers} + // \ref{vector.bool.fmt}, formatter specialization for \tcode{vector} + template requires @\exposid{is-vector-bool-reference}@ + struct formatter; +} +\end{codeblock} -\indexlibrarymember{insert}{map}% -\begin{itemdecl} -template - pair insert(P&& x); -template - iterator insert(const_iterator position, P&& x); -\end{itemdecl} +\rSec2[vector]{Class template \tcode{vector}} -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\rSec3[vector.overview]{Overview} \pnum -\effects -The first form is equivalent to -\tcode{return emplace(std::forward

(x))}. The second form is -equivalent to \tcode{return emplace_hint(position, std::forward

(x))}. -\end{itemdescr} - -\indexlibrarymember{try_emplace}{map}% -\begin{itemdecl} -template - pair try_emplace(const key_type& k, Args&&... args); -template - iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); -\end{itemdecl} +\indexlibraryglobal{vector}% +A +\tcode{vector} +is a sequence container that supports +(amortized) constant time insert and erase operations at the end; +insert and erase in the middle take linear time. +Storage management is handled automatically, though hints can be given +to improve efficiency. -\begin{itemdescr} \pnum -\expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} -from \tcode{piecewise_construct}, \tcode{for\-ward_as_tuple(k)}, -\tcode{forward_as_tuple(std::forward(args)...)}. +A \tcode{vector} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, +of a sequence container, including most of the optional sequence container +requirements\iref{sequence.reqmts}, +and, for an element type other than \tcode{bool}, +of a contiguous container\iref{container.reqmts}. +The exceptions are the +\tcode{push_front}, \tcode{prepend_range}, \tcode{pop_front}, and \tcode{emplace_front} member functions, which are not +provided. Descriptions are provided here only for operations on \tcode{vector} +that are not described in one of these tables or for operations where there is +additional semantic information. \pnum -\effects -If the map already contains an element -whose key is equivalent to \tcode{k}, -there is no effect. -Otherwise inserts an object of type \tcode{value_type} -constructed with \tcode{piecewise_construct}, \tcode{forward_as_tuple(k)}, -\tcode{forward_as_tuple(std::forward(args)...)}. +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. -\pnum -\returns -In the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. +\begin{codeblock} +namespace std { + template> + class vector { + public: + // types + using value_type = T; + using allocator_type = Allocator; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = @\impdefx{type of \tcode{vector::size_type}}@; // see \ref{container.requirements} + using difference_type = @\impdefx{type of \tcode{vector::difference_type}}@; // see \ref{container.requirements} + using iterator = @\impdefx{type of \tcode{vector::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{vector::const_iterator}}@; // see \ref{container.requirements} + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; -\pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. -\end{itemdescr} + // \ref{vector.cons}, construct/copy/destroy + constexpr vector() noexcept(noexcept(Allocator())) : vector(Allocator()) { } + constexpr explicit vector(const Allocator&) noexcept; + constexpr explicit vector(size_type n, const Allocator& = Allocator()); + constexpr vector(size_type n, const T& value, const Allocator& = Allocator()); + template + 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&); + constexpr vector(vector&&, const type_identity_t&); + constexpr vector(initializer_list, const Allocator& = Allocator()); + constexpr ~vector(); + constexpr vector& operator=(const vector& x); + constexpr vector& operator=(vector&& x) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); + 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; -\indexlibrarymember{try_emplace}{map}% -\begin{itemdecl} -template - pair try_emplace(key_type&& k, Args&&... args); -template - iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); -\end{itemdecl} + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; -\begin{itemdescr} -\pnum -\expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} -from \tcode{piecewise_construct}, \tcode{for\-ward_as_tuple(std::move(k))}, -\tcode{forward_as_tuple(std::forward(args)...)}. + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + // \ref{vector.capacity}, capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; + constexpr size_type capacity() const noexcept; + constexpr void resize(size_type sz); + constexpr void resize(size_type sz, const T& c); + constexpr void reserve(size_type n); + constexpr void shrink_to_fit(); + + // element access + constexpr reference operator[](size_type n); + constexpr const_reference operator[](size_type n) const; + constexpr reference at(size_type n); + constexpr const_reference at(size_type n) const; + constexpr reference front(); + constexpr const_reference front() const; + constexpr reference back(); + constexpr const_reference back() const; + + // \ref{vector.data}, data access + constexpr T* data() noexcept; + constexpr const T* data() const noexcept; + + // \ref{vector.modifiers}, modifiers + template 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); + constexpr iterator insert(const_iterator position, const T& x); + constexpr iterator insert(const_iterator position, T&& x); + constexpr iterator insert(const_iterator position, size_type n, const T& x); + template + 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); + constexpr void swap(vector&) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); + constexpr void clear() noexcept; + }; + + 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==}% +\indexlibrarymember{vector}{operator<} \pnum -\effects -If the map already contains an element -whose key is equivalent to \tcode{k}, -there is no effect. -Otherwise inserts an object of type \tcode{value_type} -constructed with \tcode{piecewise_construct}, \tcode{forward_as_tuple(std::move(k))}, -\tcode{forward_as_tuple(std::forward(args)...)}. +An incomplete type \tcode{T} may be used when instantiating \tcode{vector} +if the allocator meets the +allocator completeness requirements\iref{allocator.requirements.completeness}. +\tcode{T} shall be complete before any member of the resulting specialization +of \tcode{vector} is referenced. + +\rSec3[vector.cons]{Constructors} + +\indexlibraryctor{vector} +\begin{itemdecl} +constexpr explicit vector(const Allocator&) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\returns -In the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. +\effects +Constructs an empty \tcode{vector}, using the +specified allocator. \pnum \complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. +Constant. \end{itemdescr} -\indexlibrarymember{try_emplace}{map}% +\indexlibraryctor{vector} \begin{itemdecl} -template - pair try_emplace(K&& k, Args&&... args); -template - iterator try_emplace(const_iterator hint, K&& k, Args&&... args); +constexpr explicit vector(size_type n, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -The \grammarterm{qualified-id} \tcode{Compare::is_transparent} -is valid and denotes a type. -For the first overload, -\tcode{is_convertible_v} and -\tcode{is_convertible_v} -are both \tcode{false}. - \pnum \expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} from -\tcode{piecewise_construct, forward_as_tuple(std::forward(k)), -forward_as_tuple(std::forward(args)...)}. +\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{vector}. \pnum \effects -If the map already contains an element whose key is equivalent to \tcode{k}, -there is no effect. -Otherwise, let \tcode{r} be \tcode{equal_range(k)}. -Constructs an object \tcode{u} of type \tcode{value_type} with -\tcode{piecewise_construct, forward_as_tuple(std::forward(k)), -forward_as_tuple(std::forward(args)...)}.\linebreak -If \tcode{equal_range(u.first) == r} is \tcode{false}, -the behavior is undefined. -Inserts \tcode{u} into \tcode{*this}. - -\pnum -\returns -For the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. +Constructs a \tcode{vector} with \tcode{n} +default-inserted elements using the specified allocator. \pnum \complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. +Linear in \tcode{n}. \end{itemdescr} -\indexlibrarymember{insert_or_assign}{map}% +\indexlibraryctor{vector} \begin{itemdecl} -template - pair insert_or_assign(const key_type& k, M&& obj); -template - iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); +constexpr vector(size_type n, const T& value, + const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} -\pnum -\mandates -\tcode{is_assignable_v} is \tcode{true}. - \pnum \expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} -from \tcode{k}, \tcode{std::forward(obj)}. +\tcode{T} is +\oldconcept{CopyInsertable} into \tcode{vector}. \pnum \effects -If the map already contains an element \tcode{e} -whose key is equivalent to \tcode{k}, -assigns \tcode{std::for\-ward(obj)} to \tcode{e.second}. -Otherwise inserts an object of type \tcode{value_type} -constructed with \tcode{k}, \tcode{std::forward(obj)}. - -\pnum -\returns -In the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. +Constructs a \tcode{vector} with \tcode{n} +copies of \tcode{value}, using the specified allocator. \pnum \complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. +Linear in \tcode{n}. \end{itemdescr} -\indexlibrarymember{insert_or_assign}{map}% +\indexlibraryctor{vector} \begin{itemdecl} -template - pair insert_or_assign(key_type&& k, M&& obj); -template - iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); +template + constexpr vector(InputIterator first, InputIterator last, + const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} -\pnum -\mandates -\tcode{is_assignable_v} is \tcode{true}. - -\pnum -\expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} -from \tcode{std::move(k)}, \tcode{std::for\-ward(obj)}. - \pnum \effects -If the map already contains an element \tcode{e} -whose key is equivalent to \tcode{k}, -assigns \tcode{std::for\-ward(obj)} to \tcode{e.second}. -Otherwise inserts an object of type \tcode{value_type} -constructed with \tcode{std::\brk{}move(k)}, \tcode{std::forward(obj)}. - -\pnum -\returns -In the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. +Constructs a \tcode{vector} equal to the +range \range{first}{last}, using the specified allocator. \pnum \complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. +Makes only $N$ +calls to the copy constructor of +\tcode{T} +(where $N$ +is the distance between +\tcode{first} +and +\tcode{last}) +and no reallocations if +\tcode{InputIterator} meets the \oldconcept{ForwardIterator} requirements. +It makes order +$N$ +calls to the copy constructor of +\tcode{T} +and order +$\log N$ +reallocations if they are just input iterators. \end{itemdescr} -\indexlibrarymember{insert_or_assign}{map}% +\indexlibraryctor{vector}% \begin{itemdecl} -template - pair insert_or_assign(K&& k, M&& obj); -template - iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); +template<@\exposconcept{container-compatible-range}@ R> + constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -The \grammarterm{qualified-id} \tcode{Compare::is_transparent} -is valid and denotes a type. +\effects +Constructs a \tcode{vector} object with the elements of the range \tcode{rg}, +using the specified allocator. \pnum -\mandates -\tcode{is_assignable_v} is \tcode{true}. +\complexity +Initializes exactly $N$ elements +from the results of dereferencing successive iterators of \tcode{rg}, +where $N$ is \tcode{ranges::distance(rg)}. \pnum -\expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} from -\tcode{std::forward(k), std::\newline forward(obj)}. +Performs no reallocations if: +\begin{itemize} +\item +\tcode{R} models \tcode{ranges::\libconcept{approximately_sized_range}}, and +\tcode{ranges::distance(rg) <= ranges::re\-serve_hint(rg)} is \tcode{true}, or +\item +\tcode{R} models \tcode{ranges::\libconcept{forward_range}} and +\tcode{R} does not model \tcode{ranges::\libconcept{approximately_sized_range}}. +\end{itemize} +Otherwise, performs order $\log N$ reallocations and +order $N$ calls to the copy or move constructor of \tcode{T}. +\end{itemdescr} + +\rSec3[vector.capacity]{Capacity} + +\indexlibrarymember{capacity}{vector}% +\begin{itemdecl} +constexpr size_type capacity() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The total number of elements that the vector can hold +without requiring reallocation. + +\pnum +\complexity +Constant time. +\end{itemdescr} + +\indexlibrarymember{reserve}{vector}% +\begin{itemdecl} +constexpr void reserve(size_type n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{vector}. \pnum \effects -If the map already contains an element \tcode{e} -whose key is equivalent to \tcode{k}, -assigns \tcode{std::forward\newline (obj)} to \tcode{e.second}. -Otherwise, let \tcode{r} be \tcode{equal_range(k)}. -Constructs an object \tcode{u} of type \tcode{value_type} -with \tcode{std::forward(k), std::forward(obj)}. -If \tcode{equal_range(u.first) == r} is \tcode{false}, -the behavior is undefined. -Inserts \tcode{u} into \tcode{*this}. +A directive that informs a +\tcode{vector} +of a planned change in size, so that it can manage the storage allocation accordingly. +After +\tcode{reserve()}, +\tcode{capacity()} +is greater or equal to the argument of +\tcode{reserve} +if reallocation happens; and equal to the previous value of +\tcode{capacity()} +otherwise. +Reallocation happens at this point if and only if the current capacity is less than the +argument of +\tcode{reserve()}. If an exception is thrown +other than by the move constructor of a non-\oldconcept{CopyInsertable} type, +there are no effects. \pnum -\returns -For the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. +\throws +\tcode{length_error} if \tcode{n > +max_size()}. +\begin{footnote} +\tcode{reserve()} uses \tcode{Allocator::allocate()} which +can throw an appropriate exception. +\end{footnote} \pnum \complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. +It does not change the size of the sequence and takes at most linear +time in the size of the sequence. + +\pnum +\remarks +Reallocation invalidates all the references, pointers, and iterators +referring to the elements in the sequence, as well as the past-the-end iterator. +\begin{note} +If no reallocation happens, they remain valid. +\end{note} +No reallocation shall take place during insertions that happen +after a call to \tcode{reserve()} +until an insertion would make the size of the vector +greater than the value of \tcode{capacity()}. \end{itemdescr} -\rSec3[map.erasure]{Erasure} +\indexlibrarymember{shrink_to_fit}{vector}% +\begin{itemdecl} +constexpr void shrink_to_fit(); +\end{itemdecl} -\indexlibrarymember{erase_if}{map}% +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{MoveInsertable} into \tcode{vector}. + +\pnum +\effects +\tcode{shrink_to_fit} is a non-binding request to reduce +\tcode{capacity()} to \tcode{size()}. +\begin{note} +The request is non-binding to allow latitude for +implementation-specific optimizations. +\end{note} +It does not increase \tcode{capacity()}, but may reduce \tcode{capacity()} +by causing reallocation. +If an exception is thrown other than by the move constructor +of a non-\oldconcept{CopyInsertable} \tcode{T}, there are no effects. + +\pnum +\complexity +If reallocation happens, +linear in the size of the sequence. + +\pnum +\remarks +Reallocation invalidates all the references, pointers, and iterators +referring to the elements in the sequence as well as the past-the-end iterator. +\begin{note} +If no reallocation happens, they remain valid. +\end{note} +\end{itemdescr} + +\indexlibrarymember{swap}{vector}% \begin{itemdecl} -template - typename map::size_type - erase_if(map& c, Predicate pred); +constexpr void swap(vector& x) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -auto original_size = c.size(); -for (auto i = c.begin(), last = c.end(); i != last; ) { - if (pred(*i)) { - i = c.erase(i); - } else { - ++i; - } -} -return original_size - c.size(); -\end{codeblock} +Exchanges the contents and +\tcode{capacity()} +of +\tcode{*this} +with that of \tcode{x}. + +\pnum +\complexity +Constant time. \end{itemdescr} -\rSec2[multimap]{Class template \tcode{multimap}} +\indexlibrarymember{resize}{vector}% +\begin{itemdecl} +constexpr void resize(size_type sz); +\end{itemdecl} -\rSec3[multimap.overview]{Overview} +\begin{itemdescr} +\pnum +\expects +\tcode{T} is +\oldconcept{MoveInsertable} and \oldconcept{DefaultInsertable} into \tcode{vector}. \pnum -\indexlibraryglobal{multimap}% -A -\tcode{multimap} -is an associative container that supports equivalent keys (i.e., possibly containing multiple copies of -the same key value) and provides for fast retrieval of values of another type -\tcode{T} -based on the keys. -The -\tcode{multimap} -class -supports bidirectional iterators. +\effects +If \tcode{sz < size()}, erases the last \tcode{size() - sz} elements +from the sequence. Otherwise, +appends \tcode{sz - size()} default-inserted elements to the sequence. \pnum -A \tcode{multimap} meets all of the requirements -of a container\iref{container.reqmts}, -of a reversible container\iref{container.rev.reqmts}, -of an allocator-aware container\iref{container.alloc.reqmts}, and -of an associative container\iref{associative.reqmts}. -A -\tcode{multimap} -also provides most operations described in~\ref{associative.reqmts} -for equal keys. -This means that a -\tcode{multimap} -supports the -\tcode{a_eq} -operations in~\ref{associative.reqmts} -but not the -\tcode{a_uniq} -operations. -For a -\tcode{multimap} -the -\tcode{key_type} -is -\tcode{Key} -and the -\tcode{value_type} -is -\tcode{pair}. -Descriptions are provided here only for operations on -\tcode{multimap} -that are not described in one of those tables -or for operations where there is additional semantic information. +\remarks +If an exception is thrown other than by the move constructor of a non-\oldconcept{CopyInsertable} +\tcode{T}, there are no effects. +\end{itemdescr} -\indexlibrarymember{comp}{multimap::value_compare}% -\indexlibrarymember{operator()}{multimap::value_compare}% -\begin{codeblock} -namespace std { - template, - class Allocator = allocator>> - class multimap { - public: - // types - using key_type = Key; - using mapped_type = T; - using value_type = pair; - using key_compare = Compare; - using allocator_type = Allocator; - using pointer = typename allocator_traits::pointer; - using const_pointer = typename allocator_traits::const_pointer; - using reference = value_type&; - using const_reference = const value_type&; - using size_type = @\impdefx{type of \tcode{multimap::size_type}}@; // see \ref{container.requirements} - using difference_type = @\impdefx{type of \tcode{multimap::difference_type}}@; // see \ref{container.requirements} - using iterator = @\impdefx{type of \tcode{multimap::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{multimap::const_iterator}}@; // see \ref{container.requirements} - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - using node_type = @\unspec@; +\indexlibrarymember{resize}{vector}% +\begin{itemdecl} +constexpr void resize(size_type sz, const T& c); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is +\oldconcept{CopyInsertable} into \tcode{vector}. + +\pnum +\effects +If \tcode{sz < size()}, erases the last \tcode{size() - sz} elements +from the sequence. Otherwise, +appends \tcode{sz - size()} copies of \tcode{c} to the sequence. + +\pnum +\remarks +If an exception is thrown, there are no effects. +\end{itemdescr} + +\rSec3[vector.data]{Data} + +\indexlibrarymember{data}{vector}% +\begin{itemdecl} +constexpr T* data() noexcept; +constexpr const T* data() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A pointer such that \range{data()}{data() + size()} is a valid range. For a +non-empty vector, \tcode{data() == addressof(front())} is \keyword{true}. + +\pnum +\complexity +Constant time. +\end{itemdescr} + +\rSec3[vector.modifiers]{Modifiers} + +\indexlibrarymember{insert}{vector}% +\begin{itemdecl} +constexpr iterator insert(const_iterator position, const T& x); +constexpr iterator insert(const_iterator position, T&& x); +constexpr iterator insert(const_iterator position, size_type n, const T& x); +template + 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} +\pnum +\complexity +If reallocation happens, +linear in the number of elements of the resulting vector; +otherwise, +linear in the number of elements inserted plus the distance +to the end of the vector. + +\pnum +\remarks +Causes reallocation if the new size is greater than the old capacity. +Reallocation invalidates all the references, pointers, and iterators +referring to the elements in the sequence, as well as the past-the-end iterator. +If no reallocation happens, then +references, pointers, and iterators +before the insertion point remain valid +but those at or after the insertion point, +including the past-the-end iterator, +are invalidated. +If an exception is thrown other than by +the copy constructor, move constructor, +assignment operator, or move assignment operator of +\tcode{T} or by any \tcode{InputIterator} operation, +there are no effects. +If an exception is thrown while inserting a single element at the end and +\tcode{T} is \oldconcept{CopyInsertable} or \tcode{is_nothrow_move_constructible_v} +is \tcode{true}, there are no effects. +Otherwise, if an exception is thrown by the move constructor of a non-\oldconcept{CopyInsertable} +\tcode{T}, the effects are unspecified. + +\pnum +For the declarations taking a range \tcode{R}, +performs at most one reallocation if: +\begin{itemize} +\item +\tcode{R} models \tcode{ranges::\libconcept{approximately_sized_range}} and +\tcode{ranges::distance(rg) <= ranges::re\-serve_hint(rg)} is \tcode{true}, or +\item +\tcode{R} models \tcode{ranges::\libconcept{forward_range}} and +\tcode{R} does not model \tcode{ranges::\libconcept{approximately_sized_range}}. +\end{itemize} +For the declarations taking a pair of \tcode{InputIterator}, +performs at most one reallocation if +\tcode{InputItera\-tor} meets the \oldconcept{ForwardIterator} requirements. +\end{itemdescr} + +\indexlibrarymember{erase}{vector}% +\begin{itemdecl} +constexpr iterator erase(const_iterator position); +constexpr iterator erase(const_iterator first, const_iterator last); +constexpr void pop_back(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Invalidates iterators and references at or after the point of the erase. + +\pnum +\throws +Nothing unless an exception is thrown by the +assignment operator or move assignment operator of +\tcode{T}. + +\pnum +\complexity +The destructor of \tcode{T} is called the number of times equal to the +number of the elements erased, but the assignment operator +of \tcode{T} is called the number of times equal to the number of +elements in the vector after the erased elements. +\end{itemdescr} + +\rSec3[vector.erasure]{Erasure} + +\indexlibrarymember{erase}{vector}% +\begin{itemdecl} +template + constexpr typename vector::size_type + erase(vector& c, const U& value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto it = remove(c.begin(), c.end(), value); +auto r = distance(it, c.end()); +c.erase(it, c.end()); +return r; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{erase_if}{vector}% +\begin{itemdecl} +template + constexpr typename vector::size_type + erase_if(vector& c, Predicate pred); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto it = remove_if(c.begin(), c.end(), pred); +auto r = distance(it, c.end()); +c.erase(it, c.end()); +return r; +\end{codeblock} +\end{itemdescr} + +\rSec2[vector.bool]{Specialization of \tcode{vector} for \tcode{bool}} + +\rSec3[vector.bool.pspc]{Partial class template specialization \tcode{vector}} + +\pnum +\indexlibraryglobal{vector}% +To optimize space allocation, a partial specialization of \tcode{vector} for +\tcode{bool} elements is provided: +\begin{codeblock} +namespace std { + template + class vector { + public: + // types + using value_type = bool; + using allocator_type = Allocator; + using pointer = @\impdefx{type of \tcode{vector::pointer}}@; + using const_pointer = @\impdefx{type of \tcode{vector::const_pointer}}@; + using const_reference = bool; + using size_type = @\impdefx{type of \tcode{vector::size_type}}@; // see \ref{container.requirements} + using difference_type = @\impdefx{type of \tcode{vector::difference_type}}@; // see \ref{container.requirements} + using iterator = @\impdefx{type of \tcode{vector::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{vector::const_iterator}}@; // see \ref{container.requirements} + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + // bit reference + class @\libmember{reference}{vector}@ { + public: + constexpr reference(const reference&) = default; + constexpr ~reference(); + constexpr operator bool() const noexcept; + constexpr reference& operator=(bool x) noexcept; + constexpr reference& operator=(const reference& x) noexcept; + constexpr const reference& operator=(bool x) const noexcept; + constexpr void flip() noexcept; // flips the bit + }; + + // construct/copy/destroy + constexpr vector() noexcept(noexcept(Allocator())) : vector(Allocator()) { } + constexpr explicit vector(const Allocator&) noexcept; + constexpr explicit vector(size_type n, const Allocator& = Allocator()); + constexpr vector(size_type n, const bool& value, const Allocator& = Allocator()); + template + 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) noexcept; + constexpr vector(const vector&, const type_identity_t&); + constexpr vector(vector&&, const type_identity_t&); + constexpr vector(initializer_list, const Allocator& = Allocator()); + constexpr ~vector(); + constexpr vector& operator=(const vector& x); + constexpr vector& operator=(vector&& x) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); + 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; + + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; + + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + // capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; + constexpr size_type capacity() const noexcept; + constexpr void resize(size_type sz, bool c = false); + constexpr void reserve(size_type n); + constexpr void shrink_to_fit(); + + // element access + constexpr reference operator[](size_type n); + constexpr const_reference operator[](size_type n) const; + constexpr reference at(size_type n); + constexpr const_reference at(size_type n) const; + constexpr reference front(); + constexpr const_reference front() const; + constexpr reference back(); + constexpr const_reference back() const; + + // modifiers + template 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); + constexpr iterator insert(const_iterator position, size_type n, const bool& 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 il); + + constexpr iterator erase(const_iterator position); + constexpr iterator erase(const_iterator first, const_iterator last); + constexpr void swap(vector&) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); + static constexpr void swap(reference x, reference y) noexcept; + constexpr void flip() noexcept; // flips all bits + constexpr void clear() noexcept; + }; +} +\end{codeblock}% + +\pnum +Unless described below, all operations have the same requirements and +semantics as the primary \tcode{vector} template, except that operations +dealing with the \tcode{bool} value type map to bit values in the +container storage and +\tcode{allocator_traits::construct}\iref{allocator.traits.members} +is not used to construct these values. + +\pnum +There is no requirement that the data be stored as a contiguous allocation +of \tcode{bool} values. A space-optimized representation of bits is +recommended instead. + +\pnum +\tcode{reference} +is a class that simulates the behavior of references of a single bit in +\tcode{vector}. The conversion function returns \tcode{true} +when the bit is set, and \tcode{false} otherwise. The assignment operators +set the bit when the argument is (convertible to) \tcode{true} and +clear it otherwise. \tcode{flip} reverses the state of the bit. + +\indexlibrarymember{flip}{vector}% +\begin{itemdecl} +constexpr void flip() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Replaces each element in the container with its complement. +\end{itemdescr} + +\indexlibrarymember{swap}{vector}% +\begin{itemdecl} +static constexpr void swap(reference x, reference y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Exchanges the contents of \tcode{x} and \tcode{y} as if by: + +\begin{codeblock} +bool b = x; +x = y; +y = b; +\end{codeblock} + +\end{itemdescr} + +\begin{itemdecl} +template struct hash>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The specialization is enabled\iref{unord.hash}. +\end{itemdescr} + +\indexlibrary{is-vector-bool-reference@\exposid{is-vector-bool-reference}}% +\begin{itemdecl} +template + constexpr bool @\exposid{is-vector-bool-reference}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The expression +\tcode{\exposid{is-vector-bool-reference}} is \tcode{true} +if \tcode{T} denotes the type \tcode{vector::\linebreak{}reference} +for some type \tcode{Alloc} and +\tcode{vector} is not a program-defined specialization. +\end{itemdescr} + +\rSec3[vector.bool.fmt]{Formatter specialization for \tcode{vector}} + +\indexlibraryglobal{formatter}% +\begin{codeblock} +namespace std { + template + requires @\exposid{is-vector-bool-reference}@ + struct formatter { + private: + formatter @\exposid{underlying_}@; // \expos + + public: + template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); + + template + typename FormatContext::iterator + format(const T& ref, FormatContext& ctx) const; + }; +} +\end{codeblock} + +\indexlibrarymember{parse}{formatter}% +\begin{itemdecl} +template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +\end{itemdescr} + +\indexlibrarymember{format}{formatter}% +\begin{itemdecl} +template + typename FormatContext::iterator + format(const T& ref, FormatContext& ctx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Equivalent to: \tcode{return \exposid{underlying_}.format(ref, ctx);} +\end{itemdescr} + +\rSec2[inplace.vector.syn]{Header \tcode{} synopsis} + +\indexheader{inplace_vector}% +\begin{codeblock} +// mostly freestanding +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} + +namespace std { + // \ref{inplace.vector}, class template \tcode{inplace_vector} + template class inplace_vector; // partially freestanding + + // \ref{inplace.vector.erasure}, erasure + template + constexpr typename inplace_vector::size_type + erase(inplace_vector& c, const U& value); + template + constexpr typename inplace_vector::size_type + erase_if(inplace_vector& c, Predicate pred); +} +\end{codeblock} + +\rSec2[inplace.vector]{Class template \tcode{inplace_vector}} + +\rSec3[inplace.vector.overview]{Overview} + +\pnum +\indexlibraryglobal{inplace_vector}% +An \tcode{inplace_vector} is a contiguous container. +Its capacity is fixed and +its elements are stored within the \tcode{inplace_vector} object itself. + +\pnum +An \tcode{inplace_vector} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of a contiguous container, and +of a sequence container, +including most of the optional sequence container requirements\iref{sequence.reqmts}. +The exceptions are the +\tcode{push_front}, +\tcode{prepend_range}, +\tcode{pop_front}, and +\tcode{emplace_front} +member functions, which are not provided. +Descriptions are provided here only +for operations on \tcode{inplace_vector} that +are not described in one of these tables or +for operations where there is additional semantic information. + +\pnum +For any \tcode{N}, +\tcode{inplace_vector::iterator} and +\tcode{inplace_vector::const_iterator} +meet the constexpr iterator requirements. + +\pnum +Any member function of \tcode{inplace_vector} that +would cause the size to exceed \tcode{N} +throws an exception of type \tcode{bad_alloc}. + +\pnum +Let \tcode{IV} denote a specialization of \tcode{inplace_vector}. +If \tcode{N} is zero, then +\tcode{IV} is trivially copyable and empty, and +\tcode{std::is_trivially_default_constructible_v} is \tcode{true}. +Otherwise: +\begin{itemize} +\item +If \tcode{is_trivially_copy_constructible_v} is \tcode{true}, then +\tcode{IV} has a trivial copy constructor. +\item +If \tcode{is_trivially_move_constructible_v} is \tcode{true}, then +\tcode{IV} has a trivial move constructor. +\item +If \tcode{is_trivially_destructible_v} is \tcode{true}, then: + \begin{itemize} + \item + \tcode{IV} has a trivial destructor. + \item + If +\begin{codeblock} + is_trivially_copy_constructible_v && is_trivially_copy_assignable_v +\end{codeblock} + is \tcode{true}, then + \tcode{IV} has a trivial copy assignment operator. + \item + If +\begin{codeblock} + is_trivially_move_constructible_v && is_trivially_move_assignable_v +\end{codeblock} + is \tcode{true}, then + \tcode{IV} has a trivial move assignment operator. + \end{itemize} +\end{itemize} + +\begin{codeblock} +namespace std { + template + class inplace_vector { + public: + // types: + using value_type = T; + using pointer = T*; + using const_pointer = const T*; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = size_t; + using difference_type = ptrdiff_t; + using iterator = @\impdefx{type of \tcode{inplace_vector::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{inplace_vector::const_iterator}}@; // see \ref{container.requirements} + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + // \ref{inplace.vector.cons}, construct/copy/destroy + constexpr inplace_vector() noexcept; + constexpr explicit inplace_vector(size_type n); // freestanding-deleted + constexpr inplace_vector(size_type n, const T& value); // freestanding-deleted + template + constexpr inplace_vector(InputIterator first, InputIterator last); // freestanding-deleted + template<@\exposconcept{container-compatible-range}@ R> + constexpr inplace_vector(from_range_t, R&& rg); // freestanding-deleted + constexpr inplace_vector(const inplace_vector&); + constexpr inplace_vector(inplace_vector&&) + noexcept(N == 0 || is_nothrow_move_constructible_v); + constexpr inplace_vector(initializer_list il); // freestanding-deleted + constexpr ~inplace_vector(); + constexpr inplace_vector& operator=(const inplace_vector& other); + constexpr inplace_vector& operator=(inplace_vector&& other) + noexcept(N == 0 || (is_nothrow_move_assignable_v && + is_nothrow_move_constructible_v)); + constexpr inplace_vector& operator=(initializer_list); // freestanding-deleted + template + constexpr void assign(InputIterator first, InputIterator last); // freestanding-deleted + template<@\exposconcept{container-compatible-range}@ R> + constexpr void assign_range(R&& rg); // freestanding-deleted + constexpr void assign(size_type n, const T& u); // freestanding-deleted + constexpr void assign(initializer_list il); // freestanding-deleted + + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; + + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + // \ref{inplace.vector.capacity}, capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + static constexpr size_type max_size() noexcept; + static constexpr size_type capacity() noexcept; + constexpr void resize(size_type sz); // freestanding-deleted + constexpr void resize(size_type sz, const T& c); // freestanding-deleted + static constexpr void reserve(size_type n); // freestanding-deleted + static constexpr void shrink_to_fit() noexcept; + + // element access + constexpr reference operator[](size_type n); + constexpr const_reference operator[](size_type n) const; + constexpr reference at(size_type n); // freestanding-deleted + constexpr const_reference at(size_type n) const; // freestanding-deleted + constexpr reference front(); + constexpr const_reference front() const; + constexpr reference back(); + constexpr const_reference back() const; + + // \ref{inplace.vector.data}, data access + constexpr T* data() noexcept; + constexpr const T* data() const noexcept; + + // \ref{inplace.vector.modifiers}, modifiers + template + constexpr reference emplace_back(Args&&... args); // freestanding-deleted + constexpr reference push_back(const T& x); // freestanding-deleted + constexpr reference push_back(T&& x); // freestanding-deleted + template<@\exposconcept{container-compatible-range}@ R> + constexpr void append_range(R&& rg); // freestanding-deleted + constexpr void pop_back(); + + template + constexpr pointer try_emplace_back(Args&&... args); + constexpr pointer try_push_back(const T& x); + constexpr pointer try_push_back(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + constexpr ranges::borrowed_iterator_t try_append_range(R&& rg); + + template + constexpr reference unchecked_emplace_back(Args&&... args); + constexpr reference unchecked_push_back(const T& x); + constexpr reference unchecked_push_back(T&& x); + + template + constexpr iterator emplace(const_iterator position, Args&&... args); // freestanding-deleted + constexpr iterator insert(const_iterator position, const T& x); // freestanding-deleted + constexpr iterator insert(const_iterator position, T&& x); // freestanding-deleted + constexpr iterator insert(const_iterator position, size_type n, // freestanding-deleted + const T& x); + template + constexpr iterator insert(const_iterator position, // freestanding-deleted + InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator position, R&& rg); // freestanding-deleted + constexpr iterator insert(const_iterator position, // freestanding-deleted + initializer_list il); + constexpr iterator erase(const_iterator position); + constexpr iterator erase(const_iterator first, const_iterator last); + constexpr void swap(inplace_vector& x) + noexcept(N == 0 || (is_nothrow_swappable_v && + is_nothrow_move_constructible_v)); + constexpr void clear() noexcept; + + friend constexpr bool operator==(const inplace_vector& x, + const inplace_vector& y); + friend constexpr @\exposid{synth-three-way-result}@ + operator<=>(const inplace_vector& x, const inplace_vector& y); + friend constexpr void swap(inplace_vector& x, inplace_vector& y) + noexcept(N == 0 || (is_nothrow_swappable_v && + is_nothrow_move_constructible_v)) + { x.swap(y); } + }; +} +\end{codeblock} + +\rSec3[inplace.vector.cons]{Constructors} + +\indexlibraryctor{inplace_vector} +\begin{itemdecl} +constexpr explicit inplace_vector(size_type n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{inplace_vector}. + +\pnum +\effects +Constructs an \tcode{inplace_vector} with \tcode{n} default-inserted elements. + +\pnum +\complexity +Linear in \tcode{n}. +\end{itemdescr} + +\indexlibraryctor{inplace_vector} +\begin{itemdecl} +constexpr inplace_vector(size_type n, const T& value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{inplace_vector}. + +\pnum +\effects +Constructs an \tcode{inplace_vector} with \tcode{n} copies of \tcode{value}. + +\pnum +\complexity +Linear in \tcode{n}. +\end{itemdescr} + +\indexlibraryctor{inplace_vector} +\begin{itemdecl} +template + constexpr inplace_vector(InputIterator first, InputIterator last); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an \tcode{inplace_vector} equal to the range \range{first}{last}. + +\pnum +\complexity +Linear in \tcode{distance(first, last)}. +\end{itemdescr} + +\indexlibraryctor{inplace_vector} +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr inplace_vector(from_range_t, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an \tcode{inplace_vector} with +the elements of the range \tcode{rg}. + +\pnum +\complexity +Linear in \tcode{ranges::distance(rg)}. +\end{itemdescr} + +\rSec3[inplace.vector.capacity]{Capacity} + +\indexlibrarymember{capacity}{inplace_vector}% +\indexlibrarymember{max_size}{inplace_vector}% +\begin{itemdecl} +static constexpr size_type capacity() noexcept; +static constexpr size_type max_size() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{N}. +\end{itemdescr} + +\indexlibrarymember{resize}{inplace_vector}% +\begin{itemdecl} +constexpr void resize(size_type sz); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{DefaultInsertable} into \tcode{inplace_vector}. + +\pnum +\effects +%FIXME: Should "is \tcode{true}" be appended here? +If \tcode{sz < size()}, +erases the last \tcode{size() - sz} elements from the sequence. +Otherwise, +appends \tcode{sz - size()} default-inserted elements to the sequence. + +\pnum +\remarks +If an exception is thrown, there are no effects on \tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{resize}{inplace_vector}% +\begin{itemdecl} +constexpr void resize(size_type sz, const T& c); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{CopyInsertable} into \tcode{inplace_vector}. + +\pnum +\effects +%FIXME: Should "is \tcode{true}" be appended here? +If \tcode{sz < size()}, +erases the last \tcode{size() - sz} elements from the sequence. +Otherwise, +appends \tcode{sz - size()} copies of \tcode{c} to the sequence. + +\pnum +\remarks +If an exception is thrown, there are no effects on \tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{reserve}{inplace_vector}% +\begin{itemdecl} +static constexpr void reserve(size_type n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +None. + +\pnum +\throws +\tcode{bad_alloc} if \tcode{n > capacity()} is \tcode{true}. +\end{itemdescr} + +\indexlibrarymember{shrink_to_fit}{inplace_vector}% +\begin{itemdecl} +static constexpr void shrink_to_fit() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +None. +\end{itemdescr} + +\rSec3[inplace.vector.data]{Data} + +\indexlibrarymember{data}{inplace_vector}% +\begin{itemdecl} +constexpr T* data() noexcept; +constexpr const T* data() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A pointer such that \range{data()}{data() + size()} is a valid range. +For a non-empty \tcode{inplace_vector}, +\tcode{data() == addressof(front())} is \tcode{true}. + +\pnum +\complexity +Constant time. +\end{itemdescr} + +\rSec3[inplace.vector.modifiers]{Modifiers} + +\indexlibrarymember{insert}{inplace_vector}% +\indexlibrarymember{insert_range}{inplace_vector}% +\indexlibrarymember{emplace}{inplace_vector}% +\indexlibrarymember{append_range}{inplace_vector}% +\begin{itemdecl} +constexpr iterator insert(const_iterator position, const T& x); +constexpr iterator insert(const_iterator position, T&& x); +constexpr iterator insert(const_iterator position, size_type n, const T& x); +template + 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); + +template + constexpr iterator emplace(const_iterator position, Args&&... args); +template<@\exposconcept{container-compatible-range}@ R> + constexpr void append_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $n$ be the value of \tcode{size()} before this call for +the \tcode{append_range} overload, and +\tcode{distance(begin, position)} otherwise. + +\pnum +\complexity +Linear in the number of elements inserted plus +the distance to the end of the vector. + +\pnum +\remarks +If an exception is thrown other than by the +copy constructor, +move constructor, +assignment operator, or +move assignment operator +of \tcode{T} or by +any \tcode{InputIterator} operation, +there are no effects. +Otherwise, +if an exception is thrown, then +$\tcode{size()} \ge n$ and +elements in the range \tcode{begin() + \range{0}{$n$}} are not modified. +\end{itemdescr} + +\indexlibrarymember{push_back}{inplace_vector}% +\indexlibrarymember{emplace_back}{inplace_vector}% +\begin{itemdecl} +constexpr reference push_back(const T& x); +constexpr reference push_back(T&& x); +template + constexpr reference emplace_back(Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{back()}. + +\pnum +\throws +\tcode{bad_alloc} or +any exception thrown by the initialization of the inserted element. + +\pnum +\complexity +Constant. + +\pnum +\remarks +If an exception is thrown, there are no effects on \tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{try_emplace_back}{inplace_vector}% +\indexlibrarymember{try_push_back}{inplace_vector}% +\begin{itemdecl} +template + constexpr pointer try_emplace_back(Args&&... args); +constexpr pointer try_push_back(const T& x); +constexpr pointer try_push_back(T&& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{vals} denote a pack: +\begin{itemize} +\item \tcode{std::forward(args)...} for the first overload, +\item \tcode{x} for the second overload, +\item \tcode{std::move(x)} for the third overload. +\end{itemize} + +\pnum +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} +into \tcode{inplace_vector} from \tcode{vals...}. + +\pnum +\effects +If \tcode{size() < capacity()} is \tcode{true}, +appends an object of type \tcode{T} +direct-non-list-initialized with \tcode{vals...}. +Otherwise, there are no effects. + +\pnum +\returns +\keyword{nullptr} if \tcode{size() == capacity()} is \tcode{true}, +otherwise \tcode{addressof(back())}. + +\pnum +\throws +Nothing unless an exception is thrown by the initialization of the inserted element. + +\pnum +\complexity +Constant. + +\pnum +\remarks +If an exception is thrown, there are no effects on \tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{try_append_range}{inplace_vector}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr ranges::borrowed_iterator_t try_append_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} +into \tcode{inplace_vector} from\\\tcode{*ranges::begin(rg)}. + +\pnum +\effects +Appends copies of initial elements in \tcode{rg} before \tcode{end()}, +until all elements are inserted or \tcode{size() == capacity()} is \tcode{true}. +Each iterator in the range \tcode{rg} is dereferenced at most once. + +\pnum +\returns +An iterator pointing to the first element of \tcode{rg} +that was not inserted into \tcode{*this}, +or \tcode{ranges::end(rg)} if no such element exists. + +\pnum +\complexity +Linear in the number of elements inserted. + +\pnum +\remarks +Let $n$ be the value of \tcode{size()} prior to this call. +If an exception is thrown after the insertion of $k$ elements, then +\tcode{size()} equals $n + k$, +elements in the range \tcode{begin() + \range{0}{$n$}} are not modified, and +elements in the range \tcode{begin() + \range{$n$}{$n + k$}} correspond to +the inserted elements. +\end{itemdescr} + +\indexlibrarymember{unchecked_emplace_back}{inplace_vector}% +\begin{itemdecl} +template + constexpr reference unchecked_emplace_back(Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{size() < capacity()} is \tcode{true}. + +\pnum +\effects +Equivalent to: +\tcode{return *try_emplace_back(std::forward(args)...);} +\end{itemdescr} + +\indexlibrarymember{unchecked_push_back}{inplace_vector}% +\begin{itemdecl} +constexpr reference unchecked_push_back(const T& x); +constexpr reference unchecked_push_back(T&& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{size() < capacity()} is \tcode{true}. + +\pnum +\effects +Equivalent to: +\tcode{return *try_push_back(std::forward(x));} +\end{itemdescr} + +\indexlibrarymember{erase}{inplace_vector}% +\indexlibrarymember{pop_back}{inplace_vector}% +\begin{itemdecl} +constexpr iterator erase(const_iterator position); +constexpr iterator erase(const_iterator first, const_iterator last); +constexpr void pop_back(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Invalidates iterators and references at or after the point of the erase. + +\pnum +\throws +Nothing unless an exception is thrown by +the assignment operator or move assignment operator of \tcode{T}. + +\pnum +\complexity +The destructor of \tcode{T} is called the number of times +equal to the number of the elements erased, but +the assignment operator of \tcode{T} is called the number of times +equal to the number of elements after the erased elements. +\end{itemdescr} + +\rSec3[inplace.vector.erasure]{Erasure} + +\indexlibrarymember{erase}{inplace_vector}% +\begin{itemdecl} +template + constexpr size_t erase(inplace_vector& c, const U& value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto it = remove(c.begin(), c.end(), value); +auto r = distance(it, c.end()); +c.erase(it, c.end()); +return r; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{erase_if}{inplace_vector}% +\begin{itemdecl} +template + constexpr size_t erase_if(inplace_vector& c, Predicate pred); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto it = remove_if(c.begin(), c.end(), pred); +auto r = distance(it, c.end()); +c.erase(it, c.end()); +return r; +\end{codeblock} +\end{itemdescr} + +\rSec1[associative]{Associative containers} + +\rSec2[associative.general]{General} + +\pnum +The header \libheaderrefx{map}{associative.map.syn} defines the class templates +\tcode{map} and \tcode{multimap}; +the header \libheaderrefx{set}{associative.set.syn} defines the class templates +\tcode{set} and \tcode{multiset}. + +\pnum +The following exposition-only alias templates may appear in deduction guides for associative containers: +\begin{codeblock} +template + using @\placeholder{iter-value-type}@ = + typename iterator_traits::value_type; // \expos +template + using @\placeholder{iter-key-type}@ = remove_const_t< + tuple_element_t<0, @\exposid{iter-value-type}@>>; // \expos +template + using @\placeholder{iter-mapped-type}@ = + tuple_element_t<1, @\exposid{iter-value-type}@>; // \expos +template + using @\placeholder{iter-to-alloc-type}@ = pair< + add_const_t>>, + tuple_element_t<1, @\exposid{iter-value-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} + +\indexheader{map}% +\begin{codeblock} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} + +namespace std { + // \ref{map}, class template \tcode{map} + template, + class Allocator = allocator>> + class map; + + template + constexpr bool operator==(const map& x, + const map& y); + template + constexpr @\placeholder{synth-three-way-result}@> + operator<=>(const map& x, + const map& y); + + template + constexpr void swap(map& x, + map& y) + noexcept(noexcept(x.swap(y))); + + // \ref{map.erasure}, erasure for \tcode{map} + template + constexpr typename map::size_type + erase_if(map& c, Predicate pred); + + // \ref{multimap}, class template \tcode{multimap} + template, + class Allocator = allocator>> + class multimap; + + template + constexpr bool operator==(const multimap& x, + const multimap& y); + template + constexpr @\placeholder{synth-three-way-result}@> + operator<=>(const multimap& x, + const multimap& y); + + template + constexpr void swap(multimap& x, + multimap& y) + noexcept(noexcept(x.swap(y))); + + // \ref{multimap.erasure}, erasure for \tcode{multimap} + template + constexpr typename multimap::size_type + erase_if(multimap& c, Predicate pred); + + namespace pmr { + template> + using map = std::map>>; + + template> + using multimap = std::multimap>>; + } +} +\end{codeblock} + +\rSec2[map]{Class template \tcode{map}} + +\rSec3[map.overview]{Overview} + +\indexlibraryglobal{map}% +\pnum +A \tcode{map} is an associative container that +supports unique keys (i.e., contains at most one of each key value) and +provides for fast retrieval of values of another type \tcode{T} based +on the keys. The \tcode{map} class supports bidirectional iterators. + +\pnum +A \tcode{map} meets all of the requirements of +a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an associative container\iref{associative.reqmts}. +A +\tcode{map} +also provides most operations described in~\ref{associative.reqmts} +for unique keys. +This means that a +\tcode{map} +supports the +\tcode{a_uniq} +operations in~\ref{associative.reqmts} +but not the +\tcode{a_eq} +operations. +For a +\tcode{map} +the +\tcode{key_type} +is +\tcode{Key} +and the +\tcode{value_type} +is +\tcode{pair}. +Descriptions are provided here only for operations on +\tcode{map} +that are not described in one of those tables +or for operations where there is additional semantic information. + +\pnum +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. + +\indexlibrarymember{comp}{map::value_compare}% +\indexlibrarymember{operator()}{map::value_compare}% +\begin{codeblock} +namespace std { + template, + class Allocator = allocator>> + class map { + public: + // types + using key_type = Key; + using mapped_type = T; + using value_type = pair; + using key_compare = Compare; + using allocator_type = Allocator; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = @\impdefx{type of \tcode{map::size_type}}@; // see \ref{container.requirements} + using difference_type = @\impdefx{type of \tcode{map::difference_type}}@; // see \ref{container.requirements} + using iterator = @\impdefx{type of \tcode{map::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{map::const_iterator}}@; // see \ref{container.requirements} + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using node_type = @\unspec@; + using insert_return_type = @\placeholdernc{insert-return-type}@; + + class value_compare { + protected: + Compare comp; + constexpr value_compare(Compare c) : comp(c) {} + + public: + constexpr bool operator()(const value_type& x, const value_type& y) const { + return comp(x.first, y.first); + } + }; + + // \ref{map.cons}, construct/copy/destroy + constexpr map() : map(Compare()) { } + constexpr explicit map(const Compare& comp, const Allocator& = Allocator()); + template + constexpr map(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr map(from_range_t, R&& rg, const Compare& comp = Compare(), + const Allocator& = Allocator()); + constexpr map(const map& x); + constexpr map(map&& x); + explicit map(const Allocator&); + constexpr map(const map&, const type_identity_t&); + constexpr map(map&&, const type_identity_t&); + constexpr map(initializer_list, const Compare& = Compare(), + const Allocator& = Allocator()); + template + constexpr map(InputIterator first, InputIterator last, const Allocator& a) + : map(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + constexpr map(from_range_t, R&& rg, const Allocator& a)) + : map(from_range, std::forward(rg), Compare(), a) { } + constexpr map(initializer_list il, const Allocator& a) + : map(il, Compare(), a) { } + constexpr ~map(); + constexpr map& operator=(const map& x); + constexpr map& operator=(map&& x) + noexcept(allocator_traits::is_always_equal::value && + is_nothrow_move_assignable_v); + constexpr map& operator=(initializer_list); + constexpr allocator_type get_allocator() const noexcept; + + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; + + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + // capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; + + // \ref{map.access}, element access + constexpr mapped_type& operator[](const key_type& x); + constexpr mapped_type& operator[](key_type&& x); + template constexpr mapped_type& operator[](K&& x); + constexpr mapped_type& at(const key_type& x); + constexpr const mapped_type& at(const key_type& x) const; + template constexpr mapped_type& at(const K& x); + template constexpr const mapped_type& at(const K& x) const; + + // \ref{map.modifiers}, modifiers + template constexpr pair emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); + constexpr pair insert(const value_type& x); + constexpr pair insert(value_type&& x); + template constexpr pair insert(P&& x); + constexpr iterator insert(const_iterator position, const value_type& x); + constexpr iterator insert(const_iterator position, value_type&& x); + template + constexpr iterator insert(const_iterator position, P&&); + template + constexpr void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); + constexpr void insert(initializer_list); + + constexpr node_type extract(const_iterator position); + constexpr node_type extract(const key_type& x); + template constexpr node_type extract(K&& x); + constexpr insert_return_type insert(node_type&& nh); + constexpr iterator insert(const_iterator hint, node_type&& nh); + + template + constexpr pair try_emplace(const key_type& k, Args&&... args); + template + constexpr pair try_emplace(key_type&& k, Args&&... args); + template + constexpr pair try_emplace(K&& k, Args&&... args); + template + constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); + template + constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); + template + constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args); + template + constexpr pair insert_or_assign(const key_type& k, M&& obj); + template + constexpr pair insert_or_assign(key_type&& k, M&& obj); + template + constexpr pair insert_or_assign(K&& k, M&& obj); + template + constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); + template + constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); + template + constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); + + constexpr iterator erase(iterator position); + constexpr iterator erase(const_iterator position); + constexpr size_type erase(const key_type& x); + template constexpr size_type erase(K&& x); + constexpr iterator erase(const_iterator first, const_iterator last); + constexpr void swap(map&) + noexcept(allocator_traits::is_always_equal::value && + is_nothrow_swappable_v); + constexpr void clear() noexcept; + + template + constexpr void merge(map& source); + template + constexpr void merge(map&& source); + template + constexpr void merge(multimap& source); + template + constexpr void merge(multimap&& source); + + // observers + constexpr key_compare key_comp() const; + constexpr value_compare value_comp() const; + + // map operations + constexpr iterator find(const key_type& x); + constexpr const_iterator find(const key_type& x) const; + template constexpr iterator find(const K& x); + template constexpr const_iterator find(const K& x) const; + + constexpr size_type count(const key_type& x) const; + template constexpr size_type count(const K& x) const; + + constexpr bool contains(const key_type& x) const; + template constexpr bool contains(const K& x) const; + + constexpr iterator lower_bound(const key_type& x); + constexpr const_iterator lower_bound(const key_type& x) const; + template constexpr iterator lower_bound(const K& x); + template constexpr const_iterator lower_bound(const K& x) const; + + constexpr iterator upper_bound(const key_type& x); + constexpr const_iterator upper_bound(const key_type& x) const; + template constexpr iterator upper_bound(const K& x); + template constexpr const_iterator upper_bound(const K& x) const; + + constexpr pair equal_range(const key_type& x); + constexpr pair equal_range(const key_type& x) const; + template + constexpr pair equal_range(const K& x); + template + constexpr pair equal_range(const K& x) const; + }; + + template>, + class Allocator = allocator<@\placeholder{iter-to-alloc-type}@>> + 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()) + -> map; + + template + map(InputIterator, InputIterator, Allocator) + -> 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>; +} +\end{codeblock} + + +\rSec3[map.cons]{Constructors, copy, and assignment}% +\indexlibrarymember{map}{operator==}% +\indexlibrarymember{map}{operator<} + +\indexlibraryctor{map}% +\begin{itemdecl} +constexpr explicit map(const Compare& comp, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty +\tcode{map} +using the specified comparison object and allocator. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexlibraryctor{map}% +\begin{itemdecl} +template + constexpr map(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty +\tcode{map} +using the specified comparison object and allocator, +and inserts elements from the range +\range{first}{last}. + +\pnum +\complexity +Linear in $N$ if the range +\range{first}{last} +is already sorted with respect to \tcode{comp} +and otherwise $N \log N$, where $N$ +is \tcode{last - first}. +\end{itemdescr} + +\indexlibraryctor{map}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr map(from_range_t, R&& rg, const Compare& comp = Compare(), + const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{map} +using the specified comparison object and allocator, +and inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted with respect to \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + +\rSec3[map.access]{Element access} + +\indexlibrary{\idxcode{operator[]}!\idxcode{map}}% +\begin{itemdecl} +constexpr mapped_type& operator[](const key_type& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return try_emplace(x).first->second;} +\end{itemdescr} + +\indexlibrary{\idxcode{operator[]}!\idxcode{map}}% +\begin{itemdecl} +constexpr mapped_type& operator[](key_type&& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return try_emplace(std::move(x)).first->second;} +\end{itemdescr} + +\indexlibrary{\idxcode{operator[]}!\idxcode{map}}% +\begin{itemdecl} +template constexpr mapped_type& operator[](K&& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The \grammarterm{qualified-id} \tcode{Compare::is_transparent} +is valid and denotes a type. + +\pnum +\effects +Equivalent to: \tcode{return try_emplace(std::forward(x)).first->second;} +\end{itemdescr} + +\indexlibrarymember{at}{map}% +\begin{itemdecl} +constexpr mapped_type& at(const key_type& x); +constexpr const mapped_type& at(const key_type& x) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A reference to the \tcode{mapped_type} corresponding to \tcode{x} in \tcode{*this}. + +\pnum +\throws +An exception object of type \tcode{out_of_range} if +no such element is present. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\indexlibrarymember{at}{map}% +\begin{itemdecl} +template constexpr mapped_type& at(const K& x); +template constexpr const mapped_type& at(const K& x) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The \grammarterm{qualified-id} \tcode{Compare::is_transparent} +is valid and denotes a type. + +\pnum +\expects +The expression \tcode{find(x)} is well-formed and has well-defined behavior. + +\pnum +\returns +A reference to \tcode{find(x)->second}. + +\pnum +\throws +An exception object of type \tcode{out_of_range} if +\tcode{find(x) == end()} is \tcode{true}. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\rSec3[map.modifiers]{Modifiers} + +\indexlibrarymember{insert}{map}% +\begin{itemdecl} +template + constexpr pair insert(P&& x); +template + constexpr iterator insert(const_iterator position, P&& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +The first form is equivalent to +\tcode{return emplace(std::forward

(x))}. The second form is +equivalent to \tcode{return emplace_hint(position, std::forward

(x))}. +\end{itemdescr} + +\indexlibrarymember{try_emplace}{map}% +\begin{itemdecl} +template + constexpr pair try_emplace(const key_type& k, Args&&... args); +template + constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} +from \tcode{piecewise_construct}, \tcode{for\-ward_as_tuple(k)}, +\tcode{forward_as_tuple(std::forward(args)...)}. + +\pnum +\effects +If the map already contains an element +whose key is equivalent to \tcode{k}, +there is no effect. +Otherwise inserts an object of type \tcode{value_type} +constructed with \tcode{piecewise_construct}, \tcode{forward_as_tuple(k)}, +\tcode{forward_as_tuple(std::forward(args)...)}. + +\pnum +\returns +In the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. + +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, +respectively. +\end{itemdescr} + +\indexlibrarymember{try_emplace}{map}% +\begin{itemdecl} +template + constexpr pair try_emplace(key_type&& k, Args&&... args); +template + constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} +from \tcode{piecewise_construct}, \tcode{for\-ward_as_tuple(std::move(k))}, +\tcode{forward_as_tuple(std::forward(args)...)}. + +\pnum +\effects +If the map already contains an element +whose key is equivalent to \tcode{k}, +there is no effect. +Otherwise inserts an object of type \tcode{value_type} +constructed with \tcode{piecewise_construct}, \tcode{forward_as_tuple(std::move(k))}, +\tcode{forward_as_tuple(std::forward(args)...)}. + +\pnum +\returns +In the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. + +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, +respectively. +\end{itemdescr} + +\indexlibrarymember{try_emplace}{map}% +\begin{itemdecl} +template + constexpr pair try_emplace(K&& k, Args&&... args); +template + constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The \grammarterm{qualified-id} \tcode{Compare::is_transparent} +is valid and denotes a type. +For the first overload, +\tcode{is_convertible_v} and +\tcode{is_convertible_v} +are both \tcode{false}. + +\pnum +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} from +\tcode{piecewise_construct, forward_as_tuple(std::forward(k)), +forward_as_tuple(std::forward(args)...)}. + +\pnum +\effects +If the map already contains an element whose key is equivalent to \tcode{k}, +there is no effect. +Otherwise, let \tcode{r} be \tcode{equal_range(k)}. +Constructs an object \tcode{u} of type \tcode{value_type} with +\tcode{piecewise_construct, forward_as_tuple(std::forward(k)), +forward_as_tuple(std::forward(args)...)}.\linebreak +If \tcode{equal_range(u.first) == r} is \tcode{false}, +the behavior is undefined. +Inserts \tcode{u} into \tcode{*this}. + +\pnum +\returns +For the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. + +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. +\end{itemdescr} + +\indexlibrarymember{insert_or_assign}{map}% +\begin{itemdecl} +template + constexpr pair insert_or_assign(const key_type& k, M&& obj); +template + constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_assignable_v} is \tcode{true}. + +\pnum +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} +from \tcode{k}, \tcode{std::forward(obj)}. + +\pnum +\effects +If the map already contains an element \tcode{e} +whose key is equivalent to \tcode{k}, +assigns \tcode{std::for\-ward(obj)} to \tcode{e.second}. +Otherwise inserts an object of type \tcode{value_type} +constructed with \tcode{k}, \tcode{std::forward(obj)}. + +\pnum +\returns +In the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. + +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, +respectively. +\end{itemdescr} + +\indexlibrarymember{insert_or_assign}{map}% +\begin{itemdecl} +template + constexpr pair insert_or_assign(key_type&& k, M&& obj); +template + constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_assignable_v} is \tcode{true}. + +\pnum +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} +from \tcode{std::move(k)}, \tcode{std::for\-ward(obj)}. + +\pnum +\effects +If the map already contains an element \tcode{e} +whose key is equivalent to \tcode{k}, +assigns \tcode{std::for\-ward(obj)} to \tcode{e.second}. +Otherwise inserts an object of type \tcode{value_type} +constructed with \tcode{std::\brk{}move(k)}, \tcode{std::forward(obj)}. + +\pnum +\returns +In the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. + +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, +respectively. +\end{itemdescr} + +\indexlibrarymember{insert_or_assign}{map}% +\begin{itemdecl} +template + constexpr pair insert_or_assign(K&& k, M&& obj); +template + constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The \grammarterm{qualified-id} \tcode{Compare::is_transparent} +is valid and denotes a type. + +\pnum +\mandates +\tcode{is_assignable_v} is \tcode{true}. + +\pnum +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{map} from +\tcode{std::forward(k), std::\newline forward(obj)}. + +\pnum +\effects +If the map already contains an element \tcode{e} +whose key is equivalent to \tcode{k}, +assigns \tcode{std::forward\newline (obj)} to \tcode{e.second}. +Otherwise, let \tcode{r} be \tcode{equal_range(k)}. +Constructs an object \tcode{u} of type \tcode{value_type} +with \tcode{std::forward(k), std::forward(obj)}. +If \tcode{equal_range(u.first) == r} is \tcode{false}, +the behavior is undefined. +Inserts \tcode{u} into \tcode{*this}. + +\pnum +\returns +For the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. + +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. +\end{itemdescr} + +\rSec3[map.erasure]{Erasure} + +\indexlibrarymember{erase_if}{map}% +\begin{itemdecl} +template + typename map::size_type + constexpr erase_if(map& c, Predicate pred); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto original_size = c.size(); +for (auto i = c.begin(), last = c.end(); i != last; ) { + if (pred(*i)) { + i = c.erase(i); + } else { + ++i; + } +} +return original_size - c.size(); +\end{codeblock} +\end{itemdescr} + +\rSec2[multimap]{Class template \tcode{multimap}} + +\rSec3[multimap.overview]{Overview} + +\pnum +\indexlibraryglobal{multimap}% +A +\tcode{multimap} +is an associative container that supports equivalent keys (i.e., possibly containing multiple copies of +the same key value) and provides for fast retrieval of values of another type +\tcode{T} +based on the keys. +The +\tcode{multimap} +class +supports bidirectional iterators. + +\pnum +A \tcode{multimap} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an associative container\iref{associative.reqmts}. +A +\tcode{multimap} +also provides most operations described in~\ref{associative.reqmts} +for equal keys. +This means that a +\tcode{multimap} +supports the +\tcode{a_eq} +operations in~\ref{associative.reqmts} +but not the +\tcode{a_uniq} +operations. +For a +\tcode{multimap} +the +\tcode{key_type} +is +\tcode{Key} +and the +\tcode{value_type} +is +\tcode{pair}. +Descriptions are provided here only for operations on +\tcode{multimap} +that are not described in one of those tables +or for operations where there is additional semantic information. + +\pnum +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. + +\indexlibrarymember{comp}{multimap::value_compare}% +\indexlibrarymember{operator()}{multimap::value_compare}% +\begin{codeblock} +namespace std { + template, + class Allocator = allocator>> + class multimap { + public: + // types + using key_type = Key; + using mapped_type = T; + using value_type = pair; + using key_compare = Compare; + using allocator_type = Allocator; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = @\impdefx{type of \tcode{multimap::size_type}}@; // see \ref{container.requirements} + using difference_type = @\impdefx{type of \tcode{multimap::difference_type}}@; // see \ref{container.requirements} + using iterator = @\impdefx{type of \tcode{multimap::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{multimap::const_iterator}}@; // see \ref{container.requirements} + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using node_type = @\unspec@; + + class value_compare { + protected: + Compare comp; + constexpr value_compare(Compare c) : comp(c) { } + + public: + constexpr bool operator()(const value_type& x, const value_type& y) const { + return comp(x.first, y.first); + } + }; + + // \ref{multimap.cons}, construct/copy/destroy + constexpr multimap() : multimap(Compare()) { } + constexpr explicit multimap(const Compare& comp, const Allocator& = Allocator()); + template + constexpr multimap(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr multimap(from_range_t, R&& rg, + const Compare& comp = Compare(), const Allocator& = Allocator()); + constexpr multimap(const multimap& x); + constexpr multimap(multimap&& x); + constexpr explicit multimap(const Allocator&); + constexpr multimap(const multimap&, const type_identity_t&); + constexpr multimap(multimap&&, const type_identity_t&); + constexpr multimap(initializer_list, + const Compare& = Compare(), const Allocator& = Allocator()); + template + constexpr multimap(InputIterator first, InputIterator last, const Allocator& a) + : multimap(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + constexpr multimap(from_range_t, R&& rg, const Allocator& a)) + : multimap(from_range, std::forward(rg), Compare(), a) { } + constexpr multimap(initializer_list il, const Allocator& a) + : multimap(il, Compare(), a) { } + constexpr ~multimap(); + constexpr multimap& operator=(const multimap& x); + constexpr multimap& operator=(multimap&& x) + noexcept(allocator_traits::is_always_equal::value && + is_nothrow_move_assignable_v); + constexpr multimap& operator=(initializer_list); + constexpr allocator_type get_allocator() const noexcept; + + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; + + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + // capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; + + // \ref{multimap.modifiers}, modifiers + template constexpr iterator emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); + constexpr iterator insert(const value_type& x); + constexpr iterator insert(value_type&& x); + template constexpr iterator insert(P&& x); + constexpr iterator insert(const_iterator position, const value_type& x); + constexpr iterator insert(const_iterator position, value_type&& x); + template constexpr iterator insert(const_iterator position, P&& x); + template + constexpr void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); + constexpr void insert(initializer_list); + + constexpr node_type extract(const_iterator position); + constexpr node_type extract(const key_type& x); + template node_type extract(K&& x); + constexpr iterator insert(node_type&& nh); + constexpr iterator insert(const_iterator hint, node_type&& nh); + + constexpr iterator erase(iterator position); + constexpr iterator erase(const_iterator position); + constexpr size_type erase(const key_type& x); + template constexpr size_type erase(K&& x); + constexpr iterator erase(const_iterator first, const_iterator last); + constexpr void swap(multimap&) + noexcept(allocator_traits::is_always_equal::value && + is_nothrow_swappable_v); + constexpr void clear() noexcept; + + template + constexpr void merge(multimap& source); + template + constexpr void merge(multimap&& source); + template + constexpr void merge(map& source); + template + constexpr void merge(map&& source); + + // observers + constexpr key_compare key_comp() const; + constexpr value_compare value_comp() const; + + // map operations + constexpr iterator find(const key_type& x); + constexpr const_iterator find(const key_type& x) const; + template constexpr iterator find(const K& x); + template constexpr const_iterator find(const K& x) const; + + constexpr size_type count(const key_type& x) const; + template constexpr size_type count(const K& x) const; + + constexpr bool contains(const key_type& x) const; + template constexpr bool contains(const K& x) const; + + constexpr iterator lower_bound(const key_type& x); + constexpr const_iterator lower_bound(const key_type& x) const; + template constexpr iterator lower_bound(const K& x); + template constexpr const_iterator lower_bound(const K& x) const; + + constexpr iterator upper_bound(const key_type& x); + constexpr const_iterator upper_bound(const key_type& x) const; + template constexpr iterator upper_bound(const K& x); + template constexpr const_iterator upper_bound(const K& x) const; + + constexpr pair equal_range(const key_type& x); + constexpr pair equal_range(const key_type& x) const; + template + constexpr pair equal_range(const K& x); + template + constexpr pair equal_range(const K& x) const; + }; + + template>, + class Allocator = allocator<@\placeholder{iter-to-alloc-type}@>> + multimap(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) + -> 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()) + -> multimap; + + template + multimap(InputIterator, InputIterator, Allocator) + -> 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>; +} +\end{codeblock}% +\indexlibrarymember{multimap}{operator==}% +\indexlibrarymember{multimap}{operator<} + +\rSec3[multimap.cons]{Constructors} + +\indexlibraryctor{multimap}% +\begin{itemdecl} +constexpr explicit multimap(const Compare& comp, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty +\tcode{multimap} +using the specified comparison object and allocator. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexlibraryctor{multimap}% +\begin{itemdecl} +template + constexpr multimap(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty +\tcode{multimap} +using the specified comparison object and allocator, +and inserts elements from the range +\range{first}{last}. + +\pnum +\complexity +Linear in $N$ if the range +\range{first}{last} +is already sorted with respect to \tcode{comp} +and otherwise $N \log N$, +where $N$ is +\tcode{last - first}. +\end{itemdescr} + +\indexlibraryctor{multimap}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr multimap(from_range_t, R&& rg, + const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{multimap} +using the specified comparison object and allocator, and +inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted with respect to \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + +\rSec3[multimap.modifiers]{Modifiers} + +\indexlibrarymember{insert}{multimap}% +\begin{itemdecl} +template constexpr iterator insert(P&& x); +template constexpr iterator insert(const_iterator position, P&& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +The first form is equivalent to +\tcode{return emplace(std::forward

(x))}. The second form is +equivalent to \tcode{return emplace_hint(position, std::forward

(x))}. +\end{itemdescr} + +\rSec3[multimap.erasure]{Erasure} + +\indexlibrarymember{erase_if}{multimap}% +\begin{itemdecl} +template + typename multimap::size_type + constexpr erase_if(multimap& c, Predicate pred); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto original_size = c.size(); +for (auto i = c.begin(), last = c.end(); i != last; ) { + if (pred(*i)) { + i = c.erase(i); + } else { + ++i; + } +} +return original_size - c.size(); +\end{codeblock} +\end{itemdescr} + +\rSec2[associative.set.syn]{Header \tcode{} synopsis}% + +\indexheader{set}% +\begin{codeblock} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} + +namespace std { + // \ref{set}, class template \tcode{set} + template, class Allocator = allocator> + class set; + + template + constexpr bool operator==(const set& x, + const set& y); + template + constexpr @\placeholder{synth-three-way-result}@ operator<=>(const set& x, + @\itcorr@ const set& y); + + template + constexpr void swap(set& x, + set& y) + noexcept(noexcept(x.swap(y))); + + // \ref{set.erasure}, erasure for \tcode{set} + template + constexpr typename set::size_type + erase_if(set& c, Predicate pred); + + // \ref{multiset}, class template \tcode{multiset} + template, class Allocator = allocator> + class multiset; + + template + constexpr bool operator==(const multiset& x, + const multiset& y); + template + constexpr @\placeholder{synth-three-way-result}@ + operator<=>(const multiset& x, + const multiset& y); + + template + constexpr void swap(multiset& x, + multiset& y) + noexcept(noexcept(x.swap(y))); + + // \ref{multiset.erasure}, erasure for \tcode{multiset} + template + constexpr typename multiset::size_type + erase_if(multiset& c, Predicate pred); + + namespace pmr { + template> + using set = std::set>; + + template> + using multiset = std::multiset>; + } +} +\end{codeblock} + +\rSec2[set]{Class template \tcode{set}} + +\rSec3[set.overview]{Overview} + +\pnum +\indexlibraryglobal{set}% +A +\tcode{set} +is an associative container that supports unique keys (i.e., contains at most one of each key value) and +provides for fast retrieval of the keys themselves. +The +\tcode{set} class +supports bidirectional iterators. + +\pnum +A \tcode{set} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an associative container\iref{associative.reqmts}. +A +\tcode{set} +also provides most operations described in~\ref{associative.reqmts} +for unique keys. +This means that a +\tcode{set} +supports the +\tcode{a_uniq} +operations in~\ref{associative.reqmts} +but not the +\tcode{a_eq} +operations. +For a +\tcode{set} +both the +\tcode{key_type} +and +\tcode{value_type} +are +\tcode{Key}. +Descriptions are provided here only for operations on +\tcode{set} +that are not described in one of these tables +and for operations where there is additional semantic information. + +\pnum +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. + +\begin{codeblock} +namespace std { + template, + class Allocator = allocator> + class set { + public: + // types + using key_type = Key; + using key_compare = Compare; + using value_type = Key; + using value_compare = Compare; + using allocator_type = Allocator; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = @\impdefx{type of \tcode{set::size_type}}@; // see \ref{container.requirements} + using difference_type = @\impdefx{type of \tcode{set::difference_type}}@; // see \ref{container.requirements} + using iterator = @\impdefx{type of \tcode{set::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{set::const_iterator}}@; // see \ref{container.requirements} + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using node_type = @\unspec@; + using insert_return_type = @\placeholdernc{insert-return-type}@; + + // \ref{set.cons}, construct/copy/destroy + constexpr set() : set(Compare()) { } + constexpr explicit set(const Compare& comp, const Allocator& = Allocator()); + template + constexpr set(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr set(from_range_t, R&& rg, + const Compare& comp = Compare(), const Allocator& = Allocator()); + constexpr set(const set& x); + constexpr set(set&& x); + constexpr explicit set(const Allocator&); + constexpr set(const set&, const type_identity_t&); + constexpr set(set&&, const type_identity_t&); + constexpr set(initializer_list, + const Compare& = Compare(), const Allocator& = Allocator()); + template + constexpr set(InputIterator first, InputIterator last, const Allocator& a) + : set(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + constexpr set(from_range_t, R&& rg, const Allocator& a)) + : set(from_range, std::forward(rg), Compare(), a) { } + constexpr set(initializer_list il, const Allocator& a) + : set(il, Compare(), a) { } + constexpr ~set(); + constexpr set& operator=(const set& x); + constexpr set& operator=(set&& x) + noexcept(allocator_traits::is_always_equal::value && + is_nothrow_move_assignable_v); + constexpr set& operator=(initializer_list); + constexpr allocator_type get_allocator() const noexcept; + + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; + + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + // capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; + + // \ref{set.modifiers}, modifiers + template constexpr pair emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); + constexpr pair insert(const value_type& x); + constexpr pair insert(value_type&& x); + template constexpr pair insert(K&& x); + constexpr iterator insert(const_iterator position, const value_type& x); + constexpr iterator insert(const_iterator position, value_type&& x); + template constexpr iterator insert(const_iterator position, K&& x); + template + constexpr void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); + constexpr void insert(initializer_list); + + constexpr node_type extract(const_iterator position); + constexpr node_type extract(const key_type& x); + template constexpr node_type extract(K&& x); + constexpr insert_return_type insert(node_type&& nh); + constexpr iterator insert(const_iterator hint, node_type&& nh); + + constexpr iterator erase(iterator position) + requires (!@\libconcept{same_as}@); + constexpr iterator erase(const_iterator position); + constexpr size_type erase(const key_type& x); + template constexpr size_type erase(K&& x); + constexpr iterator erase(const_iterator first, const_iterator last); + constexpr void swap(set&) + noexcept(allocator_traits::is_always_equal::value && + is_nothrow_swappable_v); + constexpr void clear() noexcept; + + template + constexpr void merge(set& source); + template + constexpr void merge(set&& source); + template + constexpr void merge(multiset& source); + template + constexpr void merge(multiset&& source); + + // observers + constexpr key_compare key_comp() const; + constexpr value_compare value_comp() const; + + // set operations + constexpr iterator find(const key_type& x); + constexpr const_iterator find(const key_type& x) const; + template constexpr iterator find(const K& x); + template constexpr const_iterator find(const K& x) const; + + constexpr size_type count(const key_type& x) const; + template constexpr size_type count(const K& x) const; + + constexpr bool contains(const key_type& x) const; + template constexpr bool contains(const K& x) const; + + constexpr iterator lower_bound(const key_type& x); + constexpr const_iterator lower_bound(const key_type& x) const; + template constexpr iterator lower_bound(const K& x); + template constexpr const_iterator lower_bound(const K& x) const; + + constexpr iterator upper_bound(const key_type& x); + constexpr const_iterator upper_bound(const key_type& x) const; + template constexpr iterator upper_bound(const K& x); + template constexpr const_iterator upper_bound(const K& x) const; + + constexpr pair equal_range(const key_type& x); + constexpr pair equal_range(const key_type& x) const; + template + constexpr pair equal_range(const K& x); + template + constexpr pair equal_range(const K& x) const; + }; + + template>, + class Allocator = allocator<@\placeholder{iter-value-type}@>> + set(InputIterator, InputIterator, + 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; + + template + set(InputIterator, InputIterator, Allocator) + -> 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>; +} +\end{codeblock}% +\indexlibrarymember{set}{operator==}% +\indexlibrarymember{set}{operator<} + +\rSec3[set.cons]{Constructors, copy, and assignment} + +\indexlibraryctor{set}% +\begin{itemdecl} +constexpr explicit set(const Compare& comp, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{set} using the specified comparison object and allocator. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexlibraryctor{set}% +\begin{itemdecl} +template + constexpr set(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty +\tcode{set} +using the specified comparison object and allocator, +and inserts elements from the range +\range{first}{last}. + +\pnum +\complexity +Linear in $N$ if the range +\range{first}{last} +is already sorted with respect to \tcode{comp} +and otherwise $N \log N$, +where $N$ is +\tcode{last - first}. +\end{itemdescr} + +\indexlibraryctor{set}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr set(from_range_t, R&& rg, const Compare& comp = Compare(), + const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{set} using the specified comparison object and allocator, +and inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted with respect to \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + +\rSec3[set.erasure]{Erasure} + +\indexlibrarymember{erase_if}{set}% +\begin{itemdecl} +template + constexpr typename set::size_type + erase_if(set& c, Predicate pred); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto original_size = c.size(); +for (auto i = c.begin(), last = c.end(); i != last; ) { + if (pred(*i)) { + i = c.erase(i); + } else { + ++i; + } +} +return original_size - c.size(); +\end{codeblock} +\end{itemdescr} + +\rSec3[set.modifiers]{Modifiers} + +\indexlibrarymember{insert}{set}% +\begin{itemdecl} +template constexpr pair insert(K&& x); +template constexpr iterator insert(const_iterator hint, K&& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The \grammarterm{qualified-id} \tcode{Compare::is_transparent} +is valid and denotes a type. +For the second overload, +\tcode{is_convertible_v} and +\tcode{is_convertible_v} are both \tcode{false}. + +\pnum +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{set} from +\tcode{std::forward(x)}. + +\pnum +\effects +If the set already contains an element that is equivalent to \tcode{x}, +there is no effect. +Otherwise, let \tcode{r} be \tcode{equal_range(x)}. +Constructs an object \tcode{u} of type \tcode{value_type} +with \tcode{std::forward(x)}. +If \tcode{equal_range(u) == r} is \tcode{false}, the behavior is undefined. +Inserts \tcode{u} into \tcode{*this}. + +\pnum +\returns +For the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the set element that is equivalent to \tcode{x}. + +\pnum +\complexity +Logarithmic. +\end{itemdescr} + +\rSec2[multiset]{Class template \tcode{multiset}} + +\rSec3[multiset.overview]{Overview} + +\pnum +\indexlibraryglobal{multiset}% +A +\tcode{multiset} +is an associative container that supports equivalent keys (i.e., possibly contains multiple copies of +the same key value) and provides for fast retrieval of the keys themselves. +The +\tcode{multiset} class +supports bidirectional iterators. + +\pnum +A \tcode{multiset} meets all of the requirements +of a container\iref{container.reqmts}, +of a reversible container\iref{container.rev.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an associative container\iref{associative.reqmts}. +\tcode{multiset} +also provides most operations described in~\ref{associative.reqmts} +for duplicate keys. +This means that a +\tcode{multiset} +supports the +\tcode{a_eq} +operations in~\ref{associative.reqmts} +but not the +\tcode{a_uniq} +operations. +For a +\tcode{multiset} +both the +\tcode{key_type} +and +\tcode{value_type} +are +\tcode{Key}. +Descriptions are provided here only for operations on +\tcode{multiset} +that are not described in one of these tables +and for operations where there is additional semantic information. + +\pnum +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. + +\begin{codeblock} +namespace std { + template, + class Allocator = allocator> + class multiset { + public: + // types + using key_type = Key; + using key_compare = Compare; + using value_type = Key; + using value_compare = Compare; + using allocator_type = Allocator; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = @\impdefx{type of \tcode{multiset::size_type}}@; // see \ref{container.requirements} + using difference_type = @\impdefx{type of \tcode{multiset::difference_type}}@; // see \ref{container.requirements} + using iterator = @\impdefx{type of \tcode{multiset::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{multiset::const_iterator}}@; // see \ref{container.requirements} + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using node_type = @\unspec@; + + // \ref{multiset.cons}, construct/copy/destroy + constexpr multiset() : multiset(Compare()) { } + constexpr explicit multiset(const Compare& comp, const Allocator& = Allocator()); + template + constexpr multiset(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr multiset(from_range_t, R&& rg, + const Compare& comp = Compare(), const Allocator& = Allocator()); + constexpr multiset(const multiset& x); + constexpr multiset(multiset&& x); + constexpr explicit multiset(const Allocator&); + constexpr multiset(const multiset&, const type_identity_t&); + constexpr multiset(multiset&&, const type_identity_t&); + constexpr multiset(initializer_list, const Compare& = Compare(), + const Allocator& = Allocator()); + template + constexpr multiset(InputIterator first, InputIterator last, const Allocator& a) + : multiset(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + constexpr multiset(from_range_t, R&& rg, const Allocator& a)) + : multiset(from_range, std::forward(rg), Compare(), a) { } + constexpr multiset(initializer_list il, const Allocator& a) + : multiset(il, Compare(), a) { } + constexpr ~multiset(); + constexpr multiset& operator=(const multiset& x); + constexpr multiset& operator=(multiset&& x) + noexcept(allocator_traits::is_always_equal::value && + is_nothrow_move_assignable_v); + constexpr multiset& operator=(initializer_list); + constexpr allocator_type get_allocator() const noexcept; + + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; + + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + // capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; + + // modifiers + template constexpr iterator emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); + constexpr iterator insert(const value_type& x); + constexpr iterator insert(value_type&& x); + constexpr iterator insert(const_iterator position, const value_type& x); + constexpr iterator insert(const_iterator position, value_type&& x); + template + constexpr void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); + constexpr void insert(initializer_list); + + constexpr node_type extract(const_iterator position); + constexpr node_type extract(const key_type& x); + template constexpr node_type extract(K&& x); + constexpr iterator insert(node_type&& nh); + constexpr iterator insert(const_iterator hint, node_type&& nh); + + constexpr iterator erase(iterator position) + requires (!@\libconcept{same_as}@); + constexpr iterator erase(const_iterator position); + constexpr size_type erase(const key_type& x); + template constexpr size_type erase(K&& x); + constexpr iterator erase(const_iterator first, const_iterator last); + constexpr void swap(multiset&) + noexcept(allocator_traits::is_always_equal::value && + is_nothrow_swappable_v); + constexpr void clear() noexcept; + + template + constexpr void merge(multiset& source); + template + constexpr void merge(multiset&& source); + template + constexpr void merge(set& source); + template + constexpr void merge(set&& source); + + // observers + constexpr key_compare key_comp() const; + constexpr value_compare value_comp() const; + + // set operations + constexpr iterator find(const key_type& x); + constexpr const_iterator find(const key_type& x) const; + template constexpr iterator find(const K& x); + template constexpr const_iterator find(const K& x) const; + + constexpr size_type count(const key_type& x) const; + template constexpr size_type count(const K& x) const; + + constexpr bool contains(const key_type& x) const; + template constexpr bool contains(const K& x) const; + + constexpr iterator lower_bound(const key_type& x); + constexpr const_iterator lower_bound(const key_type& x) const; + template constexpr iterator lower_bound(const K& x); + template constexpr const_iterator lower_bound(const K& x) const; + + constexpr iterator upper_bound(const key_type& x); + constexpr const_iterator upper_bound(const key_type& x) const; + template constexpr iterator upper_bound(const K& x); + template constexpr const_iterator upper_bound(const K& x) const; + + constexpr pair equal_range(const key_type& x); + constexpr pair equal_range(const key_type& x) const; + template + constexpr pair equal_range(const K& x); + template + constexpr pair equal_range(const K& x) const; + }; + + template>, + class Allocator = allocator<@\placeholder{iter-value-type}@>> + multiset(InputIterator, InputIterator, + 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; + + template + multiset(InputIterator, InputIterator, Allocator) + -> 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>; +} +\end{codeblock}% +\indexlibrarymember{multiset}{operator==}% +\indexlibrarymember{multiset}{operator<} + +\rSec3[multiset.cons]{Constructors} + +\indexlibraryctor{multiset}% +\begin{itemdecl} +constexpr explicit multiset(const Compare& comp, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{multiset} using the specified comparison object and allocator. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexlibraryctor{multiset}% +\begin{itemdecl} +template + constexpr multiset(InputIterator first, InputIterator last, + const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty +\tcode{multiset} +using the specified comparison object and allocator, +and inserts elements from the range +\range{first}{last}. + +\pnum +\complexity +Linear in $N$ +if the range +\range{first}{last} +is already sorted with respect to \tcode{comp} and otherwise $N \log N$, +where $N$ is +\tcode{last - first}. +\end{itemdescr} + +\indexlibraryctor{multiset}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr multiset(from_range_t, R&& rg, const Compare& comp = Compare(), + const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{multiset} +using the specified comparison object and allocator, and +inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted with respect to \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + +\rSec3[multiset.erasure]{Erasure} + +\indexlibrarymember{erase_if}{multiset}% +\begin{itemdecl} +template + constexpr typename multiset::size_type + erase_if(multiset& c, Predicate pred); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto original_size = c.size(); +for (auto i = c.begin(), last = c.end(); i != last; ) { + if (pred(*i)) { + i = c.erase(i); + } else { + ++i; + } +} +return original_size - c.size(); +\end{codeblock} +\end{itemdescr} + +\rSec1[unord]{Unordered associative containers} + +\rSec2[unord.general]{General} + +\pnum +The header \libheaderrefx{unordered_map}{unord.map.syn} defines the class +templates \tcode{unordered_map} and \tcode{unordered_multimap}; +the header \libheaderrefx{unordered_set}{unord.set.syn} defines the class +templates \tcode{unordered_set} and \tcode{unordered_multiset}. + +\pnum +The exposition-only alias templates +\exposid{iter-value-type}, \exposid{iter-key-type}, +\exposid{iter-mapped-type}, \exposid{iter-to\--alloc-type}, +\exposid{range-key-type}, \exposid{range-mapped-type}, +and \exposid{range-to-alloc-type} +defined in \ref{associative.general} may appear in deduction guides for unordered containers. + +\rSec2[unord.map.syn]{Header \tcode{} synopsis} + +\indexheader{unordered_map}% +\indexlibraryglobal{unordered_map}% +\indexlibraryglobal{unordered_multimap}% +\begin{codeblock} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} + +namespace std { + // \ref{unord.map}, class template \tcode{unordered_map} + template, + class Pred = equal_to, + class Alloc = allocator>> + class unordered_map; + + // \ref{unord.multimap}, class template \tcode{unordered_multimap} + template, + class Pred = equal_to, + class Alloc = allocator>> + class unordered_multimap; + + template + constexpr bool operator==(const unordered_map& a, + const unordered_map& b); + + template + constexpr bool operator==(const unordered_multimap& a, + const unordered_multimap& b); + + template + constexpr void swap(unordered_map& x, + unordered_map& y) + noexcept(noexcept(x.swap(y))); + + template + constexpr void swap(unordered_multimap& x, + unordered_multimap& y) + noexcept(noexcept(x.swap(y))); + + // \ref{unord.map.erasure}, erasure for \tcode{unordered_map} + template + constexpr typename unordered_map::size_type + erase_if(unordered_map& c, Predicate pred); + + // \ref{unord.multimap.erasure}, erasure for \tcode{unordered_multimap} + template + constexpr typename unordered_multimap::size_type + erase_if(unordered_multimap& c, Predicate pred); + + namespace pmr { + template, + class Pred = equal_to> + using unordered_map = + std::unordered_map>>; + template, + class Pred = equal_to> + using unordered_multimap = + std::unordered_multimap>>; + + } +} +\end{codeblock} + +\rSec2[unord.map]{Class template \tcode{unordered_map}}% +\indexlibraryglobal{unordered_map} + +\rSec3[unord.map.overview]{Overview} + +\pnum +\indextext{\idxcode{unordered_map}!unique keys}% +\indextext{unordered associative containers!unique keys}% +An \tcode{unordered_map} is an unordered associative container that +supports unique keys (an \tcode{unordered_map} contains at most one of each +key value) and that associates values of another type +\tcode{mapped_type} with the keys. +The \tcode{unordered_map} class +supports forward iterators. + +\pnum +An \tcode{unordered_map} meets all of the requirements +of a container\iref{container.reqmts}, +of an allocator-aware container\iref{container.alloc.reqmts}, and +of an unordered associative container\iref{unord.req}. +It provides the operations described in the preceding requirements table for unique keys; +that is, an \tcode{unordered_map} supports the \tcode{a_uniq} operations in that table, +not the \tcode{a_eq} operations. +For an \tcode{unordered_map} the \tcode{key_type} is \tcode{Key}, +the \tcode{mapped_type} is \tcode{T}, +and the \tcode{value_type} is \tcode{pair}. + +\pnum +Subclause~\ref{unord.map} only describes operations on \tcode{unordered_map} that +are not described in one of the requirement tables, or for which there +is additional semantic information. + +\pnum +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. + +\indexlibraryglobal{unordered_map}% +\begin{codeblock} +namespace std { + template, + class Pred = equal_to, + class Allocator = allocator>> + class unordered_map { + public: + // types + using key_type = Key; + using mapped_type = T; + using value_type = pair; + using hasher = Hash; + using key_equal = Pred; + using allocator_type = Allocator; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = @\impdefx{type of \tcode{unordered_map::size_type}}@; // see \ref{container.requirements} + using difference_type = @\impdefx{type of \tcode{unordered_map::difference_type}}@; // see \ref{container.requirements} + + using iterator = @\impdefx{type of \tcode{unordered_map::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{unordered_map::const_iterator}}@; // see \ref{container.requirements} + using local_iterator = @\impdefx{type of \tcode{unordered_map::local_iterator}}@; // see \ref{container.requirements} + using const_local_iterator = @\impdefx{type of \tcode{unordered_map::const_local_iterator}}@; // see \ref{container.requirements} + using node_type = @\unspec@; + using insert_return_type = @\placeholdernc{insert-return-type}@; + + // \ref{unord.map.cnstr}, construct/copy/destroy + constexpr unordered_map(); + constexpr explicit unordered_map(size_type n, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + template + constexpr unordered_map(InputIterator f, InputIterator l, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + + template<@\exposconcept{container-compatible-range}@ R> + constexpr unordered_map(from_range_t, R&& rg, size_type n = @\seebelow@, + const hasher& hf = hasher(), const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + constexpr unordered_map(const unordered_map&); + constexpr unordered_map(unordered_map&&); + constexpr explicit unordered_map(const Allocator&); + constexpr unordered_map(const unordered_map&, const type_identity_t&); + constexpr unordered_map(unordered_map&&, const type_identity_t&); + constexpr unordered_map(initializer_list il, size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + constexpr unordered_map(size_type n, const allocator_type& a) + : unordered_map(n, hasher(), key_equal(), a) { } + constexpr unordered_map(size_type n, const hasher& hf, const allocator_type& a) + : unordered_map(n, hf, key_equal(), a) { } + template + constexpr unordered_map(InputIterator f, InputIterator l, size_type n, + const allocator_type& a) + : unordered_map(f, l, n, hasher(), key_equal(), a) { } + template + constexpr unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf, + const allocator_type& a) + : unordered_map(f, l, n, hf, key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + constexpr 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> + constexpr 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) { } + constexpr unordered_map(initializer_list il, size_type n, + const allocator_type& a) + : unordered_map(il, n, hasher(), key_equal(), a) { } + constexpr unordered_map(initializer_list il, size_type n, const hasher& hf, + const allocator_type& a) + : unordered_map(il, n, hf, key_equal(), a) { } + constexpr ~unordered_map(); + constexpr unordered_map& operator=(const unordered_map&); + constexpr unordered_map& operator=(unordered_map&&) + noexcept(allocator_traits::is_always_equal::value && + is_nothrow_move_assignable_v && + is_nothrow_move_assignable_v); + constexpr unordered_map& operator=(initializer_list); + constexpr allocator_type get_allocator() const noexcept; + + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + + // capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; + + // \ref{unord.map.modifiers}, modifiers + template constexpr pair emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); + constexpr pair insert(const value_type& obj); + constexpr pair insert(value_type&& obj); + template constexpr pair insert(P&& obj); + constexpr iterator insert(const_iterator hint, const value_type& obj); + constexpr iterator insert(const_iterator hint, value_type&& obj); + template constexpr iterator insert(const_iterator hint, P&& obj); + template constexpr void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); + constexpr void insert(initializer_list); + + constexpr node_type extract(const_iterator position); + constexpr node_type extract(const key_type& x); + template constexpr node_type extract(K&& x); + constexpr insert_return_type insert(node_type&& nh); + constexpr iterator insert(const_iterator hint, node_type&& nh); + + template + constexpr pair try_emplace(const key_type& k, Args&&... args); + template + constexpr pair try_emplace(key_type&& k, Args&&... args); + template + constexpr pair try_emplace(K&& k, Args&&... args); + template + constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); + template + constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); + template + constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args); + template + constexpr pair insert_or_assign(const key_type& k, M&& obj); + template + constexpr pair insert_or_assign(key_type&& k, M&& obj); + template + constexpr pair insert_or_assign(K&& k, M&& obj); + template + constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); + template + constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); + template + constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); + + constexpr iterator erase(iterator position); + constexpr iterator erase(const_iterator position); + constexpr size_type erase(const key_type& k); + template constexpr size_type erase(K&& x); + constexpr iterator erase(const_iterator first, const_iterator last); + constexpr void swap(unordered_map&) + noexcept(allocator_traits::is_always_equal::value && + is_nothrow_swappable_v && is_nothrow_swappable_v); + constexpr void clear() noexcept; + + template + constexpr void merge(unordered_map& source); + template + constexpr void merge(unordered_map&& source); + template + constexpr void merge(unordered_multimap& source); + template + constexpr void merge(unordered_multimap&& source); + + // observers + constexpr hasher hash_function() const; + constexpr key_equal key_eq() const; + + // map operations + constexpr iterator find(const key_type& k); + constexpr const_iterator find(const key_type& k) const; + template + constexpr iterator find(const K& k); + template + constexpr const_iterator find(const K& k) const; + constexpr size_type count(const key_type& k) const; + template + constexpr size_type count(const K& k) const; + constexpr bool contains(const key_type& k) const; + template + constexpr bool contains(const K& k) const; + constexpr pair equal_range(const key_type& k); + constexpr pair equal_range(const key_type& k) const; + template + constexpr pair equal_range(const K& k); + template + constexpr pair equal_range(const K& k) const; + + // \ref{unord.map.elem}, element access + constexpr mapped_type& operator[](const key_type& k); + constexpr mapped_type& operator[](key_type&& k); + template constexpr mapped_type& operator[](K&& k); + constexpr mapped_type& at(const key_type& k); + constexpr const mapped_type& at(const key_type& k) const; + template constexpr mapped_type& at(const K& k); + template constexpr const mapped_type& at(const K& k) const; + + // bucket interface + constexpr size_type bucket_count() const noexcept; + constexpr size_type max_bucket_count() const noexcept; + constexpr size_type bucket_size(size_type n) const; + constexpr size_type bucket(const key_type& k) const; + template constexpr size_type bucket(const K& k) const; + constexpr local_iterator begin(size_type n); + constexpr const_local_iterator begin(size_type n) const; + constexpr local_iterator end(size_type n); + constexpr const_local_iterator end(size_type n) const; + constexpr const_local_iterator cbegin(size_type n) const; + constexpr const_local_iterator cend(size_type n) const; + + // hash policy + constexpr float load_factor() const noexcept; + constexpr float max_load_factor() const noexcept; + constexpr void max_load_factor(float z); + constexpr void rehash(size_type n); + constexpr void reserve(size_type n); + }; + + template>, + class Pred = equal_to<@\placeholder{iter-key-type}@>, + class Allocator = allocator<@\placeholder{iter-to-alloc-type}@>> + unordered_map(InputIterator, InputIterator, typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> 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>, + typename @\seebelow@::size_type = @\seebelow@, Hash = Hash(), + Pred = Pred(), Allocator = Allocator()) + -> unordered_map; + + template + unordered_map(InputIterator, InputIterator, typename @\seebelow@::size_type, Allocator) + -> unordered_map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, + hash<@\placeholder{iter-key-type}@>, + equal_to<@\placeholder{iter-key-type}@>, Allocator>; + + template + unordered_map(InputIterator, InputIterator, Allocator) + -> unordered_map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, + hash<@\placeholder{iter-key-type}@>, + equal_to<@\placeholder{iter-key-type}@>, Allocator>; + + template + unordered_map(InputIterator, InputIterator, typename @\seebelow@::size_type, Hash, Allocator) + -> 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) + -> unordered_map, equal_to, Allocator>; - class value_compare { - friend class multimap; - protected: - Compare comp; - value_compare(Compare c) : comp(c) { } + template + unordered_map(initializer_list>, Allocator) + -> unordered_map, equal_to, Allocator>; - public: - bool operator()(const value_type& x, const value_type& y) const { - return comp(x.first, y.first); - } - }; + template + unordered_map(initializer_list>, typename @\seebelow@::size_type, Hash, + Allocator) + -> unordered_map, Allocator>; +} +\end{codeblock} - // \ref{multimap.cons}, construct/copy/destroy - multimap() : multimap(Compare()) { } - explicit multimap(const Compare& comp, const Allocator& = Allocator()); - template - 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&); - multimap(const multimap&, const type_identity_t&); - multimap(multimap&&, const type_identity_t&); - multimap(initializer_list, - const Compare& = Compare(), - const Allocator& = Allocator()); - 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(); - multimap& operator=(const multimap& x); - multimap& operator=(multimap&& x) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_move_assignable_v); - multimap& operator=(initializer_list); - allocator_type get_allocator() const noexcept; +\pnum +A \tcode{size_type} parameter type in an \tcode{unordered_map} deduction guide +refers to the \tcode{size_type} member type of the type deduced by the deduction guide. - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; +\rSec3[unord.map.cnstr]{Constructors} - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; +\indexlibraryctor{unordered_map}% +\begin{itemdecl} +constexpr unordered_map() : unordered_map(size_type(@\seebelow@)) { } +constexpr explicit unordered_map(size_type n, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); +\end{itemdecl} - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{unordered_map} using the +specified hash function, key equality predicate, and allocator, and +using at least \tcode{n} buckets. For the default constructor, +the number of buckets is \impldef{default number of buckets in +\tcode{unordered_map}}. +\tcode{max_load_factor()} returns \tcode{1.0}. - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; +\pnum +\complexity +Constant. +\end{itemdescr} - // \ref{multimap.modifiers}, modifiers - template iterator emplace(Args&&... args); - template iterator emplace_hint(const_iterator position, Args&&... args); - iterator insert(const value_type& x); - iterator insert(value_type&& x); - template iterator insert(P&& x); - iterator insert(const_iterator position, const value_type& x); - iterator insert(const_iterator position, value_type&& x); - 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); +\indexlibraryctor{unordered_map}% +\begin{itemdecl} +template + constexpr unordered_map(InputIterator f, InputIterator l, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + constexpr unordered_map(from_range_t, R&& rg, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); +constexpr unordered_map(initializer_list il, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); +\end{itemdecl} - node_type extract(const_iterator position); - node_type extract(const key_type& x); - template node_type extract(K&& x); - iterator insert(node_type&& nh); - iterator insert(const_iterator hint, node_type&& nh); - - iterator erase(iterator position); - iterator erase(const_iterator position); - size_type erase(const key_type& x); - template size_type erase(K&& x); - iterator erase(const_iterator first, const_iterator last); - void swap(multimap&) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_swappable_v); - void clear() noexcept; +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{unordered_map} using the +specified hash function, key equality predicate, and allocator, and +using at least \tcode{n} buckets. If \tcode{n} is not +provided, the number of buckets is \impldef{default number of buckets in +\tcode{unordered_map}}. Then +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. +\tcode{max_load_factor()} returns \tcode{1.0}. - template - void merge(multimap& source); - template - void merge(multimap&& source); - template - void merge(map& source); - template - void merge(map&& source); +\pnum +\complexity +Average case linear, worst case quadratic. +\end{itemdescr} - // observers - key_compare key_comp() const; - value_compare value_comp() const; +\rSec3[unord.map.elem]{Element access} - // map operations - iterator find(const key_type& x); - const_iterator find(const key_type& x) const; - template iterator find(const K& x); - template const_iterator find(const K& x) const; +\indexlibrarymember{unordered_map}{operator[]}% +\indextext{\idxcode{unordered_map}!element access}% +\begin{itemdecl} +constexpr mapped_type& operator[](const key_type& k); +\end{itemdecl} - size_type count(const key_type& x) const; - template size_type count(const K& x) const; +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return try_emplace(k).first->second;} +\end{itemdescr} - bool contains(const key_type& x) const; - template bool contains(const K& x) const; +\indexlibrarymember{unordered_map}{operator[]}% +\indextext{\idxcode{unordered_map}!element access}% +\begin{itemdecl} +constexpr mapped_type& operator[](key_type&& k); +\end{itemdecl} - iterator lower_bound(const key_type& x); - const_iterator lower_bound(const key_type& x) const; - template iterator lower_bound(const K& x); - template const_iterator lower_bound(const K& x) const; +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return try_emplace(std::move(k)).first->second;} +\end{itemdescr} - iterator upper_bound(const key_type& x); - const_iterator upper_bound(const key_type& x) const; - template iterator upper_bound(const K& x); - template const_iterator upper_bound(const K& x) const; +\indexlibrarymember{unordered_map}{operator[]}% +\indextext{\idxcode{unordered_map}!element access}% +\begin{itemdecl} +template constexpr mapped_type& operator[](K&& k); +\end{itemdecl} - pair equal_range(const key_type& x); - pair equal_range(const key_type& x) const; - template - pair equal_range(const K& x); - template - pair equal_range(const K& x) const; - }; +\begin{itemdescr} +\pnum +\constraints +The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and +\tcode{Pred::is_transparent} are valid and denote types. - template>, - class Allocator = allocator<@\placeholder{iter-to-alloc-type}@>> - multimap(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) - -> multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, - Compare, Allocator>; +\pnum +\effects +Equivalent to: \tcode{return try_emplace(std::forward(k)).first->second;} +\end{itemdescr} - 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>; +\indexlibrarymember{unordered_map}{at}% +\indextext{\idxcode{unordered_map}!element access}% +\begin{itemdecl} +constexpr mapped_type& at(const key_type& k); +constexpr const mapped_type& at(const key_type& k) const; +\end{itemdecl} - template, - class Allocator = allocator>> - multimap(initializer_list>, Compare = Compare(), Allocator = Allocator()) - -> multimap; +\begin{itemdescr} +\pnum +\returns +A reference to \tcode{x.second}, where \tcode{x} is the (unique) element whose key is equivalent to \tcode{k}. - template - multimap(InputIterator, InputIterator, Allocator) - -> multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, - less<@\placeholder{iter-key-type}@>, Allocator>; +\pnum +\throws +An exception object of type \tcode{out_of_range} if no such element is present. +\end{itemdescr} - template - multimap(from_range_t, R&&, Allocator) - -> multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, less<@\exposid{range-key-type}@>, Allocator>; +\indexlibrarymember{unordered_map}{at}% +\indextext{\idxcode{unordered_map}!element access}% +\begin{itemdecl} +template constexpr mapped_type& at(const K& k); +template constexpr const mapped_type& at(const K& k) const; +\end{itemdecl} - template - multimap(initializer_list>, Allocator) - -> multimap, Allocator>; -} -\end{codeblock}% -\indexlibrarymember{multimap}{operator==}% -\indexlibrarymember{multimap}{operator<} +\begin{itemdescr} +\pnum +\constraints +The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and +\tcode{Pred::is_transparent} are valid and denote types. -\rSec3[multimap.cons]{Constructors} +\pnum +\expects +The expression \tcode{find(k)} is well-formed and has well-defined behavior. -\indexlibraryctor{multimap}% +\pnum +\returns +A reference to \tcode{find(k)->second}. + +\pnum +\throws +An exception object of type \tcode{out_of_range} +if \tcode{find(k) == end()} is \tcode{true}. +\end{itemdescr} + +\rSec3[unord.map.modifiers]{Modifiers} + +\indexlibrarymember{unordered_map}{insert}% \begin{itemdecl} -explicit multimap(const Compare& comp, const Allocator& = Allocator()); +template + constexpr pair insert(P&& obj); \end{itemdecl} \begin{itemdescr} + +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + \pnum \effects -Constructs an empty -\tcode{multimap} -using the specified comparison object and allocator. +Equivalent to: \tcode{return emplace(std::forward

(obj));} +\end{itemdescr} + +\indexlibrarymember{unordered_map}{insert}% +\begin{itemdecl} +template + constexpr iterator insert(const_iterator hint, P&& obj); +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -Constant. +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +Equivalent to: +\tcode{return emplace_hint(hint, std::forward

(obj));} \end{itemdescr} -\indexlibraryctor{multimap}% +\indexlibrarymember{try_emplace}{unordered_map}% \begin{itemdecl} -template - multimap(InputIterator first, InputIterator last, - const Compare& comp = Compare(), - const Allocator& = Allocator()); +template + constexpr pair try_emplace(const key_type& k, Args&&... args); +template + constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{unordered_map} +from \tcode{piecewise_con\-struct}, \tcode{forward_as_tuple(k)}, +\tcode{forward_as_tuple(std::forward(args)...)}. + \pnum \effects -Constructs an empty -\tcode{multimap} -using the specified comparison object and allocator, -and inserts elements from the range -\range{first}{last}. +If the map already contains an element +whose key is equivalent to \tcode{k}, +there is no effect. +Otherwise inserts an object of type \tcode{value_type} +constructed with \tcode{piecewise_construct}, \tcode{forward_as_tuple(k)}, +\tcode{forward_as_tuple(std::forward(args)...)}. + +\pnum +\returns +In the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. \pnum \complexity -Linear in $N$ if the range -\range{first}{last} -is already sorted with respect to \tcode{comp} -and otherwise $N \log N$, -where $N$ is -\tcode{last - first}. +The same as \tcode{emplace} and \tcode{emplace_hint}, +respectively. \end{itemdescr} -\indexlibraryctor{multimap}% +\indexlibrarymember{try_emplace}{unordered_map}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - multimap(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +template + constexpr pair try_emplace(key_type&& k, Args&&... args); +template + constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{unordered_map} +from \tcode{piecewise_con\-struct}, \tcode{forward_as_tuple(std::move(k))}, +\tcode{forward_as_tuple(std::forward(args)...)}. + \pnum \effects -Constructs an empty \tcode{multimap} -using the specified comparison object and allocator, and -inserts elements from the range \tcode{rg}. +If the map already contains an element +whose key is equivalent to \tcode{k}, +there is no effect. +Otherwise inserts an object of type \tcode{value_type} +constructed with \tcode{piecewise_construct}, \tcode{forward_as_tuple(std::move(k))}, +\tcode{forward_as_tuple(std::forward(args)...)}. + +\pnum +\returns +In the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. \pnum \complexity -Linear in $N$ if \tcode{rg} is already sorted with respect to \tcode{comp} and -otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +The same as \tcode{emplace} and \tcode{emplace_hint}, +respectively. \end{itemdescr} -\rSec3[multimap.modifiers]{Modifiers} - -\indexlibrarymember{insert}{multimap}% +\indexlibrarymember{try_emplace}{unordered_map}% \begin{itemdecl} -template iterator insert(P&& x); -template iterator insert(const_iterator position, P&& x); +template + constexpr pair try_emplace(K&& k, Args&&... args); +template + constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_constructible_v} is \tcode{true}. +The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and +\tcode{Pred::is_transparent} are valid and denote types. +For the first overload, +\tcode{is_convertible_v} and +\tcode{is_convertible_v} are both \tcode{false}. + +\pnum +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} +into \tcode{unordered_map} from +\tcode{piecewise_construct, forward_as_tuple(std::forward(k)), +forward_as_tuple(std::forward\newline (args)...)}. \pnum \effects -The first form is equivalent to -\tcode{return emplace(std::forward

(x))}. The second form is -equivalent to \tcode{return emplace_hint(position, std::forward

(x))}. -\end{itemdescr} +If the map already contains an element whose key is equivalent to \tcode{k}, +there is no effect. +Otherwise, let \tcode{h} be \tcode{hash_function()(k)}. +Constructs an object \tcode{u} of type \tcode{value_type} +with \tcode{piecewise_construct, forward_as_tuple(std::forward(k)), +forward_as_tuple(std::forward(args)...)}.\newline +If \tcode{hash_function()(u.first) != h || contains(u.first)} is \tcode{true}, +the behavior is undefined. +Inserts \tcode{u} into \tcode{*this}. -\rSec3[multimap.erasure]{Erasure} +\pnum +\returns +For the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. -\indexlibrarymember{erase_if}{multimap}% +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. +\end{itemdescr} + +\indexlibrarymember{insert_or_assign}{unordered_map}% \begin{itemdecl} -template - typename multimap::size_type - erase_if(multimap& c, Predicate pred); +template + constexpr pair insert_or_assign(const key_type& k, M&& obj); +template + constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -auto original_size = c.size(); -for (auto i = c.begin(), last = c.end(); i != last; ) { - if (pred(*i)) { - i = c.erase(i); - } else { - ++i; - } -} -return original_size - c.size(); -\end{codeblock} -\end{itemdescr} - -\rSec2[set]{Class template \tcode{set}} - -\rSec3[set.overview]{Overview} +\mandates +\tcode{is_assignable_v} is \tcode{true}. \pnum -\indexlibraryglobal{set}% -A -\tcode{set} -is an associative container that supports unique keys (i.e., contains at most one of each key value) and -provides for fast retrieval of the keys themselves. -The -\tcode{set} class -supports bidirectional iterators. +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{unordered_map} +from \tcode{k}, \tcode{std::for\-ward(obj)}. \pnum -A \tcode{set} meets all of the requirements -of a container\iref{container.reqmts}, -of a reversible container\iref{container.rev.reqmts}, -of an allocator-aware container\iref{container.alloc.reqmts}. and -of an associative container\iref{associative.reqmts}. -A -\tcode{set} -also provides most operations described in~\ref{associative.reqmts} -for unique keys. -This means that a -\tcode{set} -supports the -\tcode{a_uniq} -operations in~\ref{associative.reqmts} -but not the -\tcode{a_eq} -operations. -For a -\tcode{set} -both the -\tcode{key_type} -and -\tcode{value_type} -are -\tcode{Key}. -Descriptions are provided here only for operations on -\tcode{set} -that are not described in one of these tables -and for operations where there is additional semantic information. - -\begin{codeblock} -namespace std { - template, - class Allocator = allocator> - class set { - public: - // types - using key_type = Key; - using key_compare = Compare; - using value_type = Key; - using value_compare = Compare; - using allocator_type = Allocator; - using pointer = typename allocator_traits::pointer; - using const_pointer = typename allocator_traits::const_pointer; - using reference = value_type&; - using const_reference = const value_type&; - using size_type = @\impdefx{type of \tcode{set::size_type}}@; // see \ref{container.requirements} - using difference_type = @\impdefx{type of \tcode{set::difference_type}}@; // see \ref{container.requirements} - using iterator = @\impdefx{type of \tcode{set::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{set::const_iterator}}@; // see \ref{container.requirements} - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - using node_type = @\unspec@; - using insert_return_type = @\placeholdernc{insert-return-type}@; - - // \ref{set.cons}, construct/copy/destroy - set() : set(Compare()) { } - explicit set(const Compare& comp, const Allocator& = Allocator()); - 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&); - set(const set&, const type_identity_t&); - set(set&&, const type_identity_t&); - set(initializer_list, const Compare& = Compare(), - const Allocator& = Allocator()); - 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(); - set& operator=(const set& x); - set& operator=(set&& x) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_move_assignable_v); - set& operator=(initializer_list); - allocator_type get_allocator() const noexcept; - - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; - - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; - - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; - - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; - - // \ref{set.modifiers}, modifiers - template pair emplace(Args&&... args); - template iterator emplace_hint(const_iterator position, Args&&... args); - pair insert(const value_type& x); - pair insert(value_type&& x); - template pair insert(K&& x); - iterator insert(const_iterator position, const value_type& x); - iterator insert(const_iterator position, value_type&& x); - template iterator insert(const_iterator position, K&& 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); - node_type extract(const key_type& x); - template node_type extract(K&& x); - insert_return_type insert(node_type&& nh); - iterator insert(const_iterator hint, node_type&& nh); - - iterator erase(iterator position) - requires (!@\libconcept{same_as}@); - iterator erase(const_iterator position); - size_type erase(const key_type& x); - template size_type erase(K&& x); - iterator erase(const_iterator first, const_iterator last); - void swap(set&) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_swappable_v); - void clear() noexcept; - - template - void merge(set& source); - template - void merge(set&& source); - template - void merge(multiset& source); - template - void merge(multiset&& source); - - // observers - key_compare key_comp() const; - value_compare value_comp() const; - - // set operations - iterator find(const key_type& x); - const_iterator find(const key_type& x) const; - template iterator find(const K& x); - template const_iterator find(const K& x) const; - - size_type count(const key_type& x) const; - template size_type count(const K& x) const; - - bool contains(const key_type& x) const; - template bool contains(const K& x) const; - - iterator lower_bound(const key_type& x); - const_iterator lower_bound(const key_type& x) const; - template iterator lower_bound(const K& x); - template const_iterator lower_bound(const K& x) const; - - iterator upper_bound(const key_type& x); - const_iterator upper_bound(const key_type& x) const; - template iterator upper_bound(const K& x); - template const_iterator upper_bound(const K& x) const; - - pair equal_range(const key_type& x); - pair equal_range(const key_type& x) const; - template - pair equal_range(const K& x); - template - pair equal_range(const K& x) const; - }; - - template>, - class Allocator = allocator<@\placeholder{iter-value-type}@>> - set(InputIterator, InputIterator, - 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; - - template - set(InputIterator, InputIterator, Allocator) - -> set<@\placeholder{iter-value-type}@, - less<@\placeholder{iter-value-type}@>, Allocator>; - - template - set(from_range_t, R&&, Allocator) - -> set, less>, Allocator>; +\effects +If the map already contains an element \tcode{e} +whose key is equivalent to \tcode{k}, +assigns \tcode{std::for\-ward(obj)} to \tcode{e.second}. +Otherwise inserts an object of type \tcode{value_type} +constructed with \tcode{k}, \tcode{std::forward(obj)}. - template - set(initializer_list, Allocator) -> set, Allocator>; -} -\end{codeblock}% -\indexlibrarymember{set}{operator==}% -\indexlibrarymember{set}{operator<} +\pnum +\returns +In the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. -\rSec3[set.cons]{Constructors, copy, and assignment} +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, +respectively. +\end{itemdescr} -\indexlibraryctor{set}% +\indexlibrarymember{insert_or_assign}{unordered_map}% \begin{itemdecl} -explicit set(const Compare& comp, const Allocator& = Allocator()); +template + constexpr pair insert_or_assign(key_type&& k, M&& obj); +template + constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); \end{itemdecl} \begin{itemdescr} +\pnum +\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)}. + \pnum \effects -Constructs an empty \tcode{set} using the specified comparison object and allocator. +If the map already contains an element \tcode{e} +whose key is equivalent to \tcode{k}, +assigns \tcode{std::for\-ward(obj)} to \tcode{e.second}. +Otherwise inserts an object of type \tcode{value_type} +constructed with \tcode{std::\brk{}move(k)}, \tcode{std::forward(obj)}. + +\pnum +\returns +In the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. \pnum \complexity -Constant. +The same as \tcode{emplace} and \tcode{emplace_hint}, +respectively. \end{itemdescr} -\indexlibraryctor{set}% +\indexlibrarymember{insert_or_assign}{unordered_map}% \begin{itemdecl} -template - set(InputIterator first, InputIterator last, - const Compare& comp = Compare(), const Allocator& = Allocator()); +template + constexpr pair insert_or_assign(K&& k, M&& obj); +template + constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Constructs an empty -\tcode{set} -using the specified comparison object and allocator, -and inserts elements from the range -\range{first}{last}. +\constraints +The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and +\tcode{Pred::is_transparent} are valid and denote types. \pnum -\complexity -Linear in $N$ if the range -\range{first}{last} -is already sorted with respect to \tcode{comp} -and otherwise $N \log N$, -where $N$ is -\tcode{last - first}. -\end{itemdescr} +\mandates +\tcode{is_assignable_v} is \tcode{true}. -\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} +\pnum +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} +into \tcode{unordered_map} +from \tcode{std::forward\newline (k), std::forward(obj)}. -\begin{itemdescr} \pnum \effects -Constructs an empty \tcode{set} using the specified comparison object and allocator, -and inserts elements from the range \tcode{rg}. +If the map already contains an element \tcode{e} +whose key is equivalent to \tcode{k}, +assigns \tcode{std::forward\newline (obj)} to \tcode{e.second}. +Otherwise, let \tcode{h} be \tcode{hash_function()(k)}. +Constructs an object \tcode{u} of type \tcode{value_type} +with \tcode{std::forward(k), std::forward(obj)}. +If \tcode{hash_function()(u.first) != h || contains(u.first)} is \tcode{true}, +the behavior is undefined. +Inserts \tcode{u} into \tcode{*this}. + +\pnum +\returns +For the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. \pnum \complexity -Linear in $N$ if \tcode{rg} is already sorted with respect to \tcode{comp} and -otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. \end{itemdescr} -\rSec3[set.erasure]{Erasure} +\rSec3[unord.map.erasure]{Erasure} -\indexlibrarymember{erase_if}{set}% +\indexlibrarymember{erase_if}{unordered_map}% \begin{itemdecl} -template - typename set::size_type - erase_if(set& c, Predicate pred); +template + constexpr typename unordered_map::size_type + erase_if(unordered_map& c, Predicate pred); \end{itemdecl} \begin{itemdescr} @@ -11023,455 +14204,426 @@ \end{codeblock} \end{itemdescr} -\rSec3[set.modifiers]{Modifiers} - -\indexlibrarymember{insert}{set}% -\begin{itemdecl} -template pair insert(K&& x); -template iterator insert(const_iterator hint, K&& x); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -The \grammarterm{qualified-id} \tcode{Compare::is_transparent} -is valid and denotes a type. -For the second overload, -\tcode{is_convertible_v} and -\tcode{is_convertible_v} are both \tcode{false}. - -\pnum -\expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{set} from -\tcode{std::forward(x)}. +\rSec2[unord.multimap]{Class template \tcode{unordered_multimap}}% +\indexlibraryglobal{unordered_multimap} -\pnum -\effects -If the set already contains an element that is equivalent to \tcode{x}, -there is no effect. -Otherwise, let \tcode{r} be \tcode{equal_range(x)}. -Constructs an object \tcode{u} of type \tcode{value_type} -with \tcode{std::forward(x)}. -If \tcode{equal_range(u) == r} is \tcode{false}, the behavior is undefined. -Inserts \tcode{u} into \tcode{*this}. +\rSec3[unord.multimap.overview]{Overview} \pnum -\returns -For the first overload, -the \tcode{bool} component of the returned pair is true -if and only if the insertion took place. -The returned iterator points to the set element that is equivalent to \tcode{x}. +\indextext{\idxcode{unordered_multimap}!equivalent keys}% +\indextext{unordered associative containers!equivalent keys}% +An \tcode{unordered_multimap} is an unordered associative container +that supports equivalent keys (an instance of \tcode{unordered_multimap} may contain +multiple copies of each key value) and that associates values of +another type \tcode{mapped_type} with the keys. +The \tcode{unordered_multimap} class +supports forward iterators. \pnum -\complexity -Logarithmic. -\end{itemdescr} - -\rSec2[multiset]{Class template \tcode{multiset}} - -\rSec3[multiset.overview]{Overview} +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 \tcode{mapped_type} is \tcode{T}, +and the \tcode{value_type} is \tcode{pair}. \pnum -\indexlibraryglobal{multiset}% -A -\tcode{multiset} -is an associative container that supports equivalent keys (i.e., possibly contains multiple copies of -the same key value) and provides for fast retrieval of the keys themselves. -The -\tcode{multiset} class -supports bidirectional iterators. +Subclause~\ref{unord.multimap} only describes operations on \tcode{unordered_multimap} +that are not described in one of the requirement tables, or for which +there is additional semantic information. \pnum -A \tcode{multiset} meets all of the requirements -of a container\iref{container.reqmts}, -of a reversible container\iref{container.rev.reqmts}, -of an allocator-aware container\iref{container.alloc.reqmts}, -of an associative container\iref{associative.reqmts}. -\tcode{multiset} -also provides most operations described in~\ref{associative.reqmts} -for duplicate keys. -This means that a -\tcode{multiset} -supports the -\tcode{a_eq} -operations in~\ref{associative.reqmts} -but not the -\tcode{a_uniq} -operations. -For a -\tcode{multiset} -both the -\tcode{key_type} -and -\tcode{value_type} -are -\tcode{Key}. -Descriptions are provided here only for operations on -\tcode{multiset} -that are not described in one of these tables -and for operations where there is additional semantic information. +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. +\indexlibraryglobal{unordered_multimap}% \begin{codeblock} namespace std { - template, - class Allocator = allocator> - class multiset { + template, + class Pred = equal_to, + class Allocator = allocator>> + class unordered_multimap { public: // types - using key_type = Key; - using key_compare = Compare; - using value_type = Key; - using value_compare = Compare; - using allocator_type = Allocator; - using pointer = typename allocator_traits::pointer; - using const_pointer = typename allocator_traits::const_pointer; - using reference = value_type&; - using const_reference = const value_type&; - using size_type = @\impdefx{type of \tcode{multiset::size_type}}@; // see \ref{container.requirements} - using difference_type = @\impdefx{type of \tcode{multiset::difference_type}}@; // see \ref{container.requirements} - using iterator = @\impdefx{type of \tcode{multiset::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{multiset::const_iterator}}@; // see \ref{container.requirements} - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - using node_type = @\unspec@; + using key_type = Key; + using mapped_type = T; + using value_type = pair; + using hasher = Hash; + using key_equal = Pred; + using allocator_type = Allocator; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = @\impdefx{type of \tcode{unordered_multimap::size_type}}@; // see \ref{container.requirements} + using difference_type = @\impdefx{type of \tcode{unordered_multimap::difference_type}}@; // see \ref{container.requirements} - // \ref{multiset.cons}, construct/copy/destroy - multiset() : multiset(Compare()) { } - explicit multiset(const Compare& comp, const Allocator& = Allocator()); + using iterator = @\impdefx{type of \tcode{unordered_multimap::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{unordered_multimap::const_iterator}}@; // see \ref{container.requirements} + using local_iterator = @\impdefx{type of \tcode{unordered_multimap::local_iterator}}@; // see \ref{container.requirements} + using const_local_iterator = @\impdefx{type of \tcode{unordered_multimap::const_local_it\-erator}}@; // see \ref{container.requirements} + using node_type = @\unspec@; + + // \ref{unord.multimap.cnstr}, construct/copy/destroy + constexpr unordered_multimap(); + constexpr explicit unordered_multimap(size_type n, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); template - multiset(InputIterator first, InputIterator last, - const Compare& comp = Compare(), const Allocator& = Allocator()); + constexpr unordered_multimap(InputIterator f, InputIterator l, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); template<@\exposconcept{container-compatible-range}@ R> - multiset(from_range_t, R&& rg, - const Compare& comp = Compare(), const Allocator& = Allocator()); - multiset(const multiset& x); - multiset(multiset&& x); - explicit multiset(const Allocator&); - multiset(const multiset&, const type_identity_t&); - multiset(multiset&&, const type_identity_t&); - multiset(initializer_list, const Compare& = Compare(), - const Allocator& = Allocator()); + constexpr unordered_multimap(from_range_t, R&& rg, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + constexpr unordered_multimap(const unordered_multimap&); + constexpr unordered_multimap(unordered_multimap&&); + constexpr explicit unordered_multimap(const Allocator&); + constexpr unordered_multimap(const unordered_multimap&, const type_identity_t&); + constexpr unordered_multimap(unordered_multimap&&, const type_identity_t&); + constexpr unordered_multimap(initializer_list il, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + constexpr unordered_multimap(size_type n, const allocator_type& a) + : unordered_multimap(n, hasher(), key_equal(), a) { } + constexpr unordered_multimap(size_type n, const hasher& hf, const allocator_type& a) + : unordered_multimap(n, hf, key_equal(), a) { } template - multiset(InputIterator first, InputIterator last, const Allocator& a) - : multiset(first, last, Compare(), a) { } + constexpr unordered_multimap(InputIterator f, InputIterator l, size_type n, + const allocator_type& a) + : unordered_multimap(f, l, n, hasher(), key_equal(), a) { } + template + constexpr unordered_multimap(InputIterator f, InputIterator l, size_type n, + const hasher& hf, const allocator_type& a) + : unordered_multimap(f, l, n, hf, key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + constexpr 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> - 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(); - multiset& operator=(const multiset& x); - multiset& operator=(multiset&& x) + constexpr 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) { } + constexpr unordered_multimap(initializer_list il, size_type n, + const allocator_type& a) + : unordered_multimap(il, n, hasher(), key_equal(), a) { } + constexpr unordered_multimap(initializer_list il, size_type n, const hasher& hf, + const allocator_type& a) + : unordered_multimap(il, n, hf, key_equal(), a) { } + constexpr ~unordered_multimap(); + constexpr unordered_multimap& operator=(const unordered_multimap&); + constexpr unordered_multimap& operator=(unordered_multimap&&) noexcept(allocator_traits::is_always_equal::value && - is_nothrow_move_assignable_v); - multiset& operator=(initializer_list); - allocator_type get_allocator() const noexcept; + is_nothrow_move_assignable_v && is_nothrow_move_assignable_v); + constexpr unordered_multimap& operator=(initializer_list); + constexpr allocator_type get_allocator() const noexcept; // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; - - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; - - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; - // modifiers - template iterator emplace(Args&&... args); - template iterator emplace_hint(const_iterator position, Args&&... args); - iterator insert(const value_type& x); - iterator insert(value_type&& x); - iterator insert(const_iterator position, const value_type& x); - iterator insert(const_iterator position, value_type&& x); - template - void insert(InputIterator first, InputIterator last); + // \ref{unord.multimap.modifiers}, modifiers + template constexpr iterator emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); + constexpr iterator insert(const value_type& obj); + constexpr iterator insert(value_type&& obj); + template constexpr iterator insert(P&& obj); + constexpr iterator insert(const_iterator hint, const value_type& obj); + constexpr iterator insert(const_iterator hint, value_type&& obj); + template constexpr iterator insert(const_iterator hint, P&& obj); + template constexpr 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); - node_type extract(const key_type& x); - template node_type extract(K&& x); - iterator insert(node_type&& nh); - iterator insert(const_iterator hint, node_type&& nh); - - iterator erase(iterator position) - requires (!@\libconcept{same_as}@); - iterator erase(const_iterator position); - size_type erase(const key_type& x); - template size_type erase(K&& x); - iterator erase(const_iterator first, const_iterator last); - void swap(multiset&) + constexpr void insert_range(R&& rg); + constexpr void insert(initializer_list); + + constexpr node_type extract(const_iterator position); + constexpr node_type extract(const key_type& x); + template constexpr node_type extract(K&& x); + constexpr iterator insert(node_type&& nh); + constexpr iterator insert(const_iterator hint, node_type&& nh); + + constexpr iterator erase(iterator position); + constexpr iterator erase(const_iterator position); + constexpr size_type erase(const key_type& k); + template constexpr size_type erase(K&& x); + constexpr iterator erase(const_iterator first, const_iterator last); + constexpr void swap(unordered_multimap&) noexcept(allocator_traits::is_always_equal::value && - is_nothrow_swappable_v); - void clear() noexcept; + is_nothrow_swappable_v && is_nothrow_swappable_v); + constexpr void clear() noexcept; - template - void merge(multiset& source); - template - void merge(multiset&& source); - template - void merge(set& source); - template - void merge(set&& source); + template + constexpr void merge(unordered_multimap& source); + template + constexpr void merge(unordered_multimap&& source); + template + constexpr void merge(unordered_map& source); + template + constexpr void merge(unordered_map&& source); // observers - key_compare key_comp() const; - value_compare value_comp() const; - - // set operations - iterator find(const key_type& x); - const_iterator find(const key_type& x) const; - template iterator find(const K& x); - template const_iterator find(const K& x) const; - - size_type count(const key_type& x) const; - template size_type count(const K& x) const; + constexpr hasher hash_function() const; + constexpr key_equal key_eq() const; - bool contains(const key_type& x) const; - template bool contains(const K& x) const; - - iterator lower_bound(const key_type& x); - const_iterator lower_bound(const key_type& x) const; - template iterator lower_bound(const K& x); - template const_iterator lower_bound(const K& x) const; - - iterator upper_bound(const key_type& x); - const_iterator upper_bound(const key_type& x) const; - template iterator upper_bound(const K& x); - template const_iterator upper_bound(const K& x) const; - - pair equal_range(const key_type& x); - pair equal_range(const key_type& x) const; + // map operations + constexpr iterator find(const key_type& k); + constexpr const_iterator find(const key_type& k) const; template - pair equal_range(const K& x); + constexpr iterator find(const K& k); template - pair equal_range(const K& x) const; + constexpr const_iterator find(const K& k) const; + constexpr size_type count(const key_type& k) const; + template + constexpr size_type count(const K& k) const; + constexpr bool contains(const key_type& k) const; + template + constexpr bool contains(const K& k) const; + constexpr pair equal_range(const key_type& k); + constexpr pair equal_range(const key_type& k) const; + template + constexpr pair equal_range(const K& k); + template + constexpr pair equal_range(const K& k) const; + + // bucket interface + constexpr size_type bucket_count() const noexcept; + constexpr size_type max_bucket_count() const noexcept; + constexpr size_type bucket_size(size_type n) const; + constexpr size_type bucket(const key_type& k) const; + template constexpr size_type bucket(const K& k) const; + constexpr local_iterator begin(size_type n); + constexpr const_local_iterator begin(size_type n) const; + constexpr local_iterator end(size_type n); + constexpr const_local_iterator end(size_type n) const; + constexpr const_local_iterator cbegin(size_type n) const; + constexpr const_local_iterator cend(size_type n) const; + + // hash policy + constexpr float load_factor() const noexcept; + constexpr float max_load_factor() const noexcept; + constexpr void max_load_factor(float z); + constexpr void rehash(size_type n); + constexpr void reserve(size_type n); }; template>, - class Allocator = allocator<@\placeholder{iter-value-type}@>> - multiset(InputIterator, InputIterator, - Compare = Compare(), Allocator = Allocator()) - -> multiset<@\placeholder{iter-value-type}@, Compare, Allocator>; + class Hash = hash<@\placeholder{iter-key-type}@>, + class Pred = equal_to<@\placeholder{iter-key-type}@>, + class Allocator = allocator<@\placeholder{iter-to-alloc-type}@>> + unordered_multimap(InputIterator, InputIterator, + typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, + Hash, Pred, Allocator>; - template>, - class Allocator = allocator>> - multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) - -> multiset, Compare, 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 Allocator = allocator> - multiset(initializer_list, Compare = Compare(), Allocator = Allocator()) - -> multiset; + template, + class Pred = equal_to, class Allocator = allocator>> + unordered_multimap(initializer_list>, + typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multimap; template - multiset(InputIterator, InputIterator, Allocator) - -> multiset<@\placeholder{iter-value-type}@, - less<@\placeholder{iter-value-type}@>, Allocator>; + unordered_multimap(InputIterator, InputIterator, typename @\seebelow@::size_type, Allocator) + -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, + hash<@\placeholder{iter-key-type}@>, + equal_to<@\placeholder{iter-key-type}@>, Allocator>; + + template + unordered_multimap(InputIterator, InputIterator, Allocator) + -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, + hash<@\placeholder{iter-key-type}@>, + equal_to<@\placeholder{iter-key-type}@>, Allocator>; + + template + unordered_multimap(InputIterator, InputIterator, typename @\seebelow@::size_type, Hash, + Allocator) + -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, + equal_to<@\placeholder{iter-key-type}@>, Allocator>; template - multiset(from_range_t, R&&, Allocator) - -> multiset, less>, Allocator>; + 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 - multiset(initializer_list, Allocator) -> multiset, Allocator>; -} -\end{codeblock}% -\indexlibrarymember{multiset}{operator==}% -\indexlibrarymember{multiset}{operator<} + 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>; -\rSec3[multiset.cons]{Constructors} + 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>; -\indexlibraryctor{multiset}% -\begin{itemdecl} -explicit multiset(const Compare& comp, const Allocator& = Allocator()); -\end{itemdecl} + template + unordered_multimap(initializer_list>, typename @\seebelow@::size_type, + Allocator) + -> unordered_multimap, equal_to, Allocator>; -\begin{itemdescr} -\pnum -\effects -Constructs an empty \tcode{multiset} using the specified comparison object and allocator. + template + unordered_multimap(initializer_list>, Allocator) + -> unordered_multimap, equal_to, Allocator>; + + template + unordered_multimap(initializer_list>, typename @\seebelow@::size_type, + Hash, Allocator) + -> unordered_multimap, Allocator>; +} +\end{codeblock} \pnum -\complexity -Constant. -\end{itemdescr} +A \tcode{size_type} parameter type in an \tcode{unordered_multimap} deduction guide +refers to the \tcode{size_type} member type of the type deduced by the deduction guide. -\indexlibraryctor{multiset}% +\rSec3[unord.multimap.cnstr]{Constructors} + +\indexlibraryctor{unordered_multimap}% \begin{itemdecl} -template - multiset(InputIterator first, InputIterator last, - const Compare& comp = Compare(), const Allocator& = Allocator()); +constexpr unordered_multimap() : unordered_multimap(size_type(@\seebelow@)) { } +constexpr explicit unordered_multimap(size_type n, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs an empty -\tcode{multiset} -using the specified comparison object and allocator, -and inserts elements from the range -\range{first}{last}. +Constructs an empty \tcode{unordered_multimap} using the +specified hash function, key equality predicate, and allocator, and +using at least \tcode{n} buckets. For the default constructor, +the number of buckets is \impldef{default number of buckets in +\tcode{unordered_multimap}}. +\tcode{max_load_factor()} returns \tcode{1.0}. \pnum \complexity -Linear in $N$ -if the range -\range{first}{last} -is already sorted with respect to \tcode{comp} and otherwise $N \log N$, -where $N$ is -\tcode{last - first}. +Constant. \end{itemdescr} -\indexlibraryctor{multiset}% +\indexlibraryctor{unordered_multimap}% \begin{itemdecl} +template + constexpr unordered_multimap(InputIterator f, InputIterator l, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); template<@\exposconcept{container-compatible-range}@ R> - multiset(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); + constexpr unordered_multimap(from_range_t, R&& rg, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); +constexpr unordered_multimap(initializer_list il, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs an empty \tcode{multiset} -using the specified comparison object and allocator, and -inserts elements from the range \tcode{rg}. +Constructs an empty \tcode{unordered_multimap} using the +specified hash function, key equality predicate, and allocator, and +using at least \tcode{n} buckets. If \tcode{n} is not +provided, the number of buckets is \impldef{default number of buckets in +\tcode{unordered_multimap}}. Then +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. +\tcode{max_load_factor()} returns \tcode{1.0}. \pnum \complexity -Linear in $N$ if \tcode{rg} is already sorted with respect to \tcode{comp} and -otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +Average case linear, worst case quadratic. \end{itemdescr} -\rSec3[multiset.erasure]{Erasure} +\rSec3[unord.multimap.modifiers]{Modifiers} -\indexlibrarymember{erase_if}{multiset}% +\indexlibrarymember{unordered_multimap}{insert}% \begin{itemdecl} -template - typename multiset::size_type - erase_if(multiset& c, Predicate pred); +template + constexpr iterator insert(P&& obj); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -auto original_size = c.size(); -for (auto i = c.begin(), last = c.end(); i != last; ) { - if (pred(*i)) { - i = c.erase(i); - } else { - ++i; - } -} -return original_size - c.size(); -\end{codeblock} -\end{itemdescr} - -\rSec1[unord]{Unordered associative containers} - -\rSec2[unord.general]{In general} - -\pnum -The header \libheader{unordered_map} defines the class templates -\tcode{unordered_map} and -\tcode{unordered_multimap}; the header \libheader{unordered_set} defines the class templates -\tcode{unordered_set} and \tcode{unordered_multiset}. +\constraints +\tcode{is_constructible_v} is \tcode{true}. \pnum -The exposition-only alias templates -\exposid{iter-value-type}, \exposid{iter-key-type}, -\exposid{iter-mapped-type}, \exposid{iter-to\--alloc-type}, -\exposid{range-key-type}, \exposid{range-mapped-type}, -and \exposid{range-to-alloc-type} -defined in \ref{associative.general} may appear in deduction guides for unordered containers. - -\rSec2[unord.map.syn]{Header \tcode{} synopsis} - -\indexheader{unordered_map}% -\indexlibraryglobal{unordered_map}% -\indexlibraryglobal{unordered_multimap}% -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} - -namespace std { - // \ref{unord.map}, class template \tcode{unordered_map} - template, - class Pred = equal_to, - class Alloc = allocator>> - class unordered_map; - - // \ref{unord.multimap}, class template \tcode{unordered_multimap} - template, - class Pred = equal_to, - class Alloc = allocator>> - class unordered_multimap; - - template - bool operator==(const unordered_map& a, - const unordered_map& b); - - template - bool operator==(const unordered_multimap& a, - const unordered_multimap& b); +\effects +Equivalent to: \tcode{return emplace(std::forward

(obj));} +\end{itemdescr} - template - void swap(unordered_map& x, - unordered_map& y) - noexcept(noexcept(x.swap(y))); +\indexlibrarymember{unordered_multimap}{insert}% +\begin{itemdecl} +template + constexpr iterator insert(const_iterator hint, P&& obj); +\end{itemdecl} - template - void swap(unordered_multimap& x, - unordered_multimap& y) - noexcept(noexcept(x.swap(y))); +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. - // \ref{unord.map.erasure}, erasure for \tcode{unordered_map} - template - typename unordered_map::size_type - erase_if(unordered_map& c, Predicate pred); +\pnum +\effects +Equivalent to: +\tcode{return emplace_hint(hint, std::forward

(obj));} +\end{itemdescr} - // \ref{unord.multimap.erasure}, erasure for \tcode{unordered_multimap} - template - typename unordered_multimap::size_type - erase_if(unordered_multimap& c, Predicate pred); +\rSec3[unord.multimap.erasure]{Erasure} - namespace pmr { - template, - class Pred = equal_to> - using unordered_map = - std::unordered_map>>; - template, - class Pred = equal_to> - using unordered_multimap = - std::unordered_multimap>>; +\indexlibrarymember{erase_if}{unordered_multimap}% +\begin{itemdecl} +template + constexpr typename unordered_multimap::size_type + erase_if(unordered_multimap& c, Predicate pred); +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto original_size = c.size(); +for (auto i = c.begin(), last = c.end(); i != last; ) { + if (pred(*i)) { + i = c.erase(i); + } else { + ++i; } } +return original_size - c.size(); \end{codeblock} +\end{itemdescr} \rSec2[unord.set.syn]{Header \tcode{} synopsis} @@ -11498,31 +14650,31 @@ class unordered_multiset; template - bool operator==(const unordered_set& a, - const unordered_set& b); + constexpr bool operator==(const unordered_set& a, + const unordered_set& b); template - bool operator==(const unordered_multiset& a, - const unordered_multiset& b); + constexpr bool operator==(const unordered_multiset& a, + const unordered_multiset& b); template - void swap(unordered_set& x, - unordered_set& y) + constexpr void swap(unordered_set& x, + unordered_set& y) noexcept(noexcept(x.swap(y))); template - void swap(unordered_multiset& x, - unordered_multiset& y) + constexpr void swap(unordered_multiset& x, + unordered_multiset& y) noexcept(noexcept(x.swap(y))); // \ref{unord.set.erasure}, erasure for \tcode{unordered_set} template - typename unordered_set::size_type + constexpr typename unordered_set::size_type erase_if(unordered_set& c, Predicate pred); // \ref{unord.multiset.erasure}, erasure for \tcode{unordered_multiset} template - typename unordered_multiset::size_type + constexpr typename unordered_multiset::size_type erase_if(unordered_multiset& c, Predicate pred); namespace pmr { @@ -11541,52 +14693,55 @@ } \end{codeblock} -\rSec2[unord.map]{Class template \tcode{unordered_map}}% -\indexlibraryglobal{unordered_map} +\rSec2[unord.set]{Class template \tcode{unordered_set}}% +\indexlibraryglobal{unordered_set} -\rSec3[unord.map.overview]{Overview} +\rSec3[unord.set.overview]{Overview} \pnum -\indextext{\idxcode{unordered_map}!unique keys}% +\indextext{\idxcode{unordered_set}!unique keys}% \indextext{unordered associative containers!unique keys}% -An \tcode{unordered_map} is an unordered associative container that -supports unique keys (an \tcode{unordered_map} contains at most one of each -key value) and that associates values of another type -\tcode{mapped_type} with the keys. -The \tcode{unordered_map} class +An \tcode{unordered_set} is an unordered associative container that +supports unique keys (an \tcode{unordered_set} contains at most one of each +key value) and in which the elements' keys are the elements +themselves. +The \tcode{unordered_set} class supports forward iterators. \pnum -An \tcode{unordered_map} meets all of the requirements +An \tcode{unordered_set} meets all of the requirements of a container\iref{container.reqmts}, of an allocator-aware container\iref{container.alloc.reqmts}, and of an unordered associative container\iref{unord.req}. It provides the operations described in the preceding requirements table for unique keys; -that is, an \tcode{unordered_map} supports the \tcode{a_uniq} operations in that table, +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_map} the \tcode{key_type} is \tcode{Key}, -the \tcode{mapped_type} is \tcode{T}, -and the \tcode{value_type} is \tcode{pair}. +For an \tcode{unordered_set} the \tcode{key_type} +and the \tcode{value_type} are both \tcode{Key}. +The \tcode{iterator} and \tcode{const_iterator} types are both constant iterator types. +It is unspecified whether they are the same type. \pnum -Subclause~\ref{unord.map} only describes operations on \tcode{unordered_map} that +Subclause~\ref{unord.set} only describes operations on \tcode{unordered_set} that are not described in one of the requirement tables, or for which there is additional semantic information. -\indexlibraryglobal{unordered_map}% +\pnum +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. + +\indexlibraryglobal{unordered_set}% \begin{codeblock} namespace std { template, class Pred = equal_to, - class Allocator = allocator>> - class unordered_map { + class Allocator = allocator> + class unordered_set { public: // types using key_type = Key; - using mapped_type = T; - using value_type = pair; + using value_type = Key; using hasher = Hash; using key_equal = Pred; using allocator_type = Allocator; @@ -11594,300 +14749,257 @@ using const_pointer = typename allocator_traits::const_pointer; using reference = value_type&; using const_reference = const value_type&; - using size_type = @\impdefx{type of \tcode{unordered_map::size_type}}@; // see \ref{container.requirements} - using difference_type = @\impdefx{type of \tcode{unordered_map::difference_type}}@; // see \ref{container.requirements} + using size_type = @\impdefx{type of \tcode{unordered_set::size_type}}@; // see \ref{container.requirements} + using difference_type = @\impdefx{type of \tcode{unordered_set::difference_type}}@; // see \ref{container.requirements} - using iterator = @\impdefx{type of \tcode{unordered_map::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{unordered_map::const_iterator}}@; // see \ref{container.requirements} - using local_iterator = @\impdefx{type of \tcode{unordered_map::local_iterator}}@; // see \ref{container.requirements} - using const_local_iterator = @\impdefx{type of \tcode{unordered_map::const_local_iterator}}@; // see \ref{container.requirements} + using iterator = @\impdefx{type of \tcode{unordered_set::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{unordered_set::const_iterator}}@; // see \ref{container.requirements} + using local_iterator = @\impdefx{type of \tcode{unordered_set::local_iterator}}@; // see \ref{container.requirements} + using const_local_iterator = @\impdefx{type of \tcode{unordered_set::const_local_iterator}}@; // see \ref{container.requirements} using node_type = @\unspec@; using insert_return_type = @\placeholdernc{insert-return-type}@; - // \ref{unord.map.cnstr}, construct/copy/destroy - unordered_map(); - explicit unordered_map(size_type n, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); + // \ref{unord.set.cnstr}, construct/copy/destroy + constexpr unordered_set(); + constexpr explicit unordered_set(size_type n, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); template - unordered_map(InputIterator f, InputIterator l, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - + constexpr unordered_set(InputIterator f, InputIterator l, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); template<@\exposconcept{container-compatible-range}@ R> - unordered_map(from_range_t, R&& rg, size_type n = @\seebelow@, - const hasher& hf = hasher(), const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - unordered_map(const unordered_map&); - unordered_map(unordered_map&&); - explicit unordered_map(const Allocator&); - unordered_map(const unordered_map&, const type_identity_t&); - unordered_map(unordered_map&&, const type_identity_t&); - unordered_map(initializer_list il, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - unordered_map(size_type n, const allocator_type& a) - : unordered_map(n, hasher(), key_equal(), a) { } - unordered_map(size_type n, const hasher& hf, const allocator_type& a) - : unordered_map(n, hf, key_equal(), a) { } + constexpr unordered_set(from_range_t, R&& rg, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + constexpr unordered_set(const unordered_set&); + constexpr unordered_set(unordered_set&&); + constexpr explicit unordered_set(const Allocator&); + constexpr unordered_set(const unordered_set&, const type_identity_t&); + constexpr unordered_set(unordered_set&&, const type_identity_t&); + constexpr unordered_set(initializer_list il, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + constexpr unordered_set(size_type n, const allocator_type& a) + : unordered_set(n, hasher(), key_equal(), a) { } + constexpr unordered_set(size_type n, const hasher& hf, const allocator_type& a) + : unordered_set(n, hf, key_equal(), a) { } template - unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a) - : unordered_map(f, l, n, hasher(), key_equal(), a) { } + constexpr unordered_set(InputIterator f, InputIterator l, size_type n, + const allocator_type& a) + : unordered_set(f, l, n, hasher(), key_equal(), a) { } template - 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) { } + constexpr unordered_set(InputIterator f, InputIterator l, size_type n, const hasher& hf, + const allocator_type& a) + : unordered_set(f, l, n, hf, key_equal(), a) { } + constexpr unordered_set(initializer_list il, size_type n, + const allocator_type& a) + : unordered_set(il, n, hasher(), 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) { } + constexpr 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_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, - const allocator_type& a) - : unordered_map(il, n, hf, key_equal(), a) { } - ~unordered_map(); - unordered_map& operator=(const unordered_map&); - unordered_map& operator=(unordered_map&&) + constexpr 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) { } + constexpr unordered_set(initializer_list il, size_type n, const hasher& hf, + const allocator_type& a) + : unordered_set(il, n, hf, key_equal(), a) { } + constexpr ~unordered_set(); + constexpr unordered_set& operator=(const unordered_set&); + constexpr unordered_set& operator=(unordered_set&&) noexcept(allocator_traits::is_always_equal::value && - is_nothrow_move_assignable_v && - is_nothrow_move_assignable_v); - unordered_map& operator=(initializer_list); - allocator_type get_allocator() const noexcept; + is_nothrow_move_assignable_v && is_nothrow_move_assignable_v); + constexpr unordered_set& operator=(initializer_list); + constexpr allocator_type get_allocator() const noexcept; // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; - // \ref{unord.map.modifiers}, modifiers - template pair emplace(Args&&... args); - template iterator emplace_hint(const_iterator position, Args&&... args); - pair insert(const value_type& obj); - pair insert(value_type&& obj); - template pair insert(P&& obj); - iterator insert(const_iterator hint, const value_type& obj); - iterator insert(const_iterator hint, value_type&& obj); - template iterator insert(const_iterator hint, P&& obj); - template void insert(InputIterator first, InputIterator last); + // \ref{unord.set.modifiers}, modifiers + template constexpr pair emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); + constexpr pair insert(const value_type& obj); + constexpr pair insert(value_type&& obj); + template constexpr pair insert(K&& obj); + constexpr iterator insert(const_iterator hint, const value_type& obj); + constexpr iterator insert(const_iterator hint, value_type&& obj); + template constexpr iterator insert(const_iterator hint, K&& obj); + template constexpr void insert(InputIterator first, InputIterator last); template<@\exposconcept{container-compatible-range}@ R> - void insert_range(R&& rg); - void insert(initializer_list); + constexpr void insert_range(R&& rg); + constexpr void insert(initializer_list); - node_type extract(const_iterator position); - node_type extract(const key_type& x); - template node_type extract(K&& x); - insert_return_type insert(node_type&& nh); - iterator insert(const_iterator hint, node_type&& nh); + constexpr node_type extract(const_iterator position); + constexpr node_type extract(const key_type& x); + template constexpr node_type extract(K&& x); + constexpr insert_return_type insert(node_type&& nh); + constexpr iterator insert(const_iterator hint, node_type&& nh); - template - pair try_emplace(const key_type& k, Args&&... args); - template - pair try_emplace(key_type&& k, Args&&... args); - template - pair try_emplace(K&& k, Args&&... args); - template - iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); - template - iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); - template - iterator try_emplace(const_iterator hint, K&& k, Args&&... args); - template - pair insert_or_assign(const key_type& k, M&& obj); - template - pair insert_or_assign(key_type&& k, M&& obj); - template - pair insert_or_assign(K&& k, M&& obj); - template - iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); - template - iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); - template - iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); - - iterator erase(iterator position); - iterator erase(const_iterator position); - size_type erase(const key_type& k); - template size_type erase(K&& x); - iterator erase(const_iterator first, const_iterator last); - void swap(unordered_map&) + constexpr iterator erase(iterator position) + requires (!@\libconcept{same_as}@); + constexpr iterator erase(const_iterator position); + constexpr size_type erase(const key_type& k); + template constexpr size_type erase(K&& x); + constexpr iterator erase(const_iterator first, const_iterator last); + constexpr void swap(unordered_set&) noexcept(allocator_traits::is_always_equal::value && - is_nothrow_swappable_v && - is_nothrow_swappable_v); - void clear() noexcept; + is_nothrow_swappable_v && is_nothrow_swappable_v); + constexpr void clear() noexcept; template - void merge(unordered_map& source); + constexpr void merge(unordered_set& source); template - void merge(unordered_map&& source); + constexpr void merge(unordered_set&& source); template - void merge(unordered_multimap& source); + constexpr void merge(unordered_multiset& source); template - void merge(unordered_multimap&& source); + constexpr void merge(unordered_multiset&& source); // observers - hasher hash_function() const; - key_equal key_eq() const; + constexpr hasher hash_function() const; + constexpr key_equal key_eq() const; - // map operations - iterator find(const key_type& k); - const_iterator find(const key_type& k) const; + // set operations + constexpr iterator find(const key_type& k); + constexpr const_iterator find(const key_type& k) const; template - iterator find(const K& k); + constexpr iterator find(const K& k); template - const_iterator find(const K& k) const; - size_type count(const key_type& k) const; + constexpr const_iterator find(const K& k) const; + constexpr size_type count(const key_type& k) const; template - size_type count(const K& k) const; - bool contains(const key_type& k) const; + constexpr size_type count(const K& k) const; + constexpr bool contains(const key_type& k) const; template - bool contains(const K& k) const; - pair equal_range(const key_type& k); - pair equal_range(const key_type& k) const; + constexpr bool contains(const K& k) const; + constexpr pair equal_range(const key_type& k); + constexpr pair equal_range(const key_type& k) const; template - pair equal_range(const K& k); + constexpr pair equal_range(const K& k); template - pair equal_range(const K& k) const; - - // \ref{unord.map.elem}, element access - mapped_type& operator[](const key_type& k); - mapped_type& operator[](key_type&& k); - template mapped_type& operator[](K&& k); - mapped_type& at(const key_type& k); - const mapped_type& at(const key_type& k) const; - template mapped_type& at(const K& k); - template const mapped_type& at(const K& k) const; + constexpr pair equal_range(const K& k) const; // bucket interface - size_type bucket_count() const noexcept; - size_type max_bucket_count() const noexcept; - size_type bucket_size(size_type n) const; - size_type bucket(const key_type& k) const; - template size_type bucket(const K& k) const; - local_iterator begin(size_type n); - const_local_iterator begin(size_type n) const; - local_iterator end(size_type n); - const_local_iterator end(size_type n) const; - const_local_iterator cbegin(size_type n) const; - const_local_iterator cend(size_type n) const; + constexpr size_type bucket_count() const noexcept; + constexpr size_type max_bucket_count() const noexcept; + constexpr size_type bucket_size(size_type n) const; + constexpr size_type bucket(const key_type& k) const; + template constexpr size_type bucket(const K& k) const; + constexpr local_iterator begin(size_type n); + constexpr const_local_iterator begin(size_type n) const; + constexpr local_iterator end(size_type n); + constexpr const_local_iterator end(size_type n) const; + constexpr const_local_iterator cbegin(size_type n) const; + constexpr const_local_iterator cend(size_type n) const; // hash policy - float load_factor() const noexcept; - float max_load_factor() const noexcept; - void max_load_factor(float z); - void rehash(size_type n); - void reserve(size_type n); + constexpr float load_factor() const noexcept; + constexpr float max_load_factor() const noexcept; + constexpr void max_load_factor(float z); + constexpr void rehash(size_type n); + constexpr void reserve(size_type n); }; template>, - class Pred = equal_to<@\placeholder{iter-key-type}@>, - class Allocator = allocator<@\placeholder{iter-to-alloc-type}@>> - unordered_map(InputIterator, InputIterator, typename @\seebelow@::size_type = @\seebelow@, + class Hash = hash<@\placeholder{iter-value-type}@>, + class Pred = equal_to<@\placeholder{iter-value-type}@>, + class Allocator = allocator<@\placeholder{iter-value-type}@>> + unordered_set(InputIterator, InputIterator, typename @\seebelow@::size_type = @\seebelow@, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) - -> unordered_map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, Pred, - Allocator>; + -> unordered_set<@\placeholder{iter-value-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@, + 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_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Hash, Pred, Allocator>; - - template, - class Pred = equal_to, class Allocator = allocator>> - unordered_map(initializer_list>, - typename @\seebelow@::size_type = @\seebelow@, Hash = Hash(), - Pred = Pred(), Allocator = Allocator()) - -> unordered_map; + -> unordered_set, Hash, Pred, Allocator>; - template - unordered_map(InputIterator, InputIterator, typename @\seebelow@::size_type, Allocator) - -> unordered_map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, - hash<@\placeholder{iter-key-type}@>, - equal_to<@\placeholder{iter-key-type}@>, Allocator>; + template, + class Pred = equal_to, class Allocator = allocator> + unordered_set(initializer_list, typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_set; template - unordered_map(InputIterator, InputIterator, Allocator) - -> unordered_map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, - hash<@\placeholder{iter-key-type}@>, - equal_to<@\placeholder{iter-key-type}@>, Allocator>; + unordered_set(InputIterator, InputIterator, typename @\seebelow@::size_type, Allocator) + -> unordered_set<@\placeholder{iter-value-type}@, + hash<@\placeholder{iter-value-type}@>, + equal_to<@\placeholder{iter-value-type}@>, + Allocator>; template - unordered_map(InputIterator, InputIterator, typename @\seebelow@::size_type, Hash, Allocator) - -> unordered_map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, - equal_to<@\placeholder{iter-key-type}@>, Allocator>; + unordered_set(InputIterator, InputIterator, typename @\seebelow@::size_type, + Hash, Allocator) + -> unordered_set<@\placeholder{iter-value-type}@, Hash, + equal_to<@\placeholder{iter-value-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>; + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_set, hash>, + equal_to>, 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>; + unordered_set(from_range_t, R&&, Allocator) + -> unordered_set, hash>, + equal_to>, 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) - -> unordered_map, equal_to, Allocator>; - - template - unordered_map(initializer_list>, Allocator) - -> unordered_map, equal_to, Allocator>; + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_set, Hash, + equal_to>, Allocator>; - template - unordered_map(initializer_list>, typename @\seebelow@::size_type, Hash, - Allocator) - -> unordered_map, Allocator>; + template + unordered_set(initializer_list, typename @\seebelow@::size_type, Allocator) + -> unordered_set, equal_to, Allocator>; + + template + unordered_set(initializer_list, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_set, Allocator>; } \end{codeblock} \pnum -A \tcode{size_type} parameter type in an \tcode{unordered_map} deduction guide -refers to the \tcode{size_type} member type of the type deduced by the deduction guide. +A \tcode{size_type} parameter type in an \tcode{unordered_set} deduction guide +refers to the \tcode{size_type} member type of +the type deduced by the deduction guide. -\rSec3[unord.map.cnstr]{Constructors} +\rSec3[unord.set.cnstr]{Constructors} -\indexlibraryctor{unordered_map}% +\indexlibraryctor{unordered_set}% \begin{itemdecl} -unordered_map() : unordered_map(size_type(@\seebelow@)) { } -explicit unordered_map(size_type n, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); +constexpr unordered_set() : unordered_set(size_type(@\seebelow@)) { } +constexpr explicit unordered_set(size_type n, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs an empty \tcode{unordered_map} using the +Constructs an empty \tcode{unordered_set} using the specified hash function, key equality predicate, and allocator, and using at least \tcode{n} buckets. For the default constructor, the number of buckets is \impldef{default number of buckets in -\tcode{unordered_map}}. +\tcode{unordered_set}}. \tcode{max_load_factor()} returns \tcode{1.0}. \pnum @@ -11895,35 +15007,32 @@ Constant. \end{itemdescr} -\indexlibraryctor{unordered_map}% +\indexlibraryctor{unordered_set}% \begin{itemdecl} template - unordered_map(InputIterator f, InputIterator l, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); + constexpr unordered_set(InputIterator f, InputIterator l, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); template<@\exposconcept{container-compatible-range}@ 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(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); + constexpr unordered_multiset(from_range_t, R&& rg, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); +constexpr unordered_set(initializer_list il, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs an empty \tcode{unordered_map} using the +Constructs an empty \tcode{unordered_set} using the specified hash function, key equality predicate, and allocator, and using at least \tcode{n} buckets. If \tcode{n} is not provided, the number of buckets is \impldef{default number of buckets in -\tcode{unordered_map}}. Then +\tcode{unordered_set}}. Then inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, respectively. \tcode{max_load_factor()} returns \tcode{1.0}. @@ -11933,36 +15042,38 @@ Average case linear, worst case quadratic. \end{itemdescr} -\rSec3[unord.map.elem]{Element access} +\rSec3[unord.set.erasure]{Erasure} -\indexlibrarymember{unordered_map}{operator[]}% -\indextext{\idxcode{unordered_map}!element access}% +\indexlibrarymember{erase_if}{unordered_set}% \begin{itemdecl} -mapped_type& operator[](const key_type& k); +template + constexpr typename unordered_set::size_type + erase_if(unordered_set& c, Predicate pred); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return try_emplace(k).first->second;} +Equivalent to: +\begin{codeblock} +auto original_size = c.size(); +for (auto i = c.begin(), last = c.end(); i != last; ) { + if (pred(*i)) { + i = c.erase(i); + } else { + ++i; + } +} +return original_size - c.size(); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{unordered_map}{operator[]}% -\indextext{\idxcode{unordered_map}!element access}% -\begin{itemdecl} -mapped_type& operator[](key_type&& k); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return try_emplace(std::move(k)).first->second;} -\end{itemdescr} +\rSec3[unord.set.modifiers]{Modifiers} -\indexlibrarymember{unordered_map}{operator[]}% -\indextext{\idxcode{unordered_map}!element access}% +\indexlibrarymember{insert}{unordered_set}% \begin{itemdecl} -template mapped_type& operator[](K&& k); +template constexpr pair insert(K&& obj); +template constexpr iterator insert(const_iterator hint, K&& obj); \end{itemdecl} \begin{itemdescr} @@ -11970,353 +15081,392 @@ \constraints The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and \tcode{Pred::is_transparent} are valid and denote types. +For the second overload, +\tcode{is_convertible_v} and +\tcode{is_convertible_v} are both \tcode{false}. \pnum -\effects -Equivalent to: \tcode{return try_emplace(std::forward(k)).first->second;} -\end{itemdescr} +\expects +\tcode{value_type} is \oldconcept{EmplaceConstructible} +into \tcode{unordered_set} from \tcode{std::forward\newline (obj)}. -\indexlibrarymember{unordered_map}{at}% -\indextext{\idxcode{unordered_map}!element access}% -\begin{itemdecl} -mapped_type& at(const key_type& k); -const mapped_type& at(const key_type& k) const; -\end{itemdecl} +\pnum +\effects +If the set already contains an element that is equivalent to \tcode{obj}, +there is no effect. +Otherwise, let \tcode{h} be \tcode{hash_function()(obj)}. +Constructs an object \tcode{u} of type \tcode{value_type} +with \tcode{std::forward(obj)}. +If \tcode{hash_function()(u) != h || contains(u)} is \tcode{true}, +the behavior is undefined. +Inserts \tcode{u} into \tcode{*this}. -\begin{itemdescr} \pnum \returns -A reference to \tcode{x.second}, where \tcode{x} is the (unique) element whose key is equivalent to \tcode{k}. +For the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the set element +that is equivalent to \tcode{obj}. \pnum -\throws -An exception object of type \tcode{out_of_range} if no such element is present. +\complexity +Average case constant, worst case linear. \end{itemdescr} -\indexlibrarymember{unordered_map}{at}% -\indextext{\idxcode{unordered_map}!element access}% -\begin{itemdecl} -template mapped_type& at(const K& k); -template const mapped_type& at(const K& k) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and -\tcode{Pred::is_transparent} are valid and denote types. +\rSec2[unord.multiset]{Class template \tcode{unordered_multiset}}% +\indexlibraryglobal{unordered_multiset} -\pnum -\expects -The expression \tcode{find(k)} is well-formed and has well-defined behavior. +\rSec3[unord.multiset.overview]{Overview} \pnum -\returns -A reference to \tcode{find(k)->second}. +\indextext{\idxcode{unordered_multiset}!equivalent keys}% +\indextext{unordered associative containers!equivalent keys}% +An \tcode{unordered_multiset} is an unordered associative container +that supports equivalent keys (an instance of \tcode{unordered_multiset} may contain +multiple copies of the same key value) and in which each element's key +is the element itself. +The \tcode{unordered_multiset} class +supports forward iterators. \pnum -\throws -An exception object of type \tcode{out_of_range} -if \tcode{find(k) == end()} is \tcode{true}. -\end{itemdescr} - -\rSec3[unord.map.modifiers]{Modifiers} - -\indexlibrarymember{unordered_map}{insert}% -\begin{itemdecl} -template - pair insert(P&& obj); -\end{itemdecl} - -\begin{itemdescr} +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 \tcode{value_type} are +both \tcode{Key}. The \tcode{iterator} and \tcode{const_iterator} types are both +constant iterator types. It is unspecified whether they are the same type. \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +Subclause~\ref{unord.multiset} only describes operations on \tcode{unordered_multiset} that +are not described in one of the requirement tables, or for which there +is additional semantic information. \pnum -\effects -Equivalent to: \tcode{return emplace(std::forward

(obj));} -\end{itemdescr} - -\indexlibrarymember{unordered_map}{insert}% -\begin{itemdecl} -template - iterator insert(const_iterator hint, P&& obj); -\end{itemdecl} +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\indexlibraryglobal{unordered_multiset}% +\begin{codeblock} +namespace std { + template, + class Pred = equal_to, + class Allocator = allocator> + class unordered_multiset { + public: + // types + using key_type = Key; + using value_type = Key; + using hasher = Hash; + using key_equal = Pred; + using allocator_type = Allocator; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = @\impdefx{type of \tcode{unordered_multiset::size_type}}@; // see \ref{container.requirements} + using difference_type = @\impdefx{type of \tcode{unordered_multiset::difference_type}}@; // see \ref{container.requirements} -\pnum -\effects -Equivalent to: -\tcode{return emplace_hint(hint, std::forward

(obj));} -\end{itemdescr} + using iterator = @\impdefx{type of \tcode{unordered_multiset::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{unordered_multiset::const_iterator}}@; // see \ref{container.requirements} + using local_iterator = @\impdefx{type of \tcode{unordered_multiset::local_iterator}}@; // see \ref{container.requirements} + using const_local_iterator = @\impdefx{type of \tcode{unordered_multiset::const_local_it\-erator}}@; // see \ref{container.requirements} + using node_type = @\unspec@; -\indexlibrarymember{try_emplace}{unordered_map}% -\begin{itemdecl} -template - pair try_emplace(const key_type& k, Args&&... args); -template - iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); -\end{itemdecl} + // \ref{unord.multiset.cnstr}, construct/copy/destroy + constexpr unordered_multiset(); + constexpr explicit unordered_multiset(size_type n, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + template + constexpr unordered_multiset(InputIterator f, InputIterator l, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr unordered_multiset(from_range_t, R&& rg, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + constexpr unordered_multiset(const unordered_multiset&); + constexpr unordered_multiset(unordered_multiset&&); + constexpr explicit unordered_multiset(const Allocator&); + constexpr unordered_multiset(const unordered_multiset&, const type_identity_t&); + constexpr unordered_multiset(unordered_multiset&&, const type_identity_t&); + constexpr unordered_multiset(initializer_list il, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + constexpr unordered_multiset(size_type n, const allocator_type& a) + : unordered_multiset(n, hasher(), key_equal(), a) { } + constexpr unordered_multiset(size_type n, const hasher& hf, const allocator_type& a) + : unordered_multiset(n, hf, key_equal(), a) { } + template + constexpr unordered_multiset(InputIterator f, InputIterator l, size_type n, + const allocator_type& a) + : unordered_multiset(f, l, n, hasher(), key_equal(), a) { } + template + constexpr unordered_multiset(InputIterator f, InputIterator l, size_type n, + const hasher& hf, const allocator_type& a) + : unordered_multiset(f, l, n, hf, key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + constexpr 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> + constexpr 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) { } + constexpr unordered_multiset(initializer_list il, size_type n, + const allocator_type& a) + : unordered_multiset(il, n, hasher(), key_equal(), a) { } + constexpr unordered_multiset(initializer_list il, size_type n, const hasher& hf, + const allocator_type& a) + : unordered_multiset(il, n, hf, key_equal(), a) { } + constexpr ~unordered_multiset(); + constexpr unordered_multiset& operator=(const unordered_multiset&); + constexpr unordered_multiset& operator=(unordered_multiset&&) + noexcept(allocator_traits::is_always_equal::value && + is_nothrow_move_assignable_v && is_nothrow_move_assignable_v); + constexpr unordered_multiset& operator=(initializer_list); + constexpr allocator_type get_allocator() const noexcept; -\begin{itemdescr} -\pnum -\expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{unordered_map} -from \tcode{piecewise_con\-struct}, \tcode{forward_as_tuple(k)}, -\tcode{forward_as_tuple(std::forward(args)...)}. + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; -\pnum -\effects -If the map already contains an element -whose key is equivalent to \tcode{k}, -there is no effect. -Otherwise inserts an object of type \tcode{value_type} -constructed with \tcode{piecewise_construct}, \tcode{forward_as_tuple(k)}, -\tcode{forward_as_tuple(std::forward(args)...)}. + // capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; -\pnum -\returns -In the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. + // modifiers + template constexpr iterator emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); + constexpr iterator insert(const value_type& obj); + constexpr iterator insert(value_type&& obj); + constexpr iterator insert(const_iterator hint, const value_type& obj); + constexpr iterator insert(const_iterator hint, value_type&& obj); + template constexpr void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); + constexpr void insert(initializer_list); -\pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. -\end{itemdescr} + constexpr node_type extract(const_iterator position); + constexpr node_type extract(const key_type& x); + template constexpr node_type extract(K&& x); + constexpr iterator insert(node_type&& nh); + constexpr iterator insert(const_iterator hint, node_type&& nh); -\indexlibrarymember{try_emplace}{unordered_map}% -\begin{itemdecl} -template - pair try_emplace(key_type&& k, Args&&... args); -template - iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); -\end{itemdecl} + constexpr iterator erase(iterator position) + requires (!@\libconcept{same_as}@); + constexpr iterator erase(const_iterator position); + constexpr size_type erase(const key_type& k); + template constexpr size_type erase(K&& x); + constexpr iterator erase(const_iterator first, const_iterator last); + constexpr void swap(unordered_multiset&) + noexcept(allocator_traits::is_always_equal::value && + is_nothrow_swappable_v && is_nothrow_swappable_v); + constexpr void clear() noexcept; -\begin{itemdescr} -\pnum -\expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{unordered_map} -from \tcode{piecewise_con\-struct}, \tcode{forward_as_tuple(std::move(k))}, -\tcode{forward_as_tuple(std::forward(args)...)}. + template + constexpr void merge(unordered_multiset& source); + template + constexpr void merge(unordered_multiset&& source); + template + constexpr void merge(unordered_set& source); + template + constexpr void merge(unordered_set&& source); -\pnum -\effects -If the map already contains an element -whose key is equivalent to \tcode{k}, -there is no effect. -Otherwise inserts an object of type \tcode{value_type} -constructed with \tcode{piecewise_construct}, \tcode{forward_as_tuple(std::move(k))}, -\tcode{forward_as_tuple(std::forward(args)...)}. + // observers + constexpr hasher hash_function() const; + constexpr key_equal key_eq() const; -\pnum -\returns -In the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. + // set operations + constexpr iterator find(const key_type& k); + constexpr const_iterator find(const key_type& k) const; + template + constexpr iterator find(const K& k); + template + constexpr const_iterator find(const K& k) const; + constexpr size_type count(const key_type& k) const; + template + constexpr size_type count(const K& k) const; + constexpr bool contains(const key_type& k) const; + template + constexpr bool contains(const K& k) const; + constexpr pair equal_range(const key_type& k); + constexpr pair equal_range(const key_type& k) const; + template + constexpr pair equal_range(const K& k); + template + constexpr pair equal_range(const K& k) const; -\pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. -\end{itemdescr} + // bucket interface + constexpr size_type bucket_count() const noexcept; + constexpr size_type max_bucket_count() const noexcept; + constexpr size_type bucket_size(size_type n) const; + constexpr size_type bucket(const key_type& k) const; + template constexpr size_type bucket(const K& k) const; + constexpr local_iterator begin(size_type n); + constexpr const_local_iterator begin(size_type n) const; + constexpr local_iterator end(size_type n); + constexpr const_local_iterator end(size_type n) const; + constexpr const_local_iterator cbegin(size_type n) const; + constexpr const_local_iterator cend(size_type n) const; -\indexlibrarymember{try_emplace}{unordered_map}% -\begin{itemdecl} -template - pair try_emplace(K&& k, Args&&... args); -template - iterator try_emplace(const_iterator hint, K&& k, Args&&... args); -\end{itemdecl} + // hash policy + constexpr float load_factor() const noexcept; + constexpr float max_load_factor() const noexcept; + constexpr void max_load_factor(float z); + constexpr void rehash(size_type n); + constexpr void reserve(size_type n); + }; -\begin{itemdescr} -\pnum -\constraints -The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and -\tcode{Pred::is_transparent} are valid and denote types. -For the first overload, -\tcode{is_convertible_v} and -\tcode{is_convertible_v} are both \tcode{false}. + template>, + class Pred = equal_to<@\placeholder{iter-value-type}@>, + class Allocator = allocator<@\placeholder{iter-value-type}@>> + unordered_multiset(InputIterator, InputIterator, @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multiset<@\placeholder{iter-value-type}@, + Hash, Pred, Allocator>; -\pnum -\expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} -into \tcode{unordered_map} from -\tcode{piecewise_construct, forward_as_tuple(std::forward(k)), -forward_as_tuple(std::forward\newline (args)...)}. + 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>; -\pnum -\effects -If the map already contains an element whose key is equivalent to \tcode{k}, -there is no effect. -Otherwise, let \tcode{h} be \tcode{hash_function()(k)}. -Constructs an object \tcode{u} of type \tcode{value_type} -with \tcode{piecewise_construct, forward_as_tuple(std::forward(k)), -forward_as_tuple(std::forward(args)...)}.\newline -If \tcode{hash_function()(u.first) != h || contains(u.first)} is \tcode{true}, -the behavior is undefined. -Inserts \tcode{u} into \tcode{*this}. + template, + class Pred = equal_to, class Allocator = allocator> + unordered_multiset(initializer_list, typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multiset; -\pnum -\returns -For the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. + template + unordered_multiset(InputIterator, InputIterator, typename @\seebelow@::size_type, Allocator) + -> unordered_multiset<@\placeholder{iter-value-type}@, + hash<@\placeholder{iter-value-type}@>, + equal_to<@\placeholder{iter-value-type}@>, + Allocator>; -\pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. -\end{itemdescr} + template + unordered_multiset(InputIterator, InputIterator, typename @\seebelow@::size_type, + Hash, Allocator) + -> unordered_multiset<@\placeholder{iter-value-type}@, Hash, + equal_to<@\placeholder{iter-value-type}@>, + Allocator>; -\indexlibrarymember{insert_or_assign}{unordered_map}% -\begin{itemdecl} -template - pair insert_or_assign(const key_type& k, M&& obj); -template - iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); -\end{itemdecl} + template + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_multiset, hash>, + equal_to>, Allocator>; -\begin{itemdescr} -\pnum -\mandates -\tcode{is_assignable_v} is \tcode{true}. + template + unordered_multiset(from_range_t, R&&, Allocator) + -> unordered_multiset, hash>, + equal_to>, Allocator>; -\pnum -\expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{unordered_map} -from \tcode{k}, \tcode{std::for\-ward(obj)}. + template + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_multiset, Hash, equal_to>, + Allocator>; -\pnum -\effects -If the map already contains an element \tcode{e} -whose key is equivalent to \tcode{k}, -assigns \tcode{std::for\-ward(obj)} to \tcode{e.second}. -Otherwise inserts an object of type \tcode{value_type} -constructed with \tcode{k}, \tcode{std::forward(obj)}. + template + unordered_multiset(initializer_list, typename @\seebelow@::size_type, Allocator) + -> unordered_multiset, equal_to, Allocator>; -\pnum -\returns -In the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. + template + unordered_multiset(initializer_list, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_multiset, Allocator>; +} +\end{codeblock} \pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. -\end{itemdescr} +A \tcode{size_type} parameter type in an \tcode{unordered_multiset} deduction guide +refers to the \tcode{size_type} member type of +the type deduced by the deduction guide. -\indexlibrarymember{insert_or_assign}{unordered_map}% +\rSec3[unord.multiset.cnstr]{Constructors} + +\indexlibraryctor{unordered_multiset}% \begin{itemdecl} -template - pair insert_or_assign(key_type&& k, M&& obj); -template - iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); +constexpr unordered_multiset() : unordered_multiset(size_type(@\seebelow@)) { } +constexpr explicit unordered_multiset(size_type n, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); \end{itemdecl} \begin{itemdescr} -\pnum -\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)}. - \pnum \effects -If the map already contains an element \tcode{e} -whose key is equivalent to \tcode{k}, -assigns \tcode{std::for\-ward(obj)} to \tcode{e.second}. -Otherwise inserts an object of type \tcode{value_type} -constructed with \tcode{std::\brk{}move(k)}, \tcode{std::forward(obj)}. - -\pnum -\returns -In the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. +Constructs an empty \tcode{unordered_multiset} using the +specified hash function, key equality predicate, and allocator, and +using at least \tcode{n} buckets. For the default constructor, +the number of buckets is \impldef{default number of buckets in +\tcode{unordered_multiset}}. +\tcode{max_load_factor()} returns \tcode{1.0}. \pnum \complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, -respectively. +Constant. \end{itemdescr} -\indexlibrarymember{insert_or_assign}{unordered_map}% +\indexlibraryctor{unordered_multiset}% \begin{itemdecl} -template - pair insert_or_assign(K&& k, M&& obj); -template - iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); +template + constexpr unordered_multiset(InputIterator f, InputIterator l, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + constexpr unordered_multiset(from_range_t, R&& rg, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); +constexpr unordered_multiset(initializer_list il, + size_type n = @\seebelow@, const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and -\tcode{Pred::is_transparent} are valid and denote types. - -\pnum -\mandates -\tcode{is_assignable_v} is \tcode{true}. - -\pnum -\expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} -into \tcode{unordered_map} -from \tcode{std::forward\newline (k), std::forward(obj)}. - \pnum \effects -If the map already contains an element \tcode{e} -whose key is equivalent to \tcode{k}, -assigns \tcode{std::forward\newline (obj)} to \tcode{e.second}. -Otherwise, let \tcode{h} be \tcode{hash_function()(k)}. -Constructs an object \tcode{u} of type \tcode{value_type} -with \tcode{std::forward(k), std::forward(obj)}. -If \tcode{hash_function()(u.first) != h || contains(u.first)} is \tcode{true}, -the behavior is undefined. -Inserts \tcode{u} into \tcode{*this}. - -\pnum -\returns -For the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. +Constructs an empty \tcode{unordered_multiset} using the +specified hash function, key equality predicate, and allocator, and +using at least \tcode{n} buckets. If \tcode{n} is not +provided, the number of buckets is \impldef{default number of buckets in +\tcode{unordered_multiset}}. Then +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. +\tcode{max_load_factor()} returns \tcode{1.0}. \pnum \complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. +Average case linear, worst case quadratic. \end{itemdescr} -\rSec3[unord.map.erasure]{Erasure} +\rSec3[unord.multiset.erasure]{Erasure} -\indexlibrarymember{erase_if}{unordered_map}% +\indexlibrarymember{erase_if}{unordered_multiset}% \begin{itemdecl} -template - typename unordered_map::size_type - erase_if(unordered_map& c, Predicate pred); +template + constexpr typename unordered_multiset::size_type + erase_if(unordered_multiset& c, Predicate pred); \end{itemdecl} \begin{itemdescr} @@ -12336,1378 +15486,1029 @@ \end{codeblock} \end{itemdescr} -\rSec2[unord.multimap]{Class template \tcode{unordered_multimap}}% -\indexlibraryglobal{unordered_multimap} +\rSec1[container.adaptors]{Container adaptors} -\rSec3[unord.multimap.overview]{Overview} +\rSec2[container.adaptors.general]{General} \pnum -\indextext{\idxcode{unordered_multimap}!equivalent keys}% -\indextext{unordered associative containers!equivalent keys}% -An \tcode{unordered_multimap} is an unordered associative container -that supports equivalent keys (an instance of \tcode{unordered_multimap} may contain -multiple copies of each key value) and that associates values of -another type \tcode{mapped_type} with the keys. -The \tcode{unordered_multimap} class -supports forward iterators. +The headers +\libheaderref{queue}, +\libheaderref{stack}, +\libheaderrefx{flat_map}{flat.map.syn}, +and \libheaderrefx{flat_set}{flat.set.syn} +define the container adaptors +\tcode{queue} and \tcode{priority_queue}, +\tcode{stack}, +\tcode{flat_map} and \tcode{flat_multimap}, +and \tcode{flat_set} and \tcode{flat_multiset}, +respectively. \pnum -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 \tcode{mapped_type} is \tcode{T}, -and the \tcode{value_type} is \tcode{pair}. +Each container adaptor takes +one or more template parameters +named \tcode{Container}, \tcode{KeyContainer}, or \tcode{MappedContainer} +that denote the types of containers that the container adaptor adapts. +Each container adaptor has at least one constructor +that takes a reference argument to one or more such template parameters. +For each constructor reference argument to a container \tcode{C}, +the constructor copies the container into the container adaptor. +If \tcode{C} takes an allocator, then a compatible allocator may be passed in +to the adaptor's constructor. Otherwise, normal copy or move construction is used for the container +argument. +For the container adaptors +that take a single container template parameter \tcode{Container}, +the first template parameter \tcode{T} of the container adaptor +shall denote the same type as \tcode{Container::value_type}. \pnum -Subclause~\ref{unord.multimap} only describes operations on \tcode{unordered_multimap} -that are not described in one of the requirement tables, or for which -there is additional semantic information. +For container adaptors, no \tcode{swap} function throws an exception unless that +exception is thrown by the swap of the adaptor's +\tcode{Container}, +\tcode{KeyContainer}, +\tcode{MappedContainer}, or +\tcode{Compare} object (if any). -\indexlibraryglobal{unordered_multimap}% +\pnum +A constructor template of a container adaptor +shall not participate in overload resolution +if it has an \tcode{InputIterator} template parameter and +a type that does not qualify as an input iterator is deduced for that parameter. + +\pnum +For container adaptors that have them, +the \tcode{insert}, \tcode{emplace}, and \tcode{erase} members +affect the validity of iterators, references, and pointers +to the adaptor's container(s) in the same way that +the containers' respective +\tcode{insert}, \tcode{emplace}, and \tcode{erase} members do. +\begin{example} +A call to \tcode{flat_map::insert} +can invalidate all iterators to the \tcode{flat_map}. +\end{example} + +\pnum +A deduction guide for a container adaptor shall not participate in overload resolution if any of the following are true: +\begin{itemize} +\item It has an \tcode{InputIterator} template parameter and a type that does not qualify as an input iterator is deduced for that parameter. +\item It has a \tcode{Compare} template parameter and a type that qualifies as an allocator is deduced for that parameter. +\item It has a \tcode{Container}, \tcode{KeyContainer}, or \tcode{MappedContainer} template parameter and a type that qualifies as an allocator is deduced for that parameter. +\item It has no \tcode{Container}, \tcode{KeyContainer}, or \tcode{MappedContainer} template parameter, and it has an \tcode{Allocator} template parameter, and a type that does not qualify as an allocator is deduced for that parameter. +\item It has both \tcode{Container} and \tcode{Allocator} template parameters, and \tcode{uses_allocator_v} is \tcode{false}. +\item It has both \tcode{KeyContainer} and \tcode{Allocator} template parameters, and +\tcode{uses_allocator_v} is \tcode{false}. +\item It has both \tcode{KeyContainer} and \tcode{Compare} template parameters, and +\begin{codeblock} +is_invocable_v +\end{codeblock} +is not a valid expression or is \tcode{false}. +\item It has both \tcode{MappedContainer} and \tcode{Allocator} template parameters, and +\tcode{uses_allocator_v} is \tcode{false}. +\end{itemize} + +\pnum +The exposition-only alias template \exposid{iter-value-type} +defined in \ref{sequences.general} and +the exposition-only alias templates \exposid{iter-key-type}, \exposid{iter-mapped-type}, +\exposid{range-key-type}, and \exposid{range-mapped-type} +defined in \ref{associative.general} +may appear in deduction guides for container adaptors. + +\pnum +The following exposition-only alias template +may appear in deduction guides for container adaptors: +\begin{codeblock} +template + using @\exposid{alloc-rebind}@ = // \expos + typename allocator_traits::template rebind_alloc; +\end{codeblock} + +\rSec2[queue.syn]{Header \tcode{} synopsis} + +\indexheader{queue} \begin{codeblock} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} + namespace std { - template, - class Pred = equal_to, - class Allocator = allocator>> - class unordered_multimap { + // \ref{queue}, class template \tcode{queue} + template> class queue; + + template + constexpr bool operator==(const queue& x, const queue& y); + template + constexpr bool operator!=(const queue& x, const queue& y); + template + constexpr bool operator< (const queue& x, const queue& y); + template + constexpr bool operator> (const queue& x, const queue& y); + template + constexpr bool operator<=(const queue& x, const queue& y); + template + constexpr bool operator>=(const queue& x, const queue& y); + template + constexpr compare_three_way_result_t + operator<=>(const queue& x, const queue& y); + + template + constexpr void swap(queue& x, queue& y) + noexcept(noexcept(x.swap(y))); + template + struct uses_allocator, Alloc>; + + // \ref{container.adaptors.format}, formatter specialization for \tcode{queue} + template Container> + struct formatter, charT>; + + // \ref{priority.queue}, class template \tcode{priority_queue} + template, + class Compare = less> + class priority_queue; + + template + constexpr void swap(priority_queue& x, + priority_queue& y) noexcept(noexcept(x.swap(y))); + template + struct uses_allocator, Alloc>; + + // \ref{container.adaptors.format}, formatter specialization for \tcode{priority_queue} + template Container, class Compare> + struct formatter, charT>; +} +\end{codeblock} + +\rSec2[queue]{Class template \tcode{queue}} + +\rSec3[queue.defn]{Definition} + +\pnum +\indexlibraryglobal{queue}% +Any sequence container supporting operations +\tcode{front()}, +\tcode{back()}, +\tcode{push_back()} +and +\tcode{pop_front()} +can be used to instantiate +\tcode{queue}. +In particular, +\tcode{list}\iref{list} +and +\tcode{deque}\iref{deque} +can be used. + +\begin{codeblock} +namespace std { + template> + class queue { public: - // types - using key_type = Key; - using mapped_type = T; - using value_type = pair; - using hasher = Hash; - using key_equal = Pred; - using allocator_type = Allocator; - using pointer = typename allocator_traits::pointer; - using const_pointer = typename allocator_traits::const_pointer; - using reference = value_type&; - using const_reference = const value_type&; - using size_type = @\impdefx{type of \tcode{unordered_multimap::size_type}}@; // see \ref{container.requirements} - using difference_type = @\impdefx{type of \tcode{unordered_multimap::difference_type}}@; // see \ref{container.requirements} + using value_type = typename Container::value_type; + using reference = typename Container::reference; + using const_reference = typename Container::const_reference; + using size_type = typename Container::size_type; + using container_type = Container; - using iterator = @\impdefx{type of \tcode{unordered_multimap::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{unordered_multimap::const_iterator}}@; // see \ref{container.requirements} - using local_iterator = @\impdefx{type of \tcode{unordered_multimap::local_iterator}}@; // see \ref{container.requirements} - using const_local_iterator = @\impdefx{type of \tcode{unordered_multimap::const_local_it\-erator}}@; // see \ref{container.requirements} - using node_type = @\unspec@; + protected: + Container c; - // \ref{unord.multimap.cnstr}, construct/copy/destroy - unordered_multimap(); - explicit unordered_multimap(size_type n, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - template - unordered_multimap(InputIterator f, InputIterator l, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - template<@\exposconcept{container-compatible-range}@ R> - unordered_multimap(from_range_t, R&& rg, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - unordered_multimap(const unordered_multimap&); - unordered_multimap(unordered_multimap&&); - explicit unordered_multimap(const Allocator&); - unordered_multimap(const unordered_multimap&, const type_identity_t&); - unordered_multimap(unordered_multimap&&, const type_identity_t&); - unordered_multimap(initializer_list il, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - unordered_multimap(size_type n, const allocator_type& a) - : unordered_multimap(n, hasher(), key_equal(), a) { } - unordered_multimap(size_type n, const hasher& hf, const allocator_type& a) - : unordered_multimap(n, hf, key_equal(), a) { } - template - unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a) - : unordered_multimap(f, l, n, hasher(), key_equal(), a) { } - template - 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, - const allocator_type& a) - : unordered_multimap(il, n, hf, key_equal(), a) { } - ~unordered_multimap(); - unordered_multimap& operator=(const unordered_multimap&); - unordered_multimap& operator=(unordered_multimap&&) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_move_assignable_v && - is_nothrow_move_assignable_v); - unordered_multimap& operator=(initializer_list); - allocator_type get_allocator() const noexcept; + public: + constexpr queue() : queue(Container()) {} + constexpr explicit queue(const Container&); + constexpr explicit queue(Container&&); + template constexpr queue(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> constexpr queue(from_range_t, R&& rg); + template constexpr explicit queue(const Alloc&); + template constexpr queue(const Container&, const Alloc&); + template constexpr queue(Container&&, const Alloc&); + template constexpr queue(const queue&, const Alloc&); + template constexpr queue(queue&&, const Alloc&); + template + constexpr queue(InputIterator first, InputIterator last, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr queue(from_range_t, R&& rg, const Alloc&); + + constexpr bool empty() const { return c.empty(); } + constexpr size_type size() const { return c.size(); } + constexpr reference front() { return c.front(); } + constexpr const_reference front() const { return c.front(); } + constexpr reference back() { return c.back(); } + constexpr const_reference back() const { return c.back(); } + constexpr void push(const value_type& x) { c.push_back(x); } + constexpr void push(value_type&& x) { c.push_back(std::move(x)); } + template<@\exposconcept{container-compatible-range}@ R> constexpr void push_range(R&& rg); + template + constexpr decltype(auto) emplace(Args&&... args) + { return c.emplace_back(std::forward(args)...); } + constexpr void pop() { c.pop_front(); } + constexpr void swap(queue& q) noexcept(is_nothrow_swappable_v) + { using std::swap; swap(c, q.c); } + }; + + template + queue(Container) -> queue; + + template + queue(InputIterator, InputIterator) -> queue<@\exposid{iter-value-type}@>; + + template + queue(from_range_t, R&&) -> queue>; + + template + queue(Container, Allocator) -> queue; + + template + queue(InputIterator, InputIterator, Allocator) + -> 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 { }; +} +\end{codeblock} - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; +\rSec3[queue.cons]{Constructors} - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; +\indexlibraryctor{queue}% +\begin{itemdecl} +constexpr explicit queue(const Container& cont); +\end{itemdecl} - // \ref{unord.multimap.modifiers}, modifiers - template iterator emplace(Args&&... args); - template iterator emplace_hint(const_iterator position, Args&&... args); - iterator insert(const value_type& obj); - iterator insert(value_type&& obj); - template iterator insert(P&& obj); - iterator insert(const_iterator hint, const value_type& obj); - 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); +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{cont}. +\end{itemdescr} - node_type extract(const_iterator position); - node_type extract(const key_type& x); - template node_type extract(K&& x); - iterator insert(node_type&& nh); - iterator insert(const_iterator hint, node_type&& nh); - - iterator erase(iterator position); - iterator erase(const_iterator position); - size_type erase(const key_type& k); - template size_type erase(K&& x); - iterator erase(const_iterator first, const_iterator last); - void swap(unordered_multimap&) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_swappable_v && - is_nothrow_swappable_v); - void clear() noexcept; +\indexlibraryctor{queue}% +\begin{itemdecl} +constexpr explicit queue(Container&& cont); +\end{itemdecl} - template - void merge(unordered_multimap& source); - template - void merge(unordered_multimap&& source); - template - void merge(unordered_map& source); - template - void merge(unordered_map&& source); +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{std::move(cont)}. +\end{itemdescr} - // observers - hasher hash_function() const; - key_equal key_eq() const; +\indexlibraryctor{queue}% +\begin{itemdecl} +template + constexpr queue(InputIterator first, InputIterator last); +\end{itemdecl} - // map operations - iterator find(const key_type& k); - const_iterator find(const key_type& k) const; - template - iterator find(const K& k); - template - const_iterator find(const K& k) const; - size_type count(const key_type& k) const; - template - size_type count(const K& k) const; - bool contains(const key_type& k) const; - template - bool contains(const K& k) const; - pair equal_range(const key_type& k); - pair equal_range(const key_type& k) const; - template - pair equal_range(const K& k); - template - pair equal_range(const K& k) const; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with +\tcode{first} as the first argument and \tcode{last} as the second argument. +\end{itemdescr} - // bucket interface - size_type bucket_count() const noexcept; - size_type max_bucket_count() const noexcept; - size_type bucket_size(size_type n) const; - size_type bucket(const key_type& k) const; - template size_type bucket(const K& k) const; - local_iterator begin(size_type n); - const_local_iterator begin(size_type n) const; - local_iterator end(size_type n); - const_local_iterator end(size_type n) const; - const_local_iterator cbegin(size_type n) const; - const_local_iterator cend(size_type n) const; +\indexlibraryctor{queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr queue(from_range_t, R&& rg); +\end{itemdecl} - // hash policy - float load_factor() const noexcept; - float max_load_factor() const noexcept; - void max_load_factor(float z); - void rehash(size_type n); - void reserve(size_type n); - }; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{ranges::to(std::forward(rg))}. +\end{itemdescr} - template>, - class Pred = equal_to<@\placeholder{iter-key-type}@>, - class Allocator = allocator<@\placeholder{iter-to-alloc-type}@>> - unordered_multimap(InputIterator, InputIterator, - typename @\seebelow@::size_type = @\seebelow@, - Hash = Hash(), Pred = Pred(), Allocator = Allocator()) - -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, - Hash, Pred, Allocator>; +\rSec3[queue.cons.alloc]{Constructors with allocators} - 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>; +\pnum +If \tcode{uses_allocator_v} is \tcode{false} +the constructors in this subclause shall not participate in overload resolution. - template, - class Pred = equal_to, class Allocator = allocator>> - unordered_multimap(initializer_list>, - typename @\seebelow@::size_type = @\seebelow@, - Hash = Hash(), Pred = Pred(), Allocator = Allocator()) - -> unordered_multimap; +\indexlibraryctor{queue}% +\begin{itemdecl} +template constexpr explicit queue(const Alloc& a); +\end{itemdecl} - template - unordered_multimap(InputIterator, InputIterator, typename @\seebelow@::size_type, Allocator) - -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, - hash<@\placeholder{iter-key-type}@>, - equal_to<@\placeholder{iter-key-type}@>, Allocator>; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{a}. +\end{itemdescr} - template - unordered_multimap(InputIterator, InputIterator, Allocator) - -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, - hash<@\placeholder{iter-key-type}@>, - equal_to<@\placeholder{iter-key-type}@>, Allocator>; +\indexlibraryctor{queue}% +\begin{itemdecl} +template constexpr queue(const container_type& cont, const Alloc& a); +\end{itemdecl} - template - unordered_multimap(InputIterator, InputIterator, typename @\seebelow@::size_type, Hash, - Allocator) - -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, - equal_to<@\placeholder{iter-key-type}@>, Allocator>; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a} +as the second argument. +\end{itemdescr} - 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>; +\indexlibraryctor{queue}% +\begin{itemdecl} +template constexpr queue(container_type&& cont, const Alloc& a); +\end{itemdecl} - 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>; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{std::move(cont)} as the first argument and \tcode{a} +as the second argument. +\end{itemdescr} - 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>; +\indexlibraryctor{queue}% +\begin{itemdecl} +template constexpr queue(const queue& q, const Alloc& a); +\end{itemdecl} - template - unordered_multimap(initializer_list>, typename @\seebelow@::size_type, - Allocator) - -> unordered_multimap, equal_to, Allocator>; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{q.c} as the first argument and \tcode{a} as the +second argument. +\end{itemdescr} - template - unordered_multimap(initializer_list>, Allocator) - -> unordered_multimap, equal_to, Allocator>; +\indexlibraryctor{queue}% +\begin{itemdecl} +template constexpr queue(queue&& q, const Alloc& a); +\end{itemdecl} - template - unordered_multimap(initializer_list>, typename @\seebelow@::size_type, - Hash, Allocator) - -> unordered_multimap, Allocator>; -} -\end{codeblock} +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{std::move(q.c)} as the first argument and \tcode{a} +as the second argument. +\end{itemdescr} + +\indexlibraryctor{queue}% +\begin{itemdecl} +template + constexpr queue(InputIterator first, InputIterator last, const Alloc& alloc); +\end{itemdecl} +\begin{itemdescr} \pnum -A \tcode{size_type} parameter type in an \tcode{unordered_multimap} deduction guide -refers to the \tcode{size_type} member type of the type deduced by the deduction guide. +\effects +Initializes \tcode{c} with +\tcode{first} as the first argument, +\tcode{last} as the second argument, and +\tcode{alloc} as the third argument. +\end{itemdescr} -\rSec3[unord.multimap.cnstr]{Constructors} +\indexlibraryctor{queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr queue(from_range_t, R&& rg, const Alloc& a); +\end{itemdecl} -\indexlibraryctor{unordered_multimap}% +\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} -unordered_multimap() : unordered_multimap(size_type(@\seebelow@)) { } -explicit unordered_multimap(size_type n, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + constexpr void push_range(R&& rg); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs an empty \tcode{unordered_multimap} using the -specified hash function, key equality predicate, and allocator, and -using at least \tcode{n} buckets. For the default constructor, -the number of buckets is \impldef{default number of buckets in -\tcode{unordered_multimap}}. -\tcode{max_load_factor()} returns \tcode{1.0}. +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}% +\begin{itemdecl} +template + constexpr bool operator==(const queue& x, const queue& y); +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -Constant. +\returns +\tcode{x.c == y.c}. \end{itemdescr} -\indexlibraryctor{unordered_multimap}% +\indexlibrary{\idxcode{operator"!=}!\idxcode{queue}}% \begin{itemdecl} -template - unordered_multimap(InputIterator f, InputIterator l, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); -template<@\exposconcept{container-compatible-range}@ 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(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); +template + constexpr bool operator!=(const queue& x, const queue& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Constructs an empty \tcode{unordered_multimap} using the -specified hash function, key equality predicate, and allocator, and -using at least \tcode{n} buckets. If \tcode{n} is not -provided, the number of buckets is \impldef{default number of buckets in -\tcode{unordered_multimap}}. Then -inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, -respectively. -\tcode{max_load_factor()} returns \tcode{1.0}. +\returns +\tcode{x.c != y.c}. +\end{itemdescr} + +\indexlibrarymember{operator<}{queue}% +\begin{itemdecl} +template + constexpr bool operator< (const queue& x, const queue& y); +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -Average case linear, worst case quadratic. +\returns +\tcode{x.c < y.c}. \end{itemdescr} -\rSec3[unord.multimap.modifiers]{Modifiers} - -\indexlibrarymember{unordered_multimap}{insert}% +\indexlibrarymember{operator>}{queue}% \begin{itemdecl} -template - iterator insert(P&& obj); +template + constexpr bool operator> (const queue& x, const queue& y); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return emplace(std::forward

(obj));} +\returns +\tcode{x.c > y.c}. \end{itemdescr} -\indexlibrarymember{unordered_multimap}{insert}% +\indexlibrarymember{operator<=}{queue}% \begin{itemdecl} -template - iterator insert(const_iterator hint, P&& obj); +template + constexpr bool operator<=(const queue& x, const queue& y); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\returns +\tcode{x.c <= y.c}. +\end{itemdescr} + +\indexlibrarymember{operator>=}{queue}% +\begin{itemdecl} +template + constexpr bool operator>=(const queue& x, const queue& y); +\end{itemdecl} +\begin{itemdescr} \pnum -\effects -Equivalent to: -\tcode{return emplace_hint(hint, std::forward

(obj));} +\returns +\tcode{x.c >= y.c}. \end{itemdescr} -\rSec3[unord.multimap.erasure]{Erasure} - -\indexlibrarymember{erase_if}{unordered_multimap}% +\indexlibrarymember{operator<=>}{queue}% \begin{itemdecl} -template - typename unordered_multimap::size_type - erase_if(unordered_multimap& c, Predicate pred); +template + constexpr compare_three_way_result_t + operator<=>(const queue& x, const queue& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -auto original_size = c.size(); -for (auto i = c.begin(), last = c.end(); i != last; ) { - if (pred(*i)) { - i = c.erase(i); - } else { - ++i; - } -} -return original_size - c.size(); -\end{codeblock} +\returns +\tcode{x.c <=> y.c}. \end{itemdescr} -\rSec2[unord.set]{Class template \tcode{unordered_set}}% -\indexlibraryglobal{unordered_set} +\rSec3[queue.special]{Specialized algorithms} -\rSec3[unord.set.overview]{Overview} +\indexlibrarymember{swap}{queue}% +\begin{itemdecl} +template + constexpr void swap(queue& x, queue& y) + noexcept(noexcept(x.swap(y))); +\end{itemdecl} +\begin{itemdescr} \pnum -\indextext{\idxcode{unordered_set}!unique keys}% -\indextext{unordered associative containers!unique keys}% -An \tcode{unordered_set} is an unordered associative container that -supports unique keys (an \tcode{unordered_set} contains at most one of each -key value) and in which the elements' keys are the elements -themselves. -The \tcode{unordered_set} class -supports forward iterators. +\constraints +\tcode{is_swappable_v} is \tcode{true}. \pnum -An \tcode{unordered_set} meets all of the requirements -of a container\iref{container.reqmts}, -of an allocator-aware container\iref{container.alloc.reqmts}, -of an unordered associative container\iref{unord.req}. -It provides the operations described in the preceding requirements table for unique keys; -that is, an \tcode{unordered_set} supports the \tcode{a_uniq} operations in that table, -not the \tcode{a_eq} operations. -For an \tcode{unordered_set} the \tcode{key_type} -and the \tcode{value_type} are both \tcode{Key}. -The \tcode{iterator} and \tcode{const_iterator} types are both constant iterator types. -It is unspecified whether they are the same type. +\effects +As if by \tcode{x.swap(y)}. +\end{itemdescr} + +\rSec2[priority.queue]{Class template \tcode{priority_queue}} + +\rSec3[priqueue.overview]{Overview} \pnum -Subclause~\ref{unord.set} only describes operations on \tcode{unordered_set} that -are not described in one of the requirement tables, or for which there -is additional semantic information. +\indexlibraryglobal{priority_queue}% +Any sequence container with random access iterator and supporting operations +\tcode{front()}, +\tcode{push_back()} +and +\tcode{pop_back()} +can be used to instantiate +\tcode{priority_queue}. +In particular, +\tcode{vector}\iref{vector} +and +\tcode{deque}\iref{deque} +can be used. +Instantiating +\tcode{priority_queue} +also involves supplying a function or function object for making +priority comparisons; the library assumes that the function or function +object defines a strict weak ordering\iref{alg.sorting}. -\indexlibraryglobal{unordered_set}% \begin{codeblock} namespace std { - template, - class Pred = equal_to, - class Allocator = allocator> - class unordered_set { + template, + class Compare = less> + class priority_queue { public: - // types - using key_type = Key; - using value_type = Key; - using hasher = Hash; - using key_equal = Pred; - using allocator_type = Allocator; - using pointer = typename allocator_traits::pointer; - using const_pointer = typename allocator_traits::const_pointer; - using reference = value_type&; - using const_reference = const value_type&; - using size_type = @\impdefx{type of \tcode{unordered_set::size_type}}@; // see \ref{container.requirements} - using difference_type = @\impdefx{type of \tcode{unordered_set::difference_type}}@; // see \ref{container.requirements} + using value_type = typename Container::value_type; + using reference = typename Container::reference; + using const_reference = typename Container::const_reference; + using size_type = typename Container::size_type; + using container_type = Container; + using value_compare = Compare; - using iterator = @\impdefx{type of \tcode{unordered_set::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{unordered_set::const_iterator}}@; // see \ref{container.requirements} - using local_iterator = @\impdefx{type of \tcode{unordered_set::local_iterator}}@; // see \ref{container.requirements} - using const_local_iterator = @\impdefx{type of \tcode{unordered_set::const_local_iterator}}@; // see \ref{container.requirements} - using node_type = @\unspec@; - using insert_return_type = @\placeholdernc{insert-return-type}@; + protected: + Container c; + Compare comp; - // \ref{unord.set.cnstr}, construct/copy/destroy - unordered_set(); - explicit unordered_set(size_type n, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); + public: + constexpr priority_queue() : priority_queue(Compare()) {} + constexpr explicit priority_queue(const Compare& x) : priority_queue(x, Container()) {} + constexpr priority_queue(const Compare& x, const Container&); + constexpr priority_queue(const Compare& x, Container&&); template - unordered_set(InputIterator f, InputIterator l, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - template<@\exposconcept{container-compatible-range}@ R> - unordered_set(from_range_t, R&& rg, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - unordered_set(const unordered_set&); - unordered_set(unordered_set&&); - explicit unordered_set(const Allocator&); - unordered_set(const unordered_set&, const type_identity_t&); - unordered_set(unordered_set&&, const type_identity_t&); - unordered_set(initializer_list il, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - unordered_set(size_type n, const allocator_type& a) - : unordered_set(n, hasher(), key_equal(), a) { } - unordered_set(size_type n, const hasher& hf, const allocator_type& a) - : unordered_set(n, hf, key_equal(), a) { } + constexpr priority_queue(InputIterator first, InputIterator last, + const Compare& x = Compare()); template - unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a) - : unordered_set(f, l, n, hasher(), key_equal(), a) { } + constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x, + const Container&); template - unordered_set(InputIterator f, InputIterator l, size_type n, const hasher& hf, - const allocator_type& a) - : unordered_set(f, l, n, hf, key_equal(), a) { } - unordered_set(initializer_list 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) { } - ~unordered_set(); - unordered_set& operator=(const unordered_set&); - unordered_set& operator=(unordered_set&&) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_move_assignable_v && - is_nothrow_move_assignable_v); - unordered_set& operator=(initializer_list); - allocator_type get_allocator() const noexcept; - - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; - - // \ref{unord.set.modifiers}, modifiers - template pair emplace(Args&&... args); - template iterator emplace_hint(const_iterator position, Args&&... args); - pair insert(const value_type& obj); - pair insert(value_type&& obj); - template pair insert(K&& obj); - iterator insert(const_iterator hint, const value_type& obj); - iterator insert(const_iterator hint, value_type&& obj); - template iterator insert(const_iterator hint, K&& 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); - node_type extract(const key_type& x); - template node_type extract(K&& x); - insert_return_type insert(node_type&& nh); - iterator insert(const_iterator hint, node_type&& nh); - - iterator erase(iterator position) - requires (!@\libconcept{same_as}@); - iterator erase(const_iterator position); - size_type erase(const key_type& k); - template size_type erase(K&& x); - iterator erase(const_iterator first, const_iterator last); - void swap(unordered_set&) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_swappable_v && - is_nothrow_swappable_v); - void clear() noexcept; - - template - void merge(unordered_set& source); - template - void merge(unordered_set&& source); - template - void merge(unordered_multiset& source); - template - void merge(unordered_multiset&& source); - - // observers - hasher hash_function() const; - key_equal key_eq() const; - - // set operations - iterator find(const key_type& k); - const_iterator find(const key_type& k) const; - template - iterator find(const K& k); - template - const_iterator find(const K& k) const; - size_type count(const key_type& k) const; - template - size_type count(const K& k) const; - bool contains(const key_type& k) const; - template - bool contains(const K& k) const; - pair equal_range(const key_type& k); - pair equal_range(const key_type& k) const; - template - pair equal_range(const K& k); - template - pair equal_range(const K& k) const; - - // bucket interface - size_type bucket_count() const noexcept; - size_type max_bucket_count() const noexcept; - size_type bucket_size(size_type n) const; - size_type bucket(const key_type& k) const; - template size_type bucket(const K& k) const; - local_iterator begin(size_type n); - const_local_iterator begin(size_type n) const; - local_iterator end(size_type n); - const_local_iterator end(size_type n) const; - const_local_iterator cbegin(size_type n) const; - const_local_iterator cend(size_type n) const; + constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x, + Container&&); + template<@\exposconcept{container-compatible-range}@ R> + constexpr priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); + template constexpr explicit priority_queue(const Alloc&); + template constexpr priority_queue(const Compare&, const Alloc&); + template + constexpr priority_queue(const Compare&, const Container&, const Alloc&); + template constexpr priority_queue(const Compare&, Container&&, const Alloc&); + template constexpr priority_queue(const priority_queue&, const Alloc&); + template constexpr priority_queue(priority_queue&&, const Alloc&); + template + constexpr priority_queue(InputIterator, InputIterator, const Alloc&); + template + constexpr priority_queue(InputIterator, InputIterator, const Compare&, const Alloc&); + template + constexpr priority_queue(InputIterator, InputIterator, const Compare&, const Container&, + const Alloc&); + template + constexpr priority_queue(InputIterator, InputIterator, const Compare&, Container&&, + const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr priority_queue(from_range_t, R&& rg, const Compare&, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr priority_queue(from_range_t, R&& rg, const Alloc&); - // hash policy - float load_factor() const noexcept; - float max_load_factor() const noexcept; - void max_load_factor(float z); - void rehash(size_type n); - void reserve(size_type n); + constexpr bool empty() const { return c.empty(); } + constexpr size_type size() const { return c.size(); } + constexpr const_reference top() const { return c.front(); } + constexpr void push(const value_type& x); + constexpr void push(value_type&& x); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void push_range(R&& rg); + template constexpr void emplace(Args&&... args); + constexpr void pop(); + constexpr void swap(priority_queue& q) + noexcept(is_nothrow_swappable_v && is_nothrow_swappable_v) + { using std::swap; swap(c, q.c); swap(comp, q.comp); } }; + template + priority_queue(Compare, Container) + -> priority_queue; + template>, - class Pred = equal_to<@\placeholder{iter-value-type}@>, - class Allocator = allocator<@\placeholder{iter-value-type}@>> - unordered_set(InputIterator, InputIterator, typename @\seebelow@::size_type = @\seebelow@, - Hash = Hash(), Pred = Pred(), Allocator = Allocator()) - -> unordered_set<@\placeholder{iter-value-type}@, - Hash, Pred, Allocator>; + class Compare = less<@\exposid{iter-value-type}@>, + class Container = vector<@\exposid{iter-value-type}@>> + priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) + -> priority_queue<@\exposid{iter-value-type}@, Container, Compare>; - 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>> + priority_queue(from_range_t, R&&, Compare = Compare()) + -> priority_queue, vector>, Compare>; - template, - class Pred = equal_to, class Allocator = allocator> - unordered_set(initializer_list, typename @\seebelow@::size_type = @\seebelow@, - Hash = Hash(), Pred = Pred(), Allocator = Allocator()) - -> unordered_set; + template + priority_queue(Compare, Container, Allocator) + -> priority_queue; template - unordered_set(InputIterator, InputIterator, typename @\seebelow@::size_type, Allocator) - -> unordered_set<@\placeholder{iter-value-type}@, - hash<@\placeholder{iter-value-type}@>, - equal_to<@\placeholder{iter-value-type}@>, - Allocator>; + priority_queue(InputIterator, InputIterator, Allocator) + -> priority_queue<@\exposid{iter-value-type}@, + vector<@\exposid{iter-value-type}@, Allocator>, + less<@\exposid{iter-value-type}@>>; - template - unordered_set(InputIterator, InputIterator, typename @\seebelow@::size_type, - Hash, Allocator) - -> unordered_set<@\placeholder{iter-value-type}@, Hash, - equal_to<@\placeholder{iter-value-type}@>, - Allocator>; + template + priority_queue(InputIterator, InputIterator, Compare, Allocator) + -> priority_queue<@\exposid{iter-value-type}@, + vector<@\exposid{iter-value-type}@, Allocator>, Compare>; - template - unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) - -> unordered_set, hash>, - equal_to>, Allocator>; + template + priority_queue(InputIterator, InputIterator, Compare, Container, Allocator) + -> priority_queue; - template - unordered_set(from_range_t, R&&, Allocator) - -> unordered_set, hash>, - equal_to>, Allocator>; + template + priority_queue(from_range_t, R&&, Compare, Allocator) + -> priority_queue, vector, Allocator>, + Compare>; - template - unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) - -> unordered_set, Hash, - equal_to>, Allocator>; + template + priority_queue(from_range_t, R&&, Allocator) + -> priority_queue, vector, Allocator>>; - template - unordered_set(initializer_list, typename @\seebelow@::size_type, Allocator) - -> unordered_set, equal_to, Allocator>; + // no equality is provided - template - unordered_set(initializer_list, typename @\seebelow@::size_type, Hash, Allocator) - -> unordered_set, Allocator>; + template + struct uses_allocator, Alloc> + : uses_allocator::type { }; } \end{codeblock} -\pnum -A \tcode{size_type} parameter type in an \tcode{unordered_set} deduction guide -refers to the \tcode{size_type} member type of -the type deduced by the deduction guide. - -\rSec3[unord.set.cnstr]{Constructors} +\rSec3[priqueue.cons]{Constructors} -\indexlibraryctor{unordered_set}% +\indexlibraryctor{priority_queue}% \begin{itemdecl} -unordered_set() : unordered_set(size_type(@\seebelow@)) { } -explicit unordered_set(size_type n, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); +constexpr priority_queue(const Compare& x, const Container& y); +constexpr priority_queue(const Compare& x, Container&& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Constructs an empty \tcode{unordered_set} using the -specified hash function, key equality predicate, and allocator, and -using at least \tcode{n} buckets. For the default constructor, -the number of buckets is \impldef{default number of buckets in -\tcode{unordered_set}}. -\tcode{max_load_factor()} returns \tcode{1.0}. +\expects +\tcode{x} defines a strict weak ordering\iref{alg.sorting}. \pnum -\complexity -Constant. +\effects +Initializes +\tcode{comp} with +\tcode{x} and +\tcode{c} with +\tcode{y} (copy constructing or move constructing as appropriate); +calls +\tcode{make_heap(c.begin(), c.end(), comp)}. \end{itemdescr} -\indexlibraryctor{unordered_set}% +\indexlibraryctor{priority_queue}% \begin{itemdecl} template - unordered_set(InputIterator f, InputIterator l, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); -template<@\exposconcept{container-compatible-range}@ 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(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); + constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare()); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Constructs an empty \tcode{unordered_set} using the -specified hash function, key equality predicate, and allocator, and -using at least \tcode{n} buckets. If \tcode{n} is not -provided, the number of buckets is \impldef{default number of buckets in -\tcode{unordered_set}}. Then -inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, -respectively. -\tcode{max_load_factor()} returns \tcode{1.0}. - -\pnum -\complexity -Average case linear, worst case quadratic. -\end{itemdescr} - -\rSec3[unord.set.erasure]{Erasure} - -\indexlibrarymember{erase_if}{unordered_set}% -\begin{itemdecl} -template - typename unordered_set::size_type - erase_if(unordered_set& c, Predicate pred); -\end{itemdecl} +\expects +\tcode{x} defines a strict weak ordering\iref{alg.sorting}. -\begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -auto original_size = c.size(); -for (auto i = c.begin(), last = c.end(); i != last; ) { - if (pred(*i)) { - i = c.erase(i); - } else { - ++i; - } -} -return original_size - c.size(); -\end{codeblock} +Initializes \tcode{c} with +\tcode{first} as the first argument and +\tcode{last} as the second argument, and +initializes \tcode{comp} with \tcode{x}; +then calls \tcode{make_heap(c.begin(), c.end(), comp)}. \end{itemdescr} -\rSec3[unord.set.modifiers]{Modifiers} - -\indexlibrarymember{insert}{unordered_set}% +\indexlibraryctor{priority_queue}% \begin{itemdecl} -template pair insert(K&& obj); -template iterator insert(const_iterator hint, K&& obj); +template + constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x, + const Container& y); +template + constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x, + Container&& y); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -The \grammarterm{qualified-id}s \tcode{Hash::is_transparent} and -\tcode{Pred::is_transparent} are valid and denote types. -For the second overload, -\tcode{is_convertible_v} and -\tcode{is_convertible_v} are both \tcode{false}. - \pnum \expects -\tcode{value_type} is \oldconcept{EmplaceConstructible} -into \tcode{unordered_set} from \tcode{std::forward\newline (obj)}. +\tcode{x} defines a strict weak ordering\iref{alg.sorting}. \pnum \effects -If the set already contains an element that is equivalent to \tcode{obj}, -there is no effect. -Otherwise, let \tcode{h} be \tcode{hash_function()(obj)}. -Constructs an object \tcode{u} of type \tcode{value_type} -with \tcode{std::forward(obj)}. -If \tcode{hash_function()(u) != h || contains(u)} is \tcode{true}, -the behavior is undefined. -Inserts \tcode{u} into \tcode{*this}. - -\pnum -\returns -For the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the set element -that is equivalent to \tcode{obj}. - -\pnum -\complexity -Average case constant, worst case linear. +Initializes +\tcode{comp} with +\tcode{x} and +\tcode{c} with +\tcode{y} (copy constructing or move constructing as appropriate); +calls +\tcode{c.insert(c.end(), first, last)}; +and finally calls +\tcode{make_heap(c.begin(), c.end(), comp)}. \end{itemdescr} -\rSec2[unord.multiset]{Class template \tcode{unordered_multiset}}% -\indexlibraryglobal{unordered_multiset} - -\rSec3[unord.multiset.overview]{Overview} - -\pnum -\indextext{\idxcode{unordered_multiset}!equivalent keys}% -\indextext{unordered associative containers!equivalent keys}% -An \tcode{unordered_multiset} is an unordered associative container -that supports equivalent keys (an instance of \tcode{unordered_multiset} may contain -multiple copies of the same key value) and in which each element's key -is the element itself. -The \tcode{unordered_multiset} class -supports forward iterators. - -\pnum -An \tcode{unordered_multiset} meets all of the requirements -of a container\iref{container.reqmts}, -of an allocator-aware container\iref{container.alloc.reqmts}, and -of an unordered associative container\iref{unord.req}. -It provides the operations described in the -preceding requirements table for equivalent keys; that is, an \tcode{unordered_multiset} -supports the \tcode{a_eq} operations in that table, not the \tcode{a_uniq} operations. -For an \tcode{unordered_multiset} the \tcode{key_type} and the \tcode{value_type} are -both \tcode{Key}. The \tcode{iterator} and \tcode{const_iterator} types are both -constant iterator types. It is unspecified whether they are the same type. - -\pnum -Subclause~\ref{unord.multiset} only describes operations on \tcode{unordered_multiset} that -are not described in one of the requirement tables, or for which there -is additional semantic information. - -\indexlibraryglobal{unordered_multiset}% -\begin{codeblock} -namespace std { - template, - class Pred = equal_to, - class Allocator = allocator> - class unordered_multiset { - public: - // types - using key_type = Key; - using value_type = Key; - using hasher = Hash; - using key_equal = Pred; - using allocator_type = Allocator; - using pointer = typename allocator_traits::pointer; - using const_pointer = typename allocator_traits::const_pointer; - using reference = value_type&; - using const_reference = const value_type&; - using size_type = @\impdefx{type of \tcode{unordered_multiset::size_type}}@; // see \ref{container.requirements} - using difference_type = @\impdefx{type of \tcode{unordered_multiset::difference_type}}@; // see \ref{container.requirements} - - using iterator = @\impdefx{type of \tcode{unordered_multiset::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{unordered_multiset::const_iterator}}@; // see \ref{container.requirements} - using local_iterator = @\impdefx{type of \tcode{unordered_multiset::local_iterator}}@; // see \ref{container.requirements} - using const_local_iterator = @\impdefx{type of \tcode{unordered_multiset::const_local_it\-erator}}@; // see \ref{container.requirements} - using node_type = @\unspec@; - - // \ref{unord.multiset.cnstr}, construct/copy/destroy - unordered_multiset(); - explicit unordered_multiset(size_type n, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - template - unordered_multiset(InputIterator f, InputIterator l, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - template<@\exposconcept{container-compatible-range}@ R> - unordered_multiset(from_range_t, R&& rg, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - unordered_multiset(const unordered_multiset&); - unordered_multiset(unordered_multiset&&); - explicit unordered_multiset(const Allocator&); - unordered_multiset(const unordered_multiset&, const type_identity_t&); - unordered_multiset(unordered_multiset&&, const type_identity_t&); - unordered_multiset(initializer_list il, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); - unordered_multiset(size_type n, const allocator_type& a) - : unordered_multiset(n, hasher(), key_equal(), a) { } - unordered_multiset(size_type n, const hasher& hf, const allocator_type& a) - : unordered_multiset(n, hf, key_equal(), a) { } - template - unordered_multiset(InputIterator f, InputIterator l, size_type n, const allocator_type& a) - : unordered_multiset(f, l, n, hasher(), key_equal(), a) { } - template - 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, - const allocator_type& a) - : unordered_multiset(il, n, hf, key_equal(), a) { } - ~unordered_multiset(); - unordered_multiset& operator=(const unordered_multiset&); - unordered_multiset& operator=(unordered_multiset&&) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_move_assignable_v && - is_nothrow_move_assignable_v); - unordered_multiset& operator=(initializer_list); - allocator_type get_allocator() const noexcept; - - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; - - // modifiers - template iterator emplace(Args&&... args); - template iterator emplace_hint(const_iterator position, Args&&... args); - iterator insert(const value_type& obj); - iterator insert(value_type&& obj); - iterator insert(const_iterator hint, const value_type& obj); - iterator insert(const_iterator hint, value_type&& obj); - template void insert(InputIterator first, InputIterator last); - template<@\exposconcept{container-compatible-range}@ R> - void insert_range(R&& rg); - void insert(initializer_list); +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); +\end{itemdecl} - node_type extract(const_iterator position); - node_type extract(const key_type& x); - template node_type extract(K&& x); - iterator insert(node_type&& nh); - iterator insert(const_iterator hint, node_type&& nh); +\begin{itemdescr} +\pnum +\expects +\tcode{x} defines a strict weak ordering\iref{alg.sorting}. - iterator erase(iterator position) - requires (!@\libconcept{same_as}@); - iterator erase(const_iterator position); - size_type erase(const key_type& k); - template size_type erase(K&& x); - iterator erase(const_iterator first, const_iterator last); - void swap(unordered_multiset&) - noexcept(allocator_traits::is_always_equal::value && - is_nothrow_swappable_v && - is_nothrow_swappable_v); - void clear() noexcept; +\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} - template - void merge(unordered_multiset& source); - template - void merge(unordered_multiset&& source); - template - void merge(unordered_set& source); - template - void merge(unordered_set&& source); +\rSec3[priqueue.cons.alloc]{Constructors with allocators} - // observers - hasher hash_function() const; - key_equal key_eq() const; +\pnum +If \tcode{uses_allocator_v} is \tcode{false} +the constructors in this subclause shall not participate in overload resolution. - // set operations - iterator find(const key_type& k); - const_iterator find(const key_type& k) const; - template - iterator find(const K& k); - template - const_iterator find(const K& k) const; - size_type count(const key_type& k) const; - template - size_type count(const K& k) const; - bool contains(const key_type& k) const; - template - bool contains(const K& k) const; - pair equal_range(const key_type& k); - pair equal_range(const key_type& k) const; - template - pair equal_range(const K& k); - template - pair equal_range(const K& k) const; +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template constexpr explicit priority_queue(const Alloc& a); +\end{itemdecl} - // bucket interface - size_type bucket_count() const noexcept; - size_type max_bucket_count() const noexcept; - size_type bucket_size(size_type n) const; - size_type bucket(const key_type& k) const; - template size_type bucket(const K& k) const; - local_iterator begin(size_type n); - const_local_iterator begin(size_type n) const; - local_iterator end(size_type n); - const_local_iterator end(size_type n) const; - const_local_iterator cbegin(size_type n) const; - const_local_iterator cend(size_type n) const; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{a} and value-initializes \tcode{comp}. +\end{itemdescr} - // hash policy - float load_factor() const noexcept; - float max_load_factor() const noexcept; - void max_load_factor(float z); - void rehash(size_type n); - void reserve(size_type n); - }; +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template constexpr priority_queue(const Compare& compare, const Alloc& a); +\end{itemdecl} - template>, - class Pred = equal_to<@\placeholder{iter-value-type}@>, - class Allocator = allocator<@\placeholder{iter-value-type}@>> - unordered_multiset(InputIterator, InputIterator, @\seebelow@::size_type = @\seebelow@, - Hash = Hash(), Pred = Pred(), Allocator = Allocator()) - -> unordered_multiset<@\placeholder{iter-value-type}@, - Hash, Pred, Allocator>; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{a} and initializes \tcode{comp} with \tcode{compare}. +\end{itemdescr} - 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>; +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template + constexpr priority_queue(const Compare& compare, const Container& cont, const Alloc& a); +\end{itemdecl} - template, - class Pred = equal_to, class Allocator = allocator> - unordered_multiset(initializer_list, typename @\seebelow@::size_type = @\seebelow@, - Hash = Hash(), Pred = Pred(), Allocator = Allocator()) - -> unordered_multiset; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a} as the second +argument, and initializes \tcode{comp} with \tcode{compare}; +calls \tcode{make_heap(c.begin(), c.end(), comp)}. +\end{itemdescr} - template - unordered_multiset(InputIterator, InputIterator, typename @\seebelow@::size_type, Allocator) - -> unordered_multiset<@\placeholder{iter-value-type}@, - hash<@\placeholder{iter-value-type}@>, - equal_to<@\placeholder{iter-value-type}@>, - Allocator>; +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template + constexpr priority_queue(const Compare& compare, Container&& cont, const Alloc& a); +\end{itemdecl} - template - unordered_multiset(InputIterator, InputIterator, typename @\seebelow@::size_type, - Hash, Allocator) - -> unordered_multiset<@\placeholder{iter-value-type}@, Hash, - equal_to<@\placeholder{iter-value-type}@>, - Allocator>; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{std::move(cont)} as the first argument and \tcode{a} +as the second argument, and initializes \tcode{comp} with \tcode{compare}; +calls \tcode{make_heap(c.begin(), c.end(), comp)}. +\end{itemdescr} - template - unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) - -> unordered_multiset, hash>, - equal_to>, Allocator>; +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template constexpr priority_queue(const priority_queue& q, const Alloc& a); +\end{itemdecl} - template - unordered_multiset(from_range_t, R&&, Allocator) - -> unordered_multiset, hash>, - equal_to>, Allocator>; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{q.c} as the first argument and \tcode{a} as +the second argument, and initializes \tcode{comp} with \tcode{q.comp}. +\end{itemdescr} - template - unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) - -> unordered_multiset, Hash, equal_to>, - Allocator>; +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template constexpr priority_queue(priority_queue&& q, const Alloc& a); +\end{itemdecl} - template - unordered_multiset(initializer_list, typename @\seebelow@::size_type, Allocator) - -> unordered_multiset, equal_to, Allocator>; +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{std::move(q.c)} as the first argument and \tcode{a} +as the second argument, and initializes \tcode{comp} with \tcode{std::move(q.comp)}. +\end{itemdescr} - template - unordered_multiset(initializer_list, typename @\seebelow@::size_type, Hash, Allocator) - -> unordered_multiset, Allocator>; -} -\end{codeblock} +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template + constexpr priority_queue(InputIterator first, InputIterator last, const Alloc& a); +\end{itemdecl} +\begin{itemdescr} \pnum -A \tcode{size_type} parameter type in an \tcode{unordered_multiset} deduction guide -refers to the \tcode{size_type} member type of -the type deduced by the deduction guide. +\effects +Initializes \tcode{c} with +\tcode{first} as the first argument, +\tcode{last} as the second argument, and +\tcode{a} as the third argument, and +value-initializes \tcode{comp}; +calls \tcode{make_heap(c.begin(), c.end(), comp)}. +\end{itemdescr} -\rSec3[unord.multiset.cnstr]{Constructors} +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template + constexpr priority_queue(InputIterator first, InputIterator last, + const Compare& compare, const Alloc& a); +\end{itemdecl} -\indexlibraryctor{unordered_multiset}% +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with +\tcode{first} as the first argument, +\tcode{last} as the second argument, and +\tcode{a} as the third argument, and +initializes \tcode{comp} with \tcode{compare}; +calls \tcode{make_heap(c.begin(), c.end(), comp)}. +\end{itemdescr} + +\indexlibraryctor{priority_queue}% \begin{itemdecl} -unordered_multiset() : unordered_multiset(size_type(@\seebelow@)) { } -explicit unordered_multiset(size_type n, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); +template + constexpr priority_queue(InputIterator first, InputIterator last, const Compare& compare, + const Container& cont, const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs an empty \tcode{unordered_multiset} using the -specified hash function, key equality predicate, and allocator, and -using at least \tcode{n} buckets. For the default constructor, -the number of buckets is \impldef{default number of buckets in -\tcode{unordered_multiset}}. -\tcode{max_load_factor()} returns \tcode{1.0}. +Initializes \tcode{c} with +\tcode{cont} as the first argument and \tcode{a} as the second argument, and +initializes \tcode{comp} with \tcode{compare}; +calls \tcode{c.insert(c.end(), first, last)}; and +finally calls \tcode{make_heap(c.begin(), c.end(), comp)}. +\end{itemdescr} + +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template + constexpr priority_queue(InputIterator first, InputIterator last, const Compare& compare, + Container&& cont, const Alloc& a); +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -Constant. +\effects +Initializes \tcode{c} with +\tcode{std::move(cont)} as the first argument and +\tcode{a} as the second argument, and +initializes \tcode{comp} with \tcode{compare}; +calls \tcode{c.insert(c.end(), first, last)}; and +finally calls \tcode{make_heap(c.begin(), c.end(), comp)}. \end{itemdescr} -\indexlibraryctor{unordered_multiset}% +\indexlibraryctor{priority_queue}% \begin{itemdecl} -template - unordered_multiset(InputIterator f, InputIterator l, - size_type n = @\seebelow@, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); -template<@\exposconcept{container-compatible-range}@ 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(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr priority_queue(from_range_t, R&& rg, const Compare& compare, const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs an empty \tcode{unordered_multiset} using the -specified hash function, key equality predicate, and allocator, and -using at least \tcode{n} buckets. If \tcode{n} is not -provided, the number of buckets is \impldef{default number of buckets in -\tcode{unordered_multiset}}. Then -inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, -respectively. -\tcode{max_load_factor()} returns \tcode{1.0}. +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> + constexpr priority_queue(from_range_t, R&& rg, const Alloc& a); +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -Average case linear, worst case quadratic. +\effects +Initializes +\tcode{c} with \tcode{ranges::to(std::forward(rg), a)} +and value-initializes \tcode{comp}; +calls \tcode{make_heap(c.begin(), c.end(), comp)}. \end{itemdescr} -\rSec3[unord.multiset.erasure]{Erasure} +\rSec3[priqueue.members]{Members} -\indexlibrarymember{erase_if}{unordered_multiset}% +\indexlibrarymember{push}{priority_queue}% \begin{itemdecl} -template - typename unordered_multiset::size_type - erase_if(unordered_multiset& c, Predicate pred); +constexpr void push(const value_type& x); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: +As if by: \begin{codeblock} -auto original_size = c.size(); -for (auto i = c.begin(), last = c.end(); i != last; ) { - if (pred(*i)) { - i = c.erase(i); - } else { - ++i; - } -} -return original_size - c.size(); +c.push_back(x); +push_heap(c.begin(), c.end(), comp); \end{codeblock} \end{itemdescr} -\rSec1[container.adaptors]{Container adaptors} - -\rSec2[container.adaptors.general]{In general} +\indexlibrarymember{push}{priority_queue}% +\begin{itemdecl} +constexpr void push(value_type&& x); +\end{itemdecl} +\begin{itemdescr} \pnum -The headers -\libheader{queue}, -\libheader{stack}, -\libheader{flat_map}, -and \libheader{flat_set} -define the container adaptors -\tcode{queue} and \tcode{priority_queue}, -\tcode{stack}, -\tcode{flat_map} and \tcode{flat_multimap}, -and \tcode{flat_set} and \tcode{flat_multiset}, -respectively. +\effects +As if by: +\begin{codeblock} +c.push_back(std::move(x)); +push_heap(c.begin(), c.end(), comp); +\end{codeblock} +\end{itemdescr} -\pnum -Each container adaptor takes -one or more template parameters -named \tcode{Container}, \tcode{KeyContainer}, or \tcode{MappedContainer} -that denote the types of containers that the container adaptor adapts. -Each container adaptor has at least one constructor -that takes a reference argument to one or more such template parameters. -For each constructor reference argument to a container \tcode{C}, -the constructor copies the container into the container adaptor. -If \tcode{C} takes an allocator, then a compatible allocator may be passed in -to the adaptor's constructor. Otherwise, normal copy or move construction is used for the container -argument. -For the container adaptors -that take a single container template parameter \tcode{Container}, -the first template parameter \tcode{T} of the container adaptor -shall denote the same type as \tcode{Container::value_type}. +\indexlibrarymember{push_range}{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr void push_range(R&& rg); +\end{itemdecl} +\begin{itemdescr} \pnum -For container adaptors, no \tcode{swap} function throws an exception unless that -exception is thrown by the swap of the adaptor's -\tcode{Container}, -\tcode{KeyContainer}, -\tcode{MappedContainer}, or -\tcode{Compare} object (if any). +\effects +Inserts all elements of \tcode{rg} in \tcode{c} via +\tcode{c.append_range(std::forward(rg))} if that is a valid expression, or +\tcode{ranges::copy(rg, back_inserter(c))} otherwise. +Then restores the heap property as if by +\tcode{make_heap(c.begin(), c.end(), comp)}. \pnum -A constructor template of a container adaptor -shall not participate in overload resolution -if it has an \tcode{InputIterator} template parameter and -a type that does not qualify as an input iterator is deduced for that parameter. +\ensures +\tcode{is_heap(c.begin(), c.end(), comp)} is \tcode{true}. +\end{itemdescr} -\pnum -For container adaptors that have them, -the \tcode{insert}, \tcode{emplace}, and \tcode{erase} members -affect the validity of iterators, references, and pointers -to the adaptor's container(s) in the same way that -the containers' respective -\tcode{insert}, \tcode{emplace}, and \tcode{erase} members do. -\begin{example} -A call to \tcode{flat_map::insert} -can invalidate all iterators to the \tcode{flat_map}. -\end{example} +\indexlibrarymember{emplace}{priority_queue}% +\begin{itemdecl} +template constexpr void emplace(Args&&... args); +\end{itemdecl} +\begin{itemdescr} \pnum -A deduction guide for a container adaptor shall not participate in overload resolution if any of the following are true: -\begin{itemize} -\item It has an \tcode{InputIterator} template parameter and a type that does not qualify as an input iterator is deduced for that parameter. -\item It has a \tcode{Compare} template parameter and a type that qualifies as an allocator is deduced for that parameter. -\item It has a \tcode{Container}, \tcode{KeyContainer}, or \tcode{MappedContainer} template parameter and a type that qualifies as an allocator is deduced for that parameter. -\item It has no \tcode{Container}, \tcode{KeyContainer}, or \tcode{MappedContainer} template parameter, and it has an \tcode{Allocator} template parameter, and a type that does not qualify as an allocator is deduced for that parameter. -\item It has both \tcode{Container} and \tcode{Allocator} template parameters, and \tcode{uses_allocator_v} is \tcode{false}. -\item It has both \tcode{KeyContainer} and \tcode{Allocator} template parameters, and -\tcode{uses_allocator_v} is \tcode{false}. -\item It has both \tcode{KeyContainer} and \tcode{Compare} template parameters, and +\effects +As if by: \begin{codeblock} -is_invocable_v +c.emplace_back(std::forward(args)...); +push_heap(c.begin(), c.end(), comp); \end{codeblock} -is not a valid expression or is \tcode{false}. -\item It has both \tcode{MappedContainer} and \tcode{Allocator} template parameters, and -\tcode{uses_allocator_v} is \tcode{false}. -\end{itemize} +\end{itemdescr} -\pnum -The exposition-only alias template \exposid{iter-value-type} -defined in \ref{sequences.general} and -the exposition-only alias templates \exposid{iter-key-type}, \exposid{iter-mapped-type}, -\exposid{range-key-type}, and \exposid{range-mapped-type} -defined in \ref{associative.general} -may appear in deduction guides for container adaptors. +\indexlibrarymember{pop}{priority_queue}% +\begin{itemdecl} +constexpr void pop(); +\end{itemdecl} +\begin{itemdescr} \pnum -The following exposition-only alias template -may appear in deduction guides for container adaptors: +\effects +As if by: \begin{codeblock} -template - using @\exposid{alloc-rebind}@ = // \expos - typename allocator_traits::template rebind_alloc; +pop_heap(c.begin(), c.end(), comp); +c.pop_back(); \end{codeblock} +\end{itemdescr} -\rSec2[queue.syn]{Header \tcode{} synopsis} - -\indexheader{queue} -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} - -namespace std { - // \ref{queue}, class template \tcode{queue} - template> class queue; - - template - bool operator==(const queue& x, const queue& y); - template - bool operator!=(const queue& x, const queue& y); - template - bool operator< (const queue& x, const queue& y); - template - bool operator> (const queue& x, const queue& y); - template - bool operator<=(const queue& x, const queue& y); - template - bool operator>=(const queue& x, const queue& y); - template - compare_three_way_result_t - operator<=>(const queue& x, const queue& y); - - template - void swap(queue& x, queue& y) noexcept(noexcept(x.swap(y))); - template - struct uses_allocator, Alloc>; - - // \ref{container.adaptors.format}, formatter specialization for \tcode{queue} - template Container> - struct formatter, charT>; +\rSec3[priqueue.special]{Specialized algorithms} - // \ref{priority.queue}, class template \tcode{priority_queue} - template, - class Compare = less> - class priority_queue; +\indexlibrarymember{swap}{priority_queue}% +\begin{itemdecl} +template + constexpr void swap(priority_queue& x, + priority_queue& y) noexcept(noexcept(x.swap(y))); +\end{itemdecl} - template - void swap(priority_queue& x, - priority_queue& y) noexcept(noexcept(x.swap(y))); - template - struct uses_allocator, Alloc>; +\begin{itemdescr} +\pnum +\constraints +\tcode{is_swappable_v} is \tcode{true} and +\tcode{is_swappable_v} is \tcode{true}. - // \ref{container.adaptors.format}, formatter specialization for \tcode{priority_queue} - template Container, class Compare> - struct formatter, charT>; -} -\end{codeblock} +\pnum +\effects +As if by \tcode{x.swap(y)}. +\end{itemdescr} \rSec2[stack.syn]{Header \tcode{} synopsis} @@ -13721,219 +16522,134 @@ template> class stack; template - bool operator==(const stack& x, const stack& y); + constexpr bool operator==(const stack& x, const stack& y); template - bool operator!=(const stack& x, const stack& y); + constexpr bool operator!=(const stack& x, const stack& y); template - bool operator< (const stack& x, const stack& y); + constexpr bool operator< (const stack& x, const stack& y); template - bool operator> (const stack& x, const stack& y); + constexpr bool operator> (const stack& x, const stack& y); template - bool operator<=(const stack& x, const stack& y); + constexpr bool operator<=(const stack& x, const stack& y); template - bool operator>=(const stack& x, const stack& y); + constexpr bool operator>=(const stack& x, const stack& y); template - compare_three_way_result_t + constexpr compare_three_way_result_t operator<=>(const stack& x, const stack& y); - template - void swap(stack& x, stack& y) noexcept(noexcept(x.swap(y))); - template - struct uses_allocator, Alloc>; - - // \ref{container.adaptors.format}, formatter specialization for \tcode{stack} - template Container> - struct formatter, charT>; -} -\end{codeblock} - -\rSec2[flat.map.syn]{Header \tcode{} synopsis} - -\indexheader{flat_map}% -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} - -namespace std { - // \ref{flat.map}, class template \tcode{flat_map} - template, - class KeyContainer = vector, class MappedContainer = vector> - class flat_map; - - struct sorted_unique_t { explicit sorted_unique_t() = default; }; - inline constexpr sorted_unique_t sorted_unique{}; - - template - struct uses_allocator, - Allocator>; - - // \ref{flat.map.erasure}, erasure for \tcode{flat_map} - template - typename flat_map::size_type - erase_if(flat_map& c, Predicate pred); - - // \ref{flat.multimap}, class template \tcode{flat_multimap} - template, - class KeyContainer = vector, class MappedContainer = vector> - class flat_multimap; - - struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; }; - inline constexpr sorted_equivalent_t sorted_equivalent{}; - - template - struct uses_allocator, - Allocator>; - - // \ref{flat.multimap.erasure}, erasure for \tcode{flat_multimap} - template - typename flat_multimap::size_type - erase_if(flat_multimap& c, Predicate pred); -} -\end{codeblock} - -\rSec2[flat.set.syn]{Header \tcode{} synopsis}% -\indexheader{flat_set}% - -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} - -namespace std { - // \ref{flat.set}, class template \tcode{flat_set} - template, class KeyContainer = vector> - class flat_set; - - struct sorted_unique_t { explicit sorted_unique_t() = default; }; - inline constexpr sorted_unique_t sorted_unique{}; - - template - struct uses_allocator, Allocator>; - - // \ref{flat.set.erasure}, erasure for \tcode{flat_set} - template - typename flat_set::size_type - erase_if(flat_set& c, Predicate pred); - - // \ref{flat.multiset}, class template \tcode{flat_multiset} - template, class KeyContainer = vector> - class flat_multiset; - - struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; }; - inline constexpr sorted_equivalent_t sorted_equivalent{}; - - template - struct uses_allocator, Allocator>; + template + constexpr void swap(stack& x, stack& y) + noexcept(noexcept(x.swap(y))); + template + struct uses_allocator, Alloc>; - // \ref{flat.multiset.erasure}, erasure for \tcode{flat_multiset} - template - typename flat_multiset::size_type - erase_if(flat_multiset& c, Predicate pred); + // \ref{container.adaptors.format}, formatter specialization for \tcode{stack} + template Container> + struct formatter, charT>; } \end{codeblock} -\rSec2[queue]{Class template \tcode{queue}} +\rSec2[stack]{Class template \tcode{stack}} -\rSec3[queue.defn]{Definition} +\rSec3[stack.general]{General} \pnum -\indexlibraryglobal{queue}% +\indexlibraryglobal{stack}% Any sequence container supporting operations -\tcode{front()}, \tcode{back()}, \tcode{push_back()} and -\tcode{pop_front()} +\tcode{pop_back()} can be used to instantiate -\tcode{queue}. +\tcode{stack}. In particular, +\tcode{vector}\iref{vector}, \tcode{list}\iref{list} and \tcode{deque}\iref{deque} can be used. +\rSec3[stack.defn]{Definition} + \begin{codeblock} namespace std { template> - class queue { + class stack { public: using value_type = typename Container::value_type; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using size_type = typename Container::size_type; - using container_type = Container; + using container_type = Container; protected: Container c; public: - queue() : queue(Container()) {} - 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&); - template queue(const queue&, const Alloc&); - template queue(queue&&, const Alloc&); + constexpr stack() : stack(Container()) {} + constexpr explicit stack(const Container&); + constexpr explicit stack(Container&&); + template constexpr stack(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr stack(from_range_t, R&& rg); + template constexpr explicit stack(const Alloc&); + template constexpr stack(const Container&, const Alloc&); + template constexpr stack(Container&&, const Alloc&); + template constexpr stack(const stack&, const Alloc&); + template constexpr stack(stack&&, const Alloc&); template - queue(InputIterator first, InputIterator last, const Alloc&); + constexpr stack(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(); } - reference front() { return c.front(); } - const_reference front() const { return c.front(); } - reference back() { return c.back(); } - const_reference back() const { return c.back(); } - void push(const value_type& x) { c.push_back(x); } - void push(value_type&& x) { c.push_back(std::move(x)); } - template<@\exposconcept{container-compatible-range}@ R> void push_range(R&& rg); + constexpr stack(from_range_t, R&& rg, const Alloc&); + + constexpr bool empty() const { return c.empty(); } + constexpr size_type size() const { return c.size(); } + constexpr reference top() { return c.back(); } + constexpr const_reference top() const { return c.back(); } + constexpr void push(const value_type& x) { c.push_back(x); } + constexpr void push(value_type&& x) { c.push_back(std::move(x)); } + template<@\exposconcept{container-compatible-range}@ R> + constexpr void push_range(R&& rg); template - decltype(auto) emplace(Args&&... args) + constexpr decltype(auto) emplace(Args&&... args) { return c.emplace_back(std::forward(args)...); } - void pop() { c.pop_front(); } - void swap(queue& q) noexcept(is_nothrow_swappable_v) - { using std::swap; swap(c, q.c); } + constexpr void pop() { c.pop_back(); } + constexpr void swap(stack& s) noexcept(is_nothrow_swappable_v) + { using std::swap; swap(c, s.c); } }; template - queue(Container) -> queue; + stack(Container) -> stack; template - queue(InputIterator, InputIterator) -> queue<@\exposid{iter-value-type}@>; + stack(InputIterator, InputIterator) -> stack<@\exposid{iter-value-type}@>; template - queue(from_range_t, R&&) -> queue>; + stack(from_range_t, R&&) -> stack>; template - queue(Container, Allocator) -> queue; + stack(Container, Allocator) -> stack; template - queue(InputIterator, InputIterator, Allocator) - -> queue<@\exposid{iter-value-type}@, deque<@\exposid{iter-value-type}@, + stack(InputIterator, InputIterator, Allocator) + -> stack<@\exposid{iter-value-type}@, deque<@\exposid{iter-value-type}@, Allocator>>; template - queue(from_range_t, R&&, Allocator) - -> queue, deque, Allocator>>; + stack(from_range_t, R&&, Allocator) + -> stack, deque, Allocator>>; template - struct uses_allocator, Alloc> + struct uses_allocator, Alloc> : uses_allocator::type { }; } \end{codeblock} -\rSec3[queue.cons]{Constructors} +\rSec3[stack.cons]{Constructors} -\indexlibraryctor{queue}% +\indexlibraryctor{stack}% \begin{itemdecl} -explicit queue(const Container& cont); +constexpr explicit stack(const Container& cont); \end{itemdecl} \begin{itemdescr} @@ -13942,9 +16658,9 @@ Initializes \tcode{c} with \tcode{cont}. \end{itemdescr} -\indexlibraryctor{queue}% +\indexlibraryctor{stack}% \begin{itemdecl} -explicit queue(Container&& cont); +constexpr explicit stack(Container&& cont); \end{itemdecl} \begin{itemdescr} @@ -13953,10 +16669,10 @@ Initializes \tcode{c} with \tcode{std::move(cont)}. \end{itemdescr} -\indexlibraryctor{queue}% +\indexlibraryctor{stack}% \begin{itemdecl} template - queue(InputIterator first, InputIterator last); + constexpr stack(InputIterator first, InputIterator last); \end{itemdecl} \begin{itemdescr} @@ -13966,10 +16682,10 @@ \tcode{first} as the first argument and \tcode{last} as the second argument. \end{itemdescr} -\indexlibraryctor{queue}% +\indexlibraryctor{stack}% \begin{itemdecl} template<@\exposconcept{container-compatible-range}@ R> - queue(from_range_t, R&& rg); + constexpr stack(from_range_t, R&& rg); \end{itemdecl} \begin{itemdescr} @@ -13978,15 +16694,15 @@ Initializes \tcode{c} with \tcode{ranges::to(std::forward(rg))}. \end{itemdescr} -\rSec3[queue.cons.alloc]{Constructors with allocators} +\rSec3[stack.cons.alloc]{Constructors with allocators} \pnum If \tcode{uses_allocator_v} is \tcode{false} the constructors in this subclause shall not participate in overload resolution. -\indexlibraryctor{queue}% +\indexlibraryctor{stack}% \begin{itemdecl} -template explicit queue(const Alloc& a); +template constexpr explicit stack(const Alloc& a); \end{itemdecl} \begin{itemdescr} @@ -13995,21 +16711,21 @@ Initializes \tcode{c} with \tcode{a}. \end{itemdescr} -\indexlibraryctor{queue}% +\indexlibraryctor{stack}% \begin{itemdecl} -template queue(const container_type& cont, const Alloc& a); +template constexpr stack(const container_type& cont, const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a} -as the second argument. +Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a} as the +second argument. \end{itemdescr} -\indexlibraryctor{queue}% +\indexlibraryctor{stack}% \begin{itemdecl} -template queue(container_type&& cont, const Alloc& a); +template constexpr stack(container_type&& cont, const Alloc& a); \end{itemdecl} \begin{itemdescr} @@ -14019,34 +16735,34 @@ as the second argument. \end{itemdescr} -\indexlibraryctor{queue}% +\indexlibraryctor{stack}% \begin{itemdecl} -template queue(const queue& q, const Alloc& a); +template constexpr stack(const stack& s, const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \tcode{c} with \tcode{q.c} as the first argument and \tcode{a} as the -second argument. +Initializes \tcode{c} with \tcode{s.c} as the first argument and \tcode{a} +as the second argument. \end{itemdescr} -\indexlibraryctor{queue}% +\indexlibraryctor{stack}% \begin{itemdecl} -template queue(queue&& q, const Alloc& a); +template constexpr stack(stack&& s, const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \tcode{c} with \tcode{std::move(q.c)} as the first argument and \tcode{a} +Initializes \tcode{c} with \tcode{std::move(s.c)} as the first argument and \tcode{a} as the second argument. \end{itemdescr} -\indexlibraryctor{queue}% +\indexlibraryctor{stack}% \begin{itemdecl} template - queue(InputIterator first, InputIterator last, const Alloc& alloc); + constexpr stack(InputIterator first, InputIterator last, const Alloc& alloc); \end{itemdecl} \begin{itemdescr} @@ -14058,25 +16774,25 @@ \tcode{alloc} as the third argument. \end{itemdescr} -\indexlibraryctor{queue}% +\indexlibraryctor{stack}% \begin{itemdecl} template<@\exposconcept{container-compatible-range}@ R, class Alloc> - queue(from_range_t, R&& rg, const Alloc& a); + constexpr 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)}. +Initializes +\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}. \end{itemdescr} -\rSec3[queue.mod]{Modifiers} +\rSec3[stack.mod]{Modifiers} -\indexlibrarymember{push_range}{queue}% +\indexlibrarymember{push_range}{stack}% \begin{itemdecl} template<@\exposconcept{container-compatible-range}@ R> - void push_range(R&& rg); + constexpr void push_range(R&& rg); \end{itemdecl} \begin{itemdescr} @@ -14087,12 +16803,12 @@ otherwise \tcode{ranges::copy(rg, back_inserter(c))}. \end{itemdescr} -\rSec3[queue.ops]{Operators} +\rSec3[stack.ops]{Operators} -\indexlibrarymember{operator==}{queue}% +\indexlibrarymember{operator==}{stack}% \begin{itemdecl} template - bool operator==(const queue& x, const queue& y); + constexpr bool operator==(const stack& x, const stack& y); \end{itemdecl} \begin{itemdescr} @@ -14101,10 +16817,10 @@ \tcode{x.c == y.c}. \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{queue}}% +\indexlibrary{\idxcode{operator"!=}!\idxcode{stack}}% \begin{itemdecl} template - bool operator!=(const queue& x, const queue& y); + constexpr bool operator!=(const stack& x, const stack& y); \end{itemdecl} \begin{itemdescr} @@ -14113,10 +16829,10 @@ \tcode{x.c != y.c}. \end{itemdescr} -\indexlibrarymember{operator<}{queue}% +\indexlibrarymember{operator<}{stack}% \begin{itemdecl} template - bool operator< (const queue& x, const queue& y); + constexpr bool operator< (const stack& x, const stack& y); \end{itemdecl} \begin{itemdescr} @@ -14125,10 +16841,10 @@ \tcode{x.c < y.c}. \end{itemdescr} -\indexlibrarymember{operator>}{queue}% +\indexlibrarymember{operator>}{stack}% \begin{itemdecl} template - bool operator> (const queue& x, const queue& y); + constexpr bool operator> (const stack& x, const stack& y); \end{itemdecl} \begin{itemdescr} @@ -14137,10 +16853,10 @@ \tcode{x.c > y.c}. \end{itemdescr} -\indexlibrarymember{operator<=}{queue}% +\indexlibrarymember{operator<=}{stack}% \begin{itemdecl} template - bool operator<=(const queue& x, const queue& y); + constexpr bool operator<=(const stack& x, const stack& y); \end{itemdecl} \begin{itemdescr} @@ -14149,11 +16865,10 @@ \tcode{x.c <= y.c}. \end{itemdescr} -\indexlibrarymember{operator>=}{queue}% +\indexlibrarymember{operator>=}{stack}% \begin{itemdecl} template - bool operator>=(const queue& x, - const queue& y); + constexpr bool operator>=(const stack& x, const stack& y); \end{itemdecl} \begin{itemdescr} @@ -14162,11 +16877,11 @@ \tcode{x.c >= y.c}. \end{itemdescr} -\indexlibrarymember{operator<=>}{queue}% +\indexlibrarymember{operator<=>}{stack}% \begin{itemdecl} template - compare_three_way_result_t - operator<=>(const queue& x, const queue& y); + constexpr compare_three_way_result_t + operator<=>(const stack& x, const stack& y); \end{itemdecl} \begin{itemdescr} @@ -14175,12 +16890,13 @@ \tcode{x.c <=> y.c}. \end{itemdescr} -\rSec3[queue.special]{Specialized algorithms} +\rSec3[stack.special]{Specialized algorithms} -\indexlibrarymember{swap}{queue}% +\indexlibrarymember{swap}{stack}% \begin{itemdecl} template - void swap(queue& x, queue& y) noexcept(noexcept(x.swap(y))); + constexpr void swap(stack& x, stack& y) + noexcept(noexcept(x.swap(y))); \end{itemdecl} \begin{itemdescr} @@ -14193,957 +16909,1336 @@ As if by \tcode{x.swap(y)}. \end{itemdescr} -\rSec2[priority.queue]{Class template \tcode{priority_queue}} +\rSec2[flat.map.syn]{Header \tcode{} synopsis} + +\indexheader{flat_map}% +\begin{codeblock} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} + +namespace std { + // \ref{flat.map}, class template \tcode{flat_map} + template, + class KeyContainer = vector, class MappedContainer = vector> + class flat_map; + + struct sorted_unique_t { explicit sorted_unique_t() = default; }; + inline constexpr sorted_unique_t sorted_unique{}; + + template + struct uses_allocator, + Allocator>; + + // \ref{flat.map.erasure}, erasure for \tcode{flat_map} + template + constexpr typename flat_map::size_type + erase_if(flat_map& c, Predicate pred); + + // \ref{flat.multimap}, class template \tcode{flat_multimap} + template, + class KeyContainer = vector, class MappedContainer = vector> + class flat_multimap; + + struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; }; + inline constexpr sorted_equivalent_t sorted_equivalent{}; + + template + struct uses_allocator, + Allocator>; + + // \ref{flat.multimap.erasure}, erasure for \tcode{flat_multimap} + template + constexpr typename flat_multimap::size_type + erase_if(flat_multimap& c, Predicate pred); +} +\end{codeblock} + +\rSec2[flat.map]{Class template \tcode{flat_map}} + +\rSec3[flat.map.overview]{Overview} + +\pnum +\indexlibraryglobal{flat_map}% +A \tcode{flat_map} is a container adaptor +that provides an associative container interface +that supports unique keys +(i.e., contains at most one of each key value) and +provides for fast retrieval of values of another type \tcode{T} +based on the keys. +\tcode{flat_map} supports iterators +that meet the \oldconcept{InputIterator} requirements and +model the +\libconcept{random_access_iterator} concept\iref{iterator.concept.random.access}. + +\pnum +A \tcode{flat_map} meets all of the requirements +of a container\iref{container.reqmts} and +of a reversible container\iref{container.rev.reqmts}, +plus the optional container requirements\iref{container.opt.reqmts}. +\tcode{flat_map} meets the requirements of +an associative container\iref{associative.reqmts}, +except that: +\begin{itemize} +\item +it does not meet the requirements related to node handles\iref{container.node}, +\item +it does not meet the requirements related to iterator invalidation, and +\item +the time complexity of the operations that insert or erase a single +element from the map is linear, including the ones that take an insertion +position iterator. +\end{itemize} +\begin{note} +A \tcode{flat_map} does not meet the additional requirements of +an allocator-aware container\iref{container.alloc.reqmts}. +\end{note} + +\pnum +A \tcode{flat_map} also provides most operations +described in \ref{associative.reqmts} for unique keys. +This means that a \tcode{flat_map} supports +the \tcode{a_uniq} operations in \ref{associative.reqmts} +but not the \tcode{a_eq} operations. +For a \tcode{flat_map} +the \tcode{key_type} is \tcode{Key} and +the \tcode{value_type} is \tcode{pair}. + +\pnum +Descriptions are provided here only for operations on \tcode{flat_map} that +are not described in one of those sets of requirements or for operations where +there is additional semantic information. + +\pnum +A \tcode{flat_map} maintains the following invariants: +\begin{itemize} +\item +it contains the same number of keys and values; +\item +the keys are sorted with respect to the comparison object; and +\item +the value at offset \tcode{off} within the value container is +the value associated with the key at offset \tcode{off} +within the key container. +\end{itemize} + +\pnum +If any member function in \ref{flat.map.defn} exits via an exception +the invariants are restored. +\begin{note} +This can result in the \tcode{flat_map} being emptied. +\end{note} + +\pnum +Any type \tcode{C} +that meets the sequence container requirements\iref{sequence.reqmts} +can be used to instantiate \tcode{flat_map}, +as long as +\tcode{C::iterator} meets the \oldconcept{RandomAccessIterator} requirements and +invocations of +member functions \tcode{C::size} and \tcode{C::max_size} do not exit via an exception. +In particular, \tcode{vector}\iref{vector} and \tcode{deque}\iref{deque} +can be used. +\begin{note} +\tcode{vector} is not a sequence container. +\end{note} + +\pnum +The program is ill-formed if +\tcode{Key} is not the same type as \tcode{KeyContainer::value_type} or +\tcode{T} is not the same type as \tcode{MappedContainer::value_type}. + +\pnum +The effect of calling a constructor +that takes +both \tcode{key_container_type} and \tcode{mapped_container_type} arguments with +containers of different sizes is undefined. -\rSec3[priqueue.overview]{Overview} +\pnum +The effect of calling a constructor or member function +that takes a \tcode{sorted_unique_t} argument with +a container, containers, or range +that is not sorted with respect to \tcode{key_comp()}, or +that contains equal elements, +is undefined. \pnum -\indexlibraryglobal{priority_queue}% -Any sequence container with random access iterator and supporting operations -\tcode{front()}, -\tcode{push_back()} -and -\tcode{pop_back()} -can be used to instantiate -\tcode{priority_queue}. -In particular, -\tcode{vector}\iref{vector} -and -\tcode{deque}\iref{deque} -can be used. -Instantiating -\tcode{priority_queue} -also involves supplying a function or function object for making -priority comparisons; the library assumes that the function or function -object defines a strict weak ordering\iref{alg.sorting}. +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. + +\rSec3[flat.map.defn]{Definition} \begin{codeblock} namespace std { - template, - class Compare = less> - class priority_queue { + template, + class KeyContainer = vector, class MappedContainer = vector> + class flat_map { public: - using value_type = typename Container::value_type; - using reference = typename Container::reference; - using const_reference = typename Container::const_reference; - using size_type = typename Container::size_type; - using container_type = Container; - using value_compare = Compare; + // types + using key_type = Key; + using mapped_type = T; + using value_type = pair; + using key_compare = Compare; + using reference = pair; + using const_reference = pair; + using size_type = size_t; + using difference_type = ptrdiff_t; + using iterator = @\impdefx{type of \tcode{flat_map::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{flat_map::const_iterator}}@; // see \ref{container.requirements} + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using key_container_type = KeyContainer; + using mapped_container_type = MappedContainer; - protected: - Container c; - Compare comp; + class value_compare { + private: + key_compare @\exposid{comp}@; // \expos + constexpr value_compare(key_compare c) : @\exposid{comp}@(c) { } // \expos + + public: + constexpr bool operator()(const_reference x, const_reference y) const { + return @\exposid{comp}@(x.first, y.first); + } + }; + + struct containers { + key_container_type keys; + mapped_container_type values; + }; + + // \ref{flat.map.cons}, constructors + constexpr flat_map() : flat_map(key_compare()) { } + + constexpr explicit flat_map(const key_compare& comp) + : @\exposid{c}@(), @\exposid{compare}@(comp) { } + + constexpr flat_map(key_container_type key_cont, mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); + + constexpr flat_map(sorted_unique_t, key_container_type key_cont, + mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); - public: - priority_queue() : priority_queue(Compare()) {} - explicit priority_queue(const Compare& x) : priority_queue(x, Container()) {} - priority_queue(const Compare& x, const Container&); - priority_queue(const Compare& x, Container&&); - template - priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare()); template - priority_queue(InputIterator first, InputIterator last, const Compare& x, - const Container&); + constexpr flat_map(InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(first, last); } + 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&); - template priority_queue(const Compare&, Container&&, const Alloc&); - template priority_queue(const priority_queue&, const Alloc&); - template priority_queue(priority_queue&&, const Alloc&); + constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(sorted_unique, first, last); } + + template<@\exposconcept{container-compatible-range}@ R> + constexpr flat_map(from_range_t, R&& rg) + : flat_map(from_range, std::forward(rg), key_compare()) { } + template<@\exposconcept{container-compatible-range}@ R> + constexpr flat_map(from_range_t, R&& rg, const key_compare& comp) + : flat_map(comp) { insert_range(std::forward(rg)); } + + constexpr flat_map(initializer_list il, const key_compare& comp = key_compare()) + : flat_map(il.begin(), il.end(), comp) { } + + constexpr flat_map(sorted_unique_t, initializer_list il, + const key_compare& comp = key_compare()) + : flat_map(sorted_unique, il.begin(), il.end(), comp) { } + + // \ref{flat.map.cons.alloc}, constructors with allocators + + template + constexpr explicit flat_map(const Alloc& a); + template + constexpr flat_map(const key_compare& comp, const Alloc& a); + template + constexpr flat_map(const key_container_type& key_cont, + const mapped_container_type& mapped_cont, + const Alloc& a); + template + constexpr flat_map(const key_container_type& key_cont, + const mapped_container_type& mapped_cont, + const key_compare& comp, const Alloc& a); + template + constexpr flat_map(sorted_unique_t, const key_container_type& key_cont, + const mapped_container_type& mapped_cont, const Alloc& a); + template + constexpr flat_map(sorted_unique_t, const key_container_type& key_cont, + const mapped_container_type& mapped_cont, const key_compare& comp, + const Alloc& a); + template + constexpr flat_map(const flat_map&, const Alloc& a); + template + constexpr flat_map(flat_map&&, const Alloc& a); template - priority_queue(InputIterator, InputIterator, const Alloc&); + constexpr flat_map(InputIterator first, InputIterator last, const Alloc& a); template - priority_queue(InputIterator, InputIterator, const Compare&, const Alloc&); + constexpr flat_map(InputIterator first, InputIterator last, + const key_compare& comp, const Alloc& a); template - priority_queue(InputIterator, InputIterator, const Compare&, const Container&, - const Alloc&); + constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last, + const Alloc& a); 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 && - is_nothrow_swappable_v) - { using std::swap; swap(c, q.c); swap(comp, q.comp); } - }; - - template - priority_queue(Compare, Container) - -> priority_queue; + constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last, + const key_compare& comp, const Alloc& a); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_map(from_range_t, R&& rg, const Alloc& a); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_map(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); + template + constexpr flat_map(initializer_list il, const Alloc& a); + template + constexpr flat_map(initializer_list il, const key_compare& comp, + const Alloc& a); + template + constexpr flat_map(sorted_unique_t, initializer_list il, const Alloc& a); + template + constexpr flat_map(sorted_unique_t, initializer_list il, + const key_compare& comp, const Alloc& a); + + constexpr flat_map& operator=(initializer_list); - template>, - class Container = vector<@\exposid{iter-value-type}@>> - priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) - -> priority_queue<@\exposid{iter-value-type}@, Container, Compare>; + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; - template>> - priority_queue(from_range_t, R&&, Compare = Compare()) - -> priority_queue, vector>, Compare>; + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; - template - priority_queue(Compare, Container, Allocator) - -> priority_queue; + 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; - template - priority_queue(InputIterator, InputIterator, Allocator) - -> priority_queue<@\exposid{iter-value-type}@, - vector<@\exposid{iter-value-type}@, Allocator>, - less<@\exposid{iter-value-type}@>>; + // \ref{flat.map.capacity}, capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; - template - priority_queue(InputIterator, InputIterator, Compare, Allocator) - -> priority_queue<@\exposid{iter-value-type}@, - vector<@\exposid{iter-value-type}@, Allocator>, Compare>; + // \ref{flat.map.access}, element access + constexpr mapped_type& operator[](const key_type& x); + constexpr mapped_type& operator[](key_type&& x); + template constexpr mapped_type& operator[](K&& x); + constexpr mapped_type& at(const key_type& x); + constexpr const mapped_type& at(const key_type& x) const; + template constexpr mapped_type& at(const K& x); + template constexpr const mapped_type& at(const K& x) const; - template - priority_queue(InputIterator, InputIterator, Compare, Container, Allocator) - -> priority_queue; + // \ref{flat.map.modifiers}, modifiers + template constexpr pair emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); - template - priority_queue(from_range_t, R&&, Compare, Allocator) - -> priority_queue, vector, Allocator>, - Compare>; + constexpr pair insert(const value_type& x) + { return emplace(x); } + constexpr pair insert(value_type&& x) + { return emplace(std::move(x)); } + constexpr iterator insert(const_iterator position, const value_type& x) + { return emplace_hint(position, x); } + constexpr iterator insert(const_iterator position, value_type&& x) + { return emplace_hint(position, std::move(x)); } - template - priority_queue(from_range_t, R&&, Allocator) - -> priority_queue, vector, Allocator>>; + template constexpr pair insert(P&& x); + template + constexpr iterator insert(const_iterator position, P&&); + template + constexpr void insert(InputIterator first, InputIterator last); + template + constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); - // no equality is provided + constexpr void insert(initializer_list il) + { insert(il.begin(), il.end()); } + constexpr void insert(sorted_unique_t, initializer_list il) + { insert(sorted_unique, il.begin(), il.end()); } - template - struct uses_allocator, Alloc> - : uses_allocator::type { }; -} -\end{codeblock} + constexpr containers extract() &&; + constexpr void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); -\rSec3[priqueue.cons]{Constructors} + template + constexpr pair try_emplace(const key_type& k, Args&&... args); + template + constexpr pair try_emplace(key_type&& k, Args&&... args); + template + constexpr pair try_emplace(K&& k, Args&&... args); + template + constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); + template + constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); + template + constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args); + template + constexpr pair insert_or_assign(const key_type& k, M&& obj); + template + constexpr pair insert_or_assign(key_type&& k, M&& obj); + template + constexpr pair insert_or_assign(K&& k, M&& obj); + template + constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); + template + constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); + template + constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -priority_queue(const Compare& x, const Container& y); -priority_queue(const Compare& x, Container&& y); -\end{itemdecl} + constexpr iterator erase(iterator position); + constexpr iterator erase(const_iterator position); + constexpr size_type erase(const key_type& x); + template constexpr size_type erase(K&& x); + constexpr iterator erase(const_iterator first, const_iterator last); -\begin{itemdescr} -\pnum -\expects -\tcode{x} defines a strict weak ordering\iref{alg.sorting}. + constexpr void swap(flat_map& y) noexcept; + constexpr void clear() noexcept; -\pnum -\effects -Initializes -\tcode{comp} with -\tcode{x} and -\tcode{c} with -\tcode{y} (copy constructing or move constructing as appropriate); -calls -\tcode{make_heap(c.begin(), c.end(), comp)}. -\end{itemdescr} + // observers + constexpr key_compare key_comp() const; + constexpr value_compare value_comp() const; -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template - priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare()); -\end{itemdecl} + constexpr const key_container_type& keys() const noexcept { return @\exposid{c}@.keys; } + constexpr const mapped_container_type& values() const noexcept { return @\exposid{c}@.values; } -\begin{itemdescr} -\pnum -\expects -\tcode{x} defines a strict weak ordering\iref{alg.sorting}. + // map operations + constexpr iterator find(const key_type& x); + constexpr const_iterator find(const key_type& x) const; + template constexpr iterator find(const K& x); + template constexpr const_iterator find(const K& x) const; + + constexpr size_type count(const key_type& x) const; + template constexpr size_type count(const K& x) const; + + constexpr bool contains(const key_type& x) const; + template constexpr bool contains(const K& x) const; + + constexpr iterator lower_bound(const key_type& x); + constexpr const_iterator lower_bound(const key_type& x) const; + template constexpr iterator lower_bound(const K& x); + template constexpr const_iterator lower_bound(const K& x) const; + + constexpr iterator upper_bound(const key_type& x); + constexpr const_iterator upper_bound(const key_type& x) const; + template constexpr iterator upper_bound(const K& x); + template constexpr const_iterator upper_bound(const K& x) const; + + constexpr pair equal_range(const key_type& x); + constexpr pair equal_range(const key_type& x) const; + template constexpr pair equal_range(const K& x); + template + constexpr pair equal_range(const K& x) const; -\pnum -\effects -Initializes \tcode{c} with -\tcode{first} as the first argument and -\tcode{last} as the second argument, and -initializes \tcode{comp} with \tcode{x}; -then calls \tcode{make_heap(c.begin(), c.end(), comp)}. -\end{itemdescr} + friend constexpr bool operator==(const flat_map& x, const flat_map& y); -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template - priority_queue(InputIterator first, InputIterator last, const Compare& x, const Container& y); -template - priority_queue(InputIterator first, InputIterator last, const Compare& x, Container&& y); -\end{itemdecl} + friend constexpr @\exposid{synth-three-way-result}@ + operator<=>(const flat_map& x, const flat_map& y); -\begin{itemdescr} -\pnum -\expects -\tcode{x} defines a strict weak ordering\iref{alg.sorting}. + friend constexpr void swap(flat_map& x, flat_map& y) noexcept + { x.swap(y); } -\pnum -\effects -Initializes -\tcode{comp} with -\tcode{x} and -\tcode{c} with -\tcode{y} (copy constructing or move constructing as appropriate); -calls -\tcode{c.insert(c.end(), first, last)}; -and finally calls -\tcode{make_heap(c.begin(), c.end(), comp)}. -\end{itemdescr} + private: + containers @\exposid{c}@; // \expos + key_compare @\exposid{compare}@; // \expos -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); -\end{itemdecl} + struct @\exposid{key-equiv}@ { // \expos + constexpr @\exposid{key-equiv}@(key_compare c) : comp(c) { } + constexpr bool operator()(const_reference x, const_reference y) const { + return !comp(x.first, y.first) && !comp(y.first, x.first); + } + key_compare comp; + }; + }; -\begin{itemdescr} -\pnum -\expects -\tcode{x} defines a strict weak ordering\iref{alg.sorting}. + template> + flat_map(KeyContainer, MappedContainer, Compare = Compare()) + -> flat_map; -\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} + template + flat_map(KeyContainer, MappedContainer, Allocator) + -> flat_map, KeyContainer, MappedContainer>; + template + flat_map(KeyContainer, MappedContainer, Compare, Allocator) + -> flat_map; -\rSec3[priqueue.cons.alloc]{Constructors with allocators} + template> + flat_map(sorted_unique_t, KeyContainer, MappedContainer, Compare = Compare()) + -> flat_map; -\pnum -If \tcode{uses_allocator_v} is \tcode{false} -the constructors in this subclause shall not participate in overload resolution. + template + flat_map(sorted_unique_t, KeyContainer, MappedContainer, Allocator) + -> flat_map, KeyContainer, MappedContainer>; + template + flat_map(sorted_unique_t, KeyContainer, MappedContainer, Compare, Allocator) + -> flat_map; -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template explicit priority_queue(const Alloc& a); -\end{itemdecl} + template>> + flat_map(InputIterator, InputIterator, Compare = Compare()) + -> flat_map<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{c} with \tcode{a} and value-initializes \tcode{comp}. -\end{itemdescr} + template>> + flat_map(sorted_unique_t, InputIterator, InputIterator, Compare = Compare()) + -> flat_map<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template priority_queue(const Compare& compare, const Alloc& a); -\end{itemdecl} + template>, + class Allocator = allocator> + flat_map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> flat_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Compare, + vector<@\exposid{range-key-type}@, @\exposid{alloc-rebind}@>>, + vector<@\exposid{range-mapped-type}@, @\exposid{alloc-rebind}@>>>; -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{c} with \tcode{a} and initializes \tcode{comp} with \tcode{compare}. -\end{itemdescr} + template + flat_map(from_range_t, R&&, Allocator) + -> flat_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, less<@\exposid{range-key-type}@>, + vector<@\exposid{range-key-type}@, @\exposid{alloc-rebind}@>>, + vector<@\exposid{range-mapped-type}@, @\exposid{alloc-rebind}@>>>; -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template - priority_queue(const Compare& compare, const Container& cont, const Alloc& a); -\end{itemdecl} + template> + flat_map(initializer_list>, Compare = Compare()) + -> flat_map; -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a} as the second -argument, and initializes \tcode{comp} with \tcode{compare}; -calls \tcode{make_heap(c.begin(), c.end(), comp)}. -\end{itemdescr} + template> + flat_map(sorted_unique_t, initializer_list>, Compare = Compare()) + -> flat_map; -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template - priority_queue(const Compare& compare, Container&& cont, const Alloc& a); -\end{itemdecl} + template + struct uses_allocator, Allocator> + : bool_constant && + uses_allocator_v> { }; +} +\end{codeblock} -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{std::move(cont)} as the first argument and \tcode{a} -as the second argument, and initializes \tcode{comp} with \tcode{compare}; -calls \tcode{make_heap(c.begin(), c.end(), comp)}. -\end{itemdescr} +The member type \tcode{containers} has the data members and special members +specified above. +It has no base classes or members other than those specified. -\indexlibraryctor{priority_queue}% +\rSec3[flat.map.cons]{Constructors} + +\indexlibraryctor{flat_map}% \begin{itemdecl} -template priority_queue(const priority_queue& q, const Alloc& a); +constexpr flat_map(key_container_type key_cont, mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \tcode{c} with \tcode{q.c} as the first argument and \tcode{a} as -the second argument, and initializes \tcode{comp} with \tcode{q.comp}. -\end{itemdescr} - -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template priority_queue(priority_queue&& q, const Alloc& a); -\end{itemdecl} +Initializes +\tcode{\exposid{c}.keys} with \tcode{std::move(key_cont)}, +\tcode{\exposid{c}.values} with \tcode{std::move(mapped_cont)}, and +\exposid{compare} with \tcode{comp}; +sorts the range \range{begin()}{end()} with respect to \tcode{value_comp()}; and +finally erases the duplicate elements as if by: +\begin{codeblock} +auto zv = views::zip(@\exposid{c}@.keys, @\exposid{c}@.values); +auto it = ranges::unique(zv, @\exposid{key-equiv}@(@\exposid{compare}@)).begin(); +auto dist = distance(zv.begin(), it); +@\exposid{c}@.keys.erase(@\exposid{c}@.keys.begin() + dist, @\exposid{c}@.keys.end()); +@\exposid{c}@.values.erase(@\exposid{c}@.values.begin() + dist, @\exposid{c}@.values.end()); +\end{codeblock} -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{std::move(q.c)} as the first argument and \tcode{a} -as the second argument, and initializes \tcode{comp} with \tcode{std::move(q.comp)}. +\complexity +Linear in $N$ if the container arguments are already sorted +with respect to \tcode{value_comp()} and otherwise $N \log N$, +where $N$ is the value of \tcode{key_cont.size()} before this call. \end{itemdescr} -\indexlibraryctor{priority_queue}% +\indexlibraryctor{flat_map}% \begin{itemdecl} -template - priority_queue(InputIterator first, InputIterator last, const Alloc& a); +constexpr flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \tcode{c} with -\tcode{first} as the first argument, -\tcode{last} as the second argument, and -\tcode{a} as the third argument, and -value-initializes \tcode{comp}; -calls \tcode{make_heap(c.begin(), c.end(), comp)}. -\end{itemdescr} - -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template - priority_queue(InputIterator first, InputIterator last, const Compare& compare, const Alloc& a); -\end{itemdecl} +Initializes +\tcode{\exposid{c}.keys} with \tcode{std::move(key_cont)}, +\tcode{\exposid{c}.values} with \tcode{std::move(mapped_cont)}, and +\exposid{compare} with \tcode{comp}. -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with -\tcode{first} as the first argument, -\tcode{last} as the second argument, and -\tcode{a} as the third argument, and -initializes \tcode{comp} with \tcode{compare}; -calls \tcode{make_heap(c.begin(), c.end(), comp)}. +\complexity +Constant. \end{itemdescr} -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template - priority_queue(InputIterator first, InputIterator last, const Compare& compare, - const Container& cont, const Alloc& a); -\end{itemdecl} +\rSec3[flat.map.cons.alloc]{Constructors with allocators} -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with -\tcode{cont} as the first argument and \tcode{a} as the second argument, and -initializes \tcode{comp} with \tcode{compare}; -calls \tcode{c.insert(c.end(), first, last)}; and -finally calls \tcode{make_heap(c.begin(), c.end(), comp)}. -\end{itemdescr} +The constructors in this subclause shall not participate in overload resolution +unless \tcode{uses_allocator_v} is \tcode{true} +and \tcode{uses_allocator_v} is \tcode{true}. -\indexlibraryctor{priority_queue}% +\indexlibraryctor{flat_map}% \begin{itemdecl} -template - priority_queue(InputIterator first, InputIterator last, const Compare& compare, Container&& cont, - const Alloc& a); +template + constexpr flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, + const Alloc& a); +template + constexpr flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, + const key_compare& comp, const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \tcode{c} with -\tcode{std::move(cont)} as the first argument and -\tcode{a} as the second argument, and -initializes \tcode{comp} with \tcode{compare}; -calls \tcode{c.insert(c.end(), first, last)}; and -finally calls \tcode{make_heap(c.begin(), c.end(), comp)}. -\end{itemdescr} - -\indexlibraryctor{priority_queue}% -\begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R, class Alloc> - priority_queue(from_range_t, R&& rg, const Compare& compare, const Alloc& a); -\end{itemdecl} +Equivalent to \tcode{flat_map(key_cont, mapped_cont)} and +\tcode{flat_map(key_cont, mapped_cont, comp)}, respectively, +except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed with +uses-allocator construction\iref{allocator.uses.construction}. -\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)}. +\complexity +Same as \tcode{flat_map(key_cont, mapped_cont)} and +\tcode{flat_map(key_cont, mapped_cont, comp)}, respectively. \end{itemdescr} -\indexlibraryctor{priority_queue}% +\indexlibraryctor{flat_map}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R, class Alloc> - priority_queue(from_range_t, R&& rg, const Alloc& a); +template + constexpr flat_map(sorted_unique_t, const key_container_type& key_cont, + const mapped_container_type& mapped_cont, const Alloc& a); +template + constexpr flat_map(sorted_unique_t, const key_container_type& key_cont, + const mapped_container_type& mapped_cont, const key_compare& comp, + const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum \effects -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}% -\begin{itemdecl} -void push(const value_type& x); -\end{itemdecl} +Equivalent to \tcode{flat_map(sorted_unique, key_cont, mapped_cont)} and +\tcode{flat_map(sorted_unique, key_cont, \linebreak{}mapped_cont, comp)}, respectively, +except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed +with uses-allocator construction\iref{allocator.uses.construction}. -\begin{itemdescr} \pnum -\effects -As if by: -\begin{codeblock} -c.push_back(x); -push_heap(c.begin(), c.end(), comp); -\end{codeblock} +\complexity +Linear. \end{itemdescr} -\indexlibrarymember{push}{priority_queue}% +\indexlibraryctor{flat_map}% \begin{itemdecl} -void push(value_type&& x); +template + constexpr explicit flat_map(const Alloc& a); +template + constexpr flat_map(const key_compare& comp, const Alloc& a); +template + constexpr flat_map(const flat_map&, const Alloc& a); +template + constexpr flat_map(flat_map&&, const Alloc& a); +template + constexpr flat_map(InputIterator first, InputIterator last, const Alloc& a); +template + constexpr flat_map(InputIterator first, InputIterator last, const key_compare& comp, + const Alloc& a); +template + constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last, const Alloc& a); +template + constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last, + const key_compare& comp, const Alloc& a); +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_map(from_range_t, R&& rg, const Alloc& a); +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_map(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); +template + constexpr flat_map(initializer_list il, const Alloc& a); +template + constexpr flat_map(initializer_list il, const key_compare& comp, const Alloc& a); +template + constexpr flat_map(sorted_unique_t, initializer_list il, const Alloc& a); +template + constexpr flat_map(sorted_unique_t, initializer_list il, + const key_compare& comp, const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum \effects -As if by: -\begin{codeblock} -c.push_back(std::move(x)); -push_heap(c.begin(), c.end(), comp); -\end{codeblock} +Equivalent to the corresponding non-allocator constructors +except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed +with uses-allocator construction\iref{allocator.uses.construction}. \end{itemdescr} -\indexlibrarymember{push_range}{priority_queue}% +\rSec3[flat.map.capacity]{Capacity} + +\indexlibrarymember{size}{flat_map}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - void push_range(R&& rg); +constexpr size_type size() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Inserts all elements of \tcode{rg} in \tcode{c} via -\tcode{c.append_range(std::forward(rg))} if that is a valid expression, or -\tcode{ranges::copy(rg, back_inserter(c))} otherwise. -Then restores the heap property as if by -\tcode{make_heap(c.begin(), c.end(), comp)}. +\returns +\tcode{\exposid{c}.keys.size()}. +\end{itemdescr} +\indexlibrarymember{max_size}{flat_map}% +\begin{itemdecl} +constexpr size_type max_size() const noexcept; +\end{itemdecl} + +\begin{itemdescr} \pnum -\ensures -\tcode{is_heap(c.begin(), c.end(), comp)} is \tcode{true}. +\returns +\tcode{min(\exposid{c}.keys.max_size(), \exposid{c}.values.max_size())}. \end{itemdescr} -\indexlibrarymember{emplace}{priority_queue}% +\rSec3[flat.map.access]{Access} + +\indexlibrarymember{operator[]}{flat_map}% \begin{itemdecl} -template void emplace(Args&&... args); +constexpr mapped_type& operator[](const key_type& x); \end{itemdecl} \begin{itemdescr} \pnum \effects -As if by: -\begin{codeblock} -c.emplace_back(std::forward(args)...); -push_heap(c.begin(), c.end(), comp); -\end{codeblock} +Equivalent to: \tcode{return try_emplace(x).first->second;} \end{itemdescr} - -\indexlibrarymember{pop}{priority_queue}% +\indexlibrarymember{operator[]}{flat_map}% \begin{itemdecl} -void pop(); +constexpr mapped_type& operator[](key_type&& x); \end{itemdecl} \begin{itemdescr} \pnum \effects -As if by: -\begin{codeblock} -pop_heap(c.begin(), c.end(), comp); -c.pop_back(); -\end{codeblock} +Equivalent to: \tcode{return try_emplace(std::move(x)).first->second;} \end{itemdescr} -\rSec3[priqueue.special]{Specialized algorithms} - -\indexlibrarymember{swap}{priority_queue}% +\indexlibrarymember{operator[]}{flat_map}% \begin{itemdecl} -template - void swap(priority_queue& x, - priority_queue& y) noexcept(noexcept(x.swap(y))); +template constexpr mapped_type& operator[](K&& x); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_swappable_v} is \tcode{true} and -\tcode{is_swappable_v} is \tcode{true}. +The \grammarterm{qualified-id} \tcode{Compare::is_transparent} is valid and +denotes a type. \pnum \effects -As if by \tcode{x.swap(y)}. +Equivalent to: \tcode{return try_emplace(std::forward(x)).first->second;} \end{itemdescr} -\rSec2[stack]{Class template \tcode{stack}} - -\rSec3[stack.general]{General} +\indexlibrarymember{at}{flat_map}% +\begin{itemdecl} +constexpr mapped_type& at(const key_type& x); +constexpr const mapped_type& at(const key_type& x) const; +\end{itemdecl} +\begin{itemdescr} \pnum -\indexlibraryglobal{stack}% -Any sequence container supporting operations -\tcode{back()}, -\tcode{push_back()} -and -\tcode{pop_back()} -can be used to instantiate -\tcode{stack}. -In particular, -\tcode{vector}\iref{vector}, -\tcode{list}\iref{list} -and -\tcode{deque}\iref{deque} -can be used. - -\rSec3[stack.defn]{Definition} - -\begin{codeblock} -namespace std { - template> - class stack { - public: - using value_type = typename Container::value_type; - using reference = typename Container::reference; - using const_reference = typename Container::const_reference; - using size_type = typename Container::size_type; - using container_type = Container; - - protected: - Container c; +\returns +A reference to the \tcode{mapped_type} corresponding +to \tcode{x} in \tcode{*this}. - public: - stack() : stack(Container()) {} - 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&); - template stack(const stack&, const Alloc&); - 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(); } - reference top() { return c.back(); } - const_reference top() const { return c.back(); } - void push(const value_type& x) { c.push_back(x); } - void push(value_type&& x) { c.push_back(std::move(x)); } - template<@\exposconcept{container-compatible-range}@ R> - void push_range(R&& rg); - template - decltype(auto) emplace(Args&&... args) - { return c.emplace_back(std::forward(args)...); } - void pop() { c.pop_back(); } - void swap(stack& s) noexcept(is_nothrow_swappable_v) - { using std::swap; swap(c, s.c); } - }; +\pnum +\throws +An exception object of type \tcode{out_of_range} if +no such element is present. - template - stack(Container) -> stack; +\pnum +\complexity +Logarithmic. +\end{itemdescr} - template - stack(InputIterator, InputIterator) -> stack<@\exposid{iter-value-type}@>; +\indexlibrarymember{at}{flat_map}% +\begin{itemdecl} +template constexpr mapped_type& at(const K& x); +template constexpr const mapped_type& at(const K& x) const; +\end{itemdecl} - template - stack(from_range_t, R&&) -> stack>; +\begin{itemdescr} +\pnum +\constraints +The \grammarterm{qualified-id} \tcode{Compare::is_transparent} +is valid and denotes a type. - template - stack(Container, Allocator) -> stack; +\pnum +\expects +The expression \tcode{find(x)} is well-formed and has well-defined behavior. - template - stack(InputIterator, InputIterator, Allocator) - -> stack<@\exposid{iter-value-type}@, deque<@\exposid{iter-value-type}@, - Allocator>>; +\pnum +\returns +A reference to the \tcode{mapped_type} corresponding to +\tcode{x} in \tcode{*this}. - template - stack(from_range_t, R&&, Allocator) - -> stack, deque, Allocator>>; +\pnum +\throws +An exception object of type \tcode{out_of_range} +if no such element is present. - template - struct uses_allocator, Alloc> - : uses_allocator::type { }; -} -\end{codeblock} +\pnum +\complexity +Logarithmic. +\end{itemdescr} -\rSec3[stack.cons]{Constructors} +\rSec3[flat.map.modifiers]{Modifiers} -\indexlibraryctor{stack}% +\indexlibrarymember{emplace}{flat_map}% \begin{itemdecl} -explicit stack(const Container& cont); +template constexpr pair emplace(Args&&... args); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v, Args...>} is \tcode{true}. + \pnum \effects -Initializes \tcode{c} with \tcode{cont}. +Initializes an object \tcode{t} of type \tcode{pair} +with \tcode{std::forward(\linebreak args)...}; +if the map already contains an element +whose key is equivalent to \tcode{t.first}, +\tcode{*this} is unchanged. +Otherwise, equivalent to: +\begin{codeblock} +auto key_it = ranges::upper_bound(@\exposid{c}@.keys, t.first, @\exposid{compare}@); +auto value_it = @\exposid{c}@.values.begin() + distance(@\exposid{c}@.keys.begin(), key_it); +@\exposid{c}@.keys.insert(key_it, std::move(t.first)); +@\exposid{c}@.values.insert(value_it, std::move(t.second)); +\end{codeblock} + +\pnum +\returns +The \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place, and +the iterator component of the pair points to +the element with key equivalent to \tcode{t.first}. \end{itemdescr} -\indexlibraryctor{stack}% +\indexlibrarymember{insert}{flat_map}% \begin{itemdecl} -explicit stack(Container&& cont); +template constexpr pair insert(P&& x); +template constexpr iterator insert(const_iterator position, P&& x); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v, P>} is \tcode{true}. + \pnum \effects -Initializes \tcode{c} with \tcode{std::move(cont)}. +The first form is equivalent to \tcode{return emplace(std::forward

(x));}. +The second form is equivalent to +\tcode{return emplace_hint(position, std::forward

(x));}. \end{itemdescr} -\indexlibraryctor{stack}% +\indexlibrarymember{insert}{flat_map}% \begin{itemdecl} template - stack(InputIterator first, InputIterator last); + constexpr void insert(InputIterator first, InputIterator last); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \tcode{c} with -\tcode{first} as the first argument and \tcode{last} as the second argument. +Adds elements to \exposid{c} as if by: +\begin{codeblock} +for (; first != last; ++first) { + value_type value = *first; + @\exposid{c}@.keys.insert(@\exposid{c}@.keys.end(), std::move(value.first)); + @\exposid{c}@.values.insert(@\exposid{c}@.values.end(), std::move(value.second)); +} +\end{codeblock} +Then, sorts the range of newly inserted elements +with respect to \tcode{value_comp()}; +merges the resulting sorted range and +the sorted range of pre-existing elements into a single sorted range; and +finally erases the duplicate elements as if by: +\begin{codeblock} +auto zv = views::zip(@\exposid{c}@.keys, @\exposid{c}@.values); +auto it = ranges::unique(zv, @\exposid{key-equiv}@(@\exposid{compare}@)).begin(); +auto dist = distance(zv.begin(), it); +@\exposid{c}@.keys.erase(@\exposid{c}@.keys.begin() + dist, @\exposid{c}@.keys.end()); +@\exposid{c}@.values.erase(@\exposid{c}@.values.begin() + dist, @\exposid{c}@.values.end()); +\end{codeblock} + +\pnum +\complexity +$N$ + $M \log M$, +where $N$ is \tcode{size()} before the operation and +$M$ is \tcode{distance(first, last)}. + +\pnum +\remarks +Since this operation performs an in-place merge, it may allocate memory. \end{itemdescr} -\indexlibraryctor{stack}% +\indexlibrarymember{insert}{flat_map}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - stack(from_range_t, R&& rg); +template + constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last); \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} +Adds elements to \exposid{c} as if by: +\begin{codeblock} +for (; first != last; ++first) { + value_type value = *first; + @\exposid{c}@.keys.insert(@\exposid{c}@.keys.end(), std::move(value.first)); + @\exposid{c}@.values.insert(@\exposid{c}@.values.end(), std::move(value.second)); +} +\end{codeblock} +Then, merges the sorted range of newly added elements and +the sorted range of pre-existing elements into a single sorted range; and +finally erases the duplicate elements as if by: +\begin{codeblock} +auto zv = views::zip(@\exposid{c}@.keys, @\exposid{c}@.values); +auto it = ranges::unique(zv, @\exposid{key-equiv}@(@\exposid{compare}@)).begin(); +auto dist = distance(zv.begin(), it); +@\exposid{c}@.keys.erase(@\exposid{c}@.keys.begin() + dist, @\exposid{c}@.keys.end()); +@\exposid{c}@.values.erase(@\exposid{c}@.values.begin() + dist, @\exposid{c}@.values.end()); +\end{codeblock} \pnum -If \tcode{uses_allocator_v} is \tcode{false} -the constructors in this subclause shall not participate in overload resolution. - -\indexlibraryctor{stack}% -\begin{itemdecl} -template explicit stack(const Alloc& a); -\end{itemdecl} +\complexity +Linear in $N$, where $N$ is \tcode{size()} after the operation. -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{a}. +\remarks +Since this operation performs an in-place merge, it may allocate memory. \end{itemdescr} -\indexlibraryctor{stack}% +\indexlibrarymember{insert_range}{flat_map}% \begin{itemdecl} -template stack(const container_type& cont, const Alloc& a); +template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \tcode{c} with \tcode{cont} as the first argument and \tcode{a} as the -second argument. +Adds elements to \exposid{c} as if by: +\begin{codeblock} +for (const auto& e : rg) { + @\exposid{c}@.keys.insert(@\exposid{c}@.keys.end(), e.first); + @\exposid{c}@.values.insert(@\exposid{c}@.values.end(), e.second); +} +\end{codeblock} +Then, sorts the range of newly inserted elements +with respect to \tcode{value_comp()}; +merges the resulting sorted range and +the sorted range of pre-existing elements into a single sorted range; and +finally erases the duplicate elements as if by: +\begin{codeblock} +auto zv = views::zip(@\exposid{c}@.keys, @\exposid{c}@.values); +auto it = ranges::unique(zv, @\exposid{key-equiv}@(@\exposid{compare}@)).begin(); +auto dist = distance(zv.begin(), it); +@\exposid{c}@.keys.erase(@\exposid{c}@.keys.begin() + dist, @\exposid{c}@.keys.end()); +@\exposid{c}@.values.erase(@\exposid{c}@.values.begin() + dist, @\exposid{c}@.values.end()); +\end{codeblock} + +\pnum +\complexity +$N$ + $M \log M$, +where $N$ is \tcode{size()} before the operation and +$M$ is \tcode{ranges::distance(rg)}. + +\pnum +\remarks +Since this operation performs an in-place merge, it may allocate memory. \end{itemdescr} -\indexlibraryctor{stack}% +\indexlibrarymember{try_emplace}{flat_map}% \begin{itemdecl} -template stack(container_type&& cont, const Alloc& a); +template + constexpr pair try_emplace(const key_type& k, Args&&... args); +template + constexpr pair try_emplace(key_type&& k, Args&&... args); +template + constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); +template + constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + \pnum \effects -Initializes \tcode{c} with \tcode{std::move(cont)} as the first argument and \tcode{a} -as the second argument. -\end{itemdescr} +If the map already contains an element whose key is equivalent to \tcode{k}, +\tcode{*this} and \tcode{args...} are unchanged. +Otherwise equivalent to: +\begin{codeblock} +auto key_it = ranges::upper_bound(@\exposid{c}@.keys, k, @\exposid{compare}@); +auto value_it = @\exposid{c}@.values.begin() + distance(@\exposid{c}@.keys.begin(), key_it); +@\exposid{c}@.keys.insert(key_it, std::forward(k)); +@\exposid{c}@.values.emplace(value_it, std::forward(args)...); +\end{codeblock} -\indexlibraryctor{stack}% -\begin{itemdecl} -template stack(const stack& s, const Alloc& a); -\end{itemdecl} +\pnum +\returns +In the first two overloads, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. -\begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{s.c} as the first argument and \tcode{a} -as the second argument. +\complexity +The same as \tcode{emplace} for the first two overloads, and +the same as \tcode{emplace_hint} for the last two overloads. \end{itemdescr} -\indexlibraryctor{stack}% +\indexlibrarymember{try_emplace}{flat_map}% \begin{itemdecl} -template stack(stack&& s, const Alloc& a); +template + constexpr pair try_emplace(K&& k, Args&&... args); +template + constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \tcode{c} with \tcode{std::move(s.c)} as the first argument and \tcode{a} -as the second argument. -\end{itemdescr} +\constraints +\begin{itemize} +\item +The \grammarterm{qualified-id} \tcode{Compare::is_transparent} +is valid and denotes a type. +\item +\tcode{is_constructible_v} is \tcode{true}. +\item +\tcode{is_constructible_v} is \tcode{true}. +\item +For the first overload, +\tcode{is_convertible_v} and +\tcode{is_convertible_v} are both \tcode{false}. +\end{itemize} -\indexlibraryctor{stack}% -\begin{itemdecl} -template - stack(InputIterator first, InputIterator last, const Alloc& alloc); -\end{itemdecl} +\pnum +\expects +The conversion from \tcode{k} into \tcode{key_type} constructs +an object \tcode{u}, +for which \tcode{find(k) == find(u)} is \tcode{true}. -\begin{itemdescr} \pnum \effects -Initializes \tcode{c} with -\tcode{first} as the first argument, -\tcode{last} as the second argument, and -\tcode{alloc} as the third argument. -\end{itemdescr} +If the map already contains an element whose key is equivalent to \tcode{k}, +\tcode{*this} and \tcode{args...} are unchanged. +Otherwise equivalent to: +\begin{codeblock} +auto key_it = upper_bound(@\exposid{c}@.keys.begin(), @\exposid{c}@.keys.end(), k, @\exposid{compare}@); +auto value_it = @\exposid{c}@.values.begin() + distance(@\exposid{c}@.keys.begin(), key_it); +@\exposid{c}@.keys.emplace(key_it, std::forward(k)); +@\exposid{c}@.values.emplace(value_it, std::forward(args)...); +\end{codeblock} -\indexlibraryctor{stack}% -\begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R, class Alloc> - stack(from_range_t, R&& rg, const Alloc& a); -\end{itemdecl} +\pnum +\returns +In the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. -\begin{itemdescr} \pnum -\effects -Initializes -\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}. +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. \end{itemdescr} -\rSec3[stack.mod]{Modifiers} - -\indexlibrarymember{push_range}{stack}% +\indexlibrarymember{insert_or_assign}{flat_map}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - void push_range(R&& rg); +template + constexpr pair insert_or_assign(const key_type& k, M&& obj); +template + constexpr pair insert_or_assign(key_type&& k, M&& obj); +template + constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); +template + constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); \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} +\constraints +\tcode{is_assignable_v} is \tcode{true} and +\tcode{is_constructible_v} is \tcode{true}. -\indexlibrarymember{operator==}{stack}% -\begin{itemdecl} -template - bool operator==(const stack& x, const stack& y); -\end{itemdecl} +\pnum +\effects +If the map already contains an element \tcode{e} +whose key is equivalent to \tcode{k}, +assigns \tcode{std::forward<\linebreak M>(obj)} to \tcode{e.second}. +Otherwise, equivalent to +\begin{codeblock} +try_emplace(std::forward(k), std::forward(obj)) +\end{codeblock} +for the first two overloads or +\begin{codeblock} +try_emplace(hint, std::forward(k), std::forward(obj)) +\end{codeblock} +for the last two overloads. -\begin{itemdescr} \pnum \returns -\tcode{x.c == y.c}. +In the first two overloads, the \tcode{bool} component of the returned pair +is \tcode{true} if and only if the insertion took place. The returned +iterator points to the map element whose key is equivalent to \tcode{k}. + +\pnum +\complexity +The same as \tcode{emplace} for the first two overloads and +the same as \tcode{emplace_hint} for the last two overloads. \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{stack}}% +\indexlibrarymember{insert_or_assign}{flat_map}% \begin{itemdecl} -template - bool operator!=(const stack& x, const stack& y); +template + constexpr pair insert_or_assign(K&& k, M&& obj); +template + constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.c != y.c}. -\end{itemdescr} +\constraints +\begin{itemize} +\item +The \grammarterm{qualified-id} \tcode{Compare::is_transparent} +is valid and denotes a type. +\item +\tcode{is_constructible_v} is \tcode{true}. +\item +\tcode{is_assignable_v} is \tcode{true}. +\item +\tcode{is_constructible_v} is \tcode{true}. +\end{itemize} -\indexlibrarymember{operator<}{stack}% -\begin{itemdecl} -template - bool operator< (const stack& x, const stack& y); -\end{itemdecl} +\pnum +\expects +The conversion from \tcode{k} into \tcode{key_type} constructs +an object \tcode{u}, for which \tcode{find(k) == find(u)} is \tcode{true}. + +\pnum +\effects +If the map already contains an element \tcode{e} +whose key is equivalent to \tcode{k}, +assigns \tcode{std::forward<\linebreak M>(obj)} to \tcode{e.second}. +Otherwise, equivalent to +\begin{codeblock} +try_emplace(std::forward(k), std::forward(obj)) +\end{codeblock} +for the first overload or +\begin{codeblock} +try_emplace(hint, std::forward(k), std::forward(obj)) +\end{codeblock} +for the second overload. -\begin{itemdescr} \pnum \returns -\tcode{x.c < y.c}. +In the first overload, +the \tcode{bool} component of the returned pair is \tcode{true} +if and only if the insertion took place. +The returned iterator points to the map element +whose key is equivalent to \tcode{k}. + +\pnum +\complexity +The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. \end{itemdescr} -\indexlibrarymember{operator>}{stack}% +\indexlibrarymember{swap}{flat_map}% \begin{itemdecl} -template - bool operator> (const stack& x, const stack& y); +constexpr void swap(flat_map& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.c > y.c}. +\effects +Equivalent to: +\begin{codeblock} +ranges::swap(@\exposid{compare}@, y.@\exposid{compare}@); +ranges::swap(@\exposid{c}@.keys, y.@\exposid{c}@.keys); +ranges::swap(@\exposid{c}@.values, y.@\exposid{c}@.values); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator<=}{stack}% +\indexlibrarymember{extract}{flat_map}% \begin{itemdecl} -template - bool operator<=(const stack& x, const stack& y); +constexpr containers extract() &&; \end{itemdecl} \begin{itemdescr} +\pnum +\ensures +\tcode{*this} is emptied, even if the function exits via an exception. + \pnum \returns -\tcode{x.c <= y.c}. +\tcode{std::move(\exposid{c})}. \end{itemdescr} -\indexlibrarymember{operator>=}{stack}% +\indexlibrarymember{replace}{flat_map}% \begin{itemdecl} -template - bool operator>=(const stack& x, const stack& y); +constexpr void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.c >= y.c}. +\expects +\tcode{key_cont.size() == mapped_cont.size()} is \tcode{true}, +the elements of \tcode{key_cont} are sorted with respect to \exposid{compare}, and +\tcode{key_cont} contains no equal elements. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{c}@.keys = std::move(key_cont); +@\exposid{c}@.values = std::move(mapped_cont); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator<=>}{stack}% +\rSec3[flat.map.erasure]{Erasure} + +\indexlibrarymember{erase_if}{flat_map}% \begin{itemdecl} -template - compare_three_way_result_t - operator<=>(const stack& x, const stack& y); +template + constexpr typename flat_map::size_type + erase_if(flat_map& c, Predicate pred); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.c <=> y.c}. -\end{itemdescr} - -\rSec3[stack.special]{Specialized algorithms} +\expects +\tcode{Key} and \tcode{T} meet the \oldconcept{MoveAssignable} requirements. -\indexlibrarymember{swap}{stack}% -\begin{itemdecl} -template - void swap(stack& x, stack& y) noexcept(noexcept(x.swap(y))); -\end{itemdecl} +\pnum +\effects +Let $E$ be \tcode{bool(pred(pair(e)))}. +Erases all elements \tcode{e} in \tcode{c} for which $E$ holds. -\begin{itemdescr} \pnum -\constraints -\tcode{is_swappable_v} is \tcode{true}. +\returns +The number of elements erased. \pnum -\effects -As if by \tcode{x.swap(y)}. +\complexity +Exactly \tcode{c.size()} applications of the predicate. + +\pnum +\remarks +Stable\iref{algorithm.stable}. +If an invocation of \tcode{erase_if} exits via an exception, +\tcode{c} is in a valid but unspecified state\iref{defns.valid}. +\begin{note} +\tcode{c} still meets its invariants, +but can be empty. +\end{note} \end{itemdescr} -\rSec2[flat.map]{Class template \tcode{flat_map}} +\rSec2[flat.multimap]{Class template \tcode{flat_multimap}} -\rSec3[flat.map.overview]{Overview} +\rSec3[flat.multimap.overview]{Overview} \pnum -\indexlibraryglobal{flat_map}% -A \tcode{flat_map} is a container adaptor +\indexlibraryglobal{flat_multimap}% +A \tcode{flat_multimap} is a container adaptor that provides an associative container interface -that supports unique keys -(i.e., contains at most one of each key value) and +that supports equivalent keys +(i.e., possibly containing multiple copies of the same key value) and provides for fast retrieval of values of another type \tcode{T} based on the keys. -\tcode{flat_map} supports iterators -that meet the \oldconcept{InputIterator} requirements and +\tcode{flat_multimap} supports iterators that meet +the \oldconcept{InputIterator} requirements and model the \libconcept{random_access_iterator} concept\iref{iterator.concept.random.access}. \pnum -A \tcode{flat_map} meets all of the requirements -of a container\iref{container.reqmts} and -of a reversible container\iref{container.rev.reqmts}, +A \tcode{flat_multimap} meets all of the requirements +for a container\iref{container.reqmts} and +for a reversible container\iref{container.rev.reqmts}, plus the optional container requirements\iref{container.opt.reqmts}. -\tcode{flat_map} meets the requirements of -an associative container\iref{associative.reqmts}, -except that: +\tcode{flat_multimap} meets the requirements of +an associative container\iref{associative.reqmts}, except that: \begin{itemize} \item it does not meet the requirements related to node handles\iref{container.node}, \item it does not meet the requirements related to iterator invalidation, and \item -the time complexity of the operations that insert or erase a single -element from the map is linear, including the ones that take an insertion -position iterator. +the time complexity of the operations +that insert or erase a single element from the map is linear, +including the ones that take an insertion position iterator. \end{itemize} \begin{note} -A \tcode{flat_map} does not meet the additional requirements of -an allocator-aware container\iref{container.alloc.reqmts}. +A \tcode{flat_multimap} does not meet the additional requirements of an +allocator-aware container\iref{container.alloc.reqmts}. \end{note} \pnum -A \tcode{flat_map} also provides most operations -described in \ref{associative.reqmts} for unique keys. -This means that a \tcode{flat_map} supports -the \tcode{a_uniq} operations in \ref{associative.reqmts} -but not the \tcode{a_eq} operations. -For a \tcode{flat_map} +A \tcode{flat_multimap} also provides most operations described +in \ref{associative.reqmts} for equal keys. +This means that a \tcode{flat_multimap} supports +the \tcode{a_eq} operations in \ref{associative.reqmts} +but not the \tcode{a_uniq} operations. +For a \tcode{flat_multimap} the \tcode{key_type} is \tcode{Key} and the \tcode{value_type} is \tcode{pair}. \pnum -Descriptions are provided here only for operations on \tcode{flat_map} that -are not described in one of those sets of requirements or for operations where -there is additional semantic information. +Except as otherwise noted, +operations on \tcode{flat_multimap} are equivalent to those of \tcode{flat_map}, +except that \tcode{flat_multimap} operations +do not remove or replace elements with equal keys. +\begin{example} +\tcode{flat_multimap} constructors and emplace do not erase +non-unique elements after sorting them. +\end{example} \pnum -A \tcode{flat_map} maintains the following invariants: +A \tcode{flat_multimap} maintains the following invariants: \begin{itemize} \item it contains the same number of keys and values; \item the keys are sorted with respect to the comparison object; and \item -the value at offset \tcode{off} within the value container is -the value associated with the key at offset \tcode{off} -within the key container. +the value at offset \tcode{off} within the value container is the value +associated with the key at offset \tcode{off} within the key container. \end{itemize} \pnum -If any member function in \ref{flat.map.defn} exits via an exception +If any member function in \ref{flat.multimap.defn} exits via an exception, the invariants are restored. \begin{note} -This can result in the \tcode{flat_map} being emptied. +This can result in the \tcode{flat_multimap} being emptied. \end{note} \pnum Any type \tcode{C} that meets the sequence container requirements\iref{sequence.reqmts} -can be used to instantiate \tcode{flat_map}, +can be used to instantiate \tcode{flat_multimap}, as long as \tcode{C::iterator} meets the \oldconcept{RandomAccessIterator} requirements and invocations of member functions \tcode{C::size} and \tcode{C::max_size} do not exit via an exception. -In particular, \tcode{vector}\iref{vector} and \tcode{deque}\iref{deque} -can be used. +In particular, +\tcode{vector}\iref{vector} and \tcode{deque}\iref{deque} can be used. \begin{note} \tcode{vector} is not a sequence container. \end{note} @@ -15155,25 +18250,27 @@ \pnum The effect of calling a constructor -that takes -both \tcode{key_container_type} and \tcode{mapped_container_type} arguments with -containers of different sizes is undefined. +that takes both \tcode{key_container_type} and +\tcode{mapped_container_type} arguments +with containers of different sizes is undefined. \pnum The effect of calling a constructor or member function -that takes a \tcode{sorted_unique_t} argument with -a container, containers, or range -that is not sorted with respect to \tcode{key_comp()}, or -that contains equal elements, -is undefined. +that takes a \tcode{sorted_equivalent_t} argument +with a container, containers, or range +that are not sorted with respect to \tcode{key_comp()} is undefined. -\rSec3[flat.map.defn]{Definition} +\pnum +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. + +\rSec3[flat.multimap.defn]{Definition} \begin{codeblock} namespace std { template, class KeyContainer = vector, class MappedContainer = vector> - class flat_map { + class flat_multimap { public: // types using key_type = Key; @@ -15184,8 +18281,8 @@ using const_reference = pair; using size_type = size_t; using difference_type = ptrdiff_t; - using iterator = @\impdefx{type of \tcode{flat_map::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{flat_map::const_iterator}}@; // see \ref{container.requirements} + using iterator = @\impdefx{type of \tcode{flat_multimap::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{flat_multimap::const_iterator}}@; // see \ref{container.requirements} using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; using key_container_type = KeyContainer; @@ -15193,12 +18290,12 @@ class value_compare { private: - key_compare comp; // \expos - value_compare(key_compare c) : comp(c) { } // \expos + key_compare @\exposid{comp}@; // \expos + constexpr value_compare(key_compare c) : @\exposid{comp}@(c) { } // \expos public: - bool operator()(const_reference x, const_reference y) const { - return comp(x.first, y.first); + constexpr bool operator()(const_reference x, const_reference y) const { + return @\exposid{comp}@(x.first, y.first); } }; @@ -15207,958 +18304,1100 @@ mapped_container_type values; }; - // \ref{flat.map.cons}, construct/copy/destroy - flat_map() : flat_map(key_compare()) { } - - template - flat_map(const flat_map&, const Allocator& a); - template - flat_map(flat_map&&, const Allocator& a); - - flat_map(key_container_type key_cont, mapped_container_type mapped_cont, - const key_compare& comp = key_compare()); - template - flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, - const Allocator& a); - template - flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, - const key_compare& comp, const Allocator& a); - - flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont, - const key_compare& comp = key_compare()); - template - flat_map(sorted_unique_t, const key_container_type& key_cont, - const mapped_container_type& mapped_cont, const Allocator& a); - template - flat_map(sorted_unique_t, const key_container_type& key_cont, - const mapped_container_type& mapped_cont, - const key_compare& comp, const Allocator& a); - - explicit flat_map(const key_compare& comp) - : c(), compare(comp) { } - template - flat_map(const key_compare& comp, const Allocator& a); - template - explicit flat_map(const Allocator& a); + // \ref{flat.multimap.cons}, constructors + constexpr flat_multimap() : flat_multimap(key_compare()) { } + + constexpr explicit flat_multimap(const key_compare& comp) + : @\exposid{c}@(), @\exposid{compare}@(comp) { } + + constexpr flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); + + constexpr flat_multimap(sorted_equivalent_t, + key_container_type key_cont, mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); + + template + constexpr flat_multimap(InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(), @\exposid{compare}@(comp) + { insert(first, last); } template - flat_map(InputIterator first, InputIterator last, const key_compare& comp = key_compare()) - : c(), compare(comp) { insert(first, last); } - template - flat_map(InputIterator first, InputIterator last, - const key_compare& comp, const Allocator& a); - template - flat_map(InputIterator first, InputIterator last, const Allocator& a); + constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(sorted_equivalent, first, last); } template<@\exposconcept{container-compatible-range}@ R> - flat_map(from_range_t fr, R&& rg) - : flat_map(fr, std::forward(rg), key_compare()) { } - template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_map(from_range_t, R&& rg, const Allocator& a); + constexpr flat_multimap(from_range_t, R&& rg) + : flat_multimap(from_range, std::forward(rg), key_compare()) { } template<@\exposconcept{container-compatible-range}@ R> - flat_map(from_range_t, R&& rg, const key_compare& comp) - : flat_map(comp) { insert_range(std::forward(rg)); } - template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_map(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); + constexpr flat_multimap(from_range_t, R&& rg, const key_compare& comp) + : flat_multimap(comp) { insert_range(std::forward(rg)); } + + constexpr flat_multimap(initializer_list il, + const key_compare& comp = key_compare()) + : flat_multimap(il.begin(), il.end(), comp) { } + + constexpr flat_multimap(sorted_equivalent_t, initializer_list il, + const key_compare& comp = key_compare()) + : flat_multimap(sorted_equivalent, il.begin(), il.end(), comp) { } + + // \ref{flat.multimap.cons.alloc}, constructors with allocators + + template + constexpr explicit flat_multimap(const Alloc& a); + template + constexpr flat_multimap(const key_compare& comp, const Alloc& a); + template + constexpr flat_multimap(const key_container_type& key_cont, + const mapped_container_type& mapped_cont, const Alloc& a); + template + constexpr flat_multimap(const key_container_type& key_cont, + const mapped_container_type& mapped_cont, + const key_compare& comp, const Alloc& a); + template + constexpr flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, + const mapped_container_type& mapped_cont, const Alloc& a); + template + constexpr flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, + const mapped_container_type& mapped_cont, + const key_compare& comp, const Alloc& a); + template + constexpr flat_multimap(const flat_multimap&, const Alloc& a); + template + constexpr flat_multimap(flat_multimap&&, const Alloc& a); + template + constexpr flat_multimap(InputIterator first, InputIterator last, const Alloc& a); + template + constexpr flat_multimap(InputIterator first, InputIterator last, + const key_compare& comp, const Alloc& a); + template + constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, + const Alloc& a); + template + constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, + const key_compare& comp, const Alloc& a); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_multimap(from_range_t, R&& rg, const Alloc& a); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); + template + constexpr flat_multimap(initializer_list il, const Alloc& a); + template + constexpr flat_multimap(initializer_list il, const key_compare& comp, + const Alloc& a); + template + constexpr flat_multimap(sorted_equivalent_t, initializer_list il, + const Alloc& a); + template + constexpr flat_multimap(sorted_equivalent_t, initializer_list il, + const key_compare& comp, const Alloc& a); + + flat_multimap& operator=(initializer_list); + + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; + + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + // capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; + + // modifiers + template constexpr iterator emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); + + constexpr iterator insert(const value_type& x) + { return emplace(x); } + constexpr iterator insert(value_type&& x) + { return emplace(std::move(x)); } + constexpr iterator insert(const_iterator position, const value_type& x) + { return emplace_hint(position, x); } + constexpr iterator insert(const_iterator position, value_type&& x) + { return emplace_hint(position, std::move(x)); } + template constexpr iterator insert(P&& x); + template + constexpr iterator insert(const_iterator position, P&&); template - flat_map(sorted_unique_t s, InputIterator first, InputIterator last, - const key_compare& comp = key_compare()) - : c(), compare(comp) { insert(s, first, last); } - template - flat_map(sorted_unique_t, InputIterator first, InputIterator last, - const key_compare& comp, const Allocator& a); - template - flat_map(sorted_unique_t, InputIterator first, InputIterator last, const Allocator& a); - - flat_map(initializer_list il, const key_compare& comp = key_compare()) - : flat_map(il.begin(), il.end(), comp) { } - template - flat_map(initializer_list il, const key_compare& comp, const Allocator& a); - template - flat_map(initializer_list il, const Allocator& a); + constexpr void insert(InputIterator first, InputIterator last); + template + constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); - flat_map(sorted_unique_t s, initializer_list il, - const key_compare& comp = key_compare()) - : flat_map(s, il.begin(), il.end(), comp) { } - template - flat_map(sorted_unique_t, initializer_list il, - const key_compare& comp, const Allocator& a); - template - flat_map(sorted_unique_t, initializer_list il, const Allocator& a); + constexpr void insert(initializer_list il) + { insert(il.begin(), il.end()); } + constexpr void insert(sorted_equivalent_t, initializer_list il) + { insert(sorted_equivalent, il.begin(), il.end()); } + + constexpr containers extract() &&; + constexpr void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); + + constexpr iterator erase(iterator position); + constexpr iterator erase(const_iterator position); + constexpr size_type erase(const key_type& x); + template constexpr size_type erase(K&& x); + constexpr iterator erase(const_iterator first, const_iterator last); + + constexpr void swap(flat_multimap&) noexcept; + constexpr void clear() noexcept; + + // observers + constexpr key_compare key_comp() const; + constexpr value_compare value_comp() const; + + constexpr const key_container_type& keys() const noexcept { return @\exposid{c}@.keys; } + constexpr const mapped_container_type& values() const noexcept { return @\exposid{c}@.values; } + + // map operations + constexpr iterator find(const key_type& x); + constexpr const_iterator find(const key_type& x) const; + template constexpr iterator find(const K& x); + template constexpr const_iterator find(const K& x) const; + + constexpr size_type count(const key_type& x) const; + template constexpr size_type count(const K& x) const; + + constexpr bool contains(const key_type& x) const; + template constexpr bool contains(const K& x) const; + + constexpr iterator lower_bound(const key_type& x); + constexpr const_iterator lower_bound(const key_type& x) const; + template constexpr iterator lower_bound(const K& x); + template constexpr const_iterator lower_bound(const K& x) const; + + constexpr iterator upper_bound(const key_type& x); + constexpr const_iterator upper_bound(const key_type& x) const; + template constexpr iterator upper_bound(const K& x); + template constexpr const_iterator upper_bound(const K& x) const; + + constexpr pair equal_range(const key_type& x); + constexpr pair equal_range(const key_type& x) const; + template + constexpr pair equal_range(const K& x); + template + constexpr pair equal_range(const K& x) const; + + friend constexpr bool operator==(const flat_multimap& x, const flat_multimap& y); + + friend constexpr @\exposid{synth-three-way-result}@ + operator<=>(const flat_multimap& x, const flat_multimap& y); + + friend constexpr void swap(flat_multimap& x, flat_multimap& y) noexcept + { x.swap(y); } + + private: + containers @\exposid{c}@; // \expos + key_compare @\exposid{compare}@; // \expos + }; + + template> + flat_multimap(KeyContainer, MappedContainer, Compare = Compare()) + -> flat_multimap; + + template + flat_multimap(KeyContainer, MappedContainer, Allocator) + -> flat_multimap, KeyContainer, MappedContainer>; + template + flat_multimap(KeyContainer, MappedContainer, Compare, Allocator) + -> flat_multimap; + + template> + flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Compare = Compare()) + -> flat_multimap; + + template + flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Allocator) + -> flat_multimap, KeyContainer, MappedContainer>; + template + flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Compare, Allocator) + -> flat_multimap; + + template>> + flat_multimap(InputIterator, InputIterator, Compare = Compare()) + -> flat_multimap<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; + + template>> + flat_multimap(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare()) + -> flat_multimap<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; + + template>, + class Allocator = allocator> + flat_multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> flat_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Compare, + vector<@\exposid{range-key-type}@, + @\exposid{alloc-rebind}@>>, + vector<@\exposid{range-mapped-type}@, + @\exposid{alloc-rebind}@>>>; + + template + flat_multimap(from_range_t, R&&, Allocator) + -> flat_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, less<@\exposid{range-key-type}@>, + vector<@\exposid{range-key-type}@, + @\exposid{alloc-rebind}@>>, + vector<@\exposid{range-mapped-type}@, + @\exposid{alloc-rebind}@>>>; - flat_map& operator=(initializer_list il); + template> + flat_multimap(initializer_list>, Compare = Compare()) + -> flat_multimap; - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; + template> + flat_multimap(sorted_equivalent_t, initializer_list>, Compare = Compare()) + -> flat_multimap; - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; + template + struct uses_allocator, + Allocator> + : bool_constant && + uses_allocator_v> { }; +} +\end{codeblock} - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; +\pnum +The member type \tcode{containers} has the data members and special members +specified above. It has no base classes or members other than those +specified. - // \ref{flat.map.capacity}, capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; +\rSec3[flat.multimap.cons]{Constructors} - // \ref{flat.map.access}, element access - mapped_type& operator[](const key_type& x); - mapped_type& operator[](key_type&& x); - template mapped_type& operator[](K&& x); - mapped_type& at(const key_type& x); - const mapped_type& at(const key_type& x) const; - template mapped_type& at(const K& x); - template const mapped_type& at(const K& x) const; +\indexlibraryctor{flat_multimap}% +\begin{itemdecl} +constexpr flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); +\end{itemdecl} - // \ref{flat.map.modifiers}, modifiers - template pair emplace(Args&&... args); - template - iterator emplace_hint(const_iterator position, Args&&... args); +\begin{itemdescr} +\pnum +\effects +Initializes +\tcode{\exposid{c}.keys} with \tcode{std::move(key_cont)}, +\tcode{\exposid{c}.values} with \tcode{std::move(mapped_cont)}, and +\exposid{compare} with \tcode{comp}; +sorts the range \range{begin()}{end()} with respect to \tcode{value_comp()}. - pair insert(const value_type& x) - { return emplace(x); } - pair insert(value_type&& x) - { return emplace(std::move(x)); } - iterator insert(const_iterator position, const value_type& x) - { return emplace_hint(position, x); } - iterator insert(const_iterator position, value_type&& x) - { return emplace_hint(position, std::move(x)); } +\pnum +\complexity +Linear in $N$ if the container arguments are already sorted +with respect to \tcode{value_comp()} and otherwise $N \log N$, +where $N$ is the value of \tcode{key_cont.size()} before this call. +\end{itemdescr} - template pair insert(P&& x); - template - iterator insert(const_iterator position, P&&); - template - void insert(InputIterator first, InputIterator last); - template - void insert(sorted_unique_t, InputIterator first, InputIterator last); - template<@\exposconcept{container-compatible-range}@ R> - void insert_range(R&& rg); +\indexlibraryctor{flat_multimap}% +\begin{itemdecl} +constexpr flat_multimap(sorted_equivalent_t, key_container_type key_cont, + mapped_container_type mapped_cont, + const key_compare& comp = key_compare()); +\end{itemdecl} - void insert(initializer_list il) - { insert(il.begin(), il.end()); } - void insert(sorted_unique_t s, initializer_list il) - { insert(s, il.begin(), il.end()); } +\begin{itemdescr} +\pnum +\effects +Initializes +\tcode{\exposid{c}.keys} with \tcode{std::move(key_cont)}, +\tcode{\exposid{c}.values} with \tcode{std::move(mapped_cont)}, and +\exposid{compare} with \tcode{comp}. - containers extract() &&; - void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); +\pnum +\complexity +Constant. +\end{itemdescr} - template - pair try_emplace(const key_type& k, Args&&... args); - template - pair try_emplace(key_type&& k, Args&&... args); - template - pair try_emplace(K&& k, Args&&... args); - template - iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); - template - iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); - template - iterator try_emplace(const_iterator hint, K&& k, Args&&... args); - template - pair insert_or_assign(const key_type& k, M&& obj); - template - pair insert_or_assign(key_type&& k, M&& obj); - template - pair insert_or_assign(K&& k, M&& obj); - template - iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); - template - iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); - template - iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); +\rSec3[flat.multimap.cons.alloc]{Constructors with allocators} - iterator erase(iterator position); - iterator erase(const_iterator position); - size_type erase(const key_type& x); - template size_type erase(K&& x); - iterator erase(const_iterator first, const_iterator last); +\pnum +The constructors in this subclause shall not participate in overload resolution +unless \tcode{uses_allocator_v} is \tcode{true} +and \tcode{uses_allocator_v} is \tcode{true}. - void swap(flat_map& y) noexcept; - void clear() noexcept; +\indexlibraryctor{flat_multimap}% +\begin{itemdecl} +template + constexpr flat_multimap(const key_container_type& key_cont, + const mapped_container_type& mapped_cont, const Alloc& a); +template + constexpr flat_multimap(const key_container_type& key_cont, + const mapped_container_type& mapped_cont, + const key_compare& comp, const Alloc& a); +\end{itemdecl} - // observers - key_compare key_comp() const; - value_compare value_comp() const; +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{flat_multimap(key_cont, mapped_cont)} and +\tcode{flat_multimap(key_cont, \linebreak{}mapped_cont, comp)}, respectively, +except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed +with uses-allocator construction\iref{allocator.uses.construction}. - const key_container_type& keys() const noexcept { return c.keys; } - const mapped_container_type& values() const noexcept { return c.values; } +\pnum +\complexity +Same as \tcode{flat_multimap(key_cont, mapped_cont)} and +\tcode{flat_multimap(key_cont, \linebreak{}mapped_cont, comp)}, respectively. +\end{itemdescr} - // map operations - iterator find(const key_type& x); - const_iterator find(const key_type& x) const; - template iterator find(const K& x); - template const_iterator find(const K& x) const; +\indexlibraryctor{flat_multimap}% +\begin{itemdecl} +template + constexpr flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, + const mapped_container_type& mapped_cont, const Alloc& a); +template + constexpr flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, + const mapped_container_type& mapped_cont, const key_compare& comp, + const Alloc& a); +\end{itemdecl} - size_type count(const key_type& x) const; - template size_type count(const K& x) const; +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{flat_multimap(sorted_equivalent, key_cont, mapped_cont)} and +\tcode{flat_multimap(sorted_equivalent, key_cont, mapped_cont, comp)}, respectively, +except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.val\-ues} are constructed +with uses-allocator construction\iref{allocator.uses.construction}. - bool contains(const key_type& x) const; - template bool contains(const K& x) const; +\pnum +\complexity +Linear. +\end{itemdescr} - iterator lower_bound(const key_type& x); - const_iterator lower_bound(const key_type& x) const; - template iterator lower_bound(const K& x); - template const_iterator lower_bound(const K& x) const; +\indexlibraryctor{flat_multimap}% +\begin{itemdecl} +template + constexpr explicit flat_multimap(const Alloc& a); +template + constexpr flat_multimap(const key_compare& comp, const Alloc& a); +template + constexpr flat_multimap(const flat_multimap&, const Alloc& a); +template + constexpr flat_multimap(flat_multimap&&, const Alloc& a); +template + constexpr flat_multimap(InputIterator first, InputIterator last, const Alloc& a); +template + constexpr flat_multimap(InputIterator first, InputIterator last, const key_compare& comp, + const Alloc& a); +template + constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, + const Alloc& a); +template + constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, + const key_compare& comp, const Alloc& a); +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_multimap(from_range_t, R&& rg, const Alloc& a); +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); +template + constexpr flat_multimap(initializer_list il, const Alloc& a); +template + constexpr flat_multimap(initializer_list il, const key_compare& comp, + const Alloc& a); +template + constexpr flat_multimap(sorted_equivalent_t, initializer_list il, const Alloc& a); +template + constexpr flat_multimap(sorted_equivalent_t, initializer_list il, + const key_compare& comp, const Alloc& a); +\end{itemdecl} - iterator upper_bound(const key_type& x); - const_iterator upper_bound(const key_type& x) const; - template iterator upper_bound(const K& x); - template const_iterator upper_bound(const K& x) const; +\begin{itemdescr} +\pnum +\effects +Equivalent to the corresponding non-allocator constructors +except that \tcode{\exposid{c}.keys} and \tcode{\exposid{c}.values} are constructed +with uses-allocator construction\iref{allocator.uses.construction}. +\end{itemdescr} - pair equal_range(const key_type& x); - pair equal_range(const key_type& x) const; - template pair equal_range(const K& x); - template pair equal_range(const K& x) const; +\rSec3[flat.multimap.erasure]{Erasure} - friend bool operator==(const flat_map& x, const flat_map& y); +\indexlibrarymember{erase_if}{flat_multimap}% +\begin{itemdecl} +template + constexpr typename flat_multimap::size_type + erase_if(flat_multimap& c, Predicate pred); +\end{itemdecl} - friend @\exposid{synth-three-way-result}@ - operator<=>(const flat_map& x, const flat_map& y); +\begin{itemdescr} +\pnum +\expects +\tcode{Key} and \tcode{T} meet the \oldconcept{MoveAssignable} requirements. - friend void swap(flat_map& x, flat_map& y) noexcept - { x.swap(y); } +\pnum +\effects +Let $E$ be \tcode{bool(pred(pair(e)))}. +Erases all elements \tcode{e} in \tcode{c} for which $E$ holds. - private: - containers c; // \expos - key_compare compare; // \expos +\pnum +\returns +The number of elements erased. - struct key_equiv { // \expos - key_equiv(key_compare c) : comp(c) { } - bool operator()(const_reference x, const_reference y) const { - return !comp(x.first, y.first) && !comp(y.first, x.first); - } - key_compare comp; - }; - }; +\pnum +\complexity +Exactly \tcode{c.size()} applications of the predicate. - template> - flat_map(KeyContainer, MappedContainer, Compare = Compare()) - -> flat_map; +\pnum +\remarks +Stable\iref{algorithm.stable}. +If an invocation of \tcode{erase_if} exits via an exception, +\tcode{c} is in a valid but unspecified state\iref{defns.valid}. +\begin{note} +\tcode{c} still meets its invariants, +but can be empty. +\end{note} +\end{itemdescr} - template - flat_map(KeyContainer, MappedContainer, Allocator) - -> flat_map, KeyContainer, MappedContainer>; - template - flat_map(KeyContainer, MappedContainer, Compare, Allocator) - -> flat_map; +\rSec2[flat.set.syn]{Header \tcode{} synopsis}% +\indexheader{flat_set}% - template> - flat_map(sorted_unique_t, KeyContainer, MappedContainer, Compare = Compare()) - -> flat_map; +\begin{codeblock} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} - template - flat_map(sorted_unique_t, KeyContainer, MappedContainer, Allocator) - -> flat_map, KeyContainer, MappedContainer>; - template - flat_map(sorted_unique_t, KeyContainer, MappedContainer, Compare, Allocator) - -> flat_map; +namespace std { + // \ref{flat.set}, class template \tcode{flat_set} + template, class KeyContainer = vector> + class flat_set; - template>> - flat_map(InputIterator, InputIterator, Compare = Compare()) - -> flat_map<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; + struct sorted_unique_t { explicit sorted_unique_t() = default; }; + inline constexpr sorted_unique_t sorted_unique{}; - template>> - flat_map(sorted_unique_t, InputIterator, InputIterator, Compare = Compare()) - -> flat_map<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; + template + struct uses_allocator, Allocator>; - template>, - class Allocator = allocator> - flat_map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) - -> flat_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Compare, - vector<@\exposid{range-key-type}@, @\exposid{alloc-rebind}@>>, - vector<@\exposid{range-mapped-type}@, @\exposid{alloc-rebind}@>>>; + // \ref{flat.set.erasure}, erasure for \tcode{flat_set} + template + constexpr typename flat_set::size_type + erase_if(flat_set& c, Predicate pred); - template - flat_map(from_range_t, R&&, Allocator) - -> flat_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, less<@\exposid{range-key-type}@>, - vector<@\exposid{range-key-type}@, @\exposid{alloc-rebind}@>>, - vector<@\exposid{range-mapped-type}@, @\exposid{alloc-rebind}@>>>; + // \ref{flat.multiset}, class template \tcode{flat_multiset} + template, class KeyContainer = vector> + class flat_multiset; - template> - flat_map(initializer_list>, Compare = Compare()) - -> flat_map; + struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; }; + inline constexpr sorted_equivalent_t sorted_equivalent{}; - template> - flat_map(sorted_unique_t, initializer_list>, Compare = Compare()) - -> flat_map; + template + struct uses_allocator, Allocator>; - template - struct uses_allocator, Allocator> - : bool_constant && - uses_allocator_v> { }; + // \ref{flat.multiset.erasure}, erasure for \tcode{flat_multiset} + template + constexpr typename flat_multiset::size_type + erase_if(flat_multiset& c, Predicate pred); } \end{codeblock} -\pnum -The member type \tcode{containers} has the data members and special members -specified above. -It has no base classes or members other than those specified. +\rSec2[flat.set]{Class template \tcode{flat_set}} -\rSec3[flat.map.cons]{Constructors} +\rSec3[flat.set.overview]{Overview} -\indexlibraryctor{flat_map}% -\begin{itemdecl} -flat_map(key_container_type key_cont, mapped_container_type mapped_cont, - const key_compare& comp = key_compare()); -\end{itemdecl} +\pnum +\indexlibraryglobal{flat_set}% +A \tcode{flat_set} is a container adaptor +that provides an associative container interface +that supports unique keys +(i.e., contains at most one of each key value) and +provides for fast retrieval of the keys themselves. +\tcode{flat_set} supports iterators that model +the \libconcept{random_access_iterator} concept\iref{iterator.concept.random.access}. -\begin{itemdescr} \pnum -\effects -Initializes -\tcode{c.keys} with \tcode{std::move(key_cont)}, -\tcode{c.values} with \tcode{std::move(mapped_cont)}, and -\tcode{compare} with \tcode{comp}; -sorts the range \range{begin()}{end()} with respect to \tcode{value_comp()}; and -finally erases the duplicate elements as if by: -\begin{codeblock} -auto zv = views::zip(c.keys, c.values); -auto it = ranges::unique(zv, key_equiv(compare)).begin(); -auto dist = distance(zv.begin(), it); -c.keys.erase(c.keys.begin() + dist, c.keys.end()); -c.values.erase(c.values.begin() + dist, c.values.end()); -\end{codeblock} +A \tcode{flat_set} meets all of the requirements +for a container\iref{container.reqmts} and +for a reversible container\iref{container.rev.reqmts}, +plus the optional container requirements\iref{container.opt.reqmts}. +\tcode{flat_set} meets the requirements of +an associative container\iref{associative.reqmts}, except that: +\begin{itemize} +\item +it does not meet the requirements +related to node handles\iref{container.node.overview}, +\item +it does not meet the requirements related to iterator invalidation, and +\item +the time complexity of the operations +that insert or erase a single element from the set +is linear, +including the ones that take an insertion position iterator. +\end{itemize} +\begin{note} +A \tcode{flat_set} does not meet +the additional requirements of an allocator-aware container, +as described in \ref{container.alloc.reqmts}. +\end{note} \pnum -\complexity -Linear in $N$ if the container arguments are already sorted -with respect to \tcode{value_comp()} and otherwise $N \log N$, -where $N$ is the value of \tcode{key_cont.size()} before this call. -\end{itemdescr} +A \tcode{flat_set} also provides most operations +described in \ref{associative.reqmts} for unique keys. +This means that a \tcode{flat_set} supports +the \tcode{a_uniq} operations in \ref{associative.reqmts} +but not the \tcode{a_eq} operations. +For a \tcode{flat_set}, +both the \tcode{key_type} and \tcode{value_type} are \tcode{Key}. -\indexlibraryctor{flat_map}% -\begin{itemdecl} -template - flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, - const Allocator& a); -template - flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, - const key_compare& comp, const Allocator& a); -\end{itemdecl} +\pnum +Descriptions are provided here only for operations on \tcode{flat_set} +that are not described in one of those sets of requirements or +for operations where there is additional semantic information. -\begin{itemdescr} \pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true} and -\tcode{uses_allocator_v} is \tcode{true}. +A \tcode{flat_set} maintains the invariant that the keys are sorted with +respect to the comparison object. \pnum -\effects -Equivalent to \tcode{flat_map(key_cont, mapped_cont)} and -\tcode{flat_map(key_cont, mapped_cont, comp)}, respectively, -except that \tcode{c.keys} and \tcode{c.values} are constructed with -uses-allocator construction\iref{allocator.uses.construction}. +If any member function in \ref{flat.set.defn} exits via an exception, +the invariant is restored. +\begin{note} +This can result in the \tcode{flat_set}'s being emptied. +\end{note} \pnum -\complexity -Same as \tcode{flat_map(key_cont, mapped_cont)} and -\tcode{flat_map(key_cont, mapped_cont, comp)}, respectively. -\end{itemdescr} +Any sequence container\iref{sequence.reqmts} +supporting \oldconcept{RandomAccessIterator} +can be used to instantiate \tcode{flat_set}. +In particular, \tcode{vector}\iref{vector} and \tcode{deque}\iref{deque} +can be used. +\begin{note} +\tcode{vector} is not a sequence container. +\end{note} -\indexlibraryctor{flat_map}% -\begin{itemdecl} -flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont, - const key_compare& comp = key_compare()); -\end{itemdecl} +\pnum +The program is ill-formed if \tcode{Key} is not the same type +as \tcode{KeyContainer::value_type}. -\begin{itemdescr} \pnum -\effects -Initializes -\tcode{c.keys} with \tcode{std::move(key_cont)}, -\tcode{c.values} with \tcode{std::move(mapped_cont)}, and -\tcode{compare} with \tcode{comp}. +The effect of calling a constructor or member function +that takes a \tcode{sorted_unique_t} argument +with a range that is not sorted with respect to \tcode{key_comp()}, or +that contains equal elements, is undefined. \pnum -\complexity -Constant. -\end{itemdescr} +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. -\indexlibraryctor{flat_map}% -\begin{itemdecl} -template - flat_map(sorted_unique_t s, const key_container_type& key_cont, - const mapped_container_type& mapped_cont, const Allocator& a); -template - flat_map(sorted_unique_t s, const key_container_type& key_cont, - const mapped_container_type& mapped_cont, const key_compare& comp, - const Allocator& a); -\end{itemdecl} +\rSec3[flat.set.defn]{Definition} -\begin{itemdescr} -\pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true} and -\tcode{uses_allocator_v} is \tcode{true}. +\begin{codeblock} +namespace std { + template, class KeyContainer = vector> + class @\libglobal{flat_set}@ { + public: + // types + using key_type = Key; + using value_type = Key; + using key_compare = Compare; + using value_compare = Compare; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = typename KeyContainer::size_type; + using difference_type = typename KeyContainer::difference_type; + using iterator = @\impdefx{type of \tcode{flat_set::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{flat_set::const_iterator}}@; // see \ref{container.requirements} + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using container_type = KeyContainer; -\pnum -\effects -Equivalent to \tcode{flat_map(s, key_cont, mapped_cont)} and -\tcode{flat_map(s, key_cont, \linebreak{}mapped_cont, comp)}, respectively, -except that \tcode{c.keys} and \tcode{c.values} are constructed -with uses-allocator construction\iref{allocator.uses.construction}. + // \ref{flat.set.cons}, constructors + constexpr flat_set() : flat_set(key_compare()) { } -\pnum -\complexity -Linear. -\end{itemdescr} + constexpr explicit flat_set(const key_compare& comp) + : @\exposid{c}@(), @\exposid{compare}@(comp) { } -\indexlibraryctor{flat_map}% -\begin{itemdecl} -template - flat_map(const flat_map&, const Allocator& a); -template - flat_map(flat_map&&, const Allocator& a); -template - flat_map(const key_compare& comp, const Allocator& a); -template - explicit flat_map(const Allocator& a); -template - flat_map(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); -template - flat_map(InputIterator first, InputIterator last, const Allocator& a); -template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_map(from_range_t, R&& rg, const Allocator& a); -template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_map(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); -template - flat_map(sorted_unique_t, InputIterator first, InputIterator last, - const key_compare& comp, const Allocator& a); -template - flat_map(sorted_unique_t, InputIterator first, InputIterator last, const Allocator& a); -template - flat_map(initializer_list il, const key_compare& comp, const Allocator& a); -template - flat_map(initializer_list il, const Allocator& a); -template - flat_map(sorted_unique_t, initializer_list il, - const key_compare& comp, const Allocator& a); -template - flat_map(sorted_unique_t, initializer_list il, const Allocator& a); -\end{itemdecl} + constexpr explicit flat_set(container_type cont, const key_compare& comp = key_compare()); -\begin{itemdescr} -\pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true} and -\tcode{uses_allocator_v} is \tcode{true}. + constexpr flat_set(sorted_unique_t, container_type cont, + const key_compare& comp = key_compare()) + : @\exposid{c}@(std::move(cont)), @\exposid{compare}@(comp) { } -\pnum -\effects -Equivalent to the corresponding non-allocator constructors -except that \tcode{c.keys} and \tcode{c.values} are constructed -with uses-allocator construction\iref{allocator.uses.construction}. -\end{itemdescr} + template + constexpr flat_set(InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(), @\exposid{compare}@(comp) + { insert(first, last); } -\rSec3[flat.map.capacity]{Capacity} + template + constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(first, last), @\exposid{compare}@(comp) { } -\indexlibrarymember{size}{flat_map}% -\begin{itemdecl} -size_type size() const noexcept; -\end{itemdecl} + template<@\exposconcept{container-compatible-range}@ R> + constexpr flat_set(from_range_t, R&& rg) + : flat_set(from_range, std::forward(rg), key_compare()) { } + template<@\exposconcept{container-compatible-range}@ R> + constexpr flat_set(from_range_t, R&& rg, const key_compare& comp) + : flat_set(comp) + { insert_range(std::forward(rg)); } -\begin{itemdescr} -\pnum -\returns -\tcode{c.keys.size()}. -\end{itemdescr} + constexpr flat_set(initializer_list il, const key_compare& comp = key_compare()) + : flat_set(il.begin(), il.end(), comp) { } -\indexlibrarymember{max_size}{flat_map}% -\begin{itemdecl} -size_type max_size() const noexcept; -\end{itemdecl} + constexpr flat_set(sorted_unique_t, initializer_list il, + const key_compare& comp = key_compare()) + : flat_set(sorted_unique, il.begin(), il.end(), comp) { } + + // \ref{flat.set.cons.alloc}, constructors with allocators + + template + constexpr explicit flat_set(const Alloc& a); + template + constexpr flat_set(const key_compare& comp, const Alloc& a); + template + constexpr flat_set(const container_type& cont, const Alloc& a); + template + constexpr flat_set(const container_type& cont, const key_compare& comp, const Alloc& a); + template + constexpr flat_set(sorted_unique_t, const container_type& cont, const Alloc& a); + template + constexpr flat_set(sorted_unique_t, const container_type& cont, + const key_compare& comp, const Alloc& a); + template + constexpr flat_set(const flat_set&, const Alloc& a); + template + constexpr flat_set(flat_set&&, const Alloc& a); + template + constexpr flat_set(InputIterator first, InputIterator last, const Alloc& a); + template + constexpr flat_set(InputIterator first, InputIterator last, + const key_compare& comp, const Alloc& a); + template + constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last, + const Alloc& a); + template + constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last, + const key_compare& comp, const Alloc& a); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_set(from_range_t, R&& rg, const Alloc& a); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_set(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); + template + constexpr flat_set(initializer_list il, const Alloc& a); + template + constexpr flat_set(initializer_list il, const key_compare& comp, + const Alloc& a); + template + constexpr flat_set(sorted_unique_t, initializer_list il, const Alloc& a); + template + constexpr flat_set(sorted_unique_t, initializer_list il, + const key_compare& comp, const Alloc& a); + + constexpr flat_set& operator=(initializer_list); -\begin{itemdescr} -\pnum -\returns -\tcode{min(c.keys.max_size(), c.values.max_size())}. -\end{itemdescr} + // iterators + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; -\rSec3[flat.map.access]{Access} + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; -\indexlibrarymember{operator[]}{flat_map}% -\begin{itemdecl} -mapped_type& operator[](const key_type& x); -\end{itemdecl} + 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; -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return try_emplace(x).first->second;} -\end{itemdescr} + // capacity + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; -\indexlibrarymember{operator[]}{flat_map}% -\begin{itemdecl} -mapped_type& operator[](key_type&& x); -\end{itemdecl} + // \ref{flat.set.modifiers}, modifiers + template constexpr pair emplace(Args&&... args); + template + constexpr iterator emplace_hint(const_iterator position, Args&&... args); -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return try_emplace(std::move(x)).first->second;} -\end{itemdescr} + constexpr pair insert(const value_type& x) + { return emplace(x); } + constexpr pair insert(value_type&& x) + { return emplace(std::move(x)); } + template constexpr pair insert(K&& x); + constexpr iterator insert(const_iterator position, const value_type& x) + { return emplace_hint(position, x); } + constexpr iterator insert(const_iterator position, value_type&& x) + { return emplace_hint(position, std::move(x)); } + template constexpr iterator insert(const_iterator hint, K&& x); -\indexlibrarymember{operator[]}{flat_map}% -\begin{itemdecl} -template mapped_type& operator[](K&& x); -\end{itemdecl} + template + constexpr void insert(InputIterator first, InputIterator last); + template + constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); -\begin{itemdescr} -\pnum -\constraints -The \grammarterm{qualified-id} \tcode{Compare::is_transparent} is valid and -denotes a type. + constexpr void insert(initializer_list il) + { insert(il.begin(), il.end()); } + constexpr void insert(sorted_unique_t, initializer_list il) + { insert(sorted_unique, il.begin(), il.end()); } -\pnum -\effects -Equivalent to: \tcode{return try_emplace(std::forward(x)).first->second;} -\end{itemdescr} + constexpr container_type extract() &&; + constexpr void replace(container_type&&); -\indexlibrarymember{at}{flat_map}% -\begin{itemdecl} -mapped_type& at(const key_type& x); -const mapped_type& at(const key_type& x) const; -\end{itemdecl} + constexpr iterator erase(iterator position); + constexpr iterator erase(const_iterator position); + constexpr size_type erase(const key_type& x); + template constexpr size_type erase(K&& x); + constexpr iterator erase(const_iterator first, const_iterator last); -\begin{itemdescr} -\pnum -\returns -A reference to the \tcode{mapped_type} corresponding -to \tcode{x} in \tcode{*this}. + constexpr void swap(flat_set& y) noexcept; + constexpr void clear() noexcept; + + // observers + constexpr key_compare key_comp() const; + constexpr value_compare value_comp() const; + + // set operations + constexpr iterator find(const key_type& x); + constexpr const_iterator find(const key_type& x) const; + template constexpr iterator find(const K& x); + template constexpr const_iterator find(const K& x) const; + + constexpr size_type count(const key_type& x) const; + template constexpr size_type count(const K& x) const; -\pnum -\throws -An exception object of type \tcode{out_of_range} if -no such element is present. + constexpr bool contains(const key_type& x) const; + template constexpr bool contains(const K& x) const; -\pnum -\complexity -Logarithmic. -\end{itemdescr} + constexpr iterator lower_bound(const key_type& x); + constexpr const_iterator lower_bound(const key_type& x) const; + template constexpr iterator lower_bound(const K& x); + template constexpr const_iterator lower_bound(const K& x) const; -\indexlibrarymember{at}{flat_map}% -\begin{itemdecl} -template mapped_type& at(const K& x); -template const mapped_type& at(const K& x) const; -\end{itemdecl} + constexpr iterator upper_bound(const key_type& x); + constexpr const_iterator upper_bound(const key_type& x) const; + template constexpr iterator upper_bound(const K& x); + template constexpr const_iterator upper_bound(const K& x) const; -\begin{itemdescr} -\pnum -\constraints -The \grammarterm{qualified-id} \tcode{Compare::is_transparent} -is valid and denotes a type. + constexpr pair equal_range(const key_type& x); + constexpr pair equal_range(const key_type& x) const; + template + constexpr pair equal_range(const K& x); + template + constexpr pair equal_range(const K& x) const; -\pnum -\expects -The expression \tcode{find(x)} is well-formed and has well-defined behavior. + friend constexpr bool operator==(const flat_set& x, const flat_set& y); -\pnum -\returns -A reference to the \tcode{mapped_type} corresponding to -\tcode{x} in \tcode{*this}. + friend constexpr @\placeholder{synth-three-way-result}@ + operator<=>(const flat_set& x, const flat_set& y); -\pnum -\throws -An exception object of type \tcode{out_of_range} -if no such element is present. + friend constexpr void swap(flat_set& x, flat_set& y) noexcept { x.swap(y); } -\pnum -\complexity -Logarithmic. -\end{itemdescr} + private: + container_type @\exposidnc{c}@; // \expos + key_compare @\exposidnc{compare}@; // \expos + }; -\rSec3[flat.map.modifiers]{Modifiers} + template> + flat_set(KeyContainer, Compare = Compare()) + -> flat_set; + template + flat_set(KeyContainer, Allocator) + -> flat_set, KeyContainer>; + template + flat_set(KeyContainer, Compare, Allocator) + -> flat_set; -\indexlibrarymember{emplace}{flat_map}% -\begin{itemdecl} -template pair emplace(Args&&... args); -\end{itemdecl} + template> + flat_set(sorted_unique_t, KeyContainer, Compare = Compare()) + -> flat_set; + template + flat_set(sorted_unique_t, KeyContainer, Allocator) + -> flat_set, KeyContainer>; + template + flat_set(sorted_unique_t, KeyContainer, Compare, Allocator) + -> flat_set; -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v, Args...>} is \tcode{true}. + template>> + flat_set(InputIterator, InputIterator, Compare = Compare()) + -> flat_set<@\placeholder{iter-value-type}@, Compare>; -\pnum -\effects -Initializes an object \tcode{t} of type \tcode{pair} -with \tcode{std::forward(\linebreak args)...}; -if the map already contains an element -whose key is equivalent to \tcode{t.first}, -\tcode{*this} is unchanged. -Otherwise, equivalent to: -\begin{codeblock} -auto key_it = ranges::upper_bound(c.keys, t.first, compare); -auto value_it = c.values.begin() + distance(c.keys.begin(), key_it); -c.keys.insert(key_it, std::move(t.first)); -c.values.insert(value_it, std::move(t.second)); -\end{codeblock} + template>> + flat_set(sorted_unique_t, InputIterator, InputIterator, Compare = Compare()) + -> flat_set<@\placeholder{iter-value-type}@, Compare>; -\pnum -\returns -The \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place, and -the iterator component of the pair points to -the element with key equivalent to \tcode{t.first}. -\end{itemdescr} + template>, + class Allocator = allocator>> + flat_set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> flat_set, Compare, + vector, + @\exposid{alloc-rebind}@>>>; -\indexlibrarymember{insert}{flat_map}% -\begin{itemdecl} -template pair insert(P&& x); -template iterator insert(const_iterator position, P&& x); -\end{itemdecl} + template + flat_set(from_range_t, R&&, Allocator) + -> flat_set, less>, + vector, + @\exposid{alloc-rebind}@>>>; -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v, P>} is \tcode{true}. + template> + flat_set(initializer_list, Compare = Compare()) + -> flat_set; -\pnum -\effects -The first form is equivalent to \tcode{return emplace(std::forward

(x));}. -The second form is equivalent to -\tcode{return emplace_hint(position, std::forward

(x));}. -\end{itemdescr} + template> + flat_set(sorted_unique_t, initializer_list, Compare = Compare()) + -> flat_set; -\indexlibrarymember{insert}{flat_map}% + template + struct uses_allocator, Allocator> + : bool_constant> { }; +} +\end{codeblock} + +\rSec3[flat.set.cons]{Constructors} + +\indexlibraryctor{flat_set}% \begin{itemdecl} -template - void insert(InputIterator first, InputIterator last); +constexpr explicit flat_set(container_type cont, const key_compare& comp = key_compare()); \end{itemdecl} \begin{itemdescr} \pnum \effects -Adds elements to \tcode{c} as if by: -\begin{codeblock} -for (; first != last; ++first) { - value_type value = *first; - c.keys.insert(c.keys.end(), std::move(value.first)); - c.values.insert(c.values.end(), std::move(value.second)); -} -\end{codeblock} -Then, sorts the range of newly inserted elements -with respect to \tcode{value_comp()}; -merges the resulting sorted range and -the sorted range of pre-existing elements into a single sorted range; and -finally erases the duplicate elements as if by: -\begin{codeblock} -auto zv = views::zip(c.keys, c.values); -auto it = ranges::unique(zv, key_equiv(compare)).begin(); -auto dist = distance(zv.begin(), it); -c.keys.erase(c.keys.begin() + dist, c.keys.end()); -c.values.erase(c.values.begin() + dist, c.values.end()); -\end{codeblock} +Initializes \exposid{c} with \tcode{std::move(cont)} and +\exposid{compare} with \tcode{comp}, +sorts the range \range{begin()}{end()} with respect to \exposid{compare}, and +finally erases all but the first element +from each group of consecutive equivalent elements. \pnum \complexity -$N$ + $M \log M$, -where $N$ is \tcode{size()} before the operation and -$M$ is \tcode{distance(first, last)}. +Linear in $N$ if \tcode{cont} is already sorted with respect to \exposid{compare} and +otherwise $N \log N$, where $N$ is the value of \tcode{cont.size()} before this call. +\end{itemdescr} + +\rSec3[flat.set.cons.alloc]{Constructors with allocators} \pnum -\remarks -Since this operation performs an in-place merge, it may allocate memory. -\end{itemdescr} +The constructors in this subclause shall not participate in overload resolution +unless \tcode{uses_allocator_v} is \tcode{true}. -\indexlibrarymember{insert}{flat_map}% +\indexlibraryctor{flat_set}% \begin{itemdecl} -template - void insert(sorted_unique_t, InputIterator first, InputIterator last); +template + constexpr flat_set(const container_type& cont, const Alloc& a); +template + constexpr flat_set(const container_type& cont, const key_compare& comp, const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum \effects -Adds elements to \tcode{c} as if by: -\begin{codeblock} -for (; first != last; ++first) { - value_type value = *first; - c.keys.insert(c.keys.end(), std::move(value.first)); - c.values.insert(c.values.end(), std::move(value.second)); -} -\end{codeblock} -Then, merges the sorted range of newly added elements and -the sorted range of pre-existing elements into a single sorted range; and -finally erases the duplicate elements as if by: -\begin{codeblock} -auto zv = views::zip(c.keys, c.values); -auto it = ranges::unique(zv, key_equiv(compare)).begin(); -auto dist = distance(zv.begin(), it); -c.keys.erase(c.keys.begin() + dist, c.keys.end()); -c.values.erase(c.values.begin() + dist, c.values.end()); -\end{codeblock} +Equivalent to +\tcode{flat_set(cont)} and \tcode{flat_set(cont, comp)}, respectively, +except that \exposid{c} is constructed with +uses-allocator construction\iref{allocator.uses.construction}. \pnum \complexity -Linear in $N$, where $N$ is \tcode{size()} after the operation. - -\pnum -\remarks -Since this operation performs an in-place merge, it may allocate memory. +Same as \tcode{flat_set(cont)} and \tcode{flat_set(cont, comp)}, respectively. \end{itemdescr} -\indexlibrarymember{insert_range}{flat_map}% +\indexlibraryctor{flat_set}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - void insert_range(R&& rg); +template + constexpr flat_set(sorted_unique_t, const container_type& cont, const Alloc& a); +template + constexpr flat_set(sorted_unique_t, const container_type& cont, + const key_compare& comp, const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum \effects -Adds elements to \tcode{c} as if by: -\begin{codeblock} -for (const auto& e : rg) { - c.keys.insert(c.keys.end(), e.first); - c.values.insert(c.values.end(), e.second); -} -\end{codeblock} -Then, sorts the range of newly inserted elements -with respect to \tcode{value_comp()}; -merges the resulting sorted range and -the sorted range of pre-existing elements into a single sorted range; and -finally erases the duplicate elements as if by: -\begin{codeblock} -auto zv = views::zip(c.keys, c.values); -auto it = ranges::unique(zv, key_equiv(compare)).begin(); -auto dist = distance(zv.begin(), it); -c.keys.erase(c.keys.begin() + dist, c.keys.end()); -c.values.erase(c.values.begin() + dist, c.values.end()); -\end{codeblock} +Equivalent to +\tcode{flat_set(sorted_unique, cont)} and +\tcode{flat_set(sorted_unique, cont,\linebreak comp)}, respectively, +except that \exposid{c} is constructed with +uses-allocator construction\iref{allocator.uses.construction}. \pnum \complexity -$N$ + $M \log M$, -where $N$ is \tcode{size()} before the operation and -$M$ is \tcode{ranges::distance(rg)}. - -\pnum -\remarks -Since this operation performs an in-place merge, it may allocate memory. +Linear. \end{itemdescr} -\indexlibrarymember{try_emplace}{flat_map}% +\indexlibraryctor{flat_set}% \begin{itemdecl} -template - pair try_emplace(const key_type& k, Args&&... args); -template - pair try_emplace(key_type&& k, Args&&... args); -template - iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); -template - iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); +template + constexpr explicit flat_set(const Alloc& a); +template + constexpr flat_set(const key_compare& comp, const Alloc& a); +template + constexpr flat_set(const flat_set&, const Alloc& a); +template + constexpr flat_set(flat_set&&, const Alloc& a); +template + constexpr flat_set(InputIterator first, InputIterator last, const Alloc& a); +template + constexpr flat_set(InputIterator first, InputIterator last, const key_compare& comp, + const Alloc& a); +template + constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last, const Alloc& a); +template + constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last, + const key_compare& comp, const Alloc& a); +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_set(from_range_t, R&& rg, const Alloc& a); +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_set(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); +template + constexpr flat_set(initializer_list il, const Alloc& a); +template + constexpr flat_set(initializer_list il, const key_compare& comp, const Alloc& a); +template + constexpr flat_set(sorted_unique_t, initializer_list il, const Alloc& a); +template + constexpr flat_set(sorted_unique_t, initializer_list il, + const key_compare& comp, const Alloc& a); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. - \pnum \effects -If the map already contains an element whose key is equivalent to \tcode{k}, -\tcode{*this} and \tcode{args...} are unchanged. -Otherwise equivalent to: -\begin{codeblock} -auto key_it = ranges::upper_bound(c.keys, k, compare); -auto value_it = c.values.begin() + distance(c.keys.begin(), key_it); -c.keys.insert(key_it, std::forward(k)); -c.values.emplace(value_it, std::forward(args)...); -\end{codeblock} - -\pnum -\returns -In the first two overloads, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. - -\pnum -\complexity -The same as \tcode{emplace} for the first two overloads, and -the same as \tcode{emplace_hint} for the last two overloads. +Equivalent to the corresponding non-allocator constructors +except that \exposid{c} is constructed with +uses-allocator construction\iref{allocator.uses.construction}. \end{itemdescr} -\indexlibrarymember{try_emplace}{flat_map}% +\rSec3[flat.set.modifiers]{Modifiers} + +\indexlibrarymember{insert}{flat_set}% \begin{itemdecl} -template - pair try_emplace(K&& k, Args&&... args); -template - iterator try_emplace(const_iterator hint, K&& k, Args&&... args); +template constexpr pair insert(K&& x); +template constexpr iterator insert(const_iterator hint, K&& x); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\begin{itemize} -\item The \grammarterm{qualified-id} \tcode{Compare::is_transparent} is valid and denotes a type. -\item -\tcode{is_constructible_v} is \tcode{true}. -\item -\tcode{is_constructible_v} is \tcode{true}. -\item -For the first overload, -\tcode{is_convertible_v} and -\tcode{is_convertible_v} are both \tcode{false}. -\end{itemize} +\tcode{is_constructi\-ble_v} is \tcode{true}. \pnum \expects -The conversion from \tcode{k} into \tcode{key_type} constructs -an object \tcode{u}, -for which \tcode{find(k) == find(u)} is \tcode{true}. +The conversion from \tcode{x} into \tcode{value_type} constructs +an object \tcode{u}, for which \tcode{find(x) == find(u)} is \tcode{true}. \pnum \effects -If the map already contains an element whose key is equivalent to \tcode{k}, -\tcode{*this} and \tcode{args...} are unchanged. -Otherwise equivalent to: -\begin{codeblock} -auto key_it = ranges::upper_bound(c.keys, k, compare); -auto value_it = c.values.begin() + distance(c.keys.begin(), key_it); -c.keys.emplace(key_it, std::forward(k)); -c.values.emplace(value_it, std::forward(args)...); -\end{codeblock} +If the set already contains an element equivalent to \tcode{x}, +\tcode{*this} and \tcode{x} are unchanged. +Otherwise, +inserts a new element as if by \tcode{emplace(std::forward(x))}. \pnum \returns In the first overload, the \tcode{bool} component of the returned pair is \tcode{true} if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. - -\pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. +The returned iterator points to the element +whose key is equivalent to \tcode{x}. \end{itemdescr} -\indexlibrarymember{insert_or_assign}{flat_map}% +\indexlibrarymember{insert}{flat_set}% \begin{itemdecl} -template - pair insert_or_assign(const key_type& k, M&& obj); -template - pair insert_or_assign(key_type&& k, M&& obj); -template - iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); -template - iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); +template + constexpr void insert(InputIterator first, InputIterator last); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{is_assignable_v} is \tcode{true} and -\tcode{is_constructible_v} is \tcode{true}. - \pnum \effects -If the map already contains an element \tcode{e} -whose key is equivalent to \tcode{k}, -assigns \tcode{std::forward<\linebreak M>(obj)} to \tcode{e.second}. -Otherwise, equivalent to -\begin{codeblock} -try_emplace(std::forward(k), std::forward(obj)) -\end{codeblock} -for the first two overloads or +Adds elements to \exposid{c} as if by: \begin{codeblock} -try_emplace(hint, std::forward(k), std::forward(obj)) +@\exposid{c}@.insert(@\exposid{c}@.end(), first, last); \end{codeblock} -for the last two overloads. +Then, +sorts the range of newly inserted elements with respect to \exposid{compare}; +merges the resulting sorted range and +the sorted range of pre-existing elements into a single sorted range; and +finally erases all but the first element +from each group of consecutive equivalent elements. \pnum -\returns -In the first two overloads, the \tcode{bool} component of the returned pair -is \tcode{true} if and only if the insertion took place. The returned -iterator points to the map element whose key is equivalent to \tcode{k}. +\complexity +$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and +$M$ is \tcode{distance(first, last)}. \pnum -\complexity -The same as \tcode{emplace} for the first two overloads and -the same as \tcode{emplace_hint} for the last two overloads. +\remarks +Since this operation performs an in-place merge, it may allocate memory. \end{itemdescr} -\indexlibrarymember{insert_or_assign}{flat_map}% +\indexlibrarymember{insert}{flat_set}% \begin{itemdecl} -template - pair insert_or_assign(K&& k, M&& obj); -template - iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); +template + constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item -The \grammarterm{qualified-id} \tcode{Compare::is_transparent} -is valid and denotes a type. -\item -\tcode{is_constructible_v} is \tcode{true}. -\item -\tcode{is_assignable_v} is \tcode{true}. -\item -\tcode{is_constructible_v} is \tcode{true}. -\end{itemize} +\effects +Equivalent to \tcode{insert(first, last)}. \pnum -\expects -The conversion from \tcode{k} into \tcode{key_type} constructs -an object \tcode{u}, for which \tcode{find(k) == find(u)} is \tcode{true}. +\complexity +Linear. +\end{itemdescr} + +\indexlibrarymember{insert_range}{flat_set}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr void insert_range(R&& rg); +\end{itemdecl} +\begin{itemdescr} \pnum \effects -If the map already contains an element \tcode{e} -whose key is equivalent to \tcode{k}, -assigns \tcode{std::forward<\linebreak M>(obj)} to \tcode{e.second}. -Otherwise, equivalent to -\begin{codeblock} -try_emplace(std::forward(k), std::forward(obj)) -\end{codeblock} -for the first overload or +Adds elements to \exposid{c} as if by: \begin{codeblock} -try_emplace(hint, std::forward(k), std::forward(obj)) +for (const auto& e : rg) { + @\exposid{c}@.insert(@\exposid{c}@.end(), e); +} \end{codeblock} -for the second overload. +Then, +sorts the range of newly inserted elements with respect to \exposid{compare}; +merges the resulting sorted range and +the sorted range of pre-existing elements into a single sorted range; and +finally erases all but the first element +from each group of consecutive equivalent elements. \pnum -\returns -In the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the map element -whose key is equivalent to \tcode{k}. +\complexity +$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and $M$ +is \tcode{ranges::distance(rg)}. \pnum -\complexity -The same as \tcode{emplace} and \tcode{emplace_hint}, respectively. +\remarks +Since this operation performs an in-place merge, it may allocate memory. \end{itemdescr} -\indexlibrarymember{swap}{flat_map}% +\indexlibrarymember{swap}{flat_set}% \begin{itemdecl} -void swap(flat_map& y) noexcept; +constexpr void swap(flat_set& y) noexcept; \end{itemdecl} \begin{itemdescr} @@ -16166,15 +19405,14 @@ \effects Equivalent to: \begin{codeblock} -ranges::swap(compare, y.compare); -ranges::swap(c.keys, y.c.keys); -ranges::swap(c.values, y.c.values); +ranges::swap(@\exposid{compare}@, y.@\exposid{compare}@); +ranges::swap(@\exposid{c}@, y.@\exposid{c}@); \end{codeblock} \end{itemdescr} -\indexlibrarymember{extract}{flat_map}% +\indexlibrarymember{extract}{flat_set}% \begin{itemdecl} -containers extract() &&; +constexpr container_type extract() &&; \end{itemdecl} \begin{itemdescr} @@ -16184,48 +19422,42 @@ \pnum \returns -\tcode{std::move(c)}. +\tcode{std::move(\exposid{c})}. \end{itemdescr} -\indexlibrarymember{replace}{flat_map}% +\indexlibrarymember{replace}{flat_set}% \begin{itemdecl} -void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); +constexpr void replace(container_type&& cont); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{key_cont.size() == mapped_cont.size()} is \tcode{true}, -the elements of \tcode{key_cont} are sorted with respect to \tcode{compare}, and -\tcode{key_cont} contains no equal elements. +The elements of \tcode{cont} are sorted with respect to \exposid{compare}, and +\tcode{cont} contains no equal elements. \pnum \effects -Equivalent to: -\begin{codeblock} -c.keys = std::move(key_cont); -c.values = std::move(mapped_cont); -\end{codeblock} +Equivalent to: \tcode{\exposid{c} = std::move(cont);} \end{itemdescr} -\rSec3[flat.map.erasure]{Erasure} +\rSec3[flat.set.erasure]{Erasure} -\indexlibrarymember{erase_if}{flat_map}% +\indexlibrarymember{erase_if}{flat_set}% \begin{itemdecl} -template - typename flat_map::size_type - erase_if(flat_map& c, Predicate pred); +template + constexpr typename flat_set::size_type + erase_if(flat_set& c, Predicate pred); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{Key} and \tcode{T} meet the \oldconcept{MoveAssignable} requirements. +\tcode{Key} meets the \oldconcept{MoveAssignable} requirements. \pnum \effects -Let $E$ be \tcode{bool(pred(pair(e)))}. +Let $E$ be \tcode{bool(pred(as_const(e)))}. Erases all elements \tcode{e} in \tcode{c} for which $E$ holds. \pnum @@ -16242,97 +19474,78 @@ If an invocation of \tcode{erase_if} exits via an exception, \tcode{c} is in a valid but unspecified state\iref{defns.valid}. \begin{note} -\tcode{c} still meets its invariants, -but can be empty. +\tcode{c} still meets its invariants, but can be empty. \end{note} \end{itemdescr} -\rSec2[flat.multimap]{Class template \tcode{flat_multimap}} +\rSec2[flat.multiset]{Class template \tcode{flat_multiset}} -\rSec3[flat.multimap.overview]{Overview} +\rSec3[flat.multiset.overview]{Overview} \pnum -\indexlibraryglobal{flat_multimap}% -A \tcode{flat_multimap} is a container adaptor +\indexlibraryglobal{flat_multiset}% +A \tcode{flat_multiset} is a container adaptor that provides an associative container interface that supports equivalent keys (i.e., possibly containing multiple copies of the same key value) and -provides for fast retrieval of values of another type \tcode{T} -based on the keys. -\tcode{flat_multimap} supports iterators that meet -the \oldconcept{InputIterator} requirements and -model the +provides for fast retrieval of the keys themselves. +\tcode{flat_multiset} supports iterators that model the \libconcept{random_access_iterator} concept\iref{iterator.concept.random.access}. \pnum -A \tcode{flat_multimap} meets all of the requirements +A \tcode{flat_multiset} meets all of the requirements for a container\iref{container.reqmts} and for a reversible container\iref{container.rev.reqmts}, plus the optional container requirements\iref{container.opt.reqmts}. -\tcode{flat_multimap} meets the requirements of +\tcode{flat_multiset} meets the requirements of an associative container\iref{associative.reqmts}, except that: \begin{itemize} \item -it does not meet the requirements related to node handles\iref{container.node}, +it does not meet the requirements +related to node handles\iref{container.node.overview}, \item it does not meet the requirements related to iterator invalidation, and \item the time complexity of the operations -that insert or erase a single element from the map is linear, +that insert or erase a single element from the +set is linear, including the ones that take an insertion position iterator. \end{itemize} \begin{note} -A \tcode{flat_multimap} does not meet the additional requirements of an -allocator-aware container\iref{container.alloc.reqmts}. +A \tcode{flat_multiset} does not meet +the additional requirements of an allocator-aware container, +as described in \ref{container.alloc.reqmts}. \end{note} \pnum -A \tcode{flat_multimap} also provides most operations described -in \ref{associative.reqmts} for equal keys. -This means that a \tcode{flat_multimap} supports +A \tcode{flat_multiset} also provides most operations +described in \ref{associative.reqmts} for equal keys. +This means that a \tcode{flat_multiset} supports the \tcode{a_eq} operations in \ref{associative.reqmts} but not the \tcode{a_uniq} operations. -For a \tcode{flat_multimap} -the \tcode{key_type} is \tcode{Key} and -the \tcode{value_type} is \tcode{pair}. +For a \tcode{flat_multiset}, +both the \tcode{key_type} and \tcode{value_type} are \tcode{Key}. \pnum -Except as otherwise noted, -operations on \tcode{flat_multimap} are equivalent to those of \tcode{flat_map}, -except that \tcode{flat_multimap} operations -do not remove or replace elements with equal keys. -\begin{example} -\tcode{flat_multimap} constructors and emplace do not erase -non-unique elements after sorting them. -\end{example} +Descriptions are provided here only for operations on \tcode{flat_multiset} +that are not described in one of the general sections or +for operations where there is additional semantic information. \pnum -A \tcode{flat_multimap} maintains the following invariants: -\begin{itemize} -\item -it contains the same number of keys and values; -\item -the keys are sorted with respect to the comparison object; and -\item -the value at offset \tcode{off} within the value container is the value -associated with the key at offset \tcode{off} within the key container. -\end{itemize} +A \tcode{flat_multiset} maintains the invariant +that the keys are sorted with respect to the comparison object. \pnum -If any member function in \ref{flat.multimap.defn} exits via an exception, -the invariants are restored. +If any member function in \ref{flat.multiset.defn} exits via an exception, +the invariant is restored. \begin{note} -This can result in the \tcode{flat_multimap} being emptied. +This can result in the \tcode{flat_multiset}'s being emptied. \end{note} \pnum -Any type \tcode{C} -that meets the sequence container requirements\iref{sequence.reqmts} -can be used to instantiate \tcode{flat_multimap}, -as long as -\tcode{C::iterator} meets the \oldconcept{RandomAccessIterator} requirements and -invocations of -member functions \tcode{C::size} and \tcode{C::max_size} do not exit via an exception. +Any sequence container\iref{sequence.reqmts} +supporting \oldconcept{RandomAccessIterator} +can be used to instantiate \tcode{flat_multiset}. In particular, \tcode{vector}\iref{vector} and \tcode{deque}\iref{deque} can be used. \begin{note} @@ -16340,505 +19553,538 @@ \end{note} \pnum -The program is ill-formed if -\tcode{Key} is not the same type as \tcode{KeyContainer::value_type} or -\tcode{T} is not the same type as \tcode{MappedContainer::value_type}. +The program is ill-formed if \tcode{Key} is not the same type +as \tcode{KeyContainer::value_type}. \pnum -The effect of calling a constructor -that takes both \tcode{key_container_type} and -\tcode{mapped_container_type} arguments -with containers of different sizes is undefined. +The effect of calling a constructor or member function +that takes a \tcode{sorted_equivalent_t} argument with a range +that is not sorted with respect to \tcode{key_comp()} is undefined. \pnum -The effect of calling a constructor or member function -that takes a \tcode{sorted_equivalent_t} argument -with a container, containers, or range -that are not sorted with respect to \tcode{key_comp()} is undefined. +The types \tcode{iterator} and \tcode{const_iterator} meet +the constexpr iterator requirements\iref{iterator.requirements.general}. -\rSec3[flat.multimap.defn]{Definition} +\rSec3[flat.multiset.defn]{Definition} \begin{codeblock} namespace std { - template, - class KeyContainer = vector, class MappedContainer = vector> - class flat_multimap { + template, class KeyContainer = vector> + class flat_multiset { public: // types - using key_type = Key; - using mapped_type = T; - using value_type = pair; - using key_compare = Compare; - using reference = pair; - using const_reference = pair; - using size_type = size_t; - using difference_type = ptrdiff_t; - using iterator = @\impdefx{type of \tcode{flat_multimap::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{flat_multimap::const_iterator}}@; // see \ref{container.requirements} - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - using key_container_type = KeyContainer; - using mapped_container_type = MappedContainer; - - class value_compare { - private: - key_compare comp; // \expos - value_compare(key_compare c) : comp(c) { } // \expos - - public: - bool operator()(const_reference x, const_reference y) const { - return comp(x.first, y.first); - } - }; + using key_type = Key; + using value_type = Key; + using key_compare = Compare; + using value_compare = Compare; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = typename KeyContainer::size_type; + using difference_type = typename KeyContainer::difference_type; + using iterator = @\impdefx{type of \tcode{flat_multiset::iterator}}@; // see \ref{container.requirements} + using const_iterator = @\impdefx{type of \tcode{flat_multiset::const_iterator}}@; // see \ref{container.requirements} + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + using container_type = KeyContainer; - struct containers { - key_container_type keys; - mapped_container_type values; - }; + // \ref{flat.multiset.cons}, constructors + constexpr flat_multiset() : flat_multiset(key_compare()) { } - // \ref{flat.multimap.cons}, construct/copy/destroy - flat_multimap() : flat_multimap(key_compare()) { } + constexpr explicit flat_multiset(const key_compare& comp) + : @\exposid{c}@(), @\exposid{compare}@(comp) { } - template - flat_multimap(const flat_multimap&, const Allocator& a); - template - flat_multimap(flat_multimap&&, const Allocator& a); + constexpr explicit flat_multiset(container_type cont, + const key_compare& comp = key_compare()); - flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont, - const key_compare& comp = key_compare()); - template - flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, - const Allocator& a); - template - flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, - const key_compare& comp, const Allocator& a); - - flat_multimap(sorted_equivalent_t, - key_container_type key_cont, mapped_container_type mapped_cont, - const key_compare& comp = key_compare()); - template - flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, - const mapped_container_type& mapped_cont, const Allocator& a); - template - flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, - const mapped_container_type& mapped_cont, - const key_compare& comp, const Allocator& a); - - explicit flat_multimap(const key_compare& comp) - : c(), compare(comp) { } - template - flat_multimap(const key_compare& comp, const Allocator& a); - template - explicit flat_multimap(const Allocator& a); + constexpr flat_multiset(sorted_equivalent_t, container_type cont, + const key_compare& comp = key_compare()) + : @\exposid{c}@(std::move(cont)), @\exposid{compare}@(comp) { } template - flat_multimap(InputIterator first, InputIterator last, - const key_compare& comp = key_compare()) - : c(), compare(comp) + constexpr flat_multiset(InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(), @\exposid{compare}@(comp) { insert(first, last); } - template - flat_multimap(InputIterator first, InputIterator last, - const key_compare& comp, const Allocator& a); - template - flat_multimap(InputIterator first, InputIterator last, const Allocator& a); + + template + constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, + const key_compare& comp = key_compare()) + : @\exposid{c}@(first, last), @\exposid{compare}@(comp) { } template<@\exposconcept{container-compatible-range}@ R> - flat_multimap(from_range_t fr, R&& rg) - : flat_multimap(fr, std::forward(rg), key_compare()) { } - template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_multimap(from_range_t, R&& rg, const Allocator& a); + constexpr flat_multiset(from_range_t, R&& rg) + : flat_multiset(from_range, std::forward(rg), key_compare()) { } template<@\exposconcept{container-compatible-range}@ R> - flat_multimap(from_range_t, R&& rg, const key_compare& comp) - : flat_multimap(comp) { insert_range(std::forward(rg)); } - template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); + constexpr flat_multiset(from_range_t, R&& rg, const key_compare& comp) + : flat_multiset(comp) + { insert_range(std::forward(rg)); } - template - flat_multimap(sorted_equivalent_t s, InputIterator first, InputIterator last, - const key_compare& comp = key_compare()) - : c(), compare(comp) { insert(s, first, last); } - template - flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, - const key_compare& comp, const Allocator& a); - template - flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, - const Allocator& a); - - flat_multimap(initializer_list il, const key_compare& comp = key_compare()) - : flat_multimap(il.begin(), il.end(), comp) { } - template - flat_multimap(initializer_list il, const key_compare& comp, - const Allocator& a); - template - flat_multimap(initializer_list il, const Allocator& a); - - flat_multimap(sorted_equivalent_t s, initializer_list il, - const key_compare& comp = key_compare()) - : flat_multimap(s, il.begin(), il.end(), comp) { } - template - flat_multimap(sorted_equivalent_t, initializer_list il, - const key_compare& comp, const Allocator& a); - template - flat_multimap(sorted_equivalent_t, initializer_list il, const Allocator& a); - - flat_multimap& operator=(initializer_list il); + constexpr flat_multiset(initializer_list il, + const key_compare& comp = key_compare()) + : flat_multiset(il.begin(), il.end(), comp) { } + + constexpr flat_multiset(sorted_equivalent_t, initializer_list il, + const key_compare& comp = key_compare()) + : flat_multiset(sorted_equivalent, il.begin(), il.end(), comp) { } + + // \ref{flat.multiset.cons.alloc}, constructors with allocators + + template + constexpr explicit flat_multiset(const Alloc& a); + template + constexpr flat_multiset(const key_compare& comp, const Alloc& a); + template + constexpr flat_multiset(const container_type& cont, const Alloc& a); + template + constexpr flat_multiset(const container_type& cont, const key_compare& comp, + const Alloc& a); + template + constexpr flat_multiset(sorted_equivalent_t, const container_type& cont, const Alloc& a); + template + constexpr flat_multiset(sorted_equivalent_t, const container_type& cont, + const key_compare& comp, const Alloc& a); + template + constexpr flat_multiset(const flat_multiset&, const Alloc& a); + template + constexpr flat_multiset(flat_multiset&&, const Alloc& a); + template + constexpr flat_multiset(InputIterator first, InputIterator last, const Alloc& a); + template + constexpr flat_multiset(InputIterator first, InputIterator last, + const key_compare& comp, const Alloc& a); + template + constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, + const Alloc& a); + template + constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, + const key_compare& comp, const Alloc& a); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_multiset(from_range_t, R&& rg, const Alloc& a); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); + template + constexpr flat_multiset(initializer_list il, const Alloc& a); + template + constexpr flat_multiset(initializer_list il, const key_compare& comp, + const Alloc& a); + template + constexpr flat_multiset(sorted_equivalent_t, initializer_list il, + const Alloc& a); + template + constexpr flat_multiset(sorted_equivalent_t, initializer_list il, + const key_compare& comp, const Alloc& a); + + constexpr flat_multiset& operator=(initializer_list); // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() noexcept; + constexpr 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; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; + constexpr bool empty() const noexcept; + constexpr size_type size() const noexcept; + constexpr size_type max_size() const noexcept; - // modifiers - template iterator emplace(Args&&... args); + // \ref{flat.multiset.modifiers}, modifiers + template constexpr iterator emplace(Args&&... args); template - iterator emplace_hint(const_iterator position, Args&&... args); + constexpr iterator emplace_hint(const_iterator position, Args&&... args); - iterator insert(const value_type& x) + constexpr iterator insert(const value_type& x) { return emplace(x); } - iterator insert(value_type&& x) + constexpr iterator insert(value_type&& x) { return emplace(std::move(x)); } - iterator insert(const_iterator position, const value_type& x) + constexpr iterator insert(const_iterator position, const value_type& x) { return emplace_hint(position, x); } - iterator insert(const_iterator position, value_type&& x) + constexpr iterator insert(const_iterator position, value_type&& x) { return emplace_hint(position, std::move(x)); } - template iterator insert(P&& x); - template - iterator insert(const_iterator position, P&&); template - void insert(InputIterator first, InputIterator last); + constexpr void insert(InputIterator first, InputIterator last); template - void insert(sorted_equivalent_t, InputIterator first, InputIterator last); + constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last); template<@\exposconcept{container-compatible-range}@ R> - void insert_range(R&& rg); + constexpr void insert_range(R&& rg); - void insert(initializer_list il) + constexpr void insert(initializer_list il) { insert(il.begin(), il.end()); } - void insert(sorted_equivalent_t s, initializer_list il) - { insert(s, il.begin(), il.end()); } + constexpr void insert(sorted_equivalent_t, initializer_list il) + { insert(sorted_equivalent, il.begin(), il.end()); } - containers extract() &&; - void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); + constexpr container_type extract() &&; + constexpr void replace(container_type&&); - iterator erase(iterator position); - iterator erase(const_iterator position); - size_type erase(const key_type& x); - template size_type erase(K&& x); - iterator erase(const_iterator first, const_iterator last); + constexpr iterator erase(iterator position); + constexpr iterator erase(const_iterator position); + constexpr size_type erase(const key_type& x); + template constexpr size_type erase(K&& x); + constexpr iterator erase(const_iterator first, const_iterator last); - void swap(flat_multimap&) noexcept; - void clear() noexcept; + constexpr void swap(flat_multiset& y) noexcept; + constexpr void clear() noexcept; // observers - key_compare key_comp() const; - value_compare value_comp() const; - - const key_container_type& keys() const noexcept { return c.keys; } - const mapped_container_type& values() const noexcept { return c.values; } + constexpr key_compare key_comp() const; + constexpr value_compare value_comp() const; - // map operations - iterator find(const key_type& x); - const_iterator find(const key_type& x) const; - template iterator find(const K& x); - template const_iterator find(const K& x) const; + // set operations + constexpr iterator find(const key_type& x); + constexpr const_iterator find(const key_type& x) const; + template constexpr iterator find(const K& x); + template constexpr const_iterator find(const K& x) const; - size_type count(const key_type& x) const; - template size_type count(const K& x) const; + constexpr size_type count(const key_type& x) const; + template constexpr size_type count(const K& x) const; - bool contains(const key_type& x) const; - template bool contains(const K& x) const; + constexpr bool contains(const key_type& x) const; + template constexpr bool contains(const K& x) const; - iterator lower_bound(const key_type& x); - const_iterator lower_bound(const key_type& x) const; - template iterator lower_bound(const K& x); - template const_iterator lower_bound(const K& x) const; + constexpr iterator lower_bound(const key_type& x); + constexpr const_iterator lower_bound(const key_type& x) const; + template constexpr iterator lower_bound(const K& x); + template constexpr const_iterator lower_bound(const K& x) const; - iterator upper_bound(const key_type& x); - const_iterator upper_bound(const key_type& x) const; - template iterator upper_bound(const K& x); - template const_iterator upper_bound(const K& x) const; + constexpr iterator upper_bound(const key_type& x); + constexpr const_iterator upper_bound(const key_type& x) const; + template constexpr iterator upper_bound(const K& x); + template constexpr const_iterator upper_bound(const K& x) const; - pair equal_range(const key_type& x); - pair equal_range(const key_type& x) const; + constexpr pair equal_range(const key_type& x); + constexpr pair equal_range(const key_type& x) const; template - pair equal_range(const K& x); + constexpr pair equal_range(const K& x); template - pair equal_range(const K& x) const; + constexpr pair equal_range(const K& x) const; - friend bool operator==(const flat_multimap& x, const flat_multimap& y); + friend constexpr bool operator==(const flat_multiset& x, const flat_multiset& y); - friend @\exposid{synth-three-way-result}@ - operator<=>(const flat_multimap& x, const flat_multimap& y); + friend constexpr @\placeholder{synth-three-way-result}@ + operator<=>(const flat_multiset& x, const flat_multiset& y); - friend void swap(flat_multimap& x, flat_multimap& y) noexcept + friend constexpr void swap(flat_multiset& x, flat_multiset& y) noexcept { x.swap(y); } private: - containers c; // \expos - key_compare compare; // \expos + container_type @\exposidnc{c}@; // \expos + key_compare @\exposidnc{compare}@; // \expos }; - template> - flat_multimap(KeyContainer, MappedContainer, Compare = Compare()) - -> flat_multimap; - - template - flat_multimap(KeyContainer, MappedContainer, Allocator) - -> flat_multimap, KeyContainer, MappedContainer>; - template - flat_multimap(KeyContainer, MappedContainer, Compare, Allocator) - -> flat_multimap; - - template> - flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Compare = Compare()) - -> flat_multimap; + template> + flat_multiset(KeyContainer, Compare = Compare()) + -> flat_multiset; + template + flat_multiset(KeyContainer, Allocator) + -> flat_multiset, KeyContainer>; + template + flat_multiset(KeyContainer, Compare, Allocator) + -> flat_multiset; - template - flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Allocator) - -> flat_multimap, KeyContainer, MappedContainer>; - template - flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Compare, Allocator) - -> flat_multimap; + template> + flat_multiset(sorted_equivalent_t, KeyContainer, Compare = Compare()) + -> flat_multiset; + template + flat_multiset(sorted_equivalent_t, KeyContainer, Allocator) + -> flat_multiset, KeyContainer>; + template + flat_multiset(sorted_equivalent_t, KeyContainer, Compare, Allocator) + -> flat_multiset; - template>> - flat_multimap(InputIterator, InputIterator, Compare = Compare()) - -> flat_multimap<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; + template>> + flat_multiset(InputIterator, InputIterator, Compare = Compare()) + -> flat_multiset<@\placeholder{iter-value-type}@, Compare>; - template>> - flat_multimap(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare()) - -> flat_multimap<@\exposid{iter-key-type}@, @\exposid{iter-mapped-type}@, Compare>; + template>> + flat_multiset(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare()) + -> flat_multiset<@\placeholder{iter-value-type}@, Compare>; - template>, - class Allocator = allocator> - flat_multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) - -> flat_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Compare, - vector<@\exposid{range-key-type}@, - @\exposid{alloc-rebind}@>>, - vector<@\exposid{range-mapped-type}@, - @\exposid{alloc-rebind}@>>>; + template>, + class Allocator = allocator>> + flat_multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> flat_multiset, Compare, + vector, + @\exposid{alloc-rebind}@>>>; template - flat_multimap(from_range_t, R&&, Allocator) - -> flat_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, less<@\exposid{range-key-type}@>, - vector<@\exposid{range-key-type}@, - @\exposid{alloc-rebind}@>>, - vector<@\exposid{range-mapped-type}@, - @\exposid{alloc-rebind}@>>>; + flat_multiset(from_range_t, R&&, Allocator) + -> flat_multiset, less>, + vector, + @\exposid{alloc-rebind}@>>>; - template> - flat_multimap(initializer_list>, Compare = Compare()) - -> flat_multimap; + template> + flat_multiset(initializer_list, Compare = Compare()) + -> flat_multiset; - template> - flat_multimap(sorted_equivalent_t, initializer_list>, Compare = Compare()) - -> flat_multimap; + template> + flat_multiset(sorted_equivalent_t, initializer_list, Compare = Compare()) + -> flat_multiset; - template - struct uses_allocator, - Allocator> - : bool_constant && - uses_allocator_v> { }; + template + struct uses_allocator, Allocator> + : bool_constant> { }; } \end{codeblock} +\rSec3[flat.multiset.cons]{Constructors} + +\indexlibraryctor{flat_multiset}% +\begin{itemdecl} +constexpr explicit flat_multiset(container_type cont, const key_compare& comp = key_compare()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{c} with \tcode{std::move(cont)} and +\exposid{compare} with \tcode{comp}, and +sorts the range \range{begin()}{end()} with respect to \exposid{compare}. + +\pnum +\complexity +Linear in $N$ if \tcode{cont} is already sorted with respect to \exposid{compare} and +otherwise $N \log N$, where $N$ is the value of \tcode{cont.size()} before this call. +\end{itemdescr} + +\rSec3[flat.multiset.cons.alloc]{Constructors with allocators} + +\pnum +The constructors in this subclause shall not participate in overload resolution +unless \tcode{uses_allocator_v} is \tcode{true}. + +\indexlibraryctor{flat_multiset}% +\begin{itemdecl} +template + constexpr flat_multiset(const container_type& cont, const Alloc& a); +template + constexpr flat_multiset(const container_type& cont, const key_compare& comp, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{flat_multiset(cont)} and +\tcode{flat_multiset(cont, comp)}, respectively, +except that \exposid{c} is constructed with +uses-allocator construction\iref{allocator.uses.construction}. + \pnum -The member type \tcode{containers} has the data members and special members -specified above. It has no base classes or members other than those -specified. - -\rSec3[flat.multimap.cons]{Constructors} +\complexity +Same as \tcode{flat_multiset(cont)} and +\tcode{flat_multiset(cont, comp)}, respectively. +\end{itemdescr} -\indexlibraryctor{flat_multimap}% +\indexlibraryctor{flat_multiset}% \begin{itemdecl} -flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont, - const key_compare& comp = key_compare()); +template + constexpr flat_multiset(sorted_equivalent_t, const container_type& cont, const Alloc& a); +template + constexpr flat_multiset(sorted_equivalent_t, const container_type& cont, + const key_compare& comp, const Alloc& a); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes -\tcode{c.keys} with \tcode{std::move(key_cont)}, -\tcode{c.values} with \tcode{std::move(mapped_cont)}, and -\tcode{compare} with \tcode{comp}; -sorts the range \range{begin()}{end()} with respect to \tcode{value_comp()}. +Equivalent to \tcode{flat_multiset(sorted_equivalent, cont)} and +\tcode{flat_multiset(sorted_equivalent, cont, comp)}, respectively, +except that \exposid{c} is constructed with +uses-allocator construction\iref{allocator.uses.construction}. \pnum \complexity -Linear in $N$ if the container arguments are already sorted -with respect to \tcode{value_comp()} and otherwise $N \log N$, -where $N$ is the value of \tcode{key_cont.size()} before this call. +Linear. \end{itemdescr} -\indexlibraryctor{flat_multimap}% +\indexlibraryctor{flat_multiset}% +\begin{itemdecl} +template + constexpr explicit flat_multiset(const Alloc& a); +template + constexpr flat_multiset(const key_compare& comp, const Alloc& a); +template + constexpr flat_multiset(const flat_multiset&, const Alloc& a); +template + constexpr flat_multiset(flat_multiset&&, const Alloc& a); +template + constexpr flat_multiset(InputIterator first, InputIterator last, const Alloc& a); +template + constexpr flat_multiset(InputIterator first, InputIterator last, + const key_compare& comp, const Alloc& a); +template + constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, + const Alloc& a); +template + constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, + const key_compare& comp, const Alloc& a); +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_multiset(from_range_t, R&& rg, const Alloc& a); +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + constexpr flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); +template + constexpr flat_multiset(initializer_list il, const Alloc& a); +template + constexpr flat_multiset(initializer_list il, const key_compare& comp, + const Alloc& a); +template + constexpr flat_multiset(sorted_equivalent_t, initializer_list il, const Alloc& a); +template + constexpr flat_multiset(sorted_equivalent_t, initializer_list il, + const key_compare& comp, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to the corresponding non-allocator constructors +except that \exposid{c} is constructed with +uses-allocator construction\iref{allocator.uses.construction}. +\end{itemdescr} + +\rSec3[flat.multiset.modifiers]{Modifiers} + +\indexlibrarymember{emplace}{flat_multiset}% \begin{itemdecl} -template - flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, - const Allocator& a); -template - flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, - const key_compare& comp, const Allocator& a); +template constexpr iterator emplace(Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{uses_allocator_v} is \tcode{true} and -\tcode{uses_allocator_v} is \tcode{true}. +\tcode{is_constructible_v} is \tcode{true}. \pnum \effects -Equivalent to \tcode{flat_multimap(key_cont, mapped_cont)} and -\tcode{flat_multimap(key_cont, \linebreak{}mapped_cont, comp)}, respectively, -except that \tcode{c.keys} and \tcode{c.values} are constructed -with uses-allocator construction\iref{allocator.uses.construction}. +First, initializes an object \tcode{t} of type \tcode{value_type} +with \tcode{std::forward(args)...}, +then inserts \tcode{t} as if by: +\begin{codeblock} +auto it = ranges::upper_bound(@\exposid{c}@, t, @\exposid{compare}@); +@\exposid{c}@.insert(it, std::move(t)); +\end{codeblock} \pnum -\complexity -Same as \tcode{flat_multimap(key_cont, mapped_cont)} and -\tcode{flat_multimap(key_cont, \linebreak{}mapped_cont, comp)}, respectively. +\returns +An iterator that points to the inserted element. \end{itemdescr} -\indexlibraryctor{flat_multimap}% +\indexlibrarymember{insert}{flat_multiset}% \begin{itemdecl} -flat_multimap(sorted_equivalent_t, key_container_type key_cont, mapped_container_type mapped_cont, - const key_compare& comp = key_compare()); +template + constexpr void insert(InputIterator first, InputIterator last); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes -\tcode{c.keys} with \tcode{std::move(key_cont)}, -\tcode{c.values} with \tcode{std::move(mapped_cont)}, and -\tcode{compare} with \tcode{comp}. +Adds elements to \exposid{c} as if by: +\begin{codeblock} +@\exposid{c}@.insert(@\exposid{c}@.end(), first, last); +\end{codeblock} +Then, sorts the range of newly inserted elements with respect to \exposid{compare}, +and merges the resulting sorted range and +the sorted range of pre-existing elements into a single sorted range. \pnum \complexity -Constant. +$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and $M$ +is \tcode{distance(first, last)}. + +\pnum +\remarks +Since this operation performs an in-place merge, it may allocate memory. \end{itemdescr} -\indexlibraryctor{flat_multimap}% +\indexlibrarymember{insert}{flat_multiset}% \begin{itemdecl} -template - flat_multimap(sorted_equivalent_t s, const key_container_type& key_cont, - const mapped_container_type& mapped_cont, const Allocator& a); -template - flat_multimap(sorted_equivalent_t s, const key_container_type& key_cont, - const mapped_container_type& mapped_cont, const key_compare& comp, - const Allocator& a); +template + constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true} and -\tcode{uses_allocator_v} is \tcode{true}. - \pnum \effects -Equivalent to \tcode{flat_multimap(s, key_cont, mapped_cont)} and -\tcode{flat_multimap(s, key_cont, mapped_cont, comp)}, respectively, -except that \tcode{c.keys} and \tcode{c.val\-ues} are constructed -with uses-allocator construction\iref{allocator.uses.construction}. +Equivalent to \tcode{insert(first, last)}. \pnum \complexity Linear. \end{itemdescr} -\indexlibraryctor{flat_multimap}% +\indexlibrarymember{swap}{flat_multiset}% \begin{itemdecl} -template - flat_multimap(const flat_multimap&, const Allocator& a); -template - flat_multimap(flat_multimap&&, const Allocator& a); -template - flat_multimap(const key_compare& comp, const Allocator& a); -template - explicit flat_multimap(const Allocator& a); -template - flat_multimap(InputIterator first, InputIterator last, const key_compare& comp, - const Allocator& a); -template - flat_multimap(InputIterator first, InputIterator last, const Allocator& a); -template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_multimap(from_range_t, R&& rg, const Allocator& a); -template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); -template - flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, - const key_compare& comp, const Allocator& a); -template - flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, - const Allocator& a); -template - flat_multimap(initializer_list il, const key_compare& comp, const Allocator& a); -template - flat_multimap(initializer_list il, const Allocator& a); -template - flat_multimap(sorted_equivalent_t, initializer_list il, - const key_compare& comp, const Allocator& a); -template - flat_multimap(sorted_equivalent_t, initializer_list il, const Allocator& a); +constexpr void swap(flat_multiset& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true} and -\tcode{uses_allocator_v} is \tcode{true}. +\effects +Equivalent to: +\begin{codeblock} +ranges::swap(@\exposid{compare}@, y.@\exposid{compare}@); +ranges::swap(@\exposid{c}@, y.@\exposid{c}@); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{extract}{flat_multiset}% +\begin{itemdecl} +constexpr container_type extract() &&; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{*this} is emptied, even if the function exits via an exception. + +\pnum +\returns +\tcode{std::move(\exposid{c})}. +\end{itemdescr} + +\indexlibrarymember{replace}{flat_multiset}% +\begin{itemdecl} +constexpr void replace(container_type&& cont); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The elements of \tcode{cont} are sorted with respect to \exposid{compare}. \pnum \effects -Equivalent to the corresponding non-allocator constructors -except that \tcode{c.keys} and \tcode{c.values} are constructed -with uses-allocator construction\iref{allocator.uses.construction}. +Equivalent to: \tcode{\exposid{c} = std::move(cont);} \end{itemdescr} -\rSec3[flat.multimap.erasure]{Erasure} +\rSec3[flat.multiset.erasure]{Erasure} -\indexlibrarymember{erase_if}{flat_multimap}% +\indexlibrarymember{erase_if}{flat_multiset}% \begin{itemdecl} -template - typename flat_multimap::size_type - erase_if(flat_multimap& c, Predicate pred); +template + constexpr typename flat_multiset::size_type + erase_if(flat_multiset& c, Predicate pred); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{Key} and \tcode{T} meet the \oldconcept{MoveAssignable} requirements. +\tcode{Key} meets the \oldconcept{MoveAssignable} requirements. \pnum \effects -Let $E$ be \tcode{bool(pred(pair(e)))}. +Let $E$ be \tcode{bool(pred(as_const(e)))}. Erases all elements \tcode{e} in \tcode{c} for which $E$ holds. \pnum @@ -16855,2534 +20101,1990 @@ If an invocation of \tcode{erase_if} exits via an exception, \tcode{c} is in a valid but unspecified state\iref{defns.valid}. \begin{note} -\tcode{c} still meets its invariants, -but can be empty. +\tcode{c} still meets its invariants, but can be empty. \end{note} \end{itemdescr} -\rSec2[flat.set]{Class template \tcode{flat_set}} - -\rSec3[flat.set.overview]{Overview} - -\pnum -\indexlibraryglobal{flat_set}% -A \tcode{flat_set} is a container adaptor -that provides an associative container interface -that supports unique keys -(i.e., contains at most one of each key value) and -provides for fast retrieval of the keys themselves. -\tcode{flat_set} supports iterators that model -the \libconcept{random_access_iterator} concept\iref{iterator.concept.random.access}. - -\pnum -A \tcode{flat_set} meets all of the requirements -for a container\iref{container.reqmts} and -for a reversible container\iref{container.rev.reqmts}, -plus the optional container requirements\iref{container.opt.reqmts}. -\tcode{flat_set} meets the requirements of -an associative container\iref{associative.reqmts}, except that: -\begin{itemize} -\item -it does not meet the requirements -related to node handles\iref{container.node.overview}, -\item -it does not meet the requirements related to iterator invalidation, and -\item -the time complexity of the operations -that insert or erase a single element from the set -is linear, -including the ones that take an insertion position iterator. -\end{itemize} -\begin{note} -A \tcode{flat_set} does not meet -the additional requirements of an allocator-aware container, -as described in \ref{container.alloc.reqmts}. -\end{note} - -\pnum -A \tcode{flat_set} also provides most operations -described in \ref{associative.reqmts} for unique keys. -This means that a \tcode{flat_set} supports -the \tcode{a_uniq} operations in \ref{associative.reqmts} -but not the \tcode{a_eq} operations. -For a \tcode{flat_set}, -both the \tcode{key_type} and \tcode{value_type} are \tcode{Key}. - -\pnum -Descriptions are provided here only for operations on \tcode{flat_set} -that are not described in one of those sets of requirements or -for operations where there is additional semantic information. - -\pnum -A \tcode{flat_set} maintains the invariant that the keys are sorted with -respect to the comparison object. - -\pnum -If any member function in \ref{flat.set.defn} exits via an exception, -the invariant is restored. -\begin{note} -This can result in the \tcode{flat_set}'s being emptied. -\end{note} - -\pnum -Any sequence container\iref{sequence.reqmts} -supporting \oldconcept{RandomAccessIterator} -can be used to instantiate \tcode{flat_set}. -In particular, \tcode{vector}\iref{vector} and \tcode{deque}\iref{deque} -can be used. -\begin{note} -\tcode{vector} is not a sequence container. -\end{note} - -\pnum -The program is ill-formed if \tcode{Key} is not the same type -as \tcode{KeyContainer::value_type}. - -\pnum -The effect of calling a constructor or member function -that takes a \tcode{sorted_unique_t} argument -with a range that is not sorted with respect to \tcode{key_comp()}, or -that contains equal elements, is undefined. - -\rSec3[flat.set.defn]{Definition} - -\begin{codeblock} -namespace std { - template, class KeyContainer = vector> - class @\libglobal{flat_set}@ { - public: - // types - using key_type = Key; - using value_type = Key; - using key_compare = Compare; - using value_compare = Compare; - using reference = value_type&; - using const_reference = const value_type&; - using size_type = typename KeyContainer::size_type; - using difference_type = typename KeyContainer::difference_type; - using iterator = @\impdefx{type of \tcode{flat_set::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{flat_set::const_iterator}}@; // see \ref{container.requirements} - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - using container_type = KeyContainer; - - // \ref{flat.set.cons}, constructors - flat_set() : flat_set(key_compare()) { } - - template - flat_set(const flat_set&, const Allocator& a); - template - flat_set(flat_set&&, const Allocator& a); - - explicit flat_set(container_type cont, const key_compare& comp = key_compare()); - template - flat_set(const container_type& cont, const Allocator& a); - template - flat_set(const container_type& cont, const key_compare& comp, const Allocator& a); - - flat_set(sorted_unique_t, container_type cont, const key_compare& comp = key_compare()) - : @\exposid{c}@(std::move(cont)), @\exposid{compare}@(comp) { } - template - flat_set(sorted_unique_t, const container_type& cont, const Allocator& a); - template - flat_set(sorted_unique_t, const container_type& cont, - const key_compare& comp, const Allocator& a); +\rSec2[container.adaptors.format]{Container adaptors formatting} - explicit flat_set(const key_compare& comp) - : @\exposid{c}@(), @\exposid{compare}@(comp) { } - template - flat_set(const key_compare& comp, const Allocator& a); - template - explicit flat_set(const Allocator& a); +\pnum +For each of +\tcode{queue}, +\tcode{priority_queue}, and +\tcode{stack}, +the library provides the following formatter specialization +where \tcode{\placeholder{adaptor-type}} is the name of the template: - template - flat_set(InputIterator first, InputIterator last, const key_compare& comp = key_compare()) - : @\exposid{c}@(), @\exposid{compare}@(comp) - { insert(first, last); } - template - flat_set(InputIterator first, InputIterator last, - const key_compare& comp, const Allocator& a); - template - flat_set(InputIterator first, InputIterator last, const Allocator& a); +\indexlibraryglobal{formatter}% +\begin{codeblock} +namespace std { + template Container, class... U> + struct formatter<@\placeholder{adaptor-type}@, charT> { + private: + using @\exposid{maybe-const-container}@ = // \expos + @\exposid{fmt-maybe-const}@; + using @\exposid{maybe-const-adaptor}@ = // \expos + @\exposid{maybe-const}@, // see \ref{ranges.syn} + @\placeholder{adaptor-type}@>; + formatter, charT> @\exposid{underlying_}@; // \expos - template<@\exposconcept{container-compatible-range}@ R> - flat_set(from_range_t fr, R&& rg) - : flat_set(fr, std::forward(rg), key_compare()) { } - template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_set(from_range_t, R&& rg, const Allocator& a); - template<@\exposconcept{container-compatible-range}@ R> - flat_set(from_range_t, R&& rg, const key_compare& comp) - : flat_set(comp) - { insert_range(std::forward(rg)); } - template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_set(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); + public: + template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); - template - flat_set(sorted_unique_t, InputIterator first, InputIterator last, - const key_compare& comp = key_compare()) - : @\exposid{c}@(first, last), @\exposid{compare}@(comp) { } - template - flat_set(sorted_unique_t, InputIterator first, InputIterator last, - const key_compare& comp, const Allocator& a); - template - flat_set(sorted_unique_t, InputIterator first, InputIterator last, const Allocator& a); + template + typename FormatContext::iterator + format(@\exposid{maybe-const-adaptor}@& r, FormatContext& ctx) const; + }; +} +\end{codeblock} - flat_set(initializer_list il, const key_compare& comp = key_compare()) - : flat_set(il.begin(), il.end(), comp) { } - template - flat_set(initializer_list il, const key_compare& comp, const Allocator& a); - template - flat_set(initializer_list il, const Allocator& a); +\indexlibrarymember{parse}{formatter}% +\begin{itemdecl} +template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); +\end{itemdecl} - flat_set(sorted_unique_t s, initializer_list il, - const key_compare& comp = key_compare()) - : flat_set(s, il.begin(), il.end(), comp) { } - template - flat_set(sorted_unique_t, initializer_list il, - const key_compare& comp, const Allocator& a); - template - flat_set(sorted_unique_t, initializer_list il, const Allocator& a); +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +\end{itemdescr} - flat_set& operator=(initializer_list); +\indexlibrarymember{format}{formatter}% +\begin{itemdecl} +template + typename FormatContext::iterator + format(@\exposid{maybe-const-adaptor}@& r, FormatContext& ctx) const; +\end{itemdecl} - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{underlying_}.format(r.c, ctx);} +\end{itemdescr} - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; +\rSec1[views]{Views} - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; +\rSec2[views.general]{General} - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; +\pnum +The header \libheaderref{span} defines the view \tcode{span}. +The header \libheaderref{mdspan} defines the class template \tcode{mdspan} and +other facilities for interacting with these multidimensional views. - // \ref{flat.set.modifiers}, modifiers - template pair emplace(Args&&... args); - template - iterator emplace_hint(const_iterator position, Args&&... args); +\rSec2[views.contiguous]{Contiguous access} - pair insert(const value_type& x) - { return emplace(x); } - pair insert(value_type&& x) - { return emplace(std::move(x)); } - template pair insert(K&& x); - iterator insert(const_iterator position, const value_type& x) - { return emplace_hint(position, x); } - iterator insert(const_iterator position, value_type&& x) - { return emplace_hint(position, std::move(x)); } - template iterator insert(const_iterator hint, K&& x); +\rSec3[span.syn]{Header \tcode{} synopsis}% - template - void insert(InputIterator first, InputIterator last); - template - void insert(sorted_unique_t, InputIterator first, InputIterator last); - template<@\exposconcept{container-compatible-range}@ R> - void insert_range(R&& rg); +\indexheader{span}% +\begin{codeblock} +#include // see \ref{initializer.list.syn} - void insert(initializer_list il) - { insert(il.begin(), il.end()); } - void insert(sorted_unique_t s, initializer_list il) - { insert(s, il.begin(), il.end()); } +// mostly freestanding +namespace std { + // constants + inline constexpr size_t @\libglobal{dynamic_extent}@ = numeric_limits::max(); - container_type extract() &&; - void replace(container_type&&); + template + concept @\defexposconcept{integral-constant-like}@ = // \expos + is_integral_v> && + !is_same_v> && + @\libconcept{convertible_to}@ && + @\libconcept{equality_comparable_with}@ && + bool_constant::value && + bool_constant(T()) == T::value>::value; - iterator erase(iterator position); - iterator erase(const_iterator position); - size_type erase(const key_type& x); - template size_type erase(K&& x); - iterator erase(const_iterator first, const_iterator last); + template + constexpr size_t @\defexposconcept{maybe-static-ext}@ = dynamic_extent; // \expos + template<@\exposconcept{integral-constant-like}@ T> + constexpr size_t @\exposconcept{maybe-static-ext}@ = {T::value}; - void swap(flat_set& y) noexcept; - void clear() noexcept; + // \ref{views.span}, class template \tcode{span} + template + class span; // partially freestanding - // observers - key_compare key_comp() const; - value_compare value_comp() const; + template + constexpr bool ranges::@\libspec{enable_view}{span}@> = true; + template + constexpr bool ranges::@\libspec{enable_borrowed_range}{span}@> = true; - // set operations - iterator find(const key_type& x); - const_iterator find(const key_type& x) const; - template iterator find(const K& x); - template const_iterator find(const K& x) const; + // \ref{span.objectrep}, views of object representation + template + span + as_bytes(span s) noexcept; - size_type count(const key_type& x) const; - template size_type count(const K& x) const; + template + span + as_writable_bytes(span s) noexcept; +} +\end{codeblock} - bool contains(const key_type& x) const; - template bool contains(const K& x) const; +\rSec3[views.span]{Class template \tcode{span}} - iterator lower_bound(const key_type& x); - const_iterator lower_bound(const key_type& x) const; - template iterator lower_bound(const K& x); - template const_iterator lower_bound(const K& x) const; +\rSec4[span.overview]{Overview} - iterator upper_bound(const key_type& x); - const_iterator upper_bound(const key_type& x) const; - template iterator upper_bound(const K& x); - template const_iterator upper_bound(const K& x) const; +\pnum +\indexlibraryglobal{span}% +A \tcode{span} is a view over a contiguous sequence of objects, +the storage of which is owned by some other object. - pair equal_range(const key_type& x); - pair equal_range(const key_type& x) const; - template - pair equal_range(const K& x); - template - pair equal_range(const K& x) const; +\pnum +All member functions of \tcode{span} have constant time complexity. - friend bool operator==(const flat_set& x, const flat_set& y); +\indexlibraryglobal{span}% +\begin{codeblock} +namespace std { + template + class span { + public: + // constants and types + using element_type = ElementType; + using value_type = remove_cv_t; + using size_type = size_t; + using difference_type = ptrdiff_t; + using pointer = element_type*; + using const_pointer = const element_type*; + using reference = element_type&; + using const_reference = const element_type&; + using iterator = @\impdefx{type of \tcode{span::iterator}}@; // see \ref{span.iterators} + using const_iterator = std::const_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::const_iterator; + static constexpr size_type extent = Extent; - friend @\placeholder{synth-three-way-result}@ - operator<=>(const flat_set& x, const flat_set& y); + // \ref{span.cons}, constructors, copy, and assignment + constexpr span() noexcept; + template + constexpr explicit(extent != dynamic_extent) span(It first, size_type count); + template + constexpr explicit(extent != dynamic_extent) span(It first, End last); + template + constexpr span(type_identity_t (&arr)[N]) noexcept; + template + constexpr span(array& arr) noexcept; + template + constexpr span(const array& arr) noexcept; + template + constexpr explicit(extent != dynamic_extent) span(R&& r); + constexpr explicit(extent != dynamic_extent) span(std::initializer_list il); + constexpr span(const span& other) noexcept = default; + template + constexpr explicit(@\seebelow@) span(const span& s) noexcept; - friend void swap(flat_set& x, flat_set& y) noexcept { x.swap(y); } + constexpr span& operator=(const span& other) noexcept = default; - private: - container_type @\exposidnc{c}@; // \expos - key_compare @\exposidnc{compare}@; // \expos - }; + // \ref{span.sub}, subviews + template + constexpr span first() const; + template + constexpr span last() const; + template + constexpr span subspan() const; - template> - flat_set(KeyContainer, Compare = Compare()) - -> flat_set; - template - flat_set(KeyContainer, Allocator) - -> flat_set, KeyContainer>; - template - flat_set(KeyContainer, Compare, Allocator) - -> flat_set; + constexpr span first(size_type count) const; + constexpr span last(size_type count) const; + constexpr span subspan( + size_type offset, size_type count = dynamic_extent) const; - template> - flat_set(sorted_unique_t, KeyContainer, Compare = Compare()) - -> flat_set; - template - flat_set(sorted_unique_t, KeyContainer, Allocator) - -> flat_set, KeyContainer>; - template - flat_set(sorted_unique_t, KeyContainer, Compare, Allocator) - -> flat_set; + // \ref{span.obs}, observers + constexpr size_type size() const noexcept; + constexpr size_type size_bytes() const noexcept; + constexpr bool empty() const noexcept; - template>> - flat_set(InputIterator, InputIterator, Compare = Compare()) - -> flat_set<@\placeholder{iter-value-type}@, Compare>; + // \ref{span.elem}, element access + constexpr reference operator[](size_type idx) const; + constexpr reference at(size_type idx) const; // freestanding-deleted + constexpr reference front() const; + constexpr reference back() const; + constexpr pointer data() const noexcept; - template>> - flat_set(sorted_unique_t, InputIterator, InputIterator, Compare = Compare()) - -> flat_set<@\placeholder{iter-value-type}@, Compare>; + // \ref{span.iterators}, iterator support + constexpr iterator begin() const noexcept; + constexpr iterator end() const noexcept; + constexpr const_iterator cbegin() const noexcept { return begin(); } + constexpr const_iterator cend() const noexcept { return end(); } + constexpr reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); } + constexpr const_reverse_iterator crend() const noexcept { return rend(); } - template>, - class Allocator = allocator>> - flat_set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) - -> flat_set, Compare, - vector, - @\exposid{alloc-rebind}@>>>; + private: + pointer @\exposid{data_}@; // \expos + size_type @\exposid{size_}@; // \expos + }; - template - flat_set(from_range_t, R&&, Allocator) - -> flat_set, less>, - vector, - @\exposid{alloc-rebind}@>>>; + template + span(It, EndOrSize) -> span>, + @\exposconcept{maybe-static-ext}@>; + template + span(T (&)[N]) -> span; + template + span(array&) -> span; + template + span(const array&) -> span; + template + span(R&&) -> span>>; +} +\end{codeblock} - template> - flat_set(initializer_list, Compare = Compare()) - -> flat_set; +\pnum +\tcode{span} is +a trivially copyable type\iref{term.trivially.copyable.type}. - template> - flat_set(sorted_unique_t, initializer_list, Compare = Compare()) - -> flat_set; +\pnum +\tcode{ElementType} is required to be +a complete object type that is not an abstract class type. - template - struct uses_allocator, Allocator> - : bool_constant> { }; -} -\end{codeblock} +\pnum +For a \tcode{span} \tcode{s}, +any operation that invalidates a pointer in +the range \range{s.data()}{s.data() + s.size()} +invalidates pointers, iterators, and references to elements of \tcode{s}. -\rSec3[flat.set.cons]{Constructors} +\rSec4[span.cons]{Constructors, copy, and assignment} -\indexlibraryctor{flat_set}% +\indexlibraryctor{span}% \begin{itemdecl} -explicit flat_set(container_type cont, const key_compare& comp = key_compare()); +constexpr span() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{c} with \tcode{std::move(cont)} and -\exposid{compare} with \tcode{comp}, -sorts the range \range{begin()}{end()} with respect to \exposid{compare}, and -finally erases all but the first element -from each group of consecutive equivalent elements. +\constraints +\tcode{Extent == dynamic_extent || Extent == 0} is \tcode{true}. \pnum -\complexity -Linear in $N$ if \tcode{cont} is sorted with respect to \exposid{compare} and -otherwise $N \log N$, where $N$ is the value of \tcode{cont.size()} before this call. +\ensures +%FIXME: Should "is \tcode{true}" be appended here? +\tcode{size() == 0 \&\& data() == nullptr}. \end{itemdescr} -\indexlibraryctor{flat_set}% +\indexlibraryctor{span}% \begin{itemdecl} -template - flat_set(const container_type& cont, const Allocator& a); -template - flat_set(const container_type& cont, const key_compare& comp, const Allocator& a); +template + constexpr explicit(extent != dynamic_extent) span(It first, size_type count); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{uses_allocator_v} is \tcode{true}. +Let \tcode{U} be \tcode{remove_reference_t>}. +\begin{itemize} +\item \tcode{It} satisfies \libconcept{contiguous_iterator}. +\item +\tcode{is_convertible_v} is \tcode{true}. +\begin{note} +The intent is to allow only qualification conversions +of the iterator reference type to \tcode{element_type}. +\end{note} +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item \range{first}{first + count} is a valid range. +\item \tcode{It} models \libconcept{contiguous_iterator}. +\end{itemize} + +\pnum +\hardexpects +If \tcode{extent} is not equal to \tcode{dynamic_extent}, +then \tcode{count == extent} is \tcode{true}. \pnum \effects -Equivalent to -\tcode{flat_set(cont)} and \tcode{flat_set(cont, comp)}, respectively, -except that \exposid{c} is constructed with -uses-allocator construction\iref{allocator.uses.construction}. +Initializes \exposid{data_} with \tcode{to_address(first)} and +\exposid{size_} with \tcode{count}. \pnum -\complexity -Same as \tcode{flat_set(cont)} and \tcode{flat_set(cont, comp)}, respectively. +\throws +Nothing. \end{itemdescr} -\indexlibraryctor{flat_set}% +\indexlibraryctor{span}% \begin{itemdecl} -template - flat_set(sorted_unique_t s, const container_type& cont, const Allocator& a); -template - flat_set(sorted_unique_t s, const container_type& cont, - const key_compare& comp, const Allocator& a); +template + constexpr explicit(extent != dynamic_extent) span(It first, End last); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{uses_allocator_v} is \tcode{true}. +Let \tcode{U} be \tcode{remove_reference_t>}. +\begin{itemize} +\item +\tcode{is_convertible_v} is \tcode{true}. +\begin{note} +The intent is to allow only qualification conversions +of the iterator reference type to \tcode{element_type}. +\end{note} +\item \tcode{It} satisfies \libconcept{contiguous_iterator}. +\item \tcode{End} satisfies \tcode{\libconcept{sized_sentinel_for}}. +\item \tcode{is_convertible_v} is \tcode{false}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item \range{first}{last} is a valid range. +\item \tcode{It} models \libconcept{contiguous_iterator}. +\item \tcode{End} models \tcode{\libconcept{sized_sentinel_for}}. +\end{itemize} + +\pnum +\hardexpects +If \tcode{extent} is not equal to \tcode{dynamic_extent}, +then \tcode{(last - first) == extent} is \tcode{true}. \pnum \effects -Equivalent to -\tcode{flat_set(s, cont)} and \tcode{flat_set(s, cont, comp)}, respectively, -except that \exposid{c} is constructed with -uses-allocator construction\iref{allocator.uses.construction}. +Initializes \exposid{data_} with \tcode{to_address(first)} and +\exposid{size_} with \tcode{last - first}. \pnum -\complexity -Linear. +\throws +When and what \tcode{last - first} throws. \end{itemdescr} -\indexlibraryctor{flat_set}% +\indexlibraryctor{span}% \begin{itemdecl} -template - flat_set(const flat_set&, const Allocator& a); -template - flat_set(flat_set&&, const Allocator& a); -template - flat_set(const key_compare& comp, const Allocator& a); -template - explicit flat_set(const Allocator& a); -template - flat_set(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a); -template - flat_set(InputIterator first, InputIterator last, const Allocator& a); -template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_set(from_range_t, R&& rg, const Allocator& a); -template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_set(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); -template - flat_set(sorted_unique_t, InputIterator first, InputIterator last, - const key_compare& comp, const Allocator& a); -template - flat_set(sorted_unique_t, InputIterator first, InputIterator last, const Allocator& a); -template - flat_set(initializer_list il, const key_compare& comp, const Allocator& a); -template - flat_set(initializer_list il, const Allocator& a); -template - flat_set(sorted_unique_t, initializer_list il, - const key_compare& comp, const Allocator& a); -template - flat_set(sorted_unique_t, initializer_list il, const Allocator& a); +template constexpr span(type_identity_t (&arr)[N]) noexcept; +template constexpr span(array& arr) noexcept; +template constexpr span(const array& arr) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{uses_allocator_v} is \tcode{true}. +Let \tcode{U} be \tcode{remove_pointer_t}. +\begin{itemize} +\item \tcode{extent == dynamic_extent || N == extent} is \tcode{true}, and +\item \tcode{is_convertible_v} is \tcode{true}. +\begin{note} +The intent is to allow only qualification conversions +of the array element type to \tcode{element_type}. +\end{note} +\end{itemize} \pnum \effects -Equivalent to the corresponding non-allocator constructors -except that \exposid{c} is constructed with -uses-allocator construction\iref{allocator.uses.construction}. -\end{itemdescr} +Constructs a \tcode{span} that is a view over the supplied array. +\begin{note} +\tcode{type_identity_t} affects class template argument deduction. +\end{note} -\rSec3[flat.set.modifiers]{Modifiers} +\pnum +\ensures +\tcode{size() == N \&\& data() == std::data(arr)} is \tcode{true}. +\end{itemdescr} -\indexlibrarymember{insert}{flat_set}% +\indexlibraryctor{span}% \begin{itemdecl} -template pair insert(K&& x); -template iterator insert(const_iterator hint, K&& x); +template constexpr explicit(extent != dynamic_extent) span(R&& r); \end{itemdecl} \begin{itemdescr} \pnum \constraints -The \grammarterm{qualified-id} \tcode{Compare::is_transparent} -is valid and denotes a type. -\tcode{is_constructi\-ble_v} is \tcode{true}. +Let \tcode{U} be \tcode{remove_reference_t>}. +\begin{itemize} +\item \tcode{R} satisfies \tcode{ranges::\libconcept{contiguous_range}} and + \tcode{ranges::\libconcept{sized_range}}. +\item Either \tcode{R} satisfies \tcode{ranges::\libconcept{borrowed_range}} or +\tcode{is_const_v} is \tcode{true}. +\item \tcode{remove_cvref_t} is not a specialization of \tcode{span}. +\item \tcode{remove_cvref_t} is not a specialization of \tcode{array}. +\item \tcode{is_array_v>} is \tcode{false}. +\item +\tcode{is_convertible_v} is \tcode{true}. +\begin{note} +The intent is to allow only qualification conversions +of the range reference type to \tcode{element_type}. +\end{note} +\end{itemize} \pnum \expects -The conversion from \tcode{x} into \tcode{value_type} constructs -an object \tcode{u}, for which \tcode{find(x) == find(u)} is true. +\begin{itemize} +\item \tcode{R} models \tcode{ranges::\libconcept{contiguous_range}} and +\tcode{ranges::\libconcept{sized_range}}. +\item If \tcode{is_const_v} is \tcode{false}, +\tcode{R} models \tcode{ranges::\libconcept{borrowed_range}}. +\end{itemize} + +\pnum +\hardexpects +If \tcode{extent} is not equal to \tcode{dynamic_extent}, +then \tcode{ranges::size(r) == extent} is \tcode{true}. \pnum \effects -If the set already contains an element equivalent to \tcode{x}, -\tcode{*this} and \tcode{x} are unchanged. -Otherwise, -inserts a new element as if by \tcode{emplace(std::forward(x))}. +Initializes \exposid{data_} with \tcode{ranges::data(r)} and +\exposid{size_} with \tcode{ranges::size(r)}. \pnum -\returns -In the first overload, -the \tcode{bool} component of the returned pair is \tcode{true} -if and only if the insertion took place. -The returned iterator points to the element -whose key is equivalent to \tcode{x}. +\throws +What and when \tcode{ranges::data(r)} and \tcode{ranges::size(r)} throw. \end{itemdescr} -\indexlibrarymember{insert}{flatset}% +\indexlibraryctor{span}% \begin{itemdecl} -template - void insert(InputIterator first, InputIterator last); +constexpr explicit(extent != dynamic_extent) span(std::initializer_list il); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Adds elements to \exposid{c} as if by: -\begin{codeblock} -@\exposid{c}@.insert(@\exposid{c}@.end(), first, last); -\end{codeblock} -Then, -sorts the range of newly inserted elements with respect to \exposid{compare}; -merges the resulting sorted range and -the sorted range of pre-existing elements into a single sorted range; and -finally erases all but the first element -from each group of consecutive equivalent elements. +\constraints +\tcode{is_const_v} is \tcode{true}. \pnum -\complexity -$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and -$M$ is \tcode{distance(first, last)}. +\hardexpects +If \tcode{extent} is not equal to \tcode{dynamic_extent}, +then \tcode{il.size() == extent} is \tcode{true}. \pnum -\remarks -Since this operation performs an in-place merge, it may allocate memory. +\effects +Initializes \exposid{data_} with \tcode{il.begin()} and +\exposid{size_} with \tcode{il.size()}. \end{itemdescr} -\indexlibrarymember{insert}{flat_set}% +\indexlibraryctor{span}% \begin{itemdecl} -template - void insert(sorted_unique_t, InputIterator first, InputIterator last); +constexpr span(const span& other) noexcept = default; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{insert(first, last)}. - -\pnum -\complexity -Linear. +\ensures +\tcode{other.size() == size() \&\& other.data() == data()}. \end{itemdescr} -\indexlibrarymember{insert_range}{flat_set}% +\indexlibraryctor{span}% \begin{itemdecl} -template<@\exposconcept{container-compatible-range}@ R> - void insert_range(R&& rg); +template + constexpr explicit(@\seebelow@) span(const span& s) noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item \tcode{extent == dynamic_extent} \tcode{||} \tcode{OtherExtent == dynamic_extent} \tcode{||} \tcode{extent == OtherExtent} is \tcode{true}, and +\item \tcode{is_convertible_v} is \tcode{true}. +\begin{note} +The intent is to allow only qualification conversions +of the \tcode{OtherElementType} to \tcode{element_type}. +\end{note} +\end{itemize} + +\pnum +\hardexpects +If \tcode{extent} is not equal to \tcode{dynamic_extent}, +then \tcode{s.size() == extent} is \tcode{true}. + \pnum \effects -Adds elements to \exposid{c} as if by: -\begin{codeblock} -for (const auto& e : rg) { - @\exposid{c}@.insert(@\exposid{c}@.end(), e); -} -\end{codeblock} -Then, -sorts the range of newly inserted elements with respect to \exposid{compare}; -merges the resulting sorted range and -the sorted range of pre-existing elements into a single sorted range; and -finally erases all but the first element -from each group of consecutive equivalent elements. +Constructs a \tcode{span} that is a view over the range +\range{s.data()}{s.data() + s.size()}. \pnum -\complexity -$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and $M$ -is \tcode{ranges::distance(rg)}. +\ensures +\tcode{size() == s.size() \&\& data() == s.data()}. \pnum \remarks -Since this operation performs an in-place merge, it may allocate memory. +The expression inside \keyword{explicit} is equivalent to: +\begin{codeblock} +extent != dynamic_extent && OtherExtent == dynamic_extent +\end{codeblock} \end{itemdescr} -\indexlibrarymember{swap}{flat_set}% +\indexlibrarymember{operator=}{span}% \begin{itemdecl} -void swap(flat_set& y) noexcept; +constexpr span& operator=(const span& other) noexcept = default; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -ranges::swap(@\exposid{compare}@, y.@\exposid{compare}@); -ranges::swap(@\exposid{c}@, y.@\exposid{c}@); -\end{codeblock} +\ensures +\tcode{size() == other.size() \&\& data() == other.data()}. \end{itemdescr} -\indexlibrarymember{extract}{flatset}% +\rSec4[span.deduct]{Deduction guides} + +\indexlibrary{\idxcode{span}!deduction guide}% \begin{itemdecl} -container_type extract() &&; +template + span(It, EndOrSize) -> span>, + @\exposconcept{maybe-static-ext}@>; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{*this} is emptied, even if the function exits via an exception. - -\pnum -\returns -\tcode{std::move(\exposid{c})}. +\constraints +\tcode{It} satisfies \libconcept{contiguous_iterator}. \end{itemdescr} -\indexlibrarymember{replace}{flat_set}% +\indexlibrary{\idxcode{span}!deduction guide}% \begin{itemdecl} -void replace(container_type&& cont); +template + span(R&&) -> span>>; \end{itemdecl} \begin{itemdescr} \pnum -\expects -The elements of \tcode{cont} are sorted with respect to \exposid{compare}, and -\tcode{cont} contains no equal elements. - -\pnum -\effects -Equivalent to: \tcode{\exposid{c} = std::move(cont);} +\constraints +\tcode{R} satisfies \tcode{ranges::\libconcept{contiguous_range}}. \end{itemdescr} -\rSec3[flat.set.erasure]{Erasure} +\rSec4[span.sub]{Subviews} -\indexlibrarymember{erase_if}{flat_set}% +\indexlibrarymember{span}{first}% \begin{itemdecl} -template - typename flat_set::size_type - erase_if(flat_set& c, Predicate pred); +template constexpr span first() const; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{Key} meets the \oldconcept{MoveAssignable} requirements. - -\pnum -\effects -Let $E$ be \tcode{bool(pred(as_const(e)))}. -Erases all elements \tcode{e} in \tcode{c} for which $E$ holds. - -\pnum -\returns -The number of elements erased. +\mandates +\tcode{Count <= Extent} is \tcode{true}. \pnum -\complexity -Exactly \tcode{c.size()} applications of the predicate. +\hardexpects +\tcode{Count <= size()} is \tcode{true}. \pnum -\remarks -Stable\iref{algorithm.stable}. -If an invocation of \tcode{erase_if} exits via an exception, -\tcode{c} is in a valid but unspecified state\iref{defns.valid}. -\begin{note} -\tcode{c} still meets its invariants, but can be empty. -\end{note} +\effects +Equivalent to: \tcode{return R\{data(), Count\};} +where \tcode{R} is the return type. \end{itemdescr} -\rSec2[flat.multiset]{Class template \tcode{flat_multiset}} - -\rSec3[flat.multiset.overview]{Overview} - -\pnum -\indexlibraryglobal{flat_multiset}% -A \tcode{flat_multiset} is a container adaptor -that provides an associative container interface -that supports equivalent keys -(i.e., possibly containing multiple copies of the same key value) and -provides for fast retrieval of the keys themselves. -\tcode{flat_multiset} supports iterators that model the -\libconcept{random_access_iterator} concept\iref{iterator.concept.random.access}. - -\pnum -A \tcode{flat_multiset} meets all of the requirements -for a container\iref{container.reqmts} and -for a reversible container\iref{container.rev.reqmts}, -plus the optional container requirements\iref{container.opt.reqmts}. -\tcode{flat_multiset} meets the requirements of -an associative container\iref{associative.reqmts}, except that: -\begin{itemize} -\item -it does not meet the requirements -related to node handles\iref{container.node.overview}, -\item -it does not meet the requirements related to iterator invalidation, and -\item -the time complexity of the operations -that insert or erase a single element from the -set is linear, -including the ones that take an insertion position iterator. -\end{itemize} -\begin{note} -A \tcode{flat_multiset} does not meet -the additional requirements of an allocator-aware container, -as described in \ref{container.alloc.reqmts}. -\end{note} - -\pnum -A \tcode{flat_multiset} also provides most operations -described in \ref{associative.reqmts} for equal keys. -This means that a \tcode{flat_multiset} supports -the \tcode{a_eq} operations in \ref{associative.reqmts} -but not the \tcode{a_uniq} operations. -For a \tcode{flat_multiset}, -both the \tcode{key_type} and \tcode{value_type} are \tcode{Key}. - -\pnum -Descriptions are provided here only for operations on \tcode{flat_multiset} -that are not described in one of the general sections or -for operations where there is additional semantic information. - -\pnum -A \tcode{flat_multiset} maintains the invariant -that the keys are sorted with respect to the comparison object. - -\pnum -If any member function in \ref{flat.multiset.defn} exits via an exception, -the invariant is restored. -\begin{note} -This can result in the \tcode{flat_multiset}'s being emptied. -\end{note} +\indexlibrarymember{span}{last}% +\begin{itemdecl} +template constexpr span last() const; +\end{itemdecl} +\begin{itemdescr} \pnum -Any sequence container\iref{sequence.reqmts} -supporting \oldconcept{RandomAccessIterator} -can be used to instantiate \tcode{flat_multiset}. -In particular, -\tcode{vector}\iref{vector} and \tcode{deque}\iref{deque} can be used. -\begin{note} -\tcode{vector} is not a sequence container. -\end{note} +\mandates +\tcode{Count <= Extent} is \tcode{true}. \pnum -The program is ill-formed if \tcode{Key} is not the same type -as \tcode{KeyContainer::value_type}. +\hardexpects +\tcode{Count <= size()} is \tcode{true}. \pnum -The effect of calling a constructor or member function -that takes a \tcode{sorted_equivalent_t} argument with a range -that is not sorted with respect to \tcode{key_comp()} is undefined. - -\rSec3[flat.multiset.defn]{Definition} - -\begin{codeblock} -namespace std { - template, class KeyContainer = vector> - class flat_multiset { - public: - // types - using key_type = Key; - using value_type = Key; - using key_compare = Compare; - using value_compare = Compare; - using reference = value_type&; - using const_reference = const value_type&; - using size_type = typename KeyContainer::size_type; - using difference_type = typename KeyContainer::difference_type; - using iterator = @\impdefx{type of \tcode{flat_multiset::iterator}}@; // see \ref{container.requirements} - using const_iterator = @\impdefx{type of \tcode{flat_multiset::const_iterator}}@; // see \ref{container.requirements} - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - using container_type = KeyContainer; - - // \ref{flat.multiset.cons}, constructors - flat_multiset() : flat_multiset(key_compare()) { } - - template - flat_multiset(const flat_multiset&, const Allocator& a); - template - flat_multiset(flat_multiset&&, const Allocator& a); - - explicit flat_multiset(container_type cont, const key_compare& comp = key_compare()); - template - flat_multiset(const container_type& cont, const Allocator& a); - template - flat_multiset(const container_type& cont, const key_compare& comp, const Allocator& a); - - flat_multiset(sorted_equivalent_t, container_type cont, - const key_compare& comp = key_compare()) - : @\exposid{c}@(std::move(cont)), @\exposid{compare}@(comp) { } - template - flat_multiset(sorted_equivalent_t, const container_type& cont, const Allocator& a); - template - flat_multiset(sorted_equivalent_t, const container_type& cont, - const key_compare& comp, const Allocator& a); - - explicit flat_multiset(const key_compare& comp) - : @\exposid{c}@(), @\exposid{compare}@(comp) { } - template - flat_multiset(const key_compare& comp, const Allocator& a); - template - explicit flat_multiset(const Allocator& a); - - template - flat_multiset(InputIterator first, InputIterator last, - const key_compare& comp = key_compare()) - : @\exposid{c}@(), @\exposid{compare}@(comp) - { insert(first, last); } - template - flat_multiset(InputIterator first, InputIterator last, - const key_compare& comp, const Allocator& a); - template - flat_multiset(InputIterator first, InputIterator last, const Allocator& a); - - template<@\exposconcept{container-compatible-range}@ R> - flat_multiset(from_range_t fr, R&& rg) - : flat_multiset(fr, std::forward(rg), key_compare()) { } - template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_multiset(from_range_t, R&& rg, const Allocator& a); - template<@\exposconcept{container-compatible-range}@ R> - flat_multiset(from_range_t, R&& rg, const key_compare& comp) - : flat_multiset(comp) - { insert_range(std::forward(rg)); } - template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); - - template - flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, - const key_compare& comp = key_compare()) - : @\exposid{c}@(first, last), @\exposid{compare}@(comp) { } - template - flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, - const key_compare& comp, const Allocator& a); - template - flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, - const Allocator& a); - - flat_multiset(initializer_list il, const key_compare& comp = key_compare()) - : flat_multiset(il.begin(), il.end(), comp) { } - template - flat_multiset(initializer_list il, const key_compare& comp, - const Allocator& a); - template - flat_multiset(initializer_list il, const Allocator& a); - - flat_multiset(sorted_equivalent_t s, initializer_list il, - const key_compare& comp = key_compare()) - : flat_multiset(s, il.begin(), il.end(), comp) { } - template - flat_multiset(sorted_equivalent_t, initializer_list il, - const key_compare& comp, const Allocator& a); - template - flat_multiset(sorted_equivalent_t, initializer_list il, const Allocator& a); - - flat_multiset& operator=(initializer_list); - - // iterators - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; - - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; - - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; - - // capacity - [[nodiscard]] bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; - - // \ref{flat.multiset.modifiers}, modifiers - template iterator emplace(Args&&... args); - template - iterator emplace_hint(const_iterator position, Args&&... args); - - iterator insert(const value_type& x) - { return emplace(x); } - iterator insert(value_type&& x) - { return emplace(std::move(x)); } - iterator insert(const_iterator position, const value_type& x) - { return emplace_hint(position, x); } - iterator insert(const_iterator position, value_type&& x) - { return emplace_hint(position, std::move(x)); } - - template - void insert(InputIterator first, InputIterator last); - template - void insert(sorted_equivalent_t, InputIterator first, InputIterator last); - template<@\exposconcept{container-compatible-range}@ R> - void insert_range(R&& rg); - - void insert(initializer_list il) - { insert(il.begin(), il.end()); } - void insert(sorted_equivalent_t s, initializer_list il) - { insert(s, il.begin(), il.end()); } - - container_type extract() &&; - void replace(container_type&&); - - iterator erase(iterator position); - iterator erase(const_iterator position); - size_type erase(const key_type& x); - template size_type erase(K&& x); - iterator erase(const_iterator first, const_iterator last); - - void swap(flat_multiset& y) noexcept; - void clear() noexcept; - - // observers - key_compare key_comp() const; - value_compare value_comp() const; - - // set operations - iterator find(const key_type& x); - const_iterator find(const key_type& x) const; - template iterator find(const K& x); - template const_iterator find(const K& x) const; - - size_type count(const key_type& x) const; - template size_type count(const K& x) const; - - bool contains(const key_type& x) const; - template bool contains(const K& x) const; - - iterator lower_bound(const key_type& x); - const_iterator lower_bound(const key_type& x) const; - template iterator lower_bound(const K& x); - template const_iterator lower_bound(const K& x) const; - - iterator upper_bound(const key_type& x); - const_iterator upper_bound(const key_type& x) const; - template iterator upper_bound(const K& x); - template const_iterator upper_bound(const K& x) const; +\effects +Equivalent to: \tcode{return R\{data() + (size() - Count), Count\};} +where \tcode{R} is the return type. +\end{itemdescr} - pair equal_range(const key_type& x); - pair equal_range(const key_type& x) const; - template - pair equal_range(const K& x); - template - pair equal_range(const K& x) const; +\indexlibrarymember{span}{subspan}% +\begin{itemdecl} +template + constexpr span subspan() const; +\end{itemdecl} - friend bool operator==(const flat_multiset& x, const flat_multiset& y); +\begin{itemdescr} +\pnum +\mandates +\begin{codeblock} +Offset <= Extent && (Count == dynamic_extent || Count <= Extent - Offset) +\end{codeblock} +is \tcode{true}. - friend @\placeholder{synth-three-way-result}@ - operator<=>(const flat_multiset& x, const flat_multiset& y); +\pnum +\hardexpects +\begin{codeblock} +Offset <= size() && (Count == dynamic_extent || Count <= size() - Offset) +\end{codeblock} +is \tcode{true}. - friend void swap(flat_multiset& x, flat_multiset& y) noexcept - { x.swap(y); } +\pnum +\effects +Equivalent to: +\begin{codeblock} +return span( + data() + Offset, Count != dynamic_extent ? Count : size() - Offset); +\end{codeblock} - private: - container_type @\exposidnc{c}@; // \expos - key_compare @\exposidnc{compare}@; // \expos - }; +\pnum +\remarks +The second template argument of the returned \tcode{span} type is: +\begin{codeblock} +Count != dynamic_extent ? Count + : (Extent != dynamic_extent ? Extent - Offset + : dynamic_extent) +\end{codeblock} +\end{itemdescr} - template> - flat_multiset(KeyContainer, Compare = Compare()) - -> flat_multiset; - template - flat_multiset(KeyContainer, Allocator) - -> flat_multiset, KeyContainer>; - template - flat_multiset(KeyContainer, Compare, Allocator) - -> flat_multiset; +\indexlibrarymember{span}{first}% +\begin{itemdecl} +constexpr span first(size_type count) const; +\end{itemdecl} - template> - flat_multiset(sorted_equivalent_t, KeyContainer, Compare = Compare()) - -> flat_multiset; - template - flat_multiset(sorted_equivalent_t, KeyContainer, Allocator) - -> flat_multiset, KeyContainer>; - template - flat_multiset(sorted_equivalent_t, KeyContainer, Compare, Allocator) - -> flat_multiset; +\begin{itemdescr} +\pnum +\hardexpects +\tcode{count <= size()} is \tcode{true}. - template>> - flat_multiset(InputIterator, InputIterator, Compare = Compare()) - -> flat_multiset<@\placeholder{iter-value-type}@, Compare>; +\pnum +\effects +Equivalent to: \tcode{return \{data(), count\};} +\end{itemdescr} - template>> - flat_multiset(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare()) - -> flat_multiset<@\placeholder{iter-value-type}@, Compare>; +\indexlibrarymember{span}{last}% +\begin{itemdecl} +constexpr span last(size_type count) const; +\end{itemdecl} - template>, - class Allocator = allocator>> - flat_multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) - -> flat_multiset, Compare, - vector, - @\exposid{alloc-rebind}@>>>; +\begin{itemdescr} +\pnum +\hardexpects +\tcode{count <= size()} is \tcode{true}. - template - flat_multiset(from_range_t, R&&, Allocator) - -> flat_multiset, less>, - vector, - @\exposid{alloc-rebind}@>>>; +\pnum +\effects +Equivalent to: \tcode{return \{data() + (size() - count), count\};} +\end{itemdescr} - template> - flat_multiset(initializer_list, Compare = Compare()) - -> flat_multiset; +\indexlibrarymember{span}{subspan}% +\begin{itemdecl} +constexpr span subspan( + size_type offset, size_type count = dynamic_extent) const; +\end{itemdecl} - template> - flat_multiset(sorted_equivalent_t, initializer_list, Compare = Compare()) - -> flat_multiset; +\begin{itemdescr} +\pnum +\hardexpects +\begin{codeblock} +offset <= size() && (count == dynamic_extent || count <= size() - offset) +\end{codeblock} +is \tcode{true}. - template - struct uses_allocator, Allocator> - : bool_constant> { }; -} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return {data() + offset, count == dynamic_extent ? size() - offset : count}; \end{codeblock} +\end{itemdescr} -\rSec3[flat.multiset.cons]{Constructors} +\rSec4[span.obs]{Observers} -\indexlibraryctor{flat_multiset}% +\indexlibrarymember{span}{size}% \begin{itemdecl} -explicit flat_multiset(container_type cont, const key_compare& comp = key_compare()); +constexpr size_type size() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{c} with \tcode{std::move(cont)} and -\exposid{compare} with \tcode{comp}, and -sorts the range \range{begin()}{end()} with respect to \exposid{compare}. - -\pnum -\complexity -Linear in $N$ if \tcode{cont} is sorted with respect to \exposid{compare} and -otherwise $N \log N$, where $N$ is the value of \tcode{cont.size()} before this call. +Equivalent to: \tcode{return \exposid{size_};} \end{itemdescr} -\indexlibraryctor{flat_multiset}% +\indexlibrarymember{span}{size_bytes}% \begin{itemdecl} -template - flat_multiset(const container_type& cont, const Allocator& a); -template - flat_multiset(const container_type& cont, const key_compare& comp, const Allocator& a); +constexpr size_type size_bytes() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true}. - \pnum \effects -Equivalent to \tcode{flat_multiset(cont)} and -\tcode{flat_multiset(cont, comp)}, respectively, -except that \exposid{c} is constructed with -uses-allocator construction\iref{allocator.uses.construction}. +Equivalent to: \tcode{return size() * sizeof(element_type);} +\end{itemdescr} + +\indexlibrarymember{span}{empty}% +\begin{itemdecl} +constexpr bool empty() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -Same as \tcode{flat_multiset(cont)} and -\tcode{flat_multiset(cont, comp)}, respectively. +\effects +Equivalent to: \tcode{return size() == 0;} \end{itemdescr} -\indexlibraryctor{flat_multiset}% +\rSec4[span.elem]{Element access} + +\indexlibrary{\idxcode{operator[]}!\idxcode{span}}% \begin{itemdecl} -template - flat_multiset(sorted_equivalent_t s, const container_type& cont, const Allocator& a); -template - flat_multiset(sorted_equivalent_t s, const container_type& cont, - const key_compare& comp, const Allocator& a); +constexpr reference operator[](size_type idx) const; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true}. +\hardexpects +\tcode{idx < size()} is \tcode{true}. \pnum -\effects -Equivalent to \tcode{flat_multiset(s, cont)} and -\tcode{flat_multiset(s, cont, comp)}, respectively, -except that \exposid{c} is constructed with -uses-allocator construction\iref{allocator.uses.construction}. +\returns +\tcode{*(data() + idx)}. \pnum -\complexity -Linear. +\throws +Nothing. \end{itemdescr} -\indexlibraryctor{flat_multiset}% +\indexlibrarymember{span}{at}% \begin{itemdecl} -template - flat_multiset(const flat_multiset&, const Allocator& a); -template - flat_multiset(flat_multiset&&, const Allocator& a); -template - flat_multiset(const key_compare& comp, const Allocator& a); -template - explicit flat_multiset(const Allocator& a); -template - flat_multiset(InputIterator first, InputIterator last, - const key_compare& comp, const Allocator& a); -template - flat_multiset(InputIterator first, InputIterator last, const Allocator& a); -template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_multiset(from_range_t, R&& rg, const Allocator& a); -template<@\exposconcept{container-compatible-range}@ R, class Allocator> - flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Allocator& a); -template - flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, - const key_compare& comp, const Allocator& a); -template - flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const Allocator& a); -template - flat_multiset(initializer_list il, const key_compare& comp, const Allocator& a); -template - flat_multiset(initializer_list il, const Allocator& a); -template - flat_multiset(sorted_equivalent_t, initializer_list il, - const key_compare& comp, const Allocator& a); -template - flat_multiset(sorted_equivalent_t, initializer_list il, const Allocator& a); +constexpr reference at(size_type idx) const; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{uses_allocator_v} is \tcode{true}. +\returns +\tcode{*(data() + idx)}. \pnum -\effects -Equivalent to the corresponding non-allocator constructors -except that \exposid{c} is constructed with -uses-allocator construction\iref{allocator.uses.construction}. +\throws +\tcode{out_of_range} if \tcode{idx >= size()} is \tcode{true}. \end{itemdescr} -\rSec3[flat.multiset.modifiers]{Modifiers} - -\indexlibrarymember{emplace}{flat_multiset}% +\indexlibrarymember{span}{front}% \begin{itemdecl} -template iterator emplace(Args&&... args); +constexpr reference front() const; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum -\effects -First, initializes an object \tcode{t} of type \tcode{value_type} -with \tcode{std::forward(args)...}, -then inserts \tcode{t} as if by: -\begin{codeblock} -auto it = ranges::upper_bound(c, t, compare); -c.insert(it, std::move(t)); -\end{codeblock} +\returns +\tcode{*data()}. \pnum -\returns -An iterator that points to the inserted element. +\throws +Nothing. \end{itemdescr} -\indexlibrarymember{insert}{flat_multiset}% +\indexlibrarymember{span}{back}% \begin{itemdecl} -template - void insert(InputIterator first, InputIterator last); +constexpr reference back() const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Adds elements to \exposid{c} as if by: -\begin{codeblock} -c.insert(c.end(), first, last); -\end{codeblock} -Then, sorts the range of newly inserted elements with respect to \exposid{compare}, -and merges the resulting sorted range and -the sorted range of pre-existing elements into a single sorted range. +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum -\complexity -$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and $M$ -is \tcode{distance(first, last)}. +\returns +\tcode{*(data() + (size() - 1))}. \pnum -\remarks -Since this operation performs an in-place merge, it may allocate memory. +\throws +Nothing. \end{itemdescr} -\indexlibrarymember{insert}{flat_multiset}% +\indexlibrarymember{span}{data}% \begin{itemdecl} -template - void insert(sorted_equivalent_t, InputIterator first, InputIterator last); +constexpr pointer data() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{insert(first, last)}. +\returns +\exposid{data_}. +\end{itemdescr} + +\rSec4[span.iterators]{Iterator support} + +\indexlibrarymember{iterator}{span}% +\begin{itemdecl} +using iterator = @\impdefx{type of \tcode{span::iterator}}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The type +models \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}, +meets the \oldconcept{RandomAccessIterator} +requirements\iref{random.access.iterators}, +and +meets the requirements for +constexpr iterators\iref{iterator.requirements.general}, +whose value type is \tcode{value_type} and +whose reference type is \tcode{reference}. \pnum -\complexity -Linear. +All requirements on container iterators\iref{container.reqmts} apply to +\tcode{span::iterator} as well. \end{itemdescr} -\indexlibrarymember{swap}{flat_multiset}% +\indexlibrarymember{span}{begin}% \begin{itemdecl} -void swap(flat_multiset& y) noexcept; +constexpr iterator begin() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -ranges::swap(compare, y.compare); -ranges::swap(c, y.c); -\end{codeblock} +\returns +An iterator referring to the first element in the span. +If \tcode{empty()} is \tcode{true}, then it returns the +same value as \tcode{end()}. \end{itemdescr} -\indexlibrarymember{extract}{flat_multiset}% +\indexlibrarymember{span}{end}% \begin{itemdecl} -container_type extract() &&; +constexpr iterator end() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\ensures -\tcode{*this} is emptied, even if the function exits via an exception. - \pnum \returns -\tcode{std::move(c)}. +An iterator which is the past-the-end value. \end{itemdescr} -\indexlibrarymember{replace}{flat_multiset}% +\indexlibrarymember{span}{rbegin}% \begin{itemdecl} -void replace(container_type&& cont); +constexpr reverse_iterator rbegin() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -The elements of \tcode{cont} are sorted with respect to \exposid{compare}. - \pnum \effects -Equivalent to: \tcode{c = std::move(cont);} +Equivalent to: \tcode{return reverse_iterator(end());} \end{itemdescr} -\rSec3[flat.multiset.erasure]{Erasure} - -\indexlibrarymember{erase_if}{flat_multiset}% +\indexlibrarymember{span}{rend}% \begin{itemdecl} -template - typename flat_multiset::size_type - erase_if(flat_multiset& c, Predicate pred); +constexpr reverse_iterator rend() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{Key} meets the \oldconcept{MoveAssignable} requirements. - \pnum \effects -Let $E$ be \tcode{bool(pred(as_const(e)))}. -Erases all elements \tcode{e} in \tcode{c} for which $E$ holds. - -\pnum -\returns -The number of elements erased. - -\pnum -\complexity -Exactly \tcode{c.size()} applications of the predicate. - -\pnum -\remarks -Stable\iref{algorithm.stable}. -If an invocation of \tcode{erase_if} exits via an exception, -\tcode{c} is in a valid but unspecified state\iref{defns.valid}. -\begin{note} -\tcode{c} still meets its invariants, but can be empty. -\end{note} +Equivalent to: \tcode{return reverse_iterator(begin());} \end{itemdescr} -\rSec2[container.adaptors.format]{Container adaptors formatting} - -\pnum -For each of -\tcode{queue}, -\tcode{priority_queue}, and -\tcode{stack}, -the library provides the following formatter specialization -where \tcode{\placeholder{adaptor-type}} is the name of the template: - -\indexlibraryglobal{formatter}% -\begin{codeblock} -namespace std { - template Container, class... U> - struct formatter<@\placeholder{adaptor-type}@, charT> { - private: - using @\exposid{maybe-const-container}@ = // \expos - @\exposid{fmt-maybe-const}@; - using @\exposid{maybe-const-adaptor}@ = // \expos - @\exposid{maybe-const}@, // see \ref{ranges.syn} - @\placeholder{adaptor-type}@>; - formatter, charT> @\exposid{underlying_}@; // \expos - - public: - template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); - - template - typename FormatContext::iterator - format(@\exposid{maybe-const-adaptor}@& r, FormatContext& ctx) const; - }; -} -\end{codeblock} +\rSec3[span.objectrep]{Views of object representation} -\indexlibrarymember{parse}{formatter}% +\indexlibraryglobal{as_bytes}% \begin{itemdecl} -template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); +template + span + as_bytes(span s) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +Equivalent to: \tcode{return R\{reinterpret_cast(s.data()), s.size_bytes()\};} +where \tcode{R} is the return type. \end{itemdescr} -\indexlibrarymember{format}{formatter}% +\indexlibraryglobal{as_writable_bytes}% \begin{itemdecl} -template - typename FormatContext::iterator - format(@\exposid{maybe-const-adaptor}@& r, FormatContext& ctx) const; +template + span + as_writable_bytes(span s) noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \effects -Equivalent to: \tcode{return \exposid{underlying_}.format(r.c, ctx);} +Equivalent to: \tcode{return R\{reinterpret_cast(s.data()), s.size_bytes()\};} +where \tcode{R} is the return type. \end{itemdescr} -\rSec1[views]{Views} +\rSec2[views.multidim]{Multidimensional access} -\rSec2[views.general]{General} +\rSec3[mdspan.overview]{Overview} \pnum -The header \libheader{span} defines the view \tcode{span}. -The header \libheader{mdspan} defines the class template \tcode{mdspan} and -other facilities for interacting with these multidimensional views. +A \defnadj{multidimensional}{index space} is +a Cartesian product of integer intervals. +Each interval can be represented by a half-open range $[L_i, U_i)$, +where $L_i$ and $U_i$ are the lower and upper bounds of +the $i^\text{th}$ dimension. +The \defn{rank} of a multidimensional index space is +the number of intervals it represents. +The \defn{size of a multidimensional index space} is +the product of $U_i - L_i$ for each dimension $i$ +if its rank is greater than 0, and 1 otherwise. -\rSec2[views.contiguous]{Contiguous access} +\pnum +An integer $r$ is a \defn{rank index} of an index space $S$ +if $r$ is in the range $[0, \text{rank of $S$})$. -\rSec3[span.syn]{Header \tcode{} synopsis}% +\pnum +A pack of integers \tcode{idx} is +a \defnadj{multidimensional}{index} in a multidimensional index space $S$ +(or representation thereof) if both of the following are true: +\begin{itemize} +\item +\tcode{sizeof...(idx)} is equal to the rank of $S$, and +\item +for every rank index $i$ of $S$, +the $i^\text{th}$ value of \tcode{idx} is an integer +in the interval $[L_i, U_i)$ of $S$. +\end{itemize} -\indexheader{span}% -\begin{codeblock} -#include // see \ref{initializer.list.syn} +\rSec3[mdspan.syn]{Header \tcode{} synopsis} +\indexheader{mdspan}% +\begin{codeblock} // mostly freestanding namespace std { - // constants - inline constexpr size_t @\libglobal{dynamic_extent}@ = numeric_limits::max(); - - // \ref{views.span}, class template \tcode{span} - template - class span; // partially freestanding - - template - constexpr bool ranges::@\libspec{enable_view}{span}@> = true; - template - constexpr bool ranges::@\libspec{enable_borrowed_range}{span}@> = true; - - // \ref{span.objectrep}, views of object representation - template - span - as_bytes(span s) noexcept; - - template - span - as_writable_bytes(span s) noexcept; -} -\end{codeblock} - -\rSec3[views.span]{Class template \tcode{span}} - -\rSec4[span.overview]{Overview} + // \ref{mdspan.extents}, class template \tcode{extents} + template + class extents; -\pnum -\indexlibraryglobal{span}% -A \tcode{span} is a view over a contiguous sequence of objects, -the storage of which is owned by some other object. + // \ref{mdspan.extents.dextents}, alias template \tcode{dextents} + template + using dextents = @\seebelow@; -\pnum -All member functions of \tcode{span} have constant time complexity. + // \ref{mdspan.extents.dims}, alias template \tcode{dims} + template + using dims = @\seebelow@; -\indexlibraryglobal{span}% -\begin{codeblock} -namespace std { - template - class span { - public: - // constants and types - using element_type = ElementType; - using value_type = remove_cv_t; - using size_type = size_t; - using difference_type = ptrdiff_t; - using pointer = element_type*; - using const_pointer = const element_type*; - using reference = element_type&; - using const_reference = const element_type&; - using iterator = @\impdefx{type of \tcode{span::iterator}}@; // see \ref{span.iterators} - using const_iterator = std::const_iterator; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::const_iterator; - static constexpr size_type extent = Extent; + // \ref{mdspan.layout}, layout mapping + struct layout_left; + struct layout_right; + struct layout_stride; + template + struct layout_left_padded; + template + struct layout_right_padded; - // \ref{span.cons}, constructors, copy, and assignment - constexpr span() noexcept; - template - constexpr explicit(extent != dynamic_extent) span(It first, size_type count); - template - constexpr explicit(extent != dynamic_extent) span(It first, End last); - template - constexpr span(type_identity_t (&arr)[N]) noexcept; - template - constexpr span(array& arr) noexcept; - template - constexpr span(const array& arr) noexcept; - template - constexpr explicit(extent != dynamic_extent) span(R&& r); - constexpr explicit(extent != dynamic_extent) span(std::initializer_list il); - constexpr span(const span& other) noexcept = default; - template - constexpr explicit(@\seebelow@) span(const span& s) noexcept; + // \ref{mdspan.accessor.default}, class template \tcode{default_accessor} + template + class default_accessor; - constexpr span& operator=(const span& other) noexcept = default; + // \ref{mdspan.accessor.aligned}, class template \tcode{aligned_accessor} + template + class aligned_accessor; - // \ref{span.sub}, subviews - template - constexpr span first() const; - template - constexpr span last() const; - template - constexpr span subspan() const; + // \ref{mdspan.mdspan}, class template \tcode{mdspan} + template> + class mdspan; // partially freestanding - constexpr span first(size_type count) const; - constexpr span last(size_type count) const; - constexpr span subspan( - size_type offset, size_type count = dynamic_extent) const; + // \ref{mdspan.sub}, \tcode{submdspan} creation + template + struct strided_slice; - // \ref{span.obs}, observers - constexpr size_type size() const noexcept; - constexpr size_type size_bytes() const noexcept; - [[nodiscard]] constexpr bool empty() const noexcept; + template + struct submdspan_mapping_result; - // \ref{span.elem}, element access - constexpr reference operator[](size_type idx) const; - constexpr reference at(size_type idx) const; // freestanding-deleted - constexpr reference front() const; - constexpr reference back() const; - constexpr pointer data() const noexcept; + struct full_extent_t { explicit full_extent_t() = default; }; + inline constexpr full_extent_t full_extent{}; - // \ref{span.iterators}, iterator support - constexpr iterator begin() const noexcept; - constexpr iterator end() const noexcept; - constexpr const_iterator cbegin() const noexcept { return begin(); } - constexpr const_iterator cend() const noexcept { return end(); } - constexpr reverse_iterator rbegin() const noexcept; - constexpr reverse_iterator rend() const noexcept; - constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); } - constexpr const_reverse_iterator crend() const noexcept { return rend(); } + template + constexpr auto submdspan_extents(const extents&, SliceSpecifiers...); - private: - pointer @\exposid{data_}@; // \expos - size_type @\exposid{size_}@; // \expos - }; + // \ref{mdspan.sub.sub}, \tcode{submdspan} function template + template + constexpr auto submdspan( + const mdspan& src, + SliceSpecifiers... slices) -> @\seebelow@; - template - span(It, EndOrSize) -> span>>; - template - span(T (&)[N]) -> span; - template - span(array&) -> span; - template - span(const array&) -> span; - template - span(R&&) -> span>>; + template + concept @\defexposconcept{index-pair-like}@ = // \expos + @\exposconcept{pair-like}@ && + @\libconcept{convertible_to}@, IndexType> && + @\libconcept{convertible_to}@, IndexType>; } \end{codeblock} -\pnum -\tcode{span} is -a trivially copyable type\iref{term.trivially.copyable.type}. +\rSec3[mdspan.extents]{Class template \tcode{extents}} -\pnum -\tcode{ElementType} is required to be -a complete object type that is not an abstract class type. +\rSec4[mdspan.extents.overview]{Overview} -\pnum -For a \tcode{span} \tcode{s}, -any operation that invalidates a pointer in -the range \range{s.data()}{s.data() + s.size()} -invalidates pointers, iterators, and references to elements of \tcode{s}. +The class template \tcode{extents} represents +a multidimensional index space of rank equal to \tcode{sizeof...(Extents)}. +In~\ref{views}, +\tcode{extents} is used synonymously with multidimensional index space. -\rSec4[span.cons]{Constructors, copy, and assignment} +\begin{codeblock} +namespace std { + template + class @\libglobal{extents}@ { + public: + using index_type = IndexType; + using size_type = make_unsigned_t; + using rank_type = size_t; -\indexlibraryctor{span}% -\begin{itemdecl} -constexpr span() noexcept; -\end{itemdecl} + // \ref{mdspan.extents.obs}, observers of the multidimensional index space + static constexpr rank_type rank() noexcept { return sizeof...(Extents); } + static constexpr rank_type rank_dynamic() noexcept { return @\exposid{dynamic-index}@(rank()); } + static constexpr size_t static_extent(rank_type) noexcept; + constexpr index_type extent(rank_type) const noexcept; -\begin{itemdescr} -\pnum -\constraints -\tcode{Extent == dynamic_extent || Extent == 0} is \tcode{true}. + // \ref{mdspan.extents.cons}, constructors + constexpr extents() noexcept = default; -\pnum -\ensures -\tcode{size() == 0 \&\& data() == nullptr}. -\end{itemdescr} + template + constexpr explicit(@\seebelow@) + extents(const extents&) noexcept; + template + constexpr explicit extents(OtherIndexTypes...) noexcept; + template + constexpr explicit(N != rank_dynamic()) + extents(span) noexcept; + template + constexpr explicit(N != rank_dynamic()) + extents(const array&) noexcept; -\indexlibraryctor{span}% -\begin{itemdecl} -template - constexpr explicit(extent != dynamic_extent) span(It first, size_type count); -\end{itemdecl} + // \ref{mdspan.extents.cmp}, comparison operators + template + friend constexpr bool operator==(const extents&, + const extents&) noexcept; + + // \ref{mdspan.extents.expo}, exposition-only helpers + constexpr size_t @\exposid{fwd-prod-of-extents}@(rank_type) const noexcept; // \expos + constexpr size_t @\exposid{rev-prod-of-extents}@(rank_type) const noexcept; // \expos + template + static constexpr auto @\exposid{index-cast}@(OtherIndexType&&) noexcept; // \expos + + private: + static constexpr rank_type @\exposid{dynamic-index}@(rank_type) noexcept; // \expos + static constexpr rank_type @\exposid{dynamic-index-inv}@(rank_type) noexcept; // \expos + array @\exposid{dynamic-extents}@{}; // \expos + }; + + template + explicit extents(Integrals...) + -> @\seebelow@; +} +\end{codeblock} -\begin{itemdescr} \pnum -\constraints -Let \tcode{U} be \tcode{remove_reference_t>}. +\mandates \begin{itemize} -\item \tcode{It} satisfies \libconcept{contiguous_iterator}. \item -\tcode{is_convertible_v} is \tcode{true}. -\begin{note} -The intent is to allow only qualification conversions -of the iterator reference type to \tcode{element_type}. -\end{note} +\tcode{IndexType} is a signed or unsigned integer type, and +\item +each element of \tcode{Extents} is either equal to \tcode{dynamic_extent}, or +is representable as a value of type \tcode{IndexType}. \end{itemize} \pnum -\expects -\begin{itemize} -\item \range{first}{first + count} is a valid range. -\item \tcode{It} models \libconcept{contiguous_iterator}. -\item -If \tcode{extent} is not equal to \tcode{dynamic_extent}, -then \tcode{count} is equal to \tcode{extent}. -\end{itemize} +Each specialization of \tcode{extents} models \libconcept{regular} and +is trivially copyable. \pnum -\effects -Initializes \exposid{data_} with \tcode{to_address(first)} and -\exposid{size_} with \tcode{count}. +Let $E_r$ be the $r^\text{th}$ element of \tcode{Extents}. +$E_r$ is a \defnadj{dynamic}{extent} if it is equal to \tcode{dynamic_extent}, +otherwise $E_r$ is a \defnadj{static}{extent}. +Let $D_r$ be the value of \tcode{\exposid{dynamic-extents}[\exposid{dynamic-index}($r$)]} +if $E_r$ is a dynamic extent, +otherwise $E_r$. \pnum -\throws -Nothing. -\end{itemdescr} +The $r^\text{th}$ interval of the multidimensional index space +represented by an \tcode{extents} object is $[0, D_r)$. + +\rSec4[mdspan.extents.expo]{Exposition-only helpers} -\indexlibraryctor{span}% \begin{itemdecl} -template - constexpr explicit(extent != dynamic_extent) span(It first, End last); +static constexpr rank_type @\exposid{dynamic-index}@(rank_type i) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -Let \tcode{U} be \tcode{remove_reference_t>}. -\begin{itemize} -\item -\tcode{is_convertible_v} is \tcode{true}. -\begin{note} -The intent is to allow only qualification conversions -of the iterator reference type to \tcode{element_type}. -\end{note} -\item \tcode{It} satisfies \libconcept{contiguous_iterator}. -\item \tcode{End} satisfies \tcode{\libconcept{sized_sentinel_for}}. -\item \tcode{is_convertible_v} is \tcode{false}. -\end{itemize} - \pnum \expects -\begin{itemize} -\item -If \tcode{extent} is not equal to \tcode{dynamic_extent}, -then \tcode{last - first} is equal to \tcode{extent}. -\item \range{first}{last} is a valid range. -\item \tcode{It} models \libconcept{contiguous_iterator}. -\item \tcode{End} models \tcode{\libconcept{sized_sentinel_for}}. -\end{itemize} - -\pnum -\effects -Initializes \exposid{data_} with \tcode{to_address(first)} and -\exposid{size_} with \tcode{last - first}. +\tcode{i <= rank()} is \tcode{true}. \pnum -\throws -When and what \tcode{last - first} throws. +\returns +The number of $E_r$ with $r < \tcode{i}$ for which $E_r$ is a dynamic extent. \end{itemdescr} -\indexlibraryctor{span}% \begin{itemdecl} -template constexpr span(type_identity_t (&arr)[N]) noexcept; -template constexpr span(array& arr) noexcept; -template constexpr span(const array& arr) noexcept; +static constexpr rank_type @\exposid{dynamic-index-inv}@(rank_type i) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -Let \tcode{U} be \tcode{remove_pointer_t}. -\begin{itemize} -\item \tcode{extent == dynamic_extent || N == extent} is \tcode{true}, and -\item \tcode{is_convertible_v} is \tcode{true}. -\begin{note} -The intent is to allow only qualification conversions -of the array element type to \tcode{element_type}. -\end{note} -\end{itemize} - -\pnum -\effects -Constructs a \tcode{span} that is a view over the supplied array. -\begin{note} -\tcode{type_identity_t} affects class template argument deduction. -\end{note} +\expects +\tcode{i < rank_dynamic()} is \tcode{true}. \pnum -\ensures -\tcode{size() == N \&\& data() == std::data(arr)} is \tcode{true}. +\returns +The minimum value of $r$ +such that \tcode{\exposid{dynamic-index}($r$ + 1) == i + 1} is \tcode{true}. \end{itemdescr} -\indexlibraryctor{span}% \begin{itemdecl} -template constexpr explicit(extent != dynamic_extent) span(R&& r); +constexpr size_t @\exposid{fwd-prod-of-extents}@(rank_type i) const noexcept; \end{itemdecl} -\begin{itemdescr} -\pnum -\constraints -Let \tcode{U} be \tcode{remove_reference_t>}. -\begin{itemize} -\item \tcode{R} satisfies \tcode{ranges::\libconcept{contiguous_range}} and - \tcode{ranges::\libconcept{sized_range}}. -\item Either \tcode{R} satisfies \tcode{ranges::\libconcept{borrowed_range}} or -\tcode{is_const_v} is \tcode{true}. -\item \tcode{remove_cvref_t} is not a specialization of \tcode{span}. -\item \tcode{remove_cvref_t} is not a specialization of \tcode{array}. -\item \tcode{is_array_v>} is \tcode{false}. -\item -\tcode{is_convertible_v} is \tcode{true}. -\begin{note} -The intent is to allow only qualification conversions -of the range reference type to \tcode{element_type}. -\end{note} -\end{itemize} - +\begin{itemdescr} \pnum \expects -\begin{itemize} -\item If \tcode{extent} is not equal to \tcode{dynamic_extent}, -then \tcode{ranges::size(r)} is equal to \tcode{extent}. -\item \tcode{R} models \tcode{ranges::\libconcept{contiguous_range}} and -\tcode{ranges::\libconcept{sized_range}}. -\item If \tcode{is_const_v} is \tcode{false}, -\tcode{R} models \tcode{ranges::\libconcept{borrowed_range}}. -\end{itemize} - -\pnum -\effects -Initializes \exposid{data_} with \tcode{ranges::data(r)} and -\exposid{size_} with \tcode{ranges::size(r)}. +\tcode{i <= rank()} is \tcode{true}. \pnum -\throws -What and when \tcode{ranges::data(r)} and \tcode{ranges::size(r)} throw. +\returns +If \tcode{i > 0} is \tcode{true}, +the product of \tcode{extent($k$)} for all $k$ in the range $[0, \tcode{i})$, +otherwise \tcode{1}. \end{itemdescr} -\indexlibraryctor{span}% \begin{itemdecl} -constexpr explicit(extent != dynamic_extent) span(std::initializer_list il); +constexpr size_t @\exposid{rev-prod-of-extents}@(rank_type i) const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{is_const_v} is \tcode{true}. - \pnum \expects -If \tcode{extent} is not equal to \tcode{dynamic_extent}, then -\tcode{il.size()} is equal to \tcode{extent}. +\tcode{i < rank()} is \tcode{true}. \pnum -\effects -Initializes \exposid{data_} with \tcode{il.begin()} and -\exposid{size_} with \tcode{il.size()}. +\returns +If \tcode{i + 1 < rank()} is \tcode{true}, +the product of \tcode{extent($k$)} +for all $k$ in the range $[\tcode{i + 1}, \tcode{rank()})$, +otherwise \tcode{1}. \end{itemdescr} -\indexlibraryctor{span}% \begin{itemdecl} -constexpr span(const span& other) noexcept = default; +template + static constexpr auto @\exposid{index-cast}@(OtherIndexType&& i) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{other.size() == size() \&\& other.data() == data()}. +\effects +\begin{itemize} +\item +If \tcode{OtherIndexType} is an integral type other than \tcode{bool}, +then equivalent to \tcode{return i;}, +\item +otherwise, equivalent to \tcode{return static_cast(i);}. +\end{itemize} +\begin{note} +This function will always return an integral type other than \tcode{bool}. +Since this function's call sites are constrained on +convertibility of \tcode{OtherIndexType} to \tcode{index_type}, +integer-class types can use the \tcode{static_cast} branch +without loss of precision. +\end{note} \end{itemdescr} -\indexlibraryctor{span}% +\rSec4[mdspan.extents.cons]{Constructors} + +\indexlibraryctor{extents}% \begin{itemdecl} -template - constexpr explicit(@\seebelow@) span(const span& s) noexcept; +template + constexpr explicit(@\seebelow@) + extents(const extents& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints \begin{itemize} -\item \tcode{extent == dynamic_extent} \tcode{||} \tcode{OtherExtent == dynamic_extent} \tcode{||} \tcode{extent == OtherExtent} is \tcode{true}, and -\item \tcode{is_convertible_v} is \tcode{true}. -\begin{note} -The intent is to allow only qualification conversions -of the \tcode{OtherElementType} to \tcode{element_type}. -\end{note} +\item +\tcode{sizeof...(OtherExtents) == rank()} is \tcode{true}. +\item +\tcode{((OtherExtents == dynamic_extent || Extents == dynamic_extent || OtherExtents ==\newline Extents) \&\& ...)} is \tcode{true}. \end{itemize} \pnum \expects -If \tcode{extent} is not equal to \tcode{dynamic_extent}, -then \tcode{s.size()} is equal to \tcode{extent}. - -\pnum -\effects -Constructs a \tcode{span} that is a view over the range -\range{s.data()}{s.data() + s.size()}. +\begin{itemize} +\item +\tcode{other.extent($r$)} equals $E_r$ +for each $r$ for which $E_r$ is a static extent, and +\item +either +\begin{itemize} +\item +\tcode{sizeof...(OtherExtents)} is zero, or +\item +\tcode{other.extent($r$)} is representable as +a value of type \tcode{index_type} for every rank index $r$ of \tcode{other}. +\end{itemize} +\end{itemize} \pnum \ensures -\tcode{size() == s.size() \&\& data() == s.data()}. +\tcode{*this == other} is \tcode{true}. \pnum \remarks -The expression inside \keyword{explicit} is equivalent to: +The expression inside \tcode{explicit} is equivalent to: \begin{codeblock} -extent != dynamic_extent && OtherExtent == dynamic_extent +(((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ... ) || +(numeric_limits::max() < numeric_limits::max()) \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator=}{span}% +\indexlibraryctor{extents}% \begin{itemdecl} -constexpr span& operator=(const span& other) noexcept = default; +template + constexpr explicit extents(OtherIndexTypes... exts) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{size() == other.size() \&\& data() == other.data()}. -\end{itemdescr} - -\rSec4[span.deduct]{Deduction guides} - -\indexlibrary{\idxcode{span}!deduction guide}% -\begin{itemdecl} -template - span(It, EndOrSize) -> span>>; -\end{itemdecl} +Let \tcode{N} be \tcode{sizeof...(OtherIndexTypes)}, +and let \tcode{exts_arr} be +\tcode{array\{static_cast<\\index_type>(std::move(exts))...\}}. -\begin{itemdescr} \pnum \constraints -\tcode{It} satisfies \libconcept{contiguous_iterator}. -\end{itemdescr} +\begin{itemize} +\item +\tcode{(is_convertible_v \&\& ...)} is \tcode{true}, +\item +\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}, and +\item +\tcode{N == rank_dynamic() || N == rank()} is \tcode{true}. +\begin{note} +One can construct \tcode{extents} from just dynamic extents, +which are all the values getting stored, or +from all the extents with a precondition. +\end{note} +\end{itemize} -\indexlibrary{\idxcode{span}!deduction guide}% -\begin{itemdecl} -template - span(R&&) -> span>>; -\end{itemdecl} +\pnum +\expects +\begin{itemize} +\item +If \tcode{N != rank_dynamic()} is \tcode{true}, +\tcode{exts_arr[$r$]} equals $E_r$ +for each $r$ for which $E_r$ is a static extent, and +\item +either +\begin{itemize} +\item +\tcode{sizeof...(exts) == 0} is \tcode{true}, or +\item +each element of \tcode{exts} is representable +as a nonnegative value of type \tcode{index_type}. +\end{itemize} +\end{itemize} -\begin{itemdescr} \pnum -\constraints -\tcode{R} satisfies \tcode{ranges::\libconcept{contiguous_range}}. +\ensures +\tcode{*this == extents(exts_arr)} is \tcode{true}. \end{itemdescr} -\rSec4[span.sub]{Subviews} - -\indexlibrarymember{span}{first}% +\indexlibraryctor{extents}% \begin{itemdecl} -template constexpr span first() const; +template + constexpr explicit(N != rank_dynamic()) + extents(span exts) noexcept; +template + constexpr explicit(N != rank_dynamic()) + extents(const array& exts) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{Count <= Extent} is \tcode{true}. +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v} is \tcode{true}, +\item +\tcode{is_nothrow_constructible_v} is \tcode{true}, and +\item +\tcode{N == rank_dynamic() || N == rank()} is \tcode{true}. +\end{itemize} \pnum \expects -\tcode{Count <= size()} is \tcode{true}. +\begin{itemize} +\item +If \tcode{N != rank_dynamic()} is \tcode{true}, +\tcode{exts[$r$]} equals $E_r$ for each $r$ for which $E_r$ is a static extent, and +\item +either +\begin{itemize} +\item +\tcode{N} is zero, or +\item +\tcode{exts[$r$]} is representable +as a nonnegative value of type \tcode{index_type} for every rank index $r$. +\end{itemize} +\end{itemize} \pnum \effects -Equivalent to: \tcode{return R\{data(), Count\};} -where \tcode{R} is the return type. +\begin{itemize} +\item +If \tcode{N} equals \tcode{rank_dynamic()}, +for all $d$ in the range $[0, \tcode{rank_dynamic()})$, +direct-non-list-initializes \tcode{\exposidnc{dynamic-extents}[$d$]} +with \tcode{as_const(exts[$d$])}. +\item +Otherwise, for all $d$ in the range $[0, \tcode{rank_dynamic()})$, +direct-non-list-initializes \exposidnc{dynamic-ex\-tents}\tcode{[$d$]} +with \tcode{as_const(exts[\exposidnc{dynamic-index-inv}($d$)])}. +\end{itemize} \end{itemdescr} -\indexlibrarymember{span}{last}% +\indexlibraryctor{extents}% \begin{itemdecl} -template constexpr span last() const; +template + explicit extents(Integrals...) -> @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{Count <= Extent} is \tcode{true}. - -\pnum -\expects -\tcode{Count <= size()} is \tcode{true}. +\constraints +\tcode{(is_convertible_v \&\& ...)} is \tcode{true}. \pnum -\effects -Equivalent to: \tcode{return R\{data() + (size() - Count), Count\};} -where \tcode{R} is the return type. +\remarks +The deduced type is \tcode{extents...>}. \end{itemdescr} -\indexlibrarymember{span}{subspan}% +\rSec4[mdspan.extents.obs]{Observers of the multidimensional index space} + +\indexlibrarymember{static_extent}{extents}% \begin{itemdecl} -template - constexpr span subspan() const; +static constexpr size_t static_extent(rank_type i) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\mandates -\begin{codeblock} -Offset <= Extent && (Count == dynamic_extent || Count <= Extent - Offset) -\end{codeblock} -is \tcode{true}. - \pnum \expects -\begin{codeblock} -Offset <= size() && (Count == dynamic_extent || Count <= size() - Offset) -\end{codeblock} -is \tcode{true}. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -return span( - data() + Offset, Count != dynamic_extent ? Count : size() - Offset); -\end{codeblock} +\tcode{i < rank()} is \tcode{true}. \pnum -\remarks -The second template argument of the returned \tcode{span} type is: -\begin{codeblock} -Count != dynamic_extent ? Count - : (Extent != dynamic_extent ? Extent - Offset - : dynamic_extent) -\end{codeblock} +\returns +$E_\tcode{i}$. \end{itemdescr} -\indexlibrarymember{span}{first}% +\indexlibrarymember{extent}{extents}% \begin{itemdecl} -constexpr span first(size_type count) const; +constexpr index_type extent(rank_type i) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{count <= size()} is \tcode{true}. +\tcode{i < rank()} is \tcode{true}. \pnum -\effects -Equivalent to: \tcode{return \{data(), count\};} +\returns +$D_\tcode{i}$. \end{itemdescr} -\indexlibrarymember{span}{last}% +\rSec4[mdspan.extents.cmp]{Comparison operators} + +\indexlibrarymember{operator==}{extents}% \begin{itemdecl} -constexpr span last(size_type count) const; +template + friend constexpr bool operator==(const extents& lhs, + const extents& rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{count <= size()} is \tcode{true}. +\returns +\tcode{true} if \tcode{lhs.rank()} equals \tcode{rhs.rank()} and +if \tcode{lhs.extent(r)} equals \tcode{rhs.extent(r)} +for every rank index \tcode{r} of \tcode{rhs}, +otherwise \tcode{false}. +\end{itemdescr} + +\rSec4[mdspan.extents.dextents]{Alias template \tcode{dextents}} + +\indexlibraryglobal{dextents}% +\begin{itemdecl} +template + using dextents = @\seebelow@; +\end{itemdecl} +\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \{data() + (size() - count), count\};} +\result +A type \tcode{E} that is a specialization of \tcode{extents} +such that \tcode{E::rank() == Rank \&\& E::rank() == E::rank_dynamic()} is \tcode{true}, and +\tcode{E::index_type} denotes \tcode{IndexType}. \end{itemdescr} -\indexlibrarymember{span}{subspan}% +\rSec4[mdspan.extents.dims]{Alias template \tcode{dims}} + +\indexlibraryglobal{dims}% \begin{itemdecl} -constexpr span subspan( - size_type offset, size_type count = dynamic_extent) const; +template + using dims = @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\begin{codeblock} -offset <= size() && (count == dynamic_extent || count <= size() - offset) -\end{codeblock} -is \tcode{true}. +\result +A type \tcode{E} that is a specialization of \tcode{extents} +such that \tcode{E::rank() == Rank \&\& E::rank() == E::rank_dynamic()} is \tcode{true}, and +\tcode{E::index_type} denotes \tcode{IndexType}. +\end{itemdescr} + +\rSec3[mdspan.layout]{Layout mapping} + +\rSec4[mdspan.layout.general]{General} \pnum -\effects -Equivalent to: +In \ref{mdspan.layout.reqmts} and \ref{mdspan.layout.policy.reqmts}: + +\begin{itemize} +\item +\tcode{M} denotes a layout mapping class. + +\item +\tcode{m} denotes a (possibly const) value of type \tcode{M}. + +\item +\tcode{i} and \tcode{j} are packs of (possibly const) integers +that are multidimensional indices in \tcode{m.extents()}\iref{mdspan.overview}. +\begin{note} +The type of each element of the packs can be a different integer type. +\end{note} + +\item +\tcode{r} is a (possibly const) rank index of \tcode{typename M::extents_type}. + +\item +$\tcode{d}_r$ is a pack of (possibly const) integers +for which \tcode{sizeof...($\tcode{d}_r$) == M::extents_type::rank()} is \tcode{true}, +the $r^\text{th}$ element is equal to 1, and +all other elements are equal to 0. +\end{itemize} + +\pnum +In \ref{mdspan.layout.reqmts} through \ref{mdspan.layout.stride}: +\begin{itemize} +\item +Let \exposid{is-mapping-of} be the exposition-only variable template defined as follows: \begin{codeblock} -return {data() + offset, count == dynamic_extent ? size() - offset : count}; +template +constexpr bool @\exposid{is-mapping-of}@ = // \expos + is_same_v, Mapping>; \end{codeblock} -\end{itemdescr} +\item +Let \exposid{is-layout-left-padded-mapping-of} be +the exposition-only variable template defined as follows: +\begin{codeblock} +template +constexpr bool @\exposid{is-layout-left-padded-mapping-of}@ = @\seebelow@; // \expos +\end{codeblock} +where \tcode{\exposid{is-layout-left-padded-mapping-of}} is \tcode{true} +if and only if \tcode{Mapping} denotes +a specialization of \tcode{layout_left_padded::mapping} +for some value \tcode{S} of type \tcode{size_t}. +\item +Let \exposid{is-layout-right-padded-mapping-of} be +the exposition-only variable template defined as follows: +\begin{codeblock} +template +constexpr bool @\exposid{is-layout-right-padded-mapping-of}@ = @\seebelow@; // \expos +\end{codeblock} +where \tcode{\exposid{is-layout-right-padded-mapping-of}} is \tcode{true} +if and only if \tcode{Mapping} denotes +a specialization of \tcode{layout_right_padded::mapping} +for some value \tcode{S} of type \tcode{size_t}. +\item +For nonnegative integers $x$ and $y$, +let $\exposid{LEAST-MULTIPLE-AT-LEAST}(x, y)$ denote +\begin{itemize} +\item +$y$ if $x$ is zero, +\item +otherwise, the least multiple of $x$ that is greater than or equal to $y$. +\end{itemize} +\end{itemize} -\rSec4[span.obs]{Observers} +\rSec4[mdspan.layout.reqmts]{Requirements} + +\pnum +A type \tcode{M} meets the \defn{layout mapping} requirements if + +\begin{itemize} +\item +\tcode{M} models \libconcept{copyable} and \libconcept{equality_comparable}, +\item +\tcode{is_nothrow_move_constructible_v} is \tcode{true}, +\item +\tcode{is_nothrow_move_assignable_v} is \tcode{true}, +\item +\tcode{is_nothrow_swappable_v} is \tcode{true}, and +\item +the following types and expressions are well-formed and +have the specified semantics. +\end{itemize} -\indexlibrarymember{span}{size}% \begin{itemdecl} -constexpr size_type size() const noexcept; +typename M::extents_type \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \exposid{size_};} +\result +A type that is a specialization of \tcode{extents}. \end{itemdescr} -\indexlibrarymember{span}{size_bytes}% \begin{itemdecl} -constexpr size_type size_bytes() const noexcept; +typename M::index_type \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return size() * sizeof(element_type);} +\result +\tcode{typename M::extents_type::index_type}. \end{itemdescr} -\indexlibrarymember{span}{empty}% \begin{itemdecl} -[[nodiscard]] constexpr bool empty() const noexcept; +typename M::rank_type \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return size() == 0;} +\result +\tcode{typename M::extents_type::rank_type}. \end{itemdescr} -\rSec4[span.elem]{Element access} - -\indexlibrary{\idxcode{operator[]}!\idxcode{span}}% \begin{itemdecl} -constexpr reference operator[](size_type idx) const; +typename M::layout_type \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{idx < size()} is \tcode{true}. - -\pnum -\effects -Equivalent to: \tcode{return *(data() + idx);} +\result +A type \tcode{MP} that meets +the layout mapping policy requirements\iref{mdspan.layout.policy.reqmts} and +for which \tcode{\exposid{is-mapping-of}} is \tcode{true}. \end{itemdescr} -\indexlibrarymember{span}{at}% \begin{itemdecl} -constexpr reference at(size_type idx) const; +m.extents() \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{*(data() + idx)}. - -\pnum -\throws -\tcode{out_of_range} if \tcode{idx >= size()} is \tcode{true}. +\result +\tcode{const typename M::extents_type\&} \end{itemdescr} -\indexlibrarymember{span}{front}% \begin{itemdecl} -constexpr reference front() const; +m(i...) \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{empty()} is \tcode{false}. +\result +\tcode{typename M::index_type} \pnum -\effects -Equivalent to: \tcode{return *data();} +\returns +A nonnegative integer +less than \tcode{numeric_limits::max()} and +less than or equal to \tcode{numeric_limits::max()}. \end{itemdescr} -\indexlibrarymember{span}{back}% \begin{itemdecl} -constexpr reference back() const; +m(i...) == m(static_cast(i)...) \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{empty()} is \tcode{false}. +\result +\tcode{bool} \pnum -\effects -Equivalent to: \tcode{return *(data() + (size() - 1));} +\returns +\tcode{true} \end{itemdescr} -\indexlibrarymember{span}{data}% \begin{itemdecl} -constexpr pointer data() const noexcept; +m.required_span_size() \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \exposid{data_};} -\end{itemdescr} +\result +\tcode{typename M::index_type} -\rSec4[span.iterators]{Iterator support} +\pnum +\returns +If the size of the multidimensional index space \tcode{m.extents()} is 0, +then \tcode{0}, +else \tcode{1} plus the maximum value of \tcode{m(i...)} for all \tcode{i}. +\end{itemdescr} -\indexlibrarymember{iterator}{span}% \begin{itemdecl} -using iterator = @\impdefx{type of \tcode{span::iterator}}@; +m.is_unique() \end{itemdecl} \begin{itemdescr} \pnum -The type -models \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}, -meets the \oldconcept{RandomAccessIterator} -requirements\iref{random.access.iterators}, -and -meets the requirements for -constexpr iterators\iref{iterator.requirements.general}, -whose value type is \tcode{value_type} and -whose reference type is \tcode{reference}. +\result +\tcode{bool} \pnum -All requirements on container iterators\iref{container.reqmts} apply to -\tcode{span::iterator} as well. +\returns +\tcode{true} only if +for every \tcode{i} and \tcode{j} where \tcode{(i != j || ...)} is \tcode{true}, +\tcode{m(i...) != m(j...)} is \tcode{true}. +\begin{note} +A mapping can return \tcode{false} even if the condition is met. +For certain layouts, it is possibly not feasible to determine efficiently +whether the layout is unique. +\end{note} \end{itemdescr} -\indexlibrarymember{span}{begin}% \begin{itemdecl} -constexpr iterator begin() const noexcept; +m.is_exhaustive() \end{itemdecl} \begin{itemdescr} +\pnum +\result +\tcode{bool} + \pnum \returns -An iterator referring to the first element in the span. -If \tcode{empty()} is \tcode{true}, then it returns the -same value as \tcode{end()}. +\tcode{true} only if +for all $k$ in the range $[0, \tcode{m.required_span_size()})$ +there exists an \tcode{i} such that \tcode{m(i...)} equals $k$. +\begin{note} +A mapping can return \tcode{false} even if the condition is met. +For certain layouts, it is possibly not feasible to determine efficiently +whether the layout is exhaustive. +\end{note} \end{itemdescr} -\indexlibrarymember{span}{end}% \begin{itemdecl} -constexpr iterator end() const noexcept; +m.is_strided() \end{itemdecl} \begin{itemdescr} +\pnum +\result +\tcode{bool} + \pnum \returns -An iterator which is the past-the-end value. +\tcode{true} only if +for every rank index $r$ of \tcode{m.extents()} there exists an integer $s_r$ +such that, +for all \tcode{i} where $(\tcode{i}+d_r)$ is +a multidimensional index in \tcode{m.extents()}\iref{mdspan.overview}, +\tcode{m((i + $d_r$)...) - m(i...)} equals $s_r$. +\begin{note} +This implies that for a strided layout +$m(i_0, \dotsc, i_k) = m(0, \dotsc, 0) + i_0 \times s_0 + \dotsb + i_k \times s_k$. +\end{note} +\begin{note} +A mapping can return \tcode{false} even if the condition is met. +For certain layouts, it is possibly not feasible to determine efficiently +whether the layout is strided. +\end{note} \end{itemdescr} -\indexlibrarymember{span}{rbegin}% \begin{itemdecl} -constexpr reverse_iterator rbegin() const noexcept; +m.stride(r) \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return reverse_iterator(end());} -\end{itemdescr} +\expects +\tcode{m.is_strided()} is \tcode{true}. -\indexlibrarymember{span}{rend}% -\begin{itemdecl} -constexpr reverse_iterator rend() const noexcept; -\end{itemdecl} +\pnum +\result +\tcode{typename M::index_type} -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return reverse_iterator(begin());} -\end{itemdescr} +\returns +$s_r$ as defined in \tcode{m.is_strided()} above. -\rSec3[span.objectrep]{Views of object representation} +\pnum +\begin{note} +It is not required for \tcode{m.stride(r)} to be well-formed +if \tcode{m.extents().rank()} is zero, +even if \tcode{m.is_always_strided()} is \tcode{true}. +\end{note} +\end{itemdescr} -\indexlibraryglobal{as_bytes}% \begin{itemdecl} -template - span - as_bytes(span s) noexcept; +M::is_always_unique() \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return R\{reinterpret_cast(s.data()), s.size_bytes()\};} -where \tcode{R} is the return type. +\result +A constant expression\iref{expr.const} of type \tcode{bool}. + +\pnum +\returns +\tcode{true} only if \tcode{m.is_unique()} is \tcode{true} +for all possible objects \tcode{m} of type \tcode{M}. +\begin{note} +A mapping can return \tcode{false} even if the above condition is met. +For certain layout mappings, it is possibly not feasible to determine +whether every instance is unique. +\end{note} \end{itemdescr} -\indexlibraryglobal{as_writable_bytes}% \begin{itemdecl} -template - span - as_writable_bytes(span s) noexcept; +M::is_always_exhaustive() \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_const_v} is \tcode{false}. +\result +A constant expression\iref{expr.const} of type \tcode{bool}. \pnum -\effects -Equivalent to: \tcode{return R\{reinterpret_cast(s.data()), s.size_bytes()\};} -where \tcode{R} is the return type. +\returns +\tcode{true} only if \tcode{m.is_exhaustive()} is \tcode{true} +for all possible objects \tcode{m} of type \tcode{M}. +\begin{note} +A mapping can return \tcode{false} even if the above condition is met. +For certain layout mappings, it is possibly not feasible to determine +whether every instance is exhaustive. +\end{note} \end{itemdescr} -\rSec2[views.multidim]{Multidimensional access} - -\rSec3[mdspan.overview]{Overview} - -\pnum -A \defnadj{multidimensional}{index space} is -a Cartesian product of integer intervals. -Each interval can be represented by a half-open range $[L_i, U_i)$, -where $L_i$ and $U_i$ are the lower and upper bounds of -the $i^\text{th}$ dimension. -The \defn{rank} of a multidimensional index space is -the number of intervals it represents. -The \defn{size of a multidimensional index space} is -the product of $U_i - L_i$ for each dimension $i$ -if its rank is greater than 0, and 1 otherwise. +\begin{itemdecl} +M::is_always_strided() +\end{itemdecl} +\begin{itemdescr} \pnum -An integer $r$ is a \defn{rank index} of an index space $S$ -if $r$ is in the range $[0, \text{rank of $S$})$. +\result +A constant expression\iref{expr.const} of type \tcode{bool}. \pnum -A pack of integers \tcode{idx} is -a \defnadj{multidimensional}{index} in a multidimensional index space $S$ -(or representation thereof) if both of the following are true: -\begin{itemize} -\item -\tcode{sizeof...(idx)} is equal to the rank of $S$, and -\item -for every rank index $i$ of $S$, -the $i^\text{th}$ value of \tcode{idx} is an integer -in the interval $[L_i, U_i)$ of $S$. -\end{itemize} - -\rSec3[mdspan.syn]{Header \tcode{} synopsis} - -\indexheader{mdspan}% -\begin{codeblock} -// all freestanding -namespace std { - // \ref{mdspan.extents}, class template \tcode{extents} - template - class extents; - - // \ref{mdspan.extents.dextents}, alias template \tcode{dextents} - template - using dextents = @\seebelow@; - - // \ref{mdspan.layout}, layout mapping - struct layout_left; - struct layout_right; - struct layout_stride; - - // \ref{mdspan.accessor.default}, class template \tcode{default_accessor} - template - class default_accessor; - - // \ref{mdspan.mdspan}, class template \tcode{mdspan} - template> - class mdspan; - - // \ref{mdspan.submdspan}, \tcode{submdspan} creation - template - struct strided_slice; - - template - struct submdspan_mapping_result; - - struct full_extent_t { explicit full_extent_t() = default; }; - inline constexpr full_extent_t full_extent{}; - - template - constexpr auto submdspan_extents(const extents&, SliceSpecifiers...); - - // \ref{mdspan.submdspan.submdspan}, \tcode{submdspan} function template - template - constexpr auto submdspan( - const mdspan& src, - SliceSpecifiers... slices) -> @\seebelow@; - - template - concept @\defexposconcept{integral-constant-like}@ = // \expos - is_integral_v && - !is_same_v> && - @\libconcept{convertible_to}@ && - @\libconcept{equality_comparable_with}@ && - bool_constant::value && - bool_constant(T()) == T::value>::value; - - template - concept @\defexposconcept{index-pair-like}@ = // \expos - @\exposconcept{pair-like}@ && - @\libconcept{convertible_to}@, IndexType> && - @\libconcept{convertible_to}@, IndexType>; -} -\end{codeblock} +\returns +\tcode{true} only if \tcode{m.is_strided()} is \tcode{true} +for all possible objects \tcode{m} of type \tcode{M}. +\begin{note} +A mapping can return \tcode{false} even if the above condition is met. +For certain layout mappings, it is possibly not feasible to determine +whether every instance is strided. +\end{note} +\end{itemdescr} -\rSec3[mdspan.extents]{Class template \tcode{extents}} +\rSec4[mdspan.layout.policy.reqmts]{Layout mapping policy requirements} -\rSec4[mdspan.extents.overview]{Overview} +\pnum +A type \tcode{MP} meets the \defn{layout mapping policy} requirements +if for a type \tcode{E} that is a specialization of \tcode{extents}, +\tcode{MP::mapping} is valid and denotes a type \tcode{X} +that meets the layout mapping requirements\iref{mdspan.layout.reqmts}, and +for which the \grammarterm{qualified-id} \tcode{X::layout_type} is valid and +denotes the type \tcode{MP} and +the \grammarterm{qualified-id} \tcode{X::extents_type} denotes \tcode{E}. -The class template \tcode{extents} represents -a multidimensional index space of rank equal to \tcode{sizeof...(Extents)}. -In subclause \iref{views}, -\tcode{extents} is used synonymously with multidimensional index space. +\rSec4[mdspan.layout.policy.overview]{Layout mapping policies} \begin{codeblock} namespace std { - template - class @\libglobal{extents}@ { - public: - using index_type = IndexType; - using size_type = make_unsigned_t; - using rank_type = size_t; - - // \ref{mdspan.extents.obs}, observers of the multidimensional index space - static constexpr rank_type rank() noexcept { return sizeof...(Extents); } - static constexpr rank_type rank_dynamic() noexcept { return @\exposid{dynamic-index}@(rank()); } - static constexpr size_t static_extent(rank_type) noexcept; - constexpr index_type extent(rank_type) const noexcept; - - // \ref{mdspan.extents.cons}, constructors - constexpr extents() noexcept = default; - - template - constexpr explicit(@\seebelow@) - extents(const extents&) noexcept; - template - constexpr explicit extents(OtherIndexTypes...) noexcept; - template - constexpr explicit(N != rank_dynamic()) - extents(span) noexcept; - template - constexpr explicit(N != rank_dynamic()) - extents(const array&) noexcept; - - // \ref{mdspan.extents.cmp}, comparison operators - template - friend constexpr bool operator==(const extents&, - const extents&) noexcept; - - // \ref{mdspan.extents.expo}, exposition-only helpers - constexpr size_t @\exposid{fwd-prod-of-extents}@(rank_type) const noexcept; // \expos - constexpr size_t @\exposid{rev-prod-of-extents}@(rank_type) const noexcept; // \expos - template - static constexpr auto @\exposid{index-cast}@(OtherIndexType&&) noexcept; // \expos - - private: - static constexpr rank_type @\exposid{dynamic-index}@(rank_type) noexcept; // \expos - static constexpr rank_type @\exposid{dynamic-index-inv}@(rank_type) noexcept; // \expos - array @\exposid{dynamic-extents}@{}; // \expos + struct layout_left { + template + class mapping; + }; + struct layout_right { + template + class mapping; + }; + struct layout_stride { + template + class mapping; }; - template - explicit extents(Integrals...) - -> @\seebelow@; + template + struct layout_left_padded { + template class mapping; + }; + template + struct layout_right_padded { + template class mapping; + }; } \end{codeblock} \pnum -\mandates -\begin{itemize} -\item -\tcode{IndexType} is a signed or unsigned integer type, and -\item -each element of \tcode{Extents} is either equal to \tcode{dynamic_extent}, or -is representable as a value of type \tcode{IndexType}. -\end{itemize} +Each of \tcode{layout_left}, \tcode{layout_right}, and \tcode{layout_stride}, +as well as each specialization of +\tcode{layout_left_padded} and \tcode{layout_right_padded}, +meets the layout mapping policy requirements and is a trivially copyable type. +Furthermore, +\tcode{is_trivially_default_constructible_v} is \tcode{true} +for any such type \tcode{T}. -\pnum -Each specialization of \tcode{extents} models \libconcept{regular} and -is trivially copyable. +\rSec4[mdspan.layout.left]{Class template \tcode{layout_left::mapping}} -\pnum -Let $E_r$ be the $r^\text{th}$ element of \tcode{Extents}. -$E_r$ is a \defnadj{dynamic}{extent} if it is equal to \tcode{dynamic_extent}, -otherwise $E_r$ is a \defnadj{static}{extent}. -Let $D_r$ be the value of \tcode{\exposid{dynamic-extents}[\exposid{dynamic-index}($r$)]} -if $E_r$ is a dynamic extent, -otherwise $E_r$. +\rSec5[mdspan.layout.left.overview]{Overview} \pnum -The $r^\text{th}$ interval of the multidimensional index space -represented by an \tcode{extents} object is $[0, D_r)$. +\tcode{layout_left} provides a layout mapping +where the leftmost extent has stride 1, and +strides increase left-to-right as the product of extents. -\rSec4[mdspan.extents.expo]{Exposition-only helpers} +\begin{codeblock} +namespace std { + template + class layout_left::mapping { + public: + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_left; -\begin{itemdecl} -static constexpr rank_type @\exposid{dynamic-index}@(rank_type i) noexcept; -\end{itemdecl} + // \ref{mdspan.layout.left.cons}, constructors + constexpr mapping() noexcept = default; + constexpr mapping(const mapping&) noexcept = default; + constexpr mapping(const extents_type&) noexcept; + template + constexpr explicit(!is_convertible_v) + mapping(const mapping&) noexcept; + template + constexpr explicit(!is_convertible_v) + mapping(const layout_right::mapping&) noexcept; + template + constexpr explicit(!is_convertible_v) + mapping(const LayoutLeftPaddedMapping&) noexcept; + template + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping&); -\begin{itemdescr} -\pnum -\expects -\tcode{i <= rank()} is \tcode{true}. + constexpr mapping& operator=(const mapping&) noexcept = default; -\pnum -\returns -The number of $E_r$ with $r < \tcode{i}$ for which $E_r$ is a dynamic extent. -\end{itemdescr} + // \ref{mdspan.layout.left.obs}, observers + constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } -\begin{itemdecl} -static constexpr rank_type @\exposid{dynamic-index-inv}@(rank_type i) noexcept; -\end{itemdecl} + constexpr index_type required_span_size() const noexcept; -\begin{itemdescr} -\pnum -\expects -\tcode{i < rank_dynamic()} is \tcode{true}. + template + constexpr index_type operator()(Indices...) const noexcept; -\pnum -\returns -The minimum value of $r$ -such that \tcode{\exposid{dynamic-index}($r$ + 1) == i + 1} is \tcode{true}. -\end{itemdescr} + static constexpr bool is_always_unique() noexcept { return true; } + static constexpr bool is_always_exhaustive() noexcept { return true; } + static constexpr bool is_always_strided() noexcept { return true; } -\begin{itemdecl} -constexpr size_t @\exposid{fwd-prod-of-extents}@(rank_type i) const noexcept; -\end{itemdecl} + static constexpr bool is_unique() noexcept { return true; } + static constexpr bool is_exhaustive() noexcept { return true; } + static constexpr bool is_strided() noexcept { return true; } -\begin{itemdescr} -\pnum -\expects -\tcode{i <= rank()} is \tcode{true}. + constexpr index_type stride(rank_type) const noexcept; -\pnum -\returns -If \tcode{i > 0} is \tcode{true}, -the product of \tcode{extent($k$)} for all $k$ in the range $[0, \tcode{i})$, -otherwise \tcode{1}. -\end{itemdescr} + template + friend constexpr bool operator==(const mapping&, const mapping&) noexcept; -\begin{itemdecl} -constexpr size_t @\exposid{rev-prod-of-extents}@(rank_type i) const noexcept; -\end{itemdecl} + private: + extents_type @\exposid{extents_}@{}; // \expos + + // \ref{mdspan.sub.map}, \tcode{submdspan} mapping specialization + template + constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const // \expos + -> @\seebelow@; + + template + friend constexpr auto submdspan_mapping( + const mapping& src, SliceSpecifiers... slices) { + return src.@\exposid{submdspan-mapping-impl}@(slices...); + } + }; +} +\end{codeblock} -\begin{itemdescr} \pnum -\expects -\tcode{i < rank()} is \tcode{true}. +If \tcode{Extents} is not a specialization of \tcode{extents}, +then the program is ill-formed. \pnum -\returns -If \tcode{i + 1 < rank()} is \tcode{true}, -the product of \tcode{extent($k$)} -for all $k$ in the range $[\tcode{i + 1}, \tcode{rank()})$, -otherwise \tcode{1}. -\end{itemdescr} +\tcode{layout_left::mapping} is a trivially copyable type +that models \libconcept{regular} for each \tcode{E}. + +\pnum +\mandates +If \tcode{Extents::rank_dynamic() == 0} is \tcode{true}, +then the size of the multidimensional index space \tcode{Extents()} +is representable as a value of type \tcode{typename Extents::index_type}. + +\rSec5[mdspan.layout.left.cons]{Constructors} +\indexlibraryctor{layout_left::mapping}% \begin{itemdecl} -template - static constexpr auto @\exposid{index-cast}@(OtherIndexType&& i) noexcept; +constexpr mapping(const extents_type& e) noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\expects +The size of the multidimensional index space \tcode{e} +is representable as a value of type \tcode{index_type}\iref{basic.fundamental}. + \pnum \effects -\begin{itemize} -\item -If \tcode{OtherIndexType} is an integral type other than \tcode{bool}, -then equivalent to \tcode{return i;}, -\item -otherwise, equivalent to \tcode{return static_cast(i);}. -\end{itemize} -\begin{note} -This function will always return an integral type other than \tcode{bool}. -Since this function's call sites are constrained on -convertibility of \tcode{OtherIndexType} to \tcode{index_type}, -integer-class types can use the \tcode{static_cast} branch -without loss of precision. -\end{note} +Direct-non-list-initializes \exposid{extents_} with \tcode{e}. \end{itemdescr} -\rSec4[mdspan.extents.cons]{Constructors} - -\indexlibraryctor{extents}% +\indexlibraryctor{layout_left::mapping}% \begin{itemdecl} -template - constexpr explicit(@\seebelow@) - extents(const extents& other) noexcept; +template + constexpr explicit(!is_convertible_v) + mapping(const mapping& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\begin{itemize} -\item -\tcode{sizeof...(OtherExtents) == rank()} is \tcode{true}. -\item -\tcode{((OtherExtents == dynamic_extent || Extents == dynamic_extent || OtherExtents ==\newline Extents) \&\& ...)} is \tcode{true}. -\end{itemize} +\tcode{is_constructible_v} is \tcode{true}. \pnum \expects -\begin{itemize} -\item -\tcode{other.extent($r$)} equals $E_r$ -for each $r$ for which $E_r$ is a static extent, and -\item -either -\begin{itemize} -\item -\tcode{sizeof...(OtherExtents)} is zero, or -\item -\tcode{other.extent($r$)} is representable as -a value of type \tcode{index_type} for every rank index $r$ of \tcode{other}. -\end{itemize} -\end{itemize} - -\pnum -\ensures -\tcode{*this == other} is \tcode{true}. +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}\iref{basic.fundamental}. \pnum -\remarks -The expression inside \tcode{explicit} is equivalent to: -\begin{codeblock} -(((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ... ) || -(numeric_limits::max() < numeric_limits::max()) -\end{codeblock} +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. \end{itemdescr} -\indexlibraryctor{extents}% +\indexlibraryctor{layout_left::mapping}% \begin{itemdecl} -template - constexpr explicit extents(OtherIndexTypes... exts) noexcept; +template + constexpr explicit(!is_convertible_v) + mapping(const layout_right::mapping& other) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{N} be \tcode{sizeof...(OtherIndexTypes)}, -and let \tcode{exts_arr} be -\tcode{array\{static_cast<\\index_type>(std::move(exts))...\}}. - \pnum \constraints \begin{itemize} \item -\tcode{(is_convertible_v \&\& ...)} is \tcode{true}, -\item -\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}, and +\tcode{extents_type::rank() <= 1} is \tcode{true}, and \item -\tcode{N == rank_dynamic() || N == rank()} is \tcode{true}. -\begin{note} -One can construct \tcode{extents} from just dynamic extents, -which are all the values getting stored, or -from all the extents with a precondition. -\end{note} +\tcode{is_constructible_v} is \tcode{true}. \end{itemize} -\pnum -\expects -\begin{itemize} -\item -If \tcode{N != rank_dynamic()} is \tcode{true}, -\tcode{exts_arr[$r$]} equals $E_r$ -for each $r$ for which $E_r$ is a static extent, and -\item -either -\begin{itemize} -\item -\tcode{sizeof...(exts) == 0} is \tcode{true}, or -\item -each element of \tcode{exts} is representable -as a nonnegative value of type \tcode{index_type}. -\end{itemize} -\end{itemize} +\pnum +\expects +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}\iref{basic.fundamental}. \pnum -\ensures -\tcode{*this == extents(exts_arr)} is \tcode{true}. +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. \end{itemdescr} -\indexlibraryctor{extents}% +\indexlibraryctor{layout_left::mapping}% \begin{itemdecl} -template - constexpr explicit(N != rank_dynamic()) - extents(span exts) noexcept; -template - constexpr explicit(N != rank_dynamic()) - extents(const array& exts) noexcept; +template + constexpr explicit(!is_convertible_v) + mapping(const LayoutLeftPaddedMapping&) noexcept; \end{itemdecl} \begin{itemdescr} @@ -19390,504 +22092,521 @@ \constraints \begin{itemize} \item -\tcode{is_convertible_v} is \tcode{true}, -\item -\tcode{is_nothrow_constructible_v} is \tcode{true}, and +\tcode{\exposid{is-layout-left-padded-mapping-of}} is \tcode{true}. \item -\tcode{N == rank_dynamic() || N == rank()} is \tcode{true}. +\tcode{is_constructible_v}\newline is \tcode{true}. \end{itemize} \pnum -\expects +\mandates +If \begin{itemize} \item -If \tcode{N != rank_dynamic()} is \tcode{true}, -\tcode{exts[$r$]} equals $E_r$ for each $r$ for which $E_r$ is a static extent, and -\item -either -\begin{itemize} +\tcode{Extents::rank()} is greater than one, \item -\tcode{N} is zero, or +\tcode{Extents::static_extent(0)} does not equal \tcode{dynamic_extent}, and \item -\tcode{exts[$r$]} is representable -as a nonnegative value of type \tcode{index_type} for every rank index $r$. -\end{itemize} +\tcode{LayoutLeftPaddedMapping::\exposid{static-padding-stride}} +does not equal \tcode{dynamic_extent}, \end{itemize} +then \tcode{Extents::static_extent(0)} equals +\tcode{LayoutLeftPaddedMapping::\exposid{static-padding-stride}}. \pnum -\effects +\expects \begin{itemize} \item -If \tcode{N} equals \tcode{dynamic_rank()}, -for all $d$ in the range $[0, \tcode{rank_dynamic()})$, -direct-non-list-initializes \tcode{\exposidnc{dynamic-extents}[$d$]} -with \tcode{as_const(exts[$d$])}. +If \tcode{extents_type::rank() > 1} is \tcode{true}, +then \tcode{other.stride(1)} equals \tcode{other.extents(0)}. \item -Otherwise, for all $d$ in the range $[0, \tcode{rank_dynamic()})$, -direct-non-list-initializes \exposidnc{dynamic-ex\-tents}\tcode{[$d$]} -with \tcode{as_const(exts[\exposidnc{dynamic-index-inv}($d$)])}. +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. \end{itemize} + +\pnum +\effects +Direct-non-list-initializes \tcode{extents_} with \tcode{other.extents()}. \end{itemdescr} -\indexlibraryctor{extents}% +\indexlibraryctor{layout_left::mapping}% \begin{itemdecl} -template - explicit extents(Integrals...) -> @\seebelow@; +template + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping& other); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{(is_convertible_v \&\& ...)} is \tcode{true}. +\tcode{is_constructible_v} is \tcode{true}. \pnum -\remarks -The deduced type is \tcode{dextents}. +\expects +\begin{itemize} +\item +If \tcode{extents_type::rank() > 0} is \tcode{true}, +then for all $r$ in the range $[0, \tcode{extents_type::rank()})$, +\tcode{other.stride($r$)} equals +\tcode{other.extents().\exposid{fwd-prod-of-extents}($r$)}, and +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}\iref{basic.fundamental}. +\end{itemize} + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. \end{itemdescr} -\rSec4[mdspan.extents.obs]{Observers of the multidimensional index space} +\rSec5[mdspan.layout.left.obs]{Observers} -\indexlibrarymember{static_extent}{extents}% +\indexlibrarymember{required_span_size}{layout_left::mapping}% \begin{itemdecl} -static constexpr size_t static_extent(rank_type i) noexcept; +constexpr index_type required_span_size() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{i < rank()} is \tcode{true}. - \pnum \returns -$E_\tcode{i}$. +\tcode{extents().\exposid{fwd-prod-of-extents}(extents_type::rank())}. \end{itemdescr} -\indexlibrarymember{extent}{extents}% +\indexlibrarymember{operator()}{layout_left::mapping}% \begin{itemdecl} -constexpr index_type extent(rank_type i) const noexcept; +template + constexpr index_type operator()(Indices... i) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{sizeof...(Indices) == extents_type::rank()} is \tcode{true}, +\item +\tcode{(is_convertible_v \&\& ...)} is \tcode{true}, and +\item +\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}. +\end{itemize} + \pnum \expects -\tcode{i < rank()} is \tcode{true}. +\tcode{extents_type::\exposid{index-cast}(i)} is +a multidimensional index in \exposid{extents_}\iref{mdspan.overview}. \pnum -\returns -$D_\tcode{i}$. +\effects +Let \tcode{P} be a parameter pack such that +\begin{codeblock} +is_same_v, index_sequence> +\end{codeblock} +is \tcode{true}. +Equivalent to: +\begin{codeblock} +return ((static_cast(i) * stride(P)) + ... + 0); +\end{codeblock} \end{itemdescr} -\rSec4[mdspan.extents.cmp]{Comparison operators} - -\indexlibrarymember{operator==}{extents}% +\indexlibrarymember{stride}{layout_left::mapping}% \begin{itemdecl} -template - friend constexpr bool operator==(const extents& lhs, - const extents& rhs) noexcept; +constexpr index_type stride(rank_type i) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{extents_type::rank() > 0} is \tcode{true}. + +\pnum +\expects +\tcode{i < extents_type::rank()} is \tcode{true}. + \pnum \returns -\tcode{true} if \tcode{lhs.rank()} equals \tcode{rhs.rank()} and -if \tcode{lhs.extent(r)} equals \tcode{rhs.extent(r)} -for every rank index \tcode{r} of \tcode{rhs}, -otherwise \tcode{false}. +\tcode{extents().\exposid{fwd-prod-of-extents}(i)}. \end{itemdescr} -\rSec4[mdspan.extents.dextents]{Alias template \tcode{dextents}} - -\indexlibraryglobal{dextents}% +\indexlibrarymember{operator==}{layout_left::mapping}% \begin{itemdecl} -template - using dextents = @\seebelow@; +template + friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\result -A type \tcode{E} that is a specialization of \tcode{extents} -such that \tcode{E::rank() == Rank \&\& E::rank() == E::rank_dynamic()} is \tcode{true}, and -\tcode{E::index_type} denotes \tcode{IndexType}. -\end{itemdescr} - -\rSec3[mdspan.layout]{Layout mapping} - -\rSec4[mdspan.layout.general]{General} +\constraints +\tcode{extents_type::rank() == OtherExtents::rank()} is \tcode{true}. \pnum -In subclauses \ref{mdspan.layout.reqmts} and \ref{mdspan.layout.policy.reqmts}: - -\begin{itemize} -\item -\tcode{M} denotes a layout mapping class. - -\item -\tcode{m} denotes a (possibly const) value of type \tcode{M}. - -\item -\tcode{i} and \tcode{j} are packs of (possibly const) integers -that are multidimensional indices in \tcode{m.extents()}\iref{mdspan.overview}. -\begin{note} -The type of each element of the packs can be a different integer type. -\end{note} +\effects +Equivalent to: \tcode{return x.extents() == y.extents();} +\end{itemdescr} -\item -\tcode{r} is a (possibly const) rank index of \tcode{typename M::extents_type}. +\rSec4[mdspan.layout.right]{Class template \tcode{layout_right::mapping}} -\item -$\tcode{d}_r$ is a pack of (possibly const) integers -for which \tcode{sizeof...($\tcode{d}_r$) == M::extents_type::rank()} is \tcode{true}, -the $r^\text{th}$ element is equal to 1, and -all other elements are equal to 0. -\end{itemize} +\rSec5[mdspan.layout.right.overview]{Overview} \pnum -In subclauses \ref{mdspan.layout.reqmts} through \ref{mdspan.layout.stride}, -let \exposid{is-mapping-of} be the exposition-only variable template defined as follows: -\begin{codeblock} -template -constexpr bool @\exposid{is-mapping-of}@ = // \expos - is_same_v, Mapping>; -\end{codeblock} +\tcode{layout_right} provides a layout mapping +where the rightmost extent is stride 1, and +strides increase right-to-left as the product of extents. -\rSec4[mdspan.layout.reqmts]{Requirements} +\begin{codeblock} +namespace std { + template + class layout_right::mapping { + public: + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_right; -\pnum -A type \tcode{M} meets the \defn{layout mapping} requirements if + // \ref{mdspan.layout.right.cons}, constructors + constexpr mapping() noexcept = default; + constexpr mapping(const mapping&) noexcept = default; + constexpr mapping(const extents_type&) noexcept; + template + constexpr explicit(!is_convertible_v) + mapping(const mapping&) noexcept; + template + constexpr explicit(!is_convertible_v) + mapping(const layout_left::mapping&) noexcept; + template + constexpr explicit(!is_convertible_v) + mapping(const LayoutRightPaddedMapping&) noexcept; + template + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping&) noexcept; -\begin{itemize} -\item -\tcode{M} models \libconcept{copyable} and \libconcept{equality_comparable}, -\item -\tcode{is_nothrow_move_constructible_v} is \tcode{true}, -\item -\tcode{is_nothrow_move_assignable_v} is \tcode{true}, -\item -\tcode{is_nothrow_swappable_v} is \tcode{true}, and -\item -the following types and expressions are well-formed and -have the specified semantics. -\end{itemize} + constexpr mapping& operator=(const mapping&) noexcept = default; -\begin{itemdecl} -typename M::extents_type -\end{itemdecl} + // \ref{mdspan.layout.right.obs}, observers + constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } -\begin{itemdescr} -\pnum -\result -A type that is a specialization of \tcode{extents}. -\end{itemdescr} + constexpr index_type required_span_size() const noexcept; -\begin{itemdecl} -typename M::index_type -\end{itemdecl} + template + constexpr index_type operator()(Indices...) const noexcept; -\begin{itemdescr} -\pnum -\result -\tcode{typename M::extents_type::index_type}. -\end{itemdescr} + static constexpr bool is_always_unique() noexcept { return true; } + static constexpr bool is_always_exhaustive() noexcept { return true; } + static constexpr bool is_always_strided() noexcept { return true; } -\begin{itemdecl} -typename M::rank_type -\end{itemdecl} + static constexpr bool is_unique() noexcept { return true; } + static constexpr bool is_exhaustive() noexcept { return true; } + static constexpr bool is_strided() noexcept { return true; } -\begin{itemdescr} -\pnum -\result -\tcode{typename M::extents_type::rank_type}. -\end{itemdescr} + constexpr index_type stride(rank_type) const noexcept; -\begin{itemdecl} -typename M::layout_type -\end{itemdecl} + template + friend constexpr bool operator==(const mapping&, const mapping&) noexcept; -\begin{itemdescr} -\pnum -\result -A type \tcode{MP} that meets -the layout mapping policy requirements\iref{mdspan.layout.policy.reqmts} and -for which \tcode{\exposid{is-mapping-of}} is \tcode{true}. -\end{itemdescr} + private: + extents_type @\exposid{extents_}@{}; // \expos -\begin{itemdecl} -m.extents() -\end{itemdecl} + // \ref{mdspan.sub.map}, \tcode{submdspan} mapping specialization + template + constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const // \expos + -> @\seebelow@; -\begin{itemdescr} -\pnum -\result -\tcode{const typename M::extents_type\&} -\end{itemdescr} + template + friend constexpr auto submdspan_mapping( + const mapping& src, SliceSpecifiers... slices) { + return src.@\exposid{submdspan-mapping-impl}@(slices...); + } + }; +} +\end{codeblock} -\begin{itemdecl} -m(i...) -\end{itemdecl} +\pnum +If \tcode{Extents} is not a specialization of \tcode{extents}, +then the program is ill-formed. -\begin{itemdescr} \pnum -\result -\tcode{typename M::index_type} +\tcode{layout_right::mapping} is a trivially copyable type +that models \libconcept{regular} for each \tcode{E}. \pnum -\returns -A nonnegative integer -less than \tcode{numeric_limits::max()} and -less than or equal to \tcode{numeric_limits::max()}. -\end{itemdescr} +\mandates +If \tcode{Extents::rank_dynamic() == 0} is \tcode{true}, +then the size of the multidimensional index space \tcode{Extents()} +is representable as a value of type \tcode{typename Extents::index_type}. + +\rSec5[mdspan.layout.right.cons]{Constructors} +\indexlibraryctor{layout_right::mapping}% \begin{itemdecl} -m(i...) == m(static_cast(i)...) +constexpr mapping(const extents_type& e) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\result -\tcode{bool} +\expects +The size of the multidimensional index space \tcode{e} is representable as +a value of type \tcode{index_type}\iref{basic.fundamental}. \pnum -\returns -\tcode{true} +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{e}. \end{itemdescr} +\indexlibraryctor{layout_right::mapping}% \begin{itemdecl} -m.required_span_size() +template + constexpr explicit(!is_convertible_v) + mapping(const mapping& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\result -\tcode{typename M::index_type} +\constraints +\tcode{is_constructible_v} is \tcode{true}. \pnum -\returns -If the size of the multidimensional index space \tcode{m.extents()} is 0, -then \tcode{0}, -else \tcode{1} plus the maximum value of \tcode{m(i...)} for all \tcode{i}. +\expects +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}\iref{basic.fundamental}. + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. \end{itemdescr} +\indexlibraryctor{layout_right::mapping}% \begin{itemdecl} -m.is_unique() +template + constexpr explicit(!is_convertible_v) + mapping(const layout_left::mapping& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\result -\tcode{bool} +\constraints +\begin{itemize} +\item +\tcode{extents_type::rank() <= 1} is \tcode{true}, and +\item +\tcode{is_constructible_v} is \tcode{true}. +\end{itemize} \pnum -\returns -\tcode{true} only if -for every \tcode{i} and \tcode{j} where \tcode{(i != j || ...)} is \tcode{true}, -\tcode{m(i...) != m(j...)} is \tcode{true}. -\begin{note} -A mapping can return \tcode{false} even if the condition is met. -For certain layouts, it is possibly not feasible to determine efficiently -whether the layout is unique. -\end{note} +\expects +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}\iref{basic.fundamental}. + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. \end{itemdescr} +\indexlibraryctor{layout_right::mapping}% \begin{itemdecl} -m.is_exhaustive() +template + constexpr explicit(!is_convertible_v) + mapping(const LayoutRightPaddedMapping&) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\result -\tcode{bool} +\constraints +\begin{itemize} +\item +\tcode{\exposid{is-layout-right-padded-mapping-of}} +is \tcode{true}. +\item +\tcode{is_constructible_v} +is \tcode{true}. +\end{itemize} \pnum -\returns -\tcode{true} only if -for all $k$ in the range $[0, \tcode{m.required_span_size()})$ -there exists an \tcode{i} such that \tcode{m(i...)} equals $k$. -\begin{note} -A mapping can return \tcode{false} even if the condition is met. -For certain layouts, it is possibly not feasible to determine efficiently -whether the layout is exhaustive. -\end{note} -\end{itemdescr} - -\begin{itemdecl} -m.is_strided() -\end{itemdecl} +\mandates +If +\begin{itemize} +\item +\tcode{Extents::rank()} is greater than one, +\item +\tcode{Extents::static_extent(Extents::rank() - 1)} +does not equal \tcode{dynamic_extent}, and +\item +\tcode{LayoutRightPaddedMapping::\exposid{static-padding-stride}} +does not equal \tcode{dynamic_extent}, +\end{itemize} +then \tcode{Extents::static_extent(Extents::rank() - 1)} equals +\tcode{LayoutRightPaddedMapping::\exposid{sta\-tic-padding-stride}}. -\begin{itemdescr} \pnum -\result -\tcode{bool} +\expects +\begin{itemize} +\item +If \tcode{extents_type::rank() > 1} is \tcode{true}, +then \tcode{other.stride(extents_type::rank() - 2)}\newline equals +\tcode{other.extents().extent(extents_type::rank() - 1)}. +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} \pnum -\returns -\tcode{true} only if -for every rank index $r$ of \tcode{m.extents()} there exists an integer $s_r$ -such that, -for all \tcode{i} where $(\tcode{i}+d_r)$ is -a multidimensional index in \tcode{m.extents()}\iref{mdspan.overview}, -\tcode{m((i + $d_r$)...) - m(i...)} equals $s_r$. -\begin{note} -This implies that for a strided layout -$m(i_0, \dotsc, i_k) = m(0, \dotsc, 0) + i_0 \times s_0 + \dotsb + i_k \times s_k$. -\end{note} -\begin{note} -A mapping can return \tcode{false} even if the condition is met. -For certain layouts, it is possibly not feasible to determine efficiently -whether the layout is strided. -\end{note} +\effects +Direct-non-list-initializes \tcode{extents_} with \tcode{other.extents()}. \end{itemdescr} +\indexlibraryctor{layout_right::mapping}% \begin{itemdecl} -m.stride(r) +template + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{m.is_strided()} is \tcode{true}. +\constraints +\tcode{is_constructible_v} is \tcode{true}. \pnum -\result -\tcode{typename M::index_type} +\expects +\begin{itemize} +\item +If \tcode{extents_type::rank() > 0} is \tcode{true}, +then for all $r$ in the range $[0, \tcode{extents_type::rank()})$, +\tcode{other.stride($r$)} equals +\tcode{other.extents().\exposid{rev-prod-of-extents}($r$)}. +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}\iref{basic.fundamental}. +\end{itemize} \pnum -\returns -$s_r$ as defined in \tcode{m.is_strided()} above. +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. \end{itemdescr} +\rSec5[mdspan.layout.right.obs]{Observers} + +\indexlibrarymember{required_span_size}{layout_right::mapping}% \begin{itemdecl} -M::is_always_unique() +constexpr index_type required_span_size() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\result -A constant expression\iref{expr.const} of type \tcode{bool}. - \pnum \returns -\tcode{true} only if \tcode{m.is_unique()} is \tcode{true} -for all possible objects \tcode{m} of type \tcode{M}. -\begin{note} -A mapping can return \tcode{false} even if the above condition is met. -For certain layout mappings, it is possibly not feasible to determine -whether every instance is unique. -\end{note} +\tcode{extents().\exposid{fwd-prod-of-extents}(extents_type::rank())}. \end{itemdescr} +\indexlibrarymember{operator()}{layout_right::mapping}% \begin{itemdecl} -M::is_always_exhaustive() +template + constexpr index_type operator()(Indices... i) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\result -A constant expression\iref{expr.const} of type \tcode{bool}. +\constraints +\begin{itemize} +\item +\tcode{sizeof...(Indices) == extents_type::rank()} is \tcode{true}, +\item +\tcode{(is_convertible_v \&\& ...)} is \tcode{true}, and +\item +\tcode{(is_nothrow_constructible_v \&\& ...)} is +\tcode{true}. +\end{itemize} \pnum -\returns -\tcode{true} only if \tcode{m.is_exhaustive()} is \tcode{true} -for all possible objects \tcode{m} of type \tcode{M}. -\begin{note} -A mapping can return \tcode{false} even if the above condition is met. -For certain layout mappings, it is possibly not feasible to determine -whether every instance is exhaustive. -\end{note} +\expects +\tcode{extents_type::\exposid{index-cast}(i)} is +a multidimensional index in \exposid{extents_}\iref{mdspan.overview}. + +\pnum +\effects +Let \tcode{P} be a parameter pack such that +\begin{codeblock} +is_same_v, index_sequence> +\end{codeblock} +is \tcode{true}. Equivalent to: +\begin{codeblock} +return ((static_cast(i) * stride(P)) + ... + 0); +\end{codeblock} \end{itemdescr} +\indexlibrarymember{stride}{layout_right::mapping}% \begin{itemdecl} -M::is_always_strided() +constexpr index_type stride(rank_type i) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\result -A constant expression\iref{expr.const} of type \tcode{bool}. +\constraints +\tcode{extents_type::rank() > 0} is \tcode{true}. + +\pnum +\expects +\tcode{i < extents_type::rank()} is \tcode{true}. \pnum \returns -\tcode{true} only if \tcode{m.is_strided()} is \tcode{true} -for all possible objects \tcode{m} of type \tcode{M}. -\begin{note} -A mapping can return \tcode{false} even if the above condition is met. -For certain layout mappings, it is possibly not feasible to determine -whether every instance is strided. -\end{note} +\tcode{extents().\exposid{rev-prod-of-extents}(i)}. \end{itemdescr} -\rSec4[mdspan.layout.policy.reqmts]{Layout mapping policy requirements} +\indexlibrarymember{operator==}{layout_right::mapping}% +\begin{itemdecl} +template + friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -A type \tcode{MP} meets the \defn{layout mapping policy} requirements -if for a type \tcode{E} that is a specialization of \tcode{extents}, -\tcode{MP::mapping} is valid and denotes a type \tcode{X} -that meets the layout mapping requirements\iref{mdspan.layout.reqmts}, and -for which the \grammarterm{qualified-id} \tcode{X::layout_type} is valid and -denotes the type \tcode{MP} and -the \grammarterm{qualified-id} \tcode{X::extents_type} denotes \tcode{E}. - -\rSec4[mdspan.layout.policy.overview]{Layout mapping policies} - -\begin{codeblock} -namespace std { - struct layout_left { - template - class mapping; - }; - struct layout_right { - template - class mapping; - }; - struct layout_stride { - template - class mapping; - }; -} -\end{codeblock} +\constraints +\tcode{extents_type::rank() == OtherExtents::rank()} is \tcode{true}. \pnum -Each of \tcode{layout_left}, \tcode{layout_right}, and \tcode{layout_stride} -meets the layout mapping policy requirements and is a trivial type. +\effects +Equivalent to: \tcode{return x.extents() == y.extents();} +\end{itemdescr} -\rSec4[mdspan.layout.left]{Class template \tcode{layout_left::mapping}} +\rSec4[mdspan.layout.stride]{Class template \tcode{layout_stride::mapping}} -\rSec5[mdspan.layout.left.overview]{Overview} +\rSec5[mdspan.layout.stride.overview]{Overview} \pnum -\tcode{layout_left} provides a layout mapping -where the leftmost extent has stride 1, and -strides increase left-to-right as the product of extents. +\tcode{layout_stride} provides a layout mapping +where the strides are user-defined. \begin{codeblock} namespace std { template - class layout_left::mapping { + class layout_stride::mapping { public: using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; - using layout_type = layout_left; + using layout_type = layout_stride; - // \ref{mdspan.layout.left.cons}, constructors - constexpr mapping() noexcept = default; + private: + static constexpr rank_type @\exposid{rank_}@ = extents_type::rank(); // \expos + + public: + // \ref{mdspan.layout.stride.cons}, constructors + constexpr mapping() noexcept; constexpr mapping(const mapping&) noexcept = default; - constexpr mapping(const extents_type&) noexcept; - template - constexpr explicit(!is_convertible_v) - mapping(const mapping&) noexcept; - template - constexpr explicit(!is_convertible_v) - mapping(const layout_right::mapping&) noexcept; - template - constexpr explicit(extents_type::rank() > 0) - mapping(const layout_stride::mapping&); + template + constexpr mapping(const extents_type&, span) noexcept; + template + constexpr mapping(const extents_type&, const array&) noexcept; + + template + constexpr explicit(@\seebelow@) mapping(const StridedLayoutMapping&) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; - // \ref{mdspan.layout.left.obs}, observers + // \ref{mdspan.layout.stride.obs}, observers constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } + constexpr array strides() const noexcept { return @\exposid{strides_}@; } constexpr index_type required_span_size() const noexcept; @@ -19895,25 +22614,26 @@ constexpr index_type operator()(Indices...) const noexcept; static constexpr bool is_always_unique() noexcept { return true; } - static constexpr bool is_always_exhaustive() noexcept { return true; } + static constexpr bool is_always_exhaustive() noexcept { return false; } static constexpr bool is_always_strided() noexcept { return true; } static constexpr bool is_unique() noexcept { return true; } - static constexpr bool is_exhaustive() noexcept { return true; } + constexpr bool is_exhaustive() const noexcept; static constexpr bool is_strided() noexcept { return true; } - constexpr index_type stride(rank_type) const noexcept; + constexpr index_type stride(rank_type i) const noexcept { return @\exposid{strides_}@[i]; } - template - friend constexpr bool operator==(const mapping&, const mapping&) noexcept; + template + friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept; private: - extents_type @\exposid{extents_}@{}; // \expos + extents_type @\exposid{extents_}@{}; // \expos + array @\exposid{strides_}@{}; // \expos - // \ref{mdspan.submdspan.mapping}, \tcode{submdspan} mapping specialization + // \ref{mdspan.sub.map}, \tcode{submdspan} mapping specialization template - constexpr auto @\exposid{submdspan-mapping-impl}@( // \expos - SliceSpecifiers... slices) const -> @\seebelow@; + constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const // \expos + -> @\seebelow@; template friend constexpr auto submdspan_mapping( @@ -19929,7 +22649,7 @@ then the program is ill-formed. \pnum -\tcode{layout_left::mapping} is a trivially copyable type +\tcode{layout_stride::mapping} is a trivially copyable type that models \libconcept{regular} for each \tcode{E}. \pnum @@ -19938,51 +22658,98 @@ then the size of the multidimensional index space \tcode{Extents()} is representable as a value of type \tcode{typename Extents::index_type}. -\rSec5[mdspan.layout.left.cons]{Constructors} +\rSec5[mdspan.layout.stride.expo]{Exposition-only helpers} -\indexlibraryctor{layout_left::mapping}% -\begin{itemdecl} -constexpr mapping(const extents_type& e) noexcept; -\end{itemdecl} +\pnum +Let \tcode{\exposid{REQUIRED-SPAN-SIZE}(e, strides)} be: +\begin{itemize} +\item +\tcode{1}, if \tcode{e.rank() == 0} is \tcode{true}, +\item +otherwise \tcode{0}, if the size of the multidimensional index space \tcode{e} is 0, +\item +otherwise \tcode{1} plus the sum of products of +\tcode{(e.extent($r$) - 1)} and +\begin{codeblock} +extents_type::@\exposid{index-cast}@(strides[@$r$@]) +\end{codeblock} + for all $r$ in the range $[0, \tcode{e.rank()})$. +\end{itemize} -\begin{itemdescr} \pnum -\expects -The size of the multidimensional index space \tcode{e} -is representable as a value of type \tcode{index_type}\iref{basic.fundamental}. +Let \tcode{\exposid{OFFSET}(m)} be: +\begin{itemize} +\item +\tcode{m()}, if \tcode{e.rank() == 0} is \tcode{true}, +\item +otherwise \tcode{0}, if the size of the multidimensional index space \tcode{e} is 0, +\item +otherwise \tcode{m(z...)} for a pack of integers \tcode{z} +that is a multidimensional index in \tcode{m.extents()} and +each element of \tcode{z} equals 0. +\end{itemize} \pnum -\effects -Direct-non-list-initializes \exposid{extents_} with \tcode{e}. -\end{itemdescr} +Let \exposid{is-extents} be the exposition-only variable template +defined as follows: +\begin{codeblock} +template + constexpr bool @\exposid{is-extents}@ = false; // \expos +template + constexpr bool @\exposid{is-extents}@> = true; // \expos +\end{codeblock} -\indexlibraryctor{layout_left::mapping}% +\pnum +Let \exposconcept{layout-mapping-alike} be the exposition-only concept +defined as follows: +\begin{codeblock} +template +concept @\defexposconcept{layout-mapping-alike}@ = requires { // \expos + requires @\exposid{is-extents}@; + { M::is_always_strided() } -> @\libconcept{same_as}@; + { M::is_always_exhaustive() } -> @\libconcept{same_as}@; + { M::is_always_unique() } -> @\libconcept{same_as}@; + bool_constant::value; + bool_constant::value; + bool_constant::value; +}; +\end{codeblock} +\begin{note} +This concept checks that the functions +\tcode{M::is_always_strided()}, +\tcode{M::is_always_exhaustive()}, and +\tcode{M::is_always_unique()} exist, +are constant expressions, and +have a return type of \tcode{bool}. +\end{note} + +\rSec5[mdspan.layout.stride.cons]{Constructors} + +\indexlibraryctor{layout_stride::mapping}% \begin{itemdecl} -template - constexpr explicit(!is_convertible_v) - mapping(const mapping& other) noexcept; +constexpr mapping() noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. - \pnum \expects -\tcode{other.required_span_size()} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}. +\tcode{layout_right::mapping().required_span_size()} +is representable as a value of type \tcode{index_type}\iref{basic.fundamental}. \pnum \effects -Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. +Direct-non-list-initializes \exposid{extents_} with \tcode{extents_type()}, and +for all $d$ in the range \range{0}{\exposid{rank_}}, +direct-non-list-initializes \tcode{\exposid{strides_}[$d$]} with +\tcode{layout_right::mapping().stride($d$)}. \end{itemdescr} -\indexlibraryctor{layout_left::mapping}% +\indexlibraryctor{layout_stride::mapping}% \begin{itemdecl} -template - constexpr explicit(!is_convertible_v) - mapping(const layout_right::mapping& other) noexcept; +template + constexpr mapping(const extents_type& e, span s) noexcept; +template + constexpr mapping(const extents_type& e, const array& s) noexcept; \end{itemdecl} \begin{itemdescr} @@ -19990,54 +22757,100 @@ \constraints \begin{itemize} \item -\tcode{extents_type::rank() <= 1} is \tcode{true}, and +\tcode{is_convertible_v} is \tcode{true}, and \item -\tcode{is_constructible_v} is \tcode{true}. +\tcode{is_nothrow_constructible_v} is \tcode{true}. \end{itemize} \pnum \expects -\tcode{other.required_span_size()} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}. +\begin{itemize} +\item +The result of converting \tcode{s[$i$]} to \tcode{index_type} +is greater than \tcode{0} +for all $i$ in the range $[0, \exposid{rank_})$. +\item +\tcode{\exposid{REQUIRED-SPAN-SIZE}(e, s)} is representable +as a value of type \tcode{index_type}\iref{basic.fundamental}. +\item +If \exposid{rank_} is greater than 0, +then there exists a permutation $P$ of the integers +in the range $[0, \exposid{rank_})$, +such that \tcode{s[$p_i$] >= s[$p_{i-1}$] * e.extent(p$_{i-1}$)} is \tcode{true} +for all $i$ in the range $[1, \exposid{rank_})$, +where $p_i$ is the $i^\text{th}$ element of $P$. +\begin{note} +For \tcode{layout_stride}, +this condition is necessary and sufficient +for \tcode{is_unique()} to be \tcode{true}. +\end{note} +\end{itemize} \pnum \effects -Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. +Direct-non-list-initializes \exposid{extents_} with \tcode{e}, and +for all $d$ in the range $[0, \exposid{rank_})$, +direct-non-list-initializes \tcode{strides_[$d$]} with \tcode{as_const(s[$d$])}. \end{itemdescr} -\indexlibraryctor{layout_left::mapping}% +\indexlibraryctor{layout_stride::mapping}% \begin{itemdecl} -template - constexpr explicit(extents_type::rank() > 0) - mapping(const layout_stride::mapping& other); +template + constexpr explicit(@\seebelow@) + mapping(const StridedLayoutMapping& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_constructible_v} is \tcode{true}. +\begin{itemize} +\item +\tcode{\exposconcept{layout-mapping-alike}} is satisfied. +\item +\tcode{is_constructible_v} is\\\tcode{true}. +\item +\tcode{StridedLayoutMapping::is_always_unique()} is \tcode{true}. +\item +\tcode{StridedLayoutMapping::is_always_strided()} is \tcode{true}. +\end{itemize} \pnum \expects \begin{itemize} \item -If \tcode{extents_type::rank() > 0} is \tcode{true}, -then for all $r$ in the range $[0, \tcode{extents_type::rank()})$, -\tcode{other.stride($r$)} equals -\tcode{other.extents().\exposid{fwd-prod-of-extents}($r$)}, and +\tcode{StridedLayoutMapping} meets the layout mapping requirements\iref{mdspan.layout.reqmts}, +\item +\tcode{other.stride($r$) > 0} is \tcode{true} +for every rank index $r$ of \tcode{extents()}, \item \tcode{other.required_span_size()} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}. +a value of type \tcode{index_type}\iref{basic.fundamental}, and +\item +\tcode{\exposid{OFFSET}(other) == 0} is \tcode{true}. \end{itemize} \pnum \effects -Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}, and +for all $d$ in the range $[0, \exposid{rank_})$, +direct-non-list-initializes \tcode{\exposid{strides_}[$d$]} +with \tcode{other.stride($d$)}. + +\pnum +Remarks: The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!(is_convertible_v && + (@\exposid{is-mapping-of}@ || + @\exposid{is-mapping-of}@ || + @\exposid{is-layout-left-padded-mapping-of}@ || + @\exposid{is-layout-right-padded-mapping-of}@ || + @\exposid{is-mapping-of}@)) +\end{codeblock} \end{itemdescr} -\rSec5[mdspan.layout.left.obs]{Observers} +\rSec5[mdspan.layout.stride.obs]{Observers} -\indexlibrarymember{required_span_size}{layout_left::mapping}% +\indexlibrarymember{required_span_size}{layout_stride::mapping}% \begin{itemdecl} constexpr index_type required_span_size() const noexcept; \end{itemdecl} @@ -20045,10 +22858,10 @@ \begin{itemdescr} \pnum \returns -\tcode{extents().\exposid{fwd-prod-of-extents}(extents_type::rank())}. +\tcode{\exposid{REQUIRED-SPAN-SIZE}(extents(), \exposid{strides_})}. \end{itemdescr} -\indexlibrarymember{operator()}{layout_left::mapping}% +\indexlibrarymember{operator()}{layout_stride::mapping}% \begin{itemdecl} template constexpr index_type operator()(Indices... i) const noexcept; @@ -20059,7 +22872,7 @@ \constraints \begin{itemize} \item -\tcode{sizeof...(Indices) == extents_type::rank()} is \tcode{true}, +\tcode{sizeof...(Indices) == \exposid{rank_}} is \tcode{true}, \item \tcode{(is_convertible_v \&\& ...)} is \tcode{true}, and \item @@ -20084,111 +22897,148 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{stride}{layout_left::mapping}% +\indexlibrarymember{is_exhaustive}{layout_stride::mapping}% \begin{itemdecl} -constexpr index_type stride(rank_type i) const; +constexpr bool is_exhaustive() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{extents_type::rank() > 0} is \tcode{true}. - -\pnum -\expects -\tcode{i < extents_type::rank()} is \tcode{true}. - \pnum \returns -\tcode{extents().\exposid{fwd-prod-of-extents}(i)}. +\begin{itemize} +\item +\tcode{true} if \exposid{rank_} is 0. +\item +Otherwise, \tcode{true} if there is +a permutation $P$ of the integers in the range $[0, \exposid{rank_})$ +such that \tcode{stride($p_0$)} equals 1, and +\tcode{stride($p_i$)} equals \tcode{stride($ p_{i-1}$) * extents().extent($p_{i-1}$)} +for $i$ in the range $[1, \exposid{rank_})$, +where $p_i$ is the $i^\text{th}$ element of $P$. +\item +Otherwise, \tcode{false}. +\end{itemize} \end{itemdescr} -\indexlibrarymember{operator==}{layout_left::mapping}% +\indexlibrarymember{operator==}{layout_stride::mapping}% \begin{itemdecl} -template - friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; +template + friend constexpr bool operator==(const mapping& x, const OtherMapping& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{extents_type::rank() == OtherExtents::rank()} is \tcode{true}. +\begin{itemize} +\item +\tcode{\exposconcept{layout-mapping-alike}} is satisfied. +\item +\tcode{\exposid{rank_} == OtherMapping::extents_type::rank()} is \tcode{true}. +\item +\tcode{OtherMapping::is_always_strided()} is \tcode{true}. +\end{itemize} \pnum -\effects -Equivalent to: \tcode{return x.extents() == y.extents();} +\expects +\tcode{OtherMapping} meets the layout mapping requirements\iref{mdspan.layout.policy.reqmts}. + +\pnum +\returns +\tcode{true} if \tcode{x.extents() == y.extents()} is \tcode{true}, +\tcode{\exposid{OFFSET}(y) == 0} is \tcode{true}, and +each of \tcode{x.stride($r$) == y.stride($r$)} is \tcode{true} +for $r$ in the range $[0, \tcode{x.extents().rank()})$. +Otherwise, \tcode{false}. \end{itemdescr} -\rSec4[mdspan.layout.right]{Class template \tcode{layout_right::mapping}} +\rSec4[mdspan.layout.leftpad]{Class template \tcode{layout_left_padded::mapping}} -\rSec5[mdspan.layout.right.overview]{Overview} +\rSec5[mdspan.layout.leftpad.overview]{Overview} \pnum -\tcode{layout_right} provides a layout mapping -where the rightmost extent is stride 1, and -strides increase right-to-left as the product of extents. +\tcode{layout_left_padded} provides a layout mapping +that behaves like \tcode{layout_left::mapping}, +except that the padding stride \tcode{stride(1)} +can be greater than or equal to \tcode{extent(0)}. \begin{codeblock} namespace std { + template template - class layout_right::mapping { + class layout_left_padded::mapping { public: + static constexpr size_t padding_value = PaddingValue; + using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; - using layout_type = layout_right; + using layout_type = layout_left_padded; - // \ref{mdspan.layout.right.cons}, constructors - constexpr mapping() noexcept = default; + private: + static constexpr size_t @\exposid{rank_}@ = extents_type::rank(); // \expos + static constexpr size_t @\exposid{first-static-extent}@ = // \expos + extents_type::static_extent(0); + + // \ref{mdspan.layout.leftpad.expo}, exposition-only members + static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@; // \expos + + public: + // \ref{mdspan.layout.leftpad.cons}, constructors + constexpr mapping() noexcept : mapping(extents_type{}) {} constexpr mapping(const mapping&) noexcept = default; - constexpr mapping(const extents_type&) noexcept; - template - constexpr explicit(!is_convertible_v) - mapping(const mapping&) noexcept; + constexpr mapping(const extents_type&); + template + constexpr mapping(const extents_type&, OtherIndexType); template constexpr explicit(!is_convertible_v) - mapping(const layout_left::mapping&) noexcept; + mapping(const layout_left::mapping&); template constexpr explicit(extents_type::rank() > 0) - mapping(const layout_stride::mapping&) noexcept; + mapping(const layout_stride::mapping&); + template + constexpr explicit(@\seebelow@) + mapping(const LayoutLeftPaddedMapping&); + template + constexpr explicit(@\seebelow@) + mapping(const LayoutRightPaddedMapping&) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; - // \ref{mdspan.layout.right.obs}, observers + // \ref{mdspan.layout.leftpad.obs}, observers constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } + constexpr array strides() const noexcept; constexpr index_type required_span_size() const noexcept; - template constexpr index_type operator()(Indices...) const noexcept; static constexpr bool is_always_unique() noexcept { return true; } - static constexpr bool is_always_exhaustive() noexcept { return true; } + static constexpr bool is_always_exhaustive() noexcept; static constexpr bool is_always_strided() noexcept { return true; } static constexpr bool is_unique() noexcept { return true; } - static constexpr bool is_exhaustive() noexcept { return true; } + constexpr bool is_exhaustive() const noexcept; static constexpr bool is_strided() noexcept { return true; } constexpr index_type stride(rank_type) const noexcept; - template - friend constexpr bool operator==(const mapping&, const mapping&) noexcept; + template + friend constexpr bool operator==(const mapping&, const LayoutLeftPaddedMapping&) noexcept; private: - extents_type @\exposid{extents_}@{}; // \expos - - // \ref{mdspan.submdspan.mapping}, \tcode{submdspan} mapping specialization + // \ref{mdspan.layout.leftpad.expo}, exposition-only members + index_type @\exposid{stride-1}@ = @\exposid{static-padding-stride}@; // \expos + extents_type @\exposid{extents_}@{}; // \expos + // \ref{mdspan.sub.map}, submdspan mapping specialization template - constexpr auto @\exposid{submdspan-mapping-impl}@( // \expos - SliceSpecifiers... slices) const -> @\seebelow@; + constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const // \expos + -> @\seebelow@; template - friend constexpr auto submdspan_mapping( - const mapping& src, SliceSpecifiers... slices) { - return src.@\exposid{submdspan-mapping-impl}@(slices...); - } + friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) { + return src.@\exposid{submdspan-mapping-impl}@(slices...); + } }; } \end{codeblock} @@ -20198,38 +23048,243 @@ then the program is ill-formed. \pnum -\tcode{layout_right::mapping} is a trivially copyable type +\tcode{layout_left_padded::mapping} is a trivially copyable type that models \libconcept{regular} for each \tcode{E}. +\pnum +Throughout \ref{mdspan.layout.leftpad}, +let \tcode{P_rank} be the following +size \exposid{rank_} parameter pack of \tcode{size_}t values: +\begin{itemize} +\item +the empty parameter pack, if \exposid{rank_} equals zero; +\item +\tcode otherwise, \tcode{0zu}, if \exposid{rank_} equals one; +\item +otherwise, the parameter pack \tcode{0zu}, \tcode{1zu}, \ldots, \tcode{\exposid{rank_}- 1}. +\end{itemize} + \pnum \mandates -If \tcode{Extents::rank_dynamic() == 0} is \tcode{true}, +\begin{itemize} +\item +If \tcode{rank_dynamic() == 0} is \tcode{true}, then the size of the multidimensional index space \tcode{Extents()} -is representable as a value of type \tcode{typename Extents::index_type}. +is representable as a value of type \tcode{index_type}. +\item +\tcode{padding_value} is representable as a value of type \tcode{index_type}. +\item +If +\begin{itemize} +\item +\exposid{rank_} is greater than one, +\item +\tcode{padding_value} does not equal \tcode{dynamic_extent}, and +\item +\exposid{first-static-extent} does not equal \tcode{dynamic_extent}, +\end{itemize} +then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, \exposid{first-static-extent})} +is representable as a val\-ue of type \tcode{size_t}, and +is representable as a value of type \tcode{index_type}. +\item +If +\begin{itemize} +\item +\exposid{rank_} is greater than one, +\item +\tcode{padding_value} does not equal \tcode{dynamic_extent}, and +\item +\tcode{extents_type::static_extent($k$)} does not equal \tcode{dynamic_extent} +for all $k$ in the range \range{0}{extents_type::rank()}, +\end{itemize} +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.static_extent(0))} and +all values \tcode{ext.static_extent($k$)} +with $k$ in the range of \range{1}{\exposid{rank_}} +is representable as a value of type \tcode{size_t}, and +is representable as a value of type \tcode{index_type}. +\end{itemize} -\rSec5[mdspan.layout.right.cons]{Constructors} +\rSec5[mdspan.layout.leftpad.expo]{Exposition-only members} -\indexlibraryctor{layout_right::mapping}% \begin{itemdecl} -constexpr mapping(const extents_type& e) noexcept; +static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The value is +\begin{itemize} +\item +\tcode{0}, if \exposid{rank_} equals zero or one; +\item +otherwise, \tcode{dynamic_extent}, +if \tcode{padding_value} or \exposid{first-static-extent} equals +\tcode{dynamic_extent}; +\item +otherwise, the \tcode{size_t} value which is +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, \exposid{first-sta\-tic-extent})}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +index_type @\exposid{stride-1}@ = @\exposid{static-padding-stride}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\recommended +Implementations should not store this value +if \exposid{static-padding-stride} is not \tcode{dynamic_extent}. +\begin{note} +Using \tcode{extents} instead of +\tcode{index_type} as the type of \exposid{stride-1} would achieve this. +\end{note} +\end{itemdescr} + +\rSec5[mdspan.layout.leftpad.cons]{Constructors} + +\indexlibraryctor{layout_left_padded::mapping}% +\begin{itemdecl} +constexpr mapping(const extents_type& ext); \end{itemdecl} \begin{itemdescr} \pnum \expects -The size of the multidimensional index space \tcode{e} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}. +\begin{itemize} +\item +The size of the multidimensional index space \tcode{ext} is representable as +a value of type \tcode{index_type}. +\item +If \exposid{rank_} is greater than one and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{\exposid{LEAST-MUL\-TIPLE-AT-LEAST}(padding_value, ext.extent(0))} +is representable as a value of type \exposid{index_type}. +\item +If \exposid{rank_} is greater than one and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(0))} and +all values \tcode{ext.extent($k$)} +with $k$ in the range of \range{1}{\exposid{rank_}} +is representable as a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{ext}; and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-1} +\begin{itemize} +\item +with \tcode{ext.extent(0)} if padding_value is \tcode{dynamic_extent}, +\item +otherwise with +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(0))}. +\end{itemize} +\end{itemize} +\end{itemdescr} + +\indexlibraryctor{layout_left_padded::mapping}% +\begin{itemdecl} +template +constexpr mapping(const extents_type& ext, OtherIndexType pad); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v} is \tcode{true}. +\item +\tcode{is_nothrow_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{pad} is representable as a value of type \tcode{index_type}. +\item +\tcode{extents_type::index-cast(pad)} is greater than zero. +\item +If \exposid{rank_} is greater than one, +then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(0))} +is representable as a value of type \tcode{index_type.} +\item +If \exposid{rank_} is greater than one, +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\linebreak 0))} and +all values \tcode{ext.extent($k$)} +with $k$ in the range of \range{1}{\exposid{rank_}} +is representable as a value of type \tcode{index_type}. +\item +If \tcode{padding_value} is not equal to \tcode{dynamic_extent}, +\tcode{padding_value} equals \tcode{extents_type::\exposid{in\-dex-cast}(pad)}. +\end{itemize} + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{ext}, and +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-1} with +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(0))}. +\end{itemdescr} + +\indexlibraryctor{layout_left_padded::mapping}% +\begin{itemdecl} +template + constexpr explicit(!is_convertible_v) + mapping(const layout_left::mapping& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\mandates +If \tcode{OtherExtents::rank()} is greater than \tcode{1}, then +\begin{codeblock} +(@\exposid{static-padding-stride}@ == dynamic_extent) || +(OtherExtents::static_extent(0) == dynamic_extent) || +(@\exposid{static-padding-stride}@ == OtherExtents::static_extent(0)) +\end{codeblock} +is \tcode{true}. + +\pnum +\expects +\begin{itemize} +\item +If \tcode{extents_type::rank() > 1} is \tcode{true} and +\tcode{padding_value} == \tcode{dynamic_extent} is \tcode{false}, +then \tcode{other.stride(1)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extents().extent(0))) +\end{codeblock} +and +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} \pnum \effects -Direct-non-list-initializes \exposid{extents_} with \tcode{e}. +Equivalent to \tcode{mapping(other.extents())}. \end{itemdescr} -\indexlibraryctor{layout_right::mapping}% +\indexlibraryctor{layout_left_padded::mapping}% \begin{itemdecl} template - constexpr explicit(!is_convertible_v) - mapping(const mapping& other) noexcept; + constexpr explicit(rank_ > 0) + mapping(const layout_stride::mapping& other); \end{itemdecl} \begin{itemdescr} @@ -20239,19 +23294,47 @@ \pnum \expects +\begin{itemize} +\item +If \exposid{rank_} is greater than \tcode{1} and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{other.\linebreak stride(1)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extents().extent(0))) +\end{codeblock} +\item +If \exposid{rank_} is greater than 0, +then \tcode{other.stride(0)} equals 1. +\item +If \exposid{rank_} is greater than 2, +then for all $r$ in the range \range{2}{\exposid{rank_}}, +\tcode{other.stride(r)} equals +\begin{codeblock} +(other.extents().@\exposid{fwd-prod-of-extents}@(r) / other.extents().extent(0)) * other.stride(1) +\end{codeblock} +\item \tcode{other.required_span_size()} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}. +a value of type \exposid{index_type}. +\end{itemize} \pnum \effects -Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()} and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-1} with +\tcode{other.stride(1)}. +\end{itemize} \end{itemdescr} -\indexlibraryctor{layout_right::mapping}% +\indexlibraryctor{layout_left_padded::mapping}% \begin{itemdecl} -template - constexpr explicit(!is_convertible_v) - mapping(const layout_left::mapping& other) noexcept; +template + constexpr explicit(@\seebelow@) + mapping(const LayoutLeftPaddedMapping& other); \end{itemdecl} \begin{itemdescr} @@ -20259,68 +23342,137 @@ \constraints \begin{itemize} \item -\tcode{extents_type::rank() <= 1} is \tcode{true}, and +\tcode{\exposid{is-layout-left-padded-mapping-of}} +is \tcode{true}. \item -\tcode{is_constructible_v} is \tcode{true}. +\tcode{is_constructible_v} +\newline is \tcode{true}. \end{itemize} +\pnum +\mandates +If \exposid{rank_} is greater than 1, +then +\begin{codeblock} +padding_value == dynamic_extent || +LayoutLeftPaddedMapping::padding_value == dynamic_extent || +padding_value == LayoutLeftPaddedMapping::padding_value +\end{codeblock} +is \tcode{true}. + \pnum \expects +\begin{itemize} +\item +If \exposid{rank_} is greater than 1 and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{other.\linebreak stride(1)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extent(0))) +\end{codeblock} +\item \tcode{other.required_span_size()} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}. +a value of type \tcode{index_type}. +\end{itemize} \pnum \effects -Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()} and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-1} with \tcode{other.stride(1)}. +\end{itemize} + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +rank_> 1 && +(padding_value != dynamic_extent || + LayoutLeftPaddedMapping::padding_value == dynamic_extent) +\end{codeblock} \end{itemdescr} -\indexlibraryctor{layout_right::mapping}% +\indexlibraryctor{layout_left_padded::mapping}% \begin{itemdecl} -template - constexpr explicit(extents_type::rank() > 0) - mapping(const layout_stride::mapping& other) noexcept; +template + constexpr explicit(@\seebelow@) + mapping(const LayoutRightPaddedMapping& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_constructible_v} is \tcode{true}. - -\pnum -\expects \begin{itemize} \item -If \tcode{extents_type::rank() > 0} is \tcode{true}, -then for all $r$ in the range $[0, \tcode{extents_type::rank()})$, -\tcode{other.stride($r$)} equals -\tcode{other.extents().\exposid{rev-prod-of-extents}($r$)}. +\tcode{\exposid{is-layout-right-padded-mapping-of}} +is \tcode{true} or\newline +\tcode{\exposid{is-mapping-of}} +is \tcode{true}. \item -\tcode{other.required_span_size()} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}. +\exposid{rank_} equals zero or one. +\item +\tcode{is_constructible_v} +is \tcode{true}. \end{itemize} +\pnum +\expects +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. + \pnum \effects Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!is_convertible_v +\end{codeblock} + +\begin{note} +Neither the input mapping nor the mapping to be constructed +uses the padding stride in the rank-0 or rank-1 case, +so the padding stride does not affect +either the constraints or the preconditions. +\end{note} \end{itemdescr} -\rSec5[mdspan.layout.right.obs]{Observers} +\rSec5[mdspan.layout.leftpad.obs]{Observers} -\indexlibrarymember{required_span_size}{layout_right::mapping}% \begin{itemdecl} -index_type required_span_size() const noexcept; +constexpr array strides() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{extents().\exposid{fwd-prod-of-extents}(extents_type::rank())}. +\tcode{array(\{stride(P_rank)...\})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr index_type required_span_size() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +\tcode{0} if the multidimensional index space \exposid{extents_} is empty, +\item +otherwise, \tcode{*this(((\exposid{extents_}(P_rank) - index_type(1))...)) + 1}. +\end{itemize} \end{itemdescr} -\indexlibrarymember{operator()}{layout_right::mapping}% \begin{itemdecl} template - constexpr index_type operator()(Indices... i) const noexcept; +constexpr size_t operator()(Indices... idxs) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -20328,105 +23480,158 @@ \constraints \begin{itemize} \item -\tcode{sizeof...(Indices) == extents_type::rank()} is \tcode{true}, +\tcode{sizeof...(Indices) == \exposid{rank_}} is \tcode{true}. \item -\tcode{(is_convertible_v \&\& ...)} is \tcode{true}, and +\tcode{(is_convertible_v \&\& ...)} is \tcode{true}. \item -\tcode{(is_nothrow_constructible_v \&\& ...)} is -\tcode{true}. +\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}. \end{itemize} \pnum \expects -\tcode{extents_type::\exposid{index-cast}(i)} is -a multidimensional index in \exposid{extents_}\iref{mdspan.overview}. +\tcode{extents_type::\exposid{index-cast}(idxs)} is +a multidimensional index in \tcode{extents()}\iref{mdspan.overview}. \pnum -\effects -Let \tcode{P} be a parameter pack such that -\begin{codeblock} -is_same_v, index_sequence> -\end{codeblock} -is \tcode{true}. Equivalent to: -\begin{codeblock} -return ((static_cast(i) * stride(P)) + ... + 0); -\end{codeblock} +\returns +\tcode{((static_cast(idxs) * stride(P_rank)) + ... + 0)}. \end{itemdescr} -\indexlibrarymember{stride}{layout_right::mapping}% \begin{itemdecl} -constexpr index_type stride(rank_type i) const noexcept; +static constexpr bool is_always_exhaustive() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{extents_type::rank() > 0} is \tcode{true}. +\returns +\begin{itemize} +\item +If \exposid{rank_} equals zero or one, then \tcode{true}; +\item +otherwise, if +neither \exposid{static-padding-stride} nor \exposid{first-static-extent} +equal \tcode{dynamic_extent}, +then \tcode{\exposid{static-padding-stride} == \exposid{first-static-extent}}; +\item +otherwise, \tcode{false}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +constexpr bool is_exhaustive() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \exposid{rank_} equals zero or one; +otherwise, \tcode{extents_.extent(0) == stride(1)}. +\end{itemdescr} +\begin{itemdecl} +constexpr index_type stride(rank_type r) const noexcept; +\end{itemdecl} + +\begin{itemdescr} \pnum \expects -\tcode{i < extents_type::rank()} is \tcode{true}. +\tcode{r} is smaller than \exposid{rank_}. \pnum \returns -\tcode{extents().\exposid{rev-prod-of-extents}(i)}. +\begin{itemize} +\item +If \tcode{r} equals zero: 1; +\item +otherwise, if \tcode{r} equals one: \exposid{stride-1}; +\item +otherwise, the product of \exposid{stride-1} and +all values \tcode{extents_.extent($k$)} with $k$ in the range \range{1}{r}. +\end{itemize} \end{itemdescr} -\indexlibrarymember{operator==}{layout_right::mapping}% \begin{itemdecl} -template - friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; +template + friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{extents_type::rank() == OtherExtents::rank()} is \tcode{true}. +\begin{itemize} +\item +\tcode{\exposid{is-layout-left-padded-mapping-of}} +is \tcode{true}. +\item +\tcode{LayoutLeftPaddedMapping::extents_type::rank() == rank_} is \tcode{true}. +\end{itemize} \pnum -\effects -Equivalent to: \tcode{return x.extents() == y.extents();} +\returns +\tcode{true} if \tcode{x.extents() == y.extents()} is \tcode{true} and +\tcode{\exposid{rank_} < 2 || x.stride(1) == y.\newline stride(1)} is \tcode{true}. +Otherwise, \tcode{false}. \end{itemdescr} -\rSec4[mdspan.layout.stride]{Class template \tcode{layout_stride::mapping}} +\rSec4[mdspan.layout.rightpad]{Class template \tcode{layout_right_padded::mapping}} -\rSec5[mdspan.layout.stride.overview]{Overview} +\rSec5[mdspan.layout.rightpad.overview]{Overview} \pnum -\tcode{layout_stride} provides a layout mapping -where the strides are user-defined. +\tcode{layout_right_padded} provides a layout mapping +that behaves like \tcode{layout_right::mapping}, +except that the padding stride \tcode{stride(extents_type::rank() - 2)} +can be greater than or equal to +\tcode{extents_type::ex\-tent(extents_type::rank() - 1)}. \begin{codeblock} namespace std { + template template - class layout_stride::mapping { + class layout_right_padded::mapping { public: + static constexpr size_t padding_value = PaddingValue; + using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; - using layout_type = layout_stride; + using layout_type = layout_right_padded; private: - static constexpr rank_type @\exposid{rank_}@ = extents_type::rank(); // \expos + static constexpr size_t @\exposid{rank_}@ = extents_type::rank(); // \expos + static constexpr size_t @\exposid{last-static-extent}@ = // \expos + extents_type::static_extent(@\exposid{rank_}@ - 1); + + // \ref{mdspan.layout.rightpad.expo}, exposition-only members + static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@; // \expos public: - // \ref{mdspan.layout.stride.cons}, constructors - constexpr mapping() noexcept; + // \ref{mdspan.layout.rightpad.cons}, constructors + constexpr mapping() noexcept : mapping(extents_type{}) {} constexpr mapping(const mapping&) noexcept = default; + constexpr mapping(const extents_type&); template - constexpr mapping(const extents_type&, span) noexcept; - template - constexpr mapping(const extents_type&, const array&) noexcept; + constexpr mapping(const extents_type&, OtherIndexType); - template - constexpr explicit(@\seebelow@) mapping(const StridedLayoutMapping&) noexcept; + template + constexpr explicit(!is_convertible_v) + mapping(const layout_right::mapping&); + template + constexpr explicit(rank_ > 0) + mapping(const layout_stride::mapping&); + template + constexpr explicit(@\seebelow@) + mapping(const LayoutRightPaddedMapping&); + template + constexpr explicit(@\seebelow@) + mapping(const LayoutLeftPaddedMapping&) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; - // \ref{mdspan.layout.stride.obs}, observers - constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } - constexpr array strides() const noexcept { return @\exposid{strides_}@; } + // \ref{mdspan.layout.rightpad.obs}, observers + constexpr const extents_type& extents() const noexcept { return extents_; } + constexpr array strides() const noexcept; constexpr index_type required_span_size() const noexcept; @@ -20434,142 +23639,331 @@ constexpr index_type operator()(Indices...) const noexcept; static constexpr bool is_always_unique() noexcept { return true; } - static constexpr bool is_always_exhaustive() noexcept { return false; } + static constexpr bool is_always_exhaustive() noexcept; static constexpr bool is_always_strided() noexcept { return true; } static constexpr bool is_unique() noexcept { return true; } constexpr bool is_exhaustive() const noexcept; static constexpr bool is_strided() noexcept { return true; } - constexpr index_type stride(rank_type i) const noexcept { return @\exposid{strides_}@[i]; } + constexpr index_type stride(rank_type) const noexcept; - template - friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept; + template + friend constexpr bool operator==(const mapping&, const LayoutRightPaddedMapping&) noexcept; private: - extents_type @\exposid{extents_}@{}; // \expos - array @\exposid{strides_}@{}; // \expos + // \ref{mdspan.layout.rightpad.expo}, exposition-only members + index_type @\exposid{stride-rm2}@ = @\exposid{static-padding-stride}@; // \expos + extents_type @\exposid{extents_}@{}; // \expos - // \ref{mdspan.submdspan.mapping}, \tcode{submdspan} mapping specialization + // \ref{mdspan.sub.map}, submdspan mapping specialization template - constexpr auto @\exposid{submdspan-mapping-impl}@( // \expos - SliceSpecifiers... slices) const -> @\seebelow@; + constexpr auto @\exposid{submdspan-mapping-impl}@(SliceSpecifiers...) const // \expos + -> @\seebelow@; template - friend constexpr auto submdspan_mapping( - const mapping& src, SliceSpecifiers... slices) { - return src.@\exposid{submdspan-mapping-impl}@(slices...); - } + friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) { + return src.@\exposid{submdspan-mapping-impl}@(slices...); + } }; } \end{codeblock} \pnum -If \tcode{Extents} is not a specialization of \tcode{extents}, -then the program is ill-formed. +If \tcode{Extents} is not a specialization of \tcode{extents}, +then the program is ill-formed. + +\pnum +\tcode{layout_right_padded::mapping} is a trivially copyable type +that models \libconcept{regular} for each \tcode{E}. + +\pnum +Throughout \ref{mdspan.layout.rightpad}, +let \tcode{P_rank} be the following +size \exposid{rank_} parameter pack of \tcode{size_}t values: +\begin{itemize} +\item +the empty parameter pack, if \exposid{rank_} equals zero; +\item +\tcode otherwise, \tcode{0zu}, if \exposid{rank_} equals one; +\item +otherwise, the parameter pack \tcode{0zu}, \tcode{1zu}, \ldots, \tcode{\exposid{rank_}- 1}. +\end{itemize} + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{rank_dynamic() == 0} is \tcode{true}, +then the size of the multidimensional index space \tcode{Extents()} +is representable as a value of type \tcode{index_type}. +\item +\tcode{padding_value} is representable as a value of type \tcode{index_type}. +\item +If +\begin{itemize} +\item +\exposid{rank_} is greater than one, +\item +\tcode{padding_value} does not equal \tcode{dynamic_extent}, and +\item +\exposid{last-static-extent} does not equal \tcode{dynamic_extent}, +\end{itemize} +then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, \exposid{last-static-extent})} +is representable as a value of type \tcode{size_t}, and +is representable as a value of type \tcode{index_type}. +\item +If +\begin{itemize} +\item +\exposid{rank_} is greater than one, +\item +\tcode{padding_value} does not equal \tcode{dynamic_extent}, and +\item +\tcode{extents_type::static_extent($k$)} does not equal \tcode{dynamic_extent} +for all $k$ in the range \range{0}{\exposid{rank_}}, +\end{itemize} +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.static_extent(\exposid{rank_} - 1))} and +all values \tcode{ext.static_extent($k$)} +with $k$ in the range of \range{0}{\exposid{rank_} - 1} +is representable as a value of type \tcode{size_t}, and +is representable as a value of type \tcode{index_type}. +\end{itemize} + +\rSec5[mdspan.layout.rightpad.expo]{Exposition-only members} + +\begin{itemdecl} +static constexpr size_t @\exposid{static-padding-stride}@ = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The value is +\begin{itemize} +\item +\tcode{0}, if \exposid{rank_} equals zero or one; +\item +otherwise, \tcode{dynamic_extent}, +if \tcode{padding_value} or \exposid{last-static-extent} equals +\tcode{dynamic_extent}; +\item +otherwise, the \tcode{size_t} value which is +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, \exposid{last-sta\-tic-extent})}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +index_type @\exposid{stride-rm2}@ = @\exposid{static-padding-stride}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\recommended +Implementations should not store this value +if \exposid{static-padding-stride} is not \tcode{dynamic_extent}. +\begin{note} +Using \tcode{extents} +instead of \tcode{index_type} as the type of \exposid{stride-\linebreak rm2} +would achieve this. +\end{note} +\end{itemdescr} + +\rSec5[mdspan.layout.rightpad.cons]{Constructors} + +\indexlibraryctor{layout_right_padded::mapping}% +\begin{itemdecl} +constexpr mapping(const extents_type& ext); +\end{itemdecl} +\begin{itemdescr} \pnum -\tcode{layout_stride::mapping} is a trivially copyable type -that models \libconcept{regular} for each \tcode{E}. +\expects +\begin{itemize} +\item +The size of the multidimensional index space \tcode{ext} +is representable as a value of type \tcode{index_type}. +\item +If \exposid{rank_} is greater than one and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{\exposid{LEAST-MUL\-TIPLE-AT-LEAST}(padding_value, ext.extent(\exposid{rank_} - 1))} +is representable as a value of type \exposid{index_type}. +\item +If \exposid{rank_} is greater than one and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(\exposid{rank_} - 1))} and +all values \tcode{ext.extent($k$)} +with $k$ in the range of \range{0}{\exposid{rank_} - 1} +is representable as a value of type \tcode{index_type}. +\end{itemize} \pnum -\mandates -If \tcode{Extents::rank_dynamic() == 0} is \tcode{true}, -then the size of the multidimensional index space \tcode{Extents()} -is representable as a value of type \tcode{typename Extents::index_type}. +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{ext}; and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-rm2} +\begin{itemize} +\item +with \tcode{ext.extent(\exposid{rank_} - 1)} +if \tcode{padding_value} is \tcode{dynamic_extent}, +\item +otherwise with +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(padding_value, ext.extent(\exposid{rank_} - 1))}. +\end{itemize} +\end{itemize} +\end{itemdescr} -\rSec5[mdspan.layout.stride.expo]{Exposition-only helpers} +\indexlibraryctor{layout_right_padded::mapping}% +\begin{itemdecl} +template +constexpr mapping(const extents_type& ext, OtherIndexType pad); +\end{itemdecl} +\begin{itemdescr} \pnum -Let \tcode{\exposid{REQUIRED-SPAN-SIZE}(e, strides)} be: +\constraints \begin{itemize} \item -\tcode{1}, if \tcode{e.rank() == 0} is \tcode{true}, -\item -otherwise \tcode{0}, if the size of the multidimensional index space \tcode{e} is 0, +\tcode{is_convertible_v} is \tcode{true}. \item -otherwise \tcode{1} plus the sum of products of -\tcode{(e.extent($r$) - 1)} and -\begin{codeblock} -extents_type::@\exposid{index-cast}@(strides[@$r$@]) -\end{codeblock} - for all $r$ in the range $[0, \tcode{e.rank()})$. +\tcode{is_nothrow_constructible_v} is \tcode{true}. \end{itemize} \pnum -Let \tcode{\exposid{OFFSET}(m)} be: +\expects \begin{itemize} \item -\tcode{m()}, if \tcode{e.rank() == 0} is \tcode{true}, +\tcode{pad} is representable as a value of type \tcode{index_type}. \item -otherwise \tcode{0}, if the size of the multidimensional index space \tcode{e} is 0, +\tcode{extents_type::\exposid{index-cast}(pad)} is greater than zero. \item -otherwise \tcode{m(z...)} for a pack of integers \tcode{z} -that is a multidimensional index in \tcode{m.extents()} and -each element of \tcode{z} equals 0. +If \exposid{rank_} is greater than one, +then \tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\exposid{rank_} - 1))} +is representable as a value of type \tcode{index_type}. +\item +If \exposid{rank_} is greater than one, +then the product of +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\exposid{\linebreak rank_} - 1))} and +all values \tcode{ext.extent($k$)} +with $k$ in the range of \range{0}{\exposid{rank_} - 1} +is representable as a value of type \tcode{index_type}. +\item +If \tcode{padding_value} is not equal to \tcode{dynamic_extent}, +\tcode{padding_value} equals \tcode{extents_type::\linebreak \exposid{index-cast}(pad)}. \end{itemize} \pnum -Let \exposid{is-extents} be the exposition-only variable template -defined as follows: +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{ext}, and +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-rm2} with +\tcode{\exposid{LEAST-MULTIPLE-AT-LEAST}(pad, ext.extent(\exposid{rank_} - 1))}. +\end{itemdescr} + +\indexlibraryctor{layout_right_padded::mapping}% +\begin{itemdecl} +template + constexpr explicit(!is_convertible_v) + mapping(const layout_right::mapping& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\mandates +If \tcode{OtherExtents::rank()} is greater than 1, then \begin{codeblock} -template - constexpr bool @\exposid{is-extents}@ = false; // \expos -template - constexpr bool @\exposid{is-extents}@> = true; // \expos +(@\exposid{static-padding-stride}@ == dynamic_extent) || +(OtherExtents::static_extent(@\exposid{rank_}@ - 1) == dynamic_extent) || +(@\exposid{static-padding-stride}@ == OtherExtents::static_extent(@\exposid{rank_}@ - 1)) \end{codeblock} +is \tcode{true}. \pnum -Let \exposconcept{layout-mapping-alike} be the exposition-only concept -defined as follows: +\expects +\begin{itemize} +\item +If \tcode{\exposid{rank_} > 1} is \tcode{true} and +\tcode{padding_value == dynamic_extent} is \tcode{false}, then +\tcode{other.stride(\newline \exposid{rank_} - 2)} equals \begin{codeblock} -template -concept @\defexposconcept{layout-mapping-alike}@ = requires { // \expos - requires @\exposid{is-extents}@; - { M::is_always_strided() } -> @\libconcept{same_as}@; - { M::is_always_exhaustive() } -> @\libconcept{same_as}@; - { M::is_always_unique() } -> @\libconcept{same_as}@; - bool_constant::value; - bool_constant::value; - bool_constant::value; -}; +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extents().extent(rank_ - 1))) \end{codeblock} -\begin{note} -This concept checks that the functions -\tcode{M::is_always_strided()}, -\tcode{M::is_always_exhaustive()}, and -\tcode{M::is_always_unique()} exist, -are constant expressions, and -have a return type of \tcode{bool}. -\end{note} +and +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} -\rSec5[mdspan.layout.stride.cons]{Constructors} +\pnum +\effects +Equivalent to \tcode{mapping(other.extents())}. +\end{itemdescr} -\indexlibraryctor{layout_stride::mapping}% +\indexlibraryctor{layout_right_padded::mapping}% \begin{itemdecl} -constexpr mapping() noexcept; +template + constexpr explicit(rank_ > 0) + mapping(const layout_stride::mapping& other); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + \pnum \expects -\tcode{layout_right::mapping().required_span_size()} -is representable as a value of type \tcode{index_type}\iref{basic.fundamental}. +\begin{itemize} +\item +If \exposid{rank_} is greater than 1 and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{other.\linebreak stride(\exposid{rank_} - 2)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extents().extent(@\exposid{rank_}@ - 1))) +\end{codeblock} +\item +If \exposid{rank_} is greater than 0, +then other.stride(\exposid{rank_} - 1) equals 1. +\item +If \exposid{rank_} is greater than 2, +then for all $r$ in the range \range{0}{\exposid{rank_} - 2}, +\tcode{other.stride($r$)} equals +\begin{codeblock} +(other.extents().@\exposid{rev-prod-of-extents}@(r) / other.extents().extent(@\exposid{rank_}@ - 1)) * + other.stride(@\exposid{rank_}@ - 2) +\end{codeblock} +\item +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. +\end{itemize} \pnum \effects -Direct-non-list-initializes \exposid{extents_} with \tcode{extents_type()}, and -for all $d$ in the range \range{0}{\exposid{rank_}}, -direct-non-list-initializes \tcode{\exposid{strides_}[$d$]} with -\tcode{layout_right::mapping().stride($d$)}. +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}; and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-rm2} +with \tcode{other.stride(\exposid{rank_} - 2)}. +\end{itemize} \end{itemdescr} -\indexlibraryctor{layout_stride::mapping}% +\indexlibraryctor{layout_right_padded::mapping}% \begin{itemdecl} -template - constexpr mapping(const extents_type& e, span s) noexcept; -template - constexpr mapping(const extents_type& e, const array& s) noexcept; +template + constexpr explicit(@\seebelow@) + mapping(const LayoutRightPaddedMapping& other); \end{itemdecl} \begin{itemdescr} @@ -20577,47 +23971,65 @@ \constraints \begin{itemize} \item -\tcode{is_convertible_v} is \tcode{true}, and +\tcode{\exposid{is-layout-right-padded-mapping-of}} +is \tcode{true}. \item -\tcode{is_nothrow_constructible_v} is \tcode{true}. +\tcode{is_constructible_v} +is \tcode{true}. \end{itemize} +\pnum +\mandates +If \exposid{rank_} is greater than 1, then +\begin{codeblock} +padding_value == dynamic_extent || +LayoutRightPaddedMapping::padding_value == dynamic_extent || +padding_value == LayoutRightPaddedMapping::padding_value +\end{codeblock} +is \tcode{true}. + \pnum \expects \begin{itemize} \item -The result of converting \tcode{s[$i$]} to \tcode{index_type} -is greater than \tcode{0} -for all $i$ in the range $[0, \exposid{rank_})$. -\item -\tcode{\exposid{REQUIRED-SPAN-SIZE}(e, s)} is representable -as a value of type \tcode{index_type}\iref{basic.fundamental}. +If \exposid{rank_} is greater than 1 and +\tcode{padding_value} does not equal \tcode{dynamic_extent}, +then \tcode{other.\linebreak stride(\exposid{rank_} - 2)} equals +\begin{codeblock} +@\exposid{LEAST-MULTIPLE-AT-LEAST}@(padding_value, + extents_type::@\exposid{index-cast}@(other.extent(@\exposid{rank_}@ - 1))) +\end{codeblock} \item -If \exposid{rank_} is greater than 0, -then there exists a permutation $P$ of the integers -in the range $[0, \exposid{rank_})$, -such that \tcode{s[$p_i$] >= s[$p_{i-1}$] * e.extent(p$_{i-1}$)} is \tcode{true} -for all $i$ in the range $[1, \exposid{rank_})$, -where $p_i$ is the $i^\text{th}$ element of $P$. -\begin{note} -For \tcode{layout_stride}, -this condition is necessary and sufficient -for \tcode{is_unique()} to be \tcode{true}. -\end{note} +\tcode{other.required_span_size()} is representable as +a value of type \tcode{index_type}. \end{itemize} \pnum \effects -Direct-non-list-initializes \exposid{extents_} with \tcode{e}, and -for all $d$ in the range $[0, \exposid{rank_})$, -direct-non-list-initializes \tcode{strides_[$d$]} with \tcode{as_const(s[$d$])}. +\begin{itemize} +\item +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}; and +\item +if \exposid{rank_} is greater than one, +direct-non-list-initializes \exposid{stride-rm2} +with \tcode{other.stride(rank_ - 2)}. +\end{itemize} + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +@\exposid{rank_}@ > 1 && +(padding_value != dynamic_extent || + LayoutRightPaddedMapping::padding_value == dynamic_extent) +\end{codeblock} \end{itemdescr} -\indexlibraryctor{layout_stride::mapping}% +\indexlibraryctor{layout_right_padded::mapping}% \begin{itemdecl} -template +template constexpr explicit(@\seebelow@) - mapping(const StridedLayoutMapping& other) noexcept; + mapping(const LayoutLeftPaddedMapping& other) noexcept; \end{itemdecl} \begin{itemdescr} @@ -20625,50 +24037,53 @@ \constraints \begin{itemize} \item -\tcode{\exposconcept{layout-mapping-alike}} is satisfied. -\item -\tcode{is_constructible_v} is\\\tcode{true}. +\tcode{\exposid{is-layout-left-padded-mapping-of}} +is \tcode{true} or\newline +\tcode{\exposid{is-mapping-of}} +is \tcode{true}. \item -\tcode{StridedLayoutMapping::is_always_unique()} is \tcode{true}. +\exposid{rank_} equals zero or one. \item -\tcode{StridedLayoutMapping::is_always_strided()} is \tcode{true}. +\tcode{is_constructible_v}\newline +is \tcode{true}. \end{itemize} \pnum \expects -\begin{itemize} -\item -\tcode{StridedLayoutMapping} meets the layout mapping requirements\iref{mdspan.layout.reqmts}, -\item -\tcode{other.stride($r$) > 0} is \tcode{true} -for every rank index $r$ of \tcode{extents()}, -\item \tcode{other.required_span_size()} is representable as -a value of type \tcode{index_type}\iref{basic.fundamental}, and -\item -\tcode{\exposid{OFFSET}(other) == 0} is \tcode{true}. -\end{itemize} +a value of type \tcode{index_type}. \pnum \effects -Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}, and -for all $d$ in the range $[0, \exposid{rank_})$, -direct-non-list-initializes \tcode{\exposid{strides_}[$d$]} -with \tcode{other.stride($d$)}. +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. \pnum -Remarks: The expression inside \tcode{explicit} is equivalent to: +\remarks +The expression inside \tcode{explicit} is equivalent to: \begin{codeblock} -!(is_convertible_v && - (@\exposid{is-mapping-of}@ || - @\exposid{is-mapping-of}@ || - @\exposid{is-mapping-of}@)) +!is_convertible_v \end{codeblock} +\begin{note} +Neither the input mapping nor the mapping to be constructed +uses the padding stride in the rank-0 or rank-1 case, +so the padding stride affects neither the constraints nor the preconditions. +\end{note} \end{itemdescr} -\rSec5[mdspan.layout.stride.obs]{Observers} +\rSec5[mdspan.layout.rightpad.obs]{Observers} -\indexlibrarymember{required_span_size}{layout_stride::mapping}% +\indexlibrarymember{layout_right_padded::mapping}{strides}% +\begin{itemdecl} +constexpr array strides() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{array({stride(P_rank)...})}. +\end{itemdescr} + +\indexlibrarymember{layout_right_padded::mapping}{required_span_size}% \begin{itemdecl} constexpr index_type required_span_size() const noexcept; \end{itemdecl} @@ -20676,72 +24091,102 @@ \begin{itemdescr} \pnum \returns -\tcode{\exposid{REQUIRED-SPAN-SIZE}(extents(), \exposid{strides_})}. +\tcode{0} if the multidimensional index space \exposid{extents_} is empty, +otherwise \tcode{*this(((\exposid{extents_}(P_rank) - index_type(1))...)) + 1}. +\end{itemdescr} + +\indexlibrarymember{layout_right_padded::mapping}{operator()}% +\begin{itemdecl} +template +constexpr size_t operator()(Indices... idxs) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{sizeof...(Indices) == \exposid{rank_}} is \tcode{true}. +\item +\tcode{(is_convertible_v \&\& ...)} is \tcode{true}. +\item +\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{extents_type::\exposid{index-cast}(idxs)} is +a multidimensional index in \tcode{extents()}\iref{mdspan.overview}. + +\pnum +\returns +\tcode{((static_cast(idxs) * stride(P_rank)) + ... + 0)}. \end{itemdescr} -\indexlibrarymember{operator()}{layout_stride::mapping}% +\indexlibrarymember{layout_right_padded::mapping}{is_always_exhaustive}% \begin{itemdecl} -template - constexpr index_type operator()(Indices... i) const noexcept; +static constexpr bool is_always_exhaustive() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\constraints +\returns \begin{itemize} \item -\tcode{sizeof...(Indices) == \exposid{rank_}} is \tcode{true}, +If \exposid{rank_} equals zero or one, then \tcode{true}; \item -\tcode{(is_convertible_v \&\& ...)} is \tcode{true}, and +otherwise, +if neither \exposid{static-padding-stride} nor \exposid{last-static-extent} +equal \tcode{dynamic_extent}, +then \tcode{\exposid{static-padding-stride} == \exposid{last-static-extent}}; \item -\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}. +otherwise, \tcode{false}. \end{itemize} +\end{itemdescr} -\pnum -\expects -\tcode{extents_type::\exposid{index-cast}(i)} is -a multidimensional index in \exposid{extents_}\iref{mdspan.overview}. +\indexlibrarymember{layout_right_padded::mapping}{is_exhaustive}% +\begin{itemdecl} +constexpr bool is_exhaustive() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\effects -Let \tcode{P} be a parameter pack such that -\begin{codeblock} -is_same_v, index_sequence> -\end{codeblock} -is \tcode{true}. -Equivalent to: +\returns +\tcode{true} if \exposid{rank_} equals zero or one; +otherwise, \begin{codeblock} -return ((static_cast(i) * stride(P)) + ... + 0); +@\exposid{extents_}@.extent(@\exposid{rank_}@ - 1) == stride(@\exposid{rank_}@ - 2) \end{codeblock} \end{itemdescr} -\indexlibrarymember{is_exhaustive}{layout_stride::mapping}% \begin{itemdecl} -constexpr bool is_exhaustive() const noexcept; +constexpr index_type stride(rank_type r) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{r} is smaller than \exposid{rank_}. + \pnum \returns \begin{itemize} \item -\tcode{true} if \exposid{rank_} is 0. +If \tcode{r} equals \tcode{\exposid{rank_} - 1}: \tcode{1}; \item -Otherwise, \tcode{true} if there is -a permutation $P$ of the integers in the range $[0, \exposid{rank_})$ -such that \tcode{stride($p_0$)} equals 1, and -\tcode{stride($p_i$)} equals \tcode{stride($ p_{i-1}$) * extents().extent($p_{i-1}$)} -for $i$ in the range $[1, \exposid{rank_})$, -where $p_i$ is the $i^\text{th}$ element of $P$. +otherwise, if \tcode{r} equals \tcode{\exposid{rank_} - 2}: \exposid{stride-rm2}; \item -Otherwise, \tcode{false}. +otherwise, +the product of \exposid{stride-rm2} and +all values \tcode{extents_.extent($k$)} +with $k$ in the range of \range{r + 1}{\exposid{rank_} - 1}. \end{itemize} \end{itemdescr} -\indexlibrarymember{operator==}{layout_stride::mapping}% +\indexlibrarymember{layout_right_padded::mapping}{operator==}% \begin{itemdecl} -template - friend constexpr bool operator==(const mapping& x, const OtherMapping& y) noexcept; +template + friend constexpr bool operator==(const mapping& x, const LayoutRightPaddedMapping& y) noexcept; \end{itemdecl} \begin{itemdescr} @@ -20749,23 +24194,17 @@ \constraints \begin{itemize} \item -\tcode{\exposconcept{layout-mapping-alike}} is satisfied. -\item -\tcode{\exposid{rank_} == OtherMapping::extents_type::rank()} is \tcode{true}. +\tcode{\exposid{is-layout-right-padded-mapping-of}} +is \tcode{true}. \item -\tcode{OtherMapping::is_always_strided()} is \tcode{true}. +\tcode{LayoutRightPaddedMapping::extents_type::rank() == \exposid{rank_}} +is \tcode{true}. \end{itemize} -\pnum -\expects -\tcode{OtherMapping} meets the layout mapping requirements\iref{mdspan.layout.policy.reqmts}. - \pnum \returns -\tcode{true} if \tcode{x.extents() == y.extents()} is \tcode{true}, -\tcode{\exposid{OFFSET}(y) == 0} is \tcode{true}, and -each of \tcode{x.stride($r$) == y.stride($r$)} is \tcode{true} -for $r$ in the range $[0, \tcode{x.extents().rank()})$. +\tcode{true} if \tcode{x.extents() == y.extents()} is \tcode{true} and +\tcode{\exposid{rank_} < 2 || x.stride(\exposid{rank_} - 2) == y.stride(\exposid{rank_} - 2)} is \tcode{true}. Otherwise, \tcode{false}. \end{itemdescr} @@ -20785,7 +24224,7 @@ the accessor policy's \tcode{access} function produces a valid reference to an object. \pnum -In subclause \ref{mdspan.accessor.reqmts}, +In \ref{mdspan.accessor.reqmts}, \begin{itemize} \item @@ -21006,6 +24445,195 @@ Equivalent to: \tcode{return p + i;} \end{itemdescr} +\rSec4[mdspan.accessor.aligned]{Class template \tcode{aligned_accessor}} + +\rSec5[mdspan.accessor.aligned.overview]{Overview} + +\begin{codeblock} +namespace std { + template + struct @\libglobal{aligned_accessor}@ { + using offset_policy = default_accessor; + using element_type = ElementType; + using reference = ElementType&; + using data_handle_type = ElementType*; + + static constexpr size_t byte_alignment = ByteAlignment; + + constexpr aligned_accessor() noexcept = default; + template + constexpr aligned_accessor( + aligned_accessor) noexcept; + template + constexpr explicit aligned_accessor(default_accessor) noexcept; + + template + constexpr operator default_accessor() const noexcept; + + constexpr reference access(data_handle_type p, size_t i) const noexcept; + + constexpr typename offset_policy::data_handle_type offset( + data_handle_type p, size_t i) const noexcept; + }; +} +\end{codeblock} + +\pnum +\mandates +\begin{itemize} +\item \tcode{byte_alignment} is a power of two, and +\item \tcode{byte_alignment >= alignof(ElementType)} is \tcode{true}. +\end{itemize} + +\pnum +\tcode{aligned_accessor} meets the accessor policy requirements. + +\pnum +\tcode{ElementType} is required to be a complete object type +that is neither an abstract class type nor an array type. + +\pnum +Each specialization of \tcode{aligned_accessor} is +a trivially copyable type that models \libconcept{semiregular}. + +\pnum +\range{0}{$n$} is an accessible range +for an object \tcode{p} of type \tcode{data_handle_type} and +an object of type \tcode{aligned_accessor} if and only if +\begin{itemize} +\item +\range{p}{p + $n$} is a valid range, and, +\item +if $n$ is greater than zero, +then \tcode{is_sufficiently_aligned(p)} is \tcode{true}. +\end{itemize} + +\pnum +\begin{example} +The following function \tcode{compute} +uses \tcode{is_sufficiently_aligned} to check +whether a given \tcode{mdspan} with \tcode{default_accessor} has +a data handle with sufficient alignment +to be used with \tcode{aligned_accessor}. +If so, the function dispatches to +a function \tcode{compute_using_fourfold_overalignment} +that requires fourfold over-alignment of arrays, +but can therefore use hardware-specific instructions, +such as four-wide SIMD (Single Instruction Multiple Data) instructions. +Otherwise, \tcode{compute} dispatches to a +possibly less optimized function \tcode{compute_without_requiring_overalignment} +that has no over-alignment requirement. +\begin{codeblock} +void compute_using_fourfold_overalignment( + std::mdspan, std::layout_right, + std::aligned_accessor> x); + +void compute_without_requiring_overalignment( + std::mdspan, std::layout_right> x); + +void compute(std::mdspan> x) { + constexpr auto byte_alignment = 4 * sizeof(float); + auto accessor = std::aligned_accessor{}; + auto x_handle = x.data_handle(); + + if (std::is_sufficiently_aligned(x_handle)) { + compute_using_fourfold_overalignment(std::mdspan{x_handle, x.mapping(), accessor}); + } else { + compute_without_requiring_overalignment(x); + } +} +\end{codeblock} +\end{example} + +\rSec5[mdspan.accessor.aligned.members]{Members} + +\indexlibraryctor{aligned_accessor}% +\begin{itemdecl} +template + constexpr aligned_accessor(aligned_accessor) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v} +is \tcode{true}. +\item +\tcode{OtherByteAlignment >= byte_alignment} is \tcode{true}. +\end{itemize} + +\pnum +\effects +None. +\end{itemdescr} + +\indexlibraryctor{aligned_accessor}% +\begin{itemdecl} +template + constexpr explicit aligned_accessor(default_accessor) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_convertible_v} +is \tcode{true}. + +\pnum +\effects +None. +\end{itemdescr} + +\indexlibrarymember{access}{aligned_accessor}% +\begin{itemdecl} +constexpr reference access(data_handle_type p, size_t i) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\range{0}{i + 1} is an accessible range for \tcode{p} and \tcode{*this}. + +\pnum +\effects +Equivalent to: \tcode{return assume_aligned(p)[i];} +\end{itemdescr} + +\indexlibrarymember{operator default_accessor}{aligned_accessor}% +\begin{itemdecl} +template + constexpr operator default_accessor() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_convertible_v} +is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return \{\};} +\end{itemdescr} + +\indexlibrarymember{offset}{aligned_accessor}% +\begin{itemdecl} +constexpr typename offset_policy::data_handle_type + offset(data_handle_type p, size_t i) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\range{0}{i + 1} is an accessible range for \tcode{p} and \tcode{*this}. + +\pnum +\effects +Equivalent to: \tcode{return assume_aligned(p) + i;} +\end{itemdescr} + \rSec3[mdspan.mdspan]{Class template \tcode{mdspan}} \rSec4[mdspan.mdspan.overview]{Overview} @@ -21071,8 +24699,18 @@ template constexpr reference operator[](const array& indices) const; + template + constexpr reference + at(OtherIndexTypes... indices) const; // freestanding-deleted + template + constexpr reference + at(span indices) const; // freestanding-deleted + template + constexpr reference + at(const array& indices) const; // freestanding-deleted + constexpr size_type size() const noexcept; - [[nodiscard]] constexpr bool empty() const noexcept; + constexpr bool empty() const noexcept; friend constexpr void swap(mdspan& x, mdspan& y) noexcept; @@ -21093,7 +24731,7 @@ constexpr bool is_exhaustive() const { return @\exposid{map_}@.is_exhaustive(); } constexpr bool is_strided() const - { return @\exposid{map_.}@is_strided(); } + { return @\exposid{map_}@.is_strided(); } constexpr index_type stride(rank_type r) const { return @\exposid{map_}@.stride(r); } @@ -21116,7 +24754,7 @@ template requires ((is_convertible_v && ...) && sizeof...(Integrals) > 0) explicit mdspan(ElementType*, Integrals...) - -> mdspan>; + -> mdspan...>>; template mdspan(ElementType*, span) @@ -21417,44 +25055,112 @@ \pnum \expects -\begin{itemize} -\item -For each rank index \tcode{r} of \tcode{extents_type}, -\tcode{static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r)} -is \tcode{true}. -\item $[0, \tcode{\exposid{map_}.required_span_size()})$ is an accessible range of \exposid{ptr_} and \exposid{acc_} for values of \exposid{ptr_}, \exposid{map_}, and \exposid{acc_} after the invocation of this constructor. + +\pnum +\hardexpects +For each rank index \tcode{r} of \tcode{extents_type}, +\tcode{static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r)} +is \tcode{true}. + +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{ptr_} with \tcode{other.\exposid{ptr_}}, +\item +direct-non-list-initializes \exposid{map_} with \tcode{other.\exposid{map_}}, and +\item +direct-non-list-initializes \exposid{acc_} with \tcode{other.\exposid{acc_}}. +\end{itemize} + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!is_convertible_v&, mapping_type> +|| !is_convertible_v +\end{codeblock} +\end{itemdescr} + +\rSec4[mdspan.mdspan.members]{Members} + +\indexlibrarymember{operator[]}{mdspan}% +\begin{itemdecl} +template + constexpr reference operator[](OtherIndexTypes... indices) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{(is_convertible_v \&\& ...)} is \tcode{true}, +\item +\tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}, and +\item +\tcode{sizeof...(OtherIndexTypes) == rank()} is \tcode{true}. \end{itemize} \pnum -\effects +Let \tcode{I} be \tcode{extents_type::\exposid{index-cast}(std::move(indices))}. + +\pnum +\hardexpects +\tcode{I} is a multidimensional index in \tcode{extents()}. +\begin{note} +This implies that +\tcode{\exposid{map_}(I) < \exposid{map_}.required_span_size()} +is \tcode{true}. +\end{note} + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{acc_}@.access(@\exposid{ptr_}@, @\exposid{map_}@(static_cast(std::move(indices))...)); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator[]}{mdspan}% +\begin{itemdecl} +template + constexpr reference operator[](span indices) const; +template + constexpr reference operator[](const array& indices) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints \begin{itemize} \item -Direct-non-list-initializes \exposid{ptr_} with \tcode{other.\exposid{ptr_}}, -\item -direct-non-list-initializes \exposid{map_} with \tcode{other.\exposid{map_}}, and +\tcode{is_convertible_v} is \tcode{true}, and \item -direct-non-list-initializes \exposid{acc_} with \tcode{other.\exposid{acc_}}. +\tcode{is_nothrow_constructible_v} is \tcode{true}. \end{itemize} \pnum -\remarks -The expression inside \tcode{explicit} is equivalent to: +\effects +Let \tcode{P} be a parameter pack such that \begin{codeblock} -!is_convertible_v&, mapping_type> -|| !is_convertible_v +is_same_v, index_sequence> +\end{codeblock} +is \tcode{true}. +Equivalent to: +\begin{codeblock} +return operator[](extents_type::@\exposid{index-cast}@(as_const(indices[P]))...); \end{codeblock} \end{itemdescr} -\rSec4[mdspan.mdspan.members]{Members} - -\indexlibrarymember{operator[]}{mdspan}% +\indexlibrarymember{at}{mdspan}% \begin{itemdecl} template - constexpr reference operator[](OtherIndexTypes... indices) const; + constexpr reference at(OtherIndexTypes... indices) const; \end{itemdecl} \begin{itemdescr} @@ -21466,35 +25172,27 @@ \item \tcode{(is_nothrow_constructible_v \&\& ...)} is \tcode{true}, and \item -\tcode{sizeof...(OtherIndexTypes) == rank()} is \tcode{true}. +\tcode{sizeof...(OtherIndexTypes) == rank()} is \tcode{true}. \end{itemize} \pnum Let \tcode{I} be \tcode{extents_type::\exposid{index-cast}(std::move(indices))}. \pnum -\expects -\tcode{I} is a multidimensional index in \tcode{extents()}. -\begin{note} -This implies that -\tcode{\exposid{map_}(I) < \exposid{map_}.required_span_size()} -is \tcode{true}. -\end{note} +\returns +\tcode{(*this)[I...]}. \pnum -\effects -Equivalent to: -\begin{codeblock} -return @\exposid{acc_}@.access(@\exposid{ptr_}@, @\exposid{map_}@(static_cast(std::move(indices))...)); -\end{codeblock} +\throws +\tcode{out_of_range} if \tcode{I} is not a multidimensional index in \tcode{extents()}. \end{itemdescr} -\indexlibrarymember{operator[]}{mdspan}% +\indexlibrarymember{at}{mdspan}% \begin{itemdecl} template - constexpr reference operator[](span indices) const; + constexpr reference at(span indices) const; template - constexpr reference operator[](const array& indices) const; + constexpr reference at(const array& indices) const; \end{itemdecl} \begin{itemdescr} @@ -21516,7 +25214,7 @@ is \tcode{true}. Equivalent to: \begin{codeblock} -return operator[](extents_type::@\exposid{index-cast}@(as_const(indices[P]))...); +return at(extents_type::@\exposid{index-cast}@(as_const(indices[P]))...); \end{codeblock} \end{itemdescr} @@ -21538,7 +25236,7 @@ \indexlibrarymember{empty}{mdspan}% \begin{itemdecl} -[[nodiscard]] constexpr bool empty() const noexcept; +constexpr bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -21565,9 +25263,9 @@ \end{codeblock} \end{itemdescr} -\rSec3[mdspan.submdspan]{\tcode{submdspan}} +\rSec3[mdspan.sub]{\tcode{submdspan}} -\rSec4[mdspan.submdspan.overview]{Overview} +\rSec4[mdspan.sub.overview]{Overview} \pnum The \tcode{submdspan} facilities create a new \tcode{mdspan} @@ -21576,7 +25274,7 @@ the \tcode{SliceSpecifier} arguments. \pnum -For each function defined in subclause \ref{mdspan.submdspan} that +For each function defined in \ref{mdspan.sub} that takes a parameter pack named \tcode{slices} as an argument: \begin{itemize} @@ -21610,7 +25308,7 @@ \end{itemize} \end{itemize} -\rSec4[mdspan.submdspan.strided.slice]{\tcode{strided_slice}} +\rSec4[mdspan.sub.strided.slice]{\tcode{strided_slice}} \pnum \tcode{strided_slice} represents a set of @@ -21649,7 +25347,7 @@ Indices are selected from the half-open interval \range{1}{1 + 10}. \end{note} -\rSec4[mdspan.submdspan.submdspan.mapping.result]{\tcode{submdspan_mapping_result}} +\rSec4[mdspan.sub.map.result]{\tcode{submdspan_mapping_result}} \pnum Specializations of \tcode{submdspan_mapping_result} @@ -21675,7 +25373,7 @@ \tcode{LayoutMapping} shall meet the layout mapping requirements\iref{mdspan.layout.policy.reqmts}. -\rSec4[mdspan.submdspan.helpers]{Exposition-only helpers} +\rSec4[mdspan.sub.helpers]{Exposition-only helpers} \indexlibraryglobal{\exposid{de-ice}}% \indexlibraryglobal{\exposid{first_}}% @@ -21798,7 +25496,7 @@ \end{itemize} \end{itemdescr} -\rSec4[mdspan.submdspan.extents]{\tcode{submdspan_extents} function} +\rSec4[mdspan.sub.extents]{\tcode{submdspan_extents} function} \indexlibraryglobal{submdspan_extents}% \begin{itemdecl} @@ -21905,45 +25603,30 @@ \end{itemize} \end{itemdescr} -\rSec4[mdspan.submdspan.mapping]{Layout specializations of \tcode{submdspan_mapping}} - -\indexlibrarymemberexpos{layout_stride::mapping}{submdspan-mapping-impl}% -\indexlibrarymemberexpos{layout_left::mapping}{submdspan-mapping-impl}% -\indexlibrarymemberexpos{layout_right::mapping}{submdspan-mapping-impl}% -\begin{itemdecl} -template - template - constexpr auto layout_left::mapping::@\exposid{submdspan-mapping-impl}@( // \expos - SliceSpecifiers... slices) const -> @\seebelow@; - -template - template - constexpr auto layout_right::mapping::@\exposid{submdspan-mapping-impl}@( // \expos - SliceSpecifiers... slices) const -> @\seebelow@; +\rSec4[mdspan.sub.map]{Specializations of \tcode{submdspan_mapping}} -template - template - constexpr auto layout_stride::mapping::@\exposid{submdspan-mapping-impl}@( // \expos - SliceSpecifiers... slices) const -> @\seebelow@; -\end{itemdecl} +\rSec5[mdspan.sub.map.common]{Common} -\begin{itemdescr} \pnum -Let \tcode{index_type} be \tcode{typename Extents::index_type}. +The following elements apply to all functions in \ref{mdspan.sub.map}. \pnum \constraints -\tcode{sizeof...(slices)} equals \tcode{Extents::rank()}. +\tcode{sizeof...(slices)} equals \tcode{extents_type::rank()}. \pnum \mandates For each rank index $k$ of \tcode{extents()}, exactly one of the following is true: \begin{itemize} -\item $S_k$ models \tcode{\libconcept{convertible_to}}, -\item $S_k$ models \tcode{\exposconcept{index-pair-like}}, -\item \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}, or -\item $S_k$ is a specialization of \tcode{strided_slice}. +\item +$S_k$ models \tcode{\libconcept{convertible_to}}, +\item +$S_k$ models \tcode{\exposconcept{index-pair-like}}, +\item +\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}, or +\item +$S_k$ is a specialization of \tcode{strided_slice}. \end{itemize} \pnum @@ -21952,106 +25635,389 @@ all of the following are \tcode{true}: \begin{itemize} \item -if $S_k$ is a specialization of \tcode{strided_slice} - \begin{itemize} - \item $\tcode{$s_k$.extent} = 0$, or - \item $\tcode{$s_k$.stride} > 0$ - \end{itemize} +if $S_k$ is a specialization of \tcode{strided_slice}, +\tcode{$s_k$.extent} is equal to zero or +\tcode{$s_k$.stride} is greater than zero; and \item -$0 \le \tcode{\exposid{first_}(slices...)} \\ -\hphantom{0 } \le \tcode{\exposid{last_}<$k$>(extents(), slices...)} \\ -\hphantom{0 } \le \tcode{extents().extent($k$)}$ +$0 \leq \tcode{\exposid{first_}(slices...)} \\ +\hphantom{0 } \leq \tcode{\exposid{last_}<$k$>(extents(), slices...)} \\ +\hphantom{0 } \leq \tcode{extents().extent($k$)}$ \end{itemize} \pnum -Let \tcode{sub_ext} be the result of -\tcode{submdspan_extents(extents(), slices...)} and -let \tcode{SubExtents} be \tcode{decltype(sub_ext)}. +Let \tcode{sub_ext} be +the result of \tcode{submdspan_extents(extents(), slices...)} and +let \tcode{SubExtents} be \tcode{decl\-type(sub_ext)}. \pnum Let \tcode{sub_strides} be -an \tcode{array} such that -for each rank index $k$ of \tcode{extents()} -for which \tcode{\placeholder{map-rank}[$k$]} is not \tcode{dynamic_extent}, -\tcode{sub_strides[\placeholder{map-rank}[\linebreak{}$k$]]} equals: - +an \tcode{array} +such that for each rank index $k$ of \tcode{extents()} +for which \tcode{\exposid{map-rank}[$k$]} is not \tcode{dynamic_extent}, +\tcode{sub_strides[\exposid{map-rank}[$k$]]} equals: \begin{itemize} \item -\tcode{stride($k$) * \exposid{de-ice}($s_k$.stride)} +\tcode{stride(k) * \exposid{de-ice}($s_k$.stride)} if $S_k$ is a specialization of \tcode{strided_slice} and -\tcode{$s_k$.stride < $s_k$.extent}; - +\tcode{$s_k$.stride < $s_k$.\linebreak extent} is \tcode{true}; \item -otherwise, -\tcode{stride($k$)}. +otherwise, \tcode{stride($k$)}. \end{itemize} \pnum -Let \tcode{P} be a parameter pack such that -\tcode{is_same_v, index_sequence<\linebreak{}P...>>} +Let \tcode{P} be a parameter pack +such that \tcode{is_same_v, index_sequence>} is \tcode{true}. \pnum -Let \tcode{offset} be a value of type \tcode{size_t} -equal to \tcode{(*this)(\exposid{first_}(slices...)...)}. +If \tcode{\exposid{first_}(slices...)} +equals \tcode{extents().extent($k$)} +for any rank index $k$ of \tcode{extents()}, then +let \tcode{offset} be a value of type \tcode{size_t} equal to +\tcode{(*this).required_span_size()}. +Otherwise, +let \tcode{offset} be a value of type \tcode{size_t} equal to +\tcode{(*this)(\exposid{first_}(slices...)...)}. + +\pnum +Given a layout mapping type \tcode{M}, a type \tcode{S} is a +\defnadjx{unit-stride}{slice for \tcode{M}}{slice} if +\begin{itemize} +\item \tcode{S} is a specialization of \tcode{strided_slice} +where \tcode{S::stride_type} models \exposconcept{integral-constant-like} +and \tcode{S::stride_type::value} equals \tcode{1}, +\item \tcode{S} models \tcode{\exposconcept{index-pair-like}}, or +\item \tcode{is_convertible_v} is \tcode{true}. +\end{itemize} + +\rSec5[mdspan.sub.map.left]{\tcode{layout_left} specialization of \tcode{submdspan_mapping}} + +\indexlibrarymemberexpos{layout_left::mapping}{submdspan-mapping-impl}% +\begin{itemdecl} +template +template +constexpr auto layout_left::mapping::@\exposid{submdspan-mapping-impl}@( + SliceSpecifiers... slices) const -> @\seebelow@; +\end{itemdecl} +\begin{itemdescr} \pnum \returns \begin{itemize} \item \tcode{submdspan_mapping_result\{*this, 0\}}, if \tcode{Extents::rank() == 0} is \tcode{true}; - +\item +otherwise, +\tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}}, +if \tcode{SubEx\-tents::rank() == 0} is \tcode{true}; \item otherwise, \tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}}, if \begin{itemize} \item - \tcode{layout_type} is \tcode{layout_left}; and - \item for each $k$ in the range \range{0}{SubExtents::rank() - 1)}, \tcode{is_convertible_v<$S_k$, full_ext\-ent_t>} is \tcode{true}; and \item for $k$ equal to \tcode{SubExtents::rank() - 1}, - $S_k$ models \tcode{\exposconcept{index-pair-like}} or - \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; + $S_k$ is a unit-stride slice for \tcode{mapping}; \end{itemize} \begin{note} If the above conditions are true, all $S_k$ with $k$ larger than \tcode{SubExtents::rank() - 1} are convertible to \tcode{index_type}. \end{note} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_left_padded::mapping(sub_ext, stride(@$u$@ + 1)), + offset} +\end{codeblock} +if for a value $u$ for which $u+1$ is +the smallest value $p$ larger than zero +for which $S_p$ is a unit-stride slice for \tcode{mapping}, +the following conditions are met: +\begin{itemize} +\item +$S_0$ is a unit-stride slice for \tcode{mapping}; and +\item +for each $k$ in the range \range{$u$ + 1}{$u$ + SubExtents::rank() - 1}, +\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and +\item +for $k$ equal to \tcode{$u$ + SubExtents::rank() - 1}, +$S_k$ is a unit-stride slice for \tcode{mapping}; +\end{itemize} +and where \tcode{S_static} is: +\begin{itemize} +\item +\tcode{dynamic_extent}, +if \tcode{static_extent($k$)} is \tcode{dynamic_extent} +for any $k$ in the range \range{0}{$u$ + 1}, +\item +otherwise, the product of all values +\tcode{static_extent($k$)} for $k$ in the range \range{0}{$u$ + 1}; +\end{itemize} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec5[mdspan.sub.map.right]{\tcode{layout_right} specialization of \tcode{submdspan_mapping}} + +\indexlibrarymemberexpos{layout_right::mapping}{submdspan-mapping-impl}% +\begin{itemdecl} +template +template +constexpr auto layout_right::mapping::@\exposid{submdspan-mapping-impl}@( + SliceSpecifiers... slices) const -> @\seebelow@; +\end{itemdecl} +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +\tcode{submdspan_mapping_result\{*this, 0\}}, +if \tcode{Extents::rank() == 0} is \tcode{true}; \item otherwise, \tcode{submdspan_mapping_result\{layout_right::mapping(sub_ext), offset\}}, +if \tcode{Sub\-Extents::rank() == 0} is \tcode{true}; +\item +otherwise, +\tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}}, if \begin{itemize} \item - \tcode{layout_type} is \tcode{layout_right}; and - \item - for each $k$ in the range - \range{Extents::rank() - SubExtents::rank() + 1}{Extents::rank()}, + for each $k$ in the range \range{\exposid{rank_} - SubExtents::rank() + 1}{\exposid{rank_}}, \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and \item - for $k$ equal to \tcode{Extents::rank() - SubExtents::rank()}, - $S_k$ models \tcode{\exposconcept{index-pair-like}} or - \tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; + for $k$ equal to \exposid{_rank} - \tcode{SubExtents::rank()}, + $S_k$ is a unit-stride slice for \tcode{mapping}; \end{itemize} \begin{note} If the above conditions are true, -all $S_k$ with $k < \tcode{Extents::rank() - SubExtents::rank()}$ +all $S_k$ with $k < \tcode{\exposid{_rank} - SubExtents::rank()}$ are convertible to \tcode{index_type}. \end{note} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_right_padded::mapping(sub_ext, + stride(@\exposid{rank_}@ - @$u$@ - 2)), offset} +\end{codeblock} +if for a value $u$ for which $\exposid{rank_} - u - 2$ is +the largest value $p$ smaller than \tcode{\exposid{rank_} - 1} +for which $S_p$ is a unit-stride slice for \tcode{mapping}, +the following conditions are met: +\begin{itemize} +\item +for $k$ equal to \tcode{\exposid{rank_} - 1}, +$S_k$ is a unit-stride slice for \tcode{mapping}; and +\item +for each $k$ in the range +\range{\exposid{rank_} - SubExtents::rank() - $u$ + 1}{\exposid{rank_} - $u$ - 1}, +\tcode{is_con\-vertible_v<$S_k$, full_extent_t>} is \tcode{true}; and +\item +for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$},\newline +$S_k$ is a unit-stride slice for \tcode{mapping}; +\end{itemize} +and where \tcode{S_static} is: +\begin{itemize} +\item +\tcode{dynamic_extent}, +if \tcode{static_extent($k$)} is \tcode{dynamic_extent} +for any $k$ in the range \range{\exposid{rank_} - $u$ - 1}{\exposid{rank_}}, +\item +otherwise, the product of all values +\tcode{static_extent($k$)} +for $k$ in the range \range{\exposid{rank_} - $u$ - 1}{\exposid{rank_}}; +\end{itemize} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec5[mdspan.sub.map.stride]{\tcode{layout_stride} specialization of \tcode{submdspan_mapping}} + +\indexlibrarymemberexpos{layout_stride::mapping}{submdspan-mapping-impl}% +\begin{itemdecl} +template +template +constexpr auto layout_stride::mapping::@\exposid{submdspan-mapping-impl}@( + SliceSpecifiers... slices) const -> @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +\tcode{submdspan_mapping_result\{*this, 0\}}, +if \tcode{Extents::rank() == 0} is \tcode{true}; +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec5[mdspan.sub.map.leftpad]{\tcode{layout_left_padded} specialization of \tcode{submdspan_mapping}} + +\indexlibrarymemberexpos{layout_left_padded::mapping}{submdspan-mapping-impl}% +\begin{itemdecl} +template +template +constexpr auto layout_left_padded::mapping::@\exposid{submdspan-mapping-impl}@( + SliceSpecifiers... slices) const -> @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +\tcode{submdspan_mapping_result\{*this, 0\}}, +if \tcode{Extents::rank() == 0} is \tcode{true}; +\item +otherwise, +\tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}}, +if \tcode{\exposid{rank_} == 1} is \tcode{true} or +\tcode{SubExtents::rank() == 0} is \tcode{true}; +\item +otherwise, +\tcode{submdspan_mapping_result\{layout_left::mapping(sub_ext), offset\}}, +if +\begin{itemize} +\item +\tcode{SubExtents::rank() == 1} is \tcode{true} and +\item +$S_0$ is a unit-stride slice for \tcode{mapping}; +\end{itemize} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_left_padded::mapping(sub_ext, stride(@$u$@ + 1)), + offset} +\end{codeblock} +if for a value $u$ +for which \tcode{$u$ + 1} is the smallest value $p$ larger than zero +for which $S_p$ is a unit-stride slice for \tcode{mapping}, +the following conditions are met: +\begin{itemize} +\item +$S_0$ is a unit-stride slice for \tcode{mapping}; and +\item +for each $k$ in the range \range{$u$ + 1}{$u$ + SubExtents::rank() - 1}, +\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and +\item +for $k$ equal to \tcode{$u$ + SubExtents::rank() - 1}, +$S_k$ is a unit-stride slice for \tcode{mapping}; +\end{itemize} +where \tcode{S_static} is: +\begin{itemize} +\item +\tcode{dynamic_extent}, +if \exposid{static-padding-stride} is \tcode{dynamic_extent} or +\tcode{static_extent($k$)} is \tcode{dynamic_extent} +for any $k$ in the range \range{1}{$u$ + 1}, +\item +otherwise, the product of \exposid{static-padding-stride} and +all values \tcode{static_extent($k$)} for $k$ in the range \range{1}{$u$ + 1}; +\end{itemize} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec5[mdspan.sub.map.rightpad]{\tcode{layout_right_padded} specialization of \tcode{submdspan_mapping}} + +\indexlibrarymemberexpos{layout_right_padded::mapping}{submdspan-mapping-impl}% +\begin{itemdecl} +template +template +constexpr auto layout_right_padded::mapping::submdspan-mapping-impl( + SliceSpecifiers... slices) const -> @\seebelow@; +\end{itemdecl} +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +\tcode{submdspan_mapping_result\{*this, 0\}}, +if \tcode{\exposid{rank_} == 0} is \tcode{true}; +\item +otherwise, +\tcode{submdspan_mapping_result\{layout_right::mapping(sub_ext), offset\}},\newline +if \tcode{\exposid{rank_} == 1} is \tcode{true} or +\tcode{SubExtents::rank() == 0} is \tcode{true}; +\item +otherwise, +\tcode{submdspan_mapping_result\{layout_right::mapping(sub_ext), offset\}}, +if +\begin{itemize} +\item +\tcode{SubExtents::rank() == 1} is \tcode{true} and +\item +for $k$ equal to \tcode{\exposid{rank_} - 1}, +$S_k$ is a unit-stride slice for \tcode{mapping}; +\end{itemize} +\item +otherwise, +\begin{codeblock} +submdspan_mapping_result{layout_right_padded::mapping(sub_ext, + stride(@\exposid{rank_}@ - @$u$@ - 2)), offset} +\end{codeblock} +if for a value $u$ +for which \tcode{\exposid{rank_} - $u$ - 2} +is the largest value p smaller than \tcode{\exposid{rank_} - 1} +for which $S_p$ is a unit-stride slice for \tcode{mapping}, +the following conditions are met: +\begin{itemize} +\item +for $k$ equal to \tcode{\exposid{rank_} - 1}, +$S_k$ is a unit-stride slice for \tcode{mapping}; and +\item +for each $k$ in the range +\range{\exposid{rank_} - SubExtents::rank() - $u$ + 1}{\exposid{rank_} - $u$ - 1)}, +\tcode{is_convertible_v<$S_k$, full_extent_t>} is \tcode{true}; and +\item +for $k$ equal to \tcode{\exposid{rank_} - SubExtents::rank() - $u$},\newline +$S_k$ is a unit-stride slice for \tcode{mapping}; +\end{itemize} +and where \tcode{S_static} is: +\begin{itemize} +\item +\tcode{dynamic_extent} +if \exposid{static-padding-stride} is \tcode{dynamic_extent} or +for any $k$ in the range \range{\exposid{rank_} - $u$ - 1}{\exposid{rank_} - 1} +\tcode{static_extent($k$)} is \tcode{dynamic_extent}, +\item +otherwise, the product of \exposid{static-padding-stride} and +all values \tcode{static_extent($k$)} +with $k$ in the range \range{\exposid{rank_} - $u$ - 1}{\exposid{rank_} - 1}; +\end{itemize} \item otherwise, -\tcode{submdspan_mapping_result\{layout_stride::mapping(sub_ext, sub_strides),\linebreak{}offset\}}. +\begin{codeblock} +submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset} +\end{codeblock} \end{itemize} \end{itemdescr} -\rSec4[mdspan.submdspan.submdspan]{\tcode{submdspan} function template} +\rSec4[mdspan.sub.sub]{\tcode{submdspan} function template} \indexlibraryglobal{submdspan}% \begin{itemdecl} @@ -22151,9 +26117,9 @@ \effects Equivalent to: \begin{codeblock} -auto sub_map_offset = submdspan_mapping(src.mapping(), slices...); -return mdspan(src.accessor().offset(src.data(), sub_map_offset.offset), - sub_map_offset.mapping, +auto sub_map_result = submdspan_mapping(src.mapping(), slices...); +return mdspan(src.accessor().offset(src.data(), sub_map_result.offset), + sub_map_result.mapping, AccessorPolicy::offset_policy(src.accessor())); \end{codeblock} \end{itemdescr} diff --git a/source/cover-reg.tex b/source/cover-reg.tex index 91e968e150..5923fce26d 100644 --- a/source/cover-reg.tex +++ b/source/cover-reg.tex @@ -59,15 +59,16 @@ \thispagestyle{cpppage} -\fbox{% -\begin{minipage}{\copyboxwidth} +\vspace*{\fill} + \vspace{1ex} -\begin{center} -\textbf{Copyright notice} -\end{center} +\raisebox{-1ex}{\includegraphics{assets/iso-logo-caution.png}}\qquad{\Large{\textbf{COPYRIGHT PROTECTED DOCUMENT}}} \vspace{2ex} +\isocopyright + All rights reserved. Unless otherwise specified, +or required in the context of its implementation, no part of this publication may be reproduced or utilized otherwise in any form or by any means, electronic or mechanical, including photocopying, @@ -75,17 +76,18 @@ without prior written permission. Permission can be requested from either ISO at the address below -or ISO's member body in the country of the requester.\\\\ +or ISO's member body in the country of the requester. \begin{indented} \microtypesetup{activate=false}% ISO copyright office\\ -Case postale 56, CH-1211 Geneva 20\\ -\rlap{Tel.}\hphantom{Fax} + 41 22 749 01 11\\ -Fax + 41 22 749 09 47\\ -E-mail \texttt{copyright@iso.org}\\ -Web \url{www.iso.org} +CP 401 \textbullet{} Ch.\ de Blandonnet 8\\ +CH-1214 Vernier, Geneva\\ +Phone: +41 22 749 01 11\\ +Email: \texttt{copyright@iso.org}\\ +Website: \url{www.iso.org} \end{indented} -\end{minipage}} + +Published in Switzerland \newpage diff --git a/source/declarations.tex b/source/declarations.tex index 6a7b78e9a5..502fa0fa29 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -1,5 +1,5 @@ %!TEX root = std.tex -\rSec0[dcl.dcl]{Declarations}% +\rSec0[dcl]{Declarations}% \indextext{declaration|(} \gramSec[gram.dcl]{Declarations} @@ -13,8 +13,7 @@ the form \begin{bnf} \nontermdef{declaration-seq}\br - declaration\br - declaration-seq declaration + declaration \opt{declaration-seq} \end{bnf} \begin{bnf} @@ -28,6 +27,7 @@ block-declaration\br nodeclspec-function-declaration\br function-definition\br + friend-type-declaration\br template-declaration\br deduction-guide\br linkage-specification\br @@ -53,6 +53,7 @@ using-enum-declaration\br using-directive\br static_assert-declaration\br + consteval-block-declaration\br alias-declaration\br opaque-enum-declaration \end{bnf} @@ -67,11 +68,27 @@ \keyword{using} identifier \opt{attribute-specifier-seq} \terminal{=} defining-type-id \terminal{;} \end{bnf} +\begin{bnf} +\nontermdef{sb-identifier}\br + \opt{\terminal{...}} identifier \opt{attribute-specifier-seq} +\end{bnf} + +\begin{bnf} +\nontermdef{sb-identifier-list}\br + sb-identifier\br + sb-identifier-list \terminal{,} sb-identifier +\end{bnf} + +\begin{bnf} +\nontermdef{structured-binding-declaration}\br + \opt{attribute-specifier-seq} decl-specifier-seq \opt{ref-qualifier} \terminal{[} sb-identifier-list \terminal{]} +\end{bnf} + \begin{bnf} \nontermdef{simple-declaration}\br decl-specifier-seq \opt{init-declarator-list} \terminal{;}\br attribute-specifier-seq decl-specifier-seq init-declarator-list \terminal{;}\br - \opt{attribute-specifier-seq} decl-specifier-seq \opt{ref-qualifier} \terminal{[} identifier-list \terminal{]} initializer \terminal{;} + structured-binding-declaration initializer \terminal{;} \end{bnf} \begin{bnf} @@ -86,6 +103,11 @@ \keyword{static_assert} \terminal{(} constant-expression \terminal{,} static_assert-message \terminal{)} \terminal{;} \end{bnf} +\begin{bnf} +\nontermdef{consteval-block-declaration}\br + \keyword{consteval} compound-statement +\end{bnf} + \begin{bnf} \nontermdef{empty-declaration}\br \terminal{;} @@ -112,11 +134,16 @@ \indextext{scope}% Certain declarations contain one or more scopes\iref{basic.scope.scope}. Unless otherwise stated, utterances in -\ref{dcl.dcl} about components in, of, or contained by a +\ref{dcl} about components in, of, or contained by a declaration or subcomponent thereof refer only to those components of the declaration that are \emph{not} nested within scopes nested within the declaration. +\pnum +If a \grammarterm{name-declaration} matches +the syntactic requirements of \grammarterm{friend-type-declaration}, +it is a \grammarterm{friend-type-declaration}. + \pnum A \grammarterm{simple-declaration} or @@ -186,14 +213,21 @@ \end{example} \pnum -A \grammarterm{simple-declaration} with an \grammarterm{identifier-list} is called +A \grammarterm{simple-declaration} or a \grammarterm{condition} +with a \grammarterm{structured-binding-declaration} is called a \defn{structured binding declaration}\iref{dcl.struct.bind}. Each \grammarterm{decl-specifier} in the \grammarterm{decl-specifier-seq} shall be +\tcode{constexpr}, +\tcode{constinit}, \tcode{static}, \tcode{thread_local}, \tcode{auto}\iref{dcl.spec.auto}, or a \grammarterm{cv-qualifier}. +The declaration shall contain at most one \grammarterm{sb-identifier} +whose \grammarterm{identifier} is preceded by an ellipsis. +If the declaration contains any such \grammarterm{sb-identifier}, +it shall declare a templated entity\iref{temp.pre}. \begin{example} \begin{codeblock} template concept C = true; @@ -205,16 +239,19 @@ of the form ``\tcode{=} \grammarterm{assignment-expression}'', of the form ``\tcode{\{} \grammarterm{assignment-expression} \tcode{\}}'', or -of the form ``\tcode{(} \grammarterm{assignment-expression} \tcode{)}'', -where the -\grammarterm{assignment-expression} is of array or non-union class type. +of the form ``\tcode{(} \grammarterm{assignment-expression} \tcode{)}''. +If the \grammarterm{structured-binding-declaration} appears as +a \grammarterm{condition}, +the \grammarterm{assignment-expression} shall be of non-union class type. +Otherwise, +the \grammarterm{assignment-expression} shall be of +array or non-union class type. \pnum If the \grammarterm{decl-specifier-seq} contains the \keyword{typedef} specifier, the declaration is a \defnx{typedef declaration}{declaration!typedef} and each \grammarterm{declarator-id} -is declared to be a \grammarterm{typedef-name}, synonymous with its -associated type\iref{dcl.typedef}. +is declared to be a \grammarterm{typedef-name}\iref{dcl.typedef}. \begin{note} Such a \grammarterm{declarator-id} is an \grammarterm{identifier}\iref{class.conv.fct}. @@ -234,16 +271,29 @@ \end{codeblock} \end{example} +\pnum +\indextext{initialization!definition and}% +An object definition causes +storage of appropriate size and alignment to be reserved and +any appropriate initialization\iref{dcl.init} to be done. + \pnum \indextext{definition!declaration as}% Syntactic components beyond those found in the general form of \grammarterm{simple-declaration} are added to a function declaration to make a -\grammarterm{function-definition}. An object declaration, however, is also -a definition unless it contains the \keyword{extern} specifier and has no -initializer\iref{basic.def}. -\indextext{initialization!definition and}% -An object definition causes storage of appropriate size and alignment to be reserved and -any appropriate initialization\iref{dcl.init} to be done. +\grammarterm{function-definition}. +A token sequence starting with \tcode{\{} or \tcode{=} +is treated as a \grammarterm{function-body}\iref{dcl.fct.def.general} +if the type of the \grammarterm{declarator-id}\iref{dcl.meaning.general} +is a function type, and +is otherwise +treated as a \grammarterm{brace-or-equal-initializer}\iref{dcl.init.general}. +\begin{note} +If the declaration acquires a function type through template instantiation, +the program is ill-formed; see \ref{temp.spec.general}. +The function type of a function definition +cannot be specified with a \grammarterm{typedef-name}\iref{dcl.fct}. +\end{note} \pnum A \grammarterm{nodeclspec-function-declaration} shall declare a @@ -337,6 +387,35 @@ \end{codeblock} \end{example} +\pnum +For a \grammarterm{consteval-block-declaration} $D$, +the expression $E$ corresponding to $D$ is: +\begin{codeblock} + [] -> void static consteval @\grammarterm{compound-statement}@ () +\end{codeblock} +$E$ shall be a constant expression\iref{expr.const}. +\begin{note} +The evaluation of the expression +corresponding to a \grammarterm{consteval-block-declaration}\iref{lex.phases} +can produce injected declarations as side effects. +\end{note} +\begin{example} +\begin{codeblock} +struct S; +consteval { + std::meta::define_aggregate(^^S, {}); // OK + + template + struct X { }; // error: local templates are not allowed + + template + concept C = true; // error: local concepts are not allowed + + return; // OK +} +\end{codeblock} +\end{example} + \pnum An \grammarterm{empty-declaration} has no effect. @@ -378,9 +457,9 @@ same type. \pnum -Each \grammarterm{decl-specifier} -shall appear at most once in a complete \grammarterm{decl-specifier-seq}, -except that \tcode{long} may appear twice. +At most one of each of the \grammarterm{decl-specifier}s +\keyword{friend}, \keyword{typedef}, or \keyword{inline} +shall appear in a \grammarterm{decl-specifier-seq}. At most one of the \keyword{constexpr}, \keyword{consteval}, and \keyword{constinit} keywords shall appear in a \grammarterm{decl-specifier-seq}. @@ -611,6 +690,9 @@ A \grammarterm{function-specifier} can be used only in a function declaration. +At most one \grammarterm{explicit-specifier} and +at most one \keyword{virtual} keyword shall appear in +a \grammarterm{decl-specifier-seq}. \begin{bnf} \nontermdef{function-specifier}\br @@ -660,9 +742,8 @@ \pnum Declarations containing the \grammarterm{decl-specifier} \keyword{typedef} -declare identifiers that can be used later for naming -fundamental\iref{basic.fundamental} or compound\iref{basic.compound} -types. The \keyword{typedef} specifier shall not be +declare \defnadjx{type}{aliases}{alias}. +The \keyword{typedef} specifier shall not be combined in a \grammarterm{decl-specifier-seq} with any other kind of specifier except a \grammarterm{defining-type-specifier}, and it shall not be used in the \grammarterm{decl-specifier-seq} of a @@ -680,14 +761,12 @@ A name declared with the \keyword{typedef} specifier becomes a \grammarterm{typedef-name}. -A \grammarterm{typedef-name} names +The underlying entity of the type alias is the type associated with the \grammarterm{identifier}\iref{dcl.decl} -or \grammarterm{simple-template-id}\iref{temp.pre}; +or \grammarterm{simple-template-id}\iref{temp.pre}. \indextext{declaration!typedef@\tcode{typedef} as type}% \indextext{equivalence!type}% -\indextext{synonym!type name as}% -a \grammarterm{typedef-name} is thus a synonym for another type. A -\grammarterm{typedef-name} does not introduce a new type the way a class +A \grammarterm{typedef-name} does not introduce a new type the way a class declaration\iref{class.name} or enum declaration\iref{dcl.enum} does. \begin{example} After @@ -704,14 +783,14 @@ \end{example} \pnum -A \grammarterm{typedef-name} can also be introduced by an +A type alias can also be declared by an \grammarterm{alias-declaration}. The \grammarterm{identifier} following the -\tcode{using} keyword is not looked up; it becomes a \grammarterm{typedef-name} +\tcode{using} keyword is not looked up; +it becomes the \grammarterm{typedef-name} of a type alias and the optional \grammarterm{attribute-specifier-seq} following the -\grammarterm{identifier} appertains to that \grammarterm{typedef-name}. -Such a \grammarterm{typedef-name} has the same -semantics as if it were introduced by the \keyword{typedef} specifier. In -particular, it does not define a new type. +\grammarterm{identifier} appertains to that type alias. +Such a type alias has the same +semantics as if it were introduced by the \keyword{typedef} specifier. \begin{example} \begin{codeblock} using handler_t = void (*)(int); @@ -730,7 +809,7 @@ \indextext{class name!\idxcode{typedef}}% A \grammarterm{simple-template-id} is only a \grammarterm{typedef-name} if its \grammarterm{template-name} names -an alias template or a template \grammarterm{template-parameter}. +an alias template or a type template template parameter. \begin{note} A \grammarterm{simple-template-id} that names a class template specialization is a \grammarterm{class-name}\iref{class.name}. @@ -807,7 +886,8 @@ \pnum The \keyword{constexpr} specifier shall be applied only to -the definition of a variable or variable template or +the definition of a variable or variable template, +a structured binding declaration, or the declaration of a function or function template. The \keyword{consteval} specifier shall be applied only to the declaration of a function or function template. @@ -866,15 +946,9 @@ \pnum \indextext{specifier!\idxcode{constexpr}!function}% \indextext{constexpr function}% -A function is \defn{constexpr-suitable} if: -\begin{itemize} -\item -it is not a coroutine\iref{dcl.fct.def.coroutine}, and +A function is \defn{constexpr-suitable} if +it is not a coroutine\iref{dcl.fct.def.coroutine}. -\item -if the function is a constructor or destructor, -its class does not have any virtual base classes. -\end{itemize} Except for instantiated constexpr functions, non-templated constexpr functions shall be constexpr-suitable. @@ -952,9 +1026,7 @@ Such an object shall have literal type and shall be initialized. -In any \keyword{constexpr} variable declaration, -the full-expression of the initialization -shall be a constant expression\iref{expr.const}. +A \keyword{constexpr} variable shall be constant-initializable\iref{expr.const}. A \keyword{constexpr} variable that is an object, as well as any temporary to which a \keyword{constexpr} reference is bound, shall have constant destruction. @@ -965,6 +1037,16 @@ }; constexpr pixel ur = { 1294, 1024 }; // OK constexpr pixel origin; // error: initializer missing + +namespace N { + void f() { + int x; + constexpr int& ar = x; // OK + static constexpr int& sr = x; // error: \tcode{x} is not constexpr-representable + // at the point indicated below + } + // immediate scope here is that of \tcode{N} +} \end{codeblock} \end{example} @@ -973,7 +1055,12 @@ \pnum The \keyword{constinit} specifier shall be applied only -to a declaration of a variable with static or thread storage duration. +to a declaration of a variable with static or thread storage duration +or to a structured binding declaration\iref{dcl.struct.bind}. +\begin{note} +A structured binding declaration introduces a uniquely named variable, +to which the \tcode{constinit} specifier applies. +\end{note} If the specifier is applied to any declaration of a variable, it shall be applied to the initializing declaration. No diagnostic is required if no \keyword{constinit} declaration @@ -1215,7 +1302,7 @@ \pnum \indextext{const object!undefined change to}% -Any attempt to modify\iref{expr.ass,expr.post.incr,expr.pre.incr} a +Any attempt to modify\iref{expr.assign,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} @@ -1315,7 +1402,8 @@ \begin{bnf} \nontermdef{computed-type-specifier}\br decltype-specifier\br - pack-index-specifier + pack-index-specifier\br + splice-type-specifier \end{bnf} \pnum @@ -1350,12 +1438,21 @@ is a placeholder for a type to be deduced\iref{dcl.spec.auto}. \indextext{deduction!class template arguments}% -A \grammarterm{type-specifier} of the form -\opt{\keyword{typename}} \opt{\grammarterm{nested-name-specifier}} \grammarterm{template-name} -is a placeholder for -a deduced class type\iref{dcl.type.class.deduct}. -The \grammarterm{nested-name-specifier}, if any, shall be non-dependent and -the \grammarterm{template-name} shall name a deducible template. +A \grammarterm{type-specifier} is a placeholder for +a deduced class type\iref{dcl.type.class.deduct} if either +\begin{itemize} +\item +it is of the form +\opt{\keyword{typename}} \opt{\grammarterm{nested-name-specifier}} \grammarterm{template-name} or +\item +it is of the form \opt{\keyword{typename}} \grammarterm{splice-specifier} and +the \grammarterm{splice-specifier} designates +a class template or alias template. +\end{itemize} +The \grammarterm{nested-name-specifier} or \grammarterm{splice-specifier}, +if any, shall be non-dependent and +the \grammarterm{template-name} or \grammarterm{splice-specifier} +shall designate a deducible template. A \defnadj{deducible}{template} is either a class template or is an alias template whose \grammarterm{defining-type-id} is of the form @@ -1393,6 +1490,7 @@ \grammarterm{placeholder-type-specifier} & the type as defined in~\ref{dcl.spec.auto}\\ \grammarterm{template-name} & the type as defined in~\ref{dcl.type.class.deduct}\\ +\grammarterm{splice-type-specifier} & the type as defined in~\ref{dcl.type.splice}\\ \tcode{char} & ``\tcode{char}'' \\ \tcode{unsigned char} & ``\tcode{unsigned char}'' \\ \tcode{signed char} & ``\tcode{signed char}'' \\ @@ -1490,8 +1588,10 @@ \indextext{name!elaborated!\idxcode{enum}}% If an \grammarterm{elaborated-type-specifier} is the sole constituent of a declaration, the declaration is ill-formed unless it is an explicit -specialization\iref{temp.expl.spec}, an explicit -instantiation\iref{temp.explicit} or it has one of the following +specialization\iref{temp.expl.spec}, +a partial specialization\iref{temp.spec.partial}, +an explicit +instantiation\iref{temp.explicit}, or it has one of the following forms: \begin{ncsimplebnf} @@ -1505,7 +1605,7 @@ The second case shall appear only in an \grammarterm{explicit-specialization}\iref{temp.expl.spec} or in a \grammarterm{template-declaration} -(where it declares a partial specialization\iref{temp.decls}). +(where it declares a partial specialization). The \grammarterm{attribute-specifier-seq}, if any, appertains to the class or template being declared. @@ -1520,30 +1620,34 @@ The target scope of $E$ is the nearest enclosing namespace or block scope. \pnum -If an \grammarterm{elaborated-type-specifier} appears with -the \keyword{friend} specifier as an entire \grammarterm{member-declaration}, -the \grammarterm{member-declaration} shall have one of the following forms: +A \grammarterm{friend-type-specifier} +that is an \grammarterm{elaborated-type-specifier} +shall have one of the following forms: \begin{ncsimplebnf} -\keyword{friend} class-key \opt{nested-name-specifier} identifier \terminal{;}\br -\keyword{friend} class-key simple-template-id \terminal{;}\br -\keyword{friend} class-key nested-name-specifier \opt{\keyword{template}} simple-template-id \terminal{;} +class-key \opt{nested-name-specifier} identifier\br +class-key simple-template-id\br +class-key nested-name-specifier \opt{\keyword{template}} simple-template-id \end{ncsimplebnf} Any unqualified lookup for the \grammarterm{identifier} (in the first case) -does not consider scopes that contain the target scope; no name is bound. +does not consider scopes that contain +the nearest enclosing namespace or block scope; no name is bound. \begin{note} A \grammarterm{using-directive} in the target scope is ignored if it refers to a namespace not contained by that scope. -\ref{basic.lookup.elab} describes how name lookup proceeds -in an \grammarterm{elaborated-type-specifier}. \end{note} \pnum \begin{note} +\ref{basic.lookup.elab} describes how name lookup proceeds +in an \grammarterm{elaborated-type-specifier}. An \grammarterm{elaborated-type-specifier} can be used to refer to a previously declared \grammarterm{class-name} or \grammarterm{enum-name} even if the name has been hidden by a non-type declaration. \end{note} + +\pnum If the \grammarterm{identifier} or \grammarterm{simple-template-id} +in an \grammarterm{elaborated-type-specifier} resolves to a \grammarterm{class-name} or \grammarterm{enum-name}, the \grammarterm{elaborated-type-specifier} introduces it into the declaration the same way a @@ -1558,12 +1662,12 @@ \begin{codeblock} friend class T; \end{codeblock} -is ill-formed. However, the similar declaration \tcode{friend T;} is well-formed.\iref{class.friend}. +is ill-formed. However, the similar declaration \tcode{friend T;} is well-formed\iref{class.friend}. \end{note} \pnum The \grammarterm{class-key} or \keyword{enum} keyword -present in the +present in an \grammarterm{elaborated-type-specifier} shall agree in kind with the declaration to which the name in the \grammarterm{elaborated-type-specifier} refers. This rule also applies to @@ -1603,8 +1707,8 @@ the specification of the structured binding declaration; \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} +naming a constant template parameter\iref{temp.param}, +\tcode{decltype($E$)} is the type of the template parameter after performing any necessary type deduction\iref{dcl.spec.auto,dcl.type.class.deduct}; @@ -1615,6 +1719,10 @@ type of the entity named by $E$. If there is no such entity, the program is ill-formed; +\item otherwise, if $E$ is an unparenthesized \grammarterm{splice-expression}, +\tcode{decltype($E$)} is the type of the entity, object, or value +designated by the \grammarterm{splice-specifier} of $E$; + \item otherwise, if $E$ is an xvalue, \tcode{decltype($E$)} is \tcode{T\&\&}, where \tcode{T} is the type of $E$; @@ -1638,11 +1746,13 @@ decltype(i) x2; // type is \tcode{int} decltype(a->x) x3; // type is \tcode{double} decltype((a->x)) x4 = x3; // type is \tcode{const double\&} +decltype([:^^x1:]) x5 = 18; // type is \tcode{const int\&\&} +decltype(([:^^x1:])) x6 = 19; // type is \tcode{const int\&} void f() { [](auto ...pack) { - decltype(pack...[0]) x5; // type is \tcode{int} - decltype((pack...[0])) x6; // type is \tcode{int\&} + decltype(pack...[0]) x7; // type is \tcode{int} + decltype((pack...[0])) x8; // type is \tcode{int\&} }(0); } \end{codeblock} @@ -1716,20 +1826,33 @@ \pnum A \grammarterm{placeholder-type-specifier} -designates a placeholder type that will be replaced later by deduction +designates a placeholder type that will be replaced later, +typically by deduction from an initializer. \pnum -A \grammarterm{placeholder-type-specifier} of the form -\opt{\grammarterm{type-constraint}} \keyword{auto} -can be used as a \grammarterm{decl-specifier} of -the \grammarterm{decl-specifier-seq} of -a \grammarterm{parameter-declaration} of -a function declaration or \grammarterm{lambda-expression} and, -if it is not the \keyword{auto} \grammarterm{type-specifier} -introducing a \grammarterm{trailing-return-type} (see below), +The type of a \grammarterm{parameter-declaration} of a +\begin{itemize} + \item function declaration\iref{dcl.fct}, + \item \grammarterm{lambda-expression}\iref{expr.prim.lambda}, or + \item \grammarterm{template-parameter}\iref{temp.param} +\end{itemize} +can be declared using +a \grammarterm{placeholder-type-specifier} of the form +\opt{\grammarterm{type-constraint}} \keyword{auto}. +The placeholder type shall appear +as one of the \grammarterm{decl-specifier}{s} in +the \grammarterm{decl-specifier-seq} or +as one of the \grammarterm{type-specifier}{s} in +a \grammarterm{trailing-return-type} +that specifies the type that replaces such +a \grammarterm{decl-specifier} (see below); +the placeholder type is a \defn{generic parameter type placeholder} -of the function declaration or \grammarterm{lambda-expression}. +of the +function declaration, +\grammarterm{lambda-expression}, or +\grammarterm{template-parameter}, respectively. \begin{note} Having a generic parameter type placeholder signifies that the function is @@ -1738,15 +1861,15 @@ \end{note} \pnum -A placeholder type can appear with a function declarator in the -\grammarterm{decl-specifier-seq}, \grammarterm{type-specifier-seq}, -\grammarterm{conversion-function-id}, or \grammarterm{trailing-return-type}, -in any context where such a declarator is valid. If the function declarator -includes a \grammarterm{trailing-return-type}\iref{dcl.fct}, that -\grammarterm{trailing-return-type} specifies -the declared return type of the function. Otherwise, the function declarator -shall declare a function. If the declared return type of the -function contains a placeholder type, the return type of the function is +A placeholder type can appear in +the \grammarterm{decl-specifier-seq} for a function declarator +that includes a \grammarterm{trailing-return-type}\iref{dcl.fct}. + +\pnum +A placeholder type can appear in +the \grammarterm{decl-specifier-seq} or \grammarterm{type-specifier-seq} +in the declared return type of a function declarator that declares a function; +the return type of the function is deduced from non-discarded \tcode{return} statements, if any, in the body of the function\iref{stmt.if}. @@ -1756,9 +1879,11 @@ This use is allowed in an initializing declaration\iref{dcl.init} of a variable. The placeholder type shall appear as one of the -\grammarterm{decl-specifier}{s} in the -\grammarterm{decl-specifier-seq} and the -\grammarterm{decl-specifier-seq} +\grammarterm{decl-specifier}{s} in the \grammarterm{decl-specifier-seq} +or as one of the +\grammarterm{type-specifier}{s} in a \grammarterm{trailing-return-type} +that specifies the type that replaces such a \grammarterm{decl-specifier}; +the \grammarterm{decl-specifier-seq} shall be followed by one or more \grammarterm{declarator}{s}, each of which shall @@ -1772,6 +1897,7 @@ 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 (*fp)() -> auto = f; // OK auto h(); // OK, \tcode{h}'s return type will be deduced when it is defined \end{codeblock} \end{example} @@ -1781,13 +1907,19 @@ \pnum A placeholder type can also be used -in the \grammarterm{type-specifier-seq} in -the \grammarterm{new-type-id} or \grammarterm{type-id} of a -\grammarterm{new-expression}\iref{expr.new} -and as a \grammarterm{decl-specifier} -of the \grammarterm{parameter-declaration}{'s} -\grammarterm{decl-specifier-seq} -in a \grammarterm{template-parameter}\iref{temp.param}. +in the \grammarterm{type-specifier-seq} of +the \grammarterm{new-type-id} or +in the \grammarterm{type-id} of a +\grammarterm{new-expression}\iref{expr.new}. +In such a \grammarterm{type-id}, +the placeholder type shall appear +as one of the \grammarterm{type-specifier}{s} in +the \grammarterm{type-specifier-seq} or +as one of the \grammarterm{type-specifier}{s} in +a \grammarterm{trailing-return-type} +that specifies the type that replaces such a \grammarterm{type-specifier}. + +\pnum The \tcode{auto} \grammarterm{type-specifier} can also be used as the \grammarterm{simple-type-specifier} in an explicit type conversion (functional notation)\iref{expr.type.conv}. @@ -1860,6 +1992,20 @@ \end{codeblock} \end{example} +\pnum +A result binding never has +an undeduced placeholder type\iref{dcl.contract.res}. +\begin{example} +\begin{codeblock} +auto f() + post(r : r == 7) // OK +{ + return 7; +} +\end{codeblock} +\end{example} + + \pnum Return type deduction for a templated function with a placeholder in its @@ -2016,9 +2162,9 @@ and $E$ is the \grammarterm{assignment-expression}. \end{itemize} \item -For a non-type template parameter declared with a type +For a constant template parameter declared with a type that contains a placeholder type, -\tcode{T} is the declared type of the non-type template parameter +\tcode{T} is the declared type of the constant template parameter and $E$ is the corresponding template argument. \end{itemize} @@ -2035,7 +2181,7 @@ shall precede\iref{basic.lookup.general} the \grammarterm{placeholder-type-specifier}. Obtain \tcode{P} from -\tcode{T} by replacing the occurrences of +\tcode{T} by replacing the occurrence of \opt{\grammarterm{type-constraint}} \keyword{auto} either with a new invented type template parameter \tcode{U} or, if the initialization is copy-list-initialization, with @@ -2162,6 +2308,59 @@ container e{5, 6}; // error: \tcode{int} is not an iterator \end{codeblock} \end{example} + +\rSec3[dcl.type.splice]{Type splicing} + +\begin{bnf} +\nontermdef{splice-type-specifier}\br + \opt{\keyword{typename}} splice-specifier\br + \opt{\keyword{typename}} splice-specialization-specifier +\end{bnf} + +\pnum +A \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} +immediately followed by \tcode{::} +is never interpreted as part of a \grammarterm{splice-type-specifier}. +A \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} +not preceded by \keyword{typename} +is only interpreted as a \grammarterm{splice-type-specifier} +within a type-only context\iref{temp.res.general}. +\begin{example} +\begin{codeblock} +template void tfn() { + typename [:R:]::type m; // OK, \keyword{typename} applies to the qualified name +} + +struct S { using type = int; }; +void fn() { + [:^^S::type:] *var; // error: \tcode{[:\caret\caret S::type:]} is an expression + typename [:^^S::type:] *var; // OK, declares variable with type \tcode{int*} +} + +using alias = [:^^S::type:]; // OK, type-only context +\end{codeblock} +\end{example} + +\pnum +For a \grammarterm{splice-type-specifier} of the form +\opt{\keyword{typename}} \grammarterm{splice-specifier}, +the \grammarterm{splice-specifier} shall designate +a type, a class template, or an alias template. +The \grammarterm{splice-type-specifier} designates +the same entity as the \grammarterm{splice-specifier}. + +\pnum +For a \grammarterm{splice-type-specifier} of the form +\opt{\keyword{typename}} \grammarterm{splice-specialization-specifier}, +the \grammarterm{splice-specifier} of +the \grammarterm{splice-specialization-specifier} +shall designate a template \tcode{T} +that is either a class template or an alias template. +The \grammarterm{splice-type-specifier} designates +the specialization of \tcode{T} corresponding to +the template argument list of the \grammarterm{splice-specialization-specifier}. \indextext{specifier|)}% \rSec1[dcl.decl]{Declarators}% @@ -2192,8 +2391,8 @@ \begin{bnf} \nontermdef{init-declarator}\br - declarator \opt{initializer}\br - declarator requires-clause + declarator initializer\br + declarator \opt{requires-clause} \opt{function-contract-specifier-seq} \end{bnf} \pnum @@ -2285,6 +2484,12 @@ \end{codeblock} \end{example} +\pnum +The optional \grammarterm{function-contract-specifier-seq}\iref{dcl.contract.func} +in an \grammarterm{init-declarator} +shall be present only if +the \grammarterm{declarator} declares a function. + \pnum Declarators have the syntax @@ -2320,7 +2525,7 @@ \end{bnf} \begin{bnf} -\microtypesetup{protrusion=false}\obeyspaces +\microtypesetup{protrusion=false} \nontermdef{ptr-operator}\br \terminal{*} \opt{attribute-specifier-seq} \opt{cv-qualifier-seq}\br \terminal{\&} \opt{attribute-specifier-seq}\br @@ -2917,7 +3122,7 @@ \end{example} \pnum -See also~\ref{expr.ass} and~\ref{dcl.init}. +See also~\ref{expr.assign} and~\ref{dcl.init}. \pnum \begin{note} @@ -3069,16 +3274,46 @@ specifier\iref{dcl.stc}, is a class member\iref{class.mem} declaration within a class definition, or is the declaration of a parameter or a return type\iref{dcl.fct}; see~\ref{basic.def}. -A reference shall be initialized to refer to a valid object or function. + +\pnum +Attempting to bind a reference to a function where +the converted initializer is a glvalue whose +type is not call-compatible\iref{expr.call} +with the type of the function's definition +results in undefined behavior. +Attempting to bind a reference to an object where +the converted initializer is a glvalue through which +the object is not type-accessible\iref{basic.lval} +results in undefined behavior. \begin{note} \indextext{reference!null}% -In particular, a null reference cannot exist in a well-defined program, -because the only way to create such a reference would be to bind it to -the ``object'' obtained by indirection through a null pointer, -which causes undefined behavior. +The object designated by such a glvalue can be +outside its lifetime\iref{basic.life}. +Because a null pointer value or a pointer past the end of an object +does not point to an object, +a reference in a well-defined program cannot refer to such things; +see~\ref{expr.unary.op}. As described in~\ref{class.bit}, a reference cannot be bound directly to a bit-field. \end{note} +The behavior of an evaluation of a reference\iref{expr.prim.id, expr.ref} that +does not happen after\iref{intro.races} the initialization of the reference +is undefined. +\begin{example} +\begin{codeblock} +int &f(int&); +int &g(); +extern int &ir3; +int *ip = 0; +int &ir1 = *ip; // undefined behavior: null pointer +int &ir2 = f(ir3); // undefined behavior: \tcode{ir3} not yet initialized +int &ir3 = g(); +int &ir4 = f(ir4); // undefined behavior: \tcode{ir4} used in its own initializer + +char x alignas(int); +int &ir5 = *reinterpret_cast(&x); // undefined behavior: initializer refers to char object +\end{codeblock} +\end{example} \pnum \indextext{reference collapsing}% @@ -3136,7 +3371,7 @@ \end{ncsimplebnf} and the \grammarterm{nested-name-specifier} -denotes a class, +designates a class, and the type of the contained \grammarterm{declarator-id} in the declaration \tcode{T} \tcode{D1} @@ -3149,6 +3384,7 @@ \tcode{T}''. The optional \grammarterm{attribute-specifier-seq}\iref{dcl.attr.grammar} appertains to the pointer-to-member. +The \grammarterm{nested-name-specifier} shall not designate an anonymous union. \pnum \begin{example} @@ -3329,8 +3565,10 @@ and the type of the array is ``array of \tcode{N} \tcode{U}''. \pnum -Furthermore, if there is a reachable declaration of the entity that inhabits the same -scope in which the bound was specified, an omitted array bound is taken to +Furthermore, if there is a reachable declaration of the entity +that specifies a bound and +has the same host scope\iref{basic.scope.scope}, +an omitted array bound is taken to be the same as in that earlier declaration, and similarly for the definition of a static data member of a class. \begin{example} @@ -3347,6 +3585,9 @@ extern int x[]; int i = sizeof(x); // error: incomplete object type } + +namespace A { extern int z[3]; } +int A::z[] = {}; // OK, defines an array of 3 elements \end{codeblock} \end{example} @@ -3436,60 +3677,44 @@ \tcode{T} \tcode{D} where +\tcode{T} may be empty and \tcode{D} has the form \begin{ncsimplebnf} \terminal{D1} \terminal{(} parameter-declaration-clause \terminal{)} \opt{cv-qualifier-seq}\br -\bnfindent\opt{ref-qualifier} \opt{noexcept-specifier} \opt{attribute-specifier-seq} +\bnfindent\opt{ref-qualifier} \opt{noexcept-specifier} \opt{attribute-specifier-seq} \opt{trailing-return-type} \end{ncsimplebnf} -and the type of the contained +a \placeholder{derived-declarator-type-list} is determined as follows: +\begin{itemize} +\item +If the \grammarterm{unqualified-id} of the \grammarterm{declarator-id} +is a \grammarterm{conversion-function-id}, +the \placeholder{derived-declarator-type-list} is empty. + +\item +Otherwise, the \placeholder{derived-declarator-type-list} is as appears in +the type ``\placeholder{derived-declarator-type-list} \tcode{T}'' +of the contained \grammarterm{declarator-id} in the declaration \tcode{T} -\tcode{D1} -is -``\placeholder{derived-declarator-type-list} -\tcode{T}'', -the type of the -\grammarterm{declarator-id} -in -\tcode{D} -is -``\placeholder{derived-declarator-type-list} -\opt{\keyword{noexcept}} -function of parameter-type-list -\opt{\grammarterm{cv-qualifier-seq}} \opt{\grammarterm{ref-qualifier}} -returning \tcode{T}'', where +\tcode{D1}. +\end{itemize} +The declared return type \tcode{U} of the function type +is determined as follows: \begin{itemize} \item -the parameter-type-list is derived from -the \grammarterm{parameter-declaration-clause} as described below and +If the \grammarterm{trailing-return-type} is present, +\tcode{T} shall be the single \grammarterm{type-specifier} \keyword{auto}, and +\tcode{U} is the type specified by the \grammarterm{trailing-return-type}. + \item -the optional \keyword{noexcept} is present if and only if -the exception specification\iref{except.spec} is non-throwing. -\end{itemize} -The optional \grammarterm{attribute-specifier-seq} -appertains to the function type. +Otherwise, if the declaration declares a conversion function, +see~\ref{class.conv.fct}. -\pnum -In a declaration -\tcode{T} -\tcode{D} -where -\tcode{D} -has the form -\begin{ncsimplebnf} -\terminal{D1} \terminal{(} parameter-declaration-clause \terminal{)} \opt{cv-qualifier-seq}\br -\bnfindent\opt{ref-qualifier} \opt{noexcept-specifier} \opt{attribute-specifier-seq} trailing-return-type -\end{ncsimplebnf} -and the type of the contained -\grammarterm{declarator-id} -in the declaration -\tcode{T} -\tcode{D1} -is -``\placeholder{derived-declarator-type-list} \tcode{T}'', -\tcode{T} shall be the single \grammarterm{type-specifier} \keyword{auto}. +\item +Otherwise, \tcode{U} is \tcode{T}. +\end{itemize} The type of the \grammarterm{declarator-id} in @@ -3503,28 +3728,26 @@ \begin{itemize} \item the parameter-type-list is derived from -the \grammarterm{parameter-declaration-clause} as described below, -\item -\tcode{U} is the type specified by the \grammarterm{trailing-return-type}, and +the \grammarterm{parameter-declaration-clause} as described below and \item the optional \keyword{noexcept} is present if and only if -the exception specification is non-throwing. +the exception specification\iref{except.spec} is non-throwing. \end{itemize} -The optional \grammarterm{attribute-specifier-seq} -appertains to the function type. - -\pnum -\indextext{type!function}% -A type of either form is a \term{function type}.% +Such a type is a \defnadj{function}{type}. \begin{footnote} As indicated by syntax, cv-qualifiers are a significant component in function return types. \end{footnote} +The optional \grammarterm{attribute-specifier-seq} +appertains to the function type. +\pnum \indextext{declaration!function}% \begin{bnf} \nontermdef{parameter-declaration-clause}\br - \opt{parameter-declaration-list} \opt{\terminal{...}}\br - parameter-declaration-list \terminal{,} \terminal{...} + \terminal{...}\br + \opt{parameter-declaration-list}\br + parameter-declaration-list \terminal{,} \terminal{...}\br + parameter-declaration-list \terminal{...} \end{bnf} \begin{bnf} @@ -3560,7 +3783,7 @@ If the \grammarterm{parameter-declaration-clause} is empty, the function takes no arguments. -A parameter list consisting of a single unnamed parameter of +A parameter list consisting of a single unnamed non-object parameter of non-dependent type \keyword{void} is equivalent to an empty parameter list. \indextext{parameter!\idxcode{void}}% @@ -3580,9 +3803,13 @@ argument and are not function parameter packs. Where syntactically correct and where ``\tcode{...}'' is not part of an \grammarterm{abstract-declarator}, -``\tcode{, ...}'' +``\tcode{...}'' is synonymous with -``\tcode{...}''. +``\tcode{, ...}''. +A \grammarterm{parameter-declaration-clause} +of the form +\grammarterm{parameter-declaration-list} \tcode{...} +is deprecated\iref{depr.ellipsis.comma}. \begin{example} The declaration \begin{codeblock} @@ -3652,11 +3879,15 @@ a \grammarterm{parameter-declaration} with a \keyword{this} specifier. An explicit-object-parameter-declaration shall appear only as the first \grammarterm{parameter-declaration} of -a \grammarterm{parameter-declaration-list} of either: +a \grammarterm{parameter-declaration-list} of one of: \begin{itemize} \item -a \grammarterm{member-declarator} -that declares a member function\iref{class.mem}, or +a declaration of +a member function or member function template\iref{class.mem}, or +\item +an explicit instantiation\iref{temp.explicit} or +explicit specialization\iref{temp.expl.spec} of +a templated member function, or \item a \grammarterm{lambda-declarator}\iref{expr.prim.lambda}. \end{itemize} @@ -3709,7 +3940,7 @@ \pnum A function type with a \grammarterm{cv-qualifier-seq} or a -\grammarterm{ref-qualifier} (including a type named by +\grammarterm{ref-qualifier} (including a type denoted by \grammarterm{typedef-name}\iref{dcl.typedef,temp.param}) shall appear only as: \begin{itemize} @@ -3721,19 +3952,22 @@ or \grammarterm{alias-declaration}, \item the \grammarterm{type-id} in the default argument of a -\grammarterm{type-parameter}\iref{temp.param}, or +\grammarterm{type-parameter}\iref{temp.param}, \item the \grammarterm{type-id} of a \grammarterm{template-argument} for a -\grammarterm{type-parameter}\iref{temp.arg.type}. +\grammarterm{type-parameter}\iref{temp.arg.type}, or + +\item the operand of a \grammarterm{reflect-expression}\iref{expr.reflect}. \end{itemize} \begin{example} \begin{codeblock} typedef int FIC(int) const; -FIC f; // error: does not declare a member function +FIC f; // error: does not declare a member function struct S { - FIC f; // OK + FIC f; // OK }; -FIC S::*pm = &S::f; // OK +FIC S::*pm = &S::f; // OK +constexpr std::meta::info yeti = ^^void(int) const &; // OK \end{codeblock} \end{example} @@ -3911,7 +4145,7 @@ An abbreviated function template is equivalent to a function template\iref{temp.fct} whose \grammarterm{template-parameter-list} includes -one invented type \grammarterm{template-parameter} +one invented \grammarterm{type-parameter} for each generic parameter type placeholder of the function declaration, in order of appearance. For a \grammarterm{placeholder-type-specifier} of the form \keyword{auto}, @@ -3921,7 +4155,7 @@ \grammarterm{type-constraint} \keyword{auto}, the invented parameter is a \grammarterm{type-parameter} with that \grammarterm{type-constraint}. -The invented type \grammarterm{template-parameter} is +The invented \grammarterm{type-parameter} declares a template parameter pack if the corresponding \grammarterm{parameter-declaration} declares a function parameter pack. @@ -3930,7 +4164,7 @@ The adjusted function parameters of an abbreviated function template are derived from the \grammarterm{parameter-declaration-clause} by replacing each occurrence of a placeholder with -the name of the corresponding invented \grammarterm{template-parameter}. +the name of the corresponding invented \grammarterm{type-parameter}. \begin{example} \begin{codeblock} template concept C1 = /* ... */; @@ -3958,7 +4192,7 @@ \pnum An abbreviated function template can have a \grammarterm{template-head}. -The invented \grammarterm{template-parameter}{s} are +The invented \grammarterm{type-parameter}{s} are appended to the \grammarterm{template-parameter-list} after the explicitly declared \grammarterm{template-parameter}{s}. \begin{example} @@ -4090,9 +4324,9 @@ \pnum For non-template functions, default arguments can be added in later declarations of a -function that inhabit the same scope. -Declarations that inhabit different -scopes have completely distinct sets of default arguments. +function that have the same host scope. +Declarations that have different +host scopes have completely distinct sets of default arguments. That is, declarations in inner scopes do not acquire default arguments from declarations in outer scopes, and vice versa. @@ -4263,9 +4497,19 @@ int h(int a, int b = sizeof(a)); // OK, unevaluated operand\iref{term.unevaluated.operand} \end{codeblock} \end{example} -A non-static member shall not appear in a default argument unless it appears as -the \grammarterm{id-expression} of a class member access expression\iref{expr.ref} or -unless it is used to form a pointer to member\iref{expr.unary.op}. +A non-static member shall not be designated in a default argument unless +\begin{itemize} +\item +it is designated by +the \grammarterm{id-expression} or \grammarterm{splice-expression} +of a class member access expression\iref{expr.ref}, +\item +it is designated by an expression +used to form a pointer to member\iref{expr.unary.op}, or +\item +it appears as the operand of +a \grammarterm{reflect-expression}\iref{expr.reflect}. +\end{itemize} \begin{example} The declaration of \tcode{X::mem1()} @@ -4277,8 +4521,10 @@ int b; class X { int a; - int mem1(int i = a); // error: non-static member \tcode{a} used as default argument - int mem2(int i = b); // OK; use \tcode{X::b} + int mem1(int i = a); // error: non-static member \tcode{a} used as default argument + int mem2(int i = b); // OK, use \tcode{X::b} + consteval void mem3(std::meta::info r = ^^a) {} // OK + int mem4(int i = [:^^a:]); // error: non-static member \tcode{a} designated in default argument static int b; }; \end{codeblock} @@ -4303,10 +4549,13 @@ int (*p2)() = &f; // error: type mismatch \end{codeblock} \end{example} +\begin{note} When an overload set contains a declaration of a function -that inhabits a scope $S$, -any default argument associated with any reachable declaration that inhabits $S$ -is available to the call. +whose host scope is $S$, +any default argument associated with any reachable declaration +whose host scope is $S$ +is available to the call\iref{over.match.viable}. +\end{note} \begin{note} The candidate might have been found through a \grammarterm{using-declarator} from which the declaration that provides the default argument is not reachable. @@ -4339,6 +4588,326 @@ \indextext{declaration!default argument|)}% \indextext{declarator!meaning of|)} +\rSec1[dcl.contract]{Function contract specifiers} +\rSec2[dcl.contract.func]{General} + +\indextext{contract assertion!function|(}% + +\begin{bnf} +\nontermdef{function-contract-specifier-seq}\br + function-contract-specifier \opt{function-contract-specifier-seq} +\end{bnf} + +\begin{bnf} +\nontermdef{function-contract-specifier}\br + precondition-specifier\br + postcondition-specifier +\end{bnf} + +\begin{bnf} +\nontermdef{precondition-specifier}\br + \terminal{pre} \opt{attribute-specifier-seq} \terminal{(} conditional-expression \terminal{)} +\end{bnf} + +\begin{bnf} +\nontermdef{postcondition-specifier}\br + \terminal{post} \opt{attribute-specifier-seq} \terminal{(} \opt{result-name-introducer} conditional-expression \terminal{)} +\end{bnf} + +\pnum +\indexdefn{contract assertion!postcondition|see{assertion, postcondition}} +\indexdefn{contract assertion!precondition|see{assertion, precondition}} +A \defnadj{function}{contract assertion} +is a contract assertion\iref{basic.contract.general} +associated with a function. +A \grammarterm{precondition-specifier} +introduces a \defnadj{precondition}{assertion}, +which is a function contract assertion +associated with entering a function. +A \grammarterm{postcondition-specifier} +introduces a \defnadj{postcondition}{assertion}, +which is a function contract assertion +associated with exiting a function normally. +\begin{note} +A postcondition assertion +is not associated with exiting a function +in any other fashion, +such as via an exception\iref{expr.throw} +or via a call to \tcode{longjmp}\iref{csetjmp.syn}. +\end{note} + +\pnum +The predicate\iref{basic.contract.general} +of a function contract assertion +is its \grammarterm{conditional-expression} +contextually converted to \tcode{bool}. + +\pnum +Each \grammarterm{function-contract-specifier} +of a \grammarterm{function-contract-specifier-seq} (if any) +of an unspecified first declaration\iref{basic.def} +of a function +introduces a corresponding function contract assertion for that function. +The optional \grammarterm{attribute-specifier-seq} +following \tcode{pre} or \tcode{post} +appertains to the introduced contract assertion. +\begin{note} +The \grammarterm{function-contract-specifier-seq} +of a \grammarterm{lambda-declarator} +applies to the function call operator or operator template +of the corresponding closure type\iref{expr.prim.lambda.closure}. +\end{note} + +\pnum +A declaration $D$ +of a function or function template \placeholder{f} +that is not a first declaration shall have either +no \grammarterm{function-contract-specifier-seq} +or the same \grammarterm{function-contract-specifier-seq} (see below) +as any first declaration $F$ reachable from $D$. +If $D$ and $F$ are +in different translation units, +a diagnostic is required only if $D$ is attached to a named module. +If a declaration $F_1$ is a +first declaration of \tcode{f} +in one translation unit and +a declaration $F_2$ is a +first declaration of \tcode{f} in another translation unit, +$F_1$ and $F_2$ shall specify the same +\grammarterm{function-contract-specifier-seq}, no diagnostic required. + +\pnum +A \grammarterm{function-contract-specifier-seq} $S_1$ +is the same as +a \grammarterm{function-contract-specifier-seq} $S_2$ +if $S_1$ and $S_2$ consist of +the same \grammarterm{function-contract-specifier}s +in the same order. +A \grammarterm{function-contract-specifier} $C_1$ +on a function declaration $D_1$ is +the same as +a \grammarterm{function-contract-specifier} $C_2$ +on a function declaration $D_2$ +if +\begin{itemize} +\item +their predicates $P_1$ and $P_2$ would +satisfy the one-definition rule\iref{basic.def.odr} +if placed in function definitions on +the declarations $D_1$ and $D_2$, respectively, except for +\begin{itemize} +\item +renaming of the parameters of \placeholder{f}, +\item +renaming of template parameters of +a template enclosing \placeholder{}, and +\item +renaming of the result binding\iref{dcl.contract.res}, if any, +\end{itemize} +and, +if $D_1$ and $D_2$ are in different translation units, +corresponding entities defined within each predicate +behave as if there is a single entity with a single definition, and +\item +both $C_1$ and $C_2$ +specify a \grammarterm{result-name-introducer} +or neither do. +\end{itemize} +If this condition is not met +solely due to the comparison of two \grammarterm{lambda-expression}s +that are contained within $P_1$ and $P_2$, +no diagnostic is required. + +\begin{note} +Equivalent +\grammarterm{function-contract-specifier-seq}s +apply to all uses and definitions +of a function across all translation units. +\end{note} +\begin{example} +\begin{codeblock} + +bool b1, b2; + +void f() pre (b1) pre ([]{ return b2; }()); +void f(); // OK, \grammarterm{function-contract-specifier}s omitted +void f() pre (b1) pre ([]{ return b2; }()); // error: closures have different types. +void f() pre (b1); // error: \grammarterm{function-contract-specifier}s only partially repeated + +int g() post(r : b1); +int g() post(b1); // error: mismatched \grammarterm{result-name-introducer} presence + +namespace N { + void h() pre (b1); + bool b1; + void h() pre (b1); // error: \grammarterm{function-contract-specifier}s differ according to + // the one-definition rule\iref{basic.def.odr}. +} +\end{codeblock} +\end{example} + +\pnum +A virtual function\iref{class.virtual}, +a deleted function\iref{dcl.fct.def.delete}, +or a function defaulted on its first declaration\iref{dcl.fct.def.default} +shall not have a \grammarterm{function-contract-specifier-seq}. + +\pnum +If the predicate of a postcondition assertion +of a function \placeholder{f} +odr-uses\iref{basic.def.odr} +a non-reference parameter of \placeholder{f}, +that parameter +and the corresponding parameter on all declarations of \placeholder{f} +shall have \keyword{const} type. +\begin{note} +This requirement applies +even to declarations that do not specify the \grammarterm{postcondition-specifier}. +Parameters with array or function type +will decay to non-\keyword{const} types +even if a \keyword{const} qualifier is present. +\begin{example} +\begin{codeblock} +int f(const int i[10]) + post(r : r == i[0]); // error: \tcode{i} has type \tcode{const int *} (not \tcode{int* const}). +\end{codeblock} +\end{example} +\end{note} + +\pnum +\begin{note} +The function contract assertions of a function +are evaluated even when invoked indirectly, +such as through a pointer to function or a pointer to member function. +A pointer to function, +pointer to member function, +or function type alias +cannot have a \grammarterm{function-contract-specifier-seq} +associated directly with it. +\end{note} + +\pnum +The function contract assertions of a function +are considered to be \defnx{needed}{needed!function contract assertion}\iref{temp.inst} when +\begin{itemize} +\item +the function is odr-used\iref{basic.def.odr} or +\item +the function is defined. +\end{itemize} +\begin{note} +Overload resolution does not consider +\grammarterm{function-contract-specifier}s\iref{temp.deduct,temp.inst}. +\begin{example} +\begin{codeblock} +template void f(T t) pre( t == "" ); +template void f(T&& t); +void g() +{ + f(5); // error: ambiguous +} +\end{codeblock} +\end{example} +\end{note} + + +\rSec2[dcl.contract.res]{Referring to the result object} + +\begin{bnf} +\nontermdef{attributed-identifier}\br + identifier \opt{attribute-specifier-seq} +\end{bnf} + +\begin{bnf} +\nontermdef{result-name-introducer}\br + attributed-identifier \terminal{:} +\end{bnf} + +\pnum +The \grammarterm{result-name-introducer} +of a \grammarterm{postcondition-specifier} +is a declaration. +The \grammarterm{result-name-introducer} +introduces the \grammarterm{identifier} +as the name of a \defn{result binding} +of the associated function. +If a postcondition assertion has a \grammarterm{result-name-introducer} +and the return type of the function is \cv{} \keyword{void}, +the program is ill-formed. +A result binding denotes +the object or reference returned by +invocation of that function. +The type of a result binding +is the return type of its associated function. +The optional \grammarterm{attribute-specifier-seq} +of the \grammarterm{attributed-identifier} +in the \grammarterm{result-name-introducer} +appertains to the result binding so introduced. +\begin{note} +An \grammarterm{id-expression} +that names a result binding is a \keyword{const} lvalue\iref{expr.prim.id.unqual}. +\end{note} + +\begin{example} +\begin{codeblock} +int f() + post(r : r == 1) +{ + return 1; +} +int i = f(); // Postcondition check succeeds. +\end{codeblock} +\end{example} + +\begin{example} +\begin{codeblock} +struct A {}; +struct B { + B() {} + B(const B&) {} +}; + +template +T f(T* const ptr) + post(r: &r == ptr) +{ + return {}; +} + +int main() { + A a = f(&a); // The postcondition check can fail if the implementation introduces + // a temporary for the return value\iref{class.temporary}. + B b = f(&b); // The postcondition check succeeds, no temporary is introduced. +} +\end{codeblock} +\end{example} + + +\pnum +When the declared return type +of a non-templated function +contains a placeholder type, +a \grammarterm{postcondition-specifier} +with a \grammarterm{result-name-introducer} +shall be present only on a definition. +\begin{example} +\begin{codeblock} +auto g(auto&) + post (r: r >= 0); // OK, \tcode{g} is a template. + +auto h() + post (r: r >= 0); // error: cannot name the return value + +auto k() + post (r: r >= 0) // OK +{ + return 0; +} +\end{codeblock} +\end{example} + +\indextext{contract assertion!function|)}% + \rSec1[dcl.init]{Initializers}% \rSec2[dcl.init.general]{General}% @@ -4445,20 +5014,16 @@ \indextext{initialization!default}% \indextext{variable!indeterminate uninitialized}% \indextext{initialization!zero-initialization}% -To -\defnx{zero-initialize}{zero-initialization} -an object or reference of type -\tcode{T} -means: +To \defnx{zero-initialize}{zero-initialization} +an object or reference of type \tcode{T} means: \begin{itemize} \item -if -\tcode{T} -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 -\tcode{T}; +if \tcode{T} is \tcode{std::meta::info}, +the object is initialized to a null reflection value; +\item +if \tcode{T} is any other scalar type\iref{term.scalar.type}, +the object is initialized to the value +obtained by converting the integer literal \tcode{0} (zero) to \tcode{T}; \begin{footnote} As specified in~\ref{conv.ptr}, converting an integer literal whose value is @@ -4524,6 +5089,9 @@ shall be met and each element is default-initialized. +\item +If \tcode{T} is \tcode{std::meta::info}, the object is zero-initialized. + \item Otherwise, no initialization is performed. @@ -4553,7 +5121,9 @@ If a program calls for the default-initialization of an object of a const-qualified type \tcode{T}, -\tcode{T} shall be a const-default-constructible class type or array thereof. +\tcode{T} shall be \tcode{std::meta::\linebreak info} +or a const-default-constructible class type, +or array thereof. \pnum To @@ -4567,17 +5137,10 @@ If \tcode{T} is a (possibly cv-qualified) class type\iref{class}, then -\begin{itemize} -\item -if \tcode{T} has -either no default constructor\iref{class.default.ctor} or a default -constructor that is user-provided or deleted, then the object is default-initialized; -\item -otherwise, -the object is zero-initialized and the semantic constraints for -default-initialization are checked, and if \tcode{T} has a -non-trivial default constructor, the object is default-initialized. -\end{itemize} +let \tcode{C} be the constructor selected to +default-initialize the object, if any. +If \tcode{C} is not user-provided, the object is first zero-initialized. +In all cases, the object is then default-initialized. \item If @@ -4599,7 +5162,7 @@ \pnum \begin{note} -For every object of static storage duration, +For every object with static storage duration, static initialization\iref{basic.start.static} is performed at program startup before any other initialization takes place. In some cases, additional initialization is done later. @@ -4648,7 +5211,7 @@ The \indextext{type!destination}% \term{destination type} -is the type of the object or reference being initialized and the +is the cv-unqualified type of the object or reference being initialized and the \term{source type} is the type of the initializer expression. If the initializer is not a single (possibly parenthesized) expression, the @@ -4691,6 +5254,8 @@ \item Otherwise, if the destination type is an array, the object is initialized as follows. +The \grammarterm{initializer} shall be of the form +\tcode{(} \grammarterm{expression-list} \tcode{)}. Let $x_1$, $\dotsc$, $x_k$ be the elements of the \grammarterm{expression-list}. If the destination type is an array of unknown bound, @@ -4707,13 +5272,13 @@ is sequenced before those associated with the initialization of the $j^\text{th}$ element. \item -Otherwise, if the destination type is a (possibly cv-qualified) class type: +Otherwise, if the destination type is a class type: \begin{itemize} \item If the initializer expression is a prvalue and the cv-unqualified version of the source type -is the same class as the class of the destination, +is the same as the destination type, the initializer expression is used to initialize the destination object. \begin{example} \tcode{T x = T(T(T()));} value-initializes \tcode{x}. @@ -4721,7 +5286,7 @@ \item Otherwise, if the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source -type is the same class as, or a derived class of, the class of the destination, +type is the same as or is derived from the class of the destination type, constructors are considered. The applicable constructors are enumerated\iref{over.match.ctor}, and the best one is chosen @@ -4818,7 +5383,7 @@ the (possibly converted) value of the initializer expression. A standard conversion sequence\iref{conv} is used to convert the initializer expression to -a prvalue of the cv-unqualified version of +a prvalue of the destination type; no user-defined conversions are considered. If the conversion cannot @@ -4960,8 +5525,8 @@ \item If the initializer list is a brace-enclosed \grammarterm{initializer-list}, the explicitly initialized elements of the aggregate -are the first $n$ elements of the aggregate, -where $n$ is the number of elements in the initializer list. +are those for which an element of the initializer list +appertains to the aggregate element or to a subobject thereof (see below). \item Otherwise, the initializer list must be \tcode{\{\}}, and there are no explicitly initialized elements. @@ -4992,21 +5557,30 @@ initializes \tcode{c.a} with 1 and \tcode{c.x} with 3. \end{example} \item -Otherwise, the element is copy-initialized -from the corresponding \grammarterm{initializer-clause} -or is initialized with the \grammarterm{brace-or-equal-initializer} +Otherwise, if the initializer list is +a brace-enclosed \grammarterm{designated-initializer-list}, +the element is initialized with the \grammarterm{brace-or-equal-initializer} of the corresponding \grammarterm{designated-initializer-clause}. If that initializer is of the form -\grammarterm{assignment-expression} or \tcode{= }\grammarterm{assignment-expression} and a narrowing conversion\iref{dcl.init.list} is required to convert the expression, the program is ill-formed. \begin{note} -If the initialization is by \grammarterm{designated-initializer-clause}, -its form determines whether copy-initialization or direct-initialization -is performed. +The form of the initializer determines +whether copy-initialization or direct-initialization is performed. \end{note} +\item +Otherwise, +the initializer list is a brace-enclosed \grammarterm{initializer-list}. +If an \grammarterm{initializer-clause} appertains to the aggregate element, +then the aggregate element is copy-initialized from the \grammarterm{initializer-clause}. +Otherwise, +the aggregate element is copy-initialized +from a brace-enclosed \grammarterm{initializer-list} +consisting of all of the \grammarterm{initializer-clause}s +that appertain to subobjects of the aggregate element, +in the order of appearance. \begin{note} If an initializer is itself an initializer list, the element is list-initialized, which will result in a recursive application @@ -5096,13 +5670,7 @@ with the value of an expression of the form \tcode{int\{\}} (that is, \tcode{0}), and \tcode{ss.d} with the value of \tcode{ss.b[ss.a]} -(that is, \tcode{'s'}), and in -\begin{codeblock} -struct X { int i, j, k = 42; }; -X a[] = { 1, 2, 3, 4, 5, 6 }; -X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } }; -\end{codeblock} -\tcode{a} and \tcode{b} have the same value +(that is, \tcode{'s'}). \begin{codeblock} struct A { @@ -5144,15 +5712,9 @@ \end{note} \pnum -An array of unknown bound initialized with a -brace-enclosed -\grammarterm{initializer-list} -containing -\tcode{n} -\grammarterm{initializer-clause}{s} -is defined as having -\tcode{n} -elements\iref{dcl.array}. +The number of elements\iref{dcl.array} in an array of unknown bound +initialized with a brace-enclosed \grammarterm{initializer-list} +is the number of explicitly initialized elements of the array. \begin{example} \begin{codeblock} int x[] = { 1, 3, 5 }; @@ -5162,6 +5724,15 @@ as a one-dimensional array that has three elements since no size was specified and there are three initializers. \end{example} +\begin{example} +In +\begin{codeblock} +struct X { int i, j, k; }; +X a[] = { 1, 2, 3, 4, 5, 6 }; +X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } }; +\end{codeblock} +\tcode{a} and \tcode{b} have the same value. +\end{example} An array of unknown bound shall not be initialized with an empty \grammarterm{braced-init-list} \tcode{\{\}}. \begin{footnote} @@ -5209,19 +5780,6 @@ \end{example} \end{note} -\pnum -An -\grammarterm{initializer-list} -is ill-formed if the number of -\grammarterm{initializer-clause}{s} -exceeds the number of elements of the aggregate. -\begin{example} -\begin{codeblock} -char cv[4] = { 'a', 's', 'd', 'f', 0 }; // error -\end{codeblock} -is ill-formed. -\end{example} - \pnum If a member has a default member initializer and a potentially-evaluated subexpression thereof is an aggregate @@ -5243,32 +5801,6 @@ \end{codeblock} \end{example} -\pnum -If an aggregate class \tcode{C} contains a subaggregate element -\tcode{e} with no elements, -the \grammarterm{initializer-clause} for \tcode{e} shall not be -omitted from an \grammarterm{initializer-list} for an object of type -\tcode{C} unless the \grammarterm{initializer-clause}{s} for all -elements of \tcode{C} following \tcode{e} are also omitted. -\begin{example} -\begin{codeblock} -struct S { } s; -struct A { - S s1; - int i1; - S s2; - int i2; - S s3; - int i3; -} a = { - { }, // Required initialization - 0, - s, // Required initialization - 0 -}; // Initialization not required for \tcode{A::s3} because \tcode{A::i3} is also not initialized -\end{codeblock} -\end{example} - \pnum When initializing a multidimensional array, the @@ -5306,28 +5838,71 @@ \end{example} \pnum -Braces can be elided in an -\grammarterm{initializer-list} -as follows. -If the -\grammarterm{initializer-list} -begins with a left brace, -then the succeeding comma-separated list of -\grammarterm{initializer-clause}{s} -initializes the elements of a subaggregate; -it is erroneous for there to be more -\grammarterm{initializer-clause}{s} -than elements. -If, however, the -\grammarterm{initializer-list} -for a subaggregate does not begin with a left brace, -then only enough -\grammarterm{initializer-clause}{s} -from the list are taken to initialize the elements of the subaggregate; -any remaining -\grammarterm{initializer-clause}{s} -are left to initialize the next element of the aggregate -of which the current subaggregate is an element. +Each \grammarterm{initializer-clause} in +a brace-enclosed \grammarterm{initializer-list} +is said to \defn{appertain} +to an element of the aggregate being initialized or +to an element of one of its subaggregates. +Considering the sequence of \grammarterm{initializer-clause}s, +and the sequence of aggregate elements +initially formed as the sequence of elements of the aggregate being initialized +and potentially modified as described below, +each \grammarterm{initializer-clause} appertains to +the corresponding aggregate element if +\begin{itemize} +\item +the aggregate element is not an aggregate, or +\item +the \grammarterm{initializer-clause} begins with a left brace, or +\item +the \grammarterm{initializer-clause} is an expression and +an implicit conversion sequence can be formed +that converts the expression to the type of the aggregate element, or +\item +the aggregate element is an aggregate that itself has no aggregate elements. +\end{itemize} +Otherwise, +the aggregate element is an aggregate and +that subaggregate is replaced in the list of aggregate elements by +the sequence of its own aggregate elements, and +the appertainment analysis resumes with +the first such element and the same \grammarterm{initializer-clause}. +\begin{note} +These rules apply recursively to the aggregate's subaggregates. +\begin{example} +In +\begin{codeblock} +struct S1 { int a, b; }; +struct S2 { S1 s, t; }; + +S2 x[2] = { 1, 2, 3, 4, 5, 6, 7, 8 }; +S2 y[2] = { + { + { 1, 2 }, + { 3, 4 } + }, + { + { 5, 6 }, + { 7, 8 } + } +}; +\end{codeblock} +\tcode{x} and \tcode{y} have the same value. +\end{example} +\end{note} +This process continues +until all \grammarterm{initializer-clause}s have been exhausted. +If any \grammarterm{initializer-clause} remains +that does not appertain to +an element of the aggregate or one of its subaggregates, +the program is ill-formed. +\begin{example} +\begin{codeblock} +char cv[4] = { 'a', 's', 'd', 'f', 0 }; // error: too many initializers +\end{codeblock} +\end{example} + +\pnum \begin{example} \begin{codeblock} float y[4][3] = { @@ -5382,21 +5957,30 @@ \end{example} \pnum -All implicit type conversions\iref{conv} are considered when -initializing the element with an \grammarterm{assignment-expression}. -If the -\grammarterm{assignment-expression} -can initialize an element, the element is initialized. -Otherwise, if the element is itself a subaggregate, -brace elision is assumed and the -\grammarterm{assignment-expression} -is considered for the initialization of the first element of the subaggregate. \begin{note} -As specified above, brace elision cannot apply to -subaggregates with no elements; an -\grammarterm{initializer-clause} for the entire subobject is needed. +The initializer for an empty subaggregate is needed +if any initializers are provided for subsequent elements. +\begin{example} +\begin{codeblock} +struct S { } s; +struct A { + S s1; + int i1; + S s2; + int i2; + S s3; + int i3; +} a = { + { }, // Required initialization + 0, + s, // Required initialization + 0 +}; // Initialization not required for \tcode{A::s3} because \tcode{A::i3} is also not initialized +\end{codeblock} +\end{example} \end{note} +\pnum \begin{example} \begin{codeblock} struct A { @@ -5410,7 +5994,6 @@ A a; B b = { 4, a, a }; \end{codeblock} - Braces are elided around the \grammarterm{initializer-clause} for @@ -5561,7 +6144,7 @@ A reference cannot be changed to refer to another object after initialization. \indextext{assignment!reference}% \begin{note} -Assignment to a reference assigns to the object referred to by the reference\iref{expr.ass}. +Assignment to a reference assigns to the object referred to by the reference\iref{expr.assign}. \end{note} \indextext{argument passing!reference and}% Argument passing\iref{expr.call} @@ -5666,13 +6249,14 @@ \item Otherwise, if the initializer expression \begin{itemize} -\item is an rvalue (but not a bit-field) or function lvalue and +\item is an rvalue (but not a bit-field) or an lvalue of function type and ``\cvqual{cv1} \tcode{T1}'' is reference-compatible with ``\cvqual{cv2} \tcode{T2}'', or \item has a class type (i.e., \tcode{T2} is a class type), where \tcode{T1} is not reference-related to \tcode{T2}, and can be converted to -an rvalue or function lvalue of type ``\cvqual{cv3} \tcode{T3}'', +an rvalue of type ``\cvqual{cv3} \tcode{T3}'' or +an lvalue of function type ``\cvqual{cv3} \tcode{T3}'', where ``\cvqual{cv1} \tcode{T1}'' is reference-compatible with ``\cvqual{cv3} \tcode{T3}'' (see~\ref{over.match.ref}), \end{itemize} @@ -5681,8 +6265,10 @@ the converted expression in the second case is called the converted initializer. If the converted initializer is a prvalue, -its type \tcode{T4} is adjusted to type ``\cvqual{cv1} \tcode{T4}''\iref{conv.qual} -and the temporary materialization conversion\iref{conv.rval} is applied. +let its type be denoted by \tcode{T4}; +the temporary materialization conversion\iref{conv.rval} is applied, +considering the type of the prvalue to be +``\cvqual{cv1} \tcode{T4}''\iref{conv.qual}. In any case, the reference binds to the resulting glvalue (or to an appropriate base class subobject). @@ -5702,6 +6288,17 @@ int i2 = 42; int&& rri = static_cast(i2); // binds directly to \tcode{i2} B&& rrb = x; // binds directly to the result of \tcode{operator B} + +constexpr int f() { + const int &x = 42; + const_cast(x) = 1; // undefined behavior + return x; +} +constexpr int z = f(); // error: not a constant expression + +typedef int *AP[3]; // array of 3 pointer to \tcode{int} +typedef const int *const ACPC[3]; // array of 3 const pointer to \tcode{const int} +ACPC &&r = AP{}; // binds directly \end{codeblock} \end{example} @@ -5715,9 +6312,10 @@ ``\cvqual{cv1} \tcode{T1}'' by 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 +copy-initialization would be ill-formed. The result $E$ of the call to the conversion function, as described for the non-reference -copy-initialization, is then used to direct-initialize the reference. +copy-initialization, is then used to direct-initialize the reference +using the form \tcode{($E$)}. For this direct-initialization, user-defined conversions are not considered. \item Otherwise, @@ -5740,7 +6338,7 @@ Banana &&banana3 = Alaska(); // error } -const double& rcd2 = 2; // \tcode{rcd2} refers to temporary with value \tcode{2.0} +const double& rcd2 = 2; // \tcode{rcd2} refers to temporary with type \tcode{const double} and value \tcode{2.0} double&& rrd = 2; // \tcode{rrd} refers to temporary with value \tcode{2.0} const volatile int cvi = 1; const int& r2 = cvi; // error: cv-qualifier dropped @@ -5792,17 +6390,17 @@ \begin{note} List-initialization can be used \begin{itemize} -\item as the initializer in a variable definition\iref{dcl.init} -\item as the initializer in a \grammarterm{new-expression}\iref{expr.new} -\item in a \tcode{return} statement\iref{stmt.return} -\item as a \grammarterm{for-range-initializer}\iref{stmt.iter} -\item as a function argument\iref{expr.call} -\item as a template argument\iref{temp.arg.nontype} -\item as a subscript\iref{expr.sub} -\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} +\item as the initializer in a variable definition\iref{dcl.init}, +\item as the initializer in a \grammarterm{new-expression}\iref{expr.new}, +\item in a \tcode{return} statement\iref{stmt.return}, +\item as a \grammarterm{for-range-initializer}\iref{stmt.iter}, +\item as a function argument\iref{expr.call}, +\item as a template argument\iref{temp.arg.nontype}, +\item as a subscript\iref{expr.sub}, +\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}, or +\item on the right-hand side of an assignment\iref{expr.assign}. \end{itemize} \begin{example} @@ -5840,7 +6438,7 @@ the program is ill-formed. \pnum -List-initialization of an object or reference of type \tcode{T} is defined as follows: +List-initialization of an object or reference of type \cvqual{cv} \tcode{T} is defined as follows: \begin{itemize} \item If the \grammarterm{braced-init-list} @@ -5863,7 +6461,7 @@ \end{example} \item If \tcode{T} is an aggregate class and the initializer list has a single element -of type \cvqual{cv} \tcode{U}, +of type \cvqual{cv1} \tcode{U}, where \tcode{U} is \tcode{T} or a class derived from \tcode{T}, the object is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for @@ -5894,7 +6492,7 @@ \item Otherwise, if the initializer list has no elements and \tcode{T} is a class type with a default constructor, the object is value-initialized. -\item Otherwise, if \tcode{T} is a specialization of \tcode{std::initializer_list}, +\item Otherwise, if \tcode{T} is a specialization of \tcode{std::initializer_list}, the object is constructed as described below. \item Otherwise, if \tcode{T} is a class type, constructors are considered. @@ -5908,12 +6506,14 @@ struct S { S(std::initializer_list); // \#1 S(std::initializer_list); // \#2 - S(); // \#3 + S(std::initializer_list); // \#3 + S(); // \#4 // ... }; S s1 = { 1.0, 2.0, 3.0 }; // invoke \#1 S s2 = { 1, 2, 3 }; // invoke \#2 -S s3 = { }; // invoke \#3 +S s3{s2}; // invoke \#3 (not the copy constructor) +S s4 = { }; // invoke \#4 \end{codeblock} \end{example} @@ -6171,10 +6771,9 @@ \item from a floating-point type \tcode{T} to another floating-point type whose floating-point conversion rank is neither greater than nor equal to that of \tcode{T}, -except where the source is a constant expression and -the actual value after conversion -is within the range of values that can be represented (even if it cannot be represented exactly), -or +except where the result of the conversion is a constant expression and +either its value is finite and the conversion did not overflow, or +the values before and after the conversion are not finite, or \item from an integer type or unscoped enumeration type to a floating-point type, except where the source is a constant expression and the actual value after conversion will fit @@ -6231,7 +6830,7 @@ \rSec1[dcl.fct.def]{Function definitions}% \indextext{definition!function|(} -\rSec2[dcl.fct.def.general]{In general} +\rSec2[dcl.fct.def.general]{General} \pnum \indextext{body!function}% @@ -6240,8 +6839,10 @@ % \begin{bnf} \nontermdef{function-definition}\br - \opt{attribute-specifier-seq} \opt{decl-specifier-seq} declarator \opt{virt-specifier-seq} function-body\br - \opt{attribute-specifier-seq} \opt{decl-specifier-seq} declarator requires-clause function-body + \opt{attribute-specifier-seq} \opt{decl-specifier-seq} declarator \opt{virt-specifier-seq}\br + \bnfindent \opt{function-contract-specifier-seq} function-body\br + \opt{attribute-specifier-seq} \opt{decl-specifier-seq} declarator requires-clause\br + \bnfindent \opt{function-contract-specifier-seq} function-body \end{bnf} \begin{bnf} @@ -6249,7 +6850,13 @@ \opt{ctor-initializer} compound-statement\br function-try-block\br \terminal{=} \keyword{default} \terminal{;}\br - \terminal{=} \keyword{delete} \terminal{;} + deleted-function-body +\end{bnf} + +\begin{bnf} +\nontermdef{deleted-function-body}\br + \terminal{=} \keyword{delete} \terminal{;}\br + \terminal{=} \keyword{delete} \terminal{(} unevaluated-string \terminal{)} \terminal{;} \end{bnf} Any informal reference to the body of a function should be interpreted as a reference to @@ -6261,8 +6868,10 @@ a \grammarterm{mem-initializer-id}\iref{class.base.init}. The optional \grammarterm{attribute-specifier-seq} in a \grammarterm{function-definition} appertains to the function. -A \grammarterm{virt-specifier-seq} can be part of a \grammarterm{function-definition} -only if it is a \grammarterm{member-declaration}\iref{class.mem}. +A \grammarterm{function-definition} with a \grammarterm{virt-specifier-seq} +shall be a \grammarterm{member-declaration}\iref{class.mem}. +A \grammarterm{function-definition} with a \grammarterm{requires-clause} +shall define a templated function. \pnum In a \grammarterm{function-definition}, @@ -6371,9 +6980,9 @@ is called an \defnx{explicitly-defaulted}{definition!function!explicitly-defaulted} definition. A function that is explicitly defaulted shall \begin{itemize} -\item be a special member function or -a comparison operator function\iref{over.binary}, and -\item not have default arguments. +\item be a special member function\iref{special} or +a comparison operator function\iref{over.binary, class.compare.default}, and +\item not have default arguments\iref{dcl.fct.default}. \end{itemize} \pnum @@ -6468,15 +7077,18 @@ (i.e., explicitly defaulted after its first declaration) is implicitly defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. +\begin{note} +Declaring a function as defaulted after its first declaration +can provide efficient execution and concise definition +while enabling a stable binary interface to an evolving code base. +\end{note} A non-user-provided defaulted function (i.e., implicitly declared or explicitly defaulted in the class) that is not defined as deleted is implicitly defined when it is odr-used\iref{basic.def.odr} or needed for constant evaluation\iref{expr.const}. \begin{note} -Declaring a function as defaulted after its first declaration can provide -efficient execution and concise -definition while enabling a stable binary interface to an evolving code -base. +The implicit definition of a non-user-provided defaulted function +does not bind any names. \end{note} \pnum @@ -6502,11 +7114,8 @@ \indextext{definition!function!deleted}% \pnum -A \defnadj{deleted}{definition} of a function is -a function definition whose -\grammarterm{function-body} -is of the form -\tcode{= delete ;} +A \defnadj{deleted}{definition} of a function is a function definition +whose \grammarterm{function-body} is a \grammarterm{deleted-function-body} or an explicitly-defaulted definition of the function where the function is defined as deleted. A \defnadj{deleted}{function} is @@ -6514,8 +7123,16 @@ deleted definition or a function that is implicitly defined as deleted. \pnum -A program that refers to a deleted function implicitly or explicitly, other -than to declare it, is ill-formed. +A construct that designates a deleted function implicitly or explicitly, +other than to declare it or to appear as the operand of +a \grammarterm{reflect-expression}\iref{expr.reflect}, +is ill-formed. + +\recommended +The resulting diagnostic message should include +the text of the \grammarterm{unevaluated-string}, +if one is supplied. + \begin{note} This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the @@ -6524,6 +7141,9 @@ function selected by overload resolution is referenced. The implicit odr-use\iref{term.odr.use} of a virtual function does not, by itself, constitute a reference. +The \grammarterm{unevaluated-string}, if present, +can be used to explain the rationale for deletion and/or +to suggest an alternative. \end{note} \pnum @@ -6654,7 +7274,13 @@ as described below. \pnum -A coroutine behaves as if its \grammarterm{function-body} were replaced by: +A coroutine behaves as if +the top-level cv-qualifiers in all +\grammarterm{parameter-declaration}s in the declarator +of its \grammarterm{function-definition} +were removed and +its \grammarterm{function-body} were replaced by +the following \defnadj{replacement}{body}: \begin{ncsimplebnf} \terminal{\{}\br \bnfindent \placeholder{promise-type} \exposid{promise} \placeholder{promise-constructor-arguments} \terminal{;}\br @@ -6719,6 +7345,13 @@ \end{itemize} \end{itemize} +\pnum +\begin{note} +An odr-use of a non-reference parameter +in a postcondition assertion +of a coroutine is ill-formed\iref{dcl.contract.func}. +\end{note} + \pnum If searches for the names \tcode{return_void} and \tcode{return_value} in the scope of the promise type each find any declarations, @@ -6752,7 +7385,8 @@ \pnum An implementation may need to allocate additional storage for a coroutine. This storage is known as the \defn{coroutine state} and is obtained by calling -a non-array allocation function\iref{basic.stc.dynamic.allocation}. +a non-array allocation function\iref{basic.stc.dynamic.allocation} +as part of the replacement body. The allocation function's name is looked up by searching for it in the scope of the promise type. \begin{itemize} \item @@ -6760,7 +7394,9 @@ overload resolution is performed on a function call created by assembling an argument list. The first argument is the amount of space requested, and is a prvalue of type \tcode{std::size_t}. -The lvalues $\tcode{p}_1 \dotsc \tcode{p}_n$ are the successive arguments. +The lvalues $\tcode{p}_1 \dotsc \tcode{p}_n$ +with their original types (including cv-qualifiers) +are the successive arguments. If no viable function is found\iref{over.match.viable}, overload resolution is performed again on a function call created by passing just @@ -6856,16 +7492,29 @@ \pnum When a coroutine is invoked, -after initializing its parameters\iref{expr.call}, -a copy is created for each coroutine parameter. -For a parameter of type \cv{}~\tcode{T}, -the copy is a variable of type \cv{}~\tcode{T} +a copy is created for each coroutine parameter +at the beginning of the replacement body. +For a parameter +whose original declaration specified the type \cv{}~\tcode{T}, +\begin{itemize} +\item +if \tcode{T} is a reference type, +the copy is a reference of type +\cv{}~\tcode{T} +bound to the same object as a parameter; +\item +otherwise, the copy is a variable +of type \cv{}~\tcode{T} with automatic storage duration that is direct-initialized from an xvalue of type \tcode{T} referring to the parameter. +\end{itemize} \begin{note} -An original parameter object is never -a const or volatile object\iref{basic.type.qualifier}. +An identifier in the \grammarterm{function-body} +that names one of these parameters +refers to the created copy, +not the original parameter\iref{expr.prim.id.unqual}. \end{note} + The initialization and destruction of each parameter copy occurs in the context of the called coroutine. Initializations of parameter copies are sequenced before the call to the @@ -6889,20 +7538,68 @@ The expression \keyword{co_await} \tcode{\exposid{promise}.final_suspend()} shall not be potentially-throwing\iref{except.spec}. +\rSec2[dcl.fct.def.replace]{Replaceable function definitions} + +\pnum +Certain functions +for which a definition is supplied by the implementation +are \defn{replaceable}. +A \Cpp{} program may +provide a definition with the signature of a replaceable function, +called a \defnadj{replacement}{function}. +The replacement function +is used instead of the default version +supplied by the implementation. +Such replacement occurs +prior to program startup\iref{basic.def.odr,basic.start}. +A declaration of the replacement function +\begin{itemize} +\item +shall not be inline, +\item +shall be attached to the global module, +\item +shall have \Cpp{} language linkage, +\item +shall have the same return type as the replaceable function, and +\item +if the function is declared in a standard library header, +shall be such that it would be valid as a redeclaration +of the declaration in that header; +\end{itemize} +no diagnostic is required. +\begin{note} +The one-definition rule\iref{basic.def.odr} +applies to the definitions of a replaceable function +provided by the program. +The implementation-supplied function definition +is an otherwise-unnamed function with no linkage. +\end{note} + + \rSec1[dcl.struct.bind]{Structured binding declarations}% \indextext{structured binding declaration}% \indextext{declaration!structured binding|see{structured binding declaration}}% \pnum A structured binding declaration introduces the \grammarterm{identifier}{s} -$\tcode{v}_0$, $\tcode{v}_1$, $\tcode{v}_2, \dotsc$ +$\tcode{v}_0$, $\tcode{v}_1$, $\tcode{v}_2, \dotsc, \tcode{v}_{N-1}$ of the -\grammarterm{identifier-list} as names -of \defn{structured binding}{s}. +\grammarterm{sb-identifier-list} as names. +An \grammarterm{sb-identifier} that contains an ellipsis +introduces a structured binding pack\iref{temp.variadic}. +A \defn{structured binding} is either +an \grammarterm{sb-identifier} that does not contain an ellipsis or +an element of a structured binding pack. +The optional \grammarterm{attribute-specifier-seq} of +an \grammarterm{sb-identifier} +appertains to the associated structured bindings. Let \cv{} denote the \grammarterm{cv-qualifier}{s} in the \grammarterm{decl-specifier-seq} and -\placeholder{S} consist of the \grammarterm{storage-class-specifier}{s} of -the \grammarterm{decl-specifier-seq} (if any). +\placeholder{S} consist of +each \grammarterm{decl-specifier} of the \grammarterm{decl-specifier-seq} +that is \tcode{constexpr}, \tcode{constinit}, or +a \grammarterm{storage-class-specifier}. A \cv{} that includes \tcode{volatile} is deprecated; see~\ref{depr.volatile.type}. First, a variable with a unique name \exposid{e} is introduced. If the @@ -6930,15 +7627,57 @@ \tcode{E} is never a reference type\iref{expr.prop}. \end{note} +\pnum +The \defn{structured binding size} of \tcode{E}, as defined below, +is the number of structured bindings +that need to be introduced by the structured binding declaration. +If there is no structured binding pack, +then the number of elements in the \grammarterm{sb-identifier-list} +shall be equal to the structured binding size of \tcode{E}. +Otherwise, the number of non-pack elements shall be no more than +the structured binding size of \tcode{E}; +the number of elements of the structured binding pack is +the structured binding size of \tcode{E} less +the number of non-pack elements in the \grammarterm{sb-identifier-list}. + +\pnum +Let $\textrm{SB}_i$ denote +the $i^\textrm{th}$ structured binding in the structured binding declaration +after expanding the structured binding pack, if any. +\begin{note} +If there is no structured binding pack, +then $\textrm{SB}_i$ denotes $\tcode{v}_i$. +\end{note} +\begin{example} +\begin{codeblock} +struct C { int x, y, z; }; + +template +void now_i_know_my() { + auto [a, b, c] = C(); // OK, $\textrm{SB}_0$ is \tcode{a}, $\textrm{SB}_1$ is \tcode{b}, and $\textrm{SB}_2$ is \tcode{c} + auto [d, ...e] = C(); // OK, $\textrm{SB}_0$ is \tcode{d}, the pack \tcode{e} $(\tcode{v}_1)$ contains two structured bindings: $\textrm{SB}_1$ and $\textrm{SB}_2$ + auto [...f, g] = C(); // OK, the pack \tcode{f} $(\tcode{v}_0)$ contains two structured bindings: $\textrm{SB}_0$ and $\textrm{SB}_1$, and $\textrm{SB}_2$ is \tcode{g} + auto [h, i, j, ...k] = C(); // OK, the pack \tcode{k} is empty + auto [l, m, n, o, ...p] = C(); // error: structured binding size is too small +} +\end{codeblock} +\end{example} + +\pnum +If a structured binding declaration appears as a \grammarterm{condition}, +the decision variable\iref{stmt.pre} of the condition is \exposid{e}. + \pnum If the \grammarterm{initializer} refers to one of the names introduced by the structured binding declaration, the program is ill-formed. \pnum -If \tcode{E} is an array type with element type \tcode{T}, the number -of elements in the \grammarterm{identifier-list} shall be equal to the -number of elements of \tcode{E}. Each $\tcode{v}_i$ is the name of an +\tcode{E} shall not be an array type of unknown bound. +If \tcode{E} is any other array type with element type \tcode{T}, +the structured binding size of \tcode{E} is equal to the +number of elements of \tcode{E}. +Each $\textrm{SB}_i$ is the name of an lvalue that refers to the element $i$ of the array and whose type is \tcode{T}; the referenced type is \tcode{T}. \begin{note} @@ -6949,6 +7688,19 @@ auto f() -> int(&)[2]; auto [ x, y ] = f(); // \tcode{x} and \tcode{y} refer to elements in a copy of the array return value auto& [ xr, yr ] = f(); // \tcode{xr} and \tcode{yr} refer to elements in the array referred to by \tcode{f}'s return value + +auto g() -> int(&)[4]; + +template +void h(int (&arr)[N]) { + auto [a, ...b, c] = arr; // \tcode{a} names the first element of the array, \tcode{b} is a pack referring to the second and + // third elements, and \tcode{c} names the fourth element + auto& [...e] = arr; // \tcode{e} is a pack referring to the four elements of the array +} + +void call_h() { + h(g()); +} \end{codeblock} \end{example} @@ -6959,8 +7711,7 @@ the expression \tcode{std::tuple_size::value} shall be a well-formed integral constant expression and -the number of elements in -the \grammarterm{identifier-list} shall be equal to the value of that +the structured binding size of \tcode{E} is equal to the value of that expression. Let \tcode{i} be an index prvalue of type \tcode{std::size_t} corresponding to $\tcode{v}_i$. @@ -6968,7 +7719,7 @@ in the scope of \tcode{E}\iref{class.member.lookup} finds at least one declaration that is a function template whose first template parameter -is a non-type parameter, +is a constant template parameter, the initializer is \tcode{\exposidnc{e}.get()}. Otherwise, the initializer is \tcode{get(\exposid{e})}, where \tcode{get} undergoes argument-dependent lookup\iref{basic.lookup.argdep}. @@ -6990,9 +7741,15 @@ \placeholder{S} \terminal{U$_i$ r$_i$ =} initializer \terminal{;} \end{ncbnf} -Each $\tcode{v}_i$ is the name of an lvalue of type $\tcode{T}_i$ +Each $\textrm{SB}_i$ is the name of an lvalue of type $\tcode{T}_i$ that refers to the object bound to $\tcode{r}_i$; the referenced type is $\tcode{T}_i$. +The initialization of \exposid{e} and +any conversion of \exposid{e} considered as a decision variable\iref{stmt.pre} +is +sequenced before the initialization of any $\tcode{r}_i$. +The initialization of each $\tcode{r}_i$ is +sequenced before the initialization of any $\tcode{r}_j$ where $i < j$. \pnum Otherwise, @@ -7002,12 +7759,12 @@ well-formed when named as \tcode{\exposidnc{e}.\placeholder{name}} in the context of the structured binding, \tcode{E} shall not have an anonymous union member, and -the number of elements in the \grammarterm{identifier-list} shall be +the structured binding size of \tcode{E} is equal to the number of non-static data members of \tcode{E}. Designating the non-static data members of \tcode{E} as $\tcode{m}_0$, $\tcode{m}_1$, $\tcode{m}_2, \dotsc$ (in declaration order), -each $\tcode{v}_i$ is the +each $\textrm{SB}_i$ is the name of an lvalue that refers to the member \tcode{m}$_i$ of \exposid{e} and whose type is that of \tcode{\exposidnc{e}.$\tcode{m}_i$}\iref{expr.ref}; @@ -7359,17 +8116,36 @@ \begin{bnf} \nontermdef{using-enum-declarator}\br \opt{nested-name-specifier} identifier\br - \opt{nested-name-specifier} simple-template-id + \opt{nested-name-specifier} simple-template-id\br + splice-type-specifier \end{bnf} \pnum -A \grammarterm{using-enum-declarator} +A \grammarterm{using-enum-declarator} of +the form \grammarterm{splice-type-specifier} +designates the same type designated by the \grammarterm{splice-type-specifier}. +Any other \grammarterm{using-enum-declarator} names the set of declarations found by -lookup\iref{basic.lookup.unqual,basic.lookup.qual} -for the \grammarterm{using-enum-declarator}. +type-only lookup\iref{basic.lookup.general} +for the \grammarterm{using-enum-declarator}\iref{basic.lookup.unqual,basic.lookup.qual}. The \grammarterm{using-enum-declarator} shall designate a non-dependent type with a reachable \grammarterm{enum-specifier}. +\begin{example} +\begin{codeblock} +enum E { x }; +void f() { + int E; + using enum E; // OK +} +using F = E; +using enum F; // OK +template using EE = T; +void g() { + using enum EE; // OK +} +\end{codeblock} +\end{example} \pnum A \grammarterm{using-enum-declaration} @@ -7612,7 +8388,7 @@ \grammarterm{unnamed-namespace-definition} and all occurrences of \exposid{unique} in a translation unit are replaced by the same identifier, and this identifier differs from all other -identifiers in the translation unit. +identifiers in the program. The optional \grammarterm{attribute-specifier-seq} in the \grammarterm{unnamed-namespace-definition} appertains to \exposid{unique}. @@ -7644,8 +8420,8 @@ \indextext{synonym} \pnum -A \grammarterm{namespace-alias-definition} declares an alternate name for a -namespace according to the following grammar: +A \grammarterm{namespace-alias-definition} declares a \defnadj{namespace}{alias} +according to the following grammar: \begin{bnf} \nontermdef{namespace-alias}\br @@ -7654,7 +8430,8 @@ \begin{bnf} \nontermdef{namespace-alias-definition}\br - \keyword{namespace} identifier \terminal{=} qualified-namespace-specifier \terminal{;} + \keyword{namespace} identifier \terminal{=} qualified-namespace-specifier \terminal{;}\br + \keyword{namespace} identifier \terminal{=} splice-specifier \terminal{;}\br \end{bnf} \begin{bnf} @@ -7662,10 +8439,19 @@ \opt{nested-name-specifier} namespace-name \end{bnf} +\pnum +The \grammarterm{splice-specifier} (if any) +shall designate a namespace that is not the global namespace. + \pnum The \grammarterm{identifier} in a \grammarterm{namespace-alias-definition} -becomes a \grammarterm{namespace-alias} and denotes the namespace denoted by the -\grammarterm{qualified-namespace-specifier}. +becomes a \grammarterm{namespace-alias}. + +\pnum +The underlying entity\iref{basic.pre} of the namespace alias is +the namespace either +denoted by the \grammarterm{qualified-namespace-specifier} or +designated by the \grammarterm{splice-specifier}. \begin{note} When looking up a \grammarterm{namespace-name} in a \grammarterm{namespace-alias-definition}, only namespace names are @@ -7677,9 +8463,18 @@ \begin{bnf} \nontermdef{using-directive}\br - \opt{attribute-specifier-seq} \keyword{using} \keyword{namespace} \opt{nested-name-specifier} namespace-name \terminal{;} + \opt{attribute-specifier-seq} \keyword{using} \keyword{namespace} \opt{nested-name-specifier} namespace-name \terminal{;}\br + \opt{attribute-specifier-seq} \keyword{using} \keyword{namespace} splice-specifier \terminal{;} \end{bnf} +\pnum +The \grammarterm{splice-specifier} (if any) shall designate a namespace +that is not the global namespace. +The \grammarterm{nested-name-specifier}, +\grammarterm{namespace-name}, and +\grammarterm{splice-specifier} +shall not be dependent. + \pnum A \grammarterm{using-directive} shall not appear in class scope, but may appear in namespace scope or in block scope. @@ -7692,13 +8487,13 @@ \pnum \begin{note} -A \grammarterm{using-directive} makes the names in the nominated +A \grammarterm{using-directive} makes the names in the designated namespace usable in the scope in which the \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 +contains both the \grammarterm{using-directive} and the designated namespace. \end{note} @@ -7739,8 +8534,8 @@ \pnum \begin{note} A \grammarterm{using-directive} is transitive: if a scope contains a -\grammarterm{using-directive} that nominates a namespace that itself -contains \grammarterm{using-directive}{s}, the namespaces nominated by those +\grammarterm{using-directive} that designates a namespace that itself +contains \grammarterm{using-directive}{s}, the namespaces designated by those \grammarterm{using-directive}{s} are also eligible to be considered. \end{note} \begin{example} @@ -8547,8 +9342,8 @@ \pnum \indextext{object!linkage specification}% \indextext{linkage!implementation-defined object}% -Linkage from \Cpp{} to objects defined in other languages and to objects -defined in \Cpp{} from other languages is \impldef{linkage of objects between \Cpp{} and other languages} and +Linkage from \Cpp{} to entities defined in other languages and to entities +defined in \Cpp{} from other languages is \impldef{linkage of entities between \Cpp{} and other languages} and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved.% @@ -8561,17 +9356,18 @@ \pnum \indextext{attribute!syntax and semantics}% -Attributes specify additional information for various source constructs -such as types, variables, names, blocks, or translation units. +Attributes and annotations specify additional information for various source constructs +such as types, variables, names, contract assertions, blocks, or translation units. \begin{bnf} \nontermdef{attribute-specifier-seq}\br - \opt{attribute-specifier-seq} attribute-specifier + attribute-specifier \opt{attribute-specifier-seq} \end{bnf} \begin{bnf} \nontermdef{attribute-specifier}\br \terminal{[} \terminal{[} \opt{attribute-using-prefix} attribute-list \terminal{]} \terminal{]}\br + \terminal{[} \terminal{[} annotation-list \terminal{]} \terminal{]}\br alignment-specifier \end{bnf} @@ -8594,11 +9390,22 @@ attribute-list \terminal{,} attribute \terminal{...} \end{bnf} +\begin{bnf} +\nontermdef{annotation-list}\br + annotation \opt{\terminal{...}}\br + annotation-list \terminal{,} annotation \opt{\terminal{...}} +\end{bnf} + \begin{bnf} \nontermdef{attribute}\br attribute-token \opt{attribute-argument-clause} \end{bnf} +\begin{bnf} +\nontermdef{annotation}\br + \terminal{=} constant-expression +\end{bnf} + \begin{bnf} \nontermdef{attribute-token}\br identifier\br @@ -8622,17 +9429,17 @@ \begin{bnf} \nontermdef{balanced-token-seq}\br - balanced-token\br - balanced-token-seq balanced-token + balanced-token \opt{balanced-token-seq} \end{bnf} \begin{bnf} -\microtypesetup{protrusion=false}\obeyspaces +\microtypesetup{protrusion=false} \nontermdef{balanced-token}\br \terminal{(} \opt{balanced-token-seq} \terminal{)}\br \terminal{[} \opt{balanced-token-seq} \terminal{]}\br \terminal{\{} \opt{balanced-token-seq} \terminal{\}}\br - \textnormal{any \grammarterm{token} other than a parenthesis, a bracket, or a brace} + \terminal{[:} \opt{balanced-token-seq} \terminal{:]}\br + \textnormal{any \grammarterm{token} other than \terminal{(}, \terminal{)}, \terminal{[}, \terminal{]}, \terminal{\{}, \terminal{\}}, \terminal{[:}, or \terminal{:]}} \end{bnf} \pnum @@ -8671,8 +9478,11 @@ In an \grammarterm{attribute-list}, an ellipsis may appear only if that \grammarterm{attribute}'s specification permits it. An \grammarterm{attribute} followed by an ellipsis is a pack expansion\iref{temp.variadic}. -An \grammarterm{attribute-specifier} that contains no \grammarterm{attribute}{s} has no -effect. The order in which the \grammarterm{attribute-token}{s} appear in an +An \grammarterm{attribute-specifier} that contains +an \grammarterm{attribute-list} with no \grammarterm{attribute}s +and no \grammarterm{alignment-specifier} +has no effect. +The order in which the \grammarterm{attribute-token}{s} appear in an \grammarterm{attribute-list} is not significant. If a keyword\iref{lex.key} or an alternative token\iref{lex.digraph} that satisfies the syntactic requirements @@ -8683,10 +9493,14 @@ \grammarterm{attribute-token}. The \grammarterm{attribute-token} determines additional requirements on the \grammarterm{attribute-argument-clause} (if any). +\pnum +An \grammarterm{annotation} followed by an ellipsis +is a pack expansion\iref{temp.variadic}. + \pnum Each \grammarterm{attribute-specifier-seq} is said to \defn{appertain} to some entity or statement, identified by the syntactic context -where it appears\iref{stmt.stmt,dcl.dcl,dcl.decl}. +where it appears\iref{stmt,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 @@ -8857,6 +9671,7 @@ \rSec2[dcl.attr.assume]{Assumption attribute} +\pnum The \grammarterm{attribute-token} \tcode{assume} may be applied to a null statement; such a statement is an \defn{assumption}. An \grammarterm{attribute-argument-clause} shall be present and @@ -8869,7 +9684,10 @@ If the converted expression would evaluate to \tcode{true} at the point where the assumption appears, the assumption has no effect. -Otherwise, the behavior is undefined. +Otherwise, +evaluation of the assumption has runtime-undefined behavior. + +\pnum \begin{note} The expression is potentially evaluated\iref{basic.def.odr}. The use of assumptions is intended to allow implementations @@ -8883,6 +9701,8 @@ if an implementation does not attempt to deduce any such information from assumptions. \end{note} + +\pnum \begin{example} \begin{codeblock} int divide_by_32(int x) { @@ -8897,86 +9717,6 @@ \end{codeblock} \end{example} -\rSec2[dcl.attr.depend]{Carries dependency attribute}% -\indextext{attribute!carries dependency} - -\pnum -The \grammarterm{attribute-token} \tcode{carries_dependency} specifies -dependency propagation into and out of functions. -No -\grammarterm{attribute-argument-clause} shall be present. The attribute may be -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 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. - -\pnum -The first declaration of a function shall specify the \tcode{carries_dependency} attribute for its -\grammarterm{declarator-id} if any declaration of the function specifies the -\tcode{carries_dependency} attribute. Furthermore, the first declaration of a function shall specify -the \tcode{carries_dependency} attribute for a parameter if any declaration of that function -specifies the \tcode{carries_dependency} attribute for that parameter. If a function or one of its -parameters is declared with the \tcode{carries_dependency} attribute in its first declaration in one -translation unit and the same function or one of its parameters is declared without the -\tcode{carries_dependency} attribute in its first declaration in another translation unit, the -program is ill-formed, no diagnostic required. - -\pnum -\begin{note} -The \tcode{carries_dependency} attribute does not change the meaning of the -program, but might result in generation of more efficient code. -\end{note} - -\pnum -\begin{example} -\begin{codeblock} -/* Translation unit A. */ - -struct foo { int* a; int* b; }; -std::atomic foo_head[10]; -int foo_array[10][10]; - -[[carries_dependency]] struct foo* f(int i) { - return foo_head[i].load(memory_order::consume); -} - -int g(int* x, int* y [[carries_dependency]]) { - return kill_dependency(foo_array[*x][*y]); -} - -/* Translation unit B. */ - -[[carries_dependency]] struct foo* f(int i); -int g(int* x, int* y [[carries_dependency]]); - -int c = 3; - -void h(int i) { - struct foo* p; - - p = f(i); - do_something_with(g(&c, p->a)); - do_something_with(g(p->a, &c)); -} -\end{codeblock} - -The \tcode{carries_dependency} attribute on function \tcode{f} means that the -return value carries a dependency out of \tcode{f}, so that the implementation -need not constrain ordering upon return from \tcode{f}. Implementations of -\tcode{f} and its caller may choose to preserve dependencies instead of emitting -hardware memory ordering instructions (a.k.a.\ fences). -Function \tcode{g}'s second parameter has a \tcode{carries_dependency} attribute, -but its first parameter does not. Therefore, function \tcode{h}'s first call to -\tcode{g} carries a dependency into \tcode{g}, but its second call does not. The -implementation might need to insert a fence prior to the second call to -\tcode{g}. -\end{example} -\indextext{attribute|)}% -\indextext{declaration|)} - \rSec2[dcl.attr.deprecated]{Deprecated attribute}% \indextext{attribute!deprecated} @@ -9001,7 +9741,7 @@ \pnum The attribute may be applied to the declaration of a class, -a \grammarterm{typedef-name}, +a type alias, a variable, a non-static data member, a function, @@ -9099,6 +9839,52 @@ \end{codeblock} \end{example} +\rSec2[dcl.attr.indet]{Indeterminate storage} +\indextext{attribute!indeterminate} + +\pnum +The \grammarterm{attribute-token} \tcode{indeterminate} may be applied +to the definition of a block variable with automatic storage duration or +to a \grammarterm{parameter-declaration} of a function declaration. +No \grammarterm{attribute-argument-clause} shall be present. +The attribute specifies +that the storage of an object with automatic storage duration +is initially indeterminate rather than erroneous\iref{basic.indet}. + +\pnum +If a function parameter is declared with the \tcode{indeterminate} attribute, +it shall be so declared in the first declaration of its function. +If a function parameter is declared with +the \tcode{indeterminate} attribute in the first declaration of its function +in one translation unit and +the same function is declared without the \tcode{indeterminate} attribute +on the same parameter in its first declaration in another translation unit, +the program is ill-formed, no diagnostic required. + +\pnum +\begin{note} +Reading from an uninitialized variable +that is marked \tcode{[[indeterminate]]} can cause undefined behavior. +\begin{codeblock} +void f(int); +void g() { + int x [[indeterminate]], y; + f(y); // erroneous behavior\iref{basic.indet} + f(x); // undefined behavior +} + +struct T { + T() {} + int x; +}; +int h(T t [[indeterminate]]) { + f(t.x); // undefined behavior when called below + return 0; +} +int _ = h(T()); +\end{codeblock} +\end{note} + \rSec2[dcl.attr.likelihood]{Likelihood attributes}% \indextext{attribute!likely} \indextext{attribute!unlikely} @@ -9173,8 +9959,10 @@ \pnum The attribute may be applied to the declaration of a class, -\grammarterm{typedef-name}, +type alias, variable (including a structured binding declaration), +structured binding, +result binding\iref{dcl.contract.res}, non-static data member, function, enumeration, or @@ -9273,6 +10061,7 @@ \recommended Appearance of a nodiscard call as a potentially-evaluated discarded-value expression\iref{expr.prop} +of non-void type is discouraged unless explicitly cast to \keyword{void}. Implementations should issue a warning in such cases. The value of @@ -9329,8 +10118,9 @@ translation unit, the program is ill-formed, no diagnostic required. \pnum -If a function \tcode{f} is called where \tcode{f} was previously declared with the \tcode{noreturn} -attribute and \tcode{f} eventually returns, the behavior is undefined. +If a function \tcode{f} is invoked where \tcode{f} was previously declared with the \tcode{noreturn} +attribute and that invocation eventually returns, +the behavior is runtime-undefined. \begin{note} The function can terminate by throwing an exception. @@ -9403,3 +10193,57 @@ could have the same address as \tcode{buckets} if their respective types are all empty. \end{example} + +\rSec2[dcl.attr.annotation]{Annotations}% +\indextext{attribute!annotations} + +\pnum +An annotation may be applied to any declaration of a +type, +type alias, +variable, +function, +namespace, +enumerator, +\grammarterm{base-specifier}, or +non-static data member. + +\pnum +Let $E$ be the expression +\tcode{std::meta::reflect_constant(\grammarterm{constant-expression})}. +$E$ shall be a constant expression; +the result of $E$ is the \defnadj{underlying}{constant} of the annotation. + +\pnum +Each \grammarterm{annotation} produces a unique annotation. + +\pnum +Substituting into an \grammarterm{annotation} +is not in the immediate context. +\begin{example} +\begin{codeblock} +[[=1]] void f(); +[[=2, =3, =2]] void g(); +void g [[=4, =2]] (); +\end{codeblock} +\tcode{f} has one annotation +and \tcode{g} has five annotations. +These can be queried with metafunctions +such as \tcode{std::\brk{}meta::\brk{}anno\-tations_of}\iref{meta.reflection.annotation}. +\end{example} +\begin{example} +\begin{codeblock} +template + [[=T::type()]] void f(T t); + +void f(int); + +void g() { + f(0); // OK + f('0'); // error, substituting into the annotation results in an invalid expression +} +\end{codeblock} +\end{example} + +\indextext{attribute|)}% +\indextext{declaration|)} diff --git a/source/diagnostics.tex b/source/diagnostics.tex index 1b4ce24a75..d16f516a77 100644 --- a/source/diagnostics.tex +++ b/source/diagnostics.tex @@ -20,7 +20,8 @@ \ref{assertions} & Assertions & \tcode{} \\ \rowsep \ref{errno} & Error numbers & \tcode{} \\ \rowsep \ref{syserr} & System error support & \tcode{} \\ \rowsep -\ref{stacktrace} & Stacktrace & \tcode{} \\ +\ref{stacktrace} & Stacktrace & \tcode{} \\ \rowsep +\ref{debugging} & Debugging & \tcode{} \\ \end{libsumtab} \rSec1[std.exceptions]{Exception classes} @@ -81,8 +82,8 @@ namespace std { class logic_error : public exception { public: - explicit logic_error(const string& what_arg); - explicit logic_error(const char* what_arg); + constexpr explicit logic_error(const string& what_arg); + constexpr explicit logic_error(const char* what_arg); }; } \end{codeblock} @@ -97,7 +98,7 @@ \indexlibraryctor{logic_error}% \begin{itemdecl} -logic_error(const string& what_arg); +constexpr logic_error(const string& what_arg); \end{itemdecl} \begin{itemdescr} @@ -108,7 +109,7 @@ \indexlibraryctor{logic_error}% \begin{itemdecl} -logic_error(const char* what_arg); +constexpr logic_error(const char* what_arg); \end{itemdecl} \begin{itemdescr} @@ -124,8 +125,8 @@ namespace std { class domain_error : public logic_error { public: - explicit domain_error(const string& what_arg); - explicit domain_error(const char* what_arg); + constexpr explicit domain_error(const string& what_arg); + constexpr explicit domain_error(const char* what_arg); }; } \end{codeblock} @@ -138,7 +139,7 @@ \indexlibraryctor{domain_error}% \begin{itemdecl} -domain_error(const string& what_arg); +constexpr domain_error(const string& what_arg); \end{itemdecl} \begin{itemdescr} @@ -149,7 +150,7 @@ \indexlibraryctor{domain_error}% \begin{itemdecl} -domain_error(const char* what_arg); +constexpr domain_error(const char* what_arg); \end{itemdecl} \begin{itemdescr} @@ -165,8 +166,8 @@ namespace std { class invalid_argument : public logic_error { public: - explicit invalid_argument(const string& what_arg); - explicit invalid_argument(const char* what_arg); + constexpr explicit invalid_argument(const string& what_arg); + constexpr explicit invalid_argument(const char* what_arg); }; } \end{codeblock} @@ -178,7 +179,7 @@ \indexlibraryctor{invalid_argument}% \begin{itemdecl} -invalid_argument(const string& what_arg); +constexpr invalid_argument(const string& what_arg); \end{itemdecl} \begin{itemdescr} @@ -189,7 +190,7 @@ \indexlibraryctor{invalid_argument}% \begin{itemdecl} -invalid_argument(const char* what_arg); +constexpr invalid_argument(const char* what_arg); \end{itemdecl} \begin{itemdescr} @@ -205,8 +206,8 @@ namespace std { class length_error : public logic_error { public: - explicit length_error(const string& what_arg); - explicit length_error(const char* what_arg); + constexpr explicit length_error(const string& what_arg); + constexpr explicit length_error(const char* what_arg); }; } \end{codeblock} @@ -220,7 +221,7 @@ \indexlibraryctor{length_error}% \begin{itemdecl} -length_error(const string& what_arg); +constexpr length_error(const string& what_arg); \end{itemdecl} \begin{itemdescr} @@ -231,7 +232,7 @@ \indexlibraryctor{length_error}% \begin{itemdecl} -length_error(const char* what_arg); +constexpr length_error(const char* what_arg); \end{itemdecl} \begin{itemdescr} @@ -247,8 +248,8 @@ namespace std { class out_of_range : public logic_error { public: - explicit out_of_range(const string& what_arg); - explicit out_of_range(const char* what_arg); + constexpr explicit out_of_range(const string& what_arg); + constexpr explicit out_of_range(const char* what_arg); }; } \end{codeblock} @@ -262,7 +263,7 @@ \indexlibraryctor{out_of_range}% \begin{itemdecl} -out_of_range(const string& what_arg); +constexpr out_of_range(const string& what_arg); \end{itemdecl} \begin{itemdescr} @@ -273,7 +274,7 @@ \indexlibraryctor{out_of_range}% \begin{itemdecl} -out_of_range(const char* what_arg); +constexpr out_of_range(const char* what_arg); \end{itemdecl} \begin{itemdescr} @@ -289,8 +290,8 @@ namespace std { class runtime_error : public exception { public: - explicit runtime_error(const string& what_arg); - explicit runtime_error(const char* what_arg); + constexpr explicit runtime_error(const string& what_arg); + constexpr explicit runtime_error(const char* what_arg); }; } \end{codeblock} @@ -303,7 +304,7 @@ \indexlibraryctor{runtime_error}% \begin{itemdecl} -runtime_error(const string& what_arg); +constexpr runtime_error(const string& what_arg); \end{itemdecl} \begin{itemdescr} @@ -314,7 +315,7 @@ \indexlibraryctor{runtime_error}% \begin{itemdecl} -runtime_error(const char* what_arg); +constexpr runtime_error(const char* what_arg); \end{itemdecl} \begin{itemdescr} @@ -330,8 +331,8 @@ namespace std { class range_error : public runtime_error { public: - explicit range_error(const string& what_arg); - explicit range_error(const char* what_arg); + constexpr explicit range_error(const string& what_arg); + constexpr explicit range_error(const char* what_arg); }; } \end{codeblock} @@ -344,7 +345,7 @@ \indexlibraryctor{range_error}% \begin{itemdecl} -range_error(const string& what_arg); +constexpr range_error(const string& what_arg); \end{itemdecl} \begin{itemdescr} @@ -355,7 +356,7 @@ \indexlibraryctor{range_error}% \begin{itemdecl} -range_error(const char* what_arg); +constexpr range_error(const char* what_arg); \end{itemdecl} \begin{itemdescr} @@ -371,8 +372,8 @@ namespace std { class overflow_error : public runtime_error { public: - explicit overflow_error(const string& what_arg); - explicit overflow_error(const char* what_arg); + constexpr explicit overflow_error(const string& what_arg); + constexpr explicit overflow_error(const char* what_arg); }; } \end{codeblock} @@ -384,7 +385,7 @@ \indexlibraryctor{overflow_error}% \begin{itemdecl} -overflow_error(const string& what_arg); +constexpr overflow_error(const string& what_arg); \end{itemdecl} \begin{itemdescr} @@ -395,7 +396,7 @@ \indexlibraryctor{overflow_error}% \begin{itemdecl} -overflow_error(const char* what_arg); +constexpr overflow_error(const char* what_arg); \end{itemdecl} \begin{itemdescr} @@ -411,8 +412,8 @@ namespace std { class underflow_error : public runtime_error { public: - explicit underflow_error(const string& what_arg); - explicit underflow_error(const char* what_arg); + constexpr explicit underflow_error(const string& what_arg); + constexpr explicit underflow_error(const char* what_arg); }; } \end{codeblock} @@ -424,7 +425,7 @@ \indexlibraryctor{underflow_error}% \begin{itemdecl} -underflow_error(const string& what_arg); +constexpr underflow_error(const string& what_arg); \end{itemdecl} \begin{itemdescr} @@ -435,7 +436,7 @@ \indexlibraryctor{underflow_error}% \begin{itemdecl} -underflow_error(const char* what_arg); +constexpr underflow_error(const char* what_arg); \end{itemdecl} \begin{itemdescr} @@ -455,9 +456,8 @@ \rSec2[cassert.syn]{Header \tcode{} synopsis} -\indexlibraryglobal{assert}% \begin{codeblock} -#define assert(...) @\seebelow@ +#define @\libmacro{assert}@(...) @\seebelow@ \end{codeblock} \rSec2[assertions.assert]{The \tcode{assert} macro} @@ -467,11 +467,11 @@ at the point in the source file where \tcode{} is included, the \tcode{assert} macro is defined as \begin{codeblock} -#define assert(...) ((void)0) +#define @\libmacro{assert}@(...) ((void)0) \end{codeblock} \pnum -Otherwise, the \tcode{assert} macro puts a diagnostic test into programs; +Otherwise, the \libmacro{assert} macro puts a diagnostic test into programs; it expands to an expression of type \keyword{void} which has the following effects: @@ -482,7 +482,7 @@ If the evaluation yields \tcode{true} there are no further effects. \item Otherwise, the \tcode{assert} macro's expression -creates a diagnostic on the standard error stream in an +creates a diagnostic on the standard error stream (\IsoC{}, 7.23.3) in an \impldef{format of diagnostic created by \tcode{assert} macro's expression} format and calls \tcode{abort()}. The diagnostic contains \tcode{\#}\mname{VA_ARGS} and @@ -521,7 +521,7 @@ \pnum The contents of the header \libheaderdef{cerrno} are the same as the POSIX header -\libheader{errno.h}, except that \tcode{errno} shall be defined as a macro. +\libheader{errno.h}, except that \libmacro{errno} shall be defined as a macro. \begin{note} The intent is to remain in close alignment with the POSIX standard. \end{note} @@ -529,158 +529,83 @@ \rSec2[cerrno.syn]{Header \tcode{} synopsis} -\indexlibraryglobal{errno}% -\indexlibraryglobal{E2BIG}% -\indexlibraryglobal{EACCES}% -\indexlibraryglobal{EADDRINUSE}% -\indexlibraryglobal{EADDRNOTAVAIL}% -\indexlibraryglobal{EAFNOSUPPORT}% -\indexlibraryglobal{EAGAIN}% -\indexlibraryglobal{EALREADY}% -\indexlibraryglobal{EBADF}% -\indexlibraryglobal{EBADMSG}% -\indexlibraryglobal{EBUSY}% -\indexlibraryglobal{ECANCELED}% -\indexlibraryglobal{ECHILD}% -\indexlibraryglobal{ECONNABORTED}% -\indexlibraryglobal{ECONNREFUSED}% -\indexlibraryglobal{ECONNRESET}% -\indexlibraryglobal{EDEADLK}% -\indexlibraryglobal{EDESTADDRREQ}% -\indexlibraryglobal{EDOM}% -\indexlibraryglobal{EEXIST}% -\indexlibraryglobal{EFAULT}% -\indexlibraryglobal{EFBIG}% -\indexlibraryglobal{EHOSTUNREACH}% -\indexlibraryglobal{EIDRM}% -\indexlibraryglobal{EILSEQ}% -\indexlibraryglobal{EINPROGRESS}% -\indexlibraryglobal{EINTR}% -\indexlibraryglobal{EINVAL}% -\indexlibraryglobal{EIO}% -\indexlibraryglobal{EISCONN}% -\indexlibraryglobal{EISDIR}% -\indexlibraryglobal{ELOOP}% -\indexlibraryglobal{EMFILE}% -\indexlibraryglobal{EMLINK}% -\indexlibraryglobal{EMSGSIZE}% -\indexlibraryglobal{ENAMETOOLONG}% -\indexlibraryglobal{ENETDOWN}% -\indexlibraryglobal{ENETRESET}% -\indexlibraryglobal{ENETUNREACH}% -\indexlibraryglobal{ENFILE}% -\indexlibraryglobal{ENOBUFS}% -\indexlibraryglobal{ENODEV}% -\indexlibraryglobal{ENOENT}% -\indexlibraryglobal{ENOEXEC}% -\indexlibraryglobal{ENOLCK}% -\indexlibraryglobal{ENOLINK}% -\indexlibraryglobal{ENOMEM}% -\indexlibraryglobal{ENOMSG}% -\indexlibraryglobal{ENOPROTOOPT}% -\indexlibraryglobal{ENOSPC}% -\indexlibraryglobal{ENOSYS}% -\indexlibraryglobal{ENOTCONN}% -\indexlibraryglobal{ENOTDIR}% -\indexlibraryglobal{ENOTEMPTY}% -\indexlibraryglobal{ENOTRECOVERABLE}% -\indexlibraryglobal{ENOTSOCK}% -\indexlibraryglobal{ENOTSUP}% -\indexlibraryglobal{ENOTTY}% -\indexlibraryglobal{ENXIO}% -\indexlibraryglobal{EOPNOTSUPP}% -\indexlibraryglobal{EOVERFLOW}% -\indexlibraryglobal{EOWNERDEAD}% -\indexlibraryglobal{EPERM}% -\indexlibraryglobal{EPIPE}% -\indexlibraryglobal{EPROTO}% -\indexlibraryglobal{EPROTONOSUPPORT}% -\indexlibraryglobal{EPROTOTYPE}% -\indexlibraryglobal{ERANGE}% -\indexlibraryglobal{EROFS}% -\indexlibraryglobal{ESPIPE}% -\indexlibraryglobal{ESRCH}% -\indexlibraryglobal{ETIMEDOUT}% -\indexlibraryglobal{ETXTBSY}% -\indexlibraryglobal{EWOULDBLOCK}% -\indexlibraryglobal{EXDEV}% \begin{codeblock} -#define errno @\seebelow@ - -#define E2BIG @\seebelow@ // freestanding -#define EACCES @\seebelow@ // freestanding -#define EADDRINUSE @\seebelow@ // freestanding -#define EADDRNOTAVAIL @\seebelow@ // freestanding -#define EAFNOSUPPORT @\seebelow@ // freestanding -#define EAGAIN @\seebelow@ // freestanding -#define EALREADY @\seebelow@ // freestanding -#define EBADF @\seebelow@ // freestanding -#define EBADMSG @\seebelow@ // freestanding -#define EBUSY @\seebelow@ // freestanding -#define ECANCELED @\seebelow@ // freestanding -#define ECHILD @\seebelow@ // freestanding -#define ECONNABORTED @\seebelow@ // freestanding -#define ECONNREFUSED @\seebelow@ // freestanding -#define ECONNRESET @\seebelow@ // freestanding -#define EDEADLK @\seebelow@ // freestanding -#define EDESTADDRREQ @\seebelow@ // freestanding -#define EDOM @\seebelow@ // freestanding -#define EEXIST @\seebelow@ // freestanding -#define EFAULT @\seebelow@ // freestanding -#define EFBIG @\seebelow@ // freestanding -#define EHOSTUNREACH @\seebelow@ // freestanding -#define EIDRM @\seebelow@ // freestanding -#define EILSEQ @\seebelow@ // freestanding -#define EINPROGRESS @\seebelow@ // freestanding -#define EINTR @\seebelow@ // freestanding -#define EINVAL @\seebelow@ // freestanding -#define EIO @\seebelow@ // freestanding -#define EISCONN @\seebelow@ // freestanding -#define EISDIR @\seebelow@ // freestanding -#define ELOOP @\seebelow@ // freestanding -#define EMFILE @\seebelow@ // freestanding -#define EMLINK @\seebelow@ // freestanding -#define EMSGSIZE @\seebelow@ // freestanding -#define ENAMETOOLONG @\seebelow@ // freestanding -#define ENETDOWN @\seebelow@ // freestanding -#define ENETRESET @\seebelow@ // freestanding -#define ENETUNREACH @\seebelow@ // freestanding -#define ENFILE @\seebelow@ // freestanding -#define ENOBUFS @\seebelow@ // freestanding -#define ENODEV @\seebelow@ // freestanding -#define ENOENT @\seebelow@ // freestanding -#define ENOEXEC @\seebelow@ // freestanding -#define ENOLCK @\seebelow@ // freestanding -#define ENOLINK @\seebelow@ // freestanding -#define ENOMEM @\seebelow@ // freestanding -#define ENOMSG @\seebelow@ // freestanding -#define ENOPROTOOPT @\seebelow@ // freestanding -#define ENOSPC @\seebelow@ // freestanding -#define ENOSYS @\seebelow@ // freestanding -#define ENOTCONN @\seebelow@ // freestanding -#define ENOTDIR @\seebelow@ // freestanding -#define ENOTEMPTY @\seebelow@ // freestanding -#define ENOTRECOVERABLE @\seebelow@ // freestanding -#define ENOTSOCK @\seebelow@ // freestanding -#define ENOTSUP @\seebelow@ // freestanding -#define ENOTTY @\seebelow@ // freestanding -#define ENXIO @\seebelow@ // freestanding -#define EOPNOTSUPP @\seebelow@ // freestanding -#define EOVERFLOW @\seebelow@ // freestanding -#define EOWNERDEAD @\seebelow@ // freestanding -#define EPERM @\seebelow@ // freestanding -#define EPIPE @\seebelow@ // freestanding -#define EPROTO @\seebelow@ // freestanding -#define EPROTONOSUPPORT @\seebelow@ // freestanding -#define EPROTOTYPE @\seebelow@ // freestanding -#define ERANGE @\seebelow@ // freestanding -#define EROFS @\seebelow@ // freestanding -#define ESPIPE @\seebelow@ // freestanding -#define ESRCH @\seebelow@ // freestanding -#define ETIMEDOUT @\seebelow@ // freestanding -#define ETXTBSY @\seebelow@ // freestanding -#define EWOULDBLOCK @\seebelow@ // freestanding -#define EXDEV @\seebelow@ // freestanding +#define @\libmacro{errno}@ @\seebelow@ + +#define @\libmacro{E2BIG}@ @\seebelow@ // freestanding +#define @\libmacro{EACCES}@ @\seebelow@ // freestanding +#define @\libmacro{EADDRINUSE}@ @\seebelow@ // freestanding +#define @\libmacro{EADDRNOTAVAIL}@ @\seebelow@ // freestanding +#define @\libmacro{EAFNOSUPPORT}@ @\seebelow@ // freestanding +#define @\libmacro{EAGAIN}@ @\seebelow@ // freestanding +#define @\libmacro{EALREADY}@ @\seebelow@ // freestanding +#define @\libmacro{EBADF}@ @\seebelow@ // freestanding +#define @\libmacro{EBADMSG}@ @\seebelow@ // freestanding +#define @\libmacro{EBUSY}@ @\seebelow@ // freestanding +#define @\libmacro{ECANCELED}@ @\seebelow@ // freestanding +#define @\libmacro{ECHILD}@ @\seebelow@ // freestanding +#define @\libmacro{ECONNABORTED}@ @\seebelow@ // freestanding +#define @\libmacro{ECONNREFUSED}@ @\seebelow@ // freestanding +#define @\libmacro{ECONNRESET}@ @\seebelow@ // freestanding +#define @\libmacro{EDEADLK}@ @\seebelow@ // freestanding +#define @\libmacro{EDESTADDRREQ}@ @\seebelow@ // freestanding +#define @\libmacro{EDOM}@ @\seebelow@ // freestanding +#define @\libmacro{EEXIST}@ @\seebelow@ // freestanding +#define @\libmacro{EFAULT}@ @\seebelow@ // freestanding +#define @\libmacro{EFBIG}@ @\seebelow@ // freestanding +#define @\libmacro{EHOSTUNREACH}@ @\seebelow@ // freestanding +#define @\libmacro{EIDRM}@ @\seebelow@ // freestanding +#define @\libmacro{EILSEQ}@ @\seebelow@ // freestanding +#define @\libmacro{EINPROGRESS}@ @\seebelow@ // freestanding +#define @\libmacro{EINTR}@ @\seebelow@ // freestanding +#define @\libmacro{EINVAL}@ @\seebelow@ // freestanding +#define @\libmacro{EIO}@ @\seebelow@ // freestanding +#define @\libmacro{EISCONN}@ @\seebelow@ // freestanding +#define @\libmacro{EISDIR}@ @\seebelow@ // freestanding +#define @\libmacro{ELOOP}@ @\seebelow@ // freestanding +#define @\libmacro{EMFILE}@ @\seebelow@ // freestanding +#define @\libmacro{EMLINK}@ @\seebelow@ // freestanding +#define @\libmacro{EMSGSIZE}@ @\seebelow@ // freestanding +#define @\libmacro{ENAMETOOLONG}@ @\seebelow@ // freestanding +#define @\libmacro{ENETDOWN}@ @\seebelow@ // freestanding +#define @\libmacro{ENETRESET}@ @\seebelow@ // freestanding +#define @\libmacro{ENETUNREACH}@ @\seebelow@ // freestanding +#define @\libmacro{ENFILE}@ @\seebelow@ // freestanding +#define @\libmacro{ENOBUFS}@ @\seebelow@ // freestanding +#define @\libmacro{ENODEV}@ @\seebelow@ // freestanding +#define @\libmacro{ENOENT}@ @\seebelow@ // freestanding +#define @\libmacro{ENOEXEC}@ @\seebelow@ // freestanding +#define @\libmacro{ENOLCK}@ @\seebelow@ // freestanding +#define @\libmacro{ENOLINK}@ @\seebelow@ // freestanding +#define @\libmacro{ENOMEM}@ @\seebelow@ // freestanding +#define @\libmacro{ENOMSG}@ @\seebelow@ // freestanding +#define @\libmacro{ENOPROTOOPT}@ @\seebelow@ // freestanding +#define @\libmacro{ENOSPC}@ @\seebelow@ // freestanding +#define @\libmacro{ENOSYS}@ @\seebelow@ // freestanding +#define @\libmacro{ENOTCONN}@ @\seebelow@ // freestanding +#define @\libmacro{ENOTDIR}@ @\seebelow@ // freestanding +#define @\libmacro{ENOTEMPTY}@ @\seebelow@ // freestanding +#define @\libmacro{ENOTRECOVERABLE}@ @\seebelow@ // freestanding +#define @\libmacro{ENOTSOCK}@ @\seebelow@ // freestanding +#define @\libmacro{ENOTSUP}@ @\seebelow@ // freestanding +#define @\libmacro{ENOTTY}@ @\seebelow@ // freestanding +#define @\libmacro{ENXIO}@ @\seebelow@ // freestanding +#define @\libmacro{EOPNOTSUPP}@ @\seebelow@ // freestanding +#define @\libmacro{EOVERFLOW}@ @\seebelow@ // freestanding +#define @\libmacro{EOWNERDEAD}@ @\seebelow@ // freestanding +#define @\libmacro{EPERM}@ @\seebelow@ // freestanding +#define @\libmacro{EPIPE}@ @\seebelow@ // freestanding +#define @\libmacro{EPROTO}@ @\seebelow@ // freestanding +#define @\libmacro{EPROTONOSUPPORT}@ @\seebelow@ // freestanding +#define @\libmacro{EPROTOTYPE}@ @\seebelow@ // freestanding +#define @\libmacro{ERANGE}@ @\seebelow@ // freestanding +#define @\libmacro{EROFS}@ @\seebelow@ // freestanding +#define @\libmacro{ESPIPE}@ @\seebelow@ // freestanding +#define @\libmacro{ESRCH}@ @\seebelow@ // freestanding +#define @\libmacro{ETIMEDOUT}@ @\seebelow@ // freestanding +#define @\libmacro{ETXTBSY}@ @\seebelow@ // freestanding +#define @\libmacro{EWOULDBLOCK}@ @\seebelow@ // freestanding +#define @\libmacro{EXDEV}@ @\seebelow@ // freestanding \end{codeblock} \pnum @@ -712,9 +637,6 @@ \indexlibraryglobal{error_code}% \indexlibraryglobal{error_condition}% \indexlibraryglobal{system_error}% -\indexlibraryglobal{is_error_code_enum}% -\indexlibraryglobal{is_error_condition_enum}% -\indexlibraryglobal{errc}% \begin{codeblock} #include // see \ref{compare.syn} @@ -728,12 +650,12 @@ class system_error; template - struct is_error_code_enum : public false_type {}; + struct @\libglobal{is_error_code_enum}@ : public false_type {}; template - struct is_error_condition_enum : public false_type {}; + struct @\libglobal{is_error_condition_enum}@ : public false_type {}; - enum class errc { // freestanding + enum class @\libglobal{errc}@ { // freestanding address_family_not_supported, // \tcode{EAFNOSUPPORT} address_in_use, // \tcode{EADDRINUSE} address_not_available, // \tcode{EADDRNOTAVAIL} @@ -836,7 +758,7 @@ // \ref{syserr}, system error support template - constexpr bool is_error_code_enum_v = is_error_code_enum::value; + constexpr bool @\libglobal{is_error_code_enum_v}@ = is_error_code_enum::value; template constexpr bool is_error_condition_enum_v = is_error_condition_enum::value; } @@ -2009,7 +1931,7 @@ const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; - [[nodiscard]] bool empty() const noexcept; + bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; @@ -2112,7 +2034,7 @@ Let \tcode{n} be \tcode{t.size()}. \pnum -\expects +\hardexpects \tcode{skip <= skip + max_depth} is \tcode{true}. \pnum @@ -2253,7 +2175,7 @@ \indexlibrarymember{empty}{basic_stacktrace}% \begin{itemdecl} -[[nodiscard]] bool empty() const noexcept; +bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -2291,7 +2213,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{frame_no < size()} is \tcode{true}. \pnum @@ -2485,3 +2407,99 @@ \pnum The specializations are enabled\iref{unord.hash}. \end{itemdescr} + +\rSec1[debugging]{Debugging} + +\rSec2[debugging.general]{General} + +\pnum +Subclause \ref{debugging} describes functionality to introspect and +interact with the execution of the program. + +\begin{note} +The facilities provided by the debugging functionality interact with a program +that could be tracing the execution of a \Cpp{} program, such as a debugger. +\end{note} + +\rSec2[debugging.syn]{Header \tcode{} synopsis} + +\indexheader{debugging}% +\begin{codeblock} +// all freestanding +namespace std { + // \ref{debugging.utility}, utility + void breakpoint() noexcept; + void breakpoint_if_debugging() noexcept; + bool is_debugger_present() noexcept; +} +\end{codeblock} + +\rSec2[debugging.utility]{Utility} + +\indexlibraryglobal{breakpoint}% +\begin{itemdecl} +void breakpoint() noexcept; +\end{itemdecl} + +\begin{itemdescr} + +\pnum +The semantics of this function are \impldef{semantics of \tcode{breakpoint}}. + +\begin{note} +It is intended that, when invoked with a debugger present, the execution of the +program temporarily halts and execution is handed to the debugger until the +program is either terminated by the debugger or the debugger resumes execution +of the program as if the function was not invoked. In particular, there is no +intent for a call to this function to accomodate resumption of the program in a +different manner. If there is no debugger present, execution of the program can +end abnormally. +\end{note} + +\end{itemdescr} + +\indexlibraryglobal{breakpoint_if_debugging}% +\begin{itemdecl} +void breakpoint_if_debugging() noexcept; +\end{itemdecl} + +\begin{itemdescr} + +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (is_debugger_present()) breakpoint(); +\end{codeblock} + +\end{itemdescr} + +\indexlibraryglobal{is_debugger_present}% +\begin{itemdecl} +bool is_debugger_present() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\required +This function has no preconditions. + +\pnum +\default +\impldef{default semantics of \tcode{is_debugger_present}}. + +\begin{note} +It is intended that, using an immediate (uncached) query to determine if the +program is being traced by a debugger, an implementation returns \tcode{true} +only when tracing the execution of the program with a debugger. On Windows or +equivalent systems, this can be achieved by calling the +\tcode{::IsDebuggerPresent()} Win32 function. For systems compatible with +ISO/IEC 23360:2021, this can be achieved by checking for a tracing process, with +a best-effort determination that such a tracing process is a debugger. +\end{note} + +\pnum +\remarks +This function is replaceable\iref{dcl.fct.def.replace}. + +\end{itemdescr} diff --git a/source/exceptions.tex b/source/exceptions.tex index 8dc2fcbc05..ba2d34d04c 100644 --- a/source/exceptions.tex +++ b/source/exceptions.tex @@ -257,14 +257,14 @@ \pnum Throwing an exception -initializes a temporary object, +initializes an object with dynamic storage duration, called the \defnx{exception object}{exception handling!exception object}. If the type of the exception object would be an incomplete type\iref{basic.types.general}, an abstract class type\iref{class.abstract}, or a pointer to an incomplete type other than -\cv{}~\keyword{void}\iref{basic.compound} +\cv{}~\keyword{void}\iref{basic.compound}, the program is ill-formed. \pnum @@ -309,12 +309,33 @@ \pnum \indextext{exception handling!exception object!constructor}% \indextext{exception handling!exception object!destructor}% -When the thrown object is a class object, the constructor selected for -the copy-initialization as well as the constructor selected for -a copy-initialization considering the thrown object as an lvalue -shall be non-deleted and accessible, even if the copy/move operation is -elided\iref{class.copy.elision}. -The destructor is potentially invoked\iref{class.dtor}. +Let \tcode{T} denote the type of the exception object. +Copy-initialization of an object of type \tcode{T} from +an lvalue of type \tcode{const T} in a context unrelated to \tcode{T} +shall be well-formed. +If \tcode{T} is a class type, +the selected constructor is odr-used\iref{basic.def.odr} and +the destructor of \tcode{T} is potentially invoked\iref{class.dtor}. + +\pnum +\indextext{exception handling!uncaught}% +An exception is considered \defnx{uncaught}{uncaught exception} +after completing the initialization of the exception object +until completing the activation of a handler for the exception\iref{except.handle}. +\begin{note} +As a consequence, an exception is considered uncaught +during any stack unwinding resulting from it being thrown. +\end{note} + +\pnum +\indexlibraryglobal{uncaught_exceptions}% +If an exception is rethrown\iref{expr.throw,propagation}, +it is considered uncaught from the point of rethrow +until the rethrown exception is caught. +\begin{note} +The function \tcode{std::uncaught_exceptions}\iref{uncaught.exceptions} +returns the number of uncaught exceptions in the current thread. +\end{note} \pnum \indextext{exception handling!rethrow}% @@ -330,7 +351,7 @@ \indextext{exception handling!terminate called@\tcode{terminate} called}% \indextext{\idxcode{terminate}!called}% If the exception handling mechanism -handling an uncaught exception\iref{except.uncaught} +handling an uncaught exception directly invokes a function that exits via an exception, the function \tcode{std::terminate} is invoked\iref{except.terminate}. \begin{example} @@ -358,7 +379,7 @@ \end{note} -\rSec1[except.ctor]{Constructors and destructors}% +\rSec1[except.ctor]{Stack unwinding}% \indextext{exception handling!constructors and destructors}% \indextext{constructor!exception handling|see{exception handling, constructors and destructors}}% \indextext{destructor!exception handling|see{exception handling, constructors and destructors}} @@ -603,10 +624,7 @@ \tcode{...} in a handler's \grammarterm{exception-declaration} -functions similarly to -\tcode{...} -in a function parameter declaration; -it specifies a match for any exception. +specifies a match for any exception. If present, a \tcode{...} handler shall be the last handler for its try block. @@ -617,6 +635,40 @@ handler continues in a dynamically surrounding try block of the same thread. +\pnum +\indextext{exception handling!terminate called@\tcode{terminate} called}% +\indextext{\idxcode{terminate}!called}% +If the search for a handler +exits the function body of a function with a +non-throwing exception specification, +the function \tcode{std::terminate}\iref{except.terminate} is invoked. +\begin{note} +An implementation is not permitted to reject an expression merely because, when +executed, it throws or might +throw an exception from a function with a non-throwing exception specification. +\end{note} +\begin{example} +\begin{codeblock} +extern void f(); // potentially-throwing + +void g() noexcept { + f(); // valid, even if \tcode{f} throws + throw 42; // valid, effectively a call to \tcode{std::terminate} +} +\end{codeblock} +The call to +\tcode{f} +is well-formed despite the possibility for it to throw an exception. +\end{example} + +\pnum +If no matching handler is found, +the function \tcode{std::terminate} is invoked; +whether or not the stack is unwound before this invocation of +\tcode{std::terminate} +is \impldef{stack unwinding before invocation of +\tcode{std::terminate}}\iref{except.terminate}. + \pnum A handler is considered \defnx{active}{exception handling!handler!active} when initialization is complete for the parameter (if any) of the catch clause. @@ -634,14 +686,6 @@ still active is called the \defnx{currently handled exception}{exception handling!currently handled exception}. -\pnum -If no matching handler is found, -the function \tcode{std::terminate} is invoked; -whether or not the stack is unwound before this invocation of -\tcode{std::terminate} -is \impldef{stack unwinding before invocation of -\tcode{std::terminate}}\iref{except.terminate}. - \pnum Referring to any non-static member or base class of an object in the handler for a @@ -727,7 +771,7 @@ \begin{bnf} \nontermdef{noexcept-specifier}\br \keyword{noexcept} \terminal{(} constant-expression \terminal{)}\br - \keyword{noexcept}\br + \keyword{noexcept} \end{bnf} \pnum @@ -806,33 +850,6 @@ has a non-throwing exception specification. \end{example} -\pnum -\indextext{exception handling!terminate called@\tcode{terminate} called}% -\indextext{\idxcode{terminate}!called}% -Whenever an exception is thrown -and the search for a handler\iref{except.handle} -encounters the outermost block of a function with a -non-throwing exception specification, -the function \tcode{std::terminate} is invoked\iref{except.terminate}. -\begin{note} -An implementation is not permitted to reject an expression merely because, when -executed, it throws or might -throw an exception from a function with a non-throwing exception specification. -\end{note} -\begin{example} -\begin{codeblock} -extern void f(); // potentially-throwing - -void g() noexcept { - f(); // valid, even if \tcode{f} throws - throw 42; // valid, effectively a call to \tcode{std::terminate} -} -\end{codeblock} -The call to -\tcode{f} -is well-formed despite the possibility for it to throw an exception. -\end{example} - \pnum An expression $E$ is \defnx{potentially-throwing}{potentially-throwing!expression} if @@ -849,7 +866,7 @@ (such as an overloaded operator, an allocation function in a \grammarterm{new-expression}, a constructor for a function argument, -or a destructor if $E$ is a full-expression\iref{intro.execution}) +or a destructor) that has a potentially-throwing exception specification, or \item @@ -970,9 +987,7 @@ \item in an expression, the function is selected by 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 -potentially-evaluated; +\item the function is odr-used\iref{term.odr.use}; \item the exception specification is compared to that of another declaration (e.g., an explicit specialization or an overriding virtual @@ -992,9 +1007,9 @@ \end{itemize} The exception specification of a defaulted function is evaluated as described above only when needed; similarly, the -\grammarterm{noexcept-specifier} of a specialization of a function -template or member function of a class template is instantiated only when -needed. +\grammarterm{noexcept-specifier} of a specialization +of a templated function +is instantiated only when needed. % \indextext{exception specification|)} @@ -1006,8 +1021,10 @@ The function \tcode{std::terminate}\iref{except.terminate} is used by the exception handling mechanism for coping with errors related to the exception handling -mechanism itself. The function -\tcode{std::current_exception()}\iref{propagation} and the class +mechanism itself. +The function \tcode{std::uncaught_exceptions}\iref{uncaught.exceptions} +reports how many exceptions are uncaught in the current thread. +The function \tcode{std::current_exception}\iref{propagation} and the class \tcode{std::nested_exception}\iref{except.nested} can be used by a program to capture the currently handled exception. @@ -1015,9 +1032,10 @@ \pnum \indextext{\idxcode{terminate}}% -% FIXME: What does it mean to abandon exception handling? -In some situations, exception handling is abandoned -for less subtle error handling techniques. +Some errors in a program cannot be recovered from, such as when an exception +is not handled or a \tcode{std::thread} object is destroyed while its thread +function is still executing. In such cases, +the function \tcode{std::terminate}\iref{exception.terminate} is invoked. \begin{note} These situations are: \indextext{\idxcode{terminate}!called}% @@ -1033,9 +1051,14 @@ \item% when the exception handling mechanism cannot find a handler for a thrown exception\iref{except.handle}, or -\item when the search for a handler\iref{except.handle} encounters the -outermost block of a function -with a non-throwing exception specification\iref{except.spec}, or +\item when the search for a handler\iref{except.handle} +exits the function body of a function +with a non-throwing exception specification\iref{except.spec}, +including when a contract-violation handler +invoked from an evaluation of +a function contract assertion\iref{basic.contract.eval} associated with the function +exits via an exception, +or \item% when the destruction of an object during stack unwinding\iref{except.ctor} @@ -1083,22 +1106,57 @@ \item% when a call to a \tcode{wait()}, \tcode{wait_until()}, or \tcode{wait_for()} function on a condition variable\iref{thread.condition.condvar,thread.condition.condvarany} -fails to meet a postcondition. +fails to meet a postcondition, or -\end{itemize} +\item% +when a callback invocation exits via an exception +when requesting stop on +a \tcode{std::stop_source} or +a \tcode{std::in\-place_stop_source}\iref{stopsource.mem,stopsource.inplace.mem}, +or in the constructor of +\tcode{std::stop_callback} or +\tcode{std::inplace_stop_callback}\iref{stopcallback.cons,stopcallback.inplace.cons} +when a callback invocation exits via an exception, or +\item% +when a \tcode{run_loop} object is destroyed +that is still in the \tcode{running} state\iref{exec.run.loop}, or + +\item% +when \tcode{unhandled_stopped} is called on +a \tcode{with_awaitable_senders} object\iref{exec.with.awaitable.senders} +whose continuation is not a handle to a coroutine +whose promise type has an \tcode{unhandled_stopped} member function, or + +\item% +when an object \tcode{scope} of type +\tcode{std::execution::simple_counting_scope} or +\tcode{std::execution::counting_scope} +is destroyed and +\tcode{scope.\exposid{state}} is not equal to +\exposid{joined}, +\exposid{unused}, or +\exposid{unused-and-closed}\iref{exec.simple.counting.ctor}, or + +\item% +when \tcode{std::execution::get_parallel_scheduler} is called and +\tcode{std::execution::system_context_replace\-ability::query_parallel_scheduler_backend()} +returns a null pointer value\iref{exec.par.scheduler}, or + +\item% +when an exception is thrown from a coroutine \tcode{std::execution::task}\iref{exec.task} +which doesn't support a \tcode{std::execution::set_error_t(std::exception_ptr)} completion. +\end{itemize} \end{note} \pnum \indextext{\idxcode{terminate}}% -In such cases, -the function \tcode{std::terminate} is invoked\iref{exception.terminate}. In the situation where no matching handler is found, it is \impldef{stack unwinding before invocation of \tcode{std::terminate}} whether or not the stack is unwound before \tcode{std::terminate} is invoked. -In the situation where the search for a handler\iref{except.handle} encounters the -outermost block of a function +In the situation where the search for a handler\iref{except.handle} +exits the function body of a function with a non-throwing exception specification\iref{except.spec}, it is \impldef{whether stack is unwound before invoking the function \tcode{std::terminate} when a \tcode{noexcept} specification is violated} @@ -1111,21 +1169,4 @@ prematurely based on a determination that the unwind process will eventually cause an invocation of the function \tcode{std::terminate}. - -\rSec2[except.uncaught]{The \tcode{std::uncaught_exceptions} function}% -\indexlibraryglobal{uncaught_exceptions} - -\pnum -An exception is considered uncaught -after completing the initialization of the exception object\iref{except.throw} -until completing the activation of a handler for the exception\iref{except.handle}. -\begin{note} -As a consequence, an exception is considered uncaught -during any stack unwinding resulting from it being thrown. -\end{note} -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} -returns the number of uncaught exceptions in the current thread.% \indextext{exception handling|)} diff --git a/source/exec.tex b/source/exec.tex new file mode 100644 index 0000000000..e87b52f52c --- /dev/null +++ b/source/exec.tex @@ -0,0 +1,8691 @@ +%!TEX root = std.tex +\rSec0[exec]{Execution control library} + +\rSec1[exec.general]{General} + +\pnum +This Clause describes components +supporting execution of function objects\iref{function.objects}. + +\pnum +The following subclauses describe +the requirements, concepts, and components +for execution control primitives as summarized in \tref{exec.summary}. + +\begin{libsumtab}{Execution control library summary}{exec.summary} +\ref{exec.sched} & Schedulers & \tcode{} \\ +\ref{exec.recv} & Receivers & \\ +\ref{exec.opstate} & Operation states & \\ +\ref{exec.snd} & Senders & \\ +\end{libsumtab} + +\pnum +\tref{exec.pos} shows +the types of customization point objects\iref{customization.point.object} +used in the execution control library. + +\begin{floattable}{Types of customization point objects in the execution control library}{exec.pos}{lx{0.23\hsize}x{0.45\hsize}} +\topline +\lhdr{Customization point} & \chdr{Purpose} & \rhdr{Examples} \\ +\lhdr{object type} & & \\ +\capsep +core & + provide core execution functionality, and connection between core components & + e.g., \tcode{connect}, \tcode{start} \\ +completion functions & + called by senders to announce the completion of the work (success, error, or cancellation) & + \tcode{set_value}, \tcode{set_error}, \tcode{set_stopped} \\ +senders & + allow the specialization of the provided sender algorithms & + \begin{itemize} + \item sender factories (e.g., \tcode{schedule}, \tcode{just}, \tcode{read_env}) + \item sender adaptors (e.g., \tcode{continues_on}, \tcode{then}, \tcode{let_value}) + \item sender consumers (e.g., \tcode{sync_wait}) + \end{itemize} + \\ +queries & + allow querying different properties of objects & + \begin{itemize} + \item general queries (e.g., \tcode{get_allocator}, \tcode{get_stop_token}) + \item environment queries (e.g., \tcode{get_scheduler}, \tcode{get_delegation_scheduler}) + \item scheduler queries (e.g., \tcode{get_forward_progress_guarantee}) + \item sender attribute queries (e.g., \tcode{get_completion_scheduler}) + \end{itemize} + \\ +\end{floattable} + +\pnum +This clause makes use of the following exposition-only entities. + +\pnum +For a subexpression \tcode{expr}, +let \tcode{\exposid{MANDATE-NOTHROW}(expr)} be +expression-equivalent to \tcode{expr}. + +\mandates +\tcode{noexcept(expr)} is \tcode{true}. + +\pnum +\begin{codeblock} +namespace std { + template + concept @\defexposconcept{movable-value}@ = // \expos + @\libconcept{move_constructible}@> && + @\libconcept{constructible_from}@, T> && + (!is_array_v>); +} +\end{codeblock} + +\pnum +For function types \tcode{F1} and \tcode{F2} denoting +\tcode{R1(Args1...)} and \tcode{R2(Args2...)}, respectively, +\tcode{\exposid{MATCHING-SIG}(F1, F2)} is \tcode{true} if and only if +\tcode{\libconcept{same_as}} +is \tcode{true}. + +\pnum +For a subexpression \tcode{err}, +let \tcode{Err} be \tcode{decltype((err))} and +let \tcode{\exposid{AS-EXCEPT-PTR}(err)} be: +\begin{itemize} +\item +\tcode{err} if \tcode{decay_t} denotes the type \tcode{exception_ptr}. + +\expects +\tcode{!err} is \tcode{false}. +\item +Otherwise, +\tcode{make_exception_ptr(system_error(err))} +if \tcode{decay_t} denotes the type \tcode{error_code}. +\item +Otherwise, \tcode{make_exception_ptr(err)}. +\end{itemize} + +\pnum +For a subexpression \tcode{expr}, +let \tcode{\exposid{AS-CONST}(expr)} be expression-equivalent to +\begin{codeblock} +[](const auto& x) noexcept -> const auto& { return x; }(expr) +\end{codeblock} + +\rSec1[exec.queryable]{Queries and queryables} + +\rSec2[exec.queryable.general]{General} + +\pnum +A \defnadj{queryable}{object} is +a read-only collection of key/value pair +where each key is a customization point object known as a \defn{query object}. +A \defn{query} is an invocation of a query object +with a queryable object as its first argument and +a (possibly empty) set of additional arguments. +A query imposes syntactic and semantic requirements on its invocations. + +\pnum +Let \tcode{q} be a query object, +let \tcode{args} be a (possibly empty) pack of subexpressions, +let \tcode{env} be a subexpression +that refers to a queryable object \tcode{o} of type \tcode{O}, and +let \tcode{cenv} be a subexpression referring to \tcode{o} +such that \tcode{decltype((cenv))} is \tcode{const O\&}. +The expression \tcode{q(env, args...)} is equal to\iref{concepts.equality} +the expression \tcode{q(cenv, args...)}. + +\pnum +The type of a query expression cannot be \tcode{void}. + +\pnum +The expression \tcode{q(env, args...)} is +equality-preserving\iref{concepts.equality} and +does not modify the query object or the arguments. + +\pnum +If the expression \tcode{env.query(q, args...)} is well-formed, +then it is expression-equivalent to \tcode{q(env, args...)}. + +\pnum +Unless otherwise specified, +the result of a query is valid as long as the queryable object is valid. + +\rSec2[exec.queryable.concept]{\tcode{queryable} concept} + +\begin{codeblock} +namespace std { + template + concept @\defexposconcept{queryable}@ = @\libconcept{destructible}@; // \expos +} +\end{codeblock} + +\pnum +The exposition-only \exposconcept{queryable} concept specifies +the constraints on the types of queryable objects. + +\pnum +Let \tcode{env} be an object of type \tcode{Env}. +The type \tcode{Env} models \exposconcept{queryable} +if for each callable object \tcode{q} and a pack of subexpressions \tcode{args}, +if \tcode{requires \{ q(env, args...) \}} is \tcode{true} then +\tcode{q(env, args...)} meets any semantic requirements imposed by \tcode{q}. + +\rSec1[exec.async.ops]{Asynchronous operations} + +\pnum +An \defnadj{execution}{resource} is a program entity that manages +a (possibly dynamic) set of execution agents\iref{thread.req.lockable.general}, +which it uses to execute parallel work on behalf of callers. +\begin{example} +The currently active thread, +a system-provided thread pool, and +uses of an API associated with an external hardware accelerator +are all examples of execution resources. +\end{example} +Execution resources execute asynchronous operations. +An execution resource is either valid or invalid. + +\pnum +An \defnadj{asynchronous}{operation} is +a distinct unit of program execution that +\begin{itemize} +\item +is explicitly created; +\item +can be explicitly started once at most; +\item +once started, eventually completes exactly once +with a (possibly empty) set of result datums and +in exactly one of three \defnx{dispositions}{disposition}: +success, failure, or cancellation; +\begin{itemize} +\item +A successful completion, also known as a \defnadj{value}{completion}, +can have an arbitrary number of result datums. +\item +A failure completion, also known as an \defnadj{error}{completion}, +has a single result datum. +\item +A cancellation completion, also known as a \defnadj{stopped}{completion}, +has no result datum. +\end{itemize} +An asynchronous operation's \defnadj{async}{result} +is its disposition and its (possibly empty) set of result datums. +\item +can complete on a different execution resource +than the execution resource on which it started; and +\item +can create and start other asynchronous operations +called \defnadj{child}{operations}. +A child operation is an asynchronous operation +that is created by the parent operation and, +if started, completes before the parent operation completes. +A \defnadj{parent}{operation} is the asynchronous operation +that created a particular child operation. +\end{itemize} +\begin{note} +An asynchronous operation can execute synchronously; +that is, it can complete during the execution of its start operation +on the thread of execution that started it. +\end{note} + +\pnum +An asynchronous operation has associated state +known as its \defnadj{operation}{state}. + +\pnum +An asynchronous operation has an associated environment. +An \defn{environment} is a queryable object\iref{exec.queryable} +representing the execution-time properties of the operation's caller. +The caller of an asynchronous operation is +its parent operation or the function that created it. + +\pnum +An asynchronous operation has an associated receiver. +A \defn{receiver} is an aggregation of three handlers +for the three asynchronous completion dispositions: +\begin{itemize} +\item a value completion handler for a value completion, +\item an error completion handler for an error completion, and +\item a stopped completion handler for a stopped completion. +\end{itemize} +A receiver has an associated environment. +An asynchronous operation's operation state owns the operation's receiver. +The environment of an asynchronous operation +is equal to its receiver's environment. + +\pnum +For each completion disposition, there is a \defnadj{completion}{function}. +A completion function is +a customization point object\iref{customization.point.object} +that accepts an asynchronous operation's receiver as the first argument and +the result datums of the asynchronous operation as additional arguments. +The value completion function invokes +the receiver's value completion handler with the value result datums; +likewise for the error completion function and the stopped completion function. +A completion function has +an associated type known as its \defnadj{completion}{tag} +that is the unqualified type of the completion function. +A valid invocation of a completion function is called +a \defnadj{completion}{operation}. + +\pnum +The \defn{lifetime of an asynchronous operation}, +also known as the operation's \defn{async lifetime}, +begins when its start operation begins executing and +ends when its completion operation begins executing. +If the lifetime of an asynchronous operation's associated operation state +ends before the lifetime of the asynchronous operation, +the behavior is undefined. +After an asynchronous operation executes a completion operation, +its associated operation state is invalid. +Accessing any part of an invalid operation state is undefined behavior. + +\pnum +An asynchronous operation shall not execute a completion operation +before its start operation has begun executing. +After its start operation has begun executing, +exactly one completion operation shall execute. +The lifetime of an asynchronous operation's operation state can end +during the execution of the completion operation. + +\pnum +A \defn{sender} is a factory for one or more asynchronous operations. +\defnx{Connecting}{connect} a sender and a receiver creates +an asynchronous operation. +The asynchronous operation's associated receiver is equal to +the receiver used to create it, and +its associated environment is equal to +the environment associated with the receiver used to create it. +The lifetime of an asynchronous operation's associated operation state +does not depend on the lifetimes of either the sender or the receiver +from which it was created. +A sender is started when it is connected to a receiver and +the resulting asynchronous operation is started. +A sender's async result is the async result of the asynchronous operation +created by connecting it to a receiver. +A sender sends its results by way of the asynchronous operation(s) it produces, +and a receiver receives those results. +A sender is either valid or invalid; +it becomes invalid when its parent sender (see below) becomes invalid. + +\pnum +A \defn{scheduler} is an abstraction of an execution resource +with a uniform, generic interface for scheduling work onto that resource. +It is a factory for senders +whose asynchronous operations execute value completion operations +on an execution agent belonging to +the scheduler's associated execution resource. +A \defn{schedule-expression} obtains such a sender from a scheduler. +A \defn{schedule sender} is the result of a schedule expression. +On success, an asynchronous operation produced by a schedule sender executes +a value completion operation with an empty set of result datums. +Multiple schedulers can refer to the same execution resource. +A scheduler can be valid or invalid. +A scheduler becomes invalid when the execution resource to which it refers +becomes invalid, +as do any schedule senders obtained from the scheduler, and +any operation states obtained from those senders. + +\pnum +An asynchronous operation has one or more associated completion schedulers +for each of its possible dispositions. +A \defn{completion scheduler} is a scheduler +whose associated execution resource is used to execute +a completion operation for an asynchronous operation. +A value completion scheduler is a scheduler +on which an asynchronous operation's value completion operation can execute. +Likewise for error completion schedulers and stopped completion schedulers. + +\pnum +A sender has an associated queryable object\iref{exec.queryable} +known as its \defnx{attributes}{attribute} +that describes various characteristics of the sender and +of the asynchronous operation(s) it produces. +For each disposition, +there is a query object for reading the associated completion scheduler +from a sender's attributes; +i.e., a value completion scheduler query object +for reading a sender's value completion scheduler, etc. +If a completion scheduler query is well-formed, +the returned completion scheduler is unique +for that disposition for any asynchronous operation the sender creates. +A schedule sender is required to have a value completion scheduler attribute +whose value is equal to the scheduler that produced the schedule sender. + +\pnum +A \defn{completion signature} is a function type +that describes a completion operation. +An asynchronous operation has a finite set of possible completion signatures +corresponding to the completion operations +that the asynchronous operation potentially evaluates\iref{basic.def.odr}. +For a completion function \tcode{set}, +receiver \tcode{rcvr}, and +pack of arguments \tcode{args}, +let \tcode{c} be the completion operation \tcode{set(rcvr, args...)}, and +let \tcode{F} be +the function type \tcode{decltype(auto(set))(decltype((args))...)}. +A completion signature \tcode{Sig} is associated with \tcode{c} +if and only if +\tcode{\exposid{MATCHING-SIG}(Sig, F)} is \tcode{true}\iref{exec.general}. +Together, a sender type and an environment type \tcode{Env} determine +the set of completion signatures of an asynchronous operation +that results from connecting the sender with a receiver +that has an environment of type \tcode{Env}. +The type of the receiver does not affect +an asynchronous operation's completion signatures, +only the type of the receiver's environment. +A \defnadj{non-dependent}{sender} is a sender type +whose completion signatures are knowable +independent of an execution environment. + +\pnum +A sender algorithm is a function that takes and/or returns a sender. +There are three categories of sender algorithms: +\begin{itemize} +\item +A \defn{sender factory} is a function +that takes non-senders as arguments and that returns a sender. +\item +A \defn{sender adaptor} is a function +that constructs and returns a parent sender +from a set of one or more child senders and +a (possibly empty) set of additional arguments. +An asynchronous operation created by a parent sender is +a parent operation to the child operations created by the child senders. +\item +A \defn{sender consumer} is a function +that takes one or more senders and +a (possibly empty) set of additional arguments, and +whose return type is not the type of a sender. +\end{itemize} + +\rSec1[execution.syn]{Header \tcode{} synopsis} + +\indexheader{execution}% +\begin{codeblock} +namespace std { + // \ref{execpol.type}, execution policy type trait + template struct is_execution_policy; // freestanding + template constexpr bool @\libglobal{is_execution_policy_v}@ = // freestanding + is_execution_policy::value; +} + +namespace std::execution { + // \ref{execpol.seq}, sequenced execution policy + class sequenced_policy; + + // \ref{execpol.par}, parallel execution policy + class parallel_policy; + + // \ref{execpol.parunseq}, parallel and unsequenced execution policy + class parallel_unsequenced_policy; + + // \ref{execpol.unseq}, unsequenced execution policy + class unsequenced_policy; + + // \ref{execpol.objects}, execution policy objects + inline constexpr sequenced_policy seq{ @\unspec@ }; + inline constexpr parallel_policy par{ @\unspec@ }; + inline constexpr parallel_unsequenced_policy par_unseq{ @\unspec@ }; + inline constexpr unsequenced_policy unseq{ @\unspec@ }; +} + +namespace std { + // \ref{exec.general}, helper concepts + template + concept @\exposconceptnc{movable-value}@ = @\seebelownc@; // \expos + + template + concept @\defexposconceptnc{decays-to}@ = @\libconcept{same_as}@, To>; // \expos + + template + concept @\defexposconceptnc{class-type}@ = @\exposconceptnc{decays-to}@ && is_class_v; // \expos + + // \ref{exec.queryable}, queryable objects + template + concept @\exposconceptnc{queryable}@ = @\seebelownc@; // \expos + + // \ref{exec.queries}, queries + struct @\libglobal{forwarding_query_t}@ { @\unspec@ }; + struct @\libglobal{get_allocator_t}@ { @\unspec@ }; + struct @\libglobal{get_stop_token_t}@ { @\unspec@ }; + + inline constexpr forwarding_query_t @\libglobal{forwarding_query}@{}; + inline constexpr get_allocator_t @\libglobal{get_allocator}@{}; + inline constexpr get_stop_token_t @\libglobal{get_stop_token}@{}; + + template + using stop_token_of_t = remove_cvref_t()))>; + + template + concept @\defexposconceptnc{forwarding-query}@ = forwarding_query(T{}); // \expos +} + +namespace std::execution { + // \ref{exec.queries}, queries + struct @\libglobal{get_domain_t}@ { @\unspec@ }; + struct @\libglobal{get_scheduler_t}@ { @\unspec@ }; + struct @\libglobal{get_delegation_scheduler_t}@ { @\unspec@ }; + struct @\libglobal{get_forward_progress_guarantee_t}@ { @\unspec@ }; + template + struct @\libglobal{get_completion_scheduler_t}@ { @\unspec@ }; + struct get_await_completion_adaptor_t { @\unspec@ }; + + inline constexpr get_domain_t @\libglobal{get_domain}@{}; + inline constexpr get_scheduler_t @\libglobal{get_scheduler}@{}; + inline constexpr get_delegation_scheduler_t @\libglobal{get_delegation_scheduler}@{}; + enum class forward_progress_guarantee; + inline constexpr get_forward_progress_guarantee_t @\libglobal{get_forward_progress_guarantee}@{}; + template + constexpr get_completion_scheduler_t @\libglobal{get_completion_scheduler}@{}; + inline constexpr get_await_completion_adaptor_t get_await_completion_adaptor{}; + + struct @\libglobal{get_env_t}@ { @\unspec@ }; + inline constexpr get_env_t @\libglobal{get_env}@{}; + + template + using @\libglobal{env_of_t}@ = decltype(get_env(declval())); + + // \ref{exec.prop}, class template \tcode{prop} + template + struct prop; + + // \ref{exec.env}, class template \tcode{env} + template<@\exposconcept{queryable}@... Envs> + struct env; + + // \ref{exec.domain.default}, execution domains + struct default_domain; + + // \ref{exec.sched}, schedulers + struct @\libglobal{scheduler_t}@ {}; + + template + concept @\libconcept{scheduler}@ = @\seebelow@; + + // \ref{exec.recv}, receivers + struct @\libglobal{receiver_t}@ {}; + + template + concept @\libconcept{receiver}@ = @\seebelow@; + + template + concept @\libconcept{receiver_of}@ = @\seebelow@; + + struct @\libglobal{set_value_t}@ { @\unspec@ }; + struct @\libglobal{set_error_t}@ { @\unspec@ }; + struct @\libglobal{set_stopped_t}@ { @\unspec@ }; + + inline constexpr set_value_t @\libglobal{set_value}@{}; + inline constexpr set_error_t @\libglobal{set_error}@{}; + inline constexpr set_stopped_t @\libglobal{set_stopped}@{}; + + // \ref{exec.opstate}, operation states + struct @\libglobal{operation_state_t}@ {}; + + template + concept @\libconcept{operation_state}@ = @\seebelow@; + + struct @\libglobal{start_t}@; + inline constexpr start_t @\libglobal{start}@{}; + + // \ref{exec.snd}, senders + struct @\libglobal{sender_t}@ {}; + + template + concept @\libconcept{sender}@ = @\seebelow@; + + template + concept @\libconcept{sender_in}@ = @\seebelow@; + + template + concept @\libconcept{dependent_sender}@ = @\seebelow@; + + template + concept @\libconcept{sender_to}@ = @\seebelow@; + + template + struct @\exposidnc{type-list}@; // \expos + + template + using @\exposidnc{decayed-tuple}@ = tuple...>; // \expos + + template + using @\exposidnc{variant-or-empty}@ = @\seebelownc@; // \expos + + template, + template class Tuple = @\exposid{decayed-tuple}@, + template class Variant = @\exposid{variant-or-empty}@> + requires @\libconcept{sender_in}@ + using value_types_of_t = @\seebelow@; + + template, + template class Variant = @\exposid{variant-or-empty}@> + requires @\libconcept{sender_in}@ + using error_types_of_t = @\seebelow@; + + template> + requires @\libconcept{sender_in}@ + constexpr bool sends_stopped = @\seebelow@; + + template + using @\exposidnc{single-sender-value-type}@ = @\seebelownc@; // \expos + + template + concept @\exposconcept{single-sender}@ = @\seebelow@; // \expos + + template<@\libconcept{sender}@ Sndr> + using tag_of_t = @\seebelow@; + + // \ref{exec.snd.transform}, sender transformations + template + requires (sizeof...(Env) <= 1) + constexpr @\libconcept{sender}@ decltype(auto) transform_sender( + Domain dom, Sndr&& sndr, const Env&... env) noexcept(@\seebelow@); + + // \ref{exec.snd.transform.env}, environment transformations + template + constexpr @\exposconcept{queryable}@ decltype(auto) transform_env( + Domain dom, Sndr&& sndr, Env&& env) noexcept; + + // \ref{exec.snd.apply}, sender algorithm application + template + constexpr decltype(auto) apply_sender( + Domain dom, Tag, Sndr&& sndr, Args&&... args) noexcept(@\seebelow@); + + // \ref{exec.connect}, the connect sender algorithm + struct @\libglobal{connect_t}@; + inline constexpr connect_t @\libglobal{connect}@{}; + + template + using @\libglobal{connect_result_t}@ = + decltype(connect(declval(), declval())); + + // \ref{exec.factories}, sender factories + struct @\libglobal{just_t}@ { @\unspec@ }; + struct @\libglobal{just_error_t}@ { @\unspec@ }; + struct @\libglobal{just_stopped_t}@ { @\unspec@ }; + struct @\libglobal{schedule_t}@ { @\unspec@ }; + + inline constexpr just_t @\libglobal{just}@{}; + inline constexpr just_error_t @\libglobal{just_error}@{}; + inline constexpr just_stopped_t @\libglobal{just_stopped}@{}; + inline constexpr schedule_t @\libglobal{schedule}@{}; + inline constexpr @\unspec@ @\libglobal{read_env}@{}; + + template<@\libconcept{scheduler}@ Sch> + using @\libglobal{schedule_result_t}@ = decltype(schedule(declval())); + + // \ref{exec.adapt}, sender adaptors + template<@\exposconcept{class-type}@ D> + struct @\libglobal{sender_adaptor_closure}@ { }; + + struct @\libglobal{starts_on_t}@ { @\unspec@ }; + struct @\libglobal{continues_on_t}@ { @\unspec@ }; + struct @\libglobal{on_t}@ { @\unspec@ }; + struct @\libglobal{schedule_from_t}@ { @\unspec@ }; + struct @\libglobal{then_t}@ { @\unspec@ }; + struct @\libglobal{upon_error_t}@ { @\unspec@ }; + struct @\libglobal{upon_stopped_t}@ { @\unspec@ }; + struct @\libglobal{let_value_t}@ { @\unspec@ }; + struct @\libglobal{let_error_t}@ { @\unspec@ }; + struct @\libglobal{let_stopped_t}@ { @\unspec@ }; + struct @\libglobal{bulk_t}@ { @\unspec@ }; + struct @\libglobal{bulk_chunked_t}@ { @\unspec@ }; + struct @\libglobal{bulk_unchunked_t}@ { @\unspec@ }; + struct @\libglobal{when_all_t}@ { @\unspec@ }; + struct @\libglobal{when_all_with_variant_t}@ { @\unspec@ }; + struct @\libglobal{into_variant_t}@ { @\unspec@ }; + struct @\libglobal{stopped_as_optional_t}@ { @\unspec@ }; + struct @\libglobal{stopped_as_error_t}@ { @\unspec@ }; + struct @\libglobal{associate_t}@ { @\unspec@ }; + struct @\libglobal{spawn_future_t}@ { @\unspec@ }; + + inline constexpr @\unspec@ @\libglobal{write_env}@{}; + inline constexpr @\unspec@ @\libglobal{unstoppable}@{}; + inline constexpr starts_on_t @\libglobal{starts_on}@{}; + inline constexpr continues_on_t @\libglobal{continues_on}@{}; + inline constexpr on_t @\libglobal{on}@{}; + inline constexpr schedule_from_t @\libglobal{schedule_from}@{}; + inline constexpr then_t @\libglobal{then}@{}; + inline constexpr upon_error_t @\libglobal{upon_error}@{}; + inline constexpr upon_stopped_t @\libglobal{upon_stopped}@{}; + inline constexpr let_value_t @\libglobal{let_value}@{}; + inline constexpr let_error_t @\libglobal{let_error}@{}; + inline constexpr let_stopped_t @\libglobal{let_stopped}@{}; + inline constexpr bulk_t @\libglobal{bulk}@{}; + inline constexpr bulk_chunked_t @\libglobal{bulk_chunked}@{}; + inline constexpr bulk_unchunked_t @\libglobal{bulk_unchunked}@{}; + inline constexpr when_all_t @\libglobal{when_all}@{}; + inline constexpr when_all_with_variant_t @\libglobal{when_all_with_variant}@{}; + inline constexpr into_variant_t @\libglobal{into_variant}@{}; + inline constexpr stopped_as_optional_t @\libglobal{stopped_as_optional}@{}; + inline constexpr stopped_as_error_t @\libglobal{stopped_as_error}@{}; + inline constexpr associate_t @\libglobal{associate}@{}; + inline constexpr spawn_future_t @\libglobal{spawn_future}@{}; + + // \ref{exec.cmplsig}, completion signatures + template + concept @\exposconceptnc{completion-signature}@ = @\seebelownc@; // \expos + + template<@\exposconcept{completion-signature}@... Fns> + struct @\libglobal{completion_signatures}@; + + template + concept @\exposconceptnc{valid-completion-signatures}@ = @\seebelownc@; // \expos + + struct dependent_sender_error : exception {}; + + // \ref{exec.getcomplsigs} + template + consteval auto get_completion_signatures() -> @\exposconcept{valid-completion-signatures}@ auto; + + template + requires @\libconcept{sender_in}@ + using completion_signatures_of_t = decltype(get_completion_signatures()); + + // \ref{exec.run.loop}, run_loop + class run_loop; +} + +namespace std::this_thread { + // \ref{exec.consumers}, consumers + struct @\libglobal{sync_wait_t}@ { @\unspec@ }; + struct @\libglobal{sync_wait_with_variant_t}@ { @\unspec@ }; + + inline constexpr sync_wait_t @\libglobal{sync_wait}@{}; + inline constexpr sync_wait_with_variant_t @\libglobal{sync_wait_with_variant}@{}; +} + +namespace std::execution { + // \ref{exec.consumers}, consumers + struct @\libglobal{spawn_t}@ { @\unspec@ }; + inline constexpr spawn_t spawn{}; + + // \ref{exec.as.awaitable} + struct @\libglobal{as_awaitable_t}@ { @\unspec@ }; + inline constexpr as_awaitable_t @\libglobal{as_awaitable}@{}; + + // \ref{exec.with.awaitable.senders} + template<@\exposconcept{class-type}@ Promise> + struct with_awaitable_senders; + + // \ref{exec.scope.concepts}, scope concepts + template + concept @\libconcept{scope_token}@ = @\seebelow@; + + // \ref{exec.scope.simple.counting} + class simple_counting_scope; + + // \ref{exec.scope.counting} + class counting_scope; +} + +namespace std::execution { + // \ref{exec.par.scheduler}, parallel scheduler + class @\libglobal{parallel_scheduler}@ { @\unspec@ }; + parallel_scheduler get_parallel_scheduler(); +} + +// \ref{exec.sysctxrepl}, namespace \tcode{system_context_replaceability} +namespace std::execution::@\libglobal{system_context_replaceability}@ { + struct receiver_proxy; + struct bulk_item_receiver_proxy; + struct parallel_scheduler_backend; + + shared_ptr query_parallel_scheduler_backend(); +} + +namespace std::execution { + // \ref{exec.affine.on} + struct @\libglobal{affine_on_t}@ { @\unspec@ }; + inline constexpr affine_on_t @\libglobal{affine_on}@{}; + + // \ref{exec.inline.scheduler} + class @\libglobal{inline_scheduler}@; + + // \ref{exec.task.scheduler} + class @\libglobal{task_scheduler}@; + + template + struct @\libglobal{with_error}@ { + using type = remove_cvref_t; + type error; + }; + template + with_error(E) -> with_error; + + template<@\libconcept{scheduler}@ Sch> + struct change_coroutine_scheduler { + using type = remove_cvref_t; + type scheduler; + }; + template<@\libconcept{scheduler}@ Sch> + change_coroutine_scheduler(Sch) -> change_coroutine_scheduler; + + // \ref{exec.task} + template + class @\libglobal{task}@; +} +\end{codeblock} + +\pnum +The exposition-only type \tcode{\exposid{variant-or-empty}} +is defined as follows: +\begin{itemize} +\item +If \tcode{sizeof...(Ts)} is greater than zero, +\tcode{\exposid{variant-or-empty}} denotes \tcode{variant} +where \tcode{Us...} is the pack \tcode{decay_t...} +with duplicate types removed. +\item +Otherwise, \tcode{\exposid{variant-or-empty}} denotes +the exposition-only class type: +\begin{codeblock} +namespace std::execution { + struct @\exposidnc{empty-variant}@ { // \expos + @\exposidnc{empty-variant}@() = delete; + }; +} +\end{codeblock} +\end{itemize} + +\pnum +For type \tcode{Sndr} and pack of types \tcode{Env}, +let \tcode{CS} be \tcode{completion_signatures_of_t}. +Then \tcode{\exposid{single-sender-value-type}} is ill-formed +if \tcode{CS} is ill-formed or +if \tcode{sizeof...(Env) > 1} is \tcode{true}; +otherwise, it is an alias for: +\begin{itemize} +\item +\tcode{\exposid{gather-signatures}} +if that type is well-formed, +\item +Otherwise, \tcode{void} +if \tcode{\exposid{gather-signatures}} is +\tcode{variant>} or \tcode{variant<>}, +\item +Otherwise, \tcode{\exposid{gather-signatures}} +if that\linebreak{} type is well-formed, +\item +Otherwise, \tcode{\exposid{single-sender-value-type}} is ill-formed. +\end{itemize} + +\pnum +The exposition-only concept \exposconcept{single-sender} is defined as follows: +\begin{codeblock} +namespace std::execution { + template + concept @\defexposconcept{single-sender}@ = @\libconcept{sender_in}@ && + requires { + typename @\exposid{single-sender-value-type}@; + }; +} +\end{codeblock} + +\pnum +A type satisfies and models the exposition-only concept +\defexposconcept{valid-completion-signatures} if +it is a specialization of the \tcode{completion_signatures} class template. + +\rSec1[exec.queries]{Queries} + +\rSec2[exec.fwd.env]{\tcode{forwarding_query}} + +\pnum +\tcode{forwarding_query} asks a query object +whether it should be forwarded through queryable adaptors. + +\pnum +The name \tcode{forwarding_query} denotes a query object. +For some query object \tcode{q} of type \tcode{Q}, +\tcode{forwarding_query(q)} is expression-equivalent to: +\begin{itemize} +\item +\tcode{\exposid{MANDATE-NOTHROW}(q.query(forwarding_query))} +if that expression is well-formed. + +\mandates +The expression above has type \tcode{bool} and +is a core constant expression if \tcode{q} is a core constant expression. +\item +Otherwise, \tcode{true} if \tcode{\libconcept{derived_from}} is \tcode{true}. +\item +Otherwise, \tcode{false}. +\end{itemize} + +\rSec2[exec.get.allocator]{\tcode{get_allocator}} + +\pnum +\tcode{get_allocator} asks a queryable object for its associated allocator. + +\pnum +The name \tcode{get_allocator} denotes a query object. +For a subexpression \tcode{env}, +\tcode{get_allocator(env)} is expression-equivalent to +\tcode{\exposid{MANDATE-NOTHROW}(\exposid{AS-CONST}(env).query(get_allocator))}. + +\mandates +If the expression above is well-formed, +its type satisfies +\exposconcept{simple-allocator}\iref{allocator.requirements.general}. + +\pnum +\tcode{forwarding_query(get_allocator)} is a core constant expression and +has value \tcode{true}. + +\rSec2[exec.get.stop.token]{\tcode{get_stop_token}} + +\pnum +\tcode{get_stop_token} asks a queryable object for an associated stop token. + +\pnum +The name \tcode{get_stop_token} denotes a query object. +For a subexpression \tcode{env}, +\tcode{get_stop_token(env)} is expression-equivalent to: +\begin{itemize} +\item +\tcode{\exposid{MANDATE-NOTHROW}(\exposid{AS-CONST}(env).query(get_stop_token))} +if that expression is well-formed. + +\mandates +The type of the expression above satisfies \libconcept{stoppable_token}. + +\item +Otherwise, \tcode{never_stop_token\{\}}. +\end{itemize} + +\pnum +\tcode{forwarding_query(get_stop_token)} is a core constant expression and +has value \tcode{true}. + +\rSec2[exec.get.env]{\tcode{execution::get_env}} + +\pnum +\tcode{execution::get_env} is a customization point object. +For a subexpression \tcode{o}, +\tcode{execution::get_env(o)} is expression-equivalent to: +\begin{itemize} +\item +\tcode{\exposid{MANDATE-NOTHROW}(\exposid{AS-CONST}(o).get_env())} +if that expression is well-formed. + +\mandates +The type of the expression above satisfies +\exposconcept{queryable}\iref{exec.queryable}. +\item +Otherwise, \tcode{env<>\{\}}. +\end{itemize} + +\pnum +The value of \tcode{get_env(o)} shall be valid while \tcode{o} is valid. + +\pnum +\begin{note} +When passed a sender object, +\tcode{get_env} returns the sender's associated attributes. +When passed a receiver, +\tcode{get_env} returns the receiver's associated execution environment. +\end{note} + +\rSec2[exec.get.domain]{\tcode{execution::get_domain}} + +\pnum +\tcode{get_domain} asks a queryable object +for its associated execution domain tag. + +\pnum +The name \tcode{get_domain} denotes a query object. +For a subexpression \tcode{env}, +\tcode{get_domain(env)} is expression-equivalent to +\tcode{\exposid{MANDATE-NOTHROW}(\exposid{AS-CONST}(env).query(get_domain))}. + +\pnum +\tcode{forwarding_query(execution::get_domain)} is +a core constant expression and has value \tcode{true}. + +\rSec2[exec.get.scheduler]{\tcode{execution::get_scheduler}} + +\pnum +\tcode{get_scheduler} asks a queryable object for its associated scheduler. + +\pnum +The name \tcode{get_scheduler} denotes a query object. +For a subexpression \tcode{env}, +\tcode{get_scheduler(env)} is expression-equivalent to +\tcode{\exposid{MANDATE-NOTHROW}(\exposid{AS-CONST}(env).query(get_scheduler))}. + +\mandates +If the expression above is well-formed, +its type satisfies \libconcept{scheduler}. + +\pnum +\tcode{forwarding_query(execution::get_scheduler)} is +a core constant expression and has value \tcode{true}. + +\rSec2[exec.get.delegation.scheduler]{\tcode{execution::get_delegation_scheduler}} + +\pnum +\tcode{get_delegation_scheduler} asks a queryable object for a scheduler +that can be used to delegate work to +for the purpose of forward progress delegation\iref{intro.progress}. + +\pnum +The name \tcode{get_delegation_scheduler} denotes a query object. +For a subexpression \tcode{env}, +\tcode{get_delegation_scheduler(env)} is expression-equivalent to +\tcode{\exposid{MANDATE-NOTHROW}(\exposid{AS-CONST}(env).query(get_delegation_scheduler))}. + +\mandates +If the expression above is well-formed, +its type satisfies \libconcept{scheduler}. + +\pnum +\tcode{forwarding_query(execution::get_delegation_scheduler)} is +a core constant expression and has value \tcode{true}. + +\rSec2[exec.get.fwd.progress]{\tcode{execution::get_forward_progress_guarantee}} + +\begin{codeblock} +namespace std::execution { + enum class @\libglobal{forward_progress_guarantee}@ { + concurrent, + parallel, + weakly_parallel + }; +} +\end{codeblock} + +\pnum +\tcode{get_forward_progress_guarantee} asks a scheduler about +the forward progress guarantee of execution agents +created by that scheduler's associated execution resource\iref{intro.progress}. + +\pnum +The name \tcode{get_forward_progress_guarantee} denotes a query object. +For a subexpression \tcode{sch}, let \tcode{Sch} be \tcode{decltype((sch))}. +If \tcode{Sch} does not satisfy \libconcept{scheduler}, +\tcode{get_forward_progress_guarantee} is ill-formed. +Otherwise, +\tcode{get_forward_progress_guarantee(sch)} is expression-equivalent to: +\begin{itemize} +\item +\tcode{\exposid{MANDATE-NOTHROW}(\exposid{AS-CONST}(sch).query(get_forward_progress_guarantee))}, +if that expression is well-formed. + +\mandates +The type of the expression above is \tcode{forward_progress_guarantee}. +\item +Otherwise, \tcode{forward_progress_guarantee::weakly_parallel}. +\end{itemize} + +\pnum +If \tcode{get_forward_progress_guarantee(sch)} for some scheduler \tcode{sch} +returns \tcode{forward_progress_guaran\-tee::concurrent}, +all execution agents created by that scheduler's associated execution resource +shall provide the concurrent forward progress guarantee. +If it returns \tcode{forward_progress_guarantee::parallel}, +all such execution agents +shall provide at least the parallel forward progress guarantee. + +\rSec2[exec.get.compl.sched]{\tcode{execution::get_completion_scheduler}} + +\pnum +\tcode{get_completion_scheduler<\exposid{completion-tag>}} obtains +the completion scheduler associated with a completion tag +from a sender's attributes. + +\pnum +The name \tcode{get_completion_scheduler} denotes a query object template. +For a subexpression \tcode{q}, +the expression \tcode{get_completion_scheduler<\exposid{completion-tag}>(q)} +is ill-formed if \exposid{completion-tag} is not one of +\tcode{set_value_t}, \tcode{set_error_t}, or \tcode{set_stopped_t}. +Otherwise, \tcode{get_completion_scheduler<\exposid{completion-tag}>(q)} +is expression-equivalent to +\begin{codeblock} +@\exposid{MANDATE-NOTHROW}@(@\exposid{AS-CONST}@(q).query(get_completion_scheduler<@\exposid{completion-tag}@>)) +\end{codeblock} +\mandates +If the expression above is well-formed, +its type satisfies \libconcept{scheduler}. + +\pnum +Let \exposid{completion-fn} be a completion function\iref{exec.async.ops}; +let \exposid{completion-tag} be +the associated completion tag of \exposid{completion-fn}; +let \tcode{args} be a pack of subexpressions; and +let \tcode{sndr} be a subexpression +such that \tcode{\libconcept{sender}} is \tcode{true} and +\tcode{get_completion_scheduler<\exposid{completion-tag}>(get_env(sndr))} +is well-formed and denotes a scheduler \tcode{sch}. +If an asynchronous operation +created by connecting \tcode{sndr} with a receiver \tcode{rcvr} +causes the evaluation of \tcode{\exposid{completion-fn}(rcvr, args...)}, +the behavior is undefined +unless the evaluation happens on an execution agent +that belongs to \tcode{sch}'s associated execution resource. + +\pnum +The expression +\tcode{forwarding_query(get_completion_scheduler<\exposid{completion-tag}>)} +is a core constant expression and has value \tcode{true}. + +\rSec2[exec.get.await.adapt]{\tcode{execution::get_await_completion_adaptor}} + +\pnum +\tcode{get_await_completion_adaptor} asks a queryable object for +its associated awaitable completion adaptor. + +\pnum +The name \tcode{get_await_completion_adaptor} denotes a query object. +For a subexpression \tcode{env}, +\begin{codeblock} +get_await_completion_adaptor(env) +\end{codeblock} +is expression-equivalent to +\begin{codeblock} +@\exposidnc{MANDATE-NOTHROW}@(@\exposid{AS-CONST}@(env).query(get_await_completion_adaptor)) +\end{codeblock} + +\pnum +\tcode{forwarding_query(execution::get_await_completion_adaptor)} +is a core constant expression and has value \tcode{true}. + +\rSec1[exec.sched]{Schedulers} + +\pnum +The \libconcept{scheduler} concept defines +the requirements of a scheduler type\iref{exec.async.ops}. +\tcode{schedule} is a customization point object +that accepts a scheduler. +A valid invocation of \tcode{schedule} is a schedule-expression. +\begin{codeblock} +namespace std::execution { + template + concept @\deflibconcept{scheduler}@ = + @\libconcept{derived_from}@::scheduler_concept, scheduler_t> && + @\exposconcept{queryable}@ && + requires(Sch&& sch) { + { schedule(std::forward(sch)) } -> @\libconcept{sender}@; + { auto(get_completion_scheduler( + get_env(schedule(std::forward(sch))))) } + -> @\libconcept{same_as}@>; + } && + @\libconcept{equality_comparable}@> && + @\libconcept{copyable}@>; +} +\end{codeblock} + +\pnum +Let \tcode{Sch} be the type of a scheduler and +let \tcode{Env} be the type of an execution environment +for which \tcode{\libconcept{sender_in}, Env>} +is satisfied. +Then \tcode{\exposconcept{sender-in-of}, Env>} +shall be modeled. + +\pnum +No operation required by +\tcode{\libconcept{copyable}>} and +\tcode{\libconcept{equality_comparable}>} +shall exit via an exception. +None of these operations, +nor a scheduler type's \tcode{schedule} function, +shall introduce data races +as a result of potentially concurrent\iref{intro.races} invocations +of those operations from different threads. + +\pnum +For any two values \tcode{sch1} and \tcode{sch2} +of some scheduler type \tcode{Sch}, +\tcode{sch1 == sch2} shall return \tcode{true} +only if both \tcode{sch1} and \tcode{sch2} share +the same associated execution resource. + +\pnum +For a given scheduler expression \tcode{sch}, +the expression +\tcode{get_completion_scheduler(get_env(schedule(sch)))} +shall compare equal to \tcode{sch}. + +\pnum +For a given scheduler expression \tcode{sch}, +if the expression \tcode{get_domain(sch)} is well-formed, +then the expression \tcode{get_domain(get_env(schedule(sch)))} +is also well-formed and has the same type. + +\pnum +A scheduler type's destructor shall not block +pending completion of any receivers +connected to the sender objects returned from \tcode{schedule}. +\begin{note} +The ability to wait for completion of submitted function objects +can be provided by the associated execution resource of the scheduler. +\end{note} + +\rSec1[exec.recv]{Receivers} + +\rSec2[exec.recv.concepts]{Receiver concepts} + +\pnum +A receiver represents the continuation of an asynchronous operation. +The \libconcept{receiver} concept defines +the requirements for a receiver type\iref{exec.async.ops}. +The \libconcept{receiver_of} concept defines +the requirements for a receiver type that is usable as +the first argument of a set of completion operations +corresponding to a set of completion signatures. +The \tcode{get_env} customization point object is used to access +a receiver's associated environment. +\begin{codeblock} +namespace std::execution { + template + concept @\deflibconcept{receiver}@ = + @\libconcept{derived_from}@::receiver_concept, receiver_t> && + requires(const remove_cvref_t& rcvr) { + { get_env(rcvr) } -> @\exposconcept{queryable}@; + } && + @\libconcept{move_constructible}@> && // rvalues are movable, and + @\libconcept{constructible_from}@, Rcvr>; // lvalues are copyable + + template + concept @\defexposconcept{valid-completion-for}@ = // \expos + requires (Signature* sig) { + [](Tag(*)(Args...)) + requires @\exposconcept{callable}@, Args...> + {}(sig); + }; + + template + concept @\defexposconcept{has-completions}@ = // \expos + requires (Completions* completions) { + []<@\exposconcept{valid-completion-for}@...Sigs>(completion_signatures*) + {}(completions); + }; + + template + concept @\deflibconcept{receiver_of}@ = + @\libconcept{receiver}@ && @\exposconcept{has-completions}@; +} +\end{codeblock} + +\pnum +Class types that are marked \tcode{final} do not model the \libconcept{receiver} concept. + +\pnum +Let \tcode{rcvr} be a receiver and +let \tcode{op_state} be an operation state associated with +an asynchronous operation created by connecting \tcode{rcvr} with a sender. +Let \tcode{token} be a stop token equal to +\tcode{get_stop_token(get_env(rcvr))}. +\tcode{token} shall remain valid +for the duration of the asynchronous operation's lifetime\iref{exec.async.ops}. +\begin{note} +This means that, unless it knows about further guarantees +provided by the type of \tcode{rcvr}, +the implementation of \tcode{op_state} cannot use \tcode{token} +after it executes a completion operation. +This also implies that any stop callbacks registered on token +must be destroyed before the invocation of the completion operation. +\end{note} + +\rSec2[exec.set.value]{\tcode{execution::set_value}} + +\pnum +\tcode{set_value} is a value completion function\iref{exec.async.ops}. +Its associated completion tag is \tcode{set_value_t}. +The expression \tcode{set_value(rcvr, vs...)} +for a subexpression \tcode{rcvr} and +pack of subexpressions \tcode{vs} is ill-formed +if \tcode{rcvr} is an lvalue or an rvalue of const type. +Otherwise, it is expression-equivalent to +\tcode{\exposid{MANDATE-NOTHROW}(rcvr.set_value(vs...))}. + +\rSec2[exec.set.error]{\tcode{execution::set_error}} + +\pnum +\tcode{set_error} is an error completion function\iref{exec.async.ops}. +Its associated completion tag is \tcode{set_error_t}. +The expression \tcode{set_error(rcvr, err)} +for some subexpressions \tcode{rcvr} and \tcode{err} is ill-formed +if \tcode{rcvr} is an lvalue or an rvalue of const type. +Otherwise, it is expression-equivalent to +\tcode{\exposid{MANDATE-NOTHROW}(rcvr.set_error(err))}. + +\rSec2[exec.set.stopped]{\tcode{execution::set_stopped}} + +\pnum +\tcode{set_stopped} is a stopped completion function\iref{exec.async.ops}. +Its associated completion tag is \tcode{set_stopped_t}. +The expression \tcode{set_stopped(rcvr)} +for a subexpression \tcode{rcvr} is ill-formed +if \tcode{rcvr} is an lvalue or an rvalue of const type. +Otherwise, it is expression-equivalent to +\tcode{\exposid{MANDATE-NOTHROW}(rcvr.set_stopped())}. + +\rSec1[exec.opstate]{Operation states} + +\rSec2[exec.opstate.general]{General} + +\pnum +The \libconcept{operation_state} concept defines +the requirements of an operation state type\iref{exec.async.ops}. +\begin{codeblock} +namespace std::execution { + template + concept @\deflibconcept{operation_state}@ = + @\libconcept{derived_from}@ && + requires (O& o) { + start(o); + }; +} +\end{codeblock} + +\pnum +If an \libconcept{operation_state} object is destroyed +during the lifetime of its asynchronous operation\iref{exec.async.ops}, +the behavior is undefined. +\begin{note} +The \libconcept{operation_state} concept does not impose requirements +on any operations other than destruction and \tcode{start}, +including copy and move operations. +Invoking any such operation on an object +whose type models \libconcept{operation_state} can lead to undefined behavior. +\end{note} + +\pnum +The program is ill-formed +if it performs a copy or move construction or assignment operation on +an operation state object created by connecting a library-provided sender. + +\rSec2[exec.opstate.start]{\tcode{execution::start}} + +\pnum +The name \tcode{start} denotes a customization point object +that starts\iref{exec.async.ops} +the asynchronous operation associated with the operation state object. +For a subexpression \tcode{op}, +the expression \tcode{start(op)} is ill-formed +if \tcode{op} is an rvalue. +Otherwise, it is expression-equivalent to +\tcode{\exposid{MANDATE-NOTHROW}(op.start())}. + +\pnum +If \tcode{op.start()} does not start\iref{exec.async.ops} +the asynchronous operation associated with the operation state \tcode{op}, +the behavior of calling \tcode{start(op)} is undefined. + +\rSec1[exec.snd]{Senders} + +\rSec2[exec.snd.general]{General} + +\pnum +Subclauses \ref{exec.factories} and \ref{exec.adapt} define +customizable algorithms that return senders. +Each algorithm has a default implementation. +Let \tcode{sndr} be the result of an invocation of such an algorithm or +an object equal to the result\iref{concepts.equality}, and +let \tcode{Sndr} be \tcode{decltype((sndr))}. +Let \tcode{rcvr} be a receiver of type \tcode{Rcvr} +with associated environment \tcode{env} of type \tcode{Env} +such that \tcode{\libconcept{sender_to}} is \tcode{true}. +For the default implementation of the algorithm that produced \tcode{sndr}, +connecting \tcode{sndr} to \tcode{rcvr} and +starting the resulting operation state\iref{exec.async.ops} +necessarily results in the potential evaluation\iref{basic.def.odr} of +a set of completion operations +whose first argument is a subexpression equal to \tcode{rcvr}. +Let \tcode{Sigs} be a pack of completion signatures corresponding to +this set of completion operations, and +let \tcode{CS} be +the type of the expression \tcode{get_completion_signatures()}. +Then \tcode{CS} is +a specialization of +the class template \tcode{completion_signatures}\iref{exec.cmplsig}, +the set of whose template arguments is \tcode{Sigs}. +If none of the types in \tcode{Sigs} are dependent on the type \tcode{Env}, then +the expression \tcode{get_completion_signatures()} is well-formed and +its type is \tcode{CS}. +If a user-provided implementation of the algorithm +that produced \tcode{sndr} is selected instead of the default: + +\begin{itemize} +\item +Any completion signature +that is in the set of types +denoted by \tcode{completion_signatures_of_t} and +that is not part of \tcode{Sigs} shall correspond to +error or stopped completion operations, +unless otherwise specified. + +\item +If none of the types in \tcode{Sigs} are dependent on the type \tcode{Env}, then +\tcode{completion_signatures_of_t} and +\tcode{completion_signatures_of_t} +shall denote the same type. +\end{itemize} + +\rSec2[exec.snd.expos]{Exposition-only entities} + +\pnum +Subclause \ref{exec.snd} makes use of the following exposition-only entities. + +\pnum +\indexlibraryglobal{\exposid{FWD-ENV}}% +For a queryable object \tcode{env}, +\tcode{\exposid{FWD-ENV}(env)} is an expression +whose type satisfies \exposconcept{queryable} +such that for a query object \tcode{q} and +a pack of subexpressions \tcode{as}, +the expression \tcode{\exposid{FWD-ENV}(env).query(q, as...)} is ill-formed +if \tcode{forwarding_query(q)} is \tcode{false}; +otherwise, it is expression-equivalent to \tcode{env.query(q, as...)}. +\indexlibraryglobal{\exposid{FWD-ENV-T}}% +The type \tcode{\exposid{FWD-ENV-T}(Env)} is +\tcode{decltype(\exposid{FWD-ENV}(declval()))}. + +\pnum +For a query object \tcode{q} and a subexpression \tcode{v}, +\tcode{\exposid{MAKE-ENV}(q, v)} is an expression \tcode{env} +whose type satisfies \exposconcept{queryable} +such that the result of \tcode{env.query(q)} has +a value equal to \tcode{v}\iref{concepts.equality}. +Unless otherwise stated, +the object to which \tcode{env.query(q)} refers remains valid +while \tcode{env} remains valid. + +\pnum +For two queryable objects \tcode{env1} and \tcode{env2}, +a query object \tcode{q}, and +a pack of subexpressions \tcode{as}, +\tcode{\exposid{JOIN-ENV}(env1, env2)} is an expression \tcode{env3} +whose type satisfies \exposconcept{queryable} +such that \tcode{env3.query(q, as...)} is expression-equivalent to: +\begin{itemize} +\item +\tcode{env1.query(q, as...)} if that expression is well-formed, +\item +otherwise, \tcode{env2.query(q, as...)} if that expression is well-formed, +\item +otherwise, \tcode{env3.query(q, as...)} is ill-formed. +\end{itemize} + +\pnum +The results of \exposid{FWD-ENV}, \exposid{MAKE-ENV}, and \exposid{JOIN-ENV} +can be context-dependent; +i.e., they can evaluate to expressions +with different types and value categories +in different contexts for the same arguments. + +\pnum +For a scheduler \tcode{sch}, +\tcode{\exposid{SCHED-ATTRS}(sch)} is an expression \tcode{o1} +whose type satisfies \exposconcept{queryable} +such that \tcode{o1.query(get_completion_scheduler)} is +an expression with the same type and value as \tcode{sch} +where \tcode{Tag} is one of \tcode{set_value_t} or \tcode{set_stopped_t}, and +such that \tcode{o1.query(get_domain)} is expression-equivalent to +\tcode{sch.query(get_domain)}. +\tcode{\exposid{SCHED-ENV}(sch)} is an expression \tcode{o2} +whose type satisfies \exposconcept{queryable} +such that \tcode{o2.query(get_scheduler)} is a prvalue +with the same type and value as \tcode{sch}, and +such that \tcode{o2.query(get_domain)} is expression-equivalent to +\tcode{sch.query(get_domain)}. + +\pnum +For two subexpressions \tcode{rcvr} and \tcode{expr}, +\tcode{\exposid{SET-VALUE}(rcvr, expr)} is expression-equivalent to +\tcode{(expr, set_value(std::move(rcvr)))} +if the type of \tcode{expr} is \tcode{void}; +otherwise, \tcode{set_value(std::move(rcvr), expr)}. +\tcode{\exposid{TRY-EVAL}(rcvr, expr)} is equivalent to: +\begin{codeblock} +try { + expr; +} catch(...) { + set_error(std::move(rcvr), current_exception()); +} +\end{codeblock} +if \tcode{expr} is potentially-throwing; otherwise, \tcode{expr}. +\tcode{\exposid{TRY-SET-VALUE}(rcvr, expr)} is +\begin{codeblock} +@\exposid{TRY-EVAL}@(rcvr, @\exposid{SET-VALUE}@(rcvr, expr)) +\end{codeblock} +except that \tcode{rcvr} is evaluated only once. + +\begin{itemdecl} +template + constexpr auto @\exposid{completion-domain}@(const Sndr& sndr) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{\exposid{COMPL-DOMAIN}(T)} is the type of the expression +\tcode{get_domain(get_completion_scheduler(get_env(sndr)))}. + +\pnum +\effects +If all of the types +\tcode{\exposid{COMPL-DOMAIN}(set_value_t)}, +\tcode{\exposid{COMPL-DOMAIN}(set_error_t)}, and\linebreak +\tcode{\exposid{COMPL-DOMAIN}(set_stopped_t)} are ill-formed, +\tcode{completion-domain(sndr)} is +a default-constructed prvalue of type \tcode{Default}. +Otherwise, if they all share a common type\iref{meta.trans.other} +(ignoring those types that are ill-formed), +then \tcode{\exposid{completion-domain}(sndr)} is +a default-constructed prvalue of that type. +Otherwise, \tcode{\exposid{completion-domain}(sndr)} is ill-formed. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr decltype(auto) @\exposid{query-with-default}@( + Tag, const Env& env, Default&& value) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{e} be the expression \tcode{Tag()(env)} +if that expression is well-formed; +otherwise, it is \tcode{static_cast(std::forward(value))}. + +\pnum +\returns +\tcode{e}. + +\pnum +\remarks +The expression in the noexcept clause is \tcode{noexcept(e)}. +\end{itemdescr} + +\begin{itemdecl} +template + constexpr auto @\exposid{get-domain-early}@(const Sndr& sndr) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return Domain(); +\end{codeblock} +where \tcode{Domain} is +the decayed type of the first of the following expressions that is well-formed: +\begin{itemize} +\item \tcode{get_domain(get_env(sndr))} +\item \tcode{\exposid{completion-domain}(sndr)} +\item \tcode{default_domain()} +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr auto @\exposid{get-domain-late}@(const Sndr& sndr, const Env& env) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{itemize} +\item +If \tcode{\exposconcept{sender-for}} is \tcode{true}, then +\begin{codeblock} +return Domain(); +\end{codeblock} +where \tcode{Domain} is the type of the following expression: +\begin{codeblock} +[] { + auto [_, sch, _] = sndr; + return @\exposid{query-with-default}@(get_domain, sch, default_domain()); +}(); +\end{codeblock} +\begin{note} +The \tcode{continues_on} algorithm works +in tandem with \tcode{schedule_from}\iref{exec.schedule.from} +to give scheduler authors a way to customize both +how to transition onto (\tcode{continues_on}) and off of (\tcode{schedule_from}) +a given execution context. +Thus, \tcode{continues_on} ignores the domain of the predecessor and +uses the domain of the destination scheduler to select a customization, +a property that is unique to \tcode{continues_on}. +That is why it is given special treatment here. +\end{note} +\item +Otherwise, +\begin{codeblock} +return Domain(); +\end{codeblock} +where \tcode{Domain} is the first of the following expressions +that is well-formed and whose type is not \tcode{void}: +\begin{itemize} +\item \tcode{get_domain(get_env(sndr))} +\item \tcode{\exposid{completion-domain}(sndr)} +\item \tcode{get_domain(env)} +\item \tcode{get_domain(get_scheduler(env))} +\item \tcode{default_domain()} +\end{itemize} +\end{itemize} +\end{itemdescr} + +\pnum +\begin{codeblock} +template<@\exposconcept{callable}@ Fun> + requires is_nothrow_move_constructible_v +struct @\exposid{emplace-from}@ { + Fun @\exposid{fun}@; // \expos + using type = @\exposid{call-result-t}@; + + constexpr operator type() && noexcept(@\exposconcept{nothrow-callable}@) { + return std::move(fun)(); + } + + constexpr type operator()() && noexcept(@\exposconcept{nothrow-callable}@) { + return std::move(fun)(); + } +}; +\end{codeblock} +\begin{note} +\exposid{emplace-from} is used to emplace non-movable types +into \tcode{tuple}, \tcode{optional}, \tcode{variant}, and similar types. +\end{note} + +\pnum +\begin{codeblock} +struct @\exposid{on-stop-request}@ { + inplace_stop_source& @\exposid{stop-src}@; // \expos + void operator()() noexcept { @\exposid{stop-src}@.request_stop(); } +}; +\end{codeblock} + +\pnum +\begin{codeblock} +template +struct @\exposid{product-type}@ { // \expos + T@$_0$@ t@$_0$@; // \expos + T@$_1$@ t@$_1$@; // \expos + @\vdots@ + T@$_n$@ t@$_n$@; // \expos + + template + constexpr decltype(auto) @\exposid{get}@(this Self&& self) noexcept; // \expos + + template + constexpr decltype(auto) @\exposid{apply}@(this Self&& self, Fn&& fn) // \expos + noexcept(@\seebelow@); +}; +\end{codeblock} + +\pnum +\begin{note} +\exposid{product-type} is presented here in pseudo-code form +for the sake of exposition. +It can be approximated in standard \Cpp{} with a tuple-like implementation +that takes care to keep the type an aggregate +that can be used as the initializer of a structured binding declaration. +\end{note} +\begin{note} +An expression of type \exposid{product-type} is usable as +the initializer of a structured binding declaration\iref{dcl.struct.bind}. +\end{note} + +\begin{itemdecl} +template +constexpr decltype(auto) @\exposid{get}@(this Self&& self) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto& [...ts] = self; +return std::forward_like(ts...[I]); +\end{codeblock} +\end{itemdescr} + +\begin{codeblock} +template +constexpr decltype(auto) @\exposid{apply}@(this Self&& self, Fn&& fn) noexcept(@\seebelow@); +\end{codeblock} + +\begin{itemdescr} +\pnum +\constraints +The expression in the \tcode{return} statement below is well-formed. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto& [...ts] = self; +return std::forward(fn)(std::forward_like(ts)...); +\end{codeblock} + +\pnum +\remarks +The expression in the \tcode{noexcept} clause is \tcode{true} +if the \tcode{return} statement above is not potentially throwing; +otherwise, \tcode{false}. +\end{itemdescr} + +\pnum +Let \exposconcept{valid-specialization} be the following concept: +\begin{codeblock} +namespace std::execution { + template class T, class... Args> + concept @\defexposconceptnc{valid-specialization}@ = // \expos + requires { typename T; }; +} +\end{codeblock} + +\begin{itemdecl} +template + constexpr auto @\exposid{make-sender}@(Tag tag, Data&& data, Child&&... child); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The following expressions are \tcode{true}: +\begin{itemize} +\item \tcode{\libconcept{semiregular}} +\item \tcode{\exposconcept{movable-value}} +\item \tcode{(\libconcept{sender} \&\& ...)} +\item% +\tcode{\libconcept{dependent_sender} || \libconcept{sender_in}}, +where \tcode{Sndr} is \tcode{\exposid{basic-sender}} +as defined below. + + \recommended +If evaluation of \tcode{\libconcept{sender_in}} results in +an uncaught exception from +the evaluation of \tcode{get_completion_signatures()}, +the implementation should include information about that exception in +the resulting diagnostic. +\end{itemize} + +\pnum +\returns +A prvalue of +type \tcode{\exposid{basic-sender}, decay_t...>} +that has been direct-list-initialized with the forwarded arguments, +where \exposid{basic-sender} is the following exposition-only class template except as noted below. +\end{itemdescr} + +\begin{codeblock} +namespace std::execution { + template + concept @\defexposconceptnc{completion-tag}@ = // \expos + @\libconcept{same_as}@ || @\libconcept{same_as}@ || @\libconcept{same_as}@; + + struct @\exposidnc{default-impls}@ { // \expos + static constexpr auto @\exposidnc{get-attrs}@ = @\seebelownc@; // \expos + static constexpr auto @\exposidnc{get-env}@ = @\seebelownc@; // \expos + static constexpr auto @\exposidnc{get-state}@ = @\seebelownc@; // \expos + static constexpr auto @\exposidnc{start}@ = @\seebelownc@; // \expos + static constexpr auto @\exposidnc{complete}@ = @\seebelownc@; // \expos + + template + static consteval void @\exposidnc{check-types}@(); // \expos + }; + + template + struct @\exposidnc{impls-for}@ : @\exposidnc{default-impls}@ {}; // \expos + + template // \expos + using @\exposid{state-type}@ = decay_t<@\exposid{call-result-t}@< + decltype(@\exposid{impls-for}@>::@\exposid{get-state}@), Sndr, Rcvr&>>; + + template // \expos + using @\exposid{env-type}@ = @\exposid{call-result-t}@< + decltype(@\exposid{impls-for}@>::@\exposid{get-env}@), Index, + @\exposid{state-type}@&, const Rcvr&>; + + template + using @\exposidnc{data-type}@ = decltype(declval().template @\exposidnc{get}@<1>()); // \expos + + template + using @\exposidnc{child-type}@ = decltype(declval().template @\exposidnc{get}@()); // \expos + + template + using @\exposidnc{indices-for}@ = remove_reference_t::@\exposidnc{indices-for}@; // \expos + + template + struct @\exposidnc{basic-state}@ { // \expos + @\exposid{basic-state}@(Sndr&& sndr, Rcvr&& rcvr) noexcept(@\seebelow@) + : @\exposid{rcvr}@(std::move(rcvr)) + , @\exposid{state}@(@\exposid{impls-for}@>::@\exposid{get-state}@(std::forward(sndr), @\exposid{rcvr}@)) { } + + Rcvr @\exposidnc{rcvr}@; // \expos + @\exposidnc{state-type}@ @\exposidnc{state}@; // \expos + }; + + template + requires @\exposconcept{valid-specialization}@<@\exposid{env-type}@, Index, Sndr, Rcvr> + struct @\exposidnc{basic-receiver}@ { // \expos + using receiver_concept = receiver_t; + + using @\exposidnc{tag-t}@ = tag_of_t; // \expos + using @\exposidnc{state-t}@ = @\exposidnc{state-type}@; // \expos + static constexpr const auto& @\exposidnc{complete}@ = @\exposidnc{impls-for}@<@\exposidnc{tag-t}@>::@\exposidnc{complete}@; // \expos + + template + requires @\exposconcept{callable}@ + void set_value(Args&&... args) && noexcept { + @\exposid{complete}@(Index(), op->@\exposid{state}@, op->@\exposid{rcvr}@, set_value_t(), std::forward(args)...); + } + + template + requires @\exposconcept{callable}@ + void set_error(Error&& err) && noexcept { + @\exposid{complete}@(Index(), op->@\exposid{state}@, op->@\exposid{rcvr}@, set_error_t(), std::forward(err)); + } + + void set_stopped() && noexcept + requires @\exposconcept{callable}@ { + @\exposid{complete}@(Index(), op->@\exposid{state}@, op->@\exposid{rcvr}@, set_stopped_t()); + } + + auto get_env() const noexcept -> @\exposid{env-type}@ { + return @\exposid{impls-for}@::@\exposid{get-env}@(Index(), op->@\exposid{state}@, op->@\exposid{rcvr}@); + } + + @\exposidnc{basic-state}@* @\exposidnc{op}@; // \expos + }; + + constexpr auto @\exposidnc{connect-all}@ = @\seebelownc@; // \expos + + template + using @\exposidnc{connect-all-result}@ = @\exposidnc{call-result-t}@< // \expos + decltype(@\exposid{connect-all}@), @\exposid{basic-state}@*, Sndr, @\exposid{indices-for}@>; + + template + requires @\exposconcept{valid-specialization}@<@\exposid{state-type}@, Sndr, Rcvr> && + @\exposconcept{valid-specialization}@<@\exposid{connect-all-result}@, Sndr, Rcvr> + struct @\exposidnc{basic-operation}@ : @\exposidnc{basic-state}@ { // \expos + using operation_state_concept = operation_state_t; + using @\exposidnc{tag-t}@ = tag_of_t; // \expos + + @\exposidnc{connect-all-result}@ @\exposidnc{inner-ops}@; // \expos + + @\exposidnc{basic-operation}@(Sndr&& sndr, Rcvr&& rcvr) noexcept(@\seebelownc@) // \expos + : @\exposid{basic-state}@(std::forward(sndr), std::move(rcvr)), + @\exposid{inner-ops}@(@\exposid{connect-all}@(this, std::forward(sndr), @\exposid{indices-for}@())) + {} + + void start() & noexcept { + auto& [...ops] = @\exposid{inner-ops}@; + @\exposid{impls-for}@::@\exposid{start}@(this->@\exposid{state}@, this->@\exposid{rcvr}@, ops...); + } + }; + + template + struct @\exposidnc{basic-sender}@ : @\exposidnc{product-type}@ { // \expos + using sender_concept = sender_t; + using @\exposidnc{indices-for}@ = index_sequence_for; // \expos + + decltype(auto) get_env() const noexcept { + auto& [_, data, ...child] = *this; + return @\exposid{impls-for}@::@\exposid{get-attrs}@(data, child...); + } + + template<@\exposconcept{decays-to}@<@\exposid{basic-sender}@> Self, @\libconcept{receiver}@ Rcvr> + auto connect(this Self&& self, Rcvr rcvr) noexcept(@\seebelow@) + -> @\exposid{basic-operation}@ { + return {std::forward(self), std::move(rcvr)}; + } + + template<@\exposconcept{decays-to}@<@\exposid{basic-sender}@> Self, class... Env> + static constexpr auto get_completion_signatures(); + }; +} +\end{codeblock} + +\pnum +The default template argument for the \tcode{Data} template parameter +denotes an unspecified empty trivially copyable class type +that models \libconcept{semiregular}. + +\pnum +It is unspecified whether a specialization of \exposid{basic-sender} +is an aggregate. + +\pnum +An expression of type \exposid{basic-sender} is usable as +the initializer of a structured binding declaration\iref{dcl.struct.bind}. + +\pnum +The expression in the \tcode{noexcept} clause of +the constructor of \exposid{basic-state} is +\begin{codeblock} +is_nothrow_move_constructible_v && +@\exposconcept{nothrow-callable}@>::@\exposid{get-state}@), Sndr, Rcvr&> && +(@\libconcept{same_as}@<@\exposid{state-type}@, @\exposid{get-state-result}@> || + is_nothrow_constructible_v<@\exposid{state-type}@, @\exposid{get-state-result}@>) +\end{codeblock} +where \exposid{get-state-result} is +\begin{codeblock} +@\exposid{call-result-t}@>::@\exposid{get-state}@), Sndr, Rcvr&>. +\end{codeblock} + +\pnum +The object \exposid{connect-all} is initialized with +a callable object equivalent to the following lambda: +\begin{itemdecl} +[]( + @\exposid{basic-state}@* op, Sndr&& sndr, index_sequence) noexcept(@\seebelow@) + -> decltype(auto) { + auto& [_, data, ...child] = sndr; + return @\exposid{product-type}@{connect( + std::forward_like(child), + @\exposid{basic-receiver}@>{op})...}; + } +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The expression in the \tcode{return} statement is well-formed. + +\pnum +\remarks +The expression in the \tcode{noexcept} clause is \tcode{true} +if the \tcode{return} statement is not potentially throwing; +otherwise, \tcode{false}. +\end{itemdescr} + +\pnum +The expression in the \tcode{noexcept} clause of +the constructor of \exposid{basic-operation} is: +\begin{codeblock} +is_nothrow_constructible_v<@\exposid{basic-state}@, Self, Rcvr> && +noexcept(@\exposid{connect-all}@(this, std::forward(sndr), @\exposid{indices-for}@())) +\end{codeblock} + +\pnum +The expression in the \tcode{noexcept} clause of +the \tcode{connect} member function of \exposid{basic-sender} is: +\begin{codeblock} +is_nothrow_constructible_v<@\exposid{basic-operation}@, Self, Rcvr> +\end{codeblock} + +\pnum +The member \tcode{\exposid{default-impls}::\exposid{get-attrs}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[](const auto&, const auto&... child) noexcept -> decltype(auto) { + if constexpr (sizeof...(child) == 1) + return (@\exposid{FWD-ENV}@(get_env(child)), ...); + else + return env<>(); +} +\end{codeblock} + +\pnum +The member \tcode{\exposid{default-impls}::\exposid{get-env}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[](auto, auto&, const auto& rcvr) noexcept -> decltype(auto) { + return @\exposid{FWD-ENV}@(get_env(rcvr)); +} +\end{codeblock} + +\pnum +The member \tcode{\exposid{default-impls}::\exposid{get-state}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[](Sndr&& sndr, Rcvr& rcvr) noexcept -> decltype(auto) { + auto& [_, data, ...child] = sndr; + return @\exposid{allocator-aware-forward}@(std::forward_like(data), rcvr); +} +\end{codeblock} + +\pnum +The member \tcode{\exposid{default-impls}::\exposid{start}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[](auto&, auto&, auto&... ops) noexcept -> void { + (execution::start(ops), ...); +} +\end{codeblock} + +\pnum +The member \tcode{\exposid{default-impls}::\exposid{complete}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[]( + Index, auto& state, Rcvr& rcvr, Tag, Args&&... args) noexcept + -> void requires @\exposconcept{callable}@ { + static_assert(Index::value == 0); + Tag()(std::move(rcvr), std::forward(args)...); +} +\end{codeblock} + +\indexlibrarymember{\exposid{check-types}}{\exposid{default-impls}}% +\begin{itemdecl} +template + static consteval void @\exposid{default-impls}@::@\exposid{check-types}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Is} be the pack of integral template arguments of +the \tcode{integer_sequence} specialization denoted by +\tcode{\exposid{indices-for}}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +(get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(), ...); +\end{codeblock} + +\pnum +\begin{note} +For any types \tcode{T} and \tcode{S}, and pack \tcode{E}, +let \tcode{e} be the expression +\tcode{\exposid{impls-for}::\exposid{check-types}()}. +Then exactly one of the following is \tcode{true}: +\begin{itemize} +\item \tcode{e} is ill-formed, or +\item the evaluation of \tcode{e} exits with an exception, or +\item \tcode{e} is a core constant expression. +\end{itemize} +When \tcode{e} is a core constant expression, +the pack \tcode{S, E...} uniquely determines a set of completion signatures. +\end{note} +\end{itemdescr} + +\indexlibrarymember{get_completion_signatures}{\exposid{basic-sender}}% +\begin{itemdecl} +template + template + constexpr auto @\exposid{basic-sender}@::get_completion_signatures(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Rcvr} be the type of a receiver whose +environment has type \tcode{E}, where +\tcode{E} is the first type in the list \tcode{Env..., env<>}. +Let \tcode{\placeholder{CHECK-TYPES}()} be the expression +\tcode{\exposid{impls-for}::template \exposid{check-types}<\linebreak{}Sndr, E>()}, and +let \tcode{CS} be a type determined as follows: + +\begin{itemize} +\item% +If \tcode{\exposid{CHECK-TYPES}()} is a core constant expression, +let \tcode{op} be an lvalue subexpression +whose type is \tcode{connect_result_t}. +Then \tcode{CS} is the specialization of \tcode{completion_signatures} +the set of whose template arguments +correspond to the set of completion operations +that are potentially evaluated\iref{basic.def.odr} +as a result of evaluating \tcode{op.start()}. + +\item% +Otherwise, \tcode{CS} is \tcode{completion_signatures<>}. +\end{itemize} + +\pnum +\constraints +\tcode{\exposid{CHECK-TYPES}()} is a well-formed expression. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{CHECK-TYPES}@(); +return CS(); +\end{codeblock} +\end{itemdescr} + +\pnum +\indexlibraryglobal{\exposid{overload-set}} +%%FIXME: Should this be in a namespace? +\begin{codeblock} +template +struct @\exposid{overload-set}@ : Fns... { + using Fns::operator()...; +}; +\end{codeblock} + +\pnum +\indexlibraryglobal{\exposid{not-a-sender}} +\indexlibrarymember{get_completion_signatures}{\exposid{not-a-sender}} +%%FIXME: Should this be in a namespace? +\begin{codeblock} +struct @\exposid{not-a-sender}@ { + using sender_concept = sender_t; + + template + static consteval auto get_completion_signatures() -> completion_signatures<> { + throw @\placeholder{unspecified-exception}@(); + } +}; +\end{codeblock} +where \tcode{\placeholder{unspecified-exception}} is +a type derived from \tcode{exception}. + +\pnum +\indexlibraryglobal{\exposid{decay-copyable-result-datums}} +%%FIXME: Should this be in a namespace? +\begin{codeblock} +constexpr void @\exposid{decay-copyable-result-datums}@(auto cs) { + cs.@\exposid{for-each}@([](Tag(*)(Ts...)) { + if constexpr (!(is_constructible_v, Ts> &&...)) + throw @\placeholder{unspecified-exception}@(); + }); +} +\end{codeblock} +where \tcode{\placeholder{unspecified-exception}} is +a type derived from \tcode{exception}. + +\begin{itemdecl} +template + decltype(auto) @\exposid{allocator-aware-forward}@(T&& obj, Context&& context); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\exposid{allocator-aware-forward} is an exposition-only function used to +either create a new object of type \tcode{T} from \tcode{obj} +or forward \tcode{obj} depending on whether an allocator is available. +If the environment associated with \tcode{context} provides an allocator +(i.e., the expression \tcode{get_allocator(get_env(context))} is valid, +let \exposid{alloc} be the result of this expression +and let \tcode{P} be \tcode{remove_cvref_t}. + +\pnum +\returns +\begin{itemize} +\item +If \exposid{alloc} is not defined, returns \tcode{std::forward(obj)}, +\item +otherwise if \tcode{P} is a specialization of \exposid{product-type}, +returns an object of type \tcode{P} whose elements are initialized using +\begin{codeblock} +make_obj_using_allocator(std::forward_like(e), @\exposid{alloc}@) +\end{codeblock} +where \tcode{e} is the corresponding element of \tcode{obj}, +\item +otherwise, returns \tcode{make_obj_using_allocator

(std::forward(obj), \exposid{alloc})}. +\end{itemize} +\end{itemdescr} + +\rSec2[exec.snd.concepts]{Sender concepts} + +\pnum +The \libconcept{sender} concept defines +the requirements for a sender type\iref{exec.async.ops}. +The \libconcept{sender_in} concept defines +the requirements for a sender type +that can create asynchronous operations given an associated environment type. +The \libconcept{sender_to} concept defines +the requirements for a sender type +that can connect with a specific receiver type. +The \tcode{get_env} customization point object is used to access +a sender's associated attributes. +The connect customization point object is used to connect\iref{exec.async.ops} +a sender and a receiver to produce an operation state. + +\indexlibraryglobal{\exposid{is-dependent-sender-helper}}% +\begin{codeblock} +namespace std::execution { + template + concept @\defexposconcept{is-constant}@ = true; // \expos + + template + concept @\defexposconcept{is-sender}@ = // \expos + @\libconcept{derived_from}@; + + template + concept @\defexposconcept{enable-sender}@ = // \expos + @\exposconcept{is-sender}@ || + @\exposconcept{is-awaitable}@>>; // \ref{exec.awaitable} + + template + inline constexpr bool enable_sender = @\exposconcept{enable-sender}@; + + template + consteval bool @\exposidnc{is-dependent-sender-helper}@() try { // \expos + get_completion_signatures(); + return false; + } catch (dependent_sender_error&) { + return true; + } + + template + concept @\deflibconcept{sender}@ = + enable_sender> && + requires (const remove_cvref_t& sndr) { + { get_env(sndr) } -> @\exposconcept{queryable}@; + } && + @\libconcept{move_constructible}@> && + @\libconcept{constructible_from}@, Sndr>; + + template + concept @\deflibconcept{sender_in}@ = + @\libconcept{sender}@ && + (sizeof...(Env) <= 1) && + (@\exposconcept{queryable}@ &&...) && + @\exposconcept{is-constant}@()>; + + template + concept @\deflibconcept{dependent_sender}@ = + @\libconcept{sender}@ && bool_constant<@\exposid{is-dependent-sender-helper}@()>::value; + + template + concept @\deflibconcept{sender_to}@ = + @\libconcept{sender_in}@> && + @\libconcept{receiver_of}@>> && + requires (Sndr&& sndr, Rcvr&& rcvr) { + connect(std::forward(sndr), std::forward(rcvr)); + }; +} +\end{codeblock} + +\pnum +For a type \tcode{Sndr}, if +\tcode{\libconcept{sender}} is \tcode{true} and +\tcode{\libconcept{dependent_sender}} is \tcode{false}, +then \tcode{Sndr} is a non-dependent sender\iref{exec.async.ops}. + +\pnum +Given a subexpression \tcode{sndr}, +let \tcode{Sndr} be \tcode{decltype((sndr))} and +let \tcode{rcvr} be a receiver +with an associated environment whose type is \tcode{Env}. +A completion operation is a \defnadj{permissible}{completion} +for \tcode{Sndr} and \tcode{Env} +if its completion signature appears in the argument list of the specialization of \tcode{completion_signatures} denoted by +\tcode{completion_signatures_of_t}. +\tcode{Sndr} and \tcode{Env} model \tcode{\libconcept{sender_in}} +if all the completion operations +that are potentially evaluated by connecting \tcode{sndr} to \tcode{rcvr} and +starting the resulting operation state +are permissible completions for \tcode{Sndr} and \tcode{Env}. + +\pnum +\remarks +Pursuant to \ref{namespace.std}, +users may specialize \tcode{enable_sender} to +\tcode{true} for cv-unqualified program-defined types that +model \libconcept{sender}, and +\tcode{false} for types that do not. +Such specializations shall +be usable in constant expressions\iref{expr.const} and +have type \tcode{const bool}. + +\pnum +The exposition-only concepts +\exposconcept{sender-of} and \exposconcept{sender-in-of} +define the requirements for a sender type +that completes with a given unique set of value result types. +\begin{codeblock} +namespace std::execution { + template + using @\exposid{value-signature}@ = set_value_t(As...); // \expos + + template + concept @\defexposconcept{sender-in-of-impl}@ = // \expos + @\libconcept{sender_in}@ && + @\exposid{MATCHING-SIG}@(SetValue, // see \ref{exec.general} + @\exposid{gather-signatures}@, + @\exposid{value-signature}@, + type_identity_t>); + + template + concept @\defexposconcept{sender-in-of}@ = // \expos + @\exposconcept{sender-in-of-impl}@; + + template + concept @\defexposconcept{sender-of}@ = // \expos + @\exposconcept{sender-in-of-impl}@; +} +\end{codeblock} + +\pnum +Let \tcode{sndr} be an expression +such that \tcode{decltype((sndr))} is \tcode{Sndr}. +The type \tcode{tag_of_t} is as follows: +\begin{itemize} +\item +If the declaration +\begin{codeblock} +auto&& [tag, data, ...children] = sndr; +\end{codeblock} +would be well-formed, \tcode{tag_of_t} is +an alias for \tcode{decltype(auto(tag))}. +\item +Otherwise, \tcode{tag_of_t} is ill-formed. +\end{itemize} + +\pnum +Let \exposconcept{sender-for} be an exposition-only concept defined as follows: +\begin{codeblock} +namespace std::execution { + template + concept @\defexposconcept{sender-for}@ = + @\libconcept{sender}@ && + @\libconcept{same_as}@, Tag>; +} +\end{codeblock} + +\pnum +For a type \tcode{T}, +\tcode{\exposid{SET-VALUE-SIG}(T)} denotes the type \tcode{set_value_t()} +if \tcode{T} is \cv{} \tcode{void}; +otherwise, it denotes the type \tcode{set_value_t(T)}. + +\pnum +Library-provided sender types +\begin{itemize} +\item +always expose an overload of a member \tcode{connect} +that accepts an rvalue sender and +\item +only expose an overload of a member \tcode{connect} +that accepts an lvalue sender if they model \libconcept{copy_constructible}. +\end{itemize} + +\rSec2[exec.awaitable]{Awaitable helpers} + +\pnum +The sender concepts recognize awaitables as senders. +For \ref{exec}, an \defn{awaitable} is an expression +that would be well-formed as the operand of a \tcode{co_await} expression +within a given context. + +\pnum +For a subexpression \tcode{c}, +let \tcode{\exposid{GET-AWAITER}(c, p)} be expression-equivalent to +the series of transformations and conversions applied to \tcode{c} +as the operand of an \grammarterm{await-expression} in a coroutine, +resulting in lvalue \tcode{e} as described by \ref{expr.await}, +where \tcode{p} is an lvalue referring to the coroutine's promise, +which has type \tcode{Promise}. +\begin{note} +This includes the invocation of +the promise type's \tcode{await_transform} member if any, +the invocation of the \tcode{operator co_await} +picked by overload resolution if any, and +any necessary implicit conversions and materializations. +\end{note} + +Let \tcode{\exposid{GET-AWAITER}(c)} be +expression-equivalent to \tcode{\exposid{GET-AWAITER}(c, q)} +where \tcode{q} is an lvalue of +an unspecified empty class type \tcode{\placeholder{none-such}} that +lacks an \tcode{await_transform} member, and +where \tcode{coroutine_handle<\placeholder{none-such}>} behaves as +\tcode{coroutine_handle}. + +\pnum +Let \exposconcept{is-awaitable} be the following exposition-only concept: +\begin{codeblock} +namespace std { + template + concept @\exposconcept{await-suspend-result}@ = @\seebelow@; // \expos + + template + concept @\defexposconcept{is-awaiter}@ = // \expos + requires (A& a, coroutine_handle h) { + a.await_ready() ? 1 : 0; + { a.await_suspend(h) } -> @\exposconcept{await-suspend-result}@; + a.await_resume(); + }; + + template + concept @\defexposconcept{is-awaitable}@ = // \expos + requires (C (*fc)() noexcept, Promise&... p) { + { @\exposid{GET-AWAITER}@(fc(), p...) } -> @\exposconcept{is-awaiter}@; + }; +} +\end{codeblock} + +\tcode{\defexposconcept{await-suspend-result}} is \tcode{true} +if and only if one of the following is \tcode{true}: +\begin{itemize} +\item \tcode{T} is \tcode{void}, or +\item \tcode{T} is \tcode{bool}, or +\item \tcode{T} is a specialization of \tcode{coroutine_handle}. +\end{itemize} + +\pnum +For a subexpression \tcode{c} +such that \tcode{decltype((c))} is type \tcode{C}, and +an lvalue \tcode{p} of type \tcode{Promise}, +\tcode{\exposid{await-result-\newline type}} denotes +the type \tcode{decltype(\exposid{GET-AWAITER}(c, p).await_resume())} and +\tcode{\exposid{await-re\-sult-type}} denotes +the type \tcode{decltype(\exposid{GET-AWAITER}(c).await_resume())}. + +\pnum +Let \exposid{with-await-transform} be the exposition-only class template: +\begin{codeblock} +namespace std::execution { + template + concept @\defexposconcept{has-as-awaitable}@ = // \expos + requires (T&& t, Promise& p) { + { std::forward(t).as_awaitable(p) } -> @\exposconcept{is-awaitable}@; + }; + + template + struct @\exposid{with-await-transform}@ { // \expos + template + T&& await_transform(T&& value) noexcept { + return std::forward(value); + } + + template<@\exposconcept{has-as-awaitable}@ T> + auto await_transform(T&& value) + noexcept(noexcept(std::forward(value).as_awaitable(declval()))) + -> decltype(std::forward(value).as_awaitable(declval())) { + return std::forward(value).as_awaitable(static_cast(*this)); + } + }; +} +\end{codeblock} + +\pnum +Let \exposid{env-promise} be the exposition-only class template: +\begin{codeblock} +namespace std::execution { + template + struct @\exposid{env-promise}@ : @\exposid{with-await-transform}@<@\exposid{env-promise}@> { // \expos + @\unspec@ get_return_object() noexcept; + @\unspec@ initial_suspend() noexcept; + @\unspec@ final_suspend() noexcept; + void unhandled_exception() noexcept; + void return_void() noexcept; + coroutine_handle<> unhandled_stopped() noexcept; + + const Env& get_env() const noexcept; + }; +} +\end{codeblock} +\begin{note} +Specializations of \exposid{env-promise} are used only for the purpose of type computation; +its members need not be defined. +\end{note} + +\rSec2[exec.domain.default]{\tcode{execution::default_domain}} + +\pnum +\begin{codeblock} +namespace std::execution { + struct @\libglobal{default_domain}@ { + template<@\libconcept{sender}@ Sndr, @\exposconcept{queryable}@... Env> + requires (sizeof...(Env) <= 1) + static constexpr @\libconcept{sender}@ decltype(auto) transform_sender(Sndr&& sndr, const Env&... env) + noexcept(@\seebelow@); + + template<@\libconcept{sender}@ Sndr, @\exposconcept{queryable}@ Env> + static constexpr @\exposconcept{queryable}@ decltype(auto) transform_env(Sndr&& sndr, Env&& env) noexcept; + + template + static constexpr decltype(auto) apply_sender(Tag, Sndr&& sndr, Args&&... args) + noexcept(@\seebelow@); + }; +} +\end{codeblock} + +\indexlibrarymember{transform_sender}{default_domain}% +\begin{itemdecl} +template<@\libconcept{sender}@ Sndr, @\exposconcept{queryable}@... Env> + requires (sizeof...(Env) <= 1) +constexpr @\libconcept{sender}@ decltype(auto) transform_sender(Sndr&& sndr, const Env&... env) + noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{e} be the expression +\begin{codeblock} +tag_of_t().transform_sender(std::forward(sndr), env...) +\end{codeblock} +if that expression is well-formed; +otherwise, \tcode{std::forward(sndr)}. + +\pnum +\returns +\tcode{e}. + +\pnum +\remarks +The exception specification is equivalent to \tcode{noexcept(e)}. +\end{itemdescr} + +\indexlibrarymember{transform_env}{default_domain}% +\begin{itemdecl} +template<@\libconcept{sender}@ Sndr, @\exposconcept{queryable}@ Env> + constexpr @\exposconcept{queryable}@ decltype(auto) transform_env(Sndr&& sndr, Env&& env) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{e} be the expression +\begin{codeblock} +tag_of_t().transform_env(std::forward(sndr), std::forward(env)) +\end{codeblock} +if that expression is well-formed; +otherwise, \tcode{\exposid{FWD-ENV}(std::forward(env))}. + +\pnum +\mandates +\tcode{noexcept(e)} is \tcode{true}. + +\pnum +\returns +\tcode{e}. +\end{itemdescr} + +\indexlibrarymember{apply_sender}{default_domain}% +\begin{itemdecl} +template +constexpr decltype(auto) apply_sender(Tag, Sndr&& sndr, Args&&... args) + noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{e} be the expression +\begin{codeblock} + Tag().apply_sender(std::forward(sndr), std::forward(args)...) +\end{codeblock} + +\pnum +\constraints +\tcode{e} is a well-formed expression. + +\pnum +\returns +\tcode{e}. + +\pnum +\remarks +The exception specification is equivalent to \tcode{noexcept(e)}. +\end{itemdescr} + +\rSec2[exec.snd.transform]{\tcode{execution::transform_sender}} + +\indexlibraryglobal{transform_sender}% +\begin{itemdecl} +namespace std::execution { + template + requires (sizeof...(Env) <= 1) + constexpr @\libconcept{sender}@ decltype(auto) transform_sender(Domain dom, Sndr&& sndr, const Env&... env) + noexcept(@\seebelow@); +} +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \exposid{transformed-sndr} be the expression +\begin{codeblock} +dom.transform_sender(std::forward(sndr), env...) +\end{codeblock} +if that expression is well-formed; otherwise, +\begin{codeblock} +default_domain().transform_sender(std::forward(sndr), env...) +\end{codeblock} +Let \exposid{final-sndr} be the expression \exposid{transformed-sndr} +if \exposid{transformed-sndr} and \exposid{sndr} +have the same type ignoring cv-qualifiers; +otherwise, it is +the expression \tcode{transform_sender(dom, \exposid{transformed-sndr}, env...)}. + +\pnum +\returns +\exposid{final-sndr}. + +\pnum +\remarks +The exception specification is equivalent to +\tcode{noexcept(\exposid{final-sndr})}. +\end{itemdescr} + +\rSec2[exec.snd.transform.env]{\tcode{execution::transform_env}} + +\indexlibraryglobal{transform_env}% +\begin{itemdecl} +namespace std::execution { + template + constexpr @\exposconcept{queryable}@ decltype(auto) transform_env(Domain dom, Sndr&& sndr, Env&& env) noexcept; +} +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{e} be the expression +\begin{codeblock} +dom.transform_env(std::forward(sndr), std::forward(env)) +\end{codeblock} +if that expression is well-formed; otherwise, +\begin{codeblock} +default_domain().transform_env(std::forward(sndr), std::forward(env)) +\end{codeblock} + +\pnum +\mandates +\tcode{noexcept(e)} is \tcode{true}. + +\pnum +\returns +\tcode{e}. +\end{itemdescr} + +\rSec2[exec.snd.apply]{\tcode{execution::apply_sender}} + +\indexlibraryglobal{apply_sender}% +\begin{itemdecl} +namespace std::execution { + template + constexpr decltype(auto) apply_sender(Domain dom, Tag, Sndr&& sndr, Args&&... args) + noexcept(@\seebelow@); +} +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $e$ be the expression +\begin{codeblock} +dom.apply_sender(Tag(), std::forward(sndr), std::forward(args)...) +\end{codeblock} +if that expression is well-formed; otherwise, +\begin{codeblock} +default_domain().apply_sender(Tag(), std::forward(sndr), std::forward(args)...) +\end{codeblock} + +\pnum +\constraints +The expression $e$ is well-formed. + +\pnum +\returns +$e$. + +\pnum +\remarks +The exception specification is equivalent to \tcode{noexcept($e$)}. +\end{itemdescr} + +\rSec2[exec.getcomplsigs]{\tcode{execution::get_completion_signatures}} + +\indexlibraryglobal{get_completion_signatures}% +%%FIXME: Should this be in namespace std::execution? +\begin{itemdecl} +template + consteval auto get_completion_signatures() -> @\exposconcept{valid-completion-signatures}@ auto; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $except$ be an rvalue subexpression of +an unspecified class type $Except$ such that +\tcode{\libconceptx{move_construc\-tible}{move_constructible}<$Except$> \&\& \libconcept{derived_from}<$Except$, exception>} +is \tcode{true}. +Let \tcode{\placeholder{CHECKED-COMPLSIGS}($e$)} be $e$ +if $e$ is a core constant expression whose +type satisfies \exposconcept{valid-completion-signatures}; +otherwise, it is the following expression: +\begin{codeblock} +(@$e$@, throw @$except$@, completion_signatures()) +\end{codeblock} +Let \tcode{\placeholder{get-complsigs}()} +be expression-equivalent to +\tcode{remove_reference_t::tem\-plate get_completion_signatures()}. +Let \tcode{NewSndr} be \tcode{Sndr} +if \tcode{sizeof...(Env) == 0} is \tcode{true}; +otherwise, \tcode{decltype($s$)} +where $s$ is the following expression: +\begin{codeblock} +transform_sender( + @\exposid{get-domain-late}@(declval(), declval()...), + declval(), + declval()...) +\end{codeblock} + +\pnum +\constraints +\tcode{sizeof...(Env) <= 1} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return $e$;} +where $e$ is expression-equivalent to the following: +\begin{itemize} +\item +\tcode{\placeholder{CHECKED-COMPLSIGS}(\placeholder{get-complsigs}())} +if \tcode{\placeholder{get-complsigs}()} +is a well-formed expression. + +\item +Otherwise, +\tcode{\placeholder{CHECKED-COMPLSIGS}(\placeholder{get-complsigs}())} +if \tcode{\placeholder{get-complsigs}()} +is a well-formed expression. + +\item +Otherwise, +\begin{codeblock} +completion_signatures< + @\exposid{SET-VALUE-SIG}@(@\exposid{await-result-type}@...>), // \ref{exec.snd.concepts} + set_error_t(exception_ptr), + set_stopped_t()> +\end{codeblock} +if \tcode{\exposconcept{is-awaitable}...>} +is \tcode{true}. + +\item +Otherwise, +\tcode{(throw \placeholder{dependent-sender-error}(), completion_signatures())} +if \tcode{sizeof...(\linebreak{}Env) == 0} is \tcode{true}, +where \tcode{\placeholder{dependent-sender-error}} is +\tcode{dependent_sender_error} or +an unspecified type derived publicly and unambiguously from +\tcode{dependent_sender_error}. + +\item +Otherwise, +\tcode{(throw $except$, completion_signatures())}. +\end{itemize} + +\pnum +Given a type \tcode{Env}, if +\tcode{completion_signatures_of_t} and +\tcode{completion_signatures_of_t} +are both well-formed, +they shall denote the same type. +\end{itemdescr} + +\pnum +Let \tcode{rcvr} be an rvalue +whose type \tcode{Rcvr} models \libconcept{receiver}, and +let \tcode{Sndr} be the type of a sender +such that \tcode{\libconcept{sender_in}>} is \tcode{true}. +Let \tcode{Sigs...} be the template arguments of +the \tcode{completion_signatures} specialization +named by \tcode{completion_signatures_of_t>}. +Let \tcode{CSO} be a completion function. +If sender \tcode{Sndr} or its operation state cause +the expression \tcode{CSO(rcvr, args...)} +to be potentially evaluated\iref{basic.def.odr} +then there shall be a signature \tcode{Sig} in \tcode{Sigs...} +such that +\begin{codeblock} +@\exposid{MATCHING-SIG}@(@\exposid{decayed-typeof}@(decltype(args)...), Sig) +\end{codeblock} +is \tcode{true}\iref{exec.general}. + +\rSec2[exec.connect]{\tcode{execution::connect}} + +\pnum +\tcode{connect} connects\iref{exec.async.ops} a sender with a receiver. + +\pnum +The name \tcode{connect} denotes a customization point object. +For subexpressions \tcode{sndr} and \tcode{rcvr}, +let \tcode{Sndr} be \tcode{decltype((sndr))} and +\tcode{Rcvr} be \tcode{decltype((rcvr))}, +let \tcode{new_sndr} be the expression +\begin{codeblock} +transform_sender(decltype(@\exposid{get-domain-late}@(sndr, get_env(rcvr))){}, sndr, get_env(rcvr)) +\end{codeblock} +and let \tcode{DS} and \tcode{DR} be +\tcode{decay_t} and \tcode{decay_t}, respectively. + +\pnum +Let \exposid{connect-awaitable-promise} be the following exposition-only class: + +\begin{codeblock} +namespace std::execution { + struct @\exposid{connect-awaitable-promise}@ : @\exposid{with-await-transform}@<@\exposid{connect-awaitable-promise}@> { + + @\exposid{connect-awaitable-promise}@(DS&, DR& rcvr) noexcept : @\exposid{rcvr}@(rcvr) {} + + suspend_always initial_suspend() noexcept { return {}; } + [[noreturn]] suspend_always final_suspend() noexcept { terminate(); } + [[noreturn]] void unhandled_exception() noexcept { terminate(); } + [[noreturn]] void return_void() noexcept { terminate(); } + + coroutine_handle<> unhandled_stopped() noexcept { + set_stopped(std::move(@\exposid{rcvr}@)); + return noop_coroutine(); + } + + @\exposid{operation-state-task}@ get_return_object() noexcept { + return @\exposid{operation-state-task}@{ + coroutine_handle<@\exposid{connect-awaitable-promise}@>::from_promise(*this)}; + } + + env_of_t get_env() const noexcept { + return execution::get_env(@\exposid{rcvr}@); + } + + private: + DR& @\exposid{rcvr}@; // \expos + }; +} +\end{codeblock} + +\pnum +Let \exposid{operation-state-task} be the following exposition-only class: +\begin{codeblock} +namespace std::execution { + struct @\exposid{operation-state-task}@ { // \expos + using operation_state_concept = operation_state_t; + using promise_type = @\exposid{connect-awaitable-promise}@; + + explicit @\exposid{operation-state-task}@(coroutine_handle<> h) noexcept : coro(h) {} + @\exposid{operation-state-task}@(@\exposid{operation-state-task}@&&) = delete; + ~@\exposid{operation-state-task}@() { @\exposid{coro}@.destroy(); } + + void start() & noexcept { + @\exposid{coro}@.resume(); + } + + private: + coroutine_handle<> @\exposid{coro}@; // \expos + }; +} +\end{codeblock} + +\pnum +Let \tcode{V} name the type +\tcode{\exposid{await-result-type}}, +let \tcode{Sigs} name the type +\begin{codeblock} +completion_signatures< + @\exposid{SET-VALUE-SIG}@(V), // see~\ref{exec.snd.concepts} + set_error_t(exception_ptr), + set_stopped_t()> +\end{codeblock} +and let \exposid{connect-awaitable} be an exposition-only coroutine +defined as follows: +\begin{codeblock} +namespace std::execution { + template + auto @\exposid{suspend-complete}@(Fun fun, Ts&&... as) noexcept { // \expos + auto fn = [&, fun]() noexcept { fun(std::forward(as)...); }; + + struct awaiter { + decltype(fn) @\exposid{fn}@; // \expos + + static constexpr bool await_ready() noexcept { return false; } + void await_suspend(coroutine_handle<>) noexcept { @\exposid{fn}@(); } + [[noreturn]] void await_resume() noexcept { unreachable(); } + }; + return awaiter{fn}; + } + + @\exposid{operation-state-task}@ @\exposid{connect-awaitable}@(DS sndr, DR rcvr) requires @\libconcept{receiver_of}@ { + exception_ptr ep; + try { + if constexpr (@\libconcept{same_as}@) { + co_await std::move(sndr); + co_await @\exposid{suspend-complete}@(set_value, std::move(rcvr)); + } else { + co_await @\exposid{suspend-complete}@(set_value, std::move(rcvr), co_await std::move(sndr)); + } + } catch(...) { + ep = current_exception(); + } + co_await @\exposid{suspend-complete}@(set_error, std::move(rcvr), std::move(ep)); + } +} +\end{codeblock} + +\pnum +The expression \tcode{connect(sndr, rcvr)} is expression-equivalent to: +\begin{itemize} +\item +\tcode{new_sndr.connect(rcvr)} if that expression is well-formed. + +\mandates +The type of the expression above satisfies \libconcept{operation_state}. + +\item +Otherwise, \tcode{\exposid{connect-awaitable}(new_sndr, rcvr)}. +\end{itemize} +Except that \tcode{rcvr} is evaluated only once. + +\mandates +The following are \tcode{true}: +\begin{itemize} +\item +\tcode{\libconcept{sender_in}>} +\item +\tcode{\libconcept{receiver_of}>>} +\end{itemize} + +\rSec2[exec.factories]{Sender factories} + +\rSec3[exec.schedule]{\tcode{execution::schedule}} + +\pnum +\tcode{schedule} obtains a schedule sender\iref{exec.async.ops} +from a scheduler. + +\pnum +The name \tcode{schedule} denotes a customization point object. +For a subexpression \tcode{sch}, +the expression \tcode{schedule(sch)} is expression-equivalent to +\tcode{sch.schedule()}. + +\pnum +\mandates +The type of \tcode{sch.schedule()} satisfies \libconcept{sender}. + +\pnum +If the expression +\begin{codeblock} +get_completion_scheduler(get_env(sch.schedule())) == sch +\end{codeblock} +is ill-formed or evaluates to \tcode{false}, +the behavior of calling \tcode{schedule(sch)} is undefined. + +\rSec3[exec.just]{\tcode{execution::just}, \tcode{execution::just_error}, \tcode{execution::just_stopped}} + +\pnum +\tcode{just}, \tcode{just_error}, and \tcode{just_stopped} are sender factories +whose asynchronous operations complete synchronously in their start operation +with a value completion operation, +an error completion operation, or +a stopped completion operation, respectively. + +\pnum +The names \tcode{just}, \tcode{just_error}, and \tcode{just_stopped} denote +customization point objects. +Let \exposid{just-cpo} be one of +\tcode{just}, \tcode{just_error}, or \tcode{just_stopped}. +For a pack of subexpressions \tcode{ts}, +let \tcode{Ts} be the pack of types \tcode{decltype((ts))}. +The expression \tcode{\exposid{just-cpo}(ts...)} is ill-formed if +\begin{itemize} +\item +\tcode{(\exposconcept{movable-value} \&\&...)} is \tcode{false}, or +\item +\exposid{just-cpo} is \tcode{just_error} and +\tcode{sizeof...(ts) == 1} is \tcode{false}, or +\item +\exposid{just-cpo} is \tcode{just_stopped} and +\tcode{sizeof...(ts) == 0} is \tcode{false}. +\end{itemize} + +Otherwise, it is expression-equivalent to +\tcode{\exposid{make-sender}(\exposid{just-cpo}, \exposid{product-type}\{ts...\})}. + +For \tcode{just}, \tcode{just_error}, and \tcode{just_stopped}, +let \exposid{set-cpo} be +\tcode{set_value}, \tcode{set_error}, and \tcode{set_stopped}, respectively. +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \exposid{just-cpo} as follows: +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@<@\exposid{decayed-typeof}@<@\exposid{just-cpo}@>> : @\exposid{default-impls}@ { + static constexpr auto @\exposid{start}@ = + [](auto& state, auto& rcvr) noexcept -> void { + auto& [...ts] = state; + @\exposid{set-cpo}@(std::move(rcvr), std::move(ts)...); + }; + }; +} +\end{codeblock} + +\rSec3[exec.read.env]{\tcode{execution::read_env}} + +\pnum +\tcode{read_env} is a sender factory for a sender +whose asynchronous operation completes synchronously in its start operation +with a value completion result equal to +a value read from the receiver's associated environment. + +\pnum +\tcode{read_env} is a customization point object. +For some query object \tcode{q}, +the expression \tcode{read_env(q)} is expression-equivalent to +\tcode{\exposid{make-sender}(read_env, q)}. + +\pnum +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \tcode{read_env} as follows: +\indexlibraryglobal{\exposid{impls-for}<\exposid{decayed-typeof}>} +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@<@\exposid{decayed-typeof}@> : @\exposid{default-impls}@ { + static constexpr auto start = + [](auto query, auto& rcvr) noexcept -> void { + @\exposid{TRY-SET-VALUE}@(rcvr, query(get_env(rcvr))); + }; + }; + + template + static consteval void @\exposid{check-types}@(); +} +\end{codeblock} + +\indexlibrarymember{\exposid{check-types}}{\exposid{impls-for}<\exposid{decayed-typeof}>} +\begin{itemdecl} +template + static consteval void @\exposid{check-types}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Q} be \tcode{decay_t<\exposid{data-type}>}. + +\pnum +\throws +An exception of an unspecified type derived from \tcode{exception} if +the expression \tcode{Q()(env)} is ill-formed or has type \tcode{void}, where +\tcode{env} is an lvalue subexpression whose type is \tcode{Env}. +\end{itemdescr} + +\rSec2[exec.adapt]{Sender adaptors} + +\rSec3[exec.adapt.general]{General} + +\pnum +Subclause \ref{exec.adapt} specifies a set of sender adaptors. + +\pnum +The bitwise inclusive \logop{or} operator is overloaded +for the purpose of creating sender chains. +The adaptors also support function call syntax with equivalent semantics. + +\pnum +Unless otherwise specified: +\begin{itemize} +\item +A sender adaptor is prohibited from causing observable effects, +apart from moving and copying its arguments, +before the returned sender is connected with a receiver using \tcode{connect}, +and \tcode{start} is called on the resulting operation state. +\item +A parent sender\iref{exec.async.ops} with a single child sender \tcode{sndr} has +an associated attribute object equal to +\tcode{\exposid{FWD-ENV}(get_env(sndr))}\iref{exec.fwd.env}. +\item +A parent sender with more than one child sender has +an associated attributes object equal to \tcode{env<>\{\}}. +\item +When a parent sender is connected to a receiver \tcode{rcvr}, +any receiver used to connect a child sender has +an associated environment equal to \tcode{\exposid{FWD-ENV}(get_env(rcvr))}. +\item +An adaptor whose child senders are all non-dependent\iref{exec.async.ops} +is itself non-dependent. +\item +These requirements apply to any function +that is selected by the implementation of the sender adaptor. +\item + \recommended +Implementations should use +the completion signatures of the adaptors +to communicate type errors to users and +to propagate any such type errors from child senders. +\end{itemize} + +\pnum +If a sender returned from a sender adaptor specified in \ref{exec.adapt} +is specified to include \tcode{set_error_t(Err)} +among its set of completion signatures +where \tcode{decay_t} denotes the type \tcode{exception_ptr}, +but the implementation does not potentially evaluate +an error completion operation with an \tcode{exception_ptr} argument, +the implementation is allowed to omit +the \tcode{exception_ptr} error completion signature from the set. + +\rSec3[exec.adapt.obj]{Closure objects} + +\pnum +A \defnadj{pipeable}{sender adaptor closure object} is a function object +that accepts one or more \libconcept{sender} arguments and returns a \libconcept{sender}. +For a pipeable sender adaptor closure object \tcode{c} and +an expression \tcode{sndr} +such that \tcode{decltype((sndr))} models \libconcept{sender}, +the following expressions are equivalent and yield a \libconcept{sender}: +\begin{codeblock} +c(sndr) +sndr | c +\end{codeblock} +Given an additional pipeable sender adaptor closure object \tcode{d}, +the expression \tcode{c | d} produces +another pipeable sender adaptor closure object \tcode{e}: + +\tcode{e} is a perfect forwarding call wrapper\iref{func.require} +with the following properties: +\begin{itemize} +\item +Its target object is an object \tcode{d2} of type \tcode{decltype(auto(d))} +direct-non-list-initialized with \tcode{d}. +\item +It has one bound argument entity, +an object \tcode{c2} of type \tcode{decltype(auto(c))} +direct-non-list-initialized with \tcode{c}. +\item +Its call pattern is \tcode{d2(c2(arg))}, +where arg is the argument used in a function call expression of \tcode{e}. +\end{itemize} +The expression \tcode{c | d} is well-formed if and only if +the initializations of the state entities\iref{func.def} of \tcode{e} +are all well-formed. + +\pnum +An object \tcode{t} of type \tcode{T} is +a pipeable sender adaptor closure object +if \tcode{T} models \tcode{\libconcept{derived_from}>}, +\tcode{T} has no other base classes +of type \tcode{sender_adaptor_closure} for any other type \tcode{U}, and +\tcode{T} does not satisfy \libconcept{sender}. + +\pnum +The template parameter \tcode{D} for \tcode{sender_adaptor_closure} can be +an incomplete type. +Before any expression of type \cv{} \tcode{D} appears 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 +A \defnadj{pipeable}{sender adaptor object} is a customization point object +that accepts a \libconcept{sender} as its first argument and +returns a \libconcept{sender}. +If a pipeable sender adaptor object accepts only one argument, +then it is a pipeable sender adaptor closure object. + +\pnum +If a pipeable sender adaptor object adaptor accepts more than one argument, +then let \tcode{sndr} be an expression +such that \tcode{decltype((sndr))} models \libconcept{sender}, +let \tcode{args...} be arguments +such that \tcode{adaptor(sndr, args...)} is a well-formed expression +as specified below, and +let \tcode{BoundArgs} be a pack that denotes \tcode{decltype(auto(args))...}. +The expression \tcode{adaptor(args...)} produces +a pipeable sender adaptor closure object \tcode{f} +that is a perfect forwarding call wrapper with the following properties: +\begin{itemize} +\item +Its target object is a copy of adaptor. +\item +Its bound argument entities \tcode{bound_args} consist of +objects of types \tcode{BoundArgs...} direct-non-list-initialized with +\tcode{std::forward(args)...}, respectively. +\item +Its call pattern is \tcode{adaptor(rcvr, bound_args...)}, +where \tcode{rcvr} is +the argument used in a function call expression of \tcode{f}. +\end{itemize} +The expression \tcode{adaptor(args...)} is well-formed if and only if +the initializations of the bound argument entities of the result, +as specified above, are all well-formed. + +\rSec3[exec.write.env]{\tcode{execution::write_env}} + +\pnum +\tcode{write_env} is a sender adaptor +that accepts a sender and a queryable object, and +that returns a sender that, +when connected with a receiver \tcode{rcvr}, +connects the adapted sender with a receiver +whose execution environment is the result of +joining the \exposconcept{queryable} object +to the result of \tcode{get_env(rcvr)}. + +\pnum +\tcode{write_env} is a customization point object. +For some subexpressions \tcode{sndr} and \tcode{env}, +if \tcode{decltype((sndr))} does not satisfy \libconcept{sender} or +if \tcode{decltype((env))} does not satisfy \exposconcept{queryable}, +the expression \tcode{write_env(sndr, env)} is ill-formed. +Otherwise, it is expression-equivalent to +\tcode{\exposid{make-sender}(write_env, env, sndr)}. + +\pnum +Let \exposid{write-env-t} denote the type \tcode{decltype(auto(write_env))}. +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \exposid{write-env-t} as follows: +\indexlibraryglobal{\exposid{impls-for}<\exposid{write-env-t}>} +\begin{codeblock} +template<> +struct @\exposid{impls-for}@<@\exposid{write-env-t}@> : @\exposid{default-impls}@ { + static constexpr auto @\exposid{join-env}@(const auto& state, const auto& env) noexcept { + return @\seebelow@; + } + + static constexpr auto @\exposid{get-env}@ = + [](auto, const auto& state, const auto& rcvr) noexcept { + return @\exposid{join-env}@(state, @\exposid{FWD-ENV}@(get_env(rcvr))); + }; + + template + static consteval void @\exposid{check-types}@(); +}; +\end{codeblock} +Invocation of +\tcode{\exposid{impls-for}<\exposid{write-env-t}>::\exposid{join-env}} +returns an object \tcode{e} such that +\begin{itemize} +\item +\tcode{decltype(e)} models \exposconcept{queryable} and +\item +given a query object \tcode{q}, +the expression \tcode{e.query(q)} is expression-equivalent +to \tcode{state.query(q)} if that expression is valid, +otherwise, \tcode{e.query(q)} is expression-equivalent +to \tcode{env.query(q)}. +\item +For a type \tcode{Sndr} and a pack of types \tcode{Env}, +let \tcode{State} be \tcode{\exposid{data-type}} and +let \tcode{JoinEnv} be the pack +\tcode{decltype(\exposid{join-env}(declval(), \exposid{FWD-ENV}(declval())))}. +Then \tcode{\exposid{impls-for}<\exposid{write-\linebreak{}env-t}>::\exposid{check-types}()} +is expression-equivalent to +\tcode{get_completion_signatures<\linebreak{}\exposid{child-type}, JoinEnv...>()}. +\end{itemize} + +\rSec3[exec.unstoppable]{\tcode{execution::unstoppable}} + +\pnum +\tcode{unstoppable} is a sender adaptor +that connects its inner sender +with a receiver that has the execution environment of the outer receiver +but with an object of type \tcode{never_stop_token} +as the result of the \tcode{get_stop_token query}. + +\pnum +For a subexpression \tcode{sndr}, +\tcode{unstoppable(sndr)} is expression-equivalent to +\tcode{write_env(sndr, prop(get_stop_token, never_stop_token\{\}))}. + +\rSec3[exec.starts.on]{\tcode{execution::starts_on}} + +\pnum +\tcode{starts_on} adapts an input sender into a sender +that will start on an execution agent belonging to +a particular scheduler's associated execution resource. + +\pnum +The name \tcode{starts_on} denotes a customization point object. +For subexpressions \tcode{sch} and \tcode{sndr}, +if \tcode{decltype((\newline sch))} does not satisfy \libconcept{scheduler}, or +\tcode{decltype((sndr))} does not satisfy \libconcept{sender}, +\tcode{starts_on(sch, sndr)} is ill-formed. + +\pnum +Otherwise, +the expression \tcode{starts_on(sch, sndr)} is expression-equivalent to: +\begin{codeblock} +transform_sender( + @\exposid{query-with-default}@(get_domain, sch, default_domain()), + @\exposid{make-sender}@(starts_on, sch, sndr)) +\end{codeblock} +except that \tcode{sch} is evaluated only once. + +\pnum +Let \tcode{out_sndr} and \tcode{env} be subexpressions +such that \tcode{OutSndr} is \tcode{decltype((out_sndr))}. +If \tcode{\exposconcept{sender-for}} is \tcode{false}, +then the expressions \tcode{starts_on.transform_env(out_sndr, env)} and\linebreak +\tcode{starts_on.transform_sender(out_sndr, env)} are ill-formed; otherwise +\begin{itemize} +\item +\tcode{starts_on.transform_env(out_sndr, env)} is equivalent to: +\begin{codeblock} +auto&& [_, sch, _] = out_sndr; +return @\exposid{JOIN-ENV}@(@\exposid{SCHED-ENV}@(sch), @\exposid{FWD-ENV}@(env)); +\end{codeblock} +\item +\tcode{starts_on.transform_sender(out_sndr, env)} is equivalent to: +\begin{codeblock} +auto&& [_, sch, sndr] = out_sndr; +return let_value( + schedule(sch), + [sndr = std::forward_like(sndr)]() mutable + noexcept(is_nothrow_move_constructible_v>) { + return std::move(sndr); + }); +\end{codeblock} +\end{itemize} + +\pnum +Let \tcode{out_sndr} be a subexpression denoting +a sender returned from \tcode{starts_on(sch, sndr)} or one equal to such, and +let \tcode{OutSndr} be the type \tcode{decltype((out_sndr))}. +Let \tcode{out_rcvr} be a subexpression denoting a receiver +that has an environment of type \tcode{Env} +such that \tcode{\libconcept{sender_in}} is \tcode{true}. +Let \tcode{op} be an lvalue referring to the operation state +that results from connecting \tcode{out_sndr} with \tcode{out_rcvr}. +Calling \tcode{start(op)} shall start \tcode{sndr} +on an execution agent of the associated execution resource of \tcode{sch}. +If scheduling onto \tcode{sch} fails, +an error completion on \tcode{out_rcvr} shall be executed +on an unspecified execution agent. + +\rSec3[exec.continues.on]{\tcode{execution::continues_on}} + +\pnum +\tcode{continues_on} adapts a sender into one +that completes on the specified scheduler. + +\pnum +The name \tcode{continues_on} denotes a pipeable sender adaptor object. +For subexpressions \tcode{sch} and \tcode{sndr}, +if \tcode{decltype((sch))} does not satisfy \libconcept{scheduler}, or +\tcode{decltype((sndr))} does not satisfy \libconcept{sender}, +\tcode{continues_on(sndr, sch)} is ill-formed. + +\pnum +Otherwise, +the expression \tcode{continues_on(sndr, sch)} is expression-equivalent to: +\begin{codeblock} +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(continues_on, sch, sndr)) +\end{codeblock} +except that \tcode{sndr} is evaluated only once. + +\pnum +The exposition-only class template \exposid{impls-for} +is specialized for \tcode{continues_on_t} as follows: +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { + static constexpr auto @\exposid{get-attrs}@ = + [](const auto& data, const auto& child) noexcept -> decltype(auto) { + return @\exposid{JOIN-ENV}@(@\exposid{SCHED-ATTRS}@(data), @\exposid{FWD-ENV}@(get_env(child))); + }; + }; +} +\end{codeblock} + +\pnum +Let \tcode{sndr} and \tcode{env} be subexpressions +such that \tcode{Sndr} is \tcode{decltype((sndr))}. +If \tcode{\exposconcept{sender-for}} is \tcode{false}, +then +the expression \tcode{continues_on.transform_sender(sndr, env)} is ill-formed; +otherwise, it is equal to: +\begin{codeblock} +auto [_, data, child] = sndr; +return schedule_from(std::move(data), std::move(child)); +\end{codeblock} +\begin{note} +This causes the \tcode{continues_on(sndr, sch)} sender to become +\tcode{schedule_from(sch, sndr)} when it is connected with a receiver +whose execution domain does not customize \tcode{continues_on}. +\end{note} + +\pnum +Let \tcode{out_sndr} be a subexpression denoting +a sender returned from \tcode{continues_on(sndr, sch)} or one equal to such, and +let \tcode{OutSndr} be the type \tcode{decltype((out_sndr))}. +Let \tcode{out_rcvr} be a subexpression denoting a receiver +that has an environment of type \tcode{Env} +such that \tcode{\libconcept{sender_in}} is \tcode{true}. +Let \tcode{op} be an lvalue referring to the operation state +that results from connecting \tcode{out_sndr} with \tcode{out_rcvr}. +Calling \tcode{start(op)} shall +start \tcode{sndr} on the current execution agent and +execute completion operations on \tcode{out_rcvr} +on an execution agent of the execution resource associated with \tcode{sch}. +If scheduling onto \tcode{sch} fails, +an error completion on \tcode{out_rcvr} shall be executed +on an unspecified execution agent. + +\rSec3[exec.schedule.from]{\tcode{execution::schedule_from}} + +\pnum +\tcode{schedule_from} schedules work dependent on the completion of a sender +onto a scheduler's associated execution resource. +\begin{note} +\tcode{schedule_from} is not meant to be used in user code; +it is used in the implementation of \tcode{continues_on}. +\end{note} + +\pnum +The name \tcode{schedule_from} denotes a customization point object. +For some subexpressions \tcode{sch} and \tcode{sndr}, +let \tcode{Sch} be \tcode{decltype((sch))} and +\tcode{Sndr} be \tcode{decltype((sndr))}. +If \tcode{Sch} does not satisfy \libconcept{scheduler}, or +\tcode{Sndr} does not satisfy \libconcept{sender}, +\tcode{schedule_from(sch, sndr)} is ill-formed. + +\pnum +Otherwise, +the expression \tcode{schedule_from(sch, sndr)} is expression-equivalent to: +\begin{codeblock} +transform_sender( + @\exposid{query-with-default}@(get_domain, sch, default_domain()), + @\exposid{make-sender}@(schedule_from, sch, sndr)) +\end{codeblock} +except that \tcode{sch} is evaluated only once. + +\pnum +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \tcode{schedule_from_t} as follows: +\indexlibraryglobal{\exposid{impls-for}}% +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { + static constexpr auto @\exposid{get-attrs}@ = @\seebelow@; + static constexpr auto @\exposid{get-state}@ = @\seebelow@; + static constexpr auto @\exposid{complete}@ = @\seebelow@; + + template + static consteval void @\exposid{check-types}@(); + }; +} +\end{codeblock} + +\pnum +The member \tcode{\exposid{impls-for}::\exposid{get-attrs}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[](const auto& data, const auto& child) noexcept -> decltype(auto) { + return @\exposid{JOIN-ENV}@(@\exposid{SCHED-ATTRS}@(data), @\exposid{FWD-ENV}@(get_env(child))); +} +\end{codeblock} + +\pnum +The member \tcode{\exposid{impls-for}::\exposid{get-state}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[](Sndr&& sndr, Rcvr& rcvr) noexcept(@\seebelow@) + requires @\libconcept{sender_in}@<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(env_of_t)> { + + auto& [_, sch, child] = sndr; + + using sched_t = decltype(auto(sch)); + using variant_t = @\seebelow@; + using receiver_t = @\seebelow@; + using operation_t = connect_result_t, receiver_t>; + constexpr bool nothrow = noexcept(connect(schedule(sch), receiver_t{nullptr})); + + struct @\exposid{state-type}@ { + Rcvr& @\exposid{rcvr}@; // \expos + variant_t @\exposid{async-result}@; // \expos + operation_t @\exposid{op-state}@; // \expos + + explicit @\exposid{state-type}@(sched_t sch, Rcvr& rcvr) noexcept(nothrow) + : @\exposid{rcvr}@(rcvr), @\exposid{op-state}@(connect(schedule(sch), receiver_t{this})) {} + }; + + return @\exposid{state-type}@{sch, rcvr}; +} +\end{codeblock} + +\indexlibrarymember{\exposid{check-types}}{\exposid{impls-for}} +\begin{itemdecl} +template + static consteval void @\exposid{check-types}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +get_completion_signatures>, @\exposid{FWD-ENV-T}@(Env)...>(); +auto cs = get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(); +@\exposid{decay-copyable-result-datums}@(cs); // see \ref{exec.snd.expos} +\end{codeblock} +\end{itemdescr} + +\pnum +Objects of the local class \exposid{state-type} can be used +to initialize a structured binding. + +\pnum +Let \tcode{Sigs} be +a pack of the arguments to the \tcode{completion_signatures} specialization +named by \tcode{completion_signatures_of_t<\exposid{child-type}, \exposid{FWD-ENV-T}(env_of_t)>}. +Let \exposid{as-tuple} be an alias template such that +\tcode{\exposid{as-tuple}} denotes +the type \tcode{\exposid{decayed-tuple}}, and +let \exposid{is-no\-throw-decay-copy-sig} be a variable template such that +\tcode{auto(\exposid{is-nothrow-decay-copy-sig})} is +a constant expression of type \tcode{bool} and +equal to \tcode{(is_nothrow_constructible_v, Args> \&\& ...)}. +Let \exposid{error-completion} be a pack consisting of +the type \tcode{set_error_t(exception_ptr)} +if \tcode{(\exposid{is-nothrow-decay-copy-sig} \&\&...)} is \tcode{false}, +and an empty pack otherwise. +Then \tcode{variant_t} denotes +the type \tcode{variant..., \exposid{error-completion}...>}, +except with duplicate types removed. + +\pnum +\tcode{receiver_t} is an alias for the following exposition-only class: +\begin{codeblock} +namespace std::execution { + struct @\exposid{receiver-type}@ { + using receiver_concept = receiver_t; + @\exposid{state-type}@* @\exposid{state}@; // \expos + + void set_value() && noexcept { + visit( + [this](Tuple& result) noexcept -> void { + if constexpr (!@\libconcept{same_as}@) { + auto& [tag, ...args] = result; + tag(std::move(@\exposid{state}@->@\exposid{rcvr}@), std::move(args)...); + } + }, + @\exposid{state}@->@\exposid{async-result}@); + } + + template + void set_error(Error&& err) && noexcept { + execution::set_error(std::move(@\exposid{state}@->@\exposid{rcvr}@), std::forward(err)); + } + + void set_stopped() && noexcept { + execution::set_stopped(std::move(@\exposid{state}@->@\exposid{rcvr}@)); + } + + decltype(auto) get_env() const noexcept { + return @\exposid{FWD-ENV}@(execution::get_env(@\exposid{state}@->@\exposid{rcvr}@)); + } + }; +} +\end{codeblock} + +\pnum +The expression in the \tcode{noexcept} clause of the lambda is \tcode{true} +if the construction of the returned \exposid{state-type} object +is not potentially throwing; +otherwise, \tcode{false}. + +\pnum +The member \tcode{\exposid{impls-for}::\exposid{complete}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[](auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept + -> void { + using result_t = @\exposid{decayed-tuple}@; + constexpr bool nothrow = (is_nothrow_constructible_v, Args> && ...); + + try { + state.@\exposid{async-result}@.template emplace(Tag(), std::forward(args)...); + } catch (...) { + if constexpr (!nothrow) + state.@\exposid{async-result}@.template emplace>(set_error, current_exception()); + } + start(state.@\exposid{op-state}@); +}; +\end{codeblock} + +\pnum +Let \tcode{out_sndr} be a subexpression denoting +a sender returned from \tcode{schedule_from(sch, sndr)} or one equal to such, +and let \tcode{OutSndr} be the type \tcode{decltype((out_sndr))}. +Let \tcode{out_rcvr} be a subexpression denoting a receiver +that has an environment of type \tcode{Env} +such that \tcode{\libconcept{sender_in}} is \tcode{true}. +Let \tcode{op} be an lvalue referring to the operation state +that results from connecting \tcode{out_sndr} with \tcode{out_rcvr}. +Calling \tcode{start(op)} shall +start \tcode{sndr} on the current execution agent and +execute completion operations on \tcode{out_rcvr} +on an execution agent of the execution resource associated with \tcode{sch}. +If scheduling onto \tcode{sch} fails, +an error completion on \tcode{out_rcvr} shall be executed +on an unspecified execution agent. + +\rSec3[exec.on]{\tcode{execution::on}} + +\pnum +The \tcode{on} sender adaptor has two forms: +\begin{itemize} +\item +\tcode{on(sch, sndr)}, +which starts a sender \tcode{sndr} on an execution agent +belonging to a scheduler \tcode{sch}'s associated execution resource and +that, upon \tcode{sndr}'s completion, +transfers execution back to the execution resource +on which the \tcode{on} sender was started. +\item +\tcode{on(sndr, sch, closure)}, +which upon completion of a sender \tcode{sndr}, +transfers execution to an execution agent +belonging to a scheduler \tcode{sch}'s associated execution resource, +then executes a sender adaptor closure \tcode{closure} +with the async results of the sender, and +that then transfers execution back to the execution resource +on which \tcode{sndr} completed. +\end{itemize} + +\pnum +The name \tcode{on} denotes a pipeable sender adaptor object. +For subexpressions \tcode{sch} and \tcode{sndr}, +\tcode{on(sch, sndr)} is ill-formed if any of the following is \tcode{true}: +\begin{itemize} +\item +\tcode{decltype((sch))} does not satisfy \libconcept{scheduler}, or +\item +\tcode{decltype((sndr))} does not satisfy \libconcept{sender} and +\tcode{sndr} is not +a pipeable sender adaptor closure object\iref{exec.adapt.obj}, or +\item +\tcode{decltype((sndr))} satisfies \libconcept{sender} and +\tcode{sndr }is also a pipeable sender adaptor closure object. +\end{itemize} + +\pnum +Otherwise, if \tcode{decltype((sndr))} satisfies \libconcept{sender}, +the expression \tcode{on(sch, sndr)} is expression-equivalent to: +\begin{codeblock} +transform_sender( + @\exposid{query-with-default}@(get_domain, sch, default_domain()), + @\exposid{make-sender}@(on, sch, sndr)) +\end{codeblock} +except that \tcode{sch} is evaluated only once. + +\pnum +For subexpressions \tcode{sndr}, \tcode{sch}, and \tcode{closure}, if +\begin{itemize} +\item +\tcode{decltype((sch))} does not satisfy \libconcept{scheduler}, or +\item +\tcode{decltype((sndr))} does not satisfy \libconcept{sender}, or +\item +\tcode{closure} is not a pipeable sender adaptor closure object\iref{exec.adapt.obj}, +\end{itemize} +the expression \tcode{on(sndr, sch, closure)} is ill-formed; +otherwise, it is expression-equivalent to: +\begin{codeblock} +transform_sender( + @\exposid{get-domain-early}@(sndr), + @\exposid{make-sender}@(on, @\exposid{product-type}@{sch, closure}, sndr)) +\end{codeblock} +except that \tcode{sndr} is evaluated only once. + +\pnum +Let \tcode{out_sndr} and \tcode{env} be subexpressions, +let \tcode{OutSndr} be \tcode{decltype((out_sndr))}, and +let \tcode{Env} be \tcode{decltype((\linebreak env))}. +If \tcode{\exposconcept{sender-for}} is \tcode{false}, +then the expressions \tcode{on.transform_env(out_sndr, env)} and +\tcode{on.transform_sender(out_sndr, env)} are ill-formed. + +\pnum +Otherwise: +Let \exposid{not-a-scheduler} be an unspecified empty class type. + +\pnum +The expression \tcode{on.transform_env(out_sndr, env)} +has effects equivalent to: +\begin{codeblock} +auto&& [_, data, _] = out_sndr; +if constexpr (@\libconcept{scheduler}@) { + return @\exposid{JOIN-ENV}@(@\exposid{SCHED-ENV}@(std::forward_like(data)), @\exposid{FWD-ENV}@(std::forward(env))); +} else { + return std::forward(env); +} +\end{codeblock} + +\pnum +The expression \tcode{on.transform_sender(out_sndr, env)} +has effects equivalent to: +\begin{codeblock} +auto&& [_, data, child] = out_sndr; +if constexpr (@\libconcept{scheduler}@) { + auto orig_sch = + @\exposid{query-with-default}@(get_scheduler, env, @\exposid{not-a-scheduler}@()); + + if constexpr (@\libconcept{same_as}@) { + return @\exposid{not-a-sender}@{}; + } else { + return continues_on( + starts_on(std::forward_like(data), std::forward_like(child)), + std::move(orig_sch)); + } +} else { + auto& [sch, closure] = data; + auto orig_sch = @\exposid{query-with-default}@( + get_completion_scheduler, + get_env(child), + @\exposid{query-with-default}@(get_scheduler, env, @\exposid{not-a-scheduler}@())); + + if constexpr (@\libconcept{same_as}@) { + return @\exposid{not-a-sender}@{}; + } else { + return write_env( + continues_on( + std::forward_like(closure)( + continues_on( + write_env(std::forward_like(child), @\exposid{SCHED-ENV}@(orig_sch)), + sch)), + orig_sch), + @\exposid{SCHED-ENV}@(sch)); + } +} +\end{codeblock} + +\pnum +Let \tcode{out_sndr} be a subexpression denoting +a sender returned from \tcode{on(sch, sndr)} or one equal to such, and +let \tcode{OutSndr} be the type \tcode{decltype((out_sndr))}. +Let \tcode{out_rcvr} be a subexpression denoting a receiver +that has an environment of type \tcode{Env} +such that \tcode{\libconcept{sender_in}} is \tcode{true}. +Let \tcode{op} be an lvalue referring to the operation state +that results from connecting \tcode{out_sndr} with \tcode{out_rcvr}. +Calling \tcode{start(op)} shall +\begin{itemize} +\item +remember the current scheduler, \tcode{get_scheduler(get_env(rcvr))}; +\item +start \tcode{sndr} on an execution agent belonging to +\tcode{sch}'s associated execution resource; +\item +upon \tcode{sndr}'s completion, +transfer execution back to the execution resource +associated with the scheduler remembered in step 1; and +\item +forward \tcode{sndr}'s async result to \tcode{out_rcvr}. +\end{itemize} +If any scheduling operation fails, +an error completion on \tcode{out_rcvr} shall be executed +on an unspecified execution agent. + +\pnum +Let \tcode{out_sndr} be a subexpression denoting +a sender returned from \tcode{on(sndr, sch, closure)} or one equal to such, and +let \tcode{OutSndr} be the type \tcode{decltype((out_sndr))}. +Let \tcode{out_rcvr} be a subexpression denoting a receiver +that has an environment of type \tcode{Env} +such that \tcode{\libconcept{sender_in}} is \tcode{true}. +Let \tcode{op} be an lvalue referring to the operation state +that results from connecting \tcode{out_sndr} with \tcode{out_rcvr}. +Calling \tcode{start(op)} shall +\begin{itemize} +\item +remember the current scheduler, +which is the first of the following expressions that is well-formed: +\begin{itemize} +\item \tcode{get_completion_scheduler(get_env(sndr))} +\item \tcode{get_scheduler(get_env(rcvr))}; +\end{itemize} +\item +start \tcode{sndr} on the current execution agent; +\item +upon \tcode{sndr}'s completion, +transfer execution to an agent +owned by \tcode{sch}'s associated execution resource; +\item +forward \tcode{sndr}'s async result as if by +connecting and starting a sender \tcode{closure(S)}, +where \tcode{S} is a sender +that completes synchronously with \tcode{sndr}'s async result; and +\item +upon completion of the operation started in the previous step, +transfer execution back to the execution resource +associated with the scheduler remembered in step 1 and +forward the operation's async result to \tcode{out_rcvr}. +\end{itemize} +If any scheduling operation fails, +an error completion on \tcode{out_rcvr} shall be executed on +an unspecified execution agent. + +\rSec3[exec.then]{\tcode{execution::then}, \tcode{execution::upon_error}, \tcode{execution::upon_stopped}} + +\pnum +\tcode{then} attaches an invocable as a continuation +for an input sender's value completion operation. +\tcode{upon_error} and \tcode{upon_stopped} do the same +for the error and stopped completion operations, respectively, +sending the result of the invocable as a value completion. + +\pnum +The names \tcode{then}, \tcode{upon_error}, and \tcode{upon_stopped} +denote pipeable sender adaptor objects. +Let the expression \exposid{then-cpo} be one of +\tcode{then}, \tcode{upon_error}, or \tcode{upon_stopped}. +For subexpressions \tcode{sndr} and \tcode{f}, +if \tcode{decltype((sndr))} does not satisfy \libconcept{sender}, or +\tcode{decltype((f))} does not satisfy \exposconcept{movable-value}, +\tcode{\exposid{then-cpo}(\linebreak sndr, f) }is ill-formed. + +\pnum +Otherwise, +the expression \tcode{\exposid{then-cpo}(sndr, f)} is expression-equivalent to: +\begin{codeblock} +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(@\exposid{then-cpo}@, f, sndr)) +\end{codeblock} +except that \tcode{sndr} is evaluated only once. + +\pnum +For \tcode{then}, \tcode{upon_error}, and \tcode{upon_stopped}, +let \exposid{set-cpo} be +\tcode{set_value}, \tcode{set_error}, and \tcode{set_stopped}, respectively. +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \exposid{then-cpo} as follows: +\indexlibraryglobal{\exposid{impls-for}<\exposid{decayed-typeof}<\exposid{then-cpo}>>} +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@<@\exposid{decayed-typeof}@<@\exposid{then-cpo}@>> : @\exposid{default-impls}@ { + static constexpr auto @\exposid{complete}@ = + [] + (auto, auto& fn, auto& rcvr, Tag, Args&&... args) noexcept -> void { + if constexpr (@\libconcept{same_as}@>) { + @\exposid{TRY-SET-VALUE}@(rcvr, + invoke(std::move(fn), std::forward(args)...)); + } else { + Tag()(std::move(rcvr), std::forward(args)...); + } + }; + + template + static consteval void @\exposid{check-types}@(); + }; +} +\end{codeblock} + +\indexlibrarymember{\exposid{check-types}}{\exposid{impls-for}<\exposid{decayed-typeof}<\exposid{then-cpo}>>} +\begin{itemdecl} +template + static consteval void @\exposid{check-types}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto cs = get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(); +auto fn = [](set_value_t(*)(Ts...)) { + if constexpr (!@\libconcept{invocable}@>, Ts...>) + throw @\placeholder{unspecified-exception}@(); +}; +cs.@\exposid{for-each}@(@\exposid{overload-set}@{fn, [](auto){}}); +\end{codeblock} +where \tcode{\placeholder{unspecified-exception}} is +a type derived from \tcode{exception}. +\end{itemdescr} + +\pnum +The expression \tcode{\exposid{then-cpo}(sndr, f)} has undefined behavior +unless it returns a sender \tcode{out_sndr} that +\begin{itemize} +\item +invokes \tcode{f} or a copy of such +with the value, error, or stopped result datums of \tcode{sndr} +for \tcode{then}, \tcode{upon_error}, and \tcode{upon_stopped}, respectively, +using the result value of \tcode{f} as \tcode{out_sndr}'s value completion, and +\item +forwards all other completion operations unchanged. +\end{itemize} + +\rSec3[exec.let]{\tcode{execution::let_value}, \tcode{execution::let_error}, \tcode{execution::let_stopped}} + +\pnum +\tcode{let_value}, \tcode{let_error}, and \tcode{let_stopped} transform +a sender's value, error, and stopped completions, respectively, +into a new child asynchronous operation +by passing the sender's result datums to a user-specified callable, +which returns a new sender that is connected and started. + +\pnum +For \tcode{let_value}, \tcode{let_error}, and \tcode{let_stopped}, +let \exposid{set-cpo} be +\tcode{set_value}, \tcode{set_error}, and \tcode{set_stopped}, respectively. +Let the expression \exposid{let-cpo} be one of +\tcode{let_value}, \tcode{let_error}, or \tcode{let_stopped}. +For a subexpression \tcode{sndr}, +let \tcode{\exposid{let-env}(sndr)} be expression-equivalent to +the first well-formed expression below: +\begin{itemize} +\item +\tcode{\exposid{SCHED-ENV}(get_completion_scheduler<\exposid{decayed-typeof}<\exposid{set-cpo}>>(get_env(sndr)))} +\item +\tcode{\exposid{MAKE-ENV}(get_domain, get_domain(get_env(sndr)))} +\item +\tcode{(void(sndr), env<>\{\})} +\end{itemize} + +\pnum +The names \tcode{let_value}, \tcode{let_error}, and \tcode{let_stopped} denote +pipeable sender adaptor objects. +For subexpressions \tcode{sndr} and \tcode{f}, +let \tcode{F} be the decayed type of \tcode{f}. +If \tcode{decltype((sndr))} does not satisfy \libconcept{sender} or +if \tcode{decltype((f))} does not satisfy \exposconcept{movable-value}, +the expression \tcode{\exposid{let-cpo}(sndr, f)} is ill-formed. +If \tcode{F} does not satisfy \libconcept{invocable}, +the expression \tcode{let_stopped(sndr, f)} is ill-formed. + +\pnum +Otherwise, +the expression \tcode{\exposid{let-cpo}(sndr, f)} is expression-equivalent to: +\begin{codeblock} +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(@\exposid{let-cpo}@, f, sndr)) +\end{codeblock} +except that \tcode{sndr} is evaluated only once. + +\pnum +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \exposid{let-cpo} as follows: +\indexlibraryglobal{\exposid{impls-for}<\exposid{decayed-typeof}<\exposid{let-cpo}>>} +\begin{codeblock} +namespace std::execution { + template + void @\exposid{let-bind}@(State& state, Rcvr& rcvr, Args&&... args); // \expos + + template<> + struct @\exposid{impls-for}@<@\exposid{decayed-typeof}@<@\exposid{let-cpo}@>> : @\exposid{default-impls}@ { + static constexpr auto @\exposid{get-state}@ = @\seebelow@; + static constexpr auto @\exposid{complete}@ = @\seebelow@; + + template + static consteval void @\exposid{check-types}@(); + }; +} +\end{codeblock} + +\pnum +Let \exposid{receiver2} denote the following exposition-only class template: +\begin{codeblock} +namespace std::execution { + template + struct @\exposid{receiver2}@ { + using receiver_concept = receiver_t; + + template + void set_value(Args&&... args) && noexcept { + execution::set_value(std::move(@\exposid{rcvr}@), std::forward(args)...); + } + + template + void set_error(Error&& err) && noexcept { + execution::set_error(std::move(@\exposid{rcvr}@), std::forward(err)); + } + + void set_stopped() && noexcept { + execution::set_stopped(std::move(@\exposid{rcvr}@)); + } + + decltype(auto) get_env() const noexcept { + return @\seebelow@; + } + + Rcvr& @\exposid{rcvr}@; // \expos + Env @\exposid{env}@; // \expos + }; +} +\end{codeblock} +Invocation of the function \tcode{\exposid{receiver2}::get_env} +returns an object \tcode{e} such that +\begin{itemize} +\item +\tcode{decltype(e)} models \exposconcept{queryable} and +\item +given a query object \tcode{q}, +the expression \tcode{e.query(q)} is expression-equivalent +to \tcode{\exposid{env}.query(q)} if that expression is valid; +otherwise, +if the type of \tcode{q} satisfies \exposconcept{forwarding-query}, +\tcode{e.query(q)} is expression-equivalent +to \tcode{get_env(\exposid{rcvr}).query(q)}; +otherwise, +\tcode{e.query(q)} is ill-formed. +\end{itemize} + +\indexlibrarymember{\exposid{check-types}}{\exposid{impls-for}<\exposid{decayed-typeof}<\exposid{let-cpo}>>} +\begin{itemdecl} +template + static consteval void @\exposid{check-types}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +using LetFn = remove_cvref_t<@\exposid{data-type}@>; +auto cs = get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(); +auto fn = [](@\exposid{decayed-typeof}@<@\exposid{set-cpo}@>(*)(Ts...)) { + if constexpr (!@\placeholder{is-valid-let-sender}@) // \seebelow + throw @\placeholder{unspecified-exception}@(); +}; +cs.@\exposid{for-each}@(@\exposid{overload-set}@(fn, [](auto){})); +\end{codeblock} +where \tcode{\placeholder{unspecified-exception}} is +a type derived from \tcode{exception}, and +where \tcode{\placeholder{is-valid-let-sender}} is \tcode{true} if and only if +all of the following are \tcode{true}: +\begin{itemize} +\item \tcode{(\libconcept{constructible_from}, Ts> \&\&...)} +\item \tcode{\libconcept{invocable}\&...>} +\item \tcode{\libconcept{sender}\&...>>} +\item% +\tcode{sizeof...(Env) == 0 || \libconcept{sender_in}\&...>, \placeholder{env-t}\linebreak{}...>} +\end{itemize} +where \tcode{\placeholder{env-t}} is the pack +\tcode{decltype(\exposid{let-cpo}.transform_env(declval(), declval()))}. +\end{itemdescr} + +\pnum +\tcode{\exposid{impls-for}<\exposid{decayed-typeof}<\exposid{let-cpo}>>::\exposid{get-state}} +is initialized with a callable object equivalent to the following: +\begin{codeblock} +[](Sndr&& sndr, Rcvr& rcvr) requires @\seebelow@ { + auto& [_, fn, child] = sndr; + using fn_t = decay_t; + using env_t = decltype(@\exposid{let-env}@(child)); + using args_variant_t = @\seebelow@; + using ops2_variant_t = @\seebelow@; + + struct @\exposid{state-type}@ { + fn_t @\exposid{fn}@; // \expos + env_t @\exposid{env}@; // \expos + args_variant_t @\exposid{args}@; // \expos + ops2_variant_t @\exposid{ops2}@; // \expos + }; + return @\exposid{state-type}@{@\exposid{allocator-aware-forward}@(std::forward_like(fn), rcvr), + @\exposid{let-env}@(child), {}, {}}; +} +\end{codeblock} + +\pnum +Let \tcode{Sigs} be a pack of the arguments +to the \tcode{completion_signatures} specialization named by +\tcode{completion_signatures_of_t<\exposid{child-type}, \exposid{FWD-ENV-T}(env_of_t)>}. +Let \tcode{LetSigs} be a pack of those types in \tcode{Sigs} +with a return type of \tcode{\exposid{decayed-typeof}<\exposid{set-cpo}>}. +Let \exposid{as-tuple} be an alias template +such that \tcode{\exposid{as-tuple}} denotes +the type \tcode{\exposid{decayed-tuple}}. +Then \tcode{args_variant_t} denotes +the type \tcode{variant...>} +except with duplicate types removed. + +\pnum +Given a type \tcode{Tag} and a pack \tcode{Args}, +let \exposid{as-sndr2} be an alias template +such that \tcode{\exposid{as-sndr2}} denotes +the type \tcode{\exposid{call-result-t}\&...>}. +Then \tcode{ops2_variant_t} denotes +the type +\begin{codeblock} +variant, @\exposid{receiver2}@>...> +\end{codeblock} +except with duplicate types removed. + +\pnum +The \grammarterm{requires-clause} constraining the above lambda is satisfied +if and only if +the types \tcode{args_variant_t} and \tcode{ops2_variant_t} are well-formed. + +\pnum +The exposition-only function template \exposid{let-bind} +has effects equivalent to: +\begin{codeblock} +using args_t = @\exposid{decayed-tuple}@; +auto mkop2 = [&] { + return connect( + apply(std::move(state.fn), + state.args.template emplace(std::forward(args)...)), + @\exposid{receiver2}@{rcvr, std::move(state.env)}); +}; +start(state.ops2.template emplace(@\exposid{emplace-from}@{mkop2})); +\end{codeblock} + +\pnum +\tcode{\exposid{impls-for}<\exposid{decayed-typeof}>::\exposid{complete}} +is initialized with a callable object equivalent to the following: +\begin{codeblock} +[] + (auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept -> void { + if constexpr (@\libconcept{same_as}@>) { + @\exposid{TRY-EVAL}@(rcvr, @\exposid{let-bind}@(state, rcvr, std::forward(args)...)); + } else { + Tag()(std::move(rcvr), std::forward(args)...); + } + } +\end{codeblock} + +\pnum +Let \tcode{sndr} and \tcode{env} be subexpressions, and +let \tcode{Sndr} be \tcode{decltype((sndr))}. +If +\tcode{\exposconcept{sender-for}>} +is \tcode{false}, +then the expression \tcode{\exposid{let-cpo}.transform_env(sndr, env)} +is ill-formed. +Otherwise, it is equal to: +\begin{codeblock} +auto& [_, _, child] = sndr; +return @\exposid{JOIN-ENV}@(@\exposid{let-env}@(child), @\exposid{FWD-ENV}@(env)); +\end{codeblock} + +\pnum +Let the subexpression \tcode{out_sndr} denote +the result of the invocation \tcode{\exposid{let-cpo}(sndr, f)} or +an object equal to such, and +let the subexpression \tcode{rcvr} denote a receiver +such that the expression \tcode{connect(out_sndr, rcvr)} is well-formed. +The expression \tcode{connect(out_sndr, rcvr)} has undefined behavior +unless it creates an asynchronous operation\iref{exec.async.ops} that, +when started: +\begin{itemize} +\item +invokes \tcode{f} when \exposid{set-cpo} is called +with \tcode{sndr}'s result datums, +\item +makes its completion dependent on +the completion of a sender returned by \tcode{f}, and +\item +propagates the other completion operations sent by \tcode{sndr}. +\end{itemize} + +\rSec3[exec.bulk]{\tcode{execution::bulk}, \tcode{execution::bulk_chunked}, and \tcode{execution::bulk_unchunked}} + +\pnum +\tcode{bulk}, \tcode{bulk_chunked}, and \tcode{bulk_unchunked} +run a task repeatedly for every index in an index space. + +\pnum +The names \tcode{bulk}, \tcode{bulk_chunked}, and \tcode{bulk_unchunked} +denote pipeable sender adaptor objects. +Let \tcode{\placeholder{bulk-algo}} be either +\tcode{bulk}, \tcode{bulk_chunked}, or \tcode{bulk_unchunked}. +For subexpressions \tcode{sndr}, \tcode{policy}, \tcode{shape}, and \tcode{f}, +let +\tcode{Policy} be \tcode{remove_cvref_t}, +\tcode{Shape} be \tcode{decltype(auto(shape))}, and +\tcode{Func} be \tcode{decay_t}. +If +\begin{itemize} +\item +\tcode{decltype((sndr))} does not satisfy \libconcept{sender}, or +\item +\tcode{is_execution_policy_v} is \tcode{false}, or +\item +\tcode{Shape} does not satisfy \libconcept{integral}, or +\item +\tcode{Func} does not model \libconcept{copy_constructible}, +\end{itemize} +\tcode{\placeholder{bulk-algo}(sndr, policy, shape, f)} is ill-formed. + +\pnum +Otherwise, +the expression \tcode{\placeholder{bulk-algo}(sndr, policy, shape, f)} +is expression-equivalent to: + +\begin{codeblock} +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@( + @\placeholder{bulk-algo}@, @\exposid{product-type}@<@\seebelow@, Shape, Func>{policy, shape, f}, sndr)) +\end{codeblock} +except that \tcode{sndr} is evaluated only once. +The first template argument of \exposid{product-type} is \tcode{Policy} +if \tcode{Policy} models \libconcept{copy_constructible}, and +\tcode{const Policy\&} otherwise. + +\pnum +Let \tcode{sndr} and \tcode{env} be subexpressions such that +\tcode{Sndr} is \tcode{decltype((sndr))}. +If \tcode{\exposconcept{sender-for}} is \tcode{false}, then +the expression \tcode{bulk.transform_sender(sndr, env)} is ill-formed; +otherwise, it is equivalent to: +\begin{codeblock} +auto [_, data, child] = sndr; +auto& [policy, shape, f] = data; +auto new_f = [func = std::move(f)](Shape begin, Shape end, auto&&... vs) + noexcept(noexcept(f(begin, vs...))) { + while (begin != end) func(begin++, vs...); +} +return bulk_chunked(std::move(child), policy, shape, std::move(new_f)); +\end{codeblock} +\begin{note} +This causes the \tcode{bulk(sndr, policy, shape, f)} sender to be +expressed in terms of \tcode{bulk_chunked(sndr, policy, shape, f)} when +it is connected to a receiver whose +execution domain does not customize \tcode{bulk}. +\end{note} + +\pnum +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \tcode{bulk_chunked_t} as follows: +\indexlibraryglobal{\exposid{impls-for}} +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { + static constexpr auto @\exposid{complete}@ = @\seebelow@; + + template + static consteval void @\exposid{check-types}@(); + }; +} +\end{codeblock} +The member \tcode{\exposid{impls-for}::\exposid{complete}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[] + (Index, State& state, Rcvr& rcvr, Tag, Args&&... args) noexcept + -> void requires @\seebelow@ { + if constexpr (@\libconcept{same_as}@) { + auto& [policy, shape, f] = state; + constexpr bool nothrow = noexcept(f(auto(shape), auto(shape), args...)); + @\exposid{TRY-EVAL}@(rcvr, [&]() noexcept(nothrow) { + f(static_cast(0), auto(shape), args...); + Tag()(std::move(rcvr), std::forward(args)...); + }()); + } else { + Tag()(std::move(rcvr), std::forward(args)...); + } + } +\end{codeblock} +The expression in the \grammarterm{requires-clause} of the lambda above is +\tcode{true} if and only +if \tcode{Tag} denotes a type other than \tcode{set_value_t} or +if the expression \tcode{f(auto(shape), auto(shape), args...)} is well-formed. + +\pnum +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \tcode{bulk_unchunked_t} as follows: +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { + static constexpr auto @\exposid{complete}@ = @\seebelow@; + }; +} +\end{codeblock} +The member \tcode{\exposid{impls-for}::\exposid{complete}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[] + (Index, State& state, Rcvr& rcvr, Tag, Args&&... args) noexcept + -> void requires @\seebelow@ { + if constexpr (@\libconcept{same_as}@) { + auto& [shape, f] = state; + constexpr bool nothrow = noexcept(f(auto(shape), args...)); + @\exposid{TRY-EVAL}@(rcvr, [&]() noexcept(nothrow) { + for (decltype(auto(shape)) i = 0; i < shape; ++i) { + f(auto(i), args...); + } + Tag()(std::move(rcvr), std::forward(args)...); + }()); + } else { + Tag()(std::move(rcvr), std::forward(args)...); + } + } +\end{codeblock} +The expression in the \grammarterm{requires-clause} of the lambda above +is \tcode{true} if and only +if \tcode{Tag} denotes a type other than \tcode{set_value_t} or +if the expression \tcode{f(auto(shape), args...)} is well-formed. + +\indexlibrarymember{\exposid{check-types}}{\exposid{impls-for}} +\begin{itemdecl} +template + static consteval void @\exposid{check-types}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto cs = get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(); +auto fn = [](set_value_t(*)(Ts...)) { + if constexpr (!@\libconcept{invocable}@>, Ts&...>) + throw @\placeholder{unspecified-exception}@(); +}; +cs.@\exposid{for-each}@(@\exposid{overload-set}@(fn, [](auto){})); +\end{codeblock} +where \tcode{\placeholder{unspecified-exception}} is +a type derived from \tcode{exception}. +\end{itemdescr} + +\pnum +Let the subexpression \tcode{out_sndr} denote +the result of the invocation +\tcode{\placeholder{bulk-algo}(sndr, policy, shape, f)} or +an object equal to such, and +let the subexpression \tcode{rcvr} denote a receiver +such that the expression \tcode{connect(out_sndr, rcvr)} is well-formed. +The expression \tcode{connect(out_sndr, rcvr)} has undefined behavior +unless it creates an asynchronous operation\iref{exec.async.ops} that, +when started: + +\begin{itemize} +\item +If \tcode{sndr} has a successful completion, where +\tcode{args} is a pack of lvalue subexpressions +referring to the value completion result datums of \tcode{sndr}, or +decayed copies of those values if they model \libconcept{copy_constructible}, +then: + + \begin{itemize} + \item + If \tcode{out_sndr} also completes successfully, then: + + \begin{itemize} + \item + for \tcode{bulk}, + invokes \tcode{f($i$, args...)} for every $i$ of type \tcode{Shape} + from \tcode{0} to \tcode{shape}; + + \item + for \tcode{bulk_unchunked}, + invokes \tcode{f($i$, args...)} for every $i$ of type \tcode{Shape} + from \tcode{0} to \tcode{shape}; + + \recommended + The underlying scheduler should execute each iteration + on a distinct execution agent. + + \item + for \tcode{bulk_chunked}, + invokes \tcode{f($b$, $e$, args...)} zero or more times + with pairs of $b$ and $e$ of type \tcode{Shape} + in range \crange{\tcode{0}}{\tcode{shape}}, + such that $b < e$ and + for every $i$ of type \tcode{Shape} from \tcode{0} to \tcode{shape}, + there is exactly one invocation with a pair $b$ and $e$, + such that $i$ is in the range \range{$b$}{$e$}. + \end{itemize} + + \item + If \tcode{out_sndr} completes with \tcode{set_error(rcvr, eptr)}, then + the asynchronous operation may invoke a subset of + the invocations of \tcode{f} + before the error completion handler is called, and + \tcode{eptr} is an \tcode{exception_ptr} containing either: + \begin{itemize} + \item + an exception thrown by an invocation of \tcode{f}, or + \item + a \tcode{bad_alloc} exception if + the implementation fails to allocate required resources, or + \item + an exception derived from \tcode{runtime_error}. + \end{itemize} + + \item + If \tcode{out_sndr} completes with \tcode{set_stopped(rcvr)}, then + the asynchronous operation may invoke a subset of + the invocations of \tcode{f} + before the stopped completion handler. + \end{itemize} + +\item +If \tcode{sndr} does not complete with \tcode{set_value}, then +the completion is forwarded to \tcode{recv}. + +\item +For \tcode{\placeholder{bulk-algo}}, +the parameter \tcode{policy} describes +the manner in which +the execution of the asynchronous operations corresponding to these algorithms +may be parallelized and +the manner in which +%%FIXME: Should this be "apply to f"? +they apply \tcode{f}. +Permissions and requirements +on parallel algorithm element access functions\iref{algorithms.parallel.exec} +apply to \tcode{f}. +\end{itemize} + +\pnum +\begin{note} +The asynchronous operation corresponding to +\tcode{\placeholder{bulk-algo}(sndr, policy, shape, f)} +can complete with \tcode{set_stopped} if cancellation is requested or +ignore cancellation requests. +\end{note} + +\rSec3[exec.when.all]{\tcode{execution::when_all}} + +\pnum +\tcode{when_all} and \tcode{when_all_with_variant} +both adapt multiple input senders into a sender +that completes when all input senders have completed. +\tcode{when_all} only accepts senders +with a single value completion signature and +on success concatenates all the input senders' value result datums +into its own value completion operation. +\tcode{when_all_with_variant(sndrs...)} is semantically equivalent to +w\tcode{hen_all(into_variant(sndrs)...)}, +where \tcode{sndrs} is a pack of subexpressions +whose types model \libconcept{sender}. + +\pnum +The names \tcode{when_all} and \tcode{when_all_with_variant} denote +customization point objects. +Let \tcode{sndrs} be a pack of subexpressions, +let \tcode{Sndrs} be a pack of the types \tcode{decltype((sndrs))...}, and +let \tcode{CD} be +the type \tcode{common_type_t}. +Let \tcode{CD2} be \tcode{CD} if \tcode{CD} is well-formed, and +\tcode{default_domain} otherwise. +The expressions \tcode{when_all(sndrs...)} and +\tcode{when_all_with_variant(sndrs...)} are ill-formed +if any of the following is \tcode{true}: +\begin{itemize} +\item +\tcode{sizeof...(sndrs)} is \tcode{0}, or +\item +\tcode{(\libconcept{sender} \&\& ...)} is \tcode{false}. +\end{itemize} + +\pnum +The expression \tcode{when_all(sndrs...)} is expression-equivalent to: +\begin{codeblock} +transform_sender(CD2(), @\exposid{make-sender}@(when_all, {}, sndrs...)) +\end{codeblock} + +\pnum +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \tcode{when_all_t} as follows: +\indexlibraryglobal{\exposid{impls-for}} +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { + static constexpr auto @\exposid{get-attrs}@ = @\seebelow@; + static constexpr auto @\exposid{get-env}@ = @\seebelow@; + static constexpr auto @\exposid{get-state}@ = @\seebelow@; + static constexpr auto @\exposid{start}@ = @\seebelow@; + static constexpr auto @\exposid{complete}@ = @\seebelow@; + + template + static consteval void @\exposid{check-types}@(); + }; +} +\end{codeblock} + +\pnum +Let \exposid{make-when-all-env} be +the following exposition-only function template: +\indexlibraryglobal{\exposid{make-when-all-env}} +%%FIXME: Should this be in namespace std::execution? +\begin{codeblock} +template + constexpr auto @\exposid{make-when-all-env}@(inplace_stop_source& stop_src, // \expos + Env&& env) noexcept { + return @\seebelow@; +} +\end{codeblock} +Returns an object \tcode{e} such that +\begin{itemize} +\item +\tcode{decltype(e)} models \exposconcept{queryable}, and +\item +\tcode{e.query(get_stop_token)} is expression-equivalent to +\tcode{state.\exposid{stop-src}.get_token()}, and +\item +given a query object \tcode{q} +with type other than \cv{} \tcode{stop_token_t} and +whose type satisfies \exposconceptx{forwarding-que\-ry}{forwarding-query}, +\tcode{e.query(q)} is expression-equivalent to \tcode{get_env(rcvr).query(q)}. +\end{itemize} + +\pnum +Let \tcode{\placeholder{when-all-env}} be an alias template such that +\tcode{\placeholder{when-all-env}} denotes the type +\tcode{decltype(\exposid{make-\linebreak{}when-all-env}(declval(), declval()))}. + +\indexlibrarymember{\exposid{check-types}}{\exposid{impls-for}} +\begin{itemdecl} +template + static consteval void @\exposid{check-types}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Is} be the pack of integral template arguments of +the \tcode{integer_sequence} specialization denoted by +\tcode{\exposid{indices-for}}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto fn = []() { + auto cs = get_completion_signatures...>(); + if constexpr (cs.@\exposid{count-of}@(set_value) >= 2) + throw @\placeholder{unspecified-exception}@(); + @\exposid{decay-copyable-result-datums}@(cs); // see \ref{exec.snd.expos} +}; +(fn.template operator()<@\exposid{child-type}@>(), ...); +\end{codeblock} +where \tcode{\placeholder{unspecified-exception}} is +a type derived from \tcode{exception}. + +\pnum +\throws +Any exception thrown as a result of evaluating the \Fundescx{Effects}, or +an exception of an unspecified type +derived from \tcode{exception} when \tcode{CD} is ill-formed. +\end{itemdescr} + +\pnum +The member \tcode{\exposid{impls-for}::\exposid{get-attrs}} +is initialized with a callable object +equivalent to the following lambda expression: +\begin{codeblock} +[](auto&&, auto&&... child) noexcept { + if constexpr (@\libconcept{same_as}@) { + return env<>(); + } else { + return @\exposid{MAKE-ENV}@(get_domain, CD()); + } +} +\end{codeblock} + +\pnum +The member \tcode{\exposid{impls-for}::\exposid{get-env}} +is initialized with a callable object +equivalent to the following lambda expression: +\begin{codeblock} +[](auto&&, State& state, const Receiver& rcvr) noexcept { + return @\exposid{make-when-all-env}@(state.@\exposid{stop-src}@, get_env(rcvr)); +} +\end{codeblock} + +\pnum +The member \tcode{\exposid{impls-for}::\exposid{get-state}} +is initialized with a callable object +equivalent to the following lambda expression: +\begin{codeblock} +[](Sndr&& sndr, Rcvr& rcvr) noexcept(noexcept(@$e$@)) -> decltype(@$e$@) { + return @$e$@; +} +\end{codeblock} +where $e$ is the expression +\begin{codeblock} +std::forward(sndr).apply(@\exposid{make-state}@()) +\end{codeblock} +and where \exposid{make-state} is the following exposition-only class template: +\begin{codeblock} +enum class @\exposid{disposition}@ { @\exposid{started}@, @\exposid{error}@, @\exposid{stopped}@ }; // \expos + +template +struct @\exposid{make-state}@ { + template + auto operator()(auto, auto, Sndrs&&... sndrs) const { + using values_tuple = @\seebelow@; + using errors_variant = @\seebelow@; + using stop_callback = stop_callback_for_t>, @\exposid{on-stop-request}@>; + + struct @\exposid{state-type}@ { + void @\exposid{arrive}@(Rcvr& rcvr) noexcept { // \expos + if (0 == --count) { + @\exposid{complete}@(rcvr); + } + } + + void @\exposid{complete}@(Rcvr& rcvr) noexcept; // \expos + + atomic @\exposid{count}@{sizeof...(sndrs)}; // \expos + inplace_stop_source @\exposid{stop_src}@{}; // \expos + atomic<@\exposid{disposition}@> disp{@\exposidnc{disposition}@::@\exposidnc{started}@}; // \expos + errors_variant @\exposid{errors}@{}; // \expos + values_tuple @\exposid{values}@{}; // \expos + optional @\exposid{on_stop}@{nullopt}; // \expos + }; + + return @\exposid{state-type}@{}; + } +}; +\end{codeblock} + +\pnum +Let \exposid{copy-fail} be \tcode{exception_ptr} +if decay-copying any of the child senders' result datums can potentially throw; +otherwise, \tcode{\placeholder{none-such}}, +where \tcode{\placeholder{none-such}} is an unspecified empty class type. + +\pnum +The alias \tcode{values_tuple} denotes the type +\begin{codeblock} +tuple), @\exposid{decayed-tuple}@, optional>...> +\end{codeblock} +if that type is well-formed; otherwise, \tcode{tuple<>}. + +\pnum +The alias \tcode{errors_variant} denotes +the type \tcode{variant<\placeholder{none-such}, \exposid{copy-fail}, Es...>} +with duplicate types removed, +where \tcode{Es} is the pack of the decayed types +of all the child senders' possible error result datums. + +\pnum +The member +\tcode{void \exposid{state-type}::\exposid{complete}(Rcvr\& rcvr) noexcept} +behaves as follows: +\begin{itemize} +\item +If \tcode{disp} is equal to \tcode{\exposid{disposition}::\exposid{started}}, +evaluates: +\begin{codeblock} +auto tie = [](tuple& t) noexcept { return tuple(t); }; +auto set = [&](auto&... t) noexcept { set_value(std::move(rcvr), std::move(t)...); }; + +@\exposid{on_stop}@.reset(); +apply( + [&](auto&... opts) noexcept { + apply(set, tuple_cat(tie(*opts)...)); + }, + values); +\end{codeblock} +\item +Otherwise, +if \tcode{disp} is equal to \tcode{\exposid{disposition}::\exposid{error}}, +evaluates: +\begin{codeblock} +@\exposid{on_stop}@.reset(); +visit( + [&](Error& error) noexcept { + if constexpr (!@\libconcept{same_as}@) { + set_error(std::move(rcvr), std::move(error)); + } + }, + errors); +\end{codeblock} +\item +Otherwise, evaluates: +\begin{codeblock} +@\exposid{on_stop}@.reset(); +set_stopped(std::move(rcvr)); +\end{codeblock} +\end{itemize} + +\pnum +The member \tcode{\exposid{impls-for}::\exposid{start}} +is initialized with a callable object +equivalent to the following lambda expression: +\begin{codeblock} +[]( + State& state, Rcvr& rcvr, Ops&... ops) noexcept -> void { + state.@\exposid{on_stop}@.emplace( + get_stop_token(get_env(rcvr)), + @\exposid{on-stop-request}@{state.@\exposid{stop_src}@}); + if (state.@\exposid{stop_src}@.stop_requested()) { + state.@\exposid{on_stop.}@reset(); + set_stopped(std::move(rcvr)); + } else { + (start(ops), ...); + } +} +\end{codeblock} + +\pnum +The member \exposid{\tcode{impls-for}::\exposid{complete}} +is initialized with a callable object +equivalent to the following lambda expression: +\begin{codeblock} +[]( + this auto& complete, Index, State& state, Rcvr& rcvr, Set, Args&&... args) noexcept -> void { + if constexpr (@\libconcept{same_as}@) { + if (@\exposid{disposition}@::@\exposid{error}@ != state.disp.exchange(@\exposid{disposition}@::@\exposid{error}@)) { + state.@\exposid{stop_src}@.request_stop(); + @\exposid{TRY-EMPLACE-ERROR}@(state.errors, std::forward(args)...); + } + } else if constexpr (@\libconcept{same_as}@) { + auto expected = @\exposid{disposition}@::@\exposid{started}@; + if (state.disp.compare_exchange_strong(expected, @\exposid{disposition}@::@\exposid{stopped}@)) { + state.@\exposid{stop_src}@.request_stop(); + } + } else if constexpr (!@\libconcept{same_as}@>) { + if (state.disp == @\exposid{disposition}@::@\exposid{started}@) { + auto& opt = get(state.values); + @\exposid{TRY-EMPLACE-VALUE}@(complete, opt, std::forward(args)...); + } + } + state.@\exposid{arrive}@(rcvr); +} +\end{codeblock} +where \tcode{\exposid{TRY-EMPLACE-ERROR}(v, e)}, +for subexpressions \tcode{v} and \tcode{e}, is equivalent to: +\begin{codeblock} +try { + v.template emplace(e); +} catch (...) { + v.template emplace(current_exception()); +} +\end{codeblock} +if the expression \tcode{decltype(auto(e))(e)} is potentially throwing; +otherwise, \tcode{v.template emplace(e)}; +and where \tcode{\exposid{TRY-EMPLACE-VALUE}(c, o, as...)}, +for subexpressions \tcode{c}, \tcode{o}, and pack of subexpressions \tcode{as}, +is equivalent to: +\begin{codeblock} +try { + o.emplace(as...); +} catch (...) { + c(Index(), state, rcvr, set_error, current_exception()); + return; +} +\end{codeblock} +if the expression \tcode{\exposid{decayed-tuple}\{as...\}} +is potentially throwing; +otherwise, \tcode{o.emplace(\linebreak as...)}. + +\pnum +The expression \tcode{when_all_with_variant(sndrs...)} +is expression-equivalent to: +\begin{codeblock} +transform_sender(CD2(), @\exposid{make-sender}@(when_all_with_variant, {}, sndrs...)); +\end{codeblock} + +\pnum +Given subexpressions \tcode{sndr} and \tcode{env}, +if +\tcode{\exposconcept{sender-for}} +is \tcode{false}, +then the expression \tcode{when_all_with_variant.transform_sender(sndr, env)} +is ill-formed; +otherwise, it is equivalent to: +\begin{codeblock} +auto&& [_, _, ...child] = sndr; +return when_all(into_variant(std::forward_like(child))...); +\end{codeblock} +\begin{note} +This causes the \tcode{when_all_with_variant(sndrs...)} sender +to become \tcode{when_all(into_variant(sndrs)...)} +when it is connected with a receiver +whose execution domain does not customize \tcode{when_all_with_variant}. +\end{note} + +\rSec3[exec.into.variant]{\tcode{execution::into_variant}} + +\pnum +\tcode{into_variant} adapts a sender with multiple value completion signatures +into a sender with just one value completion signature +consisting of a \tcode{variant} of \tcode{tuple}s. + +\pnum +The name \tcode{into_variant} denotes a pipeable sender adaptor object. +For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}. +If \tcode{Sndr} does not satisfy \libconcept{sender}, +\tcode{into_variant(sndr)} is ill-formed. + +\pnum +Otherwise, the expression \tcode{into_variant(sndr)} +is expression-equivalent to: +\begin{codeblock} +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(into_variant, {}, sndr)) +\end{codeblock} +except that \tcode{sndr} is only evaluated once. + +\pnum +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \tcode{into_variant} as follows: +\indexlibraryglobal{\exposid{impls-for}} +\indexlibrarymember{\exposid{check-types}}{\exposid{impls-for}} +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { + static constexpr auto @\exposid{get-state}@ = @\seebelow@; + static constexpr auto @\exposid{complete}@ = @\seebelow@; + + template + static consteval void @\exposid{check-types}@() { + auto cs = get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(); + @\exposid{decay-copyable-result-datums}@(cs); // see \ref{exec.snd.expos} + } + }; +} +\end{codeblock} + +\pnum +The member \tcode{\exposid{impls-for}::\exposid{get-state}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[](Sndr&& sndr, Rcvr& rcvr) noexcept + -> type_identity, @\exposid{FWD-ENV-T}@(env_of_t)>> { + return {}; +} +\end{codeblock} + +\pnum +The member \tcode{\exposid{impls-for}::\exposid{complete}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[]( + auto, State, Rcvr& rcvr, Tag, Args&&... args) noexcept -> void { + if constexpr (@\libconcept{same_as}@) { + using variant_type = typename State::type; + @\exposid{TRY-SET-VALUE}@(rcvr, variant_type(@\exposid{decayed-tuple}@{std::forward(args)...})); + } else { + Tag()(std::move(rcvr), std::forward(args)...); + } +} +\end{codeblock} + +\rSec3[exec.stopped.opt]{\tcode{execution::stopped_as_optional}} + +\pnum +\tcode{stopped_as_optional} maps a sender's stopped completion operation +into a value completion operation as a disengaged \tcode{optional}. +The sender's value completion operation +is also converted into an \tcode{optional}. +The result is a sender that never completes with stopped, +reporting cancellation by completing with a disengaged \tcode{optional}. + +\pnum +The name \tcode{stopped_as_optional} denotes a pipeable sender adaptor object. +For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}. +The expression \tcode{stopped_as_optional(sndr)} is expression-equivalent to: +\begin{codeblock} +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(stopped_as_optional, {}, sndr)) +\end{codeblock} +except that \tcode{sndr} is only evaluated once. + +\pnum +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \tcode{stopped_as_optional_t} as follows: +\indexlibraryglobal{\exposid{impls-for}} +\indexlibrarymember{\exposid{check-types}}{\exposid{impls-for}} +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { + template + static consteval void @\exposid{check-types}@() { + @\exposid{default-impls}@::@\exposid{check-types}@(); + if constexpr (!requires { + requires (!@\libconcept{same_as}@, + @\exposid{FWD-ENV-T}@(Env)...>>); }) + throw @\placeholder{unspecified-exception}@(); + } + }; +} +\end{codeblock} +where \tcode{\placeholder{unspecified-exception}} is +a type derived from \tcode{exception}. + +\pnum +Let \tcode{sndr} and \tcode{env} be subexpressions +such that \tcode{Sndr} is \tcode{decltype((sndr))} and +\tcode{Env} is \tcode{decltype((env))}. +If \tcode{\exposconcept{sender-for}} +is \tcode{false} +then the expression \tcode{stopped_as_optional.trans\-form_sender(sndr, env)} +is ill-formed; +otherwise, +if \tcode{\libconcept{sender_in}<\exposid{child-type}, \exposid{FWD-ENV-T}(Env)>} +is \tcode{false}, +the expression \tcode{stopped_as_optional.transform_sender(sndr, env)} +is equivalent to \tcode{\exposid{not-a-sen\-der}()}; +otherwise, it is equivalent to: +\begin{codeblock} +auto&& [_, _, child] = sndr; +using V = @\exposid{single-sender-value-type}@<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)>; +return let_stopped( + then(std::forward_like(child), + [](Ts&&... ts) noexcept(is_nothrow_constructible_v) { + return optional(in_place, std::forward(ts)...); + }), + []() noexcept { return just(optional()); }); +\end{codeblock} + +\rSec3[exec.stopped.err]{\tcode{execution::stopped_as_error}} + +\pnum +\tcode{stopped_as_error} maps an input sender's stopped completion operation +into an error completion operation as a custom error type. +The result is a sender that never completes with stopped, +reporting cancellation by completing with an error. + +\pnum +The name \tcode{stopped_as_error} denotes a pipeable sender adaptor object. +For some subexpressions \tcode{sndr} and \tcode{err}, +let \tcode{Sndr} be \tcode{decltype((sndr))} and +let \tcode{Err} be \tcode{decltype((err))}. +If the type \tcode{Sndr} does not satisfy \libconcept{sender} or +if the type \tcode{Err} does not satisfy \exposconcept{movable-value}, +\tcode{stopped_as_error(sndr, err)} is ill-formed. +Otherwise, the expression \tcode{stopped_as_error(sndr, err)} +is expression-equivalent to: +\begin{codeblock} +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(stopped_as_error, err, sndr)) +\end{codeblock} +except that \tcode{sndr} is only evaluated once. + +\pnum +Let \tcode{sndr} and \tcode{env} be subexpressions +such that \tcode{Sndr} is \tcode{decltype((sndr))} and +\tcode{Env} is \tcode{decltype((env))}. +If \tcode{\exposconcept{sender-for}} is \tcode{false}, +then the expression \tcode{stopped_as_error.transform_sender(sndr, env)} +is ill-formed; +otherwise, it is equivalent to: +\begin{codeblock} +auto&& [_, err, child] = sndr; +using E = decltype(auto(err)); +return let_stopped( + std::forward_like(child), + [err = std::forward_like(err)]() mutable noexcept(is_nothrow_move_constructible_v) { + return just_error(std::move(err)); + }); +\end{codeblock} + +\rSec3[exec.associate]{\tcode{std::execution::associate}} + +\pnum +\tcode{associate} tries to associate +a sender with an async scope such that +the scope can track the lifetime of any asynchronous operations +created with the sender. + +\pnum +Let \exposid{associate-data} be the following exposition-only class template: + +\indexlibraryglobal{execution::\exposid{associate-data}}% +\begin{codeblock} +namespace std::execution { + template<@\libconcept{scope_token}@ Token, @\libconcept{sender}@ Sender> + struct @\exposid{associate-data}@ { // \expos + using @\exposid{wrap-sender}@ = // \expos + remove_cvref_t().wrap(declval()))>; + + explicit @\exposid{associate-data}@(Token t, Sender&& s) + : @\exposid{sndr}@(t.wrap(std::forward(s))), + @\exposid{token}@(t) { + if (!@\exposid{token}@.try_associate()) + @\exposid{sndr}@.reset(); + } + + @\exposid{associate-data}@(const @\exposid{associate-data}@& other) + noexcept(is_nothrow_copy_constructible_v<@\exposid{wrap-sender}@> && + noexcept(other.@\exposid{token}@.try_associate())); + + @\exposid{associate-data}@(@\exposid{associate-data}@&& other) + noexcept(is_nothrow_move_constructible_v<@\exposid{wrap-sender}@>); + + ~@\exposid{associate-data}@(); + + optional> + release() && noexcept(is_nothrow_move_constructible_v<@\exposid{wrap-sender}@>); + + private: + optional<@\exposid{wrap-sender}@> @\exposid{sndr}@; // \expos + Token @\exposid{token}@; // \expos + }; + + template<@\libconcept{scope_token}@ Token, @\libconcept{sender}@ Sender> + @\exposid{associate-data}@(Token, Sender&&) -> @\exposid{associate-data}@; +} +\end{codeblock} + +\pnum +For an \exposid{associate-data} object \tcode{a}, +\tcode{a.\exposid{sndr}.has_value()} is \tcode{true} +if and only if +an association was successfully made and is owned by \tcode{a}. + +\indexlibraryctor{execution::\exposid{associate-data}}% +\begin{itemdecl} +@\exposid{associate-data}@(const @\exposid{associate-data}@& other) + noexcept(is_nothrow_copy_constructible_v<@\exposid{wrap-sender}@> && + noexcept(other.@\exposid{token}@.try_associate())); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{\libconcept{copy_constructible}<\exposid{wrap-sender}>} is \tcode{true}. + +\pnum +\effects +Value-initializes \exposid{sndr} and +initializes \exposid{token} with \tcode{other.\exposid{token}}. +If \tcode{other.\exposid{sndr}.has_value()} is \tcode{false}, +no further effects; +otherwise, +calls \tcode{\exposid{token}.try_associate()} and, +if that returns \tcode{true}, +calls \tcode{\exposid{sndr}.emplace(*other.\exposid{sndr})} and, +if that exits with an exception, +calls \tcode{\exposid{token}.disassociate()} before propagating the exception. +\end{itemdescr} + +\indexlibraryctor{execution::\exposid{associate-data}}% +\begin{itemdecl} +@\exposid{associate-data}@(@\exposid{associate-data}@&& other) + noexcept(is_nothrow_move_constructible_v<@\exposid{wrap-sender}@>); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{sndr} with \tcode{std::move(other.\exposid{sndr})} and +initializes \exposid{token} with \tcode{std::move(other.\brk{}\exposid{token})} and +then calls \tcode{other.\exposid{sndr}.reset()}. +\end{itemdescr} + +\indexlibrarydtor{execution::\exposid{associate-data}}% +\begin{itemdecl} +~@\exposid{associate-data}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{\exposid{sndr}.has_value()} returns \tcode{false} then no effect; +otherwise, invokes \tcode{\exposid{sndr}.reset()} +before invoking \tcode{\exposid{token}.disassociate()}. +\end{itemdescr} + +\indexlibrarymember{release}{execution::\exposid{associate-data}}% +\begin{itemdecl} +optional> + release() && noexcept(is_nothrow_move_constructible_v<@\exposid{wrap-sender}@>); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{\exposid{sndr}.has_value()} returns \tcode{false} then +returns an \tcode{optional} that does not contain a value; +otherwise returns an \tcode{optional} +containing a value of type \tcode{pair} +as if by: +\begin{codeblock} +return optional(pair(@\exposid{token}@, std::move(*@\exposid{sndr}@))); +\end{codeblock} + +\pnum +\ensures +\exposid{sndr} does not contain a value. +\end{itemdescr} + +\pnum +The name \tcode{associate} denotes a pipeable sender adaptor object. +For subexpressions \tcode{sndr} and \tcode{token}: +\begin{itemize} +\item +If \tcode{decltype((sndr))} does not satisfy \libconcept{sender}, or +\tcode{remove_cvref_t} +does not satisfy \libconcept{scope_token}, then +\tcode{associate(sndr, token)} is ill-formed. +\item +Otherwise, +the expression \tcode{associate(sndr, token)} +is expression-equivalent to: +\begin{codeblock} +transform_sender(@\exposid{get-domain-early}@(sndr), + @\exposid{make-sender}@(associate, @\exposid{associate-data}@(token, sndr))) +\end{codeblock} +except that \tcode{sndr} is evaluated only once. +\end{itemize} + +\pnum +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \tcode{associate_t} as follows: +\indexlibraryglobal{execution::\exposid{impls-for}}% +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { + static constexpr auto @\exposid{get-state}@ = @\seebelow@; // \expos + static constexpr auto @\exposid{start}@ = @\seebelow@; // \expos + + template + static consteval void @\exposid{check-types}@() { // \expos + using associate_data_t = remove_cvref_t<@\exposid{data-type}@>; + using child_type_t = typename associate_data_t::@\exposid{wrap-sender}@; + (void)get_completion_signatures(); + } + }; +} +\end{codeblock} + +\pnum +The member \tcode{\exposid{impls-for}::\exposid{get-state}} +is initialized with a callable object equivalent to the following lambda: + +\begin{codeblock} +[](Sndr&& sndr, Rcvr& rcvr) noexcept(@\seebelow@) { + auto [_, data] = std::forward(sndr); + auto dataParts = std::move(data).release(); + + using scope_tkn = decltype(dataParts->first); + using wrap_sender = decltype(dataParts->second); + using op_t = connect_result_t; + + struct op_state { + bool @\exposid{associated}@ = false; // \expos + union { + Rcvr* @\exposid{rcvr}@; // \expos + struct { + scope_tkn @\exposid{token}@; // \expos + op_t @\exposid{op}@; // \expos + } @\exposid{assoc}@; // \expos + }; + + explicit op_state(Rcvr& r) noexcept + : @\exposid{rcvr}@(addressof(r)) {} + + explicit op_state(scope_tkn tkn, wrap_sender&& sndr, Rcvr& r) try + : @\exposid{associated}@(true), + @\exposid{assoc}@(tkn, connect(std::move(sndr), std::move(r))) { + } + catch (...) { + tkn.disassociate(); + throw; + } + + op_state(op_state&&) = delete; + + ~op_state() { + if (@\exposid{associated}@) { + @\exposid{assoc}@.@\exposid{op}@.~op_t(); + @\exposid{assoc}@.@\exposid{token}@.disassociate(); + @\exposid{assoc}@.@\exposid{token}@.~scope_tkn(); + } + } + + void @\exposid{run}@() noexcept { // \expos + if (@\exposid{associated}@) + start(@\exposid{assoc}@.@\exposid{op}@); + else + set_stopped(std::move(*@\exposid{rcvr}@)); + } + }; + + if (dataParts) + return op_state{std::move(dataParts->first), std::move(dataParts->second), rcvr}; + else + return op_state{rcvr}; +} +\end{codeblock} + +\pnum +The expression in the \tcode{noexcept} clause of +\tcode{\exposid{impls-for}::\exposid{get-state}} is +\begin{codeblock} +is_nothrow_constructible_v, Sndr> && +is_nothrow_move_constructible_v<@\exposid{wrap-sender}@> && +@\exposconcept{nothrow-callable}@ +\end{codeblock} +where \exposid{wrap-sender} is the type +\tcode{remove_cvref_t<\exposid{data-type}>::\exposid{wrap-sender}}. + +\pnum +The member \tcode{\exposid{impls-for}::\exposid{start}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[](auto& state, auto&) noexcept -> void { + state.@\exposid{run}@(); +} +\end{codeblock} + +\pnum +%%FIXME: What are "sndr" and "token" referring to here? +The evaluation of \tcode{associate(sndr, token)} +may cause side effects observable +via \tcode{token}{'s} associated async scope object. + +\rSec3[exec.stop.when]{Exposition-only \tcode{std::execution::\exposid{stop-when}}} + +\pnum +%%FIXME: Should stop-when be declared somewhere as \expos? +\exposid{stop-when} fuses an additional stop token \tcode{t} +into a sender so that, upon connecting to a receiver \tcode{r}, +the resulting operation state receives stop requests from both +\tcode{t} and the token returned from \tcode{get_stop_token(get_env(r))}. + +\pnum +The name \exposid{stop-when} denotes an exposition-only sender adaptor. +For subexpressions \tcode{sndr} and \tcode{token}: +\begin{itemize} +\item +If \tcode{decltype((sndr))} does not satisfy \libconcept{sender}, or +\tcode{remove_cvref_t} +does not satisfy \libconcept{stoppable_token}, +then \tcode{\exposid{stop-when}(sndr, token)} is ill-formed. + +\item +Otherwise, +if \tcode{remove_cvref_t} models +\libconcept{unstoppable_token} then +\tcode{\exposid{stop-when}(\brk{}sndr, token)} is expression-equivalent to +\tcode{sndr}. + +\item +Otherwise, +\tcode{\exposid{stop-when}(sndr, token)} returns a sender \tcode{osndr}. +%%FIXME: What is rtoken if osndr is not connected to a receiver? +If \tcode{osndr} is connected to a receiver \tcode{r}, +let \tcode{rtoken} be the result of \tcode{get_stop_token(get_env(r))}. + +\begin{itemize} +\item +If the type of \tcode{rtoken} models \libconcept{unstoppable_token} then +the effects of connecting \tcode{osndr} to \tcode{r} +are equivalent to +\tcode{connect(write_env(sndr, prop(get_stop_token, token)), r)}. + +\item +Otherwise, +the effects of connecting \tcode{osndr} to \tcode{r} +are equivalent to +\tcode{connect(write_env(sndr, prop(get_stop_token, stoken)), r)} +where \tcode{stoken} is an object of +an exposition-only type \exposid{stoken-t} such that: + \begin{itemize} + \item + \exposid{stoken-t} models \libconcept{stoppable_token}; + \item + \tcode{stoken.stop_requested()} returns + \tcode{token.stop_requested() || rtoken.stop_reques-\linebreak{}ted()}; + \item + \tcode{stoken.stop_possible()} returns + \tcode{token.stop_possible() || rtoken.stop_possible()}; and + \item + for types \tcode{Fn} and \tcode{Init} such that both + \tcode{\libconcept{invocable}} and + \tcode{\libconcept{constructible_from}} + are modeled, + \tcode{\exposid{stoken-t}::callback_type} models + \tcode{\exposconcept{stoppable-callback-for}}. + \begin{tailnote} + For an object \tcode{fn} of type \tcode{Fn} + constructed from a value, \tcode{init}, of type \tcode{Init}, + registering \tcode{fn} using + \tcode{\exposid{stoken-t}::callback_type(stoken, init)} + results in an invocation of \tcode{fn} when + a callback registered with \tcode{token} or \tcode{rtoken} would be invoked. + \tcode{fn} is invoked at most once. + \end{tailnote} + \end{itemize} +\end{itemize} +\end{itemize} + +\rSec3[exec.spawn.future]{\tcode{std::execution::spawn_future}} + +\pnum +\tcode{spawn_future} attempts to associate the given input sender +with the given token's async scope and, on success, +eagerly starts the input sender; +the return value is a sender that, when connected and started, +completes with either +the result of the eagerly-started input sender or with +\tcode{set_stopped} if the input sender was not started. + +\pnum +The name \tcode{spawn_future} denotes a customization point object. +For subexpressions \tcode{sndr}, \tcode{token}, and \tcode{env}, +\begin{itemize} +\item let \tcode{Sndr} be \tcode{decltype((sndr))}, +\item let \tcode{Token} be \tcode{remove_cvref_t}, and +\item let \tcode{Env} be \tcode{remove_cvref_t}. +\end{itemize} +If any of +\tcode{\libconcept{sender}}, +\tcode{\libconcept{scope_token}}, or +\tcode{\exposconcept{queryable}} +are not satisfied, +the expression \tcode{spawn_future(sndr, token, env)} is ill-formed. + +\pnum +Let \exposid{spawn-future-state-base} be the exposition-only class template: + +\indexlibraryglobal{execution::\exposid{spawn-future-state-base}}% +\begin{codeblock} +namespace std::execution { + template + struct @\exposid{spawn-future-state-base}@; // \expos + + template + struct @\exposid{spawn-future-state-base}@> { // \expos + using @\exposid{variant-t}@ = @\seebelow@; // \expos + @\exposid{variant-t}@ @\exposid{result}@; // \expos + virtual void @\exposid{complete}@() noexcept = 0; // \expos + }; +} +\end{codeblock} + +\pnum +Let \tcode{Sigs} be the pack of arguments to +the \tcode{completion_signatures} specialization provided as +a parameter to the \exposid{spawn-future-state-base} class template. +Let \exposid{as-tuple} be an alias template that +transforms a completion signature \tcode{Tag(Args...)} +into the tuple specialization \tcode{\exposid{decayed-tuple}}. + +\begin{itemize} +\item +If \tcode{is_nothrow_constructible_v, Arg>} is \tcode{true} +for every type \tcode{Arg} +in every parameter pack \tcode{Args} +in every completion signature \tcode{Tag(Args...)} +in \tcode{Sigs} then +\exposid{variant-t} denotes the type +\tcode{variant, \placeholder{as-tuple}...>}, +except with duplicate types removed. + +\item +Otherwise +\exposid{variant-t} denotes the type +\tcode{variant, tuple, \placeholder{as-tuple}...>}, +except with duplicate types removed. +\end{itemize} + +\pnum +Let \exposid{spawn-future-receiver} be the exposition-only class template: + +\indexlibraryglobal{execution::\exposid{spawn-future-receiver}}% +\begin{codeblock} +namespace std::execution { + template + struct @\exposid{spawn-future-receiver}@ { // \expos + using receiver_concept = receiver_t; + + @\exposid{spawn-future-state-base}@* @\exposid{state}@; // \expos + + template + void set_value(T&&... t) && noexcept { + @\exposid{set-complete}@(std::forward(t)...); + } + + template + void set_error(E&& e) && noexcept { + @\exposid{set-complete}@(std::forward(e)); + } + + void set_stopped() && noexcept { + @\exposid{set-complete}@(); + } + + private: + template + void @\exposid{set-complete}@(T&&... t) noexcept { // \expos + constexpr bool nothrow = (is_nothrow_constructible_v, T> && ...); + try { + @\exposid{state}@->@\exposid{result}@.template emplace<@\exposid{decayed-tuple}@>(CPO{}, + std::forward(t)...); + } + catch (...) { + if constexpr (!nothrow) { + using tuple_t = @\exposid{decayed-tuple}@; + @\exposid{state}@->@\exposid{result}@.template emplace(set_error_t{}, current_exception()); + } + } + @\exposid{state}@->@\exposid{complete}@(); + } + }; +} +\end{codeblock} + +\pnum +Let \placeholder{ssource-t} be an unspecified type +that models \exposconcept{stoppable-source} and +let \tcode{ssource} be an lvalue of type \placeholder{ssource-t}. +Let \tcode{\placeholder{stoken-t}} be \tcode{decltype(ssource.get_token())}. +Let \exposid{future-spawned-sender} be the alias template: + +\begin{codeblock} +template<@\libconcept{sender}@ Sender, class Env> +using @\exposid{future-spawned-sender}@ = // \expos + decltype(write_env(@\exposid{stop-when}@(declval(), declval<@\placeholder{stoken-t}@>()), declval())); +\end{codeblock} + +\pnum +Let \exposid{spawn-future-state} be the exposition-only class template: + +\indexlibraryglobal{execution::\exposid{spawn-future-state}}% +\begin{codeblock} +namespace std::execution { + template + struct @\exposid{spawn-future-state}@ // \expos + : @\exposid{spawn-future-state-base}@>> { + using @\exposid{sigs-t}@ = // \expos + completion_signatures_of_t<@\exposid{future-spawned-sender}@>; + using @\exposid{receiver-t}@ = // \expos + @\exposid{spawn-future-receiver}@<@\exposid{sigs-t}@>; + using @\exposid{op-t}@ = // \expos + connect_result_t<@\exposid{future-spawned-sender}@, @\exposid{receiver-t}@>; + + @\exposid{spawn-future-state}@(Alloc alloc, Sender&& sndr, Token token, Env env) // \expos + : @\exposid{alloc}@(std::move(alloc)), + @\exposid{op}@(connect( + write_env(@\exposid{stop-when}@(std::forward(sndr), @\exposid{ssource}@.get_token()), std::move(env)), + @\exposid{receiver-t}@(this))), + @\exposid{token}@(std::move(token)), + @\exposid{associated}@(token.try_associate()) { + if (associated) + start(@\exposid{op}@); + else + set_stopped(@\exposid{receiver-t}@(this)); + } + + void @\exposid{complete}@() noexcept override; // \expos + void @\exposid{consume}@(@\libconcept{receiver}@ auto& rcvr) noexcept; // \expos + void @\exposid{abandon}@() noexcept; // \expos + + private: + using @\exposid{alloc-t}@ = // \expos + typename allocator_traits::template rebind_alloc<@\exposid{spawn-future-state}@>; + + @\exposid{alloc-t}@ @\exposid{alloc}@; // \expos + @\exposid{ssource-t}@ @\exposid{ssource}@; // \expos + @\exposid{op-t}@ @\exposid{op}@; // \expos + Token @\exposid{token}@; // \expos + bool @\exposid{associated}@; // \expos + + void @\exposid{destroy}@() noexcept; // \expos + }; +} +\end{codeblock} + +\pnum +For purposes of determining the existence of a data race, +\exposid{complete}, \exposid{consume}, and \exposid{abandon} +behave as atomic operations\iref{intro.multithread}. +These operations on a single object of a type +that is a specialization of \exposid{spawn-future-state} +appear to occur in a single total order. + +\indexlibrarymember{\exposid{complete}}{execution::\exposid{spawn-future-state}}% +\begin{itemdecl} +void @\exposid{complete}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +No effects if this invocation of \exposid{complete} happens before +an invocation of \exposid{consume} or \exposid{abandon} on \tcode{*this}; +\item +otherwise, +if an invocation of \exposid{consume} on \tcode{*this} happens before +this invocation of \exposid{complete} then +there is a receiver, \tcode{rcvr}, registered and +that receiver is completed as if by \tcode{\exposid{consume}(rcvr)}; +\item +otherwise, +\exposid{destroy} is invoked. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{\exposid{consume}}{execution::\exposid{spawn-future-state}}% +\begin{itemdecl} +void @\exposid{consume}@(@\libconcept{receiver}@ auto& rcvr) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +If this invocation of \exposid{consume} happens before +an invocation of \exposid{complete} on \tcode{*this} then +\tcode{rcvr} is registered to be completed when +\exposid{complete} is subsequently invoked on \tcode{*this}; + +\item +otherwise, +\tcode{rcvr} is completed as if by: +\begin{codeblock} +std::move(this->@\exposid{result}@).visit( + [&rcvr](auto&& tuple) noexcept { + if constexpr (!@\libconcept{same_as}@, monostate>) { + apply([&rcvr](auto cpo, auto&&... vals) { + cpo(std::move(rcvr), std::move(vals)...); + }, std::move(tuple)); + } + }); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{\exposid{abandon}}{execution::\exposid{spawn-future-state}}% +\begin{itemdecl} +void @\exposid{abandon}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +If this invocation of \exposid{abandon} happens before +an invocation of \exposid{complete} on \tcode{*this} then +equivalent to: +\begin{codeblock} +@\exposid{ssource}@.request_stop(); +\end{codeblock} +\item +otherwise, +\exposid{destroy} is invoked. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{\exposid{destroy}}{execution::\exposid{spawn-future-state}}% +\begin{itemdecl} +void @\exposid{destroy}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto token = std::move(this->@\exposid{token}@); +bool associated = this->@\exposid{associated}@; + +{ + auto alloc = std::move(this->@\exposid{alloc}@); + + allocator_traits<@\exposid{alloc-t}@>::destroy(alloc, this); + allocator_traits<@\exposid{alloc-t}@>::deallocate(alloc, this, 1); +} + +if (associated) + token.disassociate(); +\end{codeblock} +\end{itemdescr} + +\pnum +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \tcode{spawn_future_t} as follows: + +\indexlibraryglobal{execution::\exposid{impls-for}}% +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { + static constexpr auto @\exposid{start}@ = @\seebelow@; // \expos + }; +} +\end{codeblock} + +\pnum +The member \tcode{\exposid{impls-for}::\exposid{start}} +is initialized with a callable object equivalent to the following lambda: +\begin{codeblock} +[](auto& state, auto& rcvr) noexcept -> void { + state->@\exposid{consume}@(rcvr); +} +\end{codeblock} + +\pnum +For the expression \tcode{spawn_future(sndr, token, env)} +let \tcode{new_sender} be the expression \tcode{token.wrap(sndr)} and +let \tcode{alloc} and \tcode{senv} be defined as follows: +\begin{itemize} +\item +if the expression \tcode{get_allocator(env)} is well-formed, then +\tcode{alloc} is the result of \tcode{get_allocator(env)} and +\tcode{senv} is the expression \tcode{env}; +\item +otherwise, +if the expression \tcode{get_allocator(get_env(new_sender))} is well-formed, then +\tcode{alloc} is the result of \tcode{get_allocator(get_env(new_sender))} and +\tcode{senv} is the expression +\tcode{\exposid{JOIN-ENV}(prop(get_allocator, alloc), env)}; +\item +otherwise, +\tcode{alloc} is \tcode{allocator()} and +\tcode{senv} is the expression \tcode{env}. +\end{itemize} + +\pnum +The expression \tcode{spawn_future(sndr, token, env)} +has the following effects: + +\begin{itemize} +\item +Uses \tcode{alloc} to allocate and construct an object \tcode{s} of +a type that is a specialization of \exposid{spawn-future-\brk{}state} +from \tcode{alloc}, \tcode{token.wrap(sndr)}, \tcode{token}, and \tcode{senv}. +If an exception is thrown then +any constructed objects are destroyed and +any allocated memory is deallocated. + +\item +Constructs an object \tcode{u} of +a type that is a specialization of \tcode{unique_ptr} such that: + \begin{itemize} + \item + \tcode{u.get()} is equal to the address of \tcode{s}, and + \item + \tcode{u.get_deleter()(u.release())} is equivalent to + \tcode{u.release()->\exposid{abandon}()}. + \end{itemize} + +\item +Returns \tcode{\exposid{make-sender}(spawn_future, std::move(u))}. +\end{itemize} + +\pnum +The expression \tcode{spawn_future(sndr, token)} is expression-equivalent to +\tcode{spawn_future(sndr, token, ex\-ecution::env<>())}. + +\rSec2[exec.consumers]{Sender consumers} + +\rSec3[exec.sync.wait]{\tcode{this_thread::sync_wait}} + +\pnum +\tcode{this_thread::sync_wait} and \tcode{this_thread::sync_wait_with_variant} +are used +to block the current thread of execution +until the specified sender completes and +to return its async result. +\tcode{sync_wait} mandates +that the input sender has exactly one value completion signature. + +\pnum +Let \exposid{sync-wait-env} be the following exposition-only class type: +\begin{codeblock} +namespace std::this_thread { + struct @\exposid{sync-wait-env}@ { + execution::run_loop* @\exposid{loop}@; // \expos + + auto query(execution::get_scheduler_t) const noexcept { + return @\exposid{loop}@->get_scheduler(); + } + + auto query(execution::get_delegation_scheduler_t) const noexcept { + return @\exposid{loop}@->get_scheduler(); + } + }; +} +\end{codeblock} + +\pnum +Let \exposid{sync-wait-result-type} and +\exposid{sync-wait-with-variant-result-type} +be exposition-only alias templates defined as follows: +\begin{codeblock} +namespace std::this_thread { + template Sndr> + using @\exposid{sync-wait-result-type}@ = + optional>; + + template Sndr> + using @\exposid{sync-wait-with-variant-result-type}@ = + optional>; +} +\end{codeblock} + +\pnum +The name \tcode{this_thread::sync_wait} denotes a customization point object. +For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}. +The expression \tcode{this_thread::sync_wait(sndr)} +is expression-equivalent to the following, +except that \tcode{sndr} is evaluated only once: +\begin{codeblock} +apply_sender(@\exposid{get-domain-early}@(sndr), sync_wait, sndr) +\end{codeblock} +\mandates +\begin{itemize} +\item +\tcode{\libconcept{sender_in}} is \tcode{true}. +\item +The type \tcode{\exposid{sync-wait-result-type}} is well-formed. +\item +\tcode{\libconcept{same_as}>} +is \tcode{true}, where $e$ is the \tcode{apply_sender} expression above. +\end{itemize} + +\pnum +Let \exposid{sync-wait-state} and \exposid{sync-wait-receiver} +be the following exposition-only class templates: +\begin{codeblock} +namespace std::this_thread { + template + struct @\exposid{sync-wait-state}@ { // \expos + execution::run_loop @\exposid{loop}@; // \expos + exception_ptr @\exposid{error}@; // \expos + @\exposid{sync-wait-result-type}@ @\exposidnc{result}@; // \expos + }; + + template + struct @\exposid{sync-wait-receiver}@ { // \expos + using receiver_concept = execution::receiver_t; + @\exposidnc{sync-wait-state}@* @\exposid{state}@; // \expos + + template + void set_value(Args&&... args) && noexcept; + + template + void set_error(Error&& err) && noexcept; + + void set_stopped() && noexcept; + + @\exposid{sync-wait-env}@ get_env() const noexcept { return {&@\exposid{state}@->@\exposid{loop}@}; } + }; +} +\end{codeblock} + +\begin{itemdecl} +template +void set_value(Args&&... args) && noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +try { + @\exposid{state}@->@\exposid{result}@.emplace(std::forward(args)...); +} catch (...) { + @\exposid{state}@->@\exposid{error}@ = current_exception(); +} +@\exposid{state}@->@\exposid{loop}@.finish(); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template +void set_error(Error&& err) && noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{state}@->@\exposid{error}@ = @\exposid{AS-EXCEPT-PTR}@(std::forward(err)); // see \ref{exec.general} +@\exposid{state}@->@\exposid{loop}@.finish(); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +void set_stopped() && noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{\exposid{state}->\exposid{loop}.finish()}. +\end{itemdescr} + +\pnum +For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}. +If \tcode{\libconcept{sender_to}>} +is \tcode{false}, +the expression \tcode{sync_wait.apply_sender(sndr)} is ill-formed; +otherwise, it is equivalent to: +\begin{codeblock} +@\exposid{sync-wait-state}@ state; +auto op = connect(sndr, @\exposid{sync-wait-receiver}@{&state}); +start(op); + +state.@\exposid{loop}@.run(); +if (state.@\exposid{error}@) { + rethrow_exception(std::move(state.@\exposid{error}@)); +} +return std::move(state.@\exposid{result}@); +\end{codeblock} + +\pnum +The behavior of \tcode{this_thread::sync_wait(sndr)} is undefined unless: +\begin{itemize} +\item +It blocks the current thread of execution\iref{defns.block} +with forward progress guarantee delegation\iref{intro.progress} +until the specified sender completes. +\begin{note} +The default implementation of \tcode{sync_wait} achieves +forward progress guarantee delegation by providing a \tcode{run_loop} scheduler +via the \tcode{get_delegation_scheduler} query +on the \exposid{sync-wait-receiver}'s environment. +The \tcode{run_loop} is driven by the current thread of execution. +\end{note} +\item +It returns the specified sender's async results as follows: +\begin{itemize} +\item +For a value completion, +the result datums are returned in +a \tcode{tuple} in an engaged \tcode{optional} object. +\item +For an error completion, an exception is thrown. +\item +For a stopped completion, a disengaged \tcode{optional} object is returned. +\end{itemize} +\end{itemize} + +\rSec3[exec.sync.wait.var]{\tcode{this_thread::sync_wait_with_variant}} + +\pnum +The name \tcode{this_thread::sync_wait_with_variant} denotes +a customization point object. +For a subexpression \tcode{sndr}, +let \tcode{Sndr} be \tcode{decltype(into_variant(sndr))}. +The expression \tcode{this_thread::sync_wait_with_variant(sndr)} +is expression-equivalent to the following, +except \tcode{sndr} is evaluated only once: +\begin{codeblock} +apply_sender(@\exposid{get-domain-early}@(sndr), sync_wait_with_variant, sndr) +\end{codeblock} +\mandates +\begin{itemize} +\item +\tcode{\libconcept{sender_in}} is \tcode{true}. +\item +The type \tcode{\exposid{sync-wait-with-variant-result-type}} +is well-formed. +\item +\tcode{\libconcept{same_as}>} +is \tcode{true}, where $e$ is the \tcode{ap\-ply_sender} expression above. +\end{itemize} + +\pnum +The expression \tcode{sync_wait_with_variant.apply_sender(sndr)} is equivalent to: +\begin{codeblock} +using result_type = @\exposid{sync-wait-with-variant-result-type}@; +if (auto opt_value = sync_wait(into_variant(sndr))) { + return result_type(std::move(get<0>(*opt_value))); +} +return result_type(nullopt); +\end{codeblock} + +\pnum +The behavior of \tcode{this_thread::sync_wait_with_variant(sndr)} +is undefined unless: +\begin{itemize} +\item +It blocks the current thread of execution\iref{defns.block} +with forward progress guarantee delegation\iref{intro.progress} +until the specified sender completes. +\begin{note} +The default implementation of \tcode{sync_wait_with_variant} achieves +forward progress guarantee delegation by relying on +the forward progress guarantee delegation provided by \tcode{sync_wait}. +\end{note} +\item +It returns the specified sender's async results as follows: +\begin{itemize} +\item +For a value completion, +the result datums are returned in an engaged \tcode{optional} object +that contains a \tcode{variant} of \tcode{tuple}s. +\item +For an error completion, an exception is thrown. +\item +For a stopped completion, a disengaged \tcode{optional} object is returned. +\end{itemize} +\end{itemize} + +\rSec3[exec.spawn]{\tcode{std::execution::spawn}} + +\pnum +\tcode{spawn} attempts to associate the given input sender with +the given token's async scope and, on success, +eagerly starts the input sender. + +\pnum +The name \tcode{spawn} denotes a customization point object. +For subexpressions \tcode{sndr}, \tcode{token}, and \tcode{env}, +\begin{itemize} +\item let \tcode{Sndr} be \tcode{decltype((sndr))}, +\item let \tcode{Token} be \tcode{remove_cvref_t}, and +\item let \tcode{Env} be \tcode{remove_cvref_t}. +\end{itemize} +If any of +\tcode{\libconcept{sender}}, +\tcode{\libconcept{scope_token}}, or +\tcode{\exposconcept{queryable}} +are not satisfied, +the expression \tcode{spawn(\brk{}sndr, token, env)} is ill-formed. + +\pnum +Let \exposid{spawn-state-base} be the exposition-only class: + +\indexlibraryglobal{execution::\exposid{spawn-state-base}}% +\begin{codeblock} +namespace std::execution { + struct @\exposid{spawn-state-base}@ { // \expos + virtual void @\exposid{complete}@() noexcept = 0; // \expos + }; +} +\end{codeblock} + +\pnum +Let \exposid{spawn-receiver} be the exposition-only class: + +\indexlibraryglobal{execution::\exposid{spawn-receiver}}% +\begin{codeblock} +namespace std::execution { + struct @\exposid{spawn-receiver}@ { // \expos + using receiver_concept = receiver_t; + + @\exposid{spawn-state-base}@* @\exposid{state}@; // \expos + void set_value() && noexcept { @\exposid{state}@->@\exposid{complete}@(); } + void set_stopped() && noexcept { @\exposid{state}@->@\exposid{complete}@(); } + }; +} +\end{codeblock} + +\pnum +Let \exposid{spawn-state} be the exposition-only class template: + +\indexlibraryglobal{execution::\exposid{spawn-state}}% +\begin{codeblock} +namespace std::execution { + template + struct @\exposid{spawn-state}@ : @\exposid{spawn-state-base}@ { // \expos + using @\exposid{op-t}@ = connect_result_t; // \expos + + @\exposid{spawn-state}@(Alloc alloc, Sender&& sndr, Token token); // \expos + void @\exposid{complete}@() noexcept override; // \expos + void @\exposid{run}@(); // \expos + + private: + using @\exposid{alloc-t}@ = // \expos + typename allocator_traits::template rebind_alloc<@\exposid{spawn-state}@>; + + @\exposid{alloc-t}@ @\exposid{alloc}@; // \expos + @\exposid{op-t}@ @\exposid{op}@; // \expos + Token @\exposid{token}@; // \expos + + void @\exposid{destroy}@() noexcept; // \expos + }; +} +\end{codeblock} + +\indexlibraryctor{execution::\exposid{spawn-state}}% +\begin{itemdecl} +@\exposid{spawn-state}@(Alloc alloc, Sender&& sndr, Token token); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes +\exposid{alloc} with \tcode{alloc}, +\exposid{token} with \tcode{token}, and +\exposid{op} with: +\begin{codeblock} +connect(std::move(sndr), @\exposid{spawn-receiver}@(this)) +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{\exposid{run}}{execution::\exposid{spawn-state}}% +\begin{itemdecl} +void @\exposid{run}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (@\exposid{token}@.try_associate()) + start(@\exposid{op}@); +else + @\exposid{destroy}@(); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{\exposid{complete}}{execution::\exposid{spawn-state}}% +\begin{itemdecl} +void @\exposid{complete}@() noexcept override; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto token = std::move(this->@\exposid{token}@); + +@\exposid{destroy}@(); +token.disassociate(); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{\exposid{destroy}}{execution::\exposid{spawn-state}}% +\begin{itemdecl} +void @\exposid{destroy}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto alloc = std::move(this->@\exposid{alloc}@); + +allocator_traits<@\exposid{alloc-t}@>::destroy(alloc, this); +allocator_traits<@\exposid{alloc-t}@>::deallocate(alloc, this, 1); +\end{codeblock} +\end{itemdescr} + +\pnum +For the expression \tcode{spawn(sndr, token, env)} +let \tcode{new_sender} be the expression \tcode{token.wrap(sndr)} and +let \tcode{alloc} and \tcode{senv} be defined as follows: +\begin{itemize} +\item +if the expression \tcode{get_allocator(env)} is well-formed, then +\tcode{alloc} is the result of \tcode{get_allocator(env)} and +\tcode{senv} is the expression \tcode{env}, +\item +otherwise +if the expression \tcode{get_allocator(get_env(new_sender))} is well-formed, then +\tcode{alloc} is the result of \tcode{get_allocator(get_env(new_sender))} and +\tcode{senv} is the expression \tcode{\exposid{JOIN-ENV}(prop(get_allocator, alloc), env)}, +\item +otherwise +\tcode{alloc} is \tcode{allocator()} and +\tcode{senv} is the expression \tcode{env}. +\end{itemize} + +\pnum +The expression \tcode{spawn(sndr, token, env)} is of type \tcode{void} and +has the following effects: +%%FIXME: Was this supposed to be more than a single bullet? +\begin{itemize} +\item +Uses \tcode{alloc} to allocate and construct an object \tcode{o} of +type that is a specialization of \tcode{\exposid{spawn-state}} from +\tcode{alloc}, \tcode{write_env(token.wrap(sndr), senv)}, and \tcode{token} +and then +invokes \tcode{o.\exposid{run}()}. +If an exception is thrown then +any constructed objects are destroyed and any allocated memory is deallocated. +\end{itemize} + +\pnum +The expression \tcode{spawn(sndr, token)} is expression-equivalent to +\tcode{spawn(sndr, token, execution::env<>(\brk{}))}. + +\rSec1[exec.cmplsig]{Completion signatures} + +\pnum +\tcode{completion_signatures} is a type +that encodes a set of completion signatures\iref{exec.async.ops}. + +\pnum +\begin{example} +\begin{codeblock} +struct my_sender { + using sender_concept = sender_t; + using completion_signatures = + execution::completion_signatures< + set_value_t(), + set_value_t(int, float), + set_error_t(exception_ptr), + set_error_t(error_code), + set_stopped_t()>; +}; +\end{codeblock} +Declares \tcode{my_sender} to be a sender +that can complete by calling one of the following +for a receiver expression \tcode{rcvr}: +\begin{itemize} +\item \tcode{set_value(rcvr)} +\item \tcode{set_value(rcvr, int\{...\}, float\{...\})} +\item \tcode{set_error(rcvr, exception_ptr\{...\})} +\item \tcode{set_error(rcvr, error_code\{...\})} +\item \tcode{set_stopped(rcvr)} +\end{itemize} +\end{example} + +\pnum +This subclause makes use of the following exposition-only entities: +\begin{codeblock} +template + concept @\defexposconcept{completion-signature}@ = @\seebelow@; +\end{codeblock} + +\pnum +A type \tcode{Fn} satisfies \exposconcept{completion-signature} +if and only if it is a function type with one of the following forms: +\begin{itemize} +\item +\tcode{set_value_t(Vs...)}, +where \tcode{Vs} is a pack of object or reference types. +\item +\tcode{set_error_t(Err)}, +where \tcode{Err} is an object or reference type. +\item +\tcode{set_stopped_t()} +\end{itemize} + +\pnum +\begin{codeblock} +template + struct @\exposid{indirect-meta-apply}@ { + template class T, class... As> + using @\exposid{meta-apply}@ = T; // \expos + }; + +template + concept @\defexposconcept{always-true}@ = true; // \expos + +template class Tuple, + template class Variant> + using @\exposid{gather-signatures}@ = @\seebelow@; +\end{codeblock} + +\pnum +Let \tcode{Fns} be a pack of the arguments of +the \tcode{completion_signatures} specialization named by \tcode{Completions}, +let \tcode{TagFns} be a pack of the function types in \tcode{Fns} +whose return types are \tcode{Tag}, and +let $\tcode{Ts}_n$ be a pack of the function argument types +in the $n$-th type in \tcode{TagFns}. +Then, given two variadic templates \tcode{Tuple} and \tcode{Variant}, +the type \tcode{\exposid{gather-signatures}} +names the type +\begin{codeblock} +@\exposid{META-APPLY}@(Variant, @\exposid{META-APPLY}@(Tuple, Ts@$_0$@...), + @\itcorr[1]\exposid{META-APPLY}@(Tuple, Ts@$_1$@...), + @\itcorr[1]\ldots@, + @\itcorr[1]\exposid{META-APPLY}@(Tuple, Ts@$_{m-1}$@...)) +\end{codeblock} +where $m$ is the size of the pack \tcode{TagFns} and +\tcode{META-APPLY(T, As...)} is equivalent to: +\begin{codeblock} +typename @\exposid{indirect-meta-apply}@<@\exposid{always-true}@>::template @\exposid{meta-apply}@ +\end{codeblock} + +\pnum +\begin{note} +The purpose of \exposid{META-APPLY} is to make it valid +to use non-variadic templates as \tcode{Variant} and \tcode{Tuple} arguments +to \exposid{gather-signatures}. +\end{note} + +\pnum +\indexlibraryglobal{execution::completion_signatures}% +\indexlibrarymember{\exposid{for-each}}{execution::completion_signatures}% +\indexlibrarymember{\exposid{count-of}}{execution::completion_signatures}% +\begin{codeblock} +namespace std::execution { + template<@\exposconcept{completion-signature}@... Fns> + struct completion_signatures { + template + static constexpr size_t @\exposid{count-of}@(Tag) { return @\seebelow@; } + + template + static constexpr void @\exposid{for-each}@(Fn&& fn) { // \expos + (std::forward(fn)(static_cast(nullptr)), ...); + } + }; + + template, + template class Tuple = @\exposid{decayed-tuple}@, + template class Variant = @\exposid{variant-or-empty}@> + requires @\libconcept{sender_in}@ + using value_types_of_t = + @\exposid{gather-signatures}@, Tuple, Variant>; + + template, + template class Variant = @\exposid{variant-or-empty}@> + requires @\libconcept{sender_in}@ + using error_types_of_t = + @\exposid{gather-signatures}@, + type_identity_t, Variant>; + + template> + requires @\libconcept{sender_in}@ + constexpr bool sends_stopped = + !@\libconcept{same_as}@<@\exposid{type-list}@<>, + @\exposid{gather-signatures}@, + @\exposid{type-list}@, @\exposid{type-list}@>>; +} +\end{codeblock} + +\pnum +For a subexpression \tcode{tag}, +let \tcode{Tag} be the decayed type of \tcode{tag}. +\tcode{completion_signatures::\exposid{count-of}(\linebreak{}tag)} +returns the count of function types in \tcode{Fns...} that +are of the form \tcode{Tag(Ts...)} where \tcode{Ts} is a pack of types. + +\rSec1[exec.envs]{Queryable utilities} + +\rSec2[exec.prop]{Class template \tcode{prop}} + +\begin{codeblock} +namespace std::execution { + template + struct @\libglobal{prop}@ { + QueryTag @\exposid{query_}@; // \expos + ValueType @\exposid{value_}@; // \expos + + constexpr const ValueType& query(QueryTag) const noexcept { + return @\exposid{value_}@; + } + }; + + template + prop(QueryTag, ValueType) -> prop>; +} +\end{codeblock} + +\pnum +Class template \tcode{prop} is for building a queryable object +from a query object and a value. + +\pnum +\mandates +\tcode{\exposconcept{callable}>} +is modeled, +where \exposid{prop-like} is the following exposition-only class template: +\begin{codeblock} +template +struct @\exposid{prop-like}@ { // \expos + const ValueType& query(auto) const noexcept; +}; +\end{codeblock} + +\pnum +\begin{example} +\begin{codeblock} +template<@\libconcept{sender}@ Sndr> +sender auto parameterize_work(Sndr sndr) { + // Make an environment such that \tcode{get_allocator(env)} returns a reference to a copy of \tcode{my_alloc\{\}}. + auto e = prop(get_allocator, my_alloc{}); + + // Parameterize the input sender so that it will use our custom execution environment. + return write_env(sndr, e); +} +\end{codeblock} +\end{example} + +\pnum +Specializations of \tcode{prop} are not assignable. + +\rSec2[exec.env]{Class template \tcode{env}} + +\begin{codeblock} +namespace std::execution { + template<@\exposconcept{queryable}@... Envs> + struct @\libglobal{env}@ { + Envs@$_0$@ @$\exposid{envs}_0$@; // \expos + Envs@$_1$@ @$\exposid{envs}_1$@; // \expos + @\vdots@ + Envs@$_{n-1}$@ @$\exposid{envs}_{n-1}$@; // \expos + + template + constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@); + }; + + template + env(Envs...) -> env...>; +} +\end{codeblock} + +\pnum +The class template \tcode{env} is used to construct a queryable object +from several queryable objects. +Query invocations on the resulting object are resolved +by attempting to query each subobject in lexical order. + +\pnum +Specializations of \tcode{env} are not assignable. + +\pnum +It is unspecified +whether \tcode{env} supports initialization +using a parenthesized \grammarterm{expression-list}\iref{dcl.init}, +unless the \grammarterm{expression-list} consist of +a single element of type (possibly const) \tcode{env}. + +\pnum +\begin{example} +\begin{codeblock} +template<@\libconcept{sender}@ Sndr> +sender auto parameterize_work(Sndr sndr) { + // Make an environment such that: + // \tcode{get_allocator(env)} returns a reference to a copy of \tcode{my_alloc\{\}} + // \tcode{get_scheduler(env)} returns a reference to a copy of \tcode{my_sched\{\}} + auto e = env{prop(get_allocator, my_alloc{}), + prop(get_scheduler, my_sched{})}; + + // Parameterize the input sender so that it will use our custom execution environment. + return write_env(sndr, e); +} +\end{codeblock} +\end{example} + +\indexlibrarymember{query}{env}% +\begin{itemdecl} +template +constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \exposconcept{has-query} be the following exposition-only concept: +\begin{codeblock} +template + concept @\defexposconcept{has-query}@ = // \expos + requires (const Env& env) { + env.query(QueryTag()); + }; +\end{codeblock} + +\pnum +Let \exposid{fe} be the first element of +$\exposid{envs}_0$, $\exposid{envs}_1$, $\dotsc$, $\exposid{envs}_{n-1}$ +such that the expression \tcode{\exposid{fe}.query(q)} is well-formed. + +\pnum +\constraints +\tcode{(\exposconcept{has-query} || ...)} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return \exposid{fe}.query(q);} + +\pnum +\remarks +The expression in the \tcode{noexcept} clause is equivalent +to \tcode{noexcept(\exposid{fe}.query(q))}. +\end{itemdescr} + +\rSec1[exec.ctx]{Execution contexts} + +\rSec2[exec.run.loop]{\tcode{execution::run_loop}} + +\rSec3[exec.run.loop.general]{General} + +\pnum +A \tcode{run_loop} is an execution resource on which work can be scheduled. +It maintains a thread-safe first-in-first-out queue of work. +Its \tcode{run} member function removes elements from the queue and +executes them in a loop on the thread of execution that calls \tcode{run}. + +\pnum +A \tcode{run_loop} instance has an associated \defn{count} +that corresponds to the number of work items that are in its queue. +Additionally, a \tcode{run_loop} instance has an associated state +that can be one of +\defn{starting}, \defn{running}, \defn{finishing}, or \defn{finished}. + +\pnum +Concurrent invocations of the member functions of \tcode{run_loop} +other than \tcode{run} and its destructor do not introduce data races. +The member functions +\exposid{pop-front}, \exposid{push-back}, and \tcode{finish} +execute atomically. + +\pnum +\recommended +Implementations should use an intrusive queue of operation states +to hold the work units to make scheduling allocation-free. + +\begin{codeblock} +namespace std::execution { + class @\libglobal{run_loop}@ { + // \ref{exec.run.loop.types}, associated types + class @\exposid{run-loop-scheduler}@; // \expos + class @\exposid{run-loop-sender}@; // \expos + struct @\exposid{run-loop-opstate-base}@ { // \expos + virtual void @\exposid{execute}@() = 0; // \expos + run_loop* @\exposid{loop}@; // \expos + @\exposid{run-loop-opstate-base}@* @\exposid{next}@; // \expos + }; + template + using @\exposid{run-loop-opstate}@ = @\unspec@; // \expos + + // \ref{exec.run.loop.members}, member functions + @\exposid{run-loop-opstate-base}@* @\exposid{pop-front}@(); // \expos + void @\exposid{push-back}@(@\exposid{run-loop-opstate-base}@*); // \expos + + public: + // \ref{exec.run.loop.ctor}, constructor and destructor + run_loop() noexcept; + run_loop(run_loop&&) = delete; + ~run_loop(); + + // \ref{exec.run.loop.members}, member functions + @\exposid{run-loop-scheduler}@ get_scheduler(); + void run(); + void finish(); + }; +} +\end{codeblock} + +\rSec3[exec.run.loop.types]{Associated types} + +\begin{itemdecl} +class @\exposid{run-loop-scheduler}@; +\end{itemdecl} + +\pnum +\exposid{run-loop-scheduler} is an unspecified type +that models \libconcept{scheduler}. + +\pnum +Instances of \exposid{run-loop-scheduler} remain valid +until the end of the lifetime of the \tcode{run_loop} instance +from which they were obtained. + +\pnum +Two instances of \exposid{run-loop-scheduler} compare equal +if and only if they were obtained from the same \tcode{run_loop} instance. + +\pnum +Let \exposid{sch} be an expression of type \exposid{run-loop-scheduler}. +The expression \tcode{schedule(\exposid{sch})} +has type \exposid{run-loop-\newline sender} and +is not potentially-throwing if \exposid{sch} is not potentially-throwing. + +\begin{itemdecl} +class @\exposid{run-loop-sender}@; +\end{itemdecl} + +\pnum +\exposid{run-loop-sender} is an exposition-only type +that satisfies \libconcept{sender}. +\tcode{completion_signatures_of_t<\exposid{run-\linebreak{}loop-sender}>} is +\begin{codeblock} +completion_signatures +\end{codeblock} + +\pnum +An instance of \exposid{run-loop-sender} remains valid +until the end of the lifetime of its associated \tcode{run_loop} instance. + +\pnum +Let \exposid{sndr} be an expression of type \exposid{run-loop-sender}, +let \exposid{rcvr} be an expression +such that \tcode{\libconcept{receiver_of}} is \tcode{true} +where \tcode{CS} is the \tcode{completion_signatures} specialization above. +Let \tcode{C} be either \tcode{set_value_t} or \tcode{set_stopped_t}. +Then: +\begin{itemize} +\item +The expression \tcode{connect(\exposid{sndr}, \exposid{rcvr})} +has type \tcode{\exposid{run-loop-opstate}>} +and is potentially-throwing if and only if +\tcode{(void(\exposid{sndr}), auto(\exposid{rcvr}))} is potentially-throwing. +\item +The expression \tcode{get_completion_scheduler(get_env(\exposid{sndr}))} +is potentially-throwing if and only if \exposid{sndr} is potentially-throwing, +has type \exposid{run-loop-scheduler}, and +compares equal to the \exposid{run-loop-\newline scheduler} instance +from which \exposid{sndr} was obtained. +\end{itemize} + +\begin{itemdecl} +template + struct @\exposid{run-loop-opstate}@; +\end{itemdecl} + +\pnum +\tcode{\exposid{run-loop-opstate}} +inherits privately and unambiguously from \exposid{run-loop-opstate-base}. + +\pnum +Let $o$ be a non-const lvalue of type \tcode{\exposid{run-loop-opstate}}, +and let \tcode{REC($o$)} be a non-const lvalue reference to an instance of type \tcode{Rcvr} +that was initialized with the expression \exposid{rcvr} +passed to the invocation of connect that returned $o$. +Then: +\begin{itemize} +\item +The object to which \tcode{\exposid{REC}($o$)} refers +remains valid for the lifetime of the object to which $o$ refers. +\item +The type \tcode{\exposid{run-loop-opstate}} overrides +\tcode{\exposid{run-loop-opstate-base}::\exposid{execute}()} +such that \tcode{$o$.\exposid{exe\-cute}()} is equivalent to: +\begin{codeblock} +if (get_stop_token(@\exposid{REC}@(@$o$@)).stop_requested()) { + set_stopped(std::move(@\exposid{REC}@(@$o$@))); +} else { + set_value(std::move(@\exposid{REC}@(@$o$@))); +} +\end{codeblock} +\item +The expression \tcode{start($o$)} is equivalent to: +\begin{codeblock} +try { + @$o$@.@\exposid{loop}@->@\exposid{push-back}@(addressof(@$o$@)); +} catch(...) { + set_error(std::move(@\exposid{REC}@(@$o$@)), current_exception()); +} +\end{codeblock} +\end{itemize} + +\rSec3[exec.run.loop.ctor]{Constructor and destructor} + +\indexlibraryctor{run_loop}% +\begin{itemdecl} +run_loop() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\exposid{count} is \tcode{0} and \exposid{state} is \exposid{starting}. +\end{itemdescr} + +\indexlibrarydtor{run_loop}% +\begin{itemdecl} +~run_loop(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \exposid{count} is not \tcode{0} or if \exposid{state} is \exposid{running}, +invokes \tcode{terminate}\iref{except.terminate}. +Otherwise, has no effects. +\end{itemdescr} + +\rSec3[exec.run.loop.members]{Member functions} + +\begin{itemdecl} +@\exposid{run-loop-opstate-base}@* @\exposid{pop-front}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Blocks\iref{defns.block} until one of the following conditions is \tcode{true}: +\begin{itemize} +\item +\exposid{count} is \tcode{0} and \exposid{state} is \exposid{finishing}, +in which case \exposid{pop-front} sets \exposid{state} to \exposid{finished} +and returns \tcode{nullptr}; or +\item +\exposid{count} is greater than \tcode{0}, +in which case an item is removed from the front of the queue, +\exposid{count} is decremented by \tcode{1}, and +the removed item is returned. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +void @\exposid{push-back}@(@\exposid{run-loop-opstate-base}@* item); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Adds \tcode{item} to the back of the queue and +increments \exposid{count} by \tcode{1}. + +\pnum +\sync +This operation synchronizes with +the \exposid{pop-front} operation that obtains \tcode{item}. +\end{itemdescr} + +\indexlibrarymember{get_scheduler}{run_loop}% +\begin{itemdecl} +@\exposid{run-loop-scheduler}@ get_scheduler(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An instance of \exposid{run-loop-scheduler} +that can be used to schedule work onto this \tcode{run_loop} instance. +\end{itemdescr} + +\indexlibrarymember{run}{run_loop}% +\begin{itemdecl} +void run(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\exposid{state} is either \exposid{starting} or \exposid{finishing}. + +\pnum +\effects +If \exposid{state} is \exposid{starting}, +sets the \exposid{state} to \exposid{running}, +otherwise leaves \exposid{state} unchanged. +Then, equivalent to: +\begin{codeblock} +while (auto* op = @\exposid{pop-front}@()) { + op->@\exposid{execute}@(); +} +\end{codeblock} + +\pnum +\remarks +When \exposid{state} changes, it does so without introducing data races. +\end{itemdescr} + +\indexlibrarymember{finish}{run_loop}% +\begin{itemdecl} +void finish(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\exposid{state} is either \exposid{starting} or \exposid{running}. + +\pnum +\effects +Changes \exposid{state} to \exposid{finishing}. + +\pnum +\sync +\tcode{finish} synchronizes with the \exposid{pop-front} operation +that returns \tcode{nullptr}. +\end{itemdescr} + +\rSec1[exec.coro.util]{Coroutine utilities} + +\rSec2[exec.as.awaitable]{\tcode{execution::as_awaitable}} + +\pnum +\tcode{as_awaitable} transforms an object into one +that is awaitable within a particular coroutine. +Subclause \ref{exec.coro.util} makes use of +the following exposition-only entities: +\begin{codeblock} +namespace std::execution { + template + concept @\defexposconcept{awaitable-sender}@ = + @\exposconcept{single-sender}@> && + @\libconcept{sender_to}@ && // \seebelow + requires (Promise& p) { + { p.unhandled_stopped() } -> @\libconcept{convertible_to}@>; + }; + + template + concept @\defexposconcept{has-queryable-await-completion-adaptor}@ = // \expos + @\libconcept{sender}@ && + requires(Sndr&& sender) { + get_await_completion_adaptor(get_env(sender)); + }; + + template + class @\exposidnc{sender-awaitable}@; // \expos +} +\end{codeblock} + +\pnum +The type \tcode{\exposid{sender-awaitable}} is equivalent to: + +\begin{codeblock} +namespace std::execution { + template + class @\exposidnc{sender-awaitable}@ { + struct @\exposidnc{unit}@ {}; // \expos + using @\exposidnc{value-type}@ = // \expos + @\exposidnc{single-sender-value-type}@>; + using @\exposidnc{result-type }@= // \expos + conditional_t, unit, @\exposid{value-type}@>; + struct @\exposidnc{awaitable-receiver}@; // \expos + + variant @\exposidnc{result}@{}; // \expos + connect_result_t @\exposidnc{state}@; // \expos + + public: + @\exposid{sender-awaitable}@(Sndr&& sndr, Promise& p); + static constexpr bool await_ready() noexcept { return false; } + void await_suspend(coroutine_handle) noexcept { start(@\exposid{state}@); } + @\exposid{value-type}@ await_resume(); + }; +} +\end{codeblock} + +\pnum +\exposid{awaitable-receiver} is equivalent to: +\begin{codeblock} +struct @\exposid{awaitable-receiver}@ { + using receiver_concept = receiver_t; + variant* @\exposidnc{result-ptr}@; // \expos + coroutine_handle @\exposidnc{continuation}@; // \expos + // \seebelow +}; +\end{codeblock} + +\pnum +Let \tcode{rcvr} be an rvalue expression of type \exposid{awaitable-receiver}, +let \tcode{crcvr} be a const lvalue that refers to \tcode{rcvr}, +let \tcode{vs} be a pack of subexpressions, and +let \tcode{err} be an expression of type \tcode{Err}. Then: +\begin{itemize} +\item +If \tcode{\libconcept{constructible_from}<\exposid{result-type}, decltype((vs))...>} +is satisfied, +the expression \tcode{set_value(\newline rcvr, vs...)} is equivalent to: +\begin{codeblock} +try { + rcvr.@\exposid{result-ptr}@->template emplace<1>(vs...); +} catch(...) { + rcvr.@\exposid{result-ptr}@->template emplace<2>(current_exception()); +} +rcvr.@\exposid{continuation}@.resume(); +\end{codeblock} +Otherwise, \tcode{set_value(rcvr, vs...)} is ill-formed. +\item +The expression \tcode{set_error(rcvr, err)} is equivalent to: +\begin{codeblock} +rcvr.@\exposid{result-ptr}@->template emplace<2>(@\exposid{AS-EXCEPT-PTR}@(err)); // see \ref{exec.general} +rcvr.@\exposid{continuation}@.resume(); +\end{codeblock} +\item +The expression \tcode{set_stopped(rcvr)} is equivalent to: +\begin{codeblock} +static_cast>(rcvr.@\exposid{continuation}@.promise().unhandled_stopped()).resume(); +\end{codeblock} +\item +For any expression \tcode{tag} +whose type satisfies \exposconcept{forwarding-query} and +for any pack of subexpressions \tcode{as}, +\tcode{get_env(crcvr).query(tag, as...)} is expression-equivalent to: +\begin{codeblock} +tag(get_env(as_const(crcvr.@\exposid{continuation}@.promise())), as...) +\end{codeblock} +\end{itemize} + +\begin{itemdecl} +@\exposid{sender-awaitable}@(Sndr&& sndr, Promise& p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{state} with +\begin{codeblock} +connect(std::forward(sndr), + @\exposid{awaitable-receiver}@{addressof(result), coroutine_handle::from_promise(p)}) +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +@\exposid{value-type}@ await_resume(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (@\exposid{result}@.index() == 2) + rethrow_exception(get<2>(@\exposid{result}@)); +if constexpr (!is_void_v<@\exposid{value-type}@>) + return std::forward<@\exposid{value-type}@>(get<1>(@\exposid{result}@)); +\end{codeblock} +\end{itemdescr} + +\pnum +\tcode{as_awaitable} is a customization point object. +For subexpressions \tcode{expr} and \tcode{p} +where \tcode{p} is an lvalue, +\tcode{Expr} names the type \tcode{decltype((expr))} and +\tcode{Promise} names the type \tcode{decay_t}, +\tcode{as_awaitable(expr, p)} is expression-equivalent to, +except that the evaluations of \tcode{expr} and \tcode{p} +are indeterminately sequenced: +\begin{itemize} +\item +\tcode{expr.as_awaitable(p)} if that expression is well-formed. + +\mandates +\tcode{\exposconcept{is-awaitable}} is \tcode{true}, +where \tcode{A} is the type of the expression above. +\item +Otherwise, \tcode{(void(p), expr)} +if \tcode{\exposconcept{is-awaitable}} is \tcode{true}, +where \tcode{U} is an unspecified class type +that is not \tcode{Promise} and +that lacks a member named \tcode{await_transform}. + +\expects +\tcode{\exposconcept{is-awaitable}} is \tcode{true} and +the expression \tcode{co_await expr} +in a coroutine with promise type \tcode{U} is expression-equivalent to +the same expression in a coroutine with promise type \tcode{Promise}. +\item +Otherwise, \tcode{\exposid{sender-awaitable}\{\exposid{adapted-expr}, p\}} +if +\begin{codeblock} +@\exposid{has-queryable-await-completion-adaptor}@ +\end{codeblock} +and +\begin{codeblock} +@\exposid{awaitable-sender}@ +\end{codeblock} +are both satisfied, where \exposid{adapted-expr} is +\tcode{get_await_completion_adaptor(get_env(expr))(expr)}, +except that \tcode{expr} is evaluated only once. +\item +Otherwise, \tcode{\exposid{sender-awaitable}\{expr, p\}} +if \tcode{\exposconcept{awaitable-sender}} is \tcode{true}. +\item +Otherwise, \tcode{(void(p), expr)}. +\end{itemize} + +\rSec2[exec.with.awaitable.senders]{\tcode{execution::with_awaitable_senders}} + +\pnum +\tcode{with_awaitable_senders}, +when used as the base class of a coroutine promise type, +makes senders awaitable in that coroutine type. + +In addition, it provides a default implementation of \tcode{unhandled_stopped} +such that if a sender completes by calling \tcode{set_stopped}, +it is treated as if an uncatchable "stopped" exception were thrown +from the \grammarterm{await-expression}. +\begin{note} +The coroutine is never resumed, and +the \tcode{unhandled_stopped} of the coroutine caller's promise type is called. +\end{note} + +\begin{codeblock} +namespace std::execution { + template<@\exposconcept{class-type}@ Promise> + struct @\libglobal{with_awaitable_senders}@ { + template + requires (!@\libconcept{same_as}@) + void set_continuation(coroutine_handle h) noexcept; + + coroutine_handle<> @\libmember{continuation}{with_awaitable_senders}@() const noexcept { return @\exposid{continuation}@; } + + coroutine_handle<> @\libmember{unhandled_stopped}{with_awaitable_senders}@() noexcept { + return @\exposid{stopped-handler}@(@\exposid{continuation}@.address()); + } + + template + @\seebelow@ await_transform(Value&& value); + + private: + [[noreturn]] static coroutine_handle<> + @\exposid{default-unhandled-stopped}@(void*) noexcept { // \expos + terminate(); + } + coroutine_handle<> @\exposid{continuation}@{}; // \expos + coroutine_handle<> (*@\exposid{stopped-handler}@)(void*) noexcept = // \expos + &@\exposid{default-unhandled-stopped}@; + }; +} +\end{codeblock} + +\indexlibrarymember{set_continuation}{with_awaitable_senders}% +\begin{itemdecl} +template + requires (!@\libconcept{same_as}@) +void set_continuation(coroutine_handle h) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{continuation}@ = h; +if constexpr ( requires(OtherPromise& other) { other.unhandled_stopped(); } ) { + @\exposid{stopped-handler}@ = [](void* p) noexcept -> coroutine_handle<> { + return coroutine_handle::from_address(p) + .promise().unhandled_stopped(); + }; +} else { + @\exposid{stopped-handler}@ = &@\exposid{default-unhandled-stopped}@; +} +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{await_transform}{with_awaitable_senders}% +\begin{itemdecl} +template +@\exposid{call-result-t}@ await_transform(Value&& value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return as_awaitable(std::forward(value), static_cast(*this)); +\end{codeblock} +\end{itemdescr} + +\rSec2[exec.affine.on]{\tcode{execution::affine_on}} + +\pnum +\tcode{affine_on} adapts a sender into one that completes on +the specified scheduler. +If the algorithm determines that the adapted sender already completes +on the correct scheduler it can avoid any scheduling operation. + +\pnum +The name \tcode{affine_on} denotes a pipeable sender adaptor +object. +For subexpressions \tcode{sch} and \tcode{sndr}, if \tcode{decltype((sch))} +does not satisfy \libconcept{scheduler}, or \tcode{decltype((sndr))} +does not satisfy \libconcept{sender}, \tcode{affine_on(sndr, sch)} +is ill-formed. + +\pnum +Otherwise, the expression \tcode{affine_on(sndr, sch)} is +expression-equivalent to: +\begin{codeblock} +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(affine_on, sch, sndr)) +\end{codeblock} +except that \tcode{sndr} is evaluated only once. + +\pnum +The exposition-only class template \exposid{impls-for} +is specialized for \tcode{affine_on_t} as follows: + +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@ : @\exposid{default-impls}@ { + static constexpr auto @\exposid{get-attrs}@ = + [](const auto& data, const auto& child) noexcept -> decltype(auto) { + return @\exposid{JOIN-ENV}@(@\exposid{SCHED-ATTRS}@(data), @\exposid{FWD-ENV}@(get_env(child))); + }; + }; +} +\end{codeblock} + +\pnum +Let \tcode{\placeholder{out_sndr}} be a subexpression denoting a sender +returned from \tcode{affine_on(sndr, sch)} or one equal to such, +and let \tcode{\placeholder{OutSndr}} be the type \tcode{decltype((\placeholder{out_sndr}))}. +Let \tcode{\placeholder{out_rcvr}} be a subexpression denoting a receiver that +has an environment of type \tcode{Env} such that \tcode{\libconcept{sender_in}<\placeholder{OutSndr}, Env>} +is \tcode{true}. +Let \tcode{\placeholder{op}} be an lvalue referring to the operation state that +results from connecting \tcode{\placeholder{out_sndr}} to \tcode{\placeholder{out_rcvr}}. +Calling \tcode{start(\placeholder{op})} will start \tcode{sndr} on the current +execution agent and execute completion operations on \tcode{\placeholder{out_rcvr}} +on an execution agent of the execution resource associated with +\tcode{sch}. +If the current execution resource is the same as the execution +resource associated with \tcode{sch}, the completion operation on +\tcode{\placeholder{out_rcvr}} may be called before \tcode{start(\placeholder{op})} completes. +If scheduling onto \tcode{sch} fails, an error completion on +\tcode{\placeholder{out_rcvr}} shall be executed on an unspecified execution +agent. + +\rSec2[exec.inline.scheduler]{\tcode{execution::inline_scheduler}} + +\begin{codeblock} +namespace std::execution { + class @\libglobal{inline_scheduler}@ { + class @\exposidnc{inline-sender}@; // \expos + + template<@\libconcept{receiver}@ R> + class @\exposidnc{inline-state}@; // \expos + + public: + using scheduler_concept = scheduler_t; + + constexpr @\exposid{inline-sender}@ schedule() noexcept { return {}; } + constexpr bool operator==(const inline_scheduler&) const noexcept = default; + }; +} +\end{codeblock} + +\pnum +\tcode{inline_scheduler} is a class that models +\libconcept{scheduler}\iref{exec.sched}. +All objects of type \tcode{inline_scheduler} are equal. + +\pnum +\exposid{inline-sender} is an exposition-only type that satisfies +\libconcept{sender}. +The type \tcode{completion_signatures_of_t<\exposid{inline-sender}>} +is \tcode{completion_signatures}. + +\pnum +Let \tcode{sndr} be an expression of type \exposid{inline-sender}, +let \tcode{rcvr} be an expression such that +\tcode{\libconcept{receiver_of}} is \tcode{true} +where \tcode{CS} is \tcode{completion_signatures}, +then: +\begin{itemize} +\item the expression \tcode{connect(sndr, rcvr)} has +type \tcode{\exposid{inline-state}>} +and is potentially-throwing if and only if +\tcode{((void)sndr, auto(rcvr))} is potentially-throwing, and +\item the expression +\tcode{get_completion_scheduler(get_env(sndr))} has +type\brk{} \tcode{inline_\-sched\-ul\-er} and is potentially-throwing +if and only if \tcode{get_env(sndr)} is potentially-throwing. +\end{itemize} + +\pnum +Let \tcode{\placeholder{o}} be a non-\tcode{const} lvalue of type +\tcode{\exposid{inline-state}}, and let \tcode{REC(\placeholder{o})} be +a non-\tcode{const} lvalue reference to an object of type \tcode{Rcvr} that +was initialized with the expression \tcode{rcvr} passed to an +invocation of \tcode{connect} that returned \tcode{\placeholder{o}}, then: +\begin{itemize} +\item the object to which \tcode{REC(\placeholder{o})} refers remains valid for +the lifetime of the object to which \tcode{\placeholder{o}} refers, and +\item the expression \tcode{start(\placeholder{o})} is equivalent to +\tcode{set_value(std::move(REC(\placeholder{o})))}. +\end{itemize} + +\rSec2[exec.task.scheduler]{\tcode{execution::task_scheduler}} + +\begin{codeblock} +namespace std::execution { + class @\libglobal{task_scheduler}@ { + class @\exposidnc{ts-sender}@; // \expos + + template<@\libconcept{receiver}@ R> + class @\exposidnc{state}@; // \expos + + public: + using scheduler_concept = scheduler_t; + + template> + requires (!@\libconcept{same_as}@>) + && @\libconcept{scheduler}@ + explicit task_scheduler(Sch&& sch, Allocator alloc = {}); + + @\exposid{ts-sender}@ schedule(); + + friend bool operator==(const task_scheduler& lhs, const task_scheduler& rhs) + noexcept; + template + requires (!@\libconcept{same_as}@) + && @\libconcept{scheduler}@ + friend bool operator==(const task_scheduler& lhs, const Sch& rhs) noexcept; + + private: + shared_ptr @\exposidnc{sch_}@; // \expos + }; +} +\end{codeblock} + +\pnum +\tcode{task_scheduler} is a class that models +\libconcept{scheduler}\iref{exec.sched}. +Given an object \tcode{s} of type \tcode{task_scheduler}, let +\tcode{\exposid{SCHED}(s)} be the object owned by \tcode{s.\exposid{sch_}}. + +\indexlibraryctor{task_scheduler} +\begin{itemdecl} +template> + requires(!@\libconcept{same_as}@>) && @\libconcept{scheduler}@ +explicit task_scheduler(Sch&& sch, Allocator alloc = {}); +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Initialize \exposid{sch_} with +\tcode{allocate_shared>(alloc,\brk{} std::forward\brk{}(sch))}. + +\pnum +\recommended +Implementations should avoid the use of dynamically +allocated memory for small scheduler objects. + +\pnum +\remarks +Any allocations performed by construction of \exposid{ts-sender} or +\exposid{state} objects resulting from calls on \tcode{*this} are +performed using a copy of \tcode{alloc}. +\end{itemdescr} + +\indexlibrarymember{scheduler}{task_scheduler}% +\begin{itemdecl} +@\exposid{ts-sender}@ schedule(); +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Returns an object of type \exposid{ts-sender} containing a sender +initialized with \tcode{sched\-ule(\brk{}\exposid{SCHED}\brk{}(*this))}. +\end{itemdescr} + +\indexlibrarymember{operator==}{task_scheduler}% +\begin{itemdecl} +bool operator==(const task_scheduler& lhs, const task_scheduler& rhs) noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return lhs == \exposid{SCHED}(rhs);} +\end{itemdescr} + +\indexlibrarymember{operator==}{task_scheduler}% +\begin{itemdecl} +template + requires (!@\libconcept{same_as}@) + && @\libconcept{scheduler}@ +bool operator==(const task_scheduler& lhs, const Sch& rhs) noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\returns +\tcode{false} if type of \tcode{\exposid{SCHED}(lhs)} is not \tcode{Sch}, +otherwise \tcode{\exposid{SCHED}(lhs) == rhs;} +\end{itemdescr} + +\pnum +\begin{codeblock} +namespace std::execution { + class task_scheduler::@\exposidnc{ts-sender}@ { // \expos + public: + using sender_concept = sender_t; + + template<@\libconcept{receiver}@ Rcvr> + @\exposid{state}@ connect(Rcvr&& rcvr); + }; +} +\end{codeblock} +\exposid{ts-sender} is an exposition-only class that models +\libconcept{sender}\iref{exec.snd} and for which +\tcode{completion_signatures_of_t<\exposid{ts-sender}>} denotes: +\begin{codeblock} +completion_signatures< + set_value_t(), + set_error_t(error_code), + set_error_t(exception_ptr), + set_stopped_t()> +\end{codeblock} + +\pnum +Let \tcode{\placeholder{sch}} be an object of type \tcode{task_scheduler} +and let \tcode{sndr} be an object of type \exposid{ts-sender} obtained +from \tcode{schedule(\placeholder{sch})}. +Then \tcode{get_completion_scheduler(get_env(sndr)) == \placeholder{sch}} +is \tcode{true}. +The object \tcode{\exposid{SENDER}(sndr)} is the sender object contained by +\tcode{sndr} or an object move constructed from it. + +\indexlibrarymember{connect}{task_scheduler::\exposid{ts-sender}}% +\begin{itemdecl} +template<@\libconcept{receiver}@ Rcvr> + @\exposid{state}@ connect(Rcvr&& rcvr); +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Let \tcode{\placeholder{r}} be an object of a type that models \libconcept{receiver} +and whose completion handlers result in invoking the corresponding +completion handlers of \tcode{rcvr} or copy thereof. +Returns an object of type \tcode{\exposid{state}} containing +an operation state object initialized with \tcode{connect(\exposid{SENDER}(*this), +std::move(\placeholder{r}))}. +\end{itemdescr} + +\pnum +\begin{codeblock} +namespace std::execution { + template<@\libconcept{receiver}@ R> + class task_scheduler::@\exposidnc{state}@ { // \expos + public: + using operation_state_concept = operation_state_t; + + void start() & noexcept; + }; +} +\end{codeblock} +\exposid{state} is an exposition-only class template whose +specializations model \libconcept{operation_state}\iref{exec.opstate}. + +\indexlibrarymember{start}{task_scheduler::\exposid{state}}% +\begin{itemdecl} +void start() & noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{start(st)} where \tcode{st} is the operation +state object contained by \tcode{*this}. +\end{itemdescr} + +\rSec2[exec.task]{\tcode{execution::task}} + +\rSec3[task.overview]{\tcode{task} overview} + +\pnum +The \tcode{task} class template represents a sender that can +be used as the return type of coroutines. +The first template parameter \tcode{T} defines the type of the value +completion datum\iref{exec.async.ops} if \tcode{T} is not \tcode{void}. +Otherwise, there are no value completion datums. +Inside coroutines returning \tcode{task} the operand of +\tcode{co_return} (if any) becomes the argument of \tcode{set_value}. +The second template parameter \tcode{Environment} is used to customize +the behavior of \tcode{task}. + +\rSec3[task.class]{Class template \tcode{task}} + +\begin{codeblock} +namespace std::execution { + template + class @\libglobal{task}@ { + // \ref{task.state} + template<@\libconcept{receiver}@ Rcvr> + class @\exposidnc{state}@; // \expos + + public: + using sender_concept = sender_t; + using completion_signatures = @\seebelow@; + using allocator_type = @\seebelow@; + using scheduler_type = @\seebelow@; + using stop_source_type = @\seebelow@; + using stop_token_type = decltype(declval().get_token()); + using error_types = @\seebelow@; + + // \ref{task.promise} + class promise_type; + + task(task&&) noexcept; + ~task(); + + template<@\libconcept{receiver}@ Rcvr> + @\exposid{state}@ connect(Rcvr&& rcvr); + + private: + coroutine_handle @\exposidnc{handle}@; // \expos + }; +} +\end{codeblock} + +\pnum +\tcode{task} models \libconcept{sender}\iref{exec.snd} +if \tcode{T} is \tcode{void}, a reference type, or a \cv{}-unqualified +non-array object type and \tcode{E} is a class type. +Otherwise a program that instantiates the definition of \tcode{task} +is ill-formed. + +\pnum +The nested types of \tcode{task} template specializations +are determined based on the \tcode{Environment} parameter: +\begin{itemize} +\item \tcode{allocator_type} is \tcode{Environment::allocator_type} +if that \grammarterm{qualified-id} is valid and denotes a type, +\tcode{allocator} otherwise. +\item \tcode{scheduler_type} is \tcode{Environment::scheduler_type} +if that \grammarterm{qualified-id} is valid and denotes a type, +\tcode{task_scheduler} otherwise. +\item \tcode{stop_source_type} is \tcode{Environment::stop_source_type} +if that \grammarterm{qualified-id} is valid and denotes a type, +\tcode{inplace_stop_source} otherwise. +\item \tcode{error_types} is \tcode{Environment::error_types} if +that \grammarterm{qualified-id} is valid and denotes a type, +\tcode{com\-pletion_sign\-atures} otherwise. +\end{itemize} + +\pnum + A program is ill-formed if \tcode{error_types} is not a +specialization of \tcode{completion_signatures} or +\tcode{ErrorSigs} contains an element which is not of the form +\tcode{set_error_t(E)} for some type \tcode{E}. + +\pnum +The type alias \tcode{completion_signatures} is a specialization +of \tcode{execution::completion_signatures} with the template +arguments (in unspecified order): +\begin{itemize} +\item \tcode{set_value_t()} if \tcode{T} is \tcode{void}, +and \tcode{set_value_t(T)} otherwise; +\item template arguments of the specialization of +\tcode{execution::completion_signatures} denoted by \tcode{error_types}; +and +\item \tcode{set_stopped_t()}. +\end{itemize} + +\pnum +\tcode{allocator_type} shall meet the \oldconcept{Allocator} +requirements. + +\rSec3[task.members]{\tcode{task} members} + +\indexlibraryctor{task}% +\begin{itemdecl} +task(task&& other) noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{handle} with \tcode{exchange(other.\exposid{handle}, +\{\})}. +\end{itemdescr} + +\indexlibrarydtor{task}% +\begin{itemdecl} +~task(); +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (@\exposid{handle}@) + @\exposid{handle}@.destroy(); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{connect}{task}% +\begin{itemdecl} +template<@\libconcept{receiver}@ Rcvr> + @\exposid{state}@ connect(Rcvr&& recv); +\end{itemdecl} +\begin{itemdescr} +\pnum +\expects +\tcode{bool(\exposid{handle})} is \tcode{true}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{state}@(exchange(@\exposid{handle}@, {}), std::forward(recv)); +\end{codeblock} +\end{itemdescr} + +\rSec3[task.state]{\tcode{Class template \tcode{task::state}}} + +\begin{codeblock} +namespace std::execution { + template + template<@\libconcept{receiver}@ Rcvr> + class task::@\exposidnc{state}@ { // \expos + public: + using operation_state_concept = operation_state_t; + + template + @\exposid{state}@(coroutine_handle h, R&& rr); + + ~@\exposid{state}@(); + + void start() & noexcept; + + private: + using @\exposidnc{own-env-t}@ = @\seebelownc@; // \expos + coroutine_handle @\exposidnc{handle}@; // \expos + remove_cvref_t @\exposidnc{rcvr}@; // \expos + @\exposidnc{own-env-t}@ @\exposidnc{own-env}@; // \expos + Environment @\exposidnc{environment}@; // \expos + }; +} +\end{codeblock} + +\pnum +The type \exposid{own-env-t} is \tcode{Environment::template +env_type(\brk{})))\brk{}>} if that +\grammarterm{qualified-id} is valid and denotes a type, \tcode{env<>} otherwise. + +\indexlibraryctor{task::\exposid{state}}% +\begin{itemdecl} +template + @\exposid{state}@(coroutine_handle h, R&& rr); +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Initializes +\begin{itemize} +\item \exposid{handle} with \tcode{std::move(h)}; +\item \exposid{rcvr} with \tcode{std::forward(rr)}; +\item \exposid{own-env} +with \tcode{\exposid{own-env-t}(get_env(\exposid{rcvr}))} if that expression +is valid and \tcode{\exposid{own-env-t}()} otherwise. +If neither of these expressions is valid, the program is ill-formed. +\item \exposid{environment} with +\tcode{Environment(\exposid{own-env})} if that expression is +valid, otherwise \tcode{Environment(\brk{}get_env(\exposid{rcvr}))} +if this expression is valid, otherwise \tcode{Environment()}. +If neither of these expressions is valid, the program is ill-formed. +\end{itemize} +\end{itemdescr} + +\indexlibrarydtor{task::\exposid{state}}% +\begin{itemdecl} +~@\exposid{state}@(); +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (@\exposid{handle}@) + @\exposid{handle}@.destroy(); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{start}{task::\exposid{state}}% +\begin{itemdecl} +void start() & noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Let \tcode{\placeholder{prom}} be the object \tcode{\exposid{handle}.promise()}. +Associates \tcode{\exposid{STATE}(\placeholder{prom})}, \tcode{\exposid{RCVR}(\placeholder{prom})}, and \tcode{\exposid{SCHED}(\placeholder{prom})} +with \tcode{*this} as follows: +\begin{itemize} +\item \tcode{\exposid{STATE}(\placeholder{prom})} is \tcode{*this}. +\item \tcode{\exposid{RCVR}(\placeholder{prom})} is \exposid{rcvr}. +\item \tcode{\exposid{SCHED}(\placeholder{prom})} is the object initialized +with \tcode{scheduler_type(get_scheduler(get_env(\exposid{rcvr})))} +if that expression is valid and \tcode{scheduler_type()} otherwise. +If neither of these expressions is valid, the program is ill-formed. +\end{itemize} +Let \tcode{\placeholder{st}} be \tcode{get_stop_token(get_env(\exposid{rcvr}))}. +Initializes \tcode{\placeholder{prom}.\exposid{token}} and +\tcode{\placeholder{prom}.\exposid{source}} such that +\begin{itemize} +\item +\tcode{\placeholder{prom}.\exposid{token}.stop_requested()} returns +\tcode{\placeholder{st}.stop_requested()}; +\item +\tcode{\placeholder{prom}.\exposid{token}.stop_possible()} returns +\tcode{\placeholder{st}.stop_possible()}; and +\item +for types \tcode{Fn} and \tcode{Init} such that both +\tcode{\libconcept{invocable}} and +\tcode{\libconcept{constructible_from}} are modeled, +\tcode{stop_token_type::callback_type} models +\tcode{\exposconcept{stoppable-callback-for}}. +\end{itemize} +After that invokes \tcode{\exposid{handle}.resume()}. +\end{itemdescr} + +\rSec3[task.promise]{Class \tcode{task::promise_type}} + +\begin{codeblock} +namespace std::execution { + template + class task::promise_type { + public: + template + promise_type(const Args&... args); + + task get_return_object() noexcept; + + auto initial_suspend() noexcept; + auto final_suspend() noexcept; + + void uncaught_exception(); + coroutine_handle<> unhandled_stopped(); + + void return_void(); // present only if \tcode{is_void_v} is \tcode{true}; + template + void return_value(V&& value); // present only if \tcode{is_void_v} is \tcode{false}; + + template + @\unspec@ yield_value(with_error error); + + template + auto await_transform(A&& a); + template + auto await_transform(change_coroutine_scheduler sch); + + @\unspec@ get_env() const noexcept; + + template + void* operator new(size_t size, Args&&... args); + + void operator delete(void* pointer, size_t size) noexcept; + + private: + using @\exposidnc{error-variant}@ = @\seebelownc@; // \expos + + allocator_type @\exposidnc{alloc}@; // \expos + stop_source_type @\exposidnc{source}@; // \expos + stop_token_type @\exposidnc{token}@; // \expos + optional @\exposidnc{result}@; // \expos; present only if \tcode{is_void_v} is \tcode{false}; + @\exposidnc{error-variant}@ @\exposidnc{errors}@; // \expos + }; +} +\end{codeblock} + +\pnum +Let \tcode{\placeholder{prom}} be an object of \tcode{promise_type} +and let \tcode{\placeholder{tsk}} be the \tcode{task} object +created by \tcode{\placeholder{prom}.get_return_object()}. +The description below +refers to objects \tcode{\exposid{STATE}(\placeholder{prom})}, +\tcode{\exposid{RCVR}(\placeholder{prom})}, +and \tcode{\exposid{SCHED}(\placeholder{prom})} +associated with \tcode{\placeholder{tsk}} +during evaluation of \tcode{task::\exposid{state}::start} +for some receiver \tcode{Rcvr}. + +\pnum +\exposid{error-variant} is a \tcode{variant...>}, with duplicate types removed, where \tcode{E...} +are template arguments of the specialization of +\tcode{execution::completion_signatures} denoted by +\tcode{error_types}. + +\indexlibraryctor{task::promise_type}% +\begin{itemdecl} +template + promise_type(const Args&... args); +\end{itemdecl} +\begin{itemdescr} +\pnum +\mandates +The first parameter of type \tcode{allocator_arg_t} (if any) is not +the last parameter. + +\pnum +\effects +If \tcode{Args} contains an element of type \tcode{allocator_arg_t} +then \exposid{alloc} is initialized with the corresponding next +element of \tcode{args}. +Otherwise, \exposid{alloc} is initialized with \tcode{allocator_type()}. +\end{itemdescr} + +\indexlibrarymember{get_return_object}{task::promise_type}% +\begin{itemdecl} +task get_return_object() noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\returns +A \tcode{task} object whose member \exposid{handle} is +\tcode{coroutine_handle::\brk{}from_promise\brk{}(*this)}. +\end{itemdescr} + +\indexlibrarymember{initial_suspend}{task::promise_type}% +\begin{itemdecl} +auto initial_suspend() noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\returns +An awaitable object of unspecified type\iref{expr.await} whose +member functions arrange for +\begin{itemize} +\item the calling coroutine to be suspended, +\item the coroutine to be resumed on an execution agent of the +execution resource associated with \tcode{\exposid{SCHED}(*this)}. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{final_suspend}{task::promise_type}% +\begin{itemdecl} +auto final_suspend() noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\returns +An awaitable object of unspecified type\iref{expr.await} whose +member functions arrange for the completion of the asynchronous +operation associated with \tcode{\exposid{STATE}(*this)} by invoking: +\begin{itemize} +\item +\tcode{set_error(std::move(\exposid{RCVR}(*this)), std::move(e))} +if \tcode{\exposid{errors}.index()} is greater than zero and +\tcode{e} is the value held by \exposid{errors}, otherwise +\item +\tcode{set_value(std::move(\exposid{RCVR}(*this)))} if \tcode{is_void} is \tcode{true}, +and otherwise +\item + \tcode{set_value(std::move(\exposid{RCVR}(*this)), *\exposid{result})}. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{yield_value}{task::promise_type}% +\begin{itemdecl} +template + auto yield_value(with_error err); +\end{itemdecl} +\begin{itemdescr} +\pnum +\mandates +\tcode{std::move(err.error)} is convertible to exactly one of the +\tcode{set_error_t} argument types of \tcode{error_types}. +Let \tcode{\placeholder{Cerr}} be that type. + +\pnum +\returns +An awaitable object of unspecified type\iref{expr.await} whose +member functions arrange for the calling coroutine to be suspended +and then completes the asynchronous operation associated with +\tcode{\exposid{STATE}(*this)} by invoking \tcode{set_error(std::move(\exposid{RCVR}(*this)), +\placeholder{Cerr}(std::move(err.error)))}. +\end{itemdescr} + +\indexlibrarymember{await_transform}{task::promise_type}% +\begin{itemdecl} +template<@\libconcept{sender}@ Sender> + auto await_transform(Sender&& sndr) noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\returns +If \tcode{\libconcept{same_as}} is \tcode{true} +returns \tcode{as_awaitable(\brk{}std::\brk{}for\-ward(sndr), *this)}; +otherwise returns +\tcode{as_awaitable(affine_on(\brk{}std::\brk{}for\-ward(sndr), \exposid{SCHED}(*this)), *this)}. +\end{itemdescr} + +\indexlibrarymember{await_transform}{task::promise_type}% +\begin{itemdecl} +template + auto await_transform(change_coroutine_scheduler sch) noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return await_transform(just(exchange(@\exposid{SCHED}@(*this), scheduler_type(sch.scheduler))), *this); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{uncaught_exception}{task::promise_type}% +\begin{itemdecl} +void uncaught_exception(); +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +If the signature \tcode{set_error_t(exception_ptr)} is not an element +of \tcode{error_types}, calls \tcode{terminate()}\iref{except.terminate}. +Otherwise, stores \tcode{current_exception()} into \exposid{errors}. +\end{itemdescr} + +\indexlibrarymember{unhandled_stopped}{task::promise_type}% +\begin{itemdecl} +coroutine_handle<> unhandled_stopped(); +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Completes the asynchronous operation associated with \tcode{\exposid{STATE}(*this)} +by invoking \tcode{set_stopped(std::move(\exposid{RCVR}(*this)))}. +\end{itemdescr} +\begin{itemdescr} +\pnum +\returns +\tcode{noop_coroutine()}. +\end{itemdescr} + +\indexlibrarymember{get_env}{task::promise_type}% +\begin{itemdecl} +@\unspec@ get_env() const noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\returns +An object \tcode{env} such that queries are forwarded as follows: +\begin{itemize} +\item \tcode{env.query(get_scheduler)} returns \tcode{scheduler_type(\exposid{SCHED}(*this))}. +\item \tcode{env.query(get_allocator)} returns \exposid{alloc}. +\item \tcode{env.query(get_stop_token)} returns \exposid{token}. +\item For any other query \tcode{q} and arguments \tcode{a...} a +call to \tcode{env.query(q, a...)} returns +\tcode{\exposid{STATE}(*this)}. \tcode{environment.query(q, a...)} if this expression +is well-formed and \tcode{forwarding_query(q)} is well-formed and is \tcode{true}. +Otherwise \tcode{env.query(q, a...)} is ill-formed. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{operator new}{task::promise_type}% +\begin{itemdecl} +template + void* operator new(size_t size, const Args&... args); +\end{itemdecl} +\begin{itemdescr} +\pnum +If there is no parameter with type \tcode{allocator_arg_t} then let +\tcode{alloc} be \tcode{allocator_type()}. +Otherwise, let \tcode{arg_next} be the parameter +following the first \tcode{allocator_arg_t} parameter, +and let \tcode{alloc} be \tcode{allocator_type(arg_next)}. +Let \tcode{PAlloc} be \tcode{allocator_traits::template +rebind_alloc}, where \tcode{U} is an unspecified type +whose size and alignment are both \mname{STDCPP_DEFAULT_NEW_ALIGNMENT}. + +\pnum +\mandates +\begin{itemize} +\item The first parameter of type \tcode{allocator_arg_t} (if any) is not the last parameter. +\item \tcode{allocator_type(arg_next)} is a valid expression if there is a parameter +of type \tcode{allocator_arg_t}. +\item \tcode{allocator_traits::pointer} is a pointer type. +\end{itemize} + +\pnum +\effects +Initializes an allocator \tcode{palloc} of type \tcode{PAlloc} with +\tcode{alloc}. +Uses \tcode{palloc} to allocate storage for the +smallest array of \tcode{U} sufficient to provide storage for a +coroutine state of size \tcode{size}, and unspecified additional +state necessary to ensure that \tcode{operator delete} can later +deallocate this memory block with an allocator equal to \tcode{palloc}. + +\pnum +\returns +A pointer to the allocated storage. +\end{itemdescr} + +\indexlibrarymember{operator delete}{task::promise_type}% +\begin{itemdecl} +void operator delete(void* pointer, size_t size) noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\expects +\tcode{pointer} was returned from an invocation of the above overload +of \tcode{operator new} with a size argument equal to \tcode{size}. + +\pnum +\effects +Deallocates the storage pointed to by \tcode{pointer} using an +allocator equal to that used to allocate it. +\end{itemdescr} + +\rSec1[exec.scope]{Execution scope utilities} + +\rSec2[exec.scope.concepts]{Execution scope concepts} + +\pnum +The \libconcept{scope_token} concept defines the requirements on +a type \tcode{Token} that can be used to create associations +between senders and an async scope. + +\pnum +Let \placeholder{test-sender} and \placeholder{test-env} +be unspecified types such that +\tcode{\libconcept{sender_in}<\placeholder{test-sender}, \placeholder{test-env}>} +is modeled. + +\begin{codeblock} +namespace std::execution { + template + concept @\deflibconcept{scope_token}@ = + @\libconcept{copyable}@ && + requires(const Token token) { + { token.try_associate() } -> @\libconcept{same_as}@; + { token.disassociate() } noexcept -> @\libconcept{same_as}@; + { token.wrap(declval<@\placeholder{test-sender}@>()) } -> @\libconcept{sender_in}@<@\placeholder{test-env}@>; + }; +} +\end{codeblock} + +\pnum +A type \tcode{Token} models \libconcept{scope_token} only if: + +\begin{itemize} +\item +no exceptions are thrown from +copy construction, +move construction, +copy assignment, or +move assignment +of objects of type \tcode{Token}; and + +\item +given an lvalue \tcode{token} of type (possibly const) \tcode{Token}, +for all expressions \tcode{sndr} such that +\tcode{decltype((\linebreak{}sndr))} models \libconcept{sender}: + \begin{itemize} + \item + \tcode{token.wrap(sndr)} is a valid expression, + \item + \tcode{decltype(token.wrap(sndr))} models \libconcept{sender}, and + \item + \tcode{completion_signatures_of_t} + contains the same completion signatures as + \tcode{completion_signatures_of_t} + for all types \tcode{E} such that + \tcode{\libconcept{sender_in}} is modeled. + \end{itemize} +\end{itemize} + +\rSec2[exec.counting.scopes]{Counting Scopes} + +\rSec3[exec.counting.scopes.general]{General} + +\pnum +Scopes of type \tcode{simple_counting_scope} and \tcode{counting_scope} +maintain counts of associations. +Let: +\begin{itemize} +\item +\tcode{Scope} be either \tcode{simple_counting_scope} or \tcode{counting_scope}, +\item +\tcode{scope} be an object of type \tcode{Scope}, +\item +\tcode{tkn} be an object of type \tcode{Scope::token} +obtained from \tcode{scope.get_token()}, +\item +\tcode{jsndr} be a sender obtained from \tcode{scope.join()}, and +\item +\tcode{op} be an operation state obtained from +connecting \tcode{jsndr} to a receiver. +\end{itemize} +During its lifetime \tcode{scope} goes through different states +which govern what operations are allowed and the result of these operations: + +\begin{itemize} +\item +\exposid{unused}: +a newly constructed object starts in the \exposid{unused} state. + +\item +\exposid{open}: +when \tcode{tkn.try_associate()} is called +while \tcode{scope} is in the \exposid{unused} state, +\tcode{scope} moves to the \exposid{open} state. + +\item +\exposid{open-and-joining}: +when the operation state \tcode{op} is started +while \tcode{scope} is in the \exposid{unused} or \exposid{open} state, +\tcode{scope} moves to the \exposid{open-and-joining} state. + +\item +\exposid{closed}: +when \tcode{scope.close()} is called +while \tcode{scope} is in the \exposid{open} state, +\tcode{scope} moves to the \exposid{closed} state. + +\item +\exposid{unused-and-closed}: +when \tcode{scope.close()} is called +while \tcode{scope} is in the \exposid{unused} state, +\tcode{scope} moves to the \exposid{unused-and-closed} state. + +\item +\exposid{closed-and-joining}: +when \tcode{scope.close()} is called +while \tcode{scope} is in the \exposid{open-and-joining} state or +the operation state \tcode{op} is started +while \tcode{scope} is in +the \exposid{closed} or \exposid{unused-and-closed} state, +\tcode{scope} moves to the \exposid{closed-and-joining} state. + +\item +\exposid{joined}: +when the count of associations drops to zero +while \tcode{scope} is in +the \exposid{open-and-joining} or \exposid{closed-and-joining} state, +\tcode{scope} moves to the \exposid{joined} state. +\end{itemize} + +\pnum +\recommended +For \tcode{simple_counting_scope} and \tcode{counting_scope}, +implementations should store the state and the count of associations +in a single member of type \tcode{size_t}. + +\pnum +Subclause \ref{exec.counting.scopes} makes use of +the following exposition-only entities: + +\begin{codeblock} +struct @\exposid{scope-join-t}@ {}; // \expos + +enum @\exposid{scope-state-type}@ { // \expos + @\exposid{unused}@, // \expos + @\exposid{open}@, // \expos + @\exposid{closed}@, // \expos + @\exposid{open-and-joining}@, // \expos + @\exposid{closed-and-joining}@, // \expos + @\exposid{unused-and-closed}@, // \expos + @\exposid{joined}@, // \expos +}; +\end{codeblock} + +\pnum +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} +is specialized for \exposid{scope-join-t} as follows: + +\indexlibraryglobal{execution::\exposid{impls-for}<\exposid{scope-join-t}>}% +%%FIXME: The declarations of "receiver" below hide the \libconcept of the same name +\begin{codeblock} +namespace std::execution { + template<> + struct @\exposid{impls-for}@<@\exposid{scope-join-t}@> : @\exposid{default-impls}@ { + template + struct @\exposid{state}@ { // \expos + struct @\exposid{rcvr-t}@ { // \expos + using receiver_concept = receiver_t; + + Rcvr& @\exposid{rcvr}@; // \expos + + void set_value() && noexcept { + execution::set_value(std::move(@\exposid{rcvr}@)); + } + + template + void set_error(E&& e) && noexcept { + execution::set_error(std::move(@\exposid{rcvr}@), std::forward(e)); + } + + void set_stopped() && noexcept { + execution::set_stopped(std::move(@\exposid{rcvr}@)); + } + + decltype(auto) get_env() const noexcept { + return execution::get_env(@\exposid{rcvr}@); + } + }; + + using @\exposid{sched-sender}@ = // \expos + decltype(schedule(get_scheduler(get_env(declval())))); + using @\exposid{op-t}@ = // \expos + connect_result_t<@\exposid{sched-sender}@, @\exposid{rcvr-t}@>; + + Scope* @\exposid{scope}@; // \expos + Rcvr& @\exposid{receiver}@; // \expos + @\exposid{op-t}@ @\exposid{op}@; // \expos + + @\exposid{state}@(Scope* scope, Rcvr& rcvr) // \expos + noexcept(@\exposconcept{nothrow-callable}@) + : @\exposid{scope}@(scope), + @\exposid{receiver}@(rcvr), + @\exposid{op}@(connect(schedule(get_scheduler(get_env(rcvr))), @\exposid{rcvr-t}@(rcvr))) {} + + void @\exposid{complete}@() noexcept { // \expos + start(@\exposid{op}@); + } + + void @\exposid{complete-inline}@() noexcept { // \expos + set_value(std::move(@\exposid{receiver}@)); + } + }; + + static constexpr auto @\exposid{get-state}@ = // \expos + [](auto&& sender, Rcvr& receiver) + noexcept(is_nothrow_constructible_v<@\exposid{state}@, @\exposid{data-type}@, Rcvr&>) { + auto[_, self] = sender; + return @\exposid{state}@(self, receiver); + }; + + static constexpr auto @\exposid{start}@ = // \expos + [](auto& s, auto&) noexcept { + if (s.@\exposid{scope}@->@\exposid{start-join-sender}@(s)) + s.@\exposid{complete-inline}@(); + }; + }; +} +\end{codeblock} + +\rSec3[exec.scope.simple.counting]{Simple Counting Scope} + +\rSec4[exec.scope.simple.counting.general]{General} + +\indexlibraryglobal{execution::simple_counting_scope}% +\begin{codeblock} +namespace std::execution { + class simple_counting_scope { + public: + // \ref{exec.simple.counting.token}, token + struct token; + + static constexpr size_t max_associations = @\UNSP{\impldef{value of \tcode{std::execution::simple_counting_scope::max_associations}}}@; + + // \ref{exec.simple.counting.ctor}, constructor and destructor + simple_counting_scope() noexcept; + simple_counting_scope(simple_counting_scope&&) = delete; + ~simple_counting_scope(); + + // \ref{exec.simple.counting.mem}, members + token get_token() noexcept; + void close() noexcept; + @\libconcept{sender}@ auto join() noexcept; + + private: + size_t @\exposid{count}@; // \expos + @\exposid{scope-state-type}@ @\exposid{state}@; // \expos + + bool @\exposid{try-associate}@() noexcept; // \expos + void @\exposid{disassociate}@() noexcept; // \expos + template + bool @\exposid{start-join-sender}@(State& state) noexcept; // \expos + }; +} +\end{codeblock} + +\pnum +For purposes of determining the existence of a data race, +\tcode{get_token}, +\tcode{close}, +\tcode{join}, +\exposid{try-associate}, +\exposid{disassociate}, and +\exposid{start-join-sender} +behave as atomic operations\iref{intro.multithread}. +These operations on a single object of +type \tcode{simple_counting_scope} appear to occur in a single total order. + +\rSec4[exec.simple.counting.ctor]{Constructor and Destructor} + +\indexlibraryctor{execution::simple_counting_scope}% +\begin{itemdecl} +simple_counting_scope() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\exposid{count} is \tcode{0} and \exposid{state} is \exposid{unused}. +\end{itemdescr} + +\indexlibrarydtor{execution::simple_counting_scope}% +\begin{itemdecl} +~simple_counting_scope(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \exposid{state} is not one of +\exposid{joined}, \exposid{unused}, or \exposid{unused-and-closed}, +invokes \tcode{terminate}\iref{except.terminate}. +Otherwise, has no effects. +\end{itemdescr} + +\rSec4[exec.simple.counting.mem]{Members} + +\indexlibrarymember{get_token}{execution::simple_counting_scope}% +\begin{itemdecl} +token get_token() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An object \tcode{t} of type \tcode{simple_counting_scope::token} such that +\tcode{t.\exposid{scope} == this} is \tcode{true}. +\end{itemdescr} + +\indexlibrarymember{close}{execution::simple_counting_scope}% +\begin{itemdecl} +void close() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \exposid{state} is +\begin{itemize} +\item +\exposid{unused}, then changes \exposid{state} to \exposid{unused-and-closed}; +\item +\exposid{open}, then changes \exposid{state} to \exposid{closed}; +\item +\exposid{open-and-joining}, +then changes \exposid{state} to \exposid{closed-and-joining}; +\item +otherwise, no effects. +\end{itemize} + +\pnum +\ensures +Any subsequent call to \tcode{\exposid{try-associate}()} on \tcode{*this} +returns \tcode{false}. +\end{itemdescr} + +\indexlibrarymember{join}{execution::simple_counting_scope}% +\begin{itemdecl} +@\libconcept{sender}@ auto join() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{make-sender}(\exposid{scope-join-t}(), this)}. +\end{itemdescr} + +\indexlibrarymember{\exposid{try-associate}}{execution::simple_counting_scope}% +\begin{itemdecl} +bool @\exposid{try-associate}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \exposid{count} is equal to \tcode{max_associations}, then no effects. +Otherwise, if \exposid{state} is +\begin{itemize} +\item +\exposid{unused}, +then increments \exposid{count} and changes \exposid{state} to \exposid{open}; +\item +\exposid{open} or \exposid{open-and-joining}, +then increments \exposid{count}; +\item +otherwise, no effects. +\end{itemize} + +\pnum +\returns +\tcode{true} if \exposid{count} was incremented, \tcode{false} otherwise. +\end{itemdescr} + +\indexlibrarymember{\exposid{disassociate}}{execution::simple_counting_scope}% +\begin{itemdecl} +void @\exposid{disassociate}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\exposid{count} is greater than zero. + +\pnum +\effects +Decrements \exposid{count}. +If \exposid{count} is zero after decrementing and +\exposid{state} is \exposid{open-and-joining} or \exposid{closed-and-joining}, +changes \exposid{state} to \exposid{joined} and +calls \tcode{\exposid{complete}()} on all objects registered with \tcode{*this}. +\begin{note} +Calling \tcode{\exposid{complete}()} on any registered object +can cause \tcode{*this} to be destroyed. +\end{note} +\end{itemdescr} + +\indexlibrarymember{\exposid{start-join-sender}}{execution::simple_counting_scope}% +\begin{itemdecl} +template + bool @\exposid{start-join-sender}@(State& st) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \exposid{state} is +\begin{itemize} +\item +\exposid{unused}, \exposid{unused-and-closed}, or \exposid{joined}, then +changes \exposid{state} to \exposid{joined} and returns \tcode{true}; +\item +\exposid{open} or \exposid{open-and-joining}, then +changes \exposid{state} to \exposid{open-and-joining}, +registers \tcode{st} with \tcode{*this} and returns \tcode{false}; +\item +\exposid{closed} or \exposid{closed-and-joining}, then +changes \exposid{state} to \exposid{closed-and-joining}, +registers \tcode{st} with \tcode{*this} and returns \tcode{false}. +\end{itemize} +\end{itemdescr} + +\rSec4[exec.simple.counting.token]{Token} + +\indexlibraryglobal{execution::simple_counting_scope::token}% +\begin{codeblock} +namespace std::execution { + struct simple_counting_scope::token { + template<@\libconcept{sender}@ Sender> + Sender&& wrap(Sender&& snd) const noexcept; + bool try_associate() const noexcept; + void disassociate() const noexcept; + + private: + simple_counting_scope* @\exposid{scope}@; // \expos + }; +} +\end{codeblock} + +\indexlibrarymember{wrap}{execution::simple_counting_scope::token}% +\begin{itemdecl} +template<@\libconcept{sender}@ Sender> + Sender&& wrap(Sender&& snd) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{std::forward(snd)}. +\end{itemdescr} + +\indexlibrarymember{try_associate}{execution::simple_counting_scope::token}% +\begin{itemdecl} +bool try_associate() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{scope}->\exposid{try-associate}();} +\end{itemdescr} + +\indexlibrarymember{disassociate}{execution::simple_counting_scope::token}% +\begin{itemdecl} +void disassociate() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{\exposid{scope}->\exposid{disassociate}()}. +\end{itemdescr} + +\rSec3[exec.scope.counting]{Counting Scope} + +\indexlibraryglobal{execution::counting_scope}% +\indexlibrarymember{token}{execution::counting_scope}% +\begin{codeblock} +namespace std::execution { + class counting_scope { + public: + struct token { + template<@\libconcept{sender}@ Sender> + @\libconcept{sender}@ auto wrap(Sender&& snd) const noexcept(@\seebelow@); + bool try_associate() const noexcept; + void disassociate() const noexcept; + + private: + counting_scope* @\exposid{scope}@; // \expos + }; + + static constexpr size_t max_associations = @\UNSP{\impldef{value of \tcode{std::execution::counting_scope::max_associations}}}@; + + counting_scope() noexcept; + counting_scope(counting_scope&&) = delete; + ~counting_scope(); + + token get_token() noexcept; + void close() noexcept; + @\libconcept{sender}@ auto join() noexcept; + void request_stop() noexcept; + + private: + size_t @\exposid{count}@; // \expos + @\exposid{scope-state-type}@ @\exposid{state}@; // \expos + inplace_stop_source @\exposid{s_source}@; // \expos + + bool @\exposid{try-associate}@() noexcept; // \expos + void @\exposid{disassociate}@() noexcept; // \expos + + template + bool @\exposid{start-join-sender}@(State& state) noexcept; // \expos + }; +} +\end{codeblock} + +\pnum +\tcode{counting_scope} differs from \tcode{simple_counting_scope} by +adding support for cancellation. +Unless specified below, the semantics of members of \tcode{counting_scope} +are the same as the corresponding members of \tcode{simple_counting_scope}. + +\indexlibrarymember{get_token}{execution::counting_scope}% +\begin{itemdecl} +token get_token() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An object \tcode{t} of type \tcode{counting_scope::token} such that +\tcode{t.\exposid{scope} == this} is \tcode{true}. +\end{itemdescr} + +\indexlibrarymember{request_stop}{execution::counting_scope}% +\begin{itemdecl} +void request_stop() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{\exposid{s_source}.request_stop()}. + +\pnum +\remarks +Calls to \tcode{request_stop} do not introduce data races. +\end{itemdescr} + +\indexlibrarymember{wrap}{execution::counting_scope::token}% +\begin{itemdecl} +template<@\libconcept{sender}@ Sender> + @\libconcept{sender}@ auto counting_scope::token::wrap(Sender&& snd) const + noexcept(is_nothrow_constructible_v, Sender>); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{stop-when}@(std::forward(snd), @\exposid{scope}@->@\exposid{s_source}@.get_token()); +\end{codeblock} +\end{itemdescr} + +\rSec1[exec.par.scheduler]{Parallel scheduler} + +\pnum +\tcode{parallel_scheduler} models \libconcept{scheduler}. + +\pnum +Let \tcode{sch} be an object of type \tcode{parallel_scheduler}, and +let \tcode{\exposid{BACKEND-OF}(sch)} be \tcode{*ptr}, +where \tcode{sch} is associated with \tcode{ptr}. + +\pnum +The expression \tcode{get_forward_progress_guarantee(sch)} returns +\tcode{forward_progress_guarantee::paral\-lel}. + +\pnum +Let \tcode{sch2} be an object of type \tcode{parallel_scheduler}. +Two objects \tcode{sch} and \tcode{sch2} compare equal if and only if +\tcode{\exposid{BACKEND-OF}(sch)} and +\tcode{\exposid{BACKEND-OF}(sch2)} refer to the same object. + +\pnum +Let \tcode{rcvr} be a receiver. +A \defnx{proxy for \tcode{rcvr} with base \tcode{B}}{proxy} is +an lvalue \tcode{r} of type \tcode{B} such that: +\begin{itemize} +\item +\tcode{r.set_value()} has effects equivalent to +\tcode{set_value(std::move(rcvr))}. +\item +\tcode{r.set_error(e)}, where \tcode{e} is an \tcode{exception_ptr} object, +has effects equivalent to \tcode{set_error(std::move(\brk{}rcvr), std::move(e))}. +\item +\tcode{r.set_stopped()} has effects equivalent to +\tcode{set_stopped(std::move(rcvr))}. +\end{itemize} + +\pnum +A \defn{preallocated backend storage for a proxy} \tcode{r} is +an object \tcode{s} of type \tcode{span} +such that the range \tcode{s} remains valid and may be overwritten +until one of \tcode{set_value}, \tcode{set_error}, or \tcode{set_stopped} +is called on \tcode{r}. +\begin{note} +The storage referenced by \tcode{s} can be used as temporary storage +for operations launched via calls to \tcode{parallel_scheduler_backend}. +\end{note} + +\pnum +A \defnx{bulk chunked proxy for \tcode{rcvr} +with callable \tcode{f} and arguments \tcode{args}}{proxy!bulk chunked} +is a proxy \tcode{r} for \tcode{rcvr} +with base \tcode{system_context_replaceability::bulk_item_receiver_proxy} +such that +\tcode{r.execute(i, j)} for indices \tcode{i} and \tcode{j} +has effects equivalent to \tcode{f(i, j, args...)}. + +\pnum +A \defnx{bulk unchunked proxy for \tcode{rcvr} +with callable \tcode{f} and arguments \tcode{args}}{proxy!bulk unchunked} +is a proxy \tcode{r} for \tcode{rcvr} +with base \tcode{system_context_replaceability::bulk_item_receiver_proxy} +such that +\tcode{r.execute(i, i + 1)} for index \tcode{i} +has effects equivalent to \tcode{f(i, args...)}. + +\pnum +Let \tcode{b} be \tcode{\exposid{BACKEND-OF}(sch)}, +let \tcode{sndr} be the object returned by \tcode{schedule(sch)}, and +let \tcode{rcvr} be a receiver. +If \tcode{rcvr} is connected to \tcode{sndr} and +the resulting operation state is started, then: +\begin{itemize} +\item +If \tcode{sndr} completes successfully, +then \tcode{b.schedule(r, s)} is called, where +\begin{itemize} +\item +\tcode{r} is a proxy for \tcode{rcvr} +with base \tcode{system_context_replaceability::receiver_proxy} and +\item +\tcode{s} is a preallocated backend storage for \tcode{r}. +\end{itemize} +\item +All other completion operations are forwarded unchanged. +\end{itemize} + +\pnum +\tcode{parallel_scheduler} provides a customized implementation of +the \tcode{bulk_chunked} algorithm\iref{exec.bulk}. +If a receiver \tcode{rcvr} is connected to the sender +returned by \tcode{bulk_chunked(sndr, pol, shape, f)} and +the resulting operation state is started, then: +\begin{itemize} +\item +If \tcode{sndr} completes with values \tcode{vals}, +let \tcode{args} be a pack of lvalue subexpressions designating \tcode{vals}, +then \tcode{b.schedule_bulk_chunked(shape, r, s)} is called, where +\begin{itemize} +\item +\tcode{r} is a bulk chunked proxy for \tcode{rcvr} +with callable \tcode{f} and arguments \tcode{args} and +\item +\tcode{s} is a preallocated backend storage for \tcode{r}. +\end{itemize} +\item +All other completion operations are forwarded unchanged. +\end{itemize} +\begin{note} +Customizing the behavior of \tcode{bulk_chunked} +affects the default implementation of \tcode{bulk}. +\end{note} + +\pnum +\tcode{parallel_scheduler} provides a customized implementation of +the \tcode{bulk_unchunked} algorithm\iref{exec.bulk}. +If a receiver \tcode{rcvr} is connected to the sender +returned by \tcode{bulk_unchunked(sndr, pol, shape, f)} and +the resulting operation state is started, then: +\begin{itemize} +\item +If \tcode{sndr} completes with values \tcode{vals}, +let \tcode{args} be a pack of lvalue subexpressions designating \tcode{vals}, +then \tcode{b.schedule_bulk_unchunked(shape, r, s)} is called, where +\begin{itemize} +\item +\tcode{r} is a bulk unchunked proxy for \tcode{rcvr} +with callable \tcode{f} and arguments \tcode{args} and +\item +\tcode{s} is a preallocated backend storage for \tcode{r}. +\end{itemize} +\item +All other completion operations are forwarded unchanged. +\end{itemize} + +\indexlibraryglobal{get_parallel_scheduler}% +\begin{itemdecl} +parallel_scheduler get_parallel_scheduler(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \tcode{eb} be the result of \tcode{system_context_replaceability::query_parallel_scheduler_backend()}. +If \tcode{eb == nullptr} is \tcode{true}, +calls \tcode{terminate}\iref{except.terminate}. +Otherwise, returns a \tcode{parallel_scheduler} object +associated with \tcode{eb}. +\end{itemdescr} + +\rSec1[exec.sysctxrepl]{Namespace \tcode{system_context_replaceability}} + +\rSec2[exec.sysctxrepl.general]{General} + +\pnum +Facilities in the \tcode{system_context_replaceability} namespace +allow users to replace the default implementation of \tcode{parallel_scheduler}. + +\rSec2[exec.sysctxrepl.query]{\tcode{query_parallel_scheduler_backend}} +\indexlibraryglobal{query_parallel_scheduler_backend}% +\begin{itemdecl} +shared_ptr query_parallel_scheduler_backend(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{query_parallel_scheduler_backend()} returns +the implementation object for a parallel scheduler. + +\pnum +\returns +A non-null shared pointer to an object +that implements the \tcode{parallel_scheduler_backend} interface. + +\pnum +\remarks +This function is replaceable\iref{dcl.fct.def.replace}. +\end{itemdescr} + +\begin{codeblock} +namespace std::execution::system_context_replaceability { + struct @\libglobal{receiver_proxy}@ { + virtual ~receiver_proxy() = default; + + protected: + virtual bool @\exposidnc{query-env}@(@\unspecnc@) noexcept = 0; // \expos + + public: + virtual void set_value() noexcept = 0; + virtual void set_error(exception_ptr) noexcept = 0; + virtual void set_stopped() noexcept = 0; + + template + optional

try_query(Query q) noexcept; + }; + + struct @\libglobal{bulk_item_receiver_proxy}@ : receiver_proxy { + virtual void execute(size_t, size_t) noexcept = 0; + }; +} +\end{codeblock} + +\pnum +\tcode{receiver_proxy} represents a receiver +that will be notified +by the implementations of \tcode{parallel_scheduler_backend} +to trigger the completion operations. +\tcode{bulk_item_receiver_proxy} is derived from \tcode{receiver_proxy} and +is used for \tcode{bulk_chunked} and \tcode{bulk_unchunked} customizations +that will also receive notifications +from implementations of \tcode{parallel_scheduler_backend} +corresponding to different iterations. + +\begin{itemdecl} +template + optional

@\libglobal{try_query}@(Query q) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{P} is a cv-unqualified non-array object type. + +\pnum +\returns +Let \tcode{env} be the environment of the receiver represented by \tcode{*this}. +If +\begin{itemize} +\item +\tcode{Query} is not a member of an implementation-defined set +of supported queries; or +\item +\tcode{P} is not a member of an implementation-defined set +of supported result types for \tcode{Query}; or +\item +the expression \tcode{q(env)} is not well-formed or +does not have type \cv{} \tcode{P}, +\end{itemize} +then returns \tcode{nullopt}. +Otherwise, returns \tcode{q(env)}. + +\pnum +\remarks +\tcode{get_stop_token_t} is +in the implementation-defined set of supported queries, and +\tcode{inplace_stop_token} is a member +of the implementation-defined set of supported result types +for \tcode{get_stop_token_t}. +\end{itemdescr} + +\rSec2[exec.sysctxrepl.psb]{Class \tcode{parallel_scheduler_backend}} + +\begin{codeblock} +namespace std::execution::system_context_replaceability { + struct @\libglobal{parallel_scheduler_backend}@ { + virtual ~parallel_scheduler_backend() = default; + + virtual void schedule(receiver_proxy&, span) noexcept = 0; + virtual void schedule_bulk_chunked(size_t, bulk_item_receiver_proxy&, + span) noexcept = 0; + virtual void schedule_bulk_unchunked(size_t, bulk_item_receiver_proxy&, + span) noexcept = 0; + }; +} +\end{codeblock} + +\indexlibrarymember{schedule}{parallel_scheduler_backend}% +\begin{itemdecl} +virtual void schedule(receiver_proxy& r, span s) noexcept = 0; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The ends of +the lifetimes of \tcode{*this}, +the object referred to by \tcode{r}, and +any storage referenced by \tcode{s} +all happen after +the beginning of the evaluation of one of the expressions below. + +\pnum +\effects +A derived class shall implement this function such that: +\begin{itemize} +\item +One of the following expressions is evaluated: +\begin{itemize} +\item +\tcode{r.set_value()}, if no error occurs, and the work is successful; +\item +\tcode{r.set_error(eptr)}, if an error occurs, +where \tcode{eptr} is an object of type \tcode{exception_ptr}; +\item +\tcode{r.set_stopped()}, if the work is canceled. +\end{itemize} +\item +Any call to \tcode{r.set_value()} happens on +an execution agent of the execution context represented by \tcode{*this}. +\end{itemize} + +\pnum +\remarks +The storage referenced by \tcode{s} +may be used by \tcode{*this} as temporary storage +for the duration of the operation launched by this call. +\end{itemdescr} + +\indexlibrarymember{schedule_bulk_chunked}{parallel_scheduler_backend}% +\begin{itemdecl} +virtual void schedule_bulk_chunked(size_t n, bulk_item_receiver_proxy& r, + span s) noexcept = 0; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The ends of +the lifetimes of \tcode{*this}, +the object referred to by \tcode{r}, and +any storage referenced by \tcode{s} +all happen after +the beginning of the evaluation of one of the expressions below. + +\pnum +\effects +A derived class shall implement this function such that: +\begin{itemize} +\item +Eventually, one of the following expressions is evaluated: +\begin{itemize} +\item +\tcode{r.set_value()}, if no error occurs, and the work is successful; +\item +\tcode{r.set_error(eptr)}, if an error occurs, +where \tcode{eptr} is an object of type \tcode{exception_ptr}; +\item +\tcode{r.set_stopped()}, if the work is canceled. +\end{itemize} +\item +If \tcode{r.execute(b, e)} is called, +then \tcode{b} and \tcode{e} are in the range \crange{0}{n} and +$\tcode{b} < \tcode{e}$. +\item +For each $i$ in \range{0}{n}, +there is at most one call to \tcode{r.execute(b, e)} +such that $i$ is in the range \range{b}{e}. +\item +If \tcode{r.set_value()} is called, +then for each $i$ in \range{0}{n}, +there is exactly one call to \tcode{r.execute(b, e)} +such that $i$ is in the range \range{b}{e}. +\item +All calls to \tcode{execute} on \tcode{r} happen before +the call to either \tcode{set_value}, \tcode{set_error}, or \tcode{set_stopped} +on \tcode{r}. +\item +All calls to \tcode{execute} and \tcode{set_value} on \tcode{r} are made +on execution agents of the execution context represented by \tcode{*this}. +\end{itemize} + +\pnum +\remarks +The storage referenced by \tcode{s} may be used by \tcode{*this} +as temporary storage for the duration of the operation launched by this call. +\end{itemdescr} + +\indexlibrarymember{schedule_bulk_unchunked}{parallel_scheduler_backend}% +\begin{itemdecl} +virtual void schedule_bulk_unchunked(size_t n, bulk_item_receiver_proxy& r, + span s) noexcept = 0; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The ends of +the lifetimes of \tcode{*this}, +the object referred to by \tcode{r}, and +any storage referenced by \tcode{s} +all happen after +the beginning of the evaluation of one of the expressions below. + +\pnum +\effects +A derived class shall implement this function such that: +\begin{itemize} +\item +Eventually, one of the following expressions is evaluated: +\begin{itemize} +\item +\tcode{r.set_value()}, if no error occurs, and the work is successful; +\item +\tcode{r.set_error(eptr)}, if an error occurs, +where \tcode{eptr} is an object of type \tcode{exception_ptr}; +\item +\tcode{r.set_stopped()}, if the work is canceled. +\end{itemize} +\item +If \tcode{r.execute(b, e)} is called, +then \tcode{b} is in the range \range{0}{n} and +\tcode{e} is equal to \tcode{b + 1}. +For each $i$ in \range{0}{n}, +there is at most one call to \tcode{r.execute($i$, $i$ + 1)}. +\item +If \tcode{r.set_value()} is called, +then for each $i$ in \range{0}{n}, +there is exactly one call to \tcode{r.execute($i$, $i$ + 1)}. +\item +All calls to \tcode{execute} on \tcode{r} happen before +the call to either \tcode{set_value}, \tcode{set_error}, or \tcode{set_stopped} +on \tcode{r}. +\item +All calls to \tcode{execute} and \tcode{set_value} on \tcode{r} are made +on execution agents of the execution context represented by \tcode{*this}. +\end{itemize} + +\pnum +\remarks +The storage referenced by \tcode{s} may be used by \tcode{*this} +as temporary storage for the duration of the operation launched by this call. +\end{itemdescr} diff --git a/source/expressions.tex b/source/expressions.tex index 7b09b36d39..381250b8f8 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -39,7 +39,7 @@ obey the rules for syntax and evaluation order specified in \ref{expr.compound}, but the requirements of operand type and value category are replaced by the rules for function call. Relations between operators, such as -\tcode{++a} meaning \tcode{a+=1}, are not guaranteed for overloaded +\tcode{++a} meaning \tcode{a += 1}, are not guaranteed for overloaded operators\iref{over.oper}. \end{note} @@ -53,7 +53,7 @@ considered where necessary to convert the operands to types appropriate for the built-in operator. If a built-in operator is selected, such conversions will be applied to the operands before the operation is -considered further according to the rules in subclause \ref{expr.compound}; +considered further according to the rules in \ref{expr.compound}; see~\ref{over.match.oper}, \ref{over.built}. \pnum @@ -131,7 +131,7 @@ \begin{footnote} The cast and assignment operators must still perform their specific conversions as described in~\ref{expr.type.conv}, \ref{expr.cast}, -\ref{expr.static.cast} and~\ref{expr.ass}. +\ref{expr.static.cast} and~\ref{expr.assign}. \end{footnote} \rSec1[expr.prop]{Properties of expressions} @@ -147,7 +147,7 @@ \end{importgraphic} \begin{itemize} -\item A \defn{glvalue} is an expression whose evaluation determines the identity of an object or function. +\item A \defn{glvalue} is an expression whose evaluation determines the identity of an object, function, or non-static data member. \item A \defn{prvalue} is an expression whose evaluation initializes an object or computes the value of an operand of an operator, as specified by the context in which it appears, @@ -186,7 +186,8 @@ \begin{note} An expression is an xvalue if it is: \begin{itemize} -\item a move-eligible \grammarterm{id-expression}\iref{expr.prim.id.unqual}, +\item a move-eligible \grammarterm{id-expression}\iref{expr.prim.id.unqual} +or \grammarterm{splice-expression}\iref{expr.prim.splice}, \item the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type\iref{expr.call}, @@ -233,13 +234,11 @@ A prvalue whose result is the value \placeholder{V} is sometimes said to have or name the value \placeholder{V}. The \defn{result object} of a prvalue is the object initialized by the prvalue; -a non-discarded prvalue -that is used to compute the value of an operand of a built-in operator -or a prvalue that has type \cv{}~\keyword{void} +a prvalue that has type \cv{}~\keyword{void} has no result object. \begin{note} Except when the prvalue is the operand of a \grammarterm{decltype-specifier}, -a prvalue of class or array type always has a result object. +a prvalue of object type always has a result object. For a discarded prvalue that has type other than \cv{}~\keyword{void}, a temporary object is materialized; see \ref{expr.context}. \end{note} @@ -266,9 +265,11 @@ \end{note} \pnum -Whenever a prvalue appears as an operand of an operator that -expects a glvalue for that operand, the -temporary materialization conversion\iref{conv.rval} is +Unless otherwise specified\iref{expr.reinterpret.cast, expr.const.cast}, +whenever a prvalue +that is not the result of the lvalue-to-rvalue conversion\iref{conv.lval} +appears as an operand of an operator, +the temporary materialization conversion\iref{conv.rval} is applied to convert the expression to an xvalue. \pnum @@ -296,31 +297,32 @@ \begin{note} A program that attempts to modify an object through a nonmodifiable lvalue or through an rvalue -is ill-formed\iref{expr.ass,expr.post.incr,expr.pre.incr}. +is ill-formed\iref{expr.assign,expr.post.incr,expr.pre.incr}. \end{note} \pnum +An object of dynamic type $\tcode{T}_\text{obj}$ is +\defn{type-accessible} through a glvalue of type $\tcode{T}_\text{ref}$ +if $\tcode{T}_\text{ref}$ is similar\iref{conv.qual} to: +\begin{itemize} +\item $\tcode{T}_\text{obj}$, + +\item a type that is the signed or unsigned type corresponding to $\tcode{T}_\text{obj}$, or + +\item a \keyword{char}, \tcode{\keyword{unsigned} \keyword{char}}, or \tcode{std::byte} type. +\end{itemize} If a program attempts to access\iref{defns.access} the stored value of an object through a glvalue -whose type is not similar\iref{conv.qual} to -one of the following types the behavior is -undefined: +through which it is not type-accessible, +the behavior is undefined. \begin{footnote} The intent of this list is to specify those circumstances in which an object can or cannot be aliased. \end{footnote} -\begin{itemize} -\item the dynamic type of the object, - -\item a type that is the signed or unsigned type corresponding to the -dynamic type of the object, or - -\item a \keyword{char}, \tcode{\keyword{unsigned} \keyword{char}}, or \tcode{std::byte} type. -\end{itemize} If a program invokes a defaulted copy/move constructor or copy/move assignment operator for a union of type \tcode{U} with a glvalue argument -that does not denote an object of type \cv{}~\keyword{U} within its lifetime, +that does not denote an object of type \cv{}~\tcode{U} within its lifetime, the behavior is undefined. \begin{note} In C, an entire object of structure type can be accessed, e.g., using assignment. @@ -334,9 +336,13 @@ \indextext{expression!reference}% If an expression initially has the type ``reference 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. +\tcode{T} prior to any further analysis; +the value category of the expression is not altered. +Let $X$ be the object or function denoted by the reference. +If a pointer to $X$ would be valid in +the context of the evaluation of the expression\iref{basic.fundamental}, +the result designates $X$; +otherwise, the behavior is undefined. \begin{note} Before the lifetime of the reference has started or after it has ended, the behavior is undefined (see~\ref{basic.life}). @@ -376,8 +382,8 @@ ``pointer to function''; \item -if \tcode{T1} is ``pointer to \cvqual{cv1} \tcode{C1}'' and \tcode{T2} is ``pointer to -\cvqual{cv2} \tcode{C2}'', where \tcode{C1} is reference-related to \tcode{C2} or \tcode{C2} is +if \tcode{T1} is ``pointer to \tcode{C1}'' and \tcode{T2} is ``pointer to +\tcode{C2}'', where \tcode{C1} is reference-related to \tcode{C2} or \tcode{C2} is reference-related to \tcode{C1}\iref{dcl.init.ref}, the qualification-combined type\iref{conv.qual} of \tcode{T1} and \tcode{T2} or the qualification-combined type of \tcode{T2} and \tcode{T1}, @@ -432,10 +438,12 @@ \pnum \label{term.unevaluated.operand}% In some contexts, \defnx{unevaluated operands}{unevaluated operand} -appear\iref{expr.prim.req, +appear\iref{expr.prim.req.simple, +expr.prim.req.compound, expr.typeid, expr.sizeof, expr.unary.noexcept, +expr.reflect, dcl.type.decltype, temp.pre, temp.concept}. @@ -461,6 +469,7 @@ \item \tcode{(} \grammarterm{expression} \tcode{)}, where \grammarterm{expression} is one of these expressions, \item \grammarterm{id-expression}\iref{expr.prim.id}, +\item \grammarterm{splice-expression}\iref{expr.prim.splice}, \item subscripting\iref{expr.sub}, \item class member access\iref{expr.ref}, \item indirection\iref{expr.unary.op}, @@ -550,7 +559,7 @@ \pnum An expression $E$ can be \defnx{implicitly converted}{conversion!implicit} to a type \tcode{T} if and only if the -declaration \tcode{T t=$E$;} is well-formed, for some invented temporary +declaration \tcode{T t = $E$;} is well-formed, for some invented temporary variable \tcode{t}\iref{dcl.init}. \pnum @@ -621,7 +630,7 @@ prvalue is \tcode{T}. \begin{footnote} In \Cpp{} class and array prvalues can have cv-qualified types. -This differs from ISO C, in which non-lvalues never have +This differs from C, in which non-lvalues never have cv-qualified types. \end{footnote} @@ -669,11 +678,29 @@ the glvalue. \item Otherwise, if the object to which the glvalue refers contains an invalid -pointer value\iref{basic.stc.dynamic.deallocation}, the behavior is +pointer value\iref{basic.compound}, the behavior is \impldef{lvalue-to-rvalue conversion of an invalid pointer value}. -\item Otherwise, the object indicated by the glvalue is read\iref{defns.access}, -and the value contained in the object is the prvalue result. +\item Otherwise, if the bits in the value representation of +the object to which the glvalue refers +are not valid for the object's type, the behavior is undefined. +\begin{example} +\begin{codeblock} +bool f() { + bool b = true; + char c = 42; + memcpy(&b, &c, 1); + return b; // undefined behavior if \tcode{42} is not a valid value representation for \keyword{bool} +} +\end{codeblock} +\end{example} + +\item Otherwise, the object indicated by the glvalue is read\iref{defns.access}. +Let \tcode{V} be the value contained in the object. +If \tcode{T} is an integer type, +the prvalue result is +the value of type \tcode{T} congruent\iref{basic.fundamental} to \tcode{V}, and +\tcode{V} otherwise. \end{itemize} \pnum @@ -755,10 +782,6 @@ as ``pointer to \tcode{\keyword{const} \keyword{int}}'', and as ``pointer to pointer to \tcode{\keyword{const} \keyword{int}}''. \end{example} -The $n$-tuple of cv-qualifiers after the first one -in the longest qualification-decomposition of \tcode{T}, that is, -$\cv{}_1, \cv{}_2, \dotsc, \cv{}_n$, is called the -\defn{cv-qualification signature} of \tcode{T}. \pnum \indextext{type!similar|see{similar types}}% @@ -1030,16 +1053,26 @@ The pointer value\iref{basic.compound} is unchanged by this conversion. \pnum -A prvalue of type ``pointer to \cv{} \tcode{D}'', where \tcode{D} +A prvalue \tcode{v} of type ``pointer to \cv{} \tcode{D}'', where \tcode{D} is a complete class type, can be converted to a prvalue of type ``pointer to \cv{} \tcode{B}'', where \tcode{B} is a base class\iref{class.derived} of \tcode{D}. If \tcode{B} is an inaccessible\iref{class.access} or ambiguous\iref{class.member.lookup} base class of \tcode{D}, a program -that necessitates this conversion is ill-formed. The result of the -conversion is a pointer to the base class subobject of the derived class -object. The null pointer value is converted to the null pointer value of -the destination type. +that necessitates this conversion is ill-formed. +If \tcode{v} is a null pointer value, +the result is a null pointer value. +Otherwise, +if \tcode{B} is a virtual base class of \tcode{D} and +\tcode{v} does not point to an object +whose type is similar\iref{conv.qual} to \tcode{D} and +that is +within its lifetime or +within its period of construction or destruction\iref{class.cdtor}, +the behavior is undefined. +Otherwise, +the result is a pointer to the base class subobject of +the derived class object. \rSec2[conv.mem]{Pointer-to-member conversions} @@ -1151,7 +1184,7 @@ the following rules are applied: \begin{itemize} \item -If both operands have the same type, no further conversion is needed. +If both operands have the same type, no further conversion is performed. \item Otherwise, if one of the operands is of a non-floating-point type, that operand is converted to the type of @@ -1203,6 +1236,8 @@ \rSec1[expr.prim]{Primary expressions}% \indextext{expression!primary|(} +\rSec2[expr.prim.grammar]{Grammar} + \begin{bnf} \nontermdef{primary-expression}\br literal\br @@ -1211,7 +1246,8 @@ id-expression\br lambda-expression\br fold-expression\br - requires-expression + requires-expression\br + splice-expression \end{bnf} \rSec2[expr.prim.literal]{Literals} @@ -1243,6 +1279,16 @@ A \grammarterm{lambda-expression} does not introduce a class scope. \end{note} +\pnum +If the expression \tcode{this} +appears within the predicate of a contract assertion\iref{basic.contract.general} +(including as the result of an implicit transformation\iref{expr.prim.id.general} +and including in the bodies of nested \grammarterm{lambda-expression}s) +and the current class +encloses the contract assertion, +\keyword{const} is combined with the \grammarterm{cv-qualifier-seq} +used to generate the resulting type (see below). + \pnum If a declaration declares a member function or member function template of a class \tcode{X}, the expression \keyword{this} is a prvalue of type ``pointer to @@ -1251,8 +1297,8 @@ between the optional \grammarterm{cv-qualifier-seq} and the end of the \grammarterm{function-definition}, \grammarterm{member-declarator}, or \grammarterm{declarator}. It shall not appear within -the declaration of either -a static member function or an explicit object member function +the declaration of +a static or explicit object member function of the current class (although its type and value category are defined within such member functions as they are within an implicit object member function). @@ -1335,14 +1381,60 @@ operators\iref{expr.ref}. \end{note} +\pnum +If an \grammarterm{id-expression} $E$ denotes +a non-static non-type member of some class \tcode{C} at a point where +the current class\iref{expr.prim.this} is \tcode{X} and +\begin{itemize} +\item +$E$ is potentially evaluated or +\tcode{C} is \tcode{X} or a base class of \tcode{X}, and +\item +$E$ is not the \grammarterm{id-expression} of +a class member access expression\iref{expr.ref}, and +\item +$E$ is not the \grammarterm{id-expression} of +a \grammarterm{reflect-expression}\iref{expr.reflect}, and +\item +if $E$ is a \grammarterm{qualified-id}, +$E$ is not the un-parenthesized operand of +the unary \tcode{\&} operator\iref{expr.unary.op}, +\end{itemize} +the \grammarterm{id-expression} is transformed into +a class member access expression using \tcode{(*this)} as the object expression. +If this transformation occurs +in the predicate of a precondition assertion of a constructor of \tcode{X} +or a postcondition assertion of a destructor of \tcode{X}, +the expression is ill-formed. +\begin{note} +If \tcode{C} is not \tcode{X} or a base class of \tcode{X}, +the class member access expression is ill-formed. +Also, if the \grammarterm{id-expression} occurs within +a static or explicit object member function, +the class member access is ill-formed. +\end{note} +This transformation does not apply in +the template definition context\iref{temp.dep.type}. +\begin{example} +\begin{codeblock} +struct C { + bool b; + C() pre(b) // error + pre(&this->b) // OK + pre(sizeof(b) > 0); // OK, \tcode{b} is not potentially evaluated. +}; +\end{codeblock} +\end{example} + \pnum If an \grammarterm{id-expression} $E$ denotes a member $M$ of an anonymous union\iref{class.union.anon} $U$: \begin{itemize} \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}). +$E$ refers to $M$ as a member of the lookup context of the terminal name of $E$ +(after any implicit transformation to +a class member access expression). \begin{example} \tcode{o.x} is interpreted as \tcode{o.$u$.x}, where $u$ names the anonymous union member. @@ -1361,22 +1453,22 @@ \end{itemize} \pnum -An \grammarterm{id-expression} that denotes a non-static data member or +An \grammarterm{id-expression} or \grammarterm{splice-expression} +that designates a non-static data member or implicit object member function of a class can only be used: \begin{itemize} -\item as part of a class member access\iref{expr.ref} in which the +\item as part of a class member access +(after any implicit transformation (see above)) +in which the object expression refers to the member's class -\begin{footnote} -This also applies when the object expression -is an implicit \tcode{(*\keyword{this})}\iref{class.mfct.non.static}. -\end{footnote} or a class derived from that class, or \item to form a pointer to member\iref{expr.unary.op}, or -\item if that \grammarterm{id-expression} denotes a non-static data member +\item if that \grammarterm{id-expression} or \grammarterm{splice-expression} +designates a non-static data member and it appears in an unevaluated operand. \begin{example} \begin{codeblock} @@ -1385,6 +1477,7 @@ }; int i = sizeof(S::m); // OK int j = sizeof(S::m + 42); // OK +int S::*k = &[:^^S::m:]; // OK \end{codeblock} \end{example} \end{itemize} @@ -1435,10 +1528,8 @@ \indextext{identifier}% An \grammarterm{identifier} is only an \grammarterm{id-expression} if it has -been suitably declared\iref{dcl.dcl} +been suitably declared\iref{dcl} or if it appears as part of a \grammarterm{declarator-id}\iref{dcl.decl}. -An \grammarterm{identifier} that names a coroutine parameter -refers to the copy of the parameter\iref{dcl.fct.def.coroutine}. \begin{note} For \grammarterm{operator-function-id}{s}, see~\ref{over.oper}; for \grammarterm{conversion-function-id}{s}, see~\ref{class.conv.fct}; for @@ -1447,9 +1538,6 @@ A \grammarterm{type-name} or \grammarterm{computed-type-specifier} prefixed by \tcode{\~} denotes the destructor of the type so named; 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\iref{class.mfct.non.static}. \end{note} \pnum @@ -1472,21 +1560,28 @@ \pnum The result is the entity denoted by the \grammarterm{unqualified-id}\iref{basic.lookup.unqual}. -If the \grammarterm{unqualified-id} appears -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-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 -captured by copy in some intervening \grammarterm{lambda-expression}, -then let $E$ be the innermost such \grammarterm{lambda-expression}. + +\pnum +If \begin{itemize} \item -If there is such a \grammarterm{lambda-expression} and -if $P$ is in $E$'s function parameter scope -but not its \grammarterm{parameter-declaration-clause}, then +the \grammarterm{unqualified-id} +appears in a \grammarterm{lambda-expression} +at program point $P$, +\item +the entity is a local entity\iref{basic.pre} +or a variable declared by an \grammarterm{init-capture}\iref{expr.prim.lambda.capture}, +\item +naming the entity within the \grammarterm{compound-statement} of +the innermost enclosing \grammarterm{lambda-expression} of $P$, +but not in an unevaluated operand, would refer to an entity captured by copy +in some intervening \grammarterm{lambda-expression}, and +\item +$P$ is in the function parameter scope, +but not the \grammarterm{parameter-declaration-clause}, +of the innermost such \grammarterm{lambda-expression} $E$, +\end{itemize} +then the type of the expression is the type of a class member access expression\iref{expr.ref} naming the non-static data member @@ -1496,27 +1591,166 @@ If $E$ is not declared \keyword{mutable}, the type of such an identifier will typically be \keyword{const} qualified. \end{note} + +\pnum +Otherwise, +if the \grammarterm{unqualified-id} +names a coroutine parameter, +the type of the expression is +that of the copy of the parameter\iref{dcl.fct.def.coroutine}, +and the result is that copy. + +\pnum +Otherwise, +if the \grammarterm{unqualified-id} +names a result binding\iref{dcl.contract.res} +attached to a function \placeholder{f} +with return type \tcode{U}, +\begin{itemize} +\item +if \tcode{U} is ``reference to \tcode{T}'', +then the type of the expression is +\tcode{const T}; \item -Otherwise (if there is no such \grammarterm{lambda-expression} or -if $P$ either precedes $E$'s function parameter scope or -is in $E$'s \grammarterm{parameter-declaration-clause}), -the type of the expression is the type of the result. +otherwise, +the type of the expression is \tcode{const U}. \end{itemize} -\begin{note} -If the entity is a template parameter object for + +\pnum +Otherwise, +if the \grammarterm{unqualified-id} +appears in the predicate of a contract assertion $C$\iref{basic.contract} +and the entity is +\begin{itemize} +\item +a variable +declared outside of $C$ +of object type \tcode{T}, +\item +a variable or template parameter +declared outside of $C$ +of type ``reference to \tcode{T}'', or +\item +a structured binding +of type \tcode{T} +whose corresponding variable +is declared outside of $C$, +\end{itemize} +then the type of the expression is \keyword{const}~\tcode{T}. + +\pnum +\begin{example} +\begin{codeblock} +int n = 0; +struct X { bool m(); }; + +struct Y { + int z = 0; + + void f(int i, int* p, int& r, X x, X* px) + pre (++n) // error: attempting to modify const lvalue + pre (++i) // error: attempting to modify const lvalue + pre (++(*p)) // OK + pre (++r) // error: attempting to modify const lvalue + pre (x.m()) // error: calling non-const member function + pre (px->m()) // OK + pre ([=,&i,*this] mutable { + ++n; // error: attempting to modify const lvalue + ++i; // error: attempting to modify const lvalue + ++p; // OK, refers to member of closure type + ++r; // OK, refers to non-reference member of closure type + ++this->z; // OK, captured \tcode{*\keyword{this}} + ++z; // OK, captured \tcode{*\keyword{this}} + int j = 17; + [&]{ + int k = 34; + ++i; // error: attempting to modify const lvalue + ++j; // OK + ++k; // OK + }(); + return true; + }()); + + template + void g() + pre(++N) // error: attempting to modify prvalue + pre(++R) // error: attempting to modify const lvalue + pre(++(*P)); // OK + + int h() + post(r : ++r) // error: attempting to modify const lvalue + post(r: [=] mutable { + ++r; // OK, refers to member of closure type + return true; + }()); + + int& k() + post(r : ++r); // error: attempting to modify const lvalue +}; +\end{codeblock} +\end{example} + +\pnum +Otherwise, if the entity is a template parameter object for a template parameter of type \tcode{T}\iref{temp.param}, the type of the expression is \tcode{const T}. -\end{note} + +\pnum +In all other cases, the type of the expression is the type of the entity. + +\pnum \begin{note} The type will be adjusted as described in \ref{expr.type} if it is cv-qualified or is a reference type. \end{note} + +\pnum The expression is an xvalue if it is move-eligible (see below); an lvalue -if the entity is a function, variable, structured binding\iref{dcl.struct.bind}, data member, or +if the entity is a +function, +variable, +structured binding\iref{dcl.struct.bind}, +result binding\iref{dcl.contract.res}, +data member, or template parameter object; and a prvalue otherwise\iref{basic.lval}; it is a bit-field if the identifier designates a bit-field. + +\pnum +If an \grammarterm{id-expression} $E$ +appears in the predicate of +a function contract assertion attached to a function \placeholder{f} +and denotes +a function parameter of \placeholder{f} +and the implementation introduces any temporary objects +to hold the value of that parameter as specified in \ref{class.temporary}, +\begin{itemize} +\item +if the contract assertion +is a precondition assertion +and the evaluation of the precondition assertion +is sequenced before the initialization of the parameter object, +$E$ refers to the most recently initialized such temporary object, and +\item +if the contract assertion +is a postcondition assertion, +it is unspecified whether $E$ refers to +one of the temporary objects or the parameter object; +the choice is consistent within a single evaluation of a postcondition assertion. +\end{itemize} + +\pnum +If an \grammarterm{id-expression} $E$ +names a result binding +in a postcondition assertion +and the implementation introduces any temporary objects +to hold the result object as specified in \ref{class.temporary}, +and the postcondition assertion +is sequenced before the initialization of the result object\iref{expr.call}, +$E$ refers to the most recently initialized such temporary object. + + \begin{example} \begin{codeblock} void f() { @@ -1548,30 +1782,28 @@ \pnum An \defnadj{implicitly movable}{entity} is -a variable of automatic storage duration +a variable with automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type. -In the following contexts, -an \grammarterm{id-expression} is \defn{move-eligible}: +An \grammarterm{id-expression} or +\grammarterm{splice-expression}\iref{expr.prim.splice} +is \defn{move-eligible} if \begin{itemize} \item -If the \grammarterm{id-expression} (possibly parenthesized) -is the operand of a \tcode{return}\iref{stmt.return} or -\keyword{co_return}\iref{stmt.return.coroutine} statement, -and names an implicitly movable entity declared in the body -or \grammarterm{parameter-declaration-clause} of the innermost enclosing -function or \grammarterm{lambda-expression}, or -\item -if the \grammarterm{id-expression} (possibly parenthesized) -is the operand of a \grammarterm{throw-expression}\iref{expr.throw}, -and names an implicitly movable entity -that belongs to a scope that does not contain the \grammarterm{compound-statement} -of the innermost -\grammarterm{lambda-expression}, -\grammarterm{try-block}, or -\grammarterm{function-try-block} (if any) -whose \grammarterm{compound-statement} or \grammarterm{ctor-initializer} -contains the \grammarterm{throw-expression}. +it designates an implicitly movable entity, +\item +it is the (possibly parenthesized) +operand of a \tcode{return}\iref{stmt.return} or +\keyword{co_return}\iref{stmt.return.coroutine} statement or +of a \grammarterm{throw-expression}\iref{expr.throw}, and +\item +each intervening scope between +the declaration of the entity and +the innermost enclosing scope of the expression +is a block scope and, +for a \grammarterm{throw-expression}, +is not the block scope of +a \grammarterm{try-block} or \grammarterm{function-try-block}. \end{itemize} \rSec3[expr.prim.id.qual]{Qualified names} @@ -1593,9 +1825,15 @@ type-name \terminal{::}\br namespace-name \terminal{::}\br computed-type-specifier \terminal{::}\br + splice-scope-specifier \terminal{::}\br nested-name-specifier identifier \terminal{::}\br nested-name-specifier \opt{\keyword{template}} simple-template-id \terminal{::} \end{bnf} +\begin{bnf} +\nontermdef{splice-scope-specifier}\br + splice-specifier\br + \opt{\keyword{template}} splice-specialization-specifier +\end{bnf} \pnum \indextext{component name}% @@ -1608,6 +1846,33 @@ \grammarterm{simple-template-id}, and/or \grammarterm{nested-name-specifier}. +\pnum +A \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} +that is not followed by \tcode{::} +is never interpreted as part of a \grammarterm{splice-scope-specifier}. +The keyword \keyword{template} may only be omitted +from the form +\tcode{\opt{\keyword{template}} \grammarterm{splice-specialization-specifier} ::} +when the \grammarterm{splice-specialization-specifier} +is preceded by \keyword{typename}. +\begin{example} +\begin{codeblock} +template +struct TCls { + static constexpr int s = V; + using type = int; +}; + +int v1 = [:^^TCls<1>:]::s; +int v2 = template [:^^TCls:]<2>::s; // OK, \keyword{template} binds to \grammarterm{splice-scope-specifier} +typename [:^^TCls:]<3>::type v3 = 3; // OK, \keyword{typename} binds to the qualified name +template [:^^TCls:]<3>::type v4 = 4; // OK, \keyword{template} binds to the \grammarterm{splice-scope-specifier} +typename template [:^^TCls:]<3>::type v5 = 5; // OK, same as \tcode{v3} +[:^^TCls:]<3>::type v6 = 6; // error: unexpected \tcode{<} +\end{codeblock} +\end{example} + \pnum A \grammarterm{nested-name-specifier} is \defn{declarative} if it is part of \begin{itemize} @@ -1622,17 +1887,44 @@ a declarative \grammarterm{nested-name-specifier}. \end{itemize} A declarative \grammarterm{nested-name-specifier} -shall not have a \grammarterm{decltype-specifier}. +shall not have a \grammarterm{computed-type-specifier} or +a \grammarterm{splice-scope-specifier}. A declaration that uses a declarative \grammarterm{nested-name-specifier} shall be a friend declaration or inhabit a scope that contains the entity being redeclared or specialized. \pnum -The \grammarterm{nested-name-specifier} \tcode{::} nominates +The entity designated by a \grammarterm{nested-name-specifier} +is determined as follows: +\begin{itemize} +\item +The \grammarterm{nested-name-specifier} \tcode{::} designates the global namespace. +\item A \grammarterm{nested-name-specifier} with a \grammarterm{computed-type-specifier} -nominates the type denoted by the \grammarterm{computed-type-specifier}, +designates the same type designated by the \grammarterm{computed-type-specifier}, which shall be a class or enumeration type. +\item +For a \grammarterm{nested-name-specifier} of +the form \tcode{\grammarterm{splice-specifier} ::}, +the \grammarterm{splice-specifier} shall designate +a class or enumeration type or a namespace. +The \grammarterm{nested-name-specifier} designates the same entity +as the \grammarterm{splice-specifier}. +\item +For a \grammarterm{nested-name-specifier} of +the form +\tcode{\opt{\keyword{template}} \grammarterm{splice-specialization-specifier} ::}, +the \grammarterm{splice-specifier} of +the \grammarterm{splice-specialization-specifier} shall designate +a class template or an alias template $T$. +Letting $S$ be the specialization of $T$ +corresponding to the template argument list of +the \grammarterm{splice-specialization-specifier}, +$S$ shall either be a class template specialization or +an alias template specialization that denotes a class or enumeration type. +The \grammarterm{nested-name-specifier} designates the underlying entity of $S$. +\item If a \grammarterm{nested-name-specifier} $N$ is declarative and has a \grammarterm{simple-template-id} with a template argument list $A$ @@ -1643,22 +1935,24 @@ \item If $A$ is the template argument list\iref{temp.arg} of the corresponding \grammarterm{template-head} $H$\iref{temp.mem}, -$N$ nominates the primary template of $T$; +$N$ designates the primary template of $T$; $H$ shall be equivalent to the \grammarterm{template-head} of $T$\iref{temp.over.link}. \item -Otherwise, $N$ nominates the partial specialization\iref{temp.spec.partial} of $T$ +Otherwise, $N$ designates the partial specialization\iref{temp.spec.partial} of $T$ whose template argument list is equivalent to $A$\iref{temp.over.link}; the program is ill-formed if no such partial specialization exists. \end{itemize} -Any other \grammarterm{nested-name-specifier} nominates -the entity denoted by its +\item +Any other \grammarterm{nested-name-specifier} designates +the entity denotes by its \grammarterm{type-name}, \grammarterm{namespace-name}, \grammarterm{identifier}, or \grammarterm{simple-template-id}. If the \grammarterm{nested-name-specifier} is not declarative, the entity shall not be a template. +\end{itemize} \pnum A \grammarterm{qualified-id} shall not be of the form @@ -1670,7 +1964,32 @@ \pnum The result of a \grammarterm{qualified-id} $Q$ is the entity it denotes\iref{basic.lookup.qual}. -The type of the expression is the type of the result. + +\pnum +If $Q$ appears +in the predicate of a contract assertion $C$\iref{basic.contract} +and the entity is +\begin{itemize} +\item +a variable +declared outside of $C$ +of object type \tcode{T}, +\item +a variable +declared outside of $C$ +of type ``reference to \tcode{T}'', or +\item +a structured binding of type \tcode{T} +whose corresponding variable +is declared outside of $C$, +\end{itemize} +then the type of the expression is \keyword{const}~\tcode{T}. + + +\pnum +Otherwise, the type of the expression is the type of the result. + +\pnum The result is an lvalue if the member is \begin{itemize} \item @@ -1770,10 +2089,11 @@ \begin{bnf} \nontermdef{lambda-declarator}\br 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 + \bnfindent \opt{function-contract-specifier-seq}\br + noexcept-specifier \opt{attribute-specifier-seq} \opt{trailing-return-type} \opt{function-contract-specifier-seq}\br + \opt{trailing-return-type} \opt{function-contract-specifier-seq}\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} + \bnfindent \opt{trailing-return-type} \opt{requires-clause} \opt{function-contract-specifier-seq} \end{bnf} \begin{bnf} @@ -1786,8 +2106,7 @@ \begin{bnf} \nontermdef{lambda-specifier-seq}\br - lambda-specifier\br - lambda-specifier lambda-specifier-seq + lambda-specifier \opt{lambda-specifier-seq} \end{bnf} \pnum @@ -1874,8 +2193,9 @@ 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 +auto x = [](int i, auto a) { return i; }; // OK, a generic lambda +auto y = [](this auto self, int i) { return i; }; // OK, a generic lambda +auto z = [](int i) { return i; }; // OK, a generic lambda \end{codeblock} \end{example} @@ -1887,6 +2207,10 @@ called the \defn{closure type}, whose properties are described below. +\pnum +The closure type is not complete +until the end of its corresponding \grammarterm{compound-statement}. + \pnum The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding @@ -1899,16 +2223,17 @@ \end{note} \pnum -The closure type is not an aggregate type\iref{dcl.init.aggr} and -not a structural type\iref{term.structural.type}. +The closure type is not an aggregate type\iref{dcl.init.aggr}; +it is a structural type\iref{term.structural.type} if and only if +the lambda has no \grammarterm{lambda-capture}. An implementation may define the closure type differently from what is described below provided this does not alter the observable behavior of the program other than by changing: \begin{itemize} \item the size and/or alignment of the closure type, - -\item whether the closure type is trivially copyable\iref{class.prop}, or - +\item whether the closure type is trivially copyable\iref{class.prop}, +\item whether the closure type is trivially relocatable\iref{class.prop}, +\item whether the closure type is replaceable\iref{class.prop}, or \item whether the closure type is a standard-layout class\iref{class.prop}. \end{itemize} @@ -1925,6 +2250,8 @@ respectively, and whose \grammarterm{template-parameter-list} consists of the specified \grammarterm{template-parameter-list}, if any. +The function call operator or the function call operator template are +direct members of the closure type. The \grammarterm{requires-clause} of the function call operator template is the \grammarterm{requires-clause} immediately following \tcode{<}~\grammarterm{template-parameter-list}{}~\tcode{>}, if any. @@ -1971,7 +2298,7 @@ \item the closure type, \item -a class type derived from the closure type, or +a class type publicly and unambiguously derived from the closure type, or \item a reference to a possibly cv-qualified such type. \end{itemize} @@ -2003,8 +2330,9 @@ followed by \keyword{mutable} and the \grammarterm{lambda-declarator} does not contain an explicit object parameter. -It is neither virtual nor declared \tcode{volatile}. Any -\grammarterm{noexcept-specifier} specified on a \grammarterm{lambda-expression} +It is neither virtual nor declared \tcode{volatile}. +Any \grammarterm{noexcept-specifier} or \grammarterm{function-contract-specifier}\iref{dcl.contract.func} +specified on a \grammarterm{lambda-expression} 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. @@ -2083,9 +2411,55 @@ \end{example} \end{note} +\pnum +If all potential references +to a local entity implicitly captured by a \grammarterm{lambda-expression} $L$ +occur within the function contract assertions\iref{dcl.contract.func} +of the call operator or operator template of $L$ +or within \grammarterm{assertion-statement}s\iref{stmt.contract.assert} +within the body of $L$, +the program is ill-formed. +\begin{note} +Adding a contract assertion to an existing \Cpp{} program cannot +cause additional captures. +\end{note} +\begin{example} +\begin{codeblock} +static int i = 0; + +void test() { + auto f1 = [=] pre(i > 0) {}; // OK, no local entities are captured. + + int i = 1; + auto f2 = [=] pre(i > 0) {}; // error: cannot implicitly capture \tcode{i} here + auto f3 = [i] pre(i > 0) {}; // OK, \tcode{i} is captured explicitly. + + auto f4 = [=] { + contract_assert(i > 0); // error: cannot implicitly capture \tcode{i} here + }; + + auto f5 = [=] { + contract_assert(i > 0); // OK, \tcode{i} is referenced elsewhere. + (void)i; + }; + + auto f6 = [=] pre( // \#1 + []{ + bool x = true; + return [=]{ return x; }(); // OK, \#1 captures nothing. + }()) {}; + + bool y = true; + auto f7 = [=] pre([=]{ return y; }()); // error: outer capture of \tcode{y} is invalid. +} +\end{codeblock} +\end{example} + + \pnum The closure type for a non-generic \grammarterm{lambda-expression} with no \grammarterm{lambda-capture} +and no explicit object parameter\iref{dcl.fct} whose constraints (if any) are satisfied has a conversion function to pointer to function with \Cpp{} language linkage\iref{dcl.link} having @@ -2095,9 +2469,9 @@ has a non-throwing exception specification. If the function call operator is a static member function, then the value returned by this conversion function is -the address of the function call operator. +a pointer to the function call operator. Otherwise, the value returned by this conversion function -is the address of a function \tcode{F} that, when invoked, +is a pointer to a function \tcode{F} that, when invoked, has the same effect as invoking the closure type's function call operator on a default-constructed instance of the closure type. \tcode{F} is a constexpr function @@ -2106,7 +2480,9 @@ if the function call operator is an immediate function. \pnum -For a generic lambda with no \grammarterm{lambda-capture}, the closure type has a +For a generic lambda with no \grammarterm{lambda-capture} +and no explicit object parameter\iref{dcl.fct}, +the closure type has a conversion function template to pointer to function. The conversion function template has the same invented template parameter list, and the pointer to function has the same @@ -2138,7 +2514,7 @@ @\commentellip@ } template using fptr_t = - decltype(lambda_call_operator_invoker(declval())) (*)(T); + decltype(lambda_call_operator_invoker(declval())) (*)(T); template operator fptr_t() const { return &lambda_call_operator_invoker; } @@ -2170,10 +2546,10 @@ If the function call operator template is a static member function template, then the value returned by any given specialization of this conversion function template is -the address of the corresponding function call operator template specialization. +a pointer to the corresponding function call operator template specialization. Otherwise, the value returned by any given specialization of this conversion function -template is the address of a function \tcode{F} that, when invoked, has the same +template is a pointer to a function \tcode{F} that, when invoked, has the same effect as invoking the generic lambda's corresponding function call operator template specialization on a default-constructed instance of the closure type. \tcode{F} is a constexpr function @@ -2228,7 +2604,9 @@ }; \end{codeblock} \end{example} -Further, a variable \mname{func} is implicitly defined at the beginning of +Unless the \grammarterm{compound-statement} is +that of a \grammarterm{consteval-block-declaration}\iref{dcl.pre}, +a variable \mname{func} is implicitly defined at the beginning of the \grammarterm{compound-statement} of the \grammarterm{lambda-expression}, with semantics as described in~\ref{dcl.fct.def.general}. @@ -2288,7 +2666,7 @@ identifier \opt{\terminal{...}}\br \terminal{\&} identifier \opt{\terminal{...}}\br \keyword{this}\br - \terminal{*} \terminal{this} + \terminal{*} \keyword{this} \end{bnf} \begin{bnf} @@ -2299,7 +2677,7 @@ \pnum The body of a \grammarterm{lambda-expression} may refer to local entities -of enclosing block scopes by capturing those entities, as described +of enclosing scopes by capturing those entities, as described below. \pnum @@ -2315,7 +2693,7 @@ or ``\tcode{* \keyword{this}}''. \begin{note} The form \tcode{[\&,\keyword{this}]} is redundant but accepted -for compatibility with ISO \CppXIV{}. +for compatibility with \CppXIV{}. \end{note} Ignoring appearances in \grammarterm{initializer}{s} of \grammarterm{init-capture}{s}, an identifier or @@ -2340,10 +2718,19 @@ A \grammarterm{lambda-expression} shall not have a \grammarterm{capture-default} or \grammarterm{simple-capture} in its \grammarterm{lambda-introducer} -unless its innermost enclosing scope is a block scope\iref{basic.scope.block} -or it appears within a default member initializer +unless +\begin{itemize} +\item +its innermost enclosing scope is a block scope\iref{basic.scope.block}, +\item +it appears within a default member initializer and its innermost enclosing scope is -the corresponding class scope\iref{basic.scope.class}. +the corresponding class scope\iref{basic.scope.class}, or +\item +it appears within a contract assertion +and its innermost enclosing scope +is the corresponding contract-assertion scope\iref{basic.scope.contract}. +\end{itemize} \pnum The \grammarterm{identifier} in a \grammarterm{simple-capture} @@ -2581,8 +2968,8 @@ \item it is explicitly captured with a capture that is not of the form \keyword{this}, -\tcode{\&} \grammarterm{identifier}, or -\tcode{\&} \grammarterm{identifier} \grammarterm{initializer}. +\tcode{\&} \grammarterm{identifier} \opt{\tcode{...}}, or +\tcode{\&} \opt{\tcode{...}} \grammarterm{identifier} \grammarterm{initializer}. \end{itemize} For each entity captured by copy, an unnamed non-static data member is declared in the closure type. The declaration order of @@ -2612,7 +2999,7 @@ void g() { const int N = 10; [=] { - int arr[N]; // OK, not an odr-use, refers to automatic variable + int arr[N]; // OK, not an odr-use, refers to variable with automatic storage duration f(&N); // OK, causes \tcode{N} to be captured; \tcode{\&N} points to // the corresponding member of the closure type }; @@ -2800,6 +3187,9 @@ } \end{codeblock} \end{example} + +\pnum +A fold expression is a pack expansion. \indextext{expression!fold|)}% \rSec2[expr.prim.req]{Requires expressions} @@ -2824,15 +3214,14 @@ \end{bnf} \begin{bnf} -\microtypesetup{protrusion=false}\obeyspaces +\microtypesetup{protrusion=false} \nontermdef{requirement-body}\br \terminal{\{} requirement-seq \terminal{\}} \end{bnf} \begin{bnf} \nontermdef{requirement-seq}\br - requirement\br - requirement requirement-seq + requirement \opt{requirement-seq} \end{bnf} \begin{bnf} @@ -2846,8 +3235,6 @@ \pnum A \grammarterm{requires-expression} is a prvalue of type \tcode{bool} whose value is described below. -Expressions appearing within a \grammarterm{requirement-body} -are unevaluated operands\iref{term.unevaluated.operand}. \pnum \begin{example} @@ -2875,9 +3262,11 @@ \pnum A \grammarterm{requires-expression} may introduce local parameters using a -\grammarterm{parameter-declaration-clause}\iref{dcl.fct}. +\grammarterm{parameter-declaration-clause}. A local parameter of a \grammarterm{requires-expression} shall not have a default argument. +The type of such a parameter is determined as specified for +a function parameter in~\ref{dcl.fct}. These parameters have no linkage, storage, or lifetime; they are only used as notation for the purpose of defining \grammarterm{requirement}s. The \grammarterm{parameter-declaration-clause} of a @@ -2889,6 +3278,10 @@ concept C = requires(T t, ...) { // error: terminates with an ellipsis t; }; +template +concept C2 = requires(T p[2]) { + (decltype(p))nullptr; // OK, \tcode{p} has type ``pointer to \tcode{T}'' +}; \end{codeblock} \end{example} @@ -2933,10 +3326,10 @@ \pnum A \grammarterm{simple-requirement} asserts the validity of an \grammarterm{expression}. +The \grammarterm{expression} is an unevaluated operand. \begin{note} The enclosing \grammarterm{requires-expression} will evaluate to \keyword{false} if substitution of template arguments into the \grammarterm{expression} fails. -The \grammarterm{expression} is an unevaluated operand\iref{term.unevaluated.operand}. \end{note} \begin{example} \begin{codeblock} @@ -2960,13 +3353,16 @@ \begin{bnf} \nontermdef{type-requirement}\br - \keyword{typename} \opt{nested-name-specifier} type-name \terminal{;} + \keyword{typename} \opt{nested-name-specifier} type-name \terminal{;}\br + \keyword{typename} splice-specifier\br + \keyword{typename} splice-specialization-specifier \end{bnf} \pnum A \grammarterm{type-requirement} asserts the validity of a type. The component names of a \grammarterm{type-requirement} are those of its -\grammarterm{nested-name-specifier} (if any) and \grammarterm{type-name}. +\grammarterm{nested-name-specifier} (if any) and +\grammarterm{type-name} (if any). \begin{note} The enclosing \grammarterm{requires-expression} will evaluate to \keyword{false} if substitution of template arguments fails. @@ -2977,10 +3373,12 @@ template using Ref = T&; template concept C = requires { - typename T::inner; // required nested member name - typename S; // required valid\iref{temp.names} \grammarterm{template-id}; - // fails if \tcode{T::type} does not exist as a type to which \tcode{0} can be implicitly converted - typename Ref; // required alias template substitution, fails if \tcode{T} is void + typename T::inner; // required nested member name + typename S; // required valid\iref{temp.names} \grammarterm{template-id}; fails if \tcode{T::type} does not exist as a type + // to which \tcode{0} can be implicitly converted + typename Ref; // required alias template substitution, fails if \tcode{T} is void + typename [:T::r1:]; // fails if \tcode{T::r1} is not a reflection of a type + typename [:T::r2:]; // fails if \tcode{T::r2} is not a reflection of a template \tcode{Z} for which \tcode{Z} is a type }; \end{codeblock} \end{example} @@ -3004,7 +3402,9 @@ \pnum A \grammarterm{compound-requirement} asserts properties -of the \grammarterm{expression} $E$. Substitution +of the \grammarterm{expression} $E$. +The \grammarterm{expression} is an unevaluated operand. +Substitution of template arguments (if any) and verification of semantic properties proceed in the following order: @@ -3113,6 +3513,150 @@ \indextext{expression!requires|)} \indextext{expression!primary|)} +\rSec2[expr.prim.splice]{Expression splicing} + +\begin{bnf} +\nontermdef{splice-expression}\br + splice-specifier\br + \keyword{template} splice-specifier\br + \keyword{template} splice-specialization-specifier +\end{bnf} + +\pnum +A \grammarterm{splice-specifier} +or \grammarterm{splice-specialization-specifier} +immediately followed by \tcode{::} or preceded by \keyword{typename} +is never interpreted as part of a \grammarterm{splice-expression}. +\begin{example} +\begin{codeblock} +struct S { static constexpr int a = 1; }; +template struct TCls { static constexpr int b = 2; }; + +constexpr int c = [:^^S:]::a; // OK, \tcode{[:\caret\caret S:]} is not an expression +constexpr int d = template [:^^TCls:]::b; // OK, \tcode{template [:\caret\caret TCls:]} is not an expression +template constexpr int e = [:V:]; // OK +constexpr int f = template [:^^e:]<^^S::a>; // OK + +constexpr auto g = typename [:^^int:](42); // OK, \tcode{typename [:\caret\caret int:]} is a \grammarterm{splice-type-specifier} + +constexpr auto h = ^^g; +constexpr auto i = e<[:^^h:]>; // error: unparenthesized \grammarterm{splice-expression} used as template argument +constexpr auto j = e<([:^^h:])>; // OK +\end{codeblock} +\end{example} + +\pnum +For a \grammarterm{splice-expression} of the form \grammarterm{splice-specifier}, +let $S$ be the construct designated by \grammarterm{splice-specifier}. +\begin{itemize} +\item +The expression is ill-formed if $S$ is +\begin{itemize} +\item +a constructor, +\item +a destructor, +\item +an unnamed bit-field, or +\item +a local entity\iref{basic.pre} such that +\begin{itemize} +\item +there is a lambda scope that intervenes +between the expression and the point at which $S$ was introduced and +\item +the expression would be potentially evaluated +if the effect of any enclosing \keyword{typeid} expressions\iref{expr.typeid} +were ignored. +\end{itemize} +\end{itemize} +\item +Otherwise, if $S$ is a function $F$, +the expression denotes an overload set containing all declarations of $F$ +that precede either the expression or +the point immediately following the \grammarterm{class-specifier} of +the outermost class for which the expression is in a complete-class context; +overload resolution is performed\iref{over.match,over.over}. +\item +Otherwise, if $S$ is an object or a non-static data member, +the expression is an lvalue designating $S$. +The expression has the same type as that of $S$, and +is a bit-field if and only if $S$ is a bit-field. +\begin{note} +The implicit transformation +whereby an \grammarterm{id-expression} denoting a non-static member +becomes a class member access\iref{expr.prim.id} +does not apply to a \grammarterm{splice-expression}. +\end{note} +\item +Otherwise, if $S$ is a variable or a structured binding, +$S$ shall either have static or thread storage duration or +shall inhabit a scope enclosing the expression. +The expression is an lvalue referring to the object or function $X$ +associated with or referenced by $S$, +has the same type as that of $S$, and +is a bit-field if and only if $X$ is a bit-field. +\begin{note} +The type of a \grammarterm{splice-expression} +designating a variable or structured binding of reference type +will be adjusted to a non-reference type\iref{expr.type}. +\end{note} +\item +Otherwise, if $S$ is a value or an enumerator, +the expression is a prvalue that computes $S$ and +whose type is the same as that of $S$. +\item +Otherwise, the expression is ill-formed. +\end{itemize} + +\pnum +For a \grammarterm{splice-expression} of +the form \tcode{\keyword{template} \grammarterm{splice-specifier}}, +the \grammarterm{splice-specifier} shall designate a function template $T$ +that is not a constructor template. +The expression denotes an overload set containing all declarations of $T$ +that precede either the expression or +the point immediately following the \grammarterm{class-specifier} of +the outermost class for which the expression is in a complete-class context; +overload resolution is performed. +\begin{note} +During overload resolution, +candidate function templates undergo template argument deduction and +the resulting specializations are considered as candidate functions. +\end{note} + +\pnum +For a \grammarterm{splice-expression} of +the form \tcode{template \grammarterm{splice-specialization-specifier}}, +the \grammarterm{splice-specifier} of +the \grammarterm{splice-specialization-specifier} +shall designate a template $T$. +\begin{itemize} +\item +If $T$ is a function template, +the expression denotes an overload set containing all declarations of $T$ +that precede either the expression or +the point immediately following the \grammarterm{class-specifier} of +the outermost class for which the expression is in a complete-class context; +overload resolution is performed\iref{over.match,over.over}. +\item +Otherwise, if $T$ is a variable template, +let $S$ be the specialization of $T$ corresponding to +the template argument list of the \grammarterm{splice-specialization-specifier}. +The expression is an lvalue referring to +the object associated with $S$ and has the same type as that of $S$. +\item +Otherwise, the expression is ill-formed. +\end{itemize} +\begin{note} +Class members are accessible from any point +when designated by \grammarterm{splice-expression}s\iref{class.access.base}. +A class member access expression\iref{expr.ref} +whose right operand is a \grammarterm{splice-expression} is ill-formed +if the left operand (considered as a pointer) cannot be implicitly converted +to a pointer to the designating class of the right operand. +\end{note} + \rSec1[expr.compound]{Compound expressions} \rSec2[expr.post]{Postfix expressions}% @@ -3132,8 +3676,10 @@ typename-specifier \terminal{(} \opt{expression-list} \terminal{)}\br simple-type-specifier braced-init-list\br typename-specifier braced-init-list\br - postfix-expression \terminal{.} \opt{\terminal{template}} id-expression\br - postfix-expression \terminal{->} \opt{\terminal{template}} id-expression\br + postfix-expression \terminal{.} \opt{\keyword{template}} id-expression\br + postfix-expression \terminal{.} splice-expression\br + postfix-expression \terminal{->} \opt{\keyword{template}} id-expression\br + postfix-expression \terminal{->} splice-expression\br postfix-expression \terminal{++}\br postfix-expression \terminal{--}\br \keyword{dynamic_cast} \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br @@ -3169,12 +3715,12 @@ a possibly empty, comma-separated list of \grammarterm{initializer-clause}s that constitute the arguments to the subscript operator. The \grammarterm{postfix-expression} and -the initialization of the object parameter of -any applicable subscript operator function is sequenced before +the initialization of the object parameter\iref{dcl.fct} of +any applicable subscript operator function\iref{over.sub} is sequenced before each expression in the \grammarterm{expression-list} and also before -any default argument. +any default argument\iref{dcl.fct.default}. The initialization of a non-object parameter of -a subscript operator function \tcode{S}\iref{over.sub}, +a subscript operator function \tcode{S}, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other non-object parameter of \tcode{S}. @@ -3270,14 +3816,20 @@ of the class member access\iref{expr.ref,basic.life}. \pnum +A type $\tcode{T}_\text{call}$ is +\defn{call-compatible} with a function type $\tcode{T}_\text{func}$ +if $\tcode{T}_\text{call}$ is the same type as $\tcode{T}_\text{func}$ or +if the type ``pointer to $\tcode{T}_\text{func}$'' can be +converted to type ``pointer to $\tcode{T}_\text{call}$'' +via a function pointer conversion\iref{conv.fctptr}. Calling a function through an -expression whose function type \tcode{E} is different -from the function type \tcode{F} of the called function's -definition results in undefined behavior -unless the type ``pointer to \tcode{F}'' can be converted -to the type ``pointer to \tcode{E}'' via a function pointer conversion\iref{conv.fctptr}. +expression whose function type +is not call-compatible with the +type of the called function's +definition results in undefined behavior. \begin{note} -The exception applies when the expression has the type of a +This requirement allows the case +when the expression has the type of a potentially-throwing function, but the called function has a non-throwing exception specification, and the function types are otherwise the same. @@ -3289,7 +3841,9 @@ \indextext{initialization!parameter}% When a function is called, each parameter\iref{dcl.fct} is initialized\iref{dcl.init,class.copy.ctor} with -its corresponding argument. +its corresponding argument, +and each precondition assertion of the function +is evaluated\iref{dcl.contract.func}. If the function is an explicit object member function and there is an implied object argument\iref{over.call.func}, the list of provided arguments is preceded by the implied object argument @@ -3303,9 +3857,11 @@ \end{codeblock} \end{example} If the function is an implicit object member -function, the \keyword{this} parameter of the function\iref{expr.prim.this} -is initialized with a pointer to the object of the call, converted -as if by an explicit type conversion\iref{expr.cast}. +function, +the object expression of the class member access shall be a glvalue and +the implicit object parameter of the function\iref{over.match.funcs} +is initialized with that glvalue, +converted as if by an explicit type conversion\iref{expr.cast}. \begin{note} There is no access or ambiguity checking on this conversion; the access checking and disambiguation are done as part of the (possibly implicit) @@ -3320,10 +3876,12 @@ a type. However, it prevents a passed-by-value parameter to have an incomplete or abstract class type. \end{note} -It is \impldef{whether the lifetime of a parameter ends when the callee -returns or at the end of the enclosing full-expression} whether the -lifetime of a parameter ends when the function in which it is defined -returns or at the end of the enclosing full-expression. +It is \impldef{whether a parameter is destroyed when the function +exits or at the end of the enclosing full-expression} +whether a parameter is destroyed +when the function in which it is defined exits\iref{stmt.return, except.ctor, expr.await} +or at the end of the enclosing full-expression; +parameters are always destroyed in the reverse order of their construction. The initialization and destruction of each parameter occurs within the context of the full-expression\iref{intro.execution} where the function call appears. @@ -3345,9 +3903,21 @@ The \grammarterm{postfix-expression} is sequenced before each \grammarterm{expression} in the \grammarterm{expression-list} and any default argument. -The initialization of a parameter, +The initialization of a parameter or, +if the implementation introduces any temporary objects +to hold the values of function parameters\iref{class.temporary}, +the initialization of those temporaries, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter. +These evaluations are +sequenced before +the evaluation of the precondition assertions of the function, +which are evaluated in sequence\iref{dcl.contract.func}. +For any temporaries +introduced to hold the values of function parameters, +the initialization of the parameter objects from those temporaries +is indeterminately sequenced with respect to +the evaluation of each precondition assertion. \begin{note} All side effects of argument evaluations are sequenced before the function is @@ -3393,6 +3963,18 @@ chosen function, the value returned from the final overrider is converted to the return type of the statically chosen function. +\pnum +When the called function exits normally\iref{stmt.return,expr.await}, +all postcondition assertions of the function +are evaluated in sequence\iref{dcl.contract.func}. +If the implementation introduces any temporary objects +to hold the result value as specified in \ref{class.temporary}, +the evaluation of each postcondition assertion +is indeterminately sequenced with respect to +the initialization of any of those temporaries or the result object. +These evaluations, in turn, are sequenced before +the destruction of any function parameters. + \pnum \begin{note} \indextext{type checking!argument}% @@ -3429,7 +4011,7 @@ \indextext{ellipsis!conversion sequence}% When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the -argument by invoking \tcode{va_arg}\iref{support.runtime}. +argument by invoking \libmacro{va_arg}\iref{support.runtime}. \begin{note} This paragraph does not apply to arguments passed to a function parameter pack. Function parameter packs are expanded during template instantiation\iref{temp.variadic}, @@ -3469,6 +4051,9 @@ if the result type is an lvalue reference type or an rvalue reference to function type, an xvalue if the result type is an rvalue reference to object type, and a prvalue otherwise. +If it is a non-void prvalue, +the type of the function call expression shall be complete, +except as specified in \ref{dcl.type.decltype}. \rSec3[expr.type.conv]{Explicit type conversion (functional notation)} @@ -3495,6 +4080,44 @@ Otherwise, if the type contains a placeholder type, it is replaced by the type determined by placeholder type deduction\iref{dcl.type.auto.deduct}. +Let \tcode{T} denote the resulting type. +Then: + +\begin{itemize} +\item +If the initializer is a parenthesized single expression, +the type conversion expression is equivalent +to the corresponding cast +expression\iref{expr.cast}. + +\item +\indextext{type!incomplete}% +Otherwise, if \tcode{T} is \cv{}~\keyword{void}, +the initializer shall be \tcode{()} or \tcode{\{\}} +(after pack expansion, if any), and +the expression is a prvalue of type \keyword{void} +that performs no initialization. + +\item +Otherwise, if \tcode{T} is a reference type, +the expression has the same effect as +direct-initializing an invented variable \tcode{t} of type \tcode{T} from +the initializer and then +using \tcode{t} as the result of the expression; +the result is an lvalue if +\tcode{T} is an lvalue reference type or +an rvalue reference to function type and +an xvalue otherwise. + +\item +Otherwise, +the expression is a prvalue of type \tcode{T} +whose result object is direct-initialized\iref{dcl.init} +with the initializer. +\end{itemize} + +If the initializer is a parenthesized optional \grammarterm{expression-list}, +\tcode{T} shall not be an array type. \begin{example} \begin{codeblock} struct A {}; @@ -3509,24 +4132,6 @@ \end{codeblock} \end{example} -\pnum -If the initializer is a parenthesized single expression, -the type conversion expression is equivalent -to the corresponding cast -expression\iref{expr.cast}. -\indextext{type!incomplete}% -Otherwise, if the type is \cv{}~\keyword{void} -and the initializer is \tcode{()} or \tcode{\{\}} -(after pack expansion, if any), -the expression is a prvalue of type \keyword{void} -that performs no initialization. -Otherwise, -the expression is a prvalue of the specified type -whose result object is direct-initialized\iref{dcl.init} -with the initializer. -If the initializer is a parenthesized optional \grammarterm{expression-list}, -the specified type shall not be an array type. - \rSec3[expr.ref]{Class member access} \pnum @@ -3543,21 +4148,12 @@ A postfix expression followed by a dot \tcode{.} or an arrow \tcode{->}, optionally followed by the keyword \keyword{template}, and then followed by an -\grammarterm{id-expression}, is a postfix expression. The postfix -expression before the dot or arrow is evaluated; -\begin{footnote} -If the class member -access expression is evaluated, the subexpression evaluation happens even if the -result is unnecessary to determine -the value of the entire postfix expression, for example if the -\grammarterm{id-expression} denotes a static member. -\end{footnote} -the result of that evaluation, together with the -\grammarterm{id-expression}, determines the result of the entire postfix -expression. +\grammarterm{id-expression} or a \grammarterm{splice-expression}, +is a postfix expression. \begin{note} -If the keyword \keyword{template} is used, -the following unqualified name +If the keyword \keyword{template} is used and +followed by an \grammarterm{id-expression}, +the unqualified name is considered to refer to a template\iref{temp.names}. If a \grammarterm{simple-template-id} results and is followed by a \tcode{::}, the \grammarterm{id-expression} is a \grammarterm{qualified-id}. @@ -3565,20 +4161,39 @@ \pnum \indextext{type!incomplete}% -For the first option (dot) the first expression shall be a glvalue. -For the second option (arrow) the first expression +For a dot that is followed by an expression +that designates a static member or an enumerator, +the first expression is a discarded-value expression\iref{expr.context}; +if the expression after the dot designates a non-static data member, +the first expression shall be a glvalue. +A postfix expression that is followed by an arrow shall be a prvalue having pointer type. The expression \tcode{E1->E2} is converted to the equivalent form \tcode{(*(E1)).E2}; the remainder of -\ref{expr.ref}~will address only the first option (dot). +\ref{expr.ref}~will address only the form using a dot. \begin{footnote} Note that \tcode{(*(E1))} is an lvalue. \end{footnote} \pnum -Abbreviating -\grammarterm{postfix-expression}\tcode{.}\grammarterm{id-expression} +The postfix expression before the dot is evaluated; +\begin{footnote} +If the class member +access expression is evaluated, the subexpression evaluation happens even if the +result is unnecessary to determine +the value of the entire postfix expression, for example if the +\grammarterm{id-expression} denotes a static member. +\end{footnote} +the result of that evaluation, +together with +the \grammarterm{id-expression} or \grammarterm{splice-expression}, +determines the result of the entire postfix expression. + +\pnum +Abbreviating +\grammarterm{postfix-expression}\tcode{.}\grammarterm{id-expression} or +\grammarterm{postfix-expression}\tcode{.}\grammarterm{splice-expression} as \tcode{E1.E2}, \tcode{E1} is called the \defn{object expression}. If the object expression is of scalar type, \tcode{E2} shall name the pseudo-destructor @@ -3603,7 +4218,14 @@ \end{note} \pnum -If \tcode{E2} is a bit-field, \tcode{E1.E2} is a bit-field. The +If \tcode{E2} is a \grammarterm{splice-expression}, +then let \tcode{T1} be the type of \tcode{E1}. +\tcode{E2} shall designate either +a member of \tcode{T1} or +a direct base class relationship $(\tcode{T1}, \tcode{B})$. + +\pnum +If \tcode{E2} designates a bit-field, \tcode{E1.E2} is a bit-field. The type and value category of \tcode{E1.E2} are determined as follows. In the remainder of~\ref{expr.ref}, \cvqual{cq} represents either \keyword{const} or the absence of \keyword{const} and \cvqual{vq} represents @@ -3612,24 +4234,26 @@ in~\ref{basic.type.qualifier}. \pnum -If \tcode{E2} is declared to have type ``reference to \tcode{T}'', then +If \tcode{E2} designates an entity +that is declared to have type ``reference to \tcode{T}'', then \tcode{E1.E2} is an lvalue of type \tcode{T}. -If \tcode{E2} is a static data member, +In that case, if \tcode{E2} designates a static data member, \tcode{E1.E2} designates the object or function to which the reference is bound, otherwise \tcode{E1.E2} designates the object or function to which the corresponding reference member of \tcode{E1} is bound. Otherwise, one of the following rules applies. - \begin{itemize} -\item If \tcode{E2} is a static data member and the type of \tcode{E2} +\item +If \tcode{E2} designates a static data member and the type of \tcode{E2} is \tcode{T}, then \tcode{E1.E2} is an lvalue; the expression designates the named member of the class. The type of \tcode{E1.E2} is \tcode{T}. -\item If \tcode{E2} is a non-static data member and the type of +\item +Otherwise, if \tcode{E2} designates a non-static data member and the type of \tcode{E1} is ``\cvqual{cq1 vq1} \tcode{X}'', and the type of \tcode{E2} is ``\cvqual{cq2 vq2} \tcode{T}'', the expression designates the corresponding -member subobject of the object designated by the first expression. If \tcode{E1} +member subobject of the object designated by \tcode{E1}. If \tcode{E1} is an lvalue, then \tcode{E1.E2} is an lvalue; otherwise \tcode{E1.E2} is an xvalue. Let the notation \cvqual{vq12} stand for the ``union'' of @@ -3637,25 +4261,28 @@ is \tcode{volatile}, then \cvqual{vq12} is \keyword{volatile}. Similarly, let the notation \cvqual{cq12} stand for the ``union'' of \cvqual{cq1} and \cvqual{cq2}; that is, if \cvqual{cq1} or \cvqual{cq2} is -\keyword{const}, then \cvqual{cq12} is \keyword{const}. If \tcode{E2} is -declared to be a \keyword{mutable} member, then the type of \tcode{E1.E2} -is ``\cvqual{vq12} \tcode{T}''. If \tcode{E2} is not declared to be a -\keyword{mutable} member, then the type of \tcode{E1.E2} is -``\cvqual{cq12} \cvqual{vq12} \tcode{T}''. +\keyword{const}, then \cvqual{cq12} is \keyword{const}. +If the entity designated by \tcode{E2} +is declared to be a \keyword{mutable} member, +then the type of \tcode{E1.E2} is ``\cvqual{vq12} \tcode{T}''. +If the entity designated by \tcode{E2} +is not declared to be a \keyword{mutable} member, +then the type of \tcode{E1.E2} is ``\cvqual{cq12} \cvqual{vq12} \tcode{T}''. -\item If \tcode{E2} is an overload set, +\item +Otherwise, if \tcode{E2} denotes an overload set, the expression shall be the (possibly-parenthesized) left-hand operand of a member function call\iref{expr.call}, and function overload resolution\iref{over.match} is used to select the function to which \tcode{E2} refers. The type of \tcode{E1.E2} is the type of \tcode{E2} and \tcode{E1.E2} refers to the function referred to by \tcode{E2}. - \begin{itemize} -\item If \tcode{E2} refers to a static member function, +\item +If \tcode{E2} refers to a static member function, \tcode{E1.E2} is an lvalue. - -\item Otherwise (when \tcode{E2} refers to a non-static member function), +\item +Otherwise (when \tcode{E2} refers to a non-static member function), \tcode{E1.E2} is a prvalue. \begin{note} Any redundant set of parentheses surrounding the expression @@ -3663,26 +4290,68 @@ \end{note} \end{itemize} -\item If \tcode{E2} is a nested type, the expression \tcode{E1.E2} is -ill-formed. +\item +Otherwise, if \tcode{E2} designates a nested type, +the expression \tcode{E1.E2} is ill-formed. -\item If \tcode{E2} is a member enumerator and the type of \tcode{E2} +\item +Otherwise, if \tcode{E2} designates a member enumerator and the type of \tcode{E2} is \tcode{T}, the expression \tcode{E1.E2} is a prvalue of type \tcode{T} whose value is the value of the enumerator. + +\item +Otherwise, if \tcode{E2} designates a direct base class relationship $(D, B)$ +and the type of \tcode{E1} is \cv{} \tcode{T}, +the expression designates the direct base class subobject of type $B$ +of the object designated by \tcode{E1}. +If \tcode{E1} is an lvalue, +then \tcode{E1.E2} is an lvalue; +otherwise, \tcode{E1.E2} is an xvalue. +The type of \tcode{E1.E2} is ``\cv{} \tcode{$B$}''. +\begin{note} +This can only occur in an expression of the form \tcode{e1.[:e2:]}. +\end{note} +\begin{example} +\begin{codeblock} +struct B { + int b; +}; +struct C : B { + int get() const { return b; } +}; +struct D : B, C { }; + +constexpr int f() { + D d = {1, {}}; + + // \tcode{b} unambiguously refers to the direct base class of type \tcode{B}, + // not the indirect base class of type \tcode{B} + B& b = d.[: std::meta::bases_of(^^D, std::meta::access_context::current())[0] :]; + b.b += 10; + return 10 * b.b + d.get(); +} +static_assert(f() == 110); +\end{codeblock} +\end{example} + +\item +Otherwise, the program is ill-formed. \end{itemize} \pnum -If \tcode{E2} is a non-static member, -the program is ill-formed if the class of which \tcode{E2} is -directly a member is an ambiguous base\iref{class.member.lookup} of -the naming class\iref{class.access.base} of \tcode{E2}. +If \tcode{E2} designates a non-static member +(possibly after overload resolution), +the program is ill-formed if the class of which \tcode{E2} designates +a direct member is an ambiguous base\iref{class.member.lookup} of +the designating class\iref{class.access.base} of \tcode{E2}. \begin{note} The program is also ill-formed if the naming class is an ambiguous base of the class type of the object expression; see~\ref{class.access.base}. \end{note} \pnum -If \tcode{E2} is a non-static member and +If \tcode{E2} designates a non-static member +(possibly after overload resolution) and the result of \tcode{E1} is an object whose type is not similar\iref{conv.qual} to the type of \tcode{E1}, the behavior is undefined. @@ -3706,8 +4375,8 @@ \indextext{operator!increment}% \indextext{\idxcode{++}|see{operator, increment}}% \indextext{postfix \tcode{++}}% -The value of a postfix \tcode{++} expression is the value of its -operand. +The value of a postfix \tcode{++} expression is the value obtained by +applying the lvalue-to-rvalue conversion\iref{conv.lval} to its operand. \begin{note} The value obtained is a copy of the original value. \end{note} @@ -3717,7 +4386,7 @@ An operand with volatile-qualified type is deprecated; see~\ref{depr.volatile.type}. The value of the operand object is modified\iref{defns.access} -by adding \tcode{1} to it. +as if it were the operand of the prefix \tcode{++} operator\iref{expr.pre.incr}. The \indextext{value computation}% value computation of the \tcode{++} expression is sequenced before the @@ -3732,11 +4401,6 @@ \end{note} The result is a prvalue. The type of the result is the cv-unqualified version of the type of the operand. -If the operand is a bit-field that cannot represent the incremented value, the -resulting value of the bit-field is -\impldefplain{value of bit-field that cannot represent!incremented value}. -See also~\ref{expr.add} -and~\ref{expr.ass}. \pnum \indextext{expression!decrement}% @@ -3812,6 +4476,22 @@ \pnum If \tcode{v} is a null pointer value, the result is a null pointer value. +\pnum +If \tcode{v} has type ``pointer to \cv{}~\tcode{U}'' and +\tcode{v} does not point to an object +whose type is similar\iref{conv.qual} to \tcode{U} and +that is +within its lifetime or +within its period of construction or destruction\iref{class.cdtor}, +the behavior is undefined. +If \tcode{v} is a glvalue of type \tcode{U} and +\tcode{v} does not refer to an object +whose type is similar to \tcode{U} and +that is +within its lifetime or +within its period of construction or destruction, +the behavior is undefined. + \pnum If \tcode{T} is ``pointer to \cv{} \keyword{void}'', then the result is a pointer to the most derived object pointed to by \tcode{v}. @@ -3889,7 +4569,7 @@ \indextext{\idxcode{type_info}}% \indexlibraryglobal{type_info}% \keyword{const} \tcode{std::type_info}\iref{type.info} and dynamic type \keyword{const} -\tcode{std::type_info} or \keyword{const} \term{name} where \term{name} is an +\tcode{std::type_info} or \keyword{const} \tcode{\placeholder{name}} where \tcode{\placeholder{name}} is an \impldef{derived type for \tcode{typeid}} class publicly derived from \tcode{std::type_info} which preserves the behavior described in~\ref{type.info}. @@ -3907,26 +4587,27 @@ a reference to (possibly cv-qualified) class type, that class shall be completely defined. +\pnum +If an \grammarterm{expression} operand of \keyword{typeid} is +a possibly-parenthesized \grammarterm{unary-expression} +whose \grammarterm{unary-operator} is \tcode{*} and +whose operand evaluates to a null pointer value\iref{basic.compound}, +the \keyword{typeid} expression throws an exception\iref{except.throw} +of a type that would match a handler of type +\indextext{\idxcode{bad_typeid}}% +\indexlibraryglobal{bad_typeid}% +\tcode{std::bad_typeid}\iref{bad.typeid}. +\begin{note} +In other contexts, evaluating such a \grammarterm{unary-expression} +results in undefined behavior\iref{expr.unary.op}. +\end{note} + \pnum When \keyword{typeid} is applied to a glvalue whose type is a polymorphic class type\iref{class.virtual}, the result refers to a \tcode{std::type_info} object representing the type of the most derived object\iref{intro.object} (that is, the dynamic type) to which the -glvalue refers. If the glvalue is obtained by applying the -unary \tcode{*} operator to a pointer -\begin{footnote} -If \tcode{p} is an expression of -pointer type, then \tcode{*p}, -\tcode{(*p)}, \tcode{*(p)}, \tcode{((*p))}, \tcode{*((p))}, and so on -all meet this requirement. -\end{footnote} -and the pointer is a null pointer value\iref{basic.compound}, the -\keyword{typeid} expression throws an exception\iref{except.throw} of -a type that would match a handler of type -\indextext{\idxcode{bad_typeid}}% -\indexlibraryglobal{bad_typeid}% -\tcode{std::bad_typeid} -exception\iref{bad.typeid}. +glvalue refers. \pnum When \keyword{typeid} is applied to an expression other than a glvalue of @@ -3994,8 +4675,7 @@ If \tcode{T} is an lvalue reference type or an rvalue reference to function type, the result is an lvalue; if \tcode{T} is an rvalue reference to object type, the result is an xvalue; -otherwise, the result is a prvalue. The \keyword{static_cast} operator shall not cast -away constness\iref{expr.const.cast}. +otherwise, the result is a prvalue. \pnum \indextext{cast!static!reference}% @@ -4041,7 +4721,22 @@ a program that necessitates such a cast is ill-formed. \pnum -An expression $E$ can be explicitly converted to a type \tcode{T} +Any expression can be explicitly converted to type \cv{}~\keyword{void}, +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 +object is +not executed until the usual time, and the value of the object is +preserved for the purpose of executing the destructor. +\end{note} + +\pnum +Otherwise, an expression $E$ can be explicitly converted to a type \tcode{T} if there is an implicit conversion sequence\iref{over.best.ics} from $E$ to \tcode{T}, if overload resolution for a direct-initialization\iref{dcl.init} @@ -4069,56 +4764,11 @@ \end{note} \pnum -Otherwise, the \keyword{static_cast} shall perform one of the conversions -listed below. No other conversion shall be performed explicitly using a -\keyword{static_cast}. - -\pnum -Any expression can be explicitly converted to type \cv{}~\keyword{void}, -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 -object is -not executed until the usual time, and the value of the object is -preserved for the purpose of executing the destructor. -\end{note} - - -\pnum -The inverse of any standard conversion sequence\iref{conv} not containing an -lvalue-to-rvalue\iref{conv.lval}, -array-to-pointer\iref{conv.array}, -function-to-pointer\iref{conv.func}, -null pointer\iref{conv.ptr}, null member pointer\iref{conv.mem}, -boolean\iref{conv.bool}, or -function pointer\iref{conv.fctptr} -conversion, can be performed explicitly using \keyword{static_cast}. A -program is ill-formed if it uses \keyword{static_cast} to perform the -inverse of an ill-formed standard conversion sequence. -\begin{example} -\begin{codeblock} -struct B { }; -struct D : private B { }; -void f() { - static_cast((B*)0); // error: \tcode{B} is a private base of \tcode{D} - static_cast((int D::*)0); // error: \tcode{B} is a private base of \tcode{D} -} -\end{codeblock} -\end{example} - -\pnum -The lvalue-to-rvalue\iref{conv.lval}, +Otherwise, the lvalue-to-rvalue\iref{conv.lval}, array-to-pointer\iref{conv.array}, and function-to-pointer\iref{conv.func} conversions are applied to the -operand. Such a \keyword{static_cast} is subject to the restriction that -the explicit conversion does not cast away -constness\iref{expr.const.cast}, and the following additional rules -for specific cases: +operand, and the conversions that can be performed using \keyword{static_cast} are listed below. +No other conversion can be performed using \keyword{static_cast}. \pnum A value of a scoped enumeration type\iref{dcl.enum} @@ -4220,7 +4870,7 @@ If the original pointer value represents the address \tcode{A} of a byte in memory and \tcode{A} does not satisfy the alignment requirement of \tcode{T}, -then the resulting pointer value is unspecified. +then the resulting pointer value\iref{basic.compound} is unspecified. Otherwise, if the original pointer value points to an object \placeholder{a}, and there is an object \placeholder{b} of type similar to \tcode{T} that is pointer-interconvertible\iref{basic.compound} with \placeholder{a}, @@ -4290,7 +4940,7 @@ A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type -will have its original value; +will have its original value\iref{basic.compound}; \indextext{conversion!implementation-defined pointer integer}% mappings between pointers and integers are otherwise \impldef{conversions between pointers and integers}. @@ -4312,9 +4962,6 @@ \tcode{T2}'' (where \tcode{T1} and \tcode{T2} are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified. -\begin{note} -See also~\ref{conv.ptr} for more details of pointer conversions. -\end{note} \pnum An object pointer @@ -4389,22 +5036,25 @@ \indextext{cast!reinterpret!reference}% \indextext{cast!reference}% \indextext{type pun}% -A glvalue of type \tcode{T1}, +If \tcode{v} is a glvalue of type \tcode{T1}, designating an object or function \placeholder{x}, -can be cast to the type ``reference to \tcode{T2}'' +it can be cast to the type ``reference to \tcode{T2}'' if an expression of type ``pointer to \tcode{T1}'' can be explicitly converted to the type ``pointer to \tcode{T2}'' using a \keyword{reinterpret_cast}. The result is that of \tcode{*reinterpret_cast(p)} where \tcode{p} is a pointer to \placeholder{x} of type ``pointer to \tcode{T1}''. -No temporary is created, no copy is made, and +\begin{note} +No temporary is materialized\iref{conv.rval} or created, +no copy is made, and no constructors\iref{class.ctor} or conversion functions\iref{class.conv} are called. \begin{footnote} This is sometimes referred to as a type pun when the result refers to the same object as the source glvalue. \end{footnote} +\end{note} \rSec3[expr.const.cast]{Const cast} @@ -4418,7 +5068,10 @@ otherwise, the result is a prvalue and the lvalue-to-rvalue\iref{conv.lval}, array-to-pointer\iref{conv.array}, and function-to-pointer\iref{conv.func} standard conversions are -performed on the expression \tcode{v}. Conversions that can be performed explicitly using +performed on the expression \tcode{v}. +The temporary materialization conversion\iref{conv.rval} is not +performed on \tcode{v}, other than as specified below. +Conversions that can be performed explicitly using \keyword{const_cast} are listed below. No other conversion shall be performed explicitly using \keyword{const_cast}. @@ -4429,23 +5082,16 @@ \end{note} \pnum -For two similar types \tcode{T1} and \tcode{T2}\iref{conv.qual}, -a prvalue of type \tcode{T1} may be explicitly +For two similar object pointer or pointer to data member types +\tcode{T1} and \tcode{T2}\iref{conv.qual}, +a prvalue of type \tcode{T1} can be explicitly converted to the type \tcode{T2} using a \keyword{const_cast} if, considering the qualification-decompositions of both types, each $P^1_i$ is the same as $P^2_i$ for all $i$. -The result of a \keyword{const_cast} refers to the original entity. -\begin{example} -\begin{codeblock} -typedef int *A[3]; // array of 3 pointer to \tcode{int} -typedef const int *const CA[3]; // array of 3 const pointer to \tcode{const int} - -CA &&r = A{}; // OK, reference binds to temporary array object - // after qualification conversion to type \tcode{CA} -A &&r1 = const_cast(CA{}); // error: temporary array decayed to pointer -A &&r2 = const_cast(CA{}); // OK -\end{codeblock} -\end{example} +If \tcode{v} is a null pointer or null member pointer, +the result is a null pointer or null member pointer, respectively. +Otherwise, the result points to or past the end of the same object, or +points to the same member, respectively, as \tcode{v}. \pnum For two object types \tcode{T1} and \tcode{T2}, if a pointer to \tcode{T1} can @@ -4458,20 +5104,22 @@ \item a glvalue of type \tcode{T1} can be explicitly converted to an xvalue of type \tcode{T2} using the cast \tcode{\keyword{const_cast}}; and -\item if \tcode{T1} is a class type, a prvalue of type \tcode{T1} can be +\item if \tcode{T1} is a class or array type, +a prvalue of type \tcode{T1} can be explicitly converted to an xvalue of type \tcode{T2} using the cast \tcode{\keyword{const_cast}}. +The temporary materialization conversion is performed on \tcode{v}. \end{itemize} -The result of a reference \keyword{const_cast} refers -to the original object if the operand is a glvalue and -to the result of applying the temporary materialization conversion\iref{conv.rval} otherwise. +The result refers to the same object as the (possibly converted) operand. +\begin{example} +\begin{codeblock} +typedef int *A[3]; // array of 3 pointer to \tcode{int} +typedef const int *const CA[3]; // array of 3 const pointer to \tcode{const int} -\pnum -A null pointer value\iref{basic.compound} is converted to the null pointer -value of the destination type. The null member pointer -value\iref{conv.mem} is converted to the null member pointer value of -the destination type. +auto &&r2 = const_cast(CA{}); // OK, temporary materialization conversion is performed +\end{codeblock} +\end{example} \pnum \begin{note} @@ -4550,7 +5198,8 @@ \keyword{alignof} \terminal{(} type-id \terminal{)}\br noexcept-expression\br new-expression\br - delete-expression + delete-expression\br + reflect-expression \end{bnf} \indextext{operator!indirection}% @@ -4589,6 +5238,9 @@ the result denotes that object or function; otherwise, the behavior is undefined except as specified in \ref{expr.typeid}. \begin{note} +Indirection through a pointer to an out-of-lifetime object is valid\iref{basic.life}. +\end{note} +\begin{note} \indextext{type!incomplete}% Indirection through a pointer to an incomplete type (other than \cv{} \keyword{void}) is valid. The lvalue thus obtained can be @@ -4604,17 +5256,27 @@ \indextext{expression!pointer-to-member constant}% The operand of the unary \tcode{\&} operator shall be an lvalue of some type \tcode{T}. -The result is a prvalue. \begin{itemize} \item -If the operand is a \grammarterm{qualified-id} naming a non-static or variant member \tcode{m} -of some class \tcode{C}, other than an explicit object member function, the result has type ``pointer to member -of class \tcode{C} of type \tcode{T}'' and designates \tcode{C::m}. +If the operand is a \grammarterm{qualified-id} or \grammarterm{splice-expression} +designating a non-static member \tcode{m}, +other than an explicit object member function, +\tcode{m} shall be a direct member of some class \tcode{C} +that is not an anonymous union. +The result has type ``pointer to member of class \tcode{C} of type \tcode{T}'' +and designates \tcode{C::m}. +\begin{note} +A \grammarterm{qualified-id} +that names a member of a namespace-scope anonymous union +is considered to be a class member access expression\iref{expr.prim.id.general} +and cannot be used to form a pointer to member. +\end{note} \item Otherwise, the result has type ``pointer to \tcode{T}'' and points to the designated object\iref{intro.memory} or function\iref{basic.compound}. -If the operand names an explicit object member function\iref{dcl.fct}, -the operand shall be a \grammarterm{qualified-id}. +If the operand designates an explicit object member function\iref{dcl.fct}, +the operand shall be +a \grammarterm{qualified-id} or a \grammarterm{splice-expression}. \begin{note} In particular, taking the address of a variable of type ``\cv{}~\tcode{T}'' yields a pointer of type ``pointer to \cv{}~\tcode{T}''. @@ -4639,8 +5301,9 @@ \pnum A pointer to member is only formed when an explicit \tcode{\&} is used -and its operand is a \grammarterm{qualified-id} not enclosed in -parentheses. +and its operand is +a \grammarterm{qualified-id} or \grammarterm{splice-expression} +not enclosed in parentheses. \begin{note} That is, the expression \tcode{\&(qualified-id)}, where the \grammarterm{qualified-id} is enclosed in parentheses, does not form an @@ -4737,32 +5400,16 @@ \pnum \indextext{expression!increment}% \indextext{expression!decrement}% -The operand of prefix \tcode{++} \indextext{operator!increment}% +\indextext{operator!decrement}% \indextext{prefix \tcode{++}}% -is modified\iref{defns.access} by adding \tcode{1}. \indextext{prefix \tcode{--}}% -The operand shall be a modifiable lvalue. The type of the operand shall -be an arithmetic type other than \cv{}~\tcode{bool}, -or a pointer to a completely-defined object type. +The operand of prefix \tcode{++} or \tcode{--} +shall not be of type \cv{}~\tcode{bool}. An operand with volatile-qualified type is deprecated; see~\ref{depr.volatile.type}. -The result is the updated operand; it is an lvalue, and it is a -bit-field if the operand is a bit-field. -The expression \tcode{++x} is equivalent to \tcode{x+=1}. -\indextext{operator!\idxcode{+=}}% -\begin{note} -See the discussions of addition\iref{expr.add} and assignment -operators\iref{expr.ass} for information on conversions. -\end{note} - -\pnum -The operand of prefix -\indextext{operator!decrement}% -\tcode{--} is modified\iref{defns.access} by subtracting \tcode{1}. -The requirements on the operand of prefix -\tcode{--} and the properties of its result are otherwise the same as -those of prefix \tcode{++}. +The expression \tcode{++x} is otherwise equivalent to \tcode{x+=1} and +the expression \tcode{--x} is otherwise equivalent to \tcode{x-=1}\iref{expr.assign}. \begin{note} For postfix increment and decrement, see~\ref{expr.post.incr}. \end{note} @@ -4780,13 +5427,15 @@ \begin{bnf} \nontermdef{await-expression}\br - \terminal{co_await} cast-expression + \keyword{co_await} cast-expression \end{bnf} \pnum -An \grammarterm{await-expression} shall appear only in a potentially-evaluated +An \grammarterm{await-expression} shall appear only as a potentially-evaluated expression within the \grammarterm{compound-statement} of a -\grammarterm{function-body} outside of a \grammarterm{handler}\iref{except.pre}. +\grammarterm{function-body} or \grammarterm{lambda-expression}, +in either case +outside of a \grammarterm{handler}\iref{except.pre}. In a \grammarterm{declaration-statement} or in the \grammarterm{simple-declaration} (if any) of an \grammarterm{init-statement}, an \grammarterm{await-expression} @@ -4796,6 +5445,9 @@ default argument\iref{dcl.fct.default}. An \grammarterm{await-expression} shall not appear in the initializer of a block variable with static or thread storage duration. +An \grammarterm{await-expression} shall not be +a potentially-evaluated subexpression +of the predicate of a contract assertion\iref{basic.contract}. A context within a function where an \grammarterm{await-expression} can appear is called a \term{suspension context} of the function. @@ -4815,7 +5467,7 @@ an initial await expression, or a final await expression\iref{dcl.fct.def.coroutine}, a search is performed for the name \tcode{await_transform} -in the scope of \tcode{P} \iref{class.member.lookup}. +in the scope of \tcode{P}\iref{class.member.lookup}. If this search is performed and finds at least one declaration, then \placeholder{a} is \mbox{\placeholder{p}\tcode{.await_transform(}\grammarterm{cast-expression}\tcode{)}}; @@ -5050,7 +5702,7 @@ \begin{note} A \keyword{sizeof} expression is an integral constant expression\iref{expr.const}. -The type \tcode{std::size_t} is defined in the standard header +The \grammarterm{typedef-name} \tcode{std::size_t} is declared in the standard header \libheader{cstddef}\iref{cstddef.syn,support.types.layout}. \end{note} @@ -5069,7 +5721,7 @@ \begin{note} An \keyword{alignof} expression is an integral constant expression\iref{expr.const}. -The type \tcode{std::size_t} is defined in the standard header +The \grammarterm{typedef-name} \tcode{std::size_t} is declared in the standard header \libheader{cstddef}\iref{cstddef.syn,support.types.layout}. \end{note} @@ -5254,6 +5906,15 @@ \grammarterm{expression} of a \grammarterm{noptr-new-declarator}), but \tcode{new float[5][n]} is ill-formed (because \tcode{n} is not a constant expression). +Furthermore, +\tcode{new float[0]} is well-formed +(because \tcode{0} is the \grammarterm{expression} +of a \grammarterm{noptr-new-declarator}, +where a value of zero results in the allocation of an array with no elements), +but \tcode{new float[n][0]} is ill-formed +(because \tcode{0} is the \grammarterm{constant-expression} +of a \grammarterm{noptr-new-declarator}, +where only values greater than zero are allowed). \end{example} \pnum @@ -5270,7 +5931,7 @@ If the \grammarterm{expression} in a \grammarterm{noptr-new-declarator} is present, it is implicitly converted to \tcode{std::size_t}. \indextext{function!allocation}% -The \grammarterm{expression} is erroneous if: +The value of the \grammarterm{expression} is invalid if \begin{itemize} \item the expression is of non-class type and its value before converting to @@ -5298,7 +5959,7 @@ number of elements to initialize. \end{itemize} -If the \grammarterm{expression} is erroneous after converting to \tcode{std::size_t}: +If the value of the \grammarterm{expression} is invalid after converting to \tcode{std::size_t}: \begin{itemize} \item if the \grammarterm{expression} is a potentially-evaluated core constant expression, @@ -5410,12 +6071,7 @@ \pnum During an evaluation of a constant expression, -a call to an allocation function is always omitted. -\begin{note} -Only \grammarterm{new-expression}{s} that would otherwise result in -a call to a replaceable global allocation function -can be evaluated in constant expressions\iref{expr.const}. -\end{note} +a call to a replaceable allocation function is always omitted\iref{expr.const}. \pnum The implementation may @@ -5743,22 +6399,15 @@ If the operand is of class type, it is contextually implicitly converted\iref{conv} to a pointer to object -type. -\begin{footnote} -This implies that an object -cannot be deleted using a pointer of type -\tcode{\keyword{void}*} because \keyword{void} is not an object type. -\end{footnote} +type +and the converted operand is used in place of the original operand +for the remainder of this subclause. Otherwise, it shall be a prvalue of pointer to object type. The \grammarterm{delete-expression} has type \keyword{void}. \pnum \indextext{\idxcode{delete}!single-object}% -If the operand has a class type, the operand is converted to a pointer -type by calling the above-mentioned conversion function, and the -converted operand is used in place of the original operand for the -remainder of this subclause. In a single-object delete expression, the value of the operand of \keyword{delete} may be a null pointer value, a pointer value @@ -5802,15 +6451,10 @@ expression, if the dynamic type of the object to be deleted is not similar to its static type, the behavior is undefined. -\pnum -The \grammarterm{cast-expression} in a \grammarterm{delete-expression} shall -be evaluated exactly once. - \pnum \indextext{type!incomplete}% -If the object being deleted has incomplete class type at the point of -deletion and the complete class has a non-trivial destructor or a -deallocation function, the behavior is undefined. +If the object being deleted has incomplete class type at the point of deletion, +the program is ill-formed. \pnum \indextext{\idxcode{delete}!destructor and}% @@ -5904,7 +6548,7 @@ \end{note} \pnum -The deallocation the function to be called is selected as follows: +The deallocation function to be called is selected as follows: \begin{itemize} \item If any of the deallocation functions is a destroying operator delete, @@ -5990,6 +6634,232 @@ the behavior is undefined\iref{new.delete.single,new.delete.array}. \end{note} +\rSec3[expr.reflect]{The reflection operator} + +\begin{bnf} +\nontermdef{reflect-expression}\br + \terminal{\caret\caret} \terminal{::}\br + \terminal{\caret\caret} reflection-name\br + \terminal{\caret\caret} type-id\br + \terminal{\caret\caret} id-expression +\end{bnf} + +\begin{bnf} +\nontermdef{reflection-name}\br + \opt{nested-name-specifier} identifier\br + nested-name-specifier \keyword{template} identifier +\end{bnf} + +\pnum +The unary \tcode{\caret\caret} operator, +called the \defnadj{reflection}{operator}, +yields a prvalue of type \tcode{std::meta::info}\iref{basic.fundamental}. +\begin{note} +This document places no restriction on representing, by reflections, +constructs not described by this document or +using the names of such constructs +as operands of \grammarterm{reflect-expression}s. +\end{note} + +\pnum +The component names of a \grammarterm{reflection-name} +are those of its \grammarterm{nested-name-specifier} (if any) and +its \grammarterm{identifier}. +The terminal name of a \grammarterm{reflection-name} of the form +\grammarterm{nested-name-specifier} \keyword{template} \grammarterm{identifier} +shall denote a template. + +\pnum +A \grammarterm{reflect-expression} is parsed as +the longest possible sequence of tokens +that could syntactically form a \grammarterm{reflect-expression}. +An unparenthesized \grammarterm{reflect-expression} +that represents a template shall not be followed by \tcode{<}. +\begin{example} +\begin{codeblock} +static_assert(std::meta::is_type(^^int())); // \tcode{\caret\caret} applies to the type-id \tcode{int()} + +template struct X {}; +consteval bool operator<(std::meta::info, X) { return false; } +consteval void g(std::meta::info r, X xv) { + r == ^^int && true; // error: \tcode{\caret\caret} applies to the \grammarterm{type-id} \tcode{int\&\&} + r == ^^int & true; // error: \tcode{\caret\caret} applies to the type-id \tcode{int\&} + r == (^^int) && true; // OK + r == ^^int &&&& true; // error: \tcode{int \&\&\&\&} is not a valid \grammarterm{type-id} + ^^X < xv; // error: \grammarterm{reflect-expression} that represents a template is followed by \tcode{<} + (^^X) < xv; // OK + ^^X < xv; // OK +} +\end{codeblock} +\end{example} + +\pnum +A \grammarterm{reflect-expression} of the form \tcode{\caret\caret ::} +represents the global namespace. + +\pnum +If a \grammarterm{reflect-expression} $R$ matches +the form \tcode{\caret\caret \grammarterm{reflection-name}}, +it is interpreted as such; +the \grammarterm{identifier} is looked up and +the representation of $R$ is determined as follows: +\begin{itemize} +\item +If lookup finds a declaration +that replaced a \grammarterm{using-declarator} +during a single search\iref{basic.lookup.general,namespace.udecl}, +$R$ is ill-formed. +\begin{example} +\begin{codeblock} +struct A { struct S {}; }; +struct B : A { using A::S; }; +constexpr std::meta::info r1 = ^^B::S; // error: \tcode{A::S} found through \grammarterm{using-declarator} + +struct C : virtual B { struct S {}; }; +struct D : virtual B, C {}; +D::S s; // OK, names \tcode{C::S} per \ref{class.member.lookup} +constexpr std::meta::info r2 = ^^D::S; // OK, result \tcode{C::S} not found through \grammarterm{using-declarator} +\end{codeblock} +\end{example} +\item +Otherwise, if lookup finds a namespace alias\iref{namespace.alias}, +$R$ represents that namespace alias. +For any other \grammarterm{namespace-name}, +$R$ represents the denoted namespace. +\item +Otherwise, if lookup finds a namespace\iref{basic.namespace}, +$R$ represents that namespace. +\item +Otherwise, if lookup finds a concept\iref{temp.concept}, +$R$ represents the denoted concept. +\item +Otherwise, if lookup finds a template\iref{temp.names}, +the representation of $R$ is determined as follows: +\begin{itemize} +\item +If lookup finds an injected-class-name\iref{class.pre}, then: +\begin{itemize} +\item +If the \grammarterm{reflection-name} is of the form +\tcode{\grammarterm{nested-name-specifier} \keyword{template} \grammarterm{identifier}}, +then $R$ represents the class template named by the injected-class-name. +\item +Otherwise, the injected-class-name shall be unambiguous +when considered as a \grammarterm{type-name} and +$R$ represents the class template specialization so named. +\end{itemize} +\item +Otherwise, if lookup finds an overload set, +that overload set shall contain only +declarations of a unique function template F; +$R$ represents F. +\item +Otherwise, if lookup finds +a class template, variable template, or alias template, +$R$ represents that template. +\begin{note} +Lookup never finds a partial or explicit specialization. +\end{note} +\end{itemize} +\item +Otherwise, if lookup finds a type alias $A$, +$R$ represents the underlying entity of $A$ +if $A$ was introduced by the declaration of a template parameter; +otherwise, $R$ represents $A$. +\item +Otherwise, if lookup finds a class or an enumeration, +$R$ represents the denoted type. +\item +Otherwise, if lookup finds a class member of an anonymous union\iref{class.union.anon}, $R$ represents that class member. +\item +Otherwise, +the \grammarterm{reflection-name} shall be an \grammarterm{id-expression} \tcode{I} +and $R$ is \tcode{\caret\caret I} (see below). +\end{itemize} + +\pnum +A \grammarterm{reflect-expression} $R$ of the form +\tcode{\caret\caret \grammarterm{type-id}} +represents an entity determined as follows: +\begin{itemize} +\item +If the \grammarterm{type-id} designates +a placeholder type\iref{dcl.spec.auto.general}, +$R$ is ill-formed. +\item +Otherwise, if the \grammarterm{type-id} names a type alias +that is a specialization of an alias template\iref{temp.alias}, +$R$ represents that type alias. +\item +Otherwise, $R$ represents the type denoted by the \grammarterm{type-id}. +\end{itemize} + +\pnum +A \grammarterm{reflect-expression} $R$ of the form +\tcode{\caret\caret \grammarterm{id-expression}} +represents an entity determined as follows: +\begin{itemize} +\item +If the \grammarterm{id-expression} denotes +\begin{itemize} +\item +a variable declared by +an \grammarterm{init-capture}\iref{expr.prim.lambda.capture}, +\item +a function-local predefined variable\iref{dcl.fct.def.general}, +\item +a local parameter introduced by +a \grammarterm{requires-expression}\iref{expr.prim.req}, or +\item +a local entity $E$\iref{basic.pre} for which a lambda scope intervenes +between the point at which $E$ was introduced and $R$, +\end{itemize} +then $R$ is ill-formed. +\item +Otherwise, if the \grammarterm{id-expression} denotes an overload set $S$, +overload resolution for the expression \tcode{\&S} with no target +shall select a unique function\iref{over.over}; +$R$ represents that function. +\item +Otherwise, if the \grammarterm{id-expression} denotes +a variable, structured binding, enumerator, or non-static data member, +$R$ represents that entity. +\item +Otherwise, $R$ is ill-formed. +\begin{note} +This includes \grammarterm{unqualified-id}s +that name a constant template parameter and +\grammarterm{pack-index-expression}s. +\end{note} +\end{itemize} +The \grammarterm{id-expression} of +a \grammarterm{reflect-expression} is an unevaluated operand\iref{expr.context}. +\begin{example} +\begin{codeblock} +template void fn() requires (^^T != ^^int); +template void fn() requires (^^T == ^^int); +template void fn() requires (sizeof(T) == sizeof(int)); + +constexpr std::meta::info a = ^^fn; // OK +constexpr std::meta::info b = ^^fn; // error: ambiguous + +constexpr std::meta::info c = ^^std::vector; // OK + +template +struct S { + static constexpr std::meta::info r = ^^T; + using type = T; +}; +static_assert(S::r == ^^int); +static_assert(^^S::type != ^^int); + +typedef struct X {} Y; +typedef struct Z {} Z; +constexpr std::meta::info e = ^^Y; // OK, represents the type alias \tcode{Y} +constexpr std::meta::info f = ^^Z; // OK, represents the type alias \tcode{Z}, not the type\iref{basic.lookup.general} +\end{codeblock} +\end{example} + \rSec2[expr.cast]{Explicit type conversion (cast notation)}% \indextext{expression!cast|(} @@ -6055,8 +6925,9 @@ If a conversion can be interpreted in more than one of the ways listed above, the interpretation that appears first in the list is used, even if a cast resulting from that interpretation is ill-formed. If a -conversion can be interpreted in more than one way as a -\keyword{static_cast} followed by a \keyword{const_cast}, the conversion is +\keyword{static_cast} followed by a \keyword{const_cast} is used and +the conversion can be interpreted in more than one way as such, +the conversion is ill-formed. \begin{example} \begin{codeblock} @@ -6067,6 +6938,15 @@ A* foo( D* p ) { return (A*)( p ); // ill-formed \keyword{static_cast} interpretation } + +int*** ptr = 0; +auto t = (int const*const*const*)ptr; // OK, \keyword{const_cast} interpretation + +struct S { + operator const int*(); + operator volatile int*(); +}; +int *p = (int*)S(); // error: two possible interpretations using \keyword{static_cast} followed by \keyword{const_cast} \end{codeblock} \end{example} @@ -6297,7 +7177,7 @@ \begin{itemize} \item If \tcode{P} evaluates to a null pointer value and \tcode{J} evaluates to 0, the result is a null pointer value. -\item Otherwise, if \tcode{P} points to an array element $i$ +\item Otherwise, if \tcode{P} points to a (possibly-hypothetical) array element $i$ of an array object \tcode{x} with $n$ elements\iref{dcl.array}, \begin{footnote} As specified in \ref{basic.compound}, @@ -6329,7 +7209,7 @@ \indextext{comparison!undefined pointer}% When two pointer expressions \tcode{P} and \tcode{Q} are subtracted, the type of the result is an \impldef{type of \tcode{ptrdiff_t}} signed -integral type; this type shall be the same type that is defined as +integral type; this type shall be the same type that is named by \tcode{std::ptrdiff_t} in the \libheader{cstddef} header\iref{support.types.layout}. \begin{itemize} @@ -6563,13 +7443,11 @@ \end{bnf} % The -lvalue-to-rvalue\iref{conv.lval}, -array-to-pointer\iref{conv.array}, +lvalue-to-rvalue\iref{conv.lval} and function-to-pointer\iref{conv.func} standard conversions are performed on the operands. -The comparison is deprecated if -both operands were of array type -prior to these conversions\iref{depr.array.comp}. +If one of the operands is a pointer, the +array-to-pointer conversion\iref{conv.array} is performed on the other operand. \pnum The converted operands shall have arithmetic, enumeration, or pointer type. @@ -6581,7 +7459,7 @@ \pnum The usual arithmetic conversions\iref{expr.arith.conv} are performed on operands of arithmetic -or enumeration type. If both operands are pointers, +or enumeration type. If both converted operands are pointers, pointer conversions\iref{conv.ptr}, function pointer conversions\iref{conv.fctptr}, and qualification conversions\iref{conv.qual} @@ -6654,17 +7532,15 @@ The \tcode{==} (equal to) and the \tcode{!=} (not equal to) operators group left-to-right. The -lvalue-to-rvalue\iref{conv.lval}, -array-to-pointer\iref{conv.array}, +lvalue-to-rvalue\iref{conv.lval} and function-to-pointer\iref{conv.func} standard conversions are performed on the operands. -The comparison is deprecated if -both operands were of array type -prior to these conversions\iref{depr.array.comp}. +If one of the operands is a pointer or a null pointer constant\iref{conv.ptr}, +the array-to-pointer conversion\iref{conv.array} is performed +on the other operand. \pnum -The converted operands shall have arithmetic, enumeration, pointer, -or pointer-to-member type, or type \tcode{std::nullptr_t}. The operators +The converted operands shall have scalar type. The operators \tcode{==} and \tcode{!=} both yield \keyword{true} or \keyword{false}, i.e., a result of type \keyword{bool}. In each case below, the operands shall have the same type after the specified conversions have been applied. @@ -6672,7 +7548,7 @@ \pnum \indextext{comparison!pointer}% \indextext{comparison!pointer to function}% -If at least one of the operands is a pointer, +If at least one of the converted operands is a pointer, pointer conversions\iref{conv.ptr}, function pointer conversions\iref{conv.fctptr}, and qualification conversions\iref{conv.qual} @@ -6770,6 +7646,20 @@ Two operands of type \tcode{std::nullptr_t} or one operand of type \tcode{std::nullptr_t} and the other a null pointer constant compare equal. +\pnum +If both operands are of type \tcode{std::meta::info}, +they compare equal if both operands +\begin{itemize} +\item are null reflection values, +\item represent values that are template-argument-equivalent\iref{temp.type}, +\item represent the same object, +\item represent the same entity, +\item represent the same annotation\iref{dcl.attr.annotation}, +\item represent the same direct base class relationship, or +\item represent equal data member descriptions\iref{class.mem.general}, +\end{itemize} +and they compare unequal otherwise. + \pnum If two operands compare equal, the result is \keyword{true} for the \tcode{==} operator and \keyword{false} for the \tcode{!=} operator. If two operands @@ -6996,13 +7886,18 @@ formed and at least one of the operands has (possibly cv-qualified) class type: \begin{itemize} \item if \tcode{T1} and \tcode{T2} are the same class type -(ignoring cv-qualification) and -\tcode{T2} is at least as cv-qualified as \tcode{T1}, -the target type is \tcode{T2}, +(ignoring cv-qualification): + \begin{itemize} + \item + if \tcode{T2} is at least as cv-qualified as \tcode{T1}, + the target type is \tcode{T2}, + \item + otherwise, no conversion sequence is formed for this operand; + \end{itemize} \item otherwise, if \tcode{T2} is a base class of \tcode{T1}, the target type is \cvqual{cv1} \tcode{T2}, where \cvqual{cv1} -denotes the cv-qualifiers of \tcode{T1}, +denotes the cv-qualifiers of \tcode{T1}; \item otherwise, the target type is the type that \tcode{E2} would have after applying the @@ -7015,12 +7910,14 @@ Using this process, it is determined whether an implicit conversion sequence can be formed from the second operand -to the target type determined for the third operand, and vice versa. -If both sequences can be formed, or one can be formed but it is the +to the target type determined for the third operand, and vice versa, +with the following outcome: +\begin{itemize} +\item If both sequences can be formed, or one can be formed but it is the ambiguous conversion sequence, the program is ill-formed. -If no conversion sequence can be formed, the operands are left unchanged +\item If no conversion sequence can be formed, the operands are left unchanged and further checking is performed as described below. -Otherwise, if exactly one conversion sequence can be formed, +\item Otherwise, if exactly one conversion sequence can be formed, that conversion is applied to the chosen operand and the converted operand is used in place of the original operand for the remainder of this subclause. @@ -7028,6 +7925,7 @@ The conversion might be ill-formed even if an implicit conversion sequence could be formed. \end{note} +\end{itemize} \pnum If the second and third operands are glvalues of the same value category @@ -7046,30 +7944,32 @@ subclause. \pnum -Lvalue-to-rvalue\iref{conv.lval}, array-to-pointer\iref{conv.array}, +Array-to-pointer\iref{conv.array} and function-to-pointer\iref{conv.func} standard conversions are performed on the second and third operands. After those conversions, one of the following shall hold: \begin{itemize} \item The second and third operands have the same type; the result is of -that type and the result object is initialized using the selected operand. +that type and the result is copy-initialized using the selected operand. \item The second and third operands have arithmetic or enumeration type; the usual arithmetic conversions\iref{expr.arith.conv} are performed to bring them to a common type, and the result is of that type. \item One or both of the second and third operands have pointer type; -pointer conversions\iref{conv.ptr}, -function pointer conversions\iref{conv.fctptr}, and +lvalue-to-rvalue\iref{conv.lval}, +pointer\iref{conv.ptr}, +function pointer\iref{conv.fctptr}, and qualification conversions\iref{conv.qual} are performed to bring them to their composite pointer type\iref{expr.type}. The result is of the composite pointer type. \item One or both of the second and third operands have pointer-to-member type; -pointer to member conversions\iref{conv.mem}, -function pointer conversions\iref{conv.fctptr}, and +lvalue-to-rvalue\iref{conv.lval}, +pointer to member\iref{conv.mem}, +function pointer\iref{conv.fctptr}, and qualification conversions\iref{conv.qual} are performed to bring them to their composite pointer type\iref{expr.type}. The result is of the composite pointer type. @@ -7087,8 +7987,8 @@ \begin{bnf} \nontermdef{yield-expression}\br - \terminal{co_yield} assignment-expression\br - \terminal{co_yield} braced-init-list + \keyword{co_yield} assignment-expression\br + \keyword{co_yield} braced-init-list \end{bnf} \pnum @@ -7184,7 +8084,7 @@ \end{codeblock} \end{example} -\rSec2[expr.ass]{Assignment and compound assignment operators}% +\rSec2[expr.assign]{Assignment and compound assignment operators}% \indextext{expression!assignment and compound assignment} \pnum @@ -7236,9 +8136,13 @@ \end{bnf} \pnum -In simple assignment (\tcode{=}), the object referred to by the left operand -is modified\iref{defns.access} -by replacing its value with the result of the right operand. +In simple assignment (\tcode{=}), +let \tcode{V} be the result of the right operand; +the object referred to by the left operand is +modified\iref{defns.access} by replacing its value +with \tcode{V} or, +if the object is of integer type, +with the value congruent\iref{basic.fundamental} to \tcode{V}. \pnum \indextext{assignment!conversion by}% @@ -7297,7 +8201,7 @@ \item an assignment to an object of class type, in which case $B$ is passed as the argument to the assignment operator function selected by -overload resolution\iref{over.ass,over.match}. +overload resolution\iref{over.assign,over.match}. \end{itemize} \begin{example} @@ -7378,27 +8282,149 @@ \end{bnf} \pnum -A variable or temporary object \tcode{o} is \defn{constant-initialized} if +The \defnx{constituent values}{constituent value} of an object $o$ are +\begin{itemize} +\item +if $o$ has scalar type, the value of $o$; +\item +otherwise, the constituent values of any direct subobjects of $o$ +other than inactive union members. +\end{itemize} +The \defnx{constituent references}{constituent reference} of an object $o$ are +\begin{itemize} +\item +any direct members of $o$ that have reference type, and +\item +the constituent references of any direct subobjects of $o$ +other than inactive union members. +\end{itemize} + +\pnum +The constituent values and constituent references of +a variable \tcode{x} are defined as follows: +\begin{itemize} +\item +If \tcode{x} declares an object, +the constituent values and references of that object are +constituent values and references of \tcode{x}. +\item +If \tcode{x} declares a reference, +that reference is a constituent reference of \tcode{x}. +\end{itemize} +For any constituent reference \tcode{r} of a variable \tcode{x}, +if \tcode{r} is bound to a temporary object or subobject thereof +whose lifetime is extended to that of \tcode{r}, +the constituent values and references of that temporary object +are also constituent values and references of \tcode{x}, recursively. + +\pnum +An object $o$ is \defn{constexpr-referenceable} from a point $P$ if +\begin{itemize} +\item +$o$ has static storage duration, or +\item +$o$ has automatic storage duration, and, letting \tcode{v} denote +\begin{itemize} +\item +the variable corresponding to $o$'s complete object or +\item +the variable to whose lifetime that of $o$ is extended, +\end{itemize} +the smallest scope enclosing \tcode{v} and the smallest scope enclosing $P$ +that are neither +\begin{itemize} +\item +block scopes nor +\item +function parameter scopes associated with +a \grammarterm{requirement-parameter-list} +\end{itemize} +are the same function parameter scope. +\end{itemize} +\begin{example} +\begin{codeblock} +struct A { + int m; + const int& r; +}; +void f() { + static int sx; + thread_local int tx; // \tcode{tx} is never constexpr-referenceable + int ax; + A aa = {1, 2}; + static A sa = {3, 4}; + // The objects \tcode{sx}, \tcode{ax}, and \tcode{aa.m}, \tcode{sa.m}, and the temporaries to which \tcode{aa.r} and \tcode{sa.r} are bound, are constexpr-referenceable. + auto lambda = [] { + int ay; + // The objects \tcode{sx}, \tcode{sa.m}, and \tcode{ay} (but not \tcode{ax} or \tcode{aa}), and the + // temporary to which \tcode{sa.r} is bound, are constexpr-referenceable. + }; +} +\end{codeblock} +\end{example} + +\pnum +An object or reference \tcode{x} is +\defn{constexpr-representable} at a point $P$ if, +for each constituent value of \tcode{x} that points to or past an object $o$, +and for each constituent reference of \tcode{x} that refers to an object $o$, +$o$ is constexpr-referenceable from $P$. + +\pnum +\indextext{contract evaluation semantics!ignore} +A variable \tcode{v} is \defn{constant-initializable} if \begin{itemize} \item - either it has an initializer or - its default-initialization results in some initialization being performed, and -\item - the full-expression of its initialization is a constant expression - when interpreted as a \grammarterm{constant-expression}, - except that if \tcode{o} is an object, - that full-expression - may also invoke constexpr constructors - for \tcode{o} and its subobjects - even if those objects are of non-literal class types. - \begin{note} - Such a class can have a non-trivial destructor. - Within this evaluation, - \tcode{std::is_constant_evaluated()}\iref{meta.const.eval} - returns \keyword{true}. +the full-expression of its initialization is a constant expression +when interpreted as a \grammarterm{constant-expression} +with all contract assertions +using the ignore evaluation semantic\iref{basic.contract.eval}, +\begin{note} +Within this evaluation, +\tcode{std::is_constant_evaluated()}\iref{meta.const.eval} +returns \keyword{true}. +\end{note} +\begin{note} +The initialization, when evaluated, +can still evaluate contract assertions +with other evaluation semantics, +resulting in a diagnostic or ill-formed program +if a contract violation occurs. \end{note} +\item +immediately after the initializing declaration of \tcode{v}, +the object or reference \tcode{x} declared by \tcode{v} +is constexpr-representable, and +\item +if \tcode{x} has static or thread storage duration, +\tcode{x} is constexpr-representable at the nearest point +whose immediate scope is a namespace scope +that follows the initializing declaration of \tcode{v}. \end{itemize} +\pnum +A constant-initializable variable is \defn{constant-initialized} +if either it has an initializer or +its type is const-default-constructible\iref{dcl.init.general}. +\begin{example} +\begin{codeblock} +void f() { + int ax = 0; // \tcode{ax} is constant-initialized + thread_local int tx = 0; // \tcode{tx} is constant-initialized + static int sx; // \tcode{sx} is not constant-initialized + static int& rss = sx; // \tcode{rss} is constant-initialized + static int& rst = tx; // \tcode{rst} is not constant-initialized + static int& rsa = ax; // \tcode{rsa} is not constant-initialized + thread_local int& rts = sx; // \tcode{rts} is constant-initialized + thread_local int& rtt = tx; // \tcode{rtt} is not constant-initialized + thread_local int& rta = ax; // \tcode{rta} is not constant-initialized + int& ras = sx; // \tcode{ras} is constant-initialized + int& rat = tx; // \tcode{rat} is not constant-initialized + int& raa = ax; // \tcode{raa} is constant-initialized +} +\end{codeblock} +\end{example} + \pnum A variable is \defn{potentially-constant} if it is constexpr or @@ -7413,16 +8439,43 @@ \item $V$ is not initialized to a TU-local value, or \item $P$ is in the same translation unit as $D$. \end{itemize} -An object or reference is \defn{usable in constant expressions} if it is +An object or reference is +\defn{potentially usable in constant expressions} at point $P$ if it is \begin{itemize} -\item a variable that is usable in constant expressions, or -\item a template parameter object\iref{temp.param}, or -\item a string literal object\iref{lex.string}, or -\item a temporary object of non-volatile const-qualified literal type - whose lifetime is extended\iref{class.temporary} - to that of a variable that is usable in constant expressions, or -\item a non-mutable subobject or reference member of any of the above. +\item +the object or reference declared by a variable +that is usable in constant expressions at $P$, +\item +a temporary object of non-volatile const-qualified literal type +whose lifetime is extended\iref{class.temporary} +to that of a variable that is usable in constant expressions at $P$, +\item +a template parameter object\iref{temp.param}, +\item +a string literal object\iref{lex.string}, +\item +a non-mutable subobject of any of the above, or +\item +a reference member of any of the above. \end{itemize} +An object or reference is \defn{usable in constant expressions} at point $P$ +if it is an object or reference +that is potentially usable in constant expressions at $P$ and +is constexpr-representable at $P$. +\begin{example} +\begin{codeblock} +struct A { + int* const & r; +}; +void f(int x) { + constexpr A a = {&x}; + static_assert(a.r == &x); // OK + [&] { + static_assert(a.r != nullptr); // error: \tcode{a.r} is not usable in constant expressions at this point + }(); +} +\end{codeblock} +\end{example} \pnum An expression $E$ is a \defnadj{core constant}{expression} @@ -7480,9 +8533,8 @@ limits (see \ref{implimits}); \item -an operation that would have undefined behavior -as specified in \ref{intro} through \ref{cpp}, -excluding \ref{dcl.attr.assume} and \ref{dcl.attr.noreturn}; +an operation that would have undefined or erroneous behavior +as specified in \ref{intro} through \ref{\lastcorechapter}; \begin{footnote} This includes, for example, signed integer overflow\iref{expr.pre}, certain @@ -7494,6 +8546,9 @@ an lvalue-to-rvalue conversion\iref{conv.lval} unless it is applied to \begin{itemize} + \item + a glvalue of type \cv{}~\tcode{std::nullptr_t}, + \item a non-volatile glvalue that refers to an object that is usable in constant expressions, or @@ -7538,7 +8593,8 @@ \begin{note} If the odr-use occurs in an invocation of a function call operator of a closure type, -it no longer refers to \keyword{this} or to an enclosing automatic variable +it no longer refers to \keyword{this} or to an enclosing +variable with automatic storage duration due to the transformation\iref{expr.prim.lambda.capture} of the \grammarterm{id-expression} into an access of the corresponding data member. @@ -7560,13 +8616,15 @@ from a prvalue \tcode{P} of type ``pointer to \cv{}~\keyword{void}'' to a type ``\cvqual{cv1} pointer to \tcode{T}'', where \tcode{T} is not \cvqual{cv2}~\keyword{void}, -unless \tcode{P} points to an object whose type is similar to \tcode{T}; +unless \tcode{P} +is a null pointer value or +points to an object whose type is similar to \tcode{T}; \item a \keyword{reinterpret_cast}\iref{expr.reinterpret.cast}; \item -a modification of an object\iref{expr.ass,expr.post.incr,expr.pre.incr} +a modification of an object\iref{expr.assign,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$; @@ -7578,9 +8636,27 @@ \item a \grammarterm{new-expression}\iref{expr.new}, -unless the selected allocation function is +unless either +\begin{itemize} +\item +the selected allocation function is a replaceable global allocation function\iref{new.delete.single,new.delete.array} and -the allocated storage is deallocated within the evaluation of $E$; +the allocated storage is deallocated within the evaluation of $E$, or +\item +the selected allocation function is +a non-allocating form\iref{new.delete.placement} +with an allocated type \tcode{T}, where +\begin{itemize} +\item +the placement argument to the \grammarterm{new-expression} points to +an object whose type is similar to \tcode{T}\iref{conv.qual} or, +if \tcode{T} is an array type, +to the first element of an object of a type similar to \tcode{T}, and +\item +the placement argument points to storage +whose duration began within the evaluation of $E$; +\end{itemize} +\end{itemize} \item a \grammarterm{delete-expression}\iref{expr.delete}, @@ -7598,6 +8674,13 @@ unless it deallocates a region of storage allocated within the evaluation of $E$; +\item +a construction of an exception object, +unless the exception object and +all of its implicit copies created by invocations of +\tcode{std::current_exception} or \tcode{std::rethrow_exception}\iref{propagation} +are destroyed within the evaluation of $E$; + \item an \grammarterm{await-expression}\iref{expr.await}; @@ -7609,21 +8692,29 @@ relational\iref{expr.rel}, or equality\iref{expr.eq} operator where the result is unspecified; -\item -a \grammarterm{throw-expression}\iref{expr.throw}; - \item a \keyword{dynamic_cast}\iref{expr.dynamic.cast} or \keyword{typeid}\iref{expr.typeid} expression on a glvalue that refers to an object -whose dynamic type is constexpr-unknown or -that would throw an exception; +whose dynamic type is constexpr-unknown; + +\item +a \tcode{dynamic_cast}\iref{expr.dynamic.cast} expression, +\tcode{typeid}\iref{expr.typeid} expression, or +\tcode{new-expression}\iref{expr.new} +that would throw an exception +where no definition of the exception type is reachable; + +\item +an expression that would produce an injected declaration (see below), +unless $E$ is the corresponding expression of +a \grammarterm{consteval-block-declaration}\iref{dcl.pre}; \item an \grammarterm{asm-declaration}\iref{dcl.asm}; \item -an invocation of the \tcode{va_arg} macro\iref{cstdarg.syn}; +an invocation of the \libmacro{va_arg} macro\iref{cstdarg.syn}; \item a non-constant library call\iref{defns.nonconst.libcall}; @@ -7632,13 +8723,20 @@ \item a \keyword{goto} statement\iref{stmt.goto}. \begin{note} -A \keyword{goto} statement introduced by equivalence\iref{stmt.stmt} +A \keyword{goto} statement introduced by equivalence\iref{stmt} is not in scope. For example, a \keyword{while} statement\iref{stmt.while} can be executed during constant evaluation. \end{note} \end{itemize} +\pnum +It is +\impldef{whether an expression is a core constant expression} +whether $E$ is a core constant expression +if $E$ satisfies the constraints of a core constant expression, but +evaluation of $E$ has runtime-undefined behavior. + \pnum It is unspecified whether $E$ is a core constant expression if $E$ satisfies the constraints of a core constant expression, but @@ -7646,27 +8744,12 @@ \begin{itemize} \item an operation that has undefined behavior -as specified in \ref{library} through \ref{\lastlibchapter}, -\item -an invocation of the \tcode{va_start} macro\iref{cstdarg.syn}, +as specified in \ref{library} through \ref{\lastlibchapter} or \item -a call to a function -that was previously declared -with the \tcode{noreturn} attribute\iref{dcl.attr.noreturn} and -that call returns to its caller, or -\item -a statement with an assumption\iref{dcl.attr.assume} -whose converted \grammarterm{conditional-expression}, -if evaluated where the assumption appears, -would not disqualify $E$ from being a core constant expression and -would not evaluate to \tcode{true}. -\begin{note} -$E$ is not disqualified from being a core constant expression -if the hypothetical evaluation of -the converted \grammarterm{conditional-expression} -would disqualify $E$ from being a core constant expression. -\end{note} +an invocation of the \libmacro{va_start} macro\iref{cstdarg.syn}. \end{itemize} + +\pnum \begin{example} \begin{codeblock} int x; // not constant @@ -7713,14 +8796,6 @@ the evaluation of the body of a member function of \tcode{std::allocator} as defined in \ref{allocator.members}, where \tcode{T} is a literal type, is ignored. -Similarly, the evaluation of the body of -\tcode{std::construct_at} or -\tcode{std::ranges::construct_at} -is considered to include only -the initialization of the \tcode{T} object -if the first argument (of type \tcode{T*}) points -to storage allocated with \tcode{std::allocator} or -to an object whose lifetime began within the evaluation of $E$. \pnum For the purposes of determining whether $E$ is a core constant expression, @@ -7731,9 +8806,49 @@ The copy/move of the active member is trivial. \end{note} +\pnum +For the purposes of determining whether $E$ is a core constant expression, +the evaluation of an \grammarterm{id-expression} +that names a structured binding \tcode{v}\iref{dcl.struct.bind} has the +following semantics: +\begin{itemize} +\item +If \tcode{v} is an lvalue referring to the object bound to an invented reference \tcode{r}, +the behavior is as if \tcode{r} were nominated. +\item +Otherwise, if \tcode{v} names an array element or class member, +the behavior is that of +evaluating \tcode{$e$[$i$]} or \tcode{$e$.$m$}, respectively, +where $e$ is the name of the variable +initialized from the initializer of the structured binding declaration, and +$i$ is the index of the element referred to by \tcode{v} or +$m$ is the name of the member referred to by \tcode{v}, respectively. +\end{itemize} +\begin{example} +\begin{codeblock} +#include +struct S { + mutable int m; + constexpr S(int m): m(m) {} + virtual int g() const; +}; +void f(std::tuple t) { + auto [r] = t; + static_assert(r.g() >= 0); // error: dynamic type is constexpr-unknown + constexpr auto [m] = S(1); + static_assert(m == 1); // error: lvalue-to-rvalue conversion on mutable + // subobject \tcode{e.m}, where \tcode{e} is a constexpr object of type \tcode{S} + using A = int[2]; + constexpr auto [v0, v1] = A{2, 3}; + static_assert(v0 + v1 == 5); // OK, equivalent to \tcode{e[0] + e[1]} where \tcode{e} is a constexpr array +} +\end{codeblock} +\end{example} + \pnum During the evaluation of an expression $E$ as a core constant expression, -all \grammarterm{id-expression}s and uses of \tcode{*\keyword{this}} +all \grammarterm{id-expression}s, \grammarterm{splice-expression}s, and +uses of \tcode{*\keyword{this}} that refer to an object or reference whose lifetime did not begin with the evaluation of $E$ are treated as referring to a specific instance of that object or reference @@ -7801,13 +8916,13 @@ \end{example} \pnum -An object \tcode{a} is said to have \defnadj{constant}{destruction} if: +An object \tcode{a} is said to have \defnadj{constant}{destruction} if \begin{itemize} \item it is not of class type nor (possibly multidimensional) array thereof, or \item it is of class type or (possibly multidimensional) array thereof, - that class type has a constexpr destructor, and + that class type has a constexpr destructor\iref{dcl.constexpr}, and for a hypothetical expression $E$ whose only effect is to destroy \tcode{a}, $E$ would be a core constant expression @@ -7861,6 +8976,9 @@ \item qualification conversions\iref{conv.qual}, \item integral promotions\iref{conv.prom}, \item integral conversions\iref{conv.integral} other than narrowing conversions\iref{dcl.init.list}, +\item floating-point promotions\iref{conv.fpprom}, +\item floating-point conversions\iref{conv.double} where + the source value can be represented exactly in the destination type, \item null pointer conversions\iref{conv.ptr} from \tcode{std::nullptr_t}, \item null member pointer conversions\iref{conv.mem} from \tcode{std::nullptr_t}, and \item function pointer conversions\iref{conv.fctptr}, @@ -7870,9 +8988,9 @@ Such expressions can be used in \keyword{new} expressions\iref{expr.new}, as case expressions\iref{stmt.switch}, as enumerator initializers if the underlying type is -fixed\iref{dcl.enum}, as array bounds\iref{dcl.array}, and -as non-type template -arguments\iref{temp.arg}. +fixed\iref{dcl.enum}, as array bounds\iref{dcl.array}, +as constant template arguments\iref{temp.arg}, +and as the constant expression of a \grammarterm{splice-specifier}\iref{basic.splice}. \end{note} \indextext{contextually converted constant expression of type \tcode{bool}|see{conversion, contextual}}% \indextext{conversion!contextual to constant expression of type \tcode{bool}}% @@ -7883,41 +9001,58 @@ \pnum A \defnadj{constant}{expression} is either -a glvalue core constant expression that refers to -an entity that is a permitted result of a constant expression (as defined below), or -a prvalue core constant expression whose value -satisfies the following constraints: \begin{itemize} - \item - if the value is an object of class type, - each non-static data member of reference type refers to - an entity that is a permitted result of a constant expression, - - \item - if the value is an object of scalar type, - it does not have an indeterminate value\iref{basic.indet}, - - \item - if the value is of pointer type, it contains - the address of an object with static storage duration, - the address past the end of such an object\iref{expr.add}, - the address of a non-immediate function, - or a null pointer value, +\item +a glvalue core constant expression $E$ for which +\begin{itemize} +\item +$E$ refers to a non-immediate function, +\item +$E$ designates an object \tcode{o}, and +if the complete object of \tcode{o} is of consteval-only type then so is $E$, +\begin{example} +\begin{codeblock} +struct Base { }; +struct Derived : Base { std::meta::info r; }; - \item - if the value is of pointer-to-member-function type, - it does not designate an immediate function, and +consteval const Base& fn(const Derived& derived) { return derived; } - \item - if the value is an object of class or array type, - each subobject satisfies these constraints for the value. +constexpr Derived obj{.r=^^::}; // OK +constexpr const Derived& d = obj; // OK +constexpr const Base& b = fn(obj); // error: not a constant expression because \tcode{Derived} + // is a consteval-only type but \tcode{Base} is not. +\end{codeblock} +\end{example} +\end{itemize} +or +\item +a prvalue core constant expression whose result object\iref{basic.lval} +satisfies the following constraints: +\begin{itemize} +\item +each constituent reference refers to an object or a non-immediate function, +\item +no constituent value of scalar type is an indeterminate or erroneous value\iref{basic.indet}, +\item +no constituent value of pointer type is a pointer to an immediate function or +an invalid pointer value\iref{basic.compound}, +\item +no constituent value of pointer-to-member type designates an immediate function, and +\item +unless the value is of consteval-only type, +\begin{itemize} +\item +no constituent value of pointer-to-member type points to +a direct member of a consteval-only class type, +\item +no constituent value of pointer type points to or past an object +whose complete object is of consteval-only type, and +\item +no constituent reference refers to an object +whose complete object is of consteval-only type. +\end{itemize} +\end{itemize} \end{itemize} -An entity is a -\defnx{permitted result of a constant expression}{constant expression!permitted result of} -if it is an -object with static storage duration that either is not a temporary object or is -a temporary object whose value satisfies the above constraints, or if -it is a non-immediate function. \begin{note} A glvalue core constant expression that either refers to or points to an unspecified object @@ -7931,6 +9066,14 @@ constexpr int r = h(); // OK constexpr auto e = g(); // error: a pointer to an immediate function is // not a permitted result of a constant expression + +struct S { + int x; + constexpr S() {} +}; +int i() { + constexpr S s; // error: \tcode{s.x} has erroneous value +} \end{codeblock} \end{example} @@ -7984,17 +9127,17 @@ \indexdefn{conversion!immediate-escalating}% \indexdefn{immediate-escalating!expression|see{expression, immediate-escalating}}% \indexdefn{immediate-escalating!conversion|see{conversion, immediate-escalating}}% -An expression or conversion is \defn{immediate-escalating} -if it is not initially in an immediate function context -and it is either +A potentially-evaluated expression or conversion is \defn{immediate-escalating} +if it is neither initially in an immediate function context +nor a subexpression of an immediate invocation, and \begin{itemize} \item -a potentially-evaluated \grammarterm{id-expression} -that denotes an immediate function -that is not a subexpression of an immediate invocation, or +it is an \grammarterm{id-expression} or \grammarterm{splice-expression} +that designates an immediate function, +\item +it is an immediate invocation that is not a constant expression, or \item -an immediate invocation that is not a constant expression -and is not a subexpression of an immediate invocation. +it is of consteval-only type\iref{basic.types.general}. \end{itemize} \pnum @@ -8015,14 +9158,18 @@ in an immediate-escalating function. \pnum -An \defnadj{immediate}{function} is a function or constructor that is +An \defnadj{immediate}{function} is a function or constructor that is either \begin{itemize} \item declared with the \keyword{consteval} specifier, or \item an immediate-escalating function \tcode{\placeholder{F}} -whose function body contains an immediate-escalating expression \tcode{\placeholder{E}} -such that \tcode{\placeholder{E}}'s innermost enclosing non-block scope +whose function body contains either +\begin{itemize} +\item an immediate-escalating expression or +\item a definition of a non-constexpr variable with consteval-only type +\end{itemize} +whose innermost enclosing non-block scope is \tcode{\placeholder{F}}'s function parameter scope. \begin{tailnote} Default member initializers used to initialize @@ -8084,10 +9231,18 @@ constexpr int k(int) { // \tcode{k} is not an immediate function because \tcode{A(42)} is a return A(42).y; // constant expression and thus not immediate-escalating } + +constexpr int l(int c) pre(c >= 2) { + return (c % 2 == 0) ? c / 0 : c; +} + +const int i0 = l(0); // dynamic initialization; contract violation or undefined behavior +const int i1 = l(1); // static initialization; value of \tcode{1} or contract violation at compile time +const int i2 = l(2); // dynamic initialization; undefined behavior +const int i3 = l(3); // static initialization; value of \tcode{3} \end{codeblock} \end{example} - \pnum An expression or conversion is \defn{manifestly constant-evaluated} if it is: @@ -8102,7 +9257,10 @@ has constant initialization\iref{basic.start.static}. \begin{footnote} Testing this condition -can involve a trial evaluation of its initializer as described above. +can involve a trial evaluation of its initializer, +with evaluations of contract assertions +using the ignore evaluation semantic\iref{basic.contract.eval}, +as described above. \end{footnote} \begin{example} \begin{codeblock} @@ -8132,6 +9290,146 @@ is evaluated even in an unevaluated operand\iref{term.unevaluated.operand}. \end{note} +\pnum +The evaluation of an expression can introduce +one or more \defnadjx{injected}{declarations}{declaration}. +The evaluation is said to \defn{produce} the declarations. +\begin{note} +An invocation of +the library function template \tcode{std::meta::define_aggregate} +produces an injected declaration\iref{meta.reflection.define.aggregate}. +\end{note} +Each such declaration has +\begin{itemize} +\item +an associated \defnadj{synthesized}{point}, +which follows the last non-synthesized program point +in the translation unit containing that declaration, and +\item +an associated \defnadj{characteristic}{sequence} of values. +\end{itemize} +\begin{note} +Special rules concerning reachability +apply to synthesized points\iref{module.reach}. +\end{note} +\begin{note} +The program is ill-formed +if injected declarations with different characteristic sequences +define the same entity in different translation units\iref{basic.def.odr}. +\end{note} + +\pnum +A member of an entity defined by an injected declaration +shall not have a name reserved to the implementation\iref{lex.name}; +no diagnostic is required. + +\pnum +Let $C$ be a \grammarterm{consteval-block-declaration}, +the evaluation of whose corresponding expression +produces an injected declaration for an entity $E$. +The program is ill-formed if either +\begin{itemize} +\item +$C$ is enclosed by a scope associated with $E$ or +\item +letting $P$ be a point whose immediate scope is that to which $E$ belongs, +there is a function parameter scope or class scope +that encloses exactly one of $C$ or $P$. +\end{itemize} +\begin{example} +\begin{codeblock} +struct S0 { + consteval { + std::meta::define_aggregate(^^S0, {}); // error: scope associated with \tcode{S0} encloses the consteval block + } +}; + +struct S1; +consteval { std::meta::define_aggregate(^^S1, {}); } // OK + +template consteval void tfn1() { + std::meta::define_aggregate(R, {}); +} + +struct S2; +consteval { tfn1<^^S2>(); } // OK + +template consteval void tfn2() { + consteval { std::meta::define_aggregate(R, {}); } +} + +struct S3; +consteval { tfn2<^^S3>(); } + // error: function parameter scope of \tcode{tfn2<\caret\caret S3>} intervenes between the declaration of \tcode{S3} + // and the consteval block that produces the injected declaration + +template struct TCls { + struct S4; + static void sfn() requires ([] { + consteval { std::meta::define_aggregate(^^S4, {}); } + return true; + }()) { } +}; + +consteval { TCls::sfn(); } // error: \tcode{TCls::S4} is not enclosed by \grammarterm{requires-clause} lambda + +struct S5; +struct Cls { + consteval { std::meta::define_aggregate(^^S5, {}); } // error: \tcode{S5} is not enclosed by class \tcode{Cls} +}; + +struct S6; +consteval { // \#1 + struct S7; // local class + + std::meta::define_aggregate(^^S7, {}); // error: consteval block \#1 does not enclose itself, + // but encloses \tcode{S7} + + consteval { // \#2 + std::meta::define_aggregate(^^S6, {}); // error: consteval block \#1 encloses + // consteval block \#2 but not \tcode{S6} + + std::meta::define_aggregate(^^S7, {}); // OK, consteval block \#1 encloses both \#2 and \tcode{S7} + } +} +\end{codeblock} +\end{example} + +\pnum +The \defn{evaluation context} is a set of program points +that determines the behavior of certain functions +used for reflection\iref{meta.reflection}. +During the evaluation $V$ of an expression $E$ as a core constant expression, +the evaluation context of an evaluation $X$\iref{intro.execution} +consists of the following points: +\begin{itemize} +\item +The program point $\textit{EVAL-PT}(L)$, +where $L$ is the point at which $E$ appears, and +where $\textit{EVAL-PT}(P)$, for a point $P$, +is a point $R$ determined as follows: +\begin{itemize} +\item +If a potentially-evaluated subexpression\iref{intro.execution} of +a default member initializer $I$ appears at $P$, and +a (possibly aggregate) initialization during $V$ is using $I$, +then $R$ is $\textit{EVAL-PT}(Q)$ +where $Q$ is the point at which that initialization appears. +\item +Otherwise, if a potentially-evaluated subexpression of +a default argument\iref{dcl.fct.default} appears at $P$, and +an invocation of a function\iref{expr.call} during $V$ +is using that default argument, +then $R$ is $\textit{EVAL-PT}(Q)$ +where $Q$ is the point at which that invocation appears. +\item +Otherwise, $R$ is $P$. +\end{itemize} +\item +Each synthesized point corresponding to an injected declaration produced by +any evaluation sequenced before $X$\iref{intro.execution}. +\end{itemize} + \pnum \indextext{expression!potentially constant evaluated}% An expression or conversion is \defn{potentially constant evaluated} diff --git a/source/future.tex b/source/future.tex index 34173964ff..f94b2c3320 100644 --- a/source/future.tex +++ b/source/future.tex @@ -4,8 +4,8 @@ \rSec1[depr.general]{General} \pnum -This Annex describes features of the \Cpp{} Standard that are specified for compatibility with -existing implementations. +This Annex describes features of this document +that are specified for compatibility with existing implementations. \pnum These are deprecated features, where @@ -16,6 +16,26 @@ An implementation may declare library names and entities described in this Clause with the \tcode{deprecated} attribute\iref{dcl.attr.deprecated}. +\rSec1[depr.local]{Non-local use of TU-local entities} + +\pnum +A declaration of a non-TU-local entity that is an exposure\iref{basic.link} +is deprecated. +\begin{note} +Such a declaration in an importable module unit is ill-formed. +\end{note} +\begin{example} +\begin{codeblock} +namespace { + struct A { + void f() {} + }; +} +A h(); // deprecated: not internal linkage +inline void g() {A().f();} // deprecated: inline and not internal linkage +\end{codeblock} +\end{example} + \rSec1[depr.capture.this]{Implicit capture of \tcode{*this} by reference} \pnum @@ -35,25 +55,6 @@ \end{codeblock} \end{example} -\rSec1[depr.array.comp]{Array comparisons} - -\pnum -Equality and relational comparisons\iref{expr.eq,expr.rel} -between two operands of array type -are deprecated. -\begin{note} -Three-way comparisons\iref{expr.spaceship} between such operands are ill-formed. -\end{note} -\begin{example} -\begin{codeblock} -int arr1[5]; -int arr2[5]; -bool same = arr1 == arr2; // deprecated, same as \tcode{\&arr1[0] == \&arr2[0]}, - // does not compare array contents -auto cmp = arr1 <=> arr2; // error -\end{codeblock} -\end{example} - \rSec1[depr.volatile.type]{Deprecated \tcode{volatile} types} \pnum @@ -72,7 +73,7 @@ \pnum Certain assignments where the left operand is a volatile-qualified non-class type -are deprecated; see~\ref{expr.ass}. +are deprecated; see~\ref{expr.assign}. \begin{example} \begin{codeblock} @@ -114,41 +115,17 @@ \end{codeblock} \end{example} +\rSec1[depr.ellipsis.comma]{Non-comma-separated ellipsis parameters} -\rSec1[depr.static.constexpr]{Redeclaration of \tcode{static constexpr} data members} - -\pnum -For compatibility with prior revisions of \Cpp{}, a \keyword{constexpr} -static data member may be redundantly redeclared outside the class with no -initializer\iref{basic.def,class.static.data}. -This usage is deprecated. -\begin{example} -\begin{codeblock} -struct A { - static constexpr int n = 5; // definition (declaration in \CppXIV{}) -}; - -constexpr int A::n; // redundant declaration (definition in \CppXIV{}) -\end{codeblock} -\end{example} - -\rSec1[depr.local]{Non-local use of TU-local entities} - -\pnum -A declaration of a non-TU-local entity that is an exposure\iref{basic.link} -is deprecated. -\begin{note} -Such a declaration in an importable module unit is ill-formed. -\end{note} +A \grammarterm{parameter-declaration-clause} +of the form +\grammarterm{parameter-declaration-list} \tcode{...} +is deprecated\iref{dcl.fct}. \begin{example} \begin{codeblock} -namespace { - struct A { - void f() {} - }; -} -A h(); // deprecated: not internal linkage -inline void g() {A().f();} // deprecated: inline and not internal linkage +void f(int...); // deprecated +void g(auto...); // OK, declares a function parameter pack +void h(auto......); // deprecated \end{codeblock} \end{example} @@ -166,12 +143,29 @@ It is possible that future versions of \Cpp{} will specify that these implicit definitions are deleted\iref{dcl.fct.def.delete}. +\rSec1[depr.static.constexpr]{Redeclaration of \tcode{static constexpr} data members} + +\pnum +For compatibility with prior revisions of \Cpp{}, a \keyword{constexpr} +static data member may be redundantly redeclared outside the class with no +initializer\iref{basic.def,class.static.data}. +This usage is deprecated. +\begin{example} +\begin{codeblock} +struct A { + static constexpr int n = 5; // definition (declaration in \CppXIV{}) +}; + +constexpr int A::n; // redundant declaration (definition in \CppXIV{}) +\end{codeblock} +\end{example} + \rSec1[depr.lit]{Literal operator function declarations using an identifier} \pnum A \grammarterm{literal-operator-id}\iref{over.literal} of the form \begin{codeblock} -operator @\grammarterm{string-literal}@ @\grammarterm{identifier}@ +operator @\grammarterm{unevaluated-string}@ @\grammarterm{identifier}@ \end{codeblock} is deprecated. @@ -187,13 +181,12 @@ \pnum The following type is defined in addition to those specified in \libheaderref{limits}: -\indexlibraryglobal{float_denorm_style}% \begin{codeblock} namespace std { - enum float_denorm_style { - denorm_indeterminate = -1, - denorm_absent = 0, - denorm_present = 1 + enum @\libglobal{float_denorm_style}@ { + @\libmember{denorm_indeterminate}{float_denorm_style}@ = -1, + @\libmember{denorm_absent}{float_denorm_style}@ = 0, + @\libmember{denorm_present}{float_denorm_style}@ = 1 }; } \end{codeblock} @@ -227,2177 +220,494 @@ \rSec1[depr.c.macros]{Deprecated C macros} \pnum -The header \libheader{stdalign.h} has the following macro: -\indexheader{stdalign.h}% -\indexlibraryglobal{__alignas_is_defined}% +The header \libheaderref{cfloat} has the following macros: \begin{codeblock} -#define @\xname{alignas_is_defined}@ 1 +#define @\libmacro{FLT_HAS_SUBNORM}@ @\seebelow@ +#define @\libmacro{DBL_HAS_SUBNORM}@ @\seebelow@ +#define @\libmacro{LDBL_HAS_SUBNORM}@ @\seebelow@ +#define @\libmacro{DECIMAL_DIG}@ @\seebelow@ \end{codeblock} +The header defines these macros the same as +the C standard library header \libheader{float.h}. + +\xrefc{5.2.4.2.2, 7.33.5} \pnum -The header \libheader{stdbool.h} has the following macro: -\indexheader{stdbool.h}% -\indexhdr{stdbool.h}% -\indexlibraryglobal{__bool_true_false_are_defined}% -\begin{codeblock} -#define @\xname{bool_true_false_are_defined}@ 1 -\end{codeblock} +In addition to being available via inclusion of the \libheader{cfloat} header, +the macros \tcode{INFINITY} and \tcode{NAN} are +available when \libheaderref{cmath} is included. -\rSec1[depr.relops]{Relational operators}% -\indexlibraryglobal{rel_ops}% +\xrefc{7.12} \pnum -The header \libheaderref{utility} has the following additions: - +The header \libheaderref{stdbool.h} has the following macro: \begin{codeblock} -namespace std::rel_ops { - template bool operator!=(const T&, const T&); - template bool operator> (const T&, const T&); - template bool operator<=(const T&, const T&); - template bool operator>=(const T&, const T&); -} +#define @\libxmacro{bool_true_false_are_defined}@ 1 \end{codeblock} -\pnum -To avoid redundant definitions of \tcode{operator!=} out of \tcode{operator==} -and operators \tcode{>}, \tcode{<=}, and \tcode{>=} out of \tcode{operator<}, -the library provides the following: - -\indexlibrary{\idxcode{operator"!=}}% -\begin{itemdecl} -template bool operator!=(const T& x, const T& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{T} meets the \oldconcept{EqualityComparable} requirements (\tref{cpp17.equalitycomparable}). - -\pnum -\returns -\tcode{!(x == y)}. -\end{itemdescr} - -\indexlibraryglobal{operator>}% -\begin{itemdecl} -template bool operator>(const T& x, const T& y); -\end{itemdecl} +\xrefc{7.19} -\begin{itemdescr} -\pnum -\expects -\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). +\rSec1[depr.cerrno]{Deprecated error numbers} \pnum -\returns -\tcode{y < x}. -\end{itemdescr} +The header \libheaderref{cerrno} has the following additional macros: -\indexlibrary{\idxcode{operator<=}}% -\begin{itemdecl} -template bool operator<=(const T& x, const T& y); -\end{itemdecl} +\begin{codeblock} +#define @\libmacro{ENODATA}@ @\seebelow@ +#define @\libmacro{ENOSR}@ @\seebelow@ +#define @\libmacro{ENOSTR}@ @\seebelow@ +#define @\libmacro{ETIME}@ @\seebelow@ +\end{codeblock} -\begin{itemdescr} \pnum -\expects -\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). +The meaning of these macros is defined by the POSIX standard. \pnum -\returns -\tcode{!(y < x)}. -\end{itemdescr} - -\indexlibrary{\idxcode{operator>=}}% -\begin{itemdecl} -template bool operator>=(const T& x, const T& y); -\end{itemdecl} +The following \tcode{enum errc} enumerators are defined +in addition to those specified in \ref{system.error.syn}: -\begin{itemdescr} -\pnum -\expects -\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). +\begin{codeblock} +@\libmember{no_message_available}{errc}@, // \tcode{ENODATA} +@\libmember{no_stream_resources}{errc}@, // \tcode{ENOSR} +@\libmember{not_a_stream}{errc}@, // \tcode{ENOSTR} +@\libmember{stream_timeout}{errc}@, // \tcode{ETIME} +\end{codeblock} \pnum -\returns -\tcode{!(x < y)}. -\end{itemdescr} - -\rSec1[depr.str.strstreams]{\tcode{char*} streams} +The value of each \tcode{enum errc} enumerator above +is the same as the value of the \libheader{cerrno} macro +shown in the above synopsis. -\rSec2[depr.strstream.syn]{Header \tcode{} synopsis} +\rSec1[depr.meta.types]{Deprecated type traits} \pnum -The header \libheaderdef{strstream} -defines types that associate stream buffers with -character array objects and assist reading and writing such objects. - -\begin{codeblock} -namespace std { - class strstreambuf; - class istrstream; - class ostrstream; - class strstream; -} -\end{codeblock} - -\rSec2[depr.strstreambuf]{Class \tcode{strstreambuf}} - -\rSec3[depr.strstreambuf.general]{General} +The header \libheaderrefx{type_traits}{meta.type.synop} +has the following addition: -\indexlibraryglobal{strstreambuf}% \begin{codeblock} namespace std { - class strstreambuf : public basic_streambuf { - public: - strstreambuf() : strstreambuf(0) {} - explicit strstreambuf(streamsize alsize_arg); - strstreambuf(void* (*palloc_arg)(size_t), void (*pfree_arg)(void*)); - strstreambuf(char* gnext_arg, streamsize n, char* pbeg_arg = nullptr); - strstreambuf(const char* gnext_arg, streamsize n); - - strstreambuf(signed char* gnext_arg, streamsize n, - signed char* pbeg_arg = nullptr); - strstreambuf(const signed char* gnext_arg, streamsize n); - strstreambuf(unsigned char* gnext_arg, streamsize n, - unsigned char* pbeg_arg = nullptr); - strstreambuf(const unsigned char* gnext_arg, streamsize n); - - virtual ~strstreambuf(); - - void freeze(bool freezefl = true); - char* str(); - int pcount(); - - protected: - int_type overflow (int_type c = EOF) override; - int_type pbackfail(int_type c = EOF) override; - int_type underflow() override; - pos_type seekoff(off_type off, ios_base::seekdir way, - ios_base::openmode which = ios_base::in | ios_base::out) override; - pos_type seekpos(pos_type sp, - ios_base::openmode which = ios_base::in | ios_base::out) override; - streambuf* setbuf(char* s, streamsize n) override; - - private: - using strstate = T1; // \expos - static const strstate allocated; // \expos - static const strstate constant; // \expos - static const strstate dynamic; // \expos - static const strstate frozen; // \expos - strstate strmode; // \expos - streamsize alsize; // \expos - void* (*palloc)(size_t); // \expos - void (*pfree)(void*); // \expos - }; + template struct is_trivial; + template constexpr bool is_trivial_v = is_trivial::value; + template struct is_pod; + template 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} \pnum -The class -\tcode{strstreambuf} -associates the input sequence, and possibly the output sequence, with an object of some -\textit{character} -array type, whose elements store arbitrary values. -The array object has several attributes. - -\pnum -\begin{note} -For the sake of exposition, these are represented as elements of a bitmask type -(indicated here as \tcode{T1}) called \tcode{strstate}. -The elements are: -\begin{itemize} -\item -\tcode{allocated}, set when a dynamic array object has been -allocated, and hence will be freed by the destructor for the -\tcode{strstreambuf} object; -\item -\tcode{constant}, set when the array object has -\keyword{const} elements, so the output sequence cannot be written; -\item -\tcode{dynamic}, set when the array object is allocated -(or reallocated) -as necessary to hold a character sequence that can change in length; -\item -\tcode{frozen}, set when the program has requested that the -array object not be altered, reallocated, or freed. -\end{itemize} -\end{note} +The behavior of a program that adds specializations for +any of the templates defined in this subclause is undefined, +unless explicitly permitted by the specification of the corresponding template. \pnum +\label{term.trivial.type}% +A \defnadj{trivial}{class} is a class that is trivially copyable and +has one or more eligible default constructors, all of which are trivial. \begin{note} -For the sake of exposition, the maintained data is presented here as: -\begin{itemize} -\item -\tcode{strstate strmode}, the attributes of the array object -associated with the \tcode{strstreambuf} object; -\item -\tcode{int alsize}, the suggested minimum size for a -dynamic array object; -\item -\tcode{void* (*palloc)(size_t)}, points to the function -to call to allocate a dynamic array object; -\item -\tcode{void (*pfree)(void*)}, points to the function to -call to free a dynamic array object. -\end{itemize} +In particular, +a trivial class does not have virtual functions or virtual base classes. \end{note} +A \defnadj{trivial}{type} is a scalar type, a trivial class, +an array of such a type, or a cv-qualified version of one of these types. \pnum -Each object of class -\tcode{strstreambuf} -has a -\term{seekable area}, -delimited by the pointers \tcode{seeklow} and \tcode{seekhigh}. -If \tcode{gnext} is a null pointer, the seekable area is undefined. -Otherwise, \tcode{seeklow} equals \tcode{gbeg} and -\tcode{seekhigh} is either \tcode{pend}, -if \tcode{pend} is not a null pointer, or \tcode{gend}. - -\rSec3[depr.strstreambuf.cons]{\tcode{strstreambuf} constructors} +\indextext{POD}% +A \term{POD class} is a class that is both a trivial class and a +standard-layout class, and has no non-static data members of type non-POD class +(or array thereof). A \term{POD type} is a scalar type, a POD class, an array +of such a type, or a cv-qualified version of one of these types. -\indexlibraryctor{strstreambuf}% +\indexlibraryglobal{is_trivial}% \begin{itemdecl} -explicit strstreambuf(streamsize alsize_arg); +template struct is_trivial; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes the base class with \tcode{streambuf()}. -The postconditions of this function are indicated in \tref{depr.strstreambuf.cons.sz}. -\end{itemdescr} - -\begin{libtab2}{\tcode{strstreambuf(streamsize)} effects}{depr.strstreambuf.cons.sz} -{ll} -{Element}{Value} -\tcode{strmode} & \tcode{dynamic} \\ -\tcode{alsize} & \tcode{alsize_arg} \\ -\tcode{palloc} & a null pointer \\ -\tcode{pfree} & a null pointer \\ -\end{libtab2} +\expects +\tcode{remove_all_extents_t} shall be a complete type or \cv{} \keyword{void}. -\indexlibraryctor{strstreambuf}% -\begin{itemdecl} -strstreambuf(void* (*palloc_arg)(size_t), void (*pfree_arg)(void*)); -\end{itemdecl} +\pnum +\remarks +\tcode{is_trivial} is a \oldconcept{UnaryTypeTrait}\iref{meta.rqmts} +with a base characteristic of \tcode{true_type} +if \tcode{T} is a trivial type, +and \tcode{false_type} otherwise. -\begin{itemdescr} \pnum -\effects -Initializes the base class with \tcode{streambuf()}. -The postconditions of this function are indicated in \tref{depr.strstreambuf.cons.alloc}. - -\begin{libtab2}{\tcode{strstreambuf(void* (*)(size_t), void (*)(void*))} effects} -{depr.strstreambuf.cons.alloc} -{ll} -{Element}{Value} -\tcode{strmode} & \tcode{dynamic} \\ -\tcode{alsize} & an unspecified value \\ -\tcode{palloc} & \tcode{palloc_arg} \\ -\tcode{pfree} & \tcode{pfree_arg} \\ -\end{libtab2} +\begin{note} +It is unspecified +whether a closure type\iref{expr.prim.lambda.closure} is a trivial type. +\end{note} \end{itemdescr} -\indextext{unspecified}% -\indexlibraryctor{strstreambuf}% +\indexlibraryglobal{is_pod}% \begin{itemdecl} -strstreambuf(char* gnext_arg, streamsize n, char* pbeg_arg = nullptr); -strstreambuf(signed char* gnext_arg, streamsize n, - signed char* pbeg_arg = nullptr); -strstreambuf(unsigned char* gnext_arg, streamsize n, - unsigned char* pbeg_arg = nullptr); +template struct is_pod; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes the base class with \tcode{streambuf()}. -The postconditions of this function are indicated in \tref{depr.strstreambuf.cons.ptr}. - -\begin{libtab2}{\tcode{strstreambuf(charT*, streamsize, charT*)} effects} -{depr.strstreambuf.cons.ptr} -{ll} -{Element}{Value} -\tcode{strmode} & 0 \\ -\tcode{alsize} & an unspecified value \\ -\tcode{palloc} & a null pointer \\ -\tcode{pfree} & a null pointer \\ -\end{libtab2} - -\pnum -\tcode{gnext_arg} shall point to the first element of an array -object whose number of elements \tcode{N} is determined as follows: -\begin{itemize} -\item -If -\tcode{n > 0}, -\tcode{N} is \tcode{n}. -\item -If -\tcode{n == 0}, -\tcode{N} is -\tcode{std::strlen(gnext_arg)}. -\indexlibraryglobal{strlen}% -\item -If -\tcode{n < 0}, -\tcode{N} is -\tcode{INT_MAX}. -\begin{footnote} -The function signature -\indexlibraryglobal{strlen}% -\tcode{strlen(const char*)} -is declared in \libheaderref{cstring}. -The macro \tcode{INT_MAX} is defined in \libheaderref{climits}. -\end{footnote} -\end{itemize} +\expects +\tcode{remove_all_extents_t} shall be a complete type or \cv{} \keyword{void}. \pnum -If \tcode{pbeg_arg} is a null pointer, the function executes: - -\begin{codeblock} -setg(gnext_arg, gnext_arg, gnext_arg + N); -\end{codeblock} +\remarks +\tcode{is_pod} is a \oldconcept{UnaryTypeTrait}\iref{meta.rqmts} +with a base characteristic of \tcode{true_type} +if \tcode{T} is a POD type, +and \tcode{false_type} otherwise. \pnum -Otherwise, the function executes: - -\begin{codeblock} -setg(gnext_arg, gnext_arg, pbeg_arg); -setp(pbeg_arg, pbeg_arg + N); -\end{codeblock} +\begin{note} +It is unspecified whether a closure type\iref{expr.prim.lambda.closure} is a POD type. +\end{note} \end{itemdescr} - -\indexlibraryctor{strstreambuf}% +\indexlibraryglobal{aligned_storage}% \begin{itemdecl} -strstreambuf(const char* gnext_arg, streamsize n); -strstreambuf(const signed char* gnext_arg, streamsize n); -strstreambuf(const unsigned char* gnext_arg, streamsize n); +template + struct aligned_storage; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Behaves the same as -\tcode{strstreambuf((char*)gnext_arg,n)}, -except that the constructor also sets \tcode{constant} in \tcode{strmode}. -\end{itemdescr} - -\indexlibrarydtor{strstreambuf}% -\begin{itemdecl} -virtual ~strstreambuf(); -\end{itemdecl} +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}. -\begin{itemdescr} \pnum -\effects -Destroys an object of class -\tcode{strstreambuf}. -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.) -\end{itemdescr} - -\rSec3[depr.strstreambuf.members]{Member functions} - -\indexlibrarymember{freeze}{strstreambuf}% -\begin{itemdecl} -void freeze(bool freezefl = true); -\end{itemdecl} +\mandates +\tcode{Len} is not zero. +\tcode{Align} is equal to \tcode{alignof(T)} for some type \tcode{T} or +to \exposid{default-alignment}. -\begin{itemdescr} \pnum -\effects -If \tcode{strmode \& dynamic} is nonzero, alters the -freeze status of the dynamic array object as follows: -\begin{itemize} -\item -If \tcode{freezefl} is -\tcode{true}, -the function sets \tcode{frozen} in \tcode{strmode}. -\item -Otherwise, it clears \tcode{frozen} in \tcode{strmode}. -\end{itemize} -\end{itemdescr} - -\indexlibrarymember{str}{strstreambuf}% -\begin{itemdecl} -char* str(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls -\tcode{freeze()}, -then returns the beginning pointer for the input sequence, \tcode{gbeg}. - -\pnum -\remarks -The return value can be a null pointer. -\end{itemdescr} - -\indexlibrarymember{pcount}{strstreambuf}% -\begin{itemdecl} -int pcount() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If the next pointer for the output sequence, \tcode{pnext}, is -a null pointer, returns zero. -Otherwise, returns the current -effective length of the array object as the next pointer minus the beginning -pointer for the output sequence, \tcode{pnext - pbeg}. -\end{itemdescr} - -\rSec3[depr.strstreambuf.virtuals]{\tcode{strstreambuf} overridden virtual functions} - -\indexlibrarymember{overflow}{strstreambuf}% -\begin{itemdecl} -int_type overflow(int_type c = EOF) override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Appends the character designated by \tcode{c} to the output -sequence, if possible, in one of two ways: -\begin{itemize} -\item -If -\tcode{c != EOF} -and if either the output sequence has a write position available or -the function makes a write position available -(as described below), -assigns \tcode{c} to -\tcode{*pnext++}. - -Returns -\tcode{(unsigned char)c}. - -\item -If -\tcode{c == EOF}, -there is no character to append. - -Returns a value other than \tcode{EOF}. -\end{itemize} - -\pnum -Returns -\tcode{EOF} -to indicate failure. - -\pnum -\remarks -The function can alter the number of write positions available as a -result of any call. - -\pnum -To make a write position available, the function reallocates -(or initially allocates) -an array object with a sufficient number of elements -\tcode{n} to hold the current array object (if any), -plus at least one additional write position. -How many additional write positions are made -available is otherwise unspecified.% -\indextext{unspecified}% -If \tcode{palloc} is not a null pointer, the function calls -\tcode{(*palloc)(n)} -to allocate the new dynamic array object. -Otherwise, it evaluates the expression -\tcode{new charT[n]}. -In either case, if the allocation fails, the function returns -\tcode{EOF}. -Otherwise, it sets \tcode{allocated} in \tcode{strmode}. - -\pnum -To free a previously existing dynamic array object whose first -element address is \tcode{p}: -If \tcode{pfree} is not a null pointer, -the function calls -\tcode{(*pfree)(p)}. -Otherwise, it evaluates the expression \tcode{delete[]p}. - -\pnum -If -\tcode{(strmode \& dynamic) == 0}, -or if -\tcode{(strmode \& frozen) != 0}, -the function cannot extend the array (reallocate it with greater length) to make a write position available. - -\pnum -\recommended -An implementation should consider \tcode{alsize} in making the -decision how many additional write positions to make available. -\end{itemdescr} - -\indexlibrarymember{pbackfail}{strstreambuf}% -\begin{itemdecl} -int_type pbackfail(int_type c = EOF) override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -Puts back the character designated by \tcode{c} to the input -sequence, if possible, in one of three ways: -\begin{itemize} -\item -If -\tcode{c != EOF}, -if the input sequence has a putback position available, and if -\tcode{(char)c == gnext[-1]}, -assigns -\tcode{gnext - 1} -to \tcode{gnext}. - -Returns \tcode{c}. -\item -If -\tcode{c != EOF}, -if the input sequence has a putback position available, and if -\tcode{strmode \& constant} is zero, -assigns \tcode{c} to -\tcode{*--gnext}. - -Returns -\tcode{c}. -\item -If -\tcode{c == EOF} -and if the input sequence has a putback position available, -assigns -\tcode{gnext - 1} -to \tcode{gnext}. - -Returns a value other than -\tcode{EOF}. -\end{itemize} - -\pnum -Returns -\tcode{EOF} -to indicate failure. - -\pnum -\remarks -If the function can succeed in more than one of these ways, it is -unspecified which way is chosen. -\indextext{unspecified}% -The function can alter the number of putback -positions available as a result of any call. -\end{itemdescr} - -\indexlibrarymember{underflow}{strstreambuf}% -\begin{itemdecl} -int_type underflow() override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Reads a character from the -\term{input sequence}, -if possible, without moving the stream position past it, as follows: -\begin{itemize} -\item -If the input sequence has a read position available, the function -signals success by returning -\tcode{(unsigned char)\brk*gnext}. -\item -Otherwise, if -the current write next pointer \tcode{pnext} is not a null pointer and -is greater than the current read end pointer \tcode{gend}, -makes a -\term{read position} -available by -assigning to \tcode{gend} a value greater than \tcode{gnext} and -no greater than \tcode{pnext}. - -Returns \tcode{(unsigned char)*gnext}. -\end{itemize} - -\pnum -Returns -\tcode{EOF} -to indicate failure. - -\pnum -\remarks -The function can alter the number of read positions available as a -result of any call. -\end{itemdescr} - -\indexlibrarymember{seekoff}{strstreambuf}% -\begin{itemdecl} -pos_type seekoff(off_type off, seekdir way, openmode which = in | out) override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Alters the stream position within one of the -controlled sequences, if possible, as indicated in \tref{depr.strstreambuf.seekoff.pos}. - -\begin{libtab2}{\tcode{seekoff} positioning}{depr.strstreambuf.seekoff.pos} -{p{2.5in}l}{Conditions}{Result} -\tcode{(which \& ios::in) != 0} & - positions the input sequence \\ \rowsep -\tcode{(which \& ios::out) != 0} & - positions the output sequence \\ \rowsep -\tcode{(which \& (ios::in | ios::out)) ==}\br -\tcode{(ios::in | ios::out)} and either\br -\tcode{way == ios::beg} or \tcode{way == ios::end} & - positions both the input and the output sequences \\ \rowsep -Otherwise & - the positioning operation fails. \\ -\end{libtab2} - -\pnum -For a sequence to be positioned, if its next pointer is a null pointer, -the positioning operation fails. -Otherwise, the function determines \tcode{newoff} as indicated in -\tref{depr.strstreambuf.seekoff.newoff}. - -\begin{libtab2}{\tcode{newoff} values}{depr.strstreambuf.seekoff.newoff} -{p{2.0in}p{2.0in}}{Condition}{\tcode{newoff} Value} -\tcode{way == ios::beg} & - 0 \\ \rowsep -\tcode{way == ios::cur} & - the next pointer minus the beginning pointer (\tcode{xnext - xbeg}). \\ \rowsep -\tcode{way == ios::end} & - \tcode{seekhigh} minus the beginning pointer (\tcode{seekhigh - xbeg}). \\ -\end{libtab2} - -\pnum -If \tcode{(newoff + off) < (seeklow - xbeg)} -or \tcode{(seekhigh - xbeg) < (newoff + off)}, -the positioning operation fails. -Otherwise, the function assigns -\tcode{xbeg + newoff + off} -to the next pointer \tcode{xnext}. - -\pnum -\returns -\tcode{pos_type(newoff)}, -constructed from the resultant offset -\tcode{newoff} (of type -\tcode{off_type}), -that stores the resultant stream position, if possible. -If the positioning operation fails, or -if the constructed object cannot represent the resultant stream position, -the return value is -\tcode{pos_type(off_type(-1))}. -\end{itemdescr} - -\indexlibrarymember{seekpos}{strstreambuf}% -\begin{itemdecl} -pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Alters the stream position within one of the -controlled sequences, if possible, to correspond to the -stream position stored in \tcode{sp} -(as described below). -\begin{itemize} -\item -If -\tcode{(which \& ios::in) != 0}, -positions the input sequence. -\item -If -\tcode{(which \& ios::out) != 0}, -positions the output sequence. -\item -If the function positions neither sequence, the positioning operation fails. -\end{itemize} - -\pnum -For a sequence to be positioned, if its next pointer is a null pointer, -the positioning operation fails. -Otherwise, the function determines \tcode{newoff} from -\tcode{sp.offset()}: -\begin{itemize} -\item -If \tcode{newoff} is an invalid stream position, -has a negative value, or -has a value greater than (\tcode{seekhigh - seeklow}), -the positioning operation fails -\item -Otherwise, the function -adds \tcode{newoff} to the beginning pointer \tcode{xbeg} and -stores the result in the next pointer \tcode{xnext}. -\end{itemize} +The member typedef \tcode{type} denotes 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 -\returns -\tcode{pos_type(newoff)}, -constructed from the resultant offset \tcode{newoff} -(of type -\tcode{off_type}), -that stores the resultant stream position, if possible. -If the positioning operation fails, or -if the constructed object cannot represent the resultant stream position, -the return value is -\tcode{pos_type(off_type(-1))}. -\end{itemdescr} - -\indexlibrarymember{setbuf}{strstreambuf}% -\begin{itemdecl} -streambuf* setbuf(char* s, streamsize n) override; -\end{itemdecl} +\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} -\begin{itemdescr} \pnum -\effects -Behavior is \impldef{behavior of \tcode{strstreambuf::setbuf}}, -except that -\tcode{setbuf(0, 0)} -has no effect.% -\end{itemdescr} - -\rSec2[depr.istrstream]{Class \tcode{istrstream}} - -\rSec3[depr.istrstream.general]{General} - -\indexlibraryglobal{istrstream}% +\begin{note} +A typical implementation would define \tcode{aligned_storage} as: \begin{codeblock} -namespace std { - class istrstream : public basic_istream { - public: - explicit istrstream(const char* s); - explicit istrstream(char* s); - istrstream(const char* s, streamsize n); - istrstream(char* s, streamsize n); - virtual ~istrstream(); - - strstreambuf* rdbuf() const; - char* str(); - private: - strstreambuf sb; // \expos - }; -} +template +struct aligned_storage { + typedef struct { + alignas(Alignment) unsigned char __data[Len]; + } type; +}; \end{codeblock} +\end{note} -\pnum -The class -\tcode{istrstream} -supports the reading of objects of class -\tcode{strstreambuf}. -It supplies a -\tcode{strstreambuf} -object to control the associated array object. -For the sake of exposition, the maintained data is presented here as: - -\begin{itemize} -\item -\tcode{sb}, the \tcode{strstreambuf} object. -\end{itemize} - -\rSec3[depr.istrstream.cons]{\tcode{istrstream} constructors} - -\indexlibraryctor{istrstream}% -\begin{itemdecl} -explicit istrstream(const char* s); -explicit istrstream(char* s); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the base class with \tcode{istream(\&sb)} and -\tcode{sb} with \tcode{strstreambuf(s, 0)}. -\tcode{s} shall designate the first element of an \ntbs{}.% -\indextext{NTBS@\ntbs{}} \end{itemdescr} -\indexlibraryctor{istrstream}% +\indexlibraryglobal{aligned_union}% \begin{itemdecl} -istrstream(const char* s, streamsize n); -istrstream(char* s, streamsize n); +template + struct aligned_union; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes the base class with \tcode{istream(\&sb)} -and \tcode{sb} with \tcode{strstreambuf(s, n)}. -\tcode{s} shall designate the first element of an array whose length is -\tcode{n} elements, and \tcode{n} shall be greater than zero. -\end{itemdescr} - -\rSec3[depr.istrstream.members]{Member functions} - -\indexlibrarymember{rdbuf}{istrstream}% -\begin{itemdecl} -strstreambuf* rdbuf() const; -\end{itemdecl} +\mandates +At least one type is provided. +Each type in the template parameter pack \tcode{Types} +is a complete object type. -\begin{itemdescr} \pnum -\returns -\tcode{const_cast(\&sb)}. +The member typedef \tcode{type} denotes 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} -\indexlibrarymember{str}{istrstream}% -\begin{itemdecl} -char* str(); -\end{itemdecl} +\rSec1[depr.relops]{Relational operators}% +\indexlibraryglobal{rel_ops}% -\begin{itemdescr} \pnum -\returns -\tcode{rdbuf()->str()}. -\end{itemdescr} - -\rSec2[depr.ostrstream]{Class \tcode{ostrstream}} - -\rSec3[depr.ostrstream.general]{General} +The header \libheaderref{utility} has the following additions: -\indexlibraryglobal{ostrstream}% \begin{codeblock} -namespace std { - class ostrstream : public basic_ostream { - public: - ostrstream(); - ostrstream(char* s, int n, ios_base::openmode mode = ios_base::out); - virtual ~ostrstream(); - - strstreambuf* rdbuf() const; - void freeze(bool freezefl = true); - char* str(); - int pcount() const; - private: - strstreambuf sb; // \expos - }; +namespace std::rel_ops { + template bool operator!=(const T&, const T&); + template bool operator> (const T&, const T&); + template bool operator<=(const T&, const T&); + template bool operator>=(const T&, const T&); } \end{codeblock} \pnum -The class -\tcode{ostrstream} -supports the writing of objects of class -\tcode{strstreambuf}. -It supplies a -\tcode{strstreambuf} -object to control the associated array object. -For the sake of exposition, the maintained data is presented here as: - -\begin{itemize} -\item -\tcode{sb}, the \tcode{strstreambuf} object. -\end{itemize} - -\rSec3[depr.ostrstream.cons]{\tcode{ostrstream} constructors} - -\indexlibraryctor{ostrstream}% -\begin{itemdecl} -ostrstream(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the base class with \tcode{ostream(\&sb)} and -\tcode{sb} with \tcode{strstreambuf()}. -\end{itemdescr} +To avoid redundant definitions of \tcode{operator!=} out of \tcode{operator==} +and operators \tcode{>}, \tcode{<=}, and \tcode{>=} out of \tcode{operator<}, +the library provides the following: -\indexlibraryctor{ostrstream}% +\indexlibrary{\idxcode{operator"!=}}% \begin{itemdecl} -ostrstream(char* s, int n, ios_base::openmode mode = ios_base::out); +template bool operator!=(const T& x, const T& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes the base class with \tcode{ostream(\&sb)}, -and \tcode{sb} with one of two constructors: - -\begin{itemize} -\item -If -\tcode{(mode \& app) == 0}, -then \tcode{s} shall designate the first element of an array of \tcode{n} elements. - -The constructor is -\tcode{strstreambuf(s, n, s)}. -\item -If -\tcode{(mode \& app) != 0}, -then \tcode{s} shall designate the first element of an array of \tcode{n} elements that -contains an \ntbs{} whose first element is designated by \tcode{s}. -\indextext{NTBS@\ntbs{}}% -The constructor is -\tcode{strstreambuf(s, n, s + std::strlen(s))}. -\begin{footnote} -The function signature -\indexlibraryglobal{strlen}% -\tcode{strlen(const char*)} -is declared in \libheaderref{cstring}. -\end{footnote} -\end{itemize} -\end{itemdescr} - -\rSec3[depr.ostrstream.members]{Member functions} - -\indexlibrarymember{rdbuf}{ostrstream}% -\begin{itemdecl} -strstreambuf* rdbuf() const; -\end{itemdecl} +\expects +\tcode{T} meets the \oldconcept{EqualityComparable} requirements (\tref{cpp17.equalitycomparable}). -\begin{itemdescr} \pnum \returns -\tcode{(strstreambuf*)\&sb}. -\end{itemdescr} - -\indexlibrarymember{freeze}{ostrstream}% -\begin{itemdecl} -void freeze(bool freezefl = true); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls -\tcode{rdbuf()->freeze(freezefl)}. +\tcode{!(x == y)}. \end{itemdescr} -\indexlibrarymember{str}{ostrstream}% +\indexlibraryglobal{operator>}% \begin{itemdecl} -char* str(); +template bool operator>(const T& x, const T& y); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{rdbuf()->str()}. -\end{itemdescr} - -\indexlibrarymember{pcount}{ostrstream}% -\begin{itemdecl} -int pcount() const; -\end{itemdecl} +\expects +\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). -\begin{itemdescr} \pnum \returns -\tcode{rdbuf()->pcount()}. -\end{itemdescr} - -\rSec2[depr.strstream]{Class \tcode{strstream}} - -\rSec3[depr.strstream.general]{General} - -\indexlibraryglobal{strstream}% -\begin{codeblock} -namespace std { - class strstream - : public basic_iostream { - public: - // types - using char_type = char; - using int_type = char_traits::int_type; - using pos_type = char_traits::pos_type; - using off_type = char_traits::off_type; - - // constructors/destructor - strstream(); - strstream(char* s, int n, - ios_base::openmode mode = ios_base::in|ios_base::out); - virtual ~strstream(); - - // members - strstreambuf* rdbuf() const; - void freeze(bool freezefl = true); - int pcount() const; - char* str(); - - private: - strstreambuf sb; // \expos - }; -} -\end{codeblock} - -\pnum -The class -\tcode{strstream} -supports reading and writing from objects of class -\tcode{strstreambuf}. -It supplies a -\tcode{strstreambuf} -object to control the associated array object. -For the sake of exposition, the maintained data is presented here as: - -\begin{itemize} -\item -\tcode{sb}, the \tcode{strstreambuf} object. -\end{itemize} - -\rSec3[depr.strstream.cons]{\tcode{strstream} constructors} - -\indexlibraryctor{strstream}% -\begin{itemdecl} -strstream(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the base class with \tcode{iostream(\&sb)}. +\tcode{y < x}. \end{itemdescr} -\indexlibraryctor{strstream}% -\begin{itemdecl} -strstream(char* s, int n, - ios_base::openmode mode = ios_base::in|ios_base::out); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes the base class with \tcode{iostream(\&sb)}, -and \tcode{sb} with one of the two constructors: -\begin{itemize} -\item -If -\tcode{(mode \& app) == 0}, -then \tcode{s} shall designate the first element of an array of \tcode{n} elements. -The constructor is -\tcode{strstreambuf(s,n,s)}. -\item -If -\tcode{(mode \& app) != 0}, -then \tcode{s} shall -designate the first element of an array of \tcode{n} elements that contains -an \ntbs{} whose first element is designated by \tcode{s}. -The constructor is -\tcode{strstreambuf(s,n,s + std::strlen(s))}. -\indexlibrarydtor{strstream}% -\end{itemize} -\end{itemdescr} - -\rSec3[depr.strstream.dest]{\tcode{strstream} destructor} - -\indexlibrarydtor{strstream}% -\begin{itemdecl} -virtual ~strstream(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Destroys an object of class -\tcode{strstream}. -\end{itemdescr} - -\rSec3[depr.strstream.oper]{\tcode{strstream} operations} - -\indexlibrarymember{rdbuf}{strstream}% -\begin{itemdecl} -strstreambuf* rdbuf() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{const_cast(\&sb)}. -\end{itemdescr} - -\indexlibrarymember{freeze}{strstream}% -\begin{itemdecl} -void freeze(bool freezefl = true); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls -\tcode{rdbuf()->freeze(freezefl)}. -\end{itemdescr} - -\indexlibrarymember{str}{strstream}% -\begin{itemdecl} -char* str(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{rdbuf()->str()}. -\end{itemdescr} - -\indexlibrarymember{pcount}{strstream}% -\begin{itemdecl} -int pcount() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{rdbuf()->pcount()}. -\end{itemdescr} - -\rSec1[depr.cerrno]{Deprecated error numbers} - -\pnum -The following macros are defined in addition to those -specified in \ref{cerrno.syn}: - -\indexlibraryglobal{ENODATA}% -\indexlibraryglobal{ENOSR}% -\indexlibraryglobal{ENOSTR}% -\indexlibraryglobal{ETIME}% -\begin{codeblock} -#define ENODATA @\seebelow@ -#define ENOSR @\seebelow@ -#define ENOSTR @\seebelow@ -#define ETIME @\seebelow@ -\end{codeblock} - -\pnum -The meaning of these macros is defined by the POSIX standard. - -\pnum -The following \tcode{enum errc} enumerators are defined -in addition to those specified in \ref{system.error.syn}: - -\begin{codeblock} -no_message_available, // \tcode{ENODATA} -no_stream_resources, // \tcode{ENOSR} -not_a_stream, // \tcode{ENOSTR} -stream_timeout, // \tcode{ETIME} -\end{codeblock} - -\pnum -The value of each \tcode{enum errc} enumerator above -is the same as the value of the \libheader{cerrno} macro -shown in the above synopsis. - -\rSec1[depr.mem.poly.allocator.mem]{Deprecated \tcode{polymorphic_allocator} member function} - -\pnum -The following member is declared in addition to those members -specified in \ref{mem.poly.allocator.mem}: - -\begin{codeblock} -namespace std::pmr { - template - class polymorphic_allocator { - public: - template - void destroy(T* p); - }; -} -\end{codeblock} - -\indexlibrarymember{destroy}{polymorphic_allocator}% -\begin{itemdecl} -template - void destroy(T* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by \tcode{p->\~T()}. -\end{itemdescr} - -\rSec1[depr.meta.types]{Deprecated type traits} - -\pnum -The header \libheaderrefx{type_traits}{meta.type.synop} -has the following addition: - -\begin{codeblock} -namespace std { - template struct is_pod; - template 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} - -\pnum -The behavior of a program that adds specializations for -any of the templates defined in this subclause is undefined, -unless explicitly permitted by the specification of the corresponding template. - -\pnum -\indextext{POD}% -A \term{POD class} is a class that is both a trivial class and a -standard-layout class, and has no non-static data members of type non-POD class -(or array thereof). A \term{POD type} is a scalar type, a POD class, an array -of such a type, or a cv-qualified version of one of these types. - -\indexlibraryglobal{is_pod}% -\begin{itemdecl} -template struct is_pod; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{remove_all_extents_t} shall be a complete type or \cv{} \keyword{void}. - -\pnum -\remarks -\tcode{is_pod} is a \oldconcept{UnaryTypeTrait}\iref{meta.rqmts} -with a base characteristic of \tcode{true_type} -if \tcode{T} is a POD type, -and \tcode{false_type} otherwise. - -\pnum -\begin{note} -It is unspecified whether a closure type\iref{expr.prim.lambda.closure} is a POD type. -\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} denotes 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} denotes 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 -The header \libheaderref{tuple} has the following additions: - -\begin{codeblock} -namespace std { - template struct tuple_size; - template struct tuple_size; - - template struct tuple_element; - template struct tuple_element; -} -\end{codeblock} - -\begin{itemdecl} -template struct tuple_size; -template struct tuple_size; -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{TS} denote \tcode{tuple_size} of the cv-unqualified type \tcode{T}. -If the expression \tcode{TS::value} is well-formed -when treated as an unevaluated operand\iref{term.unevaluated.operand}, -then specializations of each of the two templates meet -the \oldconcept{TransformationTrait} requirements with a base characteristic of -\tcode{integral_constant}. -Otherwise, they have no member \tcode{value}. - -\pnum -Access checking is performed as if -in a context unrelated to \tcode{TS} and \tcode{T}. -Only the validity of the immediate context of the expression is considered. - -\pnum -In addition to being available via inclusion of the \libheaderref{tuple} header, -the two templates are available when any of the headers -\libheaderref{array}, -\libheaderref{ranges}, or -\libheaderref{utility} -are included. -\end{itemdescr} - -\begin{itemdecl} -template struct tuple_element; -template struct tuple_element; -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{TE} denote \tcode{tuple_element_t} -of the cv-unqualified type \tcode{T}. -Then specializations of each of the two templates meet -the \oldconcept{TransformationTrait} requirements -with a member typedef \tcode{type} that names the following type: -\begin{itemize} -\item for the first specialization, \tcode{add_volatile_t}, and -\item for the second specialization, \tcode{add_cv_t}. -\end{itemize} - -\pnum -In addition to being available via inclusion of the \libheaderref{tuple} header, -the two templates are available when any of the headers -\libheaderref{array}, -\libheaderref{ranges}, or -\libheaderref{utility} -are included. -\end{itemdescr} - -\rSec1[depr.variant]{Variant} - -\pnum -The header \libheaderref{variant} has the following additions: - -\begin{codeblock} -namespace std { - template struct variant_size; - template struct variant_size; - - template struct variant_alternative; - template struct variant_alternative; -} -\end{codeblock} - -\begin{itemdecl} -template struct variant_size; -template struct variant_size; -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VS} denote \tcode{variant_size} -of the cv-unqualified type \tcode{T}. -Then specializations of each of the two templates meet -the \oldconcept{UnaryTypeTrait} requirements -with a base characteristic of \tcode{integral_constant}. -\end{itemdescr} - -\begin{itemdecl} -template struct variant_alternative; -template struct variant_alternative; -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VA} denote \tcode{variant_alternative} -of the cv-unqualified type \tcode{T}. -Then specializations of each of the two templates meet -the \oldconcept{TransformationTrait} requirements -with a member typedef \tcode{type} that names the following type: -\begin{itemize} -\item for the first specialization, \tcode{add_volatile_t}, and -\item for the second specialization, \tcode{add_cv_t}. -\end{itemize} -\end{itemdescr} - -\rSec1[depr.iterator]{Deprecated \tcode{iterator} class template} - -\pnum -The header \libheaderrefx{iterator}{iterator.synopsis} has the following addition: - -\indexlibraryglobal{iterator}% -\begin{codeblock} -namespace std { - template - struct iterator { - using iterator_category = Category; - using value_type = T; - using difference_type = Distance; - using pointer = Pointer; - using reference = Reference; - }; -} -\end{codeblock} - -\pnum -The -\tcode{iterator} -template may be used as a base class to ease the definition of required types -for new iterators. - -\pnum -\begin{note} -If the new iterator type is a class template, then these aliases -will not be visible from within the iterator class's template definition, but -only to callers of that class. -\end{note} - -\pnum -\begin{example} -If a \Cpp{} program wants to define a bidirectional iterator for some data -structure containing \tcode{double} and such that it works on a large memory -model of the implementation, it can do so with: - -\begin{codeblock} -class MyIterator : - public iterator { - // code implementing \tcode{++}, etc. -}; -\end{codeblock} -\end{example} - -\rSec1[depr.move.iter.elem]{Deprecated \tcode{move_iterator} access} - -\pnum -The following member is declared in addition to those members -specified in \ref{move.iter.elem}: - -\begin{codeblock} -namespace std { - template - class move_iterator { - public: - constexpr pointer operator->() const; - }; -} -\end{codeblock} - -\indexlibrarymember{operator->}{move_iterator}% -\begin{itemdecl} -constexpr pointer operator->() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{current}. -\end{itemdescr} - -\rSec1[depr.util.smartptr.shared.atomic]{Deprecated \tcode{shared_ptr} atomic access} - -\pnum -The header \libheaderref{memory} has the following additions: - -\indexlibraryglobal{shared_ptr}% -\begin{codeblock} -namespace std { - template - bool atomic_is_lock_free(const shared_ptr* p); - - template - shared_ptr atomic_load(const shared_ptr* p); - template - shared_ptr atomic_load_explicit(const shared_ptr* p, memory_order mo); - - template - void atomic_store(shared_ptr* p, shared_ptr r); - template - void atomic_store_explicit(shared_ptr* p, shared_ptr r, memory_order mo); - - template - shared_ptr atomic_exchange(shared_ptr* p, shared_ptr r); - template - shared_ptr atomic_exchange_explicit(shared_ptr* p, shared_ptr r, memory_order mo); - - template - bool atomic_compare_exchange_weak(shared_ptr* p, shared_ptr* v, shared_ptr w); - template - bool atomic_compare_exchange_strong(shared_ptr* p, shared_ptr* v, shared_ptr w); - template - bool atomic_compare_exchange_weak_explicit( - shared_ptr* p, shared_ptr* v, shared_ptr w, - memory_order success, memory_order failure); - template - bool atomic_compare_exchange_strong_explicit( - shared_ptr* p, shared_ptr* v, shared_ptr w, - memory_order success, memory_order failure); -} -\end{codeblock} - -\pnum -Concurrent access to a \tcode{shared_ptr} object from multiple threads does not -introduce a data race if the access is done exclusively via the functions in -this subclause and the instance is passed as their first argument. - -\pnum -The meaning of the arguments of type \tcode{memory_order} is explained in~\ref{atomics.order}. - -\indexlibrarymember{atomic_is_lock_free}{shared_ptr}% -\begin{itemdecl} -template bool atomic_is_lock_free(const shared_ptr* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null. - -\pnum -\returns -\tcode{true} if atomic access to \tcode{*p} is lock-free, \tcode{false} otherwise. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_load}{shared_ptr}% -\begin{itemdecl} -template shared_ptr atomic_load(const shared_ptr* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null. - -\pnum -\returns -\tcode{atomic_load_explicit(p, memory_order::seq_cst)}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_load_explicit}{shared_ptr}% -\begin{itemdecl} -template shared_ptr atomic_load_explicit(const shared_ptr* p, memory_order mo); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null. -\tcode{mo} is neither \tcode{memory_order::release} nor \tcode{memory_order::acq_rel}. - -\pnum -\returns -\tcode{*p}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_store}{shared_ptr}% -\begin{itemdecl} -template void atomic_store(shared_ptr* p, shared_ptr r); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null. - -\pnum -\effects -As if by \tcode{atomic_store_explicit(p, r, memory_order::seq_cst)}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_store_explicit}{shared_ptr}% -\begin{itemdecl} -template void atomic_store_explicit(shared_ptr* p, shared_ptr r, memory_order mo); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null. -\tcode{mo} is neither \tcode{memory_order::acquire} nor \tcode{memory_order::acq_rel}. - -\pnum -\effects -As if by \tcode{p->swap(r)}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_exchange}{shared_ptr}% -\begin{itemdecl} -template shared_ptr atomic_exchange(shared_ptr* p, shared_ptr r); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null. - -\pnum -\returns -\tcode{atomic_exchange_explicit(p, r, memory_order::seq_cst)}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_exchange_explicit}{shared_ptr}% -\begin{itemdecl} -template - shared_ptr atomic_exchange_explicit(shared_ptr* p, shared_ptr r, memory_order mo); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null. - -\pnum -\effects -As if by \tcode{p->swap(r)}. - -\pnum -\returns -The previous value of \tcode{*p}. - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_compare_exchange_weak}{shared_ptr}% -\begin{itemdecl} -template - bool atomic_compare_exchange_weak(shared_ptr* p, shared_ptr* v, shared_ptr w); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null and \tcode{v} is not null. - -\pnum -\returns -\begin{codeblock} -atomic_compare_exchange_weak_explicit(p, v, w, memory_order::seq_cst, memory_order::seq_cst) -\end{codeblock} - -\pnum -\throws -Nothing. -\end{itemdescr} - -\indexlibrarymember{atomic_compare_exchange_strong}{shared_ptr}% -\begin{itemdecl} -template - bool atomic_compare_exchange_strong(shared_ptr* p, shared_ptr* v, shared_ptr w); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\begin{codeblock} -atomic_compare_exchange_strong_explicit(p, v, w, memory_order::seq_cst, - memory_order::seq_cst) -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{atomic_compare_exchange_weak_explicit}{shared_ptr}% -\indexlibrarymember{atomic_compare_exchange_strong_explicit}{shared_ptr}% -\begin{itemdecl} -template - bool atomic_compare_exchange_weak_explicit( - shared_ptr* p, shared_ptr* v, shared_ptr w, - memory_order success, memory_order failure); -template - bool atomic_compare_exchange_strong_explicit( - shared_ptr* p, shared_ptr* v, shared_ptr w, - memory_order success, memory_order failure); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{p} is not null and \tcode{v} is not null. -The \tcode{failure} argument is neither \tcode{memory_order::release} nor -\tcode{memory_order::acq_rel}. - -\pnum -\effects -If \tcode{*p} is equivalent to \tcode{*v}, assigns \tcode{w} to -\tcode{*p} and has synchronization semantics corresponding to the value of -\tcode{success}, otherwise assigns \tcode{*p} to \tcode{*v} and has -synchronization semantics corresponding to the value of \tcode{failure}. - -\pnum -\returns -\tcode{true} if \tcode{*p} was equivalent to \tcode{*v}, \tcode{false} otherwise. - -\pnum -\throws -Nothing. - -\pnum -\remarks -Two \tcode{shared_ptr} objects are equivalent if they store the same -pointer value and share ownership. -The weak form may fail spuriously. See~\ref{atomics.types.operations}. -\end{itemdescr} - -\rSec1[depr.format]{Deprecated formatting} - -\rSec2[depr.format.syn]{Header \tcode{} synopsis} - -\pnum -The header \libheaderref{format}{format.syn} has the following additions: - -\begin{codeblock} -namespace std { - template - decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg arg); -} -\end{codeblock} - -\rSec2[depr.format.arg]{Formatting arguments} - -\indexlibraryglobal{visit_format_arg}% -\begin{itemdecl} -template - decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg arg); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return visit(std::forward(vis), arg.value);} -\end{itemdescr} - -\rSec1[depr.conversions]{Deprecated convenience conversion interfaces} - -\rSec2[depr.conversions.general]{General} - -\pnum -The header \libheaderref{locale} has the following additions: - -\begin{codeblock} -namespace std { - template, - class ByteAlloc = allocator> - class wstring_convert; - - template> - class wbuffer_convert; -} -\end{codeblock} - -\rSec2[depr.conversions.string]{Class template \tcode{wstring_convert}} - -\pnum -Class template \tcode{wstring_convert} performs conversions between a wide -string and a byte string. It lets you specify a code conversion facet -(like class template \tcode{codecvt}) to perform the conversions, without -affecting any streams or locales. -\begin{example} -If you want to use a code -conversion facet, \tcode{codecvt_for_utf8}, to output to \tcode{cout} a UTF-8 -multibyte sequence corresponding to a wide string, but you don't want to -alter the locale for \tcode{cout}, you can write something like: -\begin{codeblock} -std::wstring_convert> myconv; -std::string mbstring = myconv.to_bytes(L"Hello\n"); -std::cout << mbstring; -\end{codeblock} -\end{example} - -\indexlibraryglobal{wstring_convert}% -\indexlibrarymember{byte_string}{wstring_convert}% -\indexlibrarymember{int_type}{wstring_convert}% -\indexlibrarymember{state_type}{wstring_convert}% -\indexlibrarymember{wide_string}{wstring_convert}% -\begin{codeblock} -namespace std { - template, - class ByteAlloc = allocator> - class wstring_convert { - public: - using byte_string = basic_string, ByteAlloc>; - using wide_string = basic_string, WideAlloc>; - using state_type = typename Codecvt::state_type; - using int_type = typename wide_string::traits_type::int_type; - - wstring_convert() : wstring_convert(new Codecvt) {} - explicit wstring_convert(Codecvt* pcvt); - wstring_convert(Codecvt* pcvt, state_type state); - explicit wstring_convert(const byte_string& byte_err, - const wide_string& wide_err = wide_string()); - ~wstring_convert(); - - wstring_convert(const wstring_convert&) = delete; - wstring_convert& operator=(const wstring_convert&) = delete; - - wide_string from_bytes(char byte); - wide_string from_bytes(const char* ptr); - wide_string from_bytes(const byte_string& str); - wide_string from_bytes(const char* first, const char* last); - - byte_string to_bytes(Elem wchar); - byte_string to_bytes(const Elem* wptr); - byte_string to_bytes(const wide_string& wstr); - byte_string to_bytes(const Elem* first, const Elem* last); - - size_t converted() const noexcept; - state_type state() const; - - private: - byte_string byte_err_string; // \expos - wide_string wide_err_string; // \expos - Codecvt* cvtptr; // \expos - state_type cvtstate; // \expos - size_t cvtcount; // \expos - }; -} -\end{codeblock} - -\pnum -The class template describes an object that controls conversions between wide -string objects of class \tcode{basic_string, -WideAlloc>} and byte string objects of class \tcode{basic_string, ByteAlloc>}. The class template defines the types -\tcode{wide_string} and \tcode{byte_string} as synonyms for these two types. -Conversion between a sequence of \tcode{Elem} values (stored in a -\tcode{wide_string} object) and multibyte sequences (stored in a -\tcode{byte_string} object) is performed by an object of class -\tcode{Codecvt}, which meets the -requirements of the standard code-conversion facet \tcode{codecvt}. - -\pnum -An object of this class template stores: - -\begin{itemize} -\item \tcode{byte_err_string} --- a byte string to display on errors -\item \tcode{wide_err_string} --- a wide string to display on errors -\item \tcode{cvtptr} --- a pointer to the allocated conversion object -(which is freed when the \tcode{wstring_convert} object is destroyed) -\item \tcode{cvtstate} --- a conversion state object -\item \tcode{cvtcount} --- a conversion count -\end{itemize} - -\indexlibrarymember{converted}{wstring_convert}% -\begin{itemdecl} -size_t converted() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{cvtcount}. -\end{itemdescr} - -\indexlibrarymember{from_bytes}{wstring_convert}% -\begin{itemdecl} -wide_string from_bytes(char byte); -wide_string from_bytes(const char* ptr); -wide_string from_bytes(const byte_string& str); -wide_string from_bytes(const char* first, const char* last); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -The first member function converts the single-element sequence \tcode{byte} to a -wide string. The second member function converts the null-terminated -sequence beginning at \tcode{ptr} to a wide string. The third member function -converts the sequence stored in \tcode{str} to a wide string. The fourth member -function converts the sequence defined by the range \range{first}{last} to a -wide string. - -\pnum -In all cases: - -\begin{itemize} -\item If the \tcode{cvtstate} object was not constructed with an explicit value, it -is set to its default value (the initial conversion state) before the -conversion begins. Otherwise it is left unchanged. - -\item The number of input elements successfully converted is stored in \tcode{cvtcount}. -\end{itemize} - -\pnum -\returns -If no conversion error occurs, the member function returns the converted wide string. -Otherwise, if the object was constructed with a wide-error string, the -member function returns the wide-error string. -Otherwise, the member function throws an object of class \tcode{range_error}. -\end{itemdescr} - -\indexlibrarymember{state}{wstring_convert}% +\indexlibrary{\idxcode{operator<=}}% \begin{itemdecl} -state_type state() const; +template bool operator<=(const T& x, const T& y); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). + \pnum \returns -\tcode{cvtstate}. +\tcode{!(y < x)}. \end{itemdescr} -\indexlibrarymember{to_bytes}{wstring_convert}% +\indexlibrary{\idxcode{operator>=}}% \begin{itemdecl} -byte_string to_bytes(Elem wchar); -byte_string to_bytes(const Elem* wptr); -byte_string to_bytes(const wide_string& wstr); -byte_string to_bytes(const Elem* first, const Elem* last); +template bool operator>=(const T& x, const T& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -The first member function converts the single-element sequence \tcode{wchar} to a byte string. -The second member function converts the null-terminated sequence beginning at \tcode{wptr} to -a byte string. The third member function converts the sequence stored in \tcode{wstr} to a -byte string. The fourth member function converts the sequence defined by the -range \range{first}{last} to a byte string. +\expects +\tcode{T} meets the \oldconcept{LessThanComparable} requirements (\tref{cpp17.lessthancomparable}). \pnum -In all cases: +\returns +\tcode{!(x < y)}. +\end{itemdescr} -\begin{itemize} -\item If the \tcode{cvtstate} object was not constructed with an explicit value, -it is set to its default value (the initial conversion state) before the -conversion begins. Otherwise it is left unchanged. -\item The number of input elements successfully converted is stored -in \tcode{cvtcount}. -\end{itemize} +\rSec1[depr.tuple]{Tuple} \pnum -\returns -If no conversion error occurs, the member function returns the converted byte string. -Otherwise, if the object was constructed with a byte-error string, the -member function returns the byte-error string. -Otherwise, the member function throws an object of class \tcode{range_error}. -\end{itemdescr} +The header \libheaderref{tuple} has the following additions: + +\begin{codeblock} +namespace std { + template struct tuple_size; + template struct tuple_size; + + template struct tuple_element; + template struct tuple_element; +} +\end{codeblock} -\indexlibraryctor{wstring_convert}% \begin{itemdecl} -explicit wstring_convert(Codecvt* pcvt); -wstring_convert(Codecvt* pcvt, state_type state); -explicit wstring_convert(const byte_string& byte_err, - const wide_string& wide_err = wide_string()); +template struct tuple_size; +template struct tuple_size; \end{itemdecl} \begin{itemdescr} \pnum -\expects -For the first and second constructors, \tcode{pcvt} is not null. +Let \tcode{TS} denote \tcode{tuple_size} of the cv-unqualified type \tcode{T}. +If the expression \tcode{TS::value} is well-formed +when treated as an unevaluated operand\iref{term.unevaluated.operand}, +then specializations of each of the two templates meet +the \oldconcept{TransformationTrait} requirements with a base characteristic of +\tcode{integral_constant}. +Otherwise, they have no member \tcode{value}. \pnum -\effects -The first constructor stores \tcode{pcvt} in \tcode{cvtptr} and -default values in \tcode{cvtstate}, \tcode{byte_err_string}, and -\tcode{wide_err_string}. -The second constructor stores \tcode{pcvt} in \tcode{cvtptr}, -\tcode{state} in \tcode{cvtstate}, and default values in -\tcode{byte_err_string} and \tcode{wide_err_string}; moreover the -stored state is retained between calls to \tcode{from_bytes} and -\tcode{to_bytes}. -The third constructor stores \tcode{new Codecvt} in \tcode{cvtptr}, -\tcode{state_type()} in \tcode{cvtstate}, \tcode{byte_err} -in \tcode{byte_err_string}, and \tcode{wide_err} in -\tcode{wide_err_string}. +Access checking is performed as if +in a context unrelated to \tcode{TS} and \tcode{T}. +Only the validity of the immediate context of the expression is considered. + +\pnum +In addition to being available via inclusion of the \libheaderref{tuple} header, +the two templates are available when any of the headers +\libheaderref{array}, +\libheaderref{ranges}, or +\libheaderref{utility} +are included. \end{itemdescr} -\indexlibrarydtor{wstring_convert}% \begin{itemdecl} -~wstring_convert(); +template struct tuple_element; +template struct tuple_element; \end{itemdecl} \begin{itemdescr} \pnum -\effects -\tcode{delete cvtptr}. +Let \tcode{TE} denote \tcode{tuple_element_t} +of the cv-unqualified type \tcode{T}. +Then specializations of each of the two templates meet +the \oldconcept{TransformationTrait} requirements +with a member typedef \tcode{type} that names the following type: +\begin{itemize} +\item for the first specialization, \tcode{add_volatile_t}, and +\item for the second specialization, \tcode{add_cv_t}. +\end{itemize} + +\pnum +In addition to being available via inclusion of the \libheaderref{tuple} header, +the two templates are available when any of the headers +\libheaderref{array}, +\libheaderref{ranges}, or +\libheaderref{utility} +are included. \end{itemdescr} -\rSec2[depr.conversions.buffer]{Class template \tcode{wbuffer_convert}} +\rSec1[depr.variant]{Variant} \pnum -Class template \tcode{wbuffer_convert} looks like a wide stream buffer, but -performs all its I/O through an underlying byte stream buffer that you -specify when you construct it. Like class template \tcode{wstring_convert}, it -lets you specify a code conversion facet to perform the conversions, -without affecting any streams or locales. +The header \libheaderref{variant} has the following additions: -\indexlibraryglobal{wbuffer_convert}% -\indexlibrarymember{state_type}{wbuffer_convert}% \begin{codeblock} namespace std { - template> - class wbuffer_convert : public basic_streambuf { - public: - using state_type = typename Codecvt::state_type; - - wbuffer_convert() : wbuffer_convert(nullptr) {} - explicit wbuffer_convert(streambuf* bytebuf, - Codecvt* pcvt = new Codecvt, - state_type state = state_type()); - - ~wbuffer_convert(); - - wbuffer_convert(const wbuffer_convert&) = delete; - wbuffer_convert& operator=(const wbuffer_convert&) = delete; - - streambuf* rdbuf() const; - streambuf* rdbuf(streambuf* bytebuf); - - state_type state() const; + template struct variant_size; + template struct variant_size; - private: - streambuf* bufptr; // \expos - Codecvt* cvtptr; // \expos - state_type cvtstate; // \expos - }; + template struct variant_alternative; + template struct variant_alternative; } \end{codeblock} -\pnum -The class template describes a stream buffer that controls the -transmission of elements of type \tcode{Elem}, whose character traits are -described by the class \tcode{Tr}, to and from a byte stream buffer of type -\tcode{streambuf}. Conversion between a sequence of \tcode{Elem} values and -multibyte sequences is performed by an object of class -\tcode{Codecvt}, which shall meet the requirements -of the standard code-conversion facet \tcode{codecvt}. - -\pnum -An object of this class template stores: - -\begin{itemize} -\item \tcode{bufptr} --- a pointer to its underlying byte stream buffer -\item \tcode{cvtptr} --- a pointer to the allocated conversion object -(which is freed when the \tcode{wbuffer_convert} object is destroyed) -\item \tcode{cvtstate} --- a conversion state object -\end{itemize} - -\indexlibrarymember{state}{wbuffer_convert}% \begin{itemdecl} -state_type state() const; +template struct variant_size; +template struct variant_size; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{cvtstate}. +Let \tcode{VS} denote \tcode{variant_size} +of the cv-unqualified type \tcode{T}. +Then specializations of each of the two templates meet +the \oldconcept{UnaryTypeTrait} requirements +with a base characteristic of \tcode{integral_constant}. \end{itemdescr} -\indexlibrarymember{rdbuf}{wbuffer_convert}% \begin{itemdecl} -streambuf* rdbuf() const; +template struct variant_alternative; +template struct variant_alternative; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{bufptr}. +Let \tcode{VA} denote \tcode{variant_alternative} +of the cv-unqualified type \tcode{T}. +Then specializations of each of the two templates meet +the \oldconcept{TransformationTrait} requirements +with a member typedef \tcode{type} that names the following type: +\begin{itemize} +\item for the first specialization, \tcode{add_volatile_t}, and +\item for the second specialization, \tcode{add_cv_t}. +\end{itemize} \end{itemdescr} -\indexlibrarymember{rdbuf}{wbuffer_convert}% -\begin{itemdecl} -streambuf* rdbuf(streambuf* bytebuf); -\end{itemdecl} +\rSec1[depr.iterator]{Deprecated \tcode{iterator} class template} -\begin{itemdescr} \pnum -\effects -Stores \tcode{bytebuf} in \tcode{bufptr}. +The header \libheaderrefx{iterator}{iterator.synopsis} has the following addition: + +\indexlibraryglobal{iterator}% +\begin{codeblock} +namespace std { + template + struct iterator { + using iterator_category = Category; + using value_type = T; + using difference_type = Distance; + using pointer = Pointer; + using reference = Reference; + }; +} +\end{codeblock} \pnum -\returns -The previous value of \tcode{bufptr}. -\end{itemdescr} +The +\tcode{iterator} +template may be used as a base class to ease the definition of required types +for new iterators. -\indexlibraryctor{wbuffer_convert}% -\begin{itemdecl} -explicit wbuffer_convert( - streambuf* bytebuf, - Codecvt* pcvt = new Codecvt, - state_type state = state_type()); -\end{itemdecl} +\pnum +\begin{note} +If the new iterator type is a class template, then these aliases +will not be visible from within the iterator class's template definition, but +only to callers of that class. +\end{note} -\begin{itemdescr} \pnum -\expects -\tcode{pcvt} is not null. +\begin{example} +If a \Cpp{} program wants to define a bidirectional iterator for some data +structure containing \tcode{double} and such that it works on a large memory +model of the implementation, it can do so with: + +\begin{codeblock} +class MyIterator : + public iterator { + // code implementing \tcode{++}, etc. +}; +\end{codeblock} +\end{example} + +\rSec1[depr.move.iter.elem]{Deprecated \tcode{move_iterator} access} \pnum -\effects -The constructor constructs a stream buffer object, initializes -\tcode{bufptr} to \tcode{bytebuf}, initializes \tcode{cvtptr} -to \tcode{pcvt}, and initializes \tcode{cvtstate} to \tcode{state}. -\end{itemdescr} +The following member is declared in addition to those members +specified in \ref{move.iter.elem}: + +\begin{codeblock} +namespace std { + template + class move_iterator { + public: + constexpr pointer operator->() const; + }; +} +\end{codeblock} -\indexlibrarydtor{wbuffer_convert}% +\indexlibrarymember{operator->}{move_iterator}% \begin{itemdecl} -~wbuffer_convert(); +constexpr pointer operator->() const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -\tcode{delete cvtptr}. +\returns +\tcode{current}. \end{itemdescr} \rSec1[depr.locale.category]{Deprecated locale category facets} @@ -2405,21 +715,25 @@ \pnum The \tcode{ctype} locale category includes the following facets as if they were specified -in table \tref{locale.category.facets} of \ref{locale.category}. +in \tref{locale.category.facets} of \ref{locale.category}. \begin{codeblock} codecvt codecvt +codecvt +codecvt \end{codeblock} \pnum The \tcode{ctype} locale category includes the following facets as if they were specified -in table \tref{locale.spec} of \ref{locale.category}. +in \tref{locale.spec} of \ref{locale.category}. \begin{codeblock} codecvt_byname codecvt_byname +codecvt_byname +codecvt_byname \end{codeblock} \pnum @@ -2427,13 +741,60 @@ in addition to those specified in~\ref{locale.codecvt}. \indextext{UTF-8}% \indextext{UTF-16}% -The specialization \tcode{codecvt} -converts between the UTF-16 and UTF-8 encoding forms, and +The specializations \tcode{codecvt} and +\tcode{codecvt} +convert between the UTF-16 and UTF-8 encoding forms, and \indextext{UTF-32}% -the specialization \tcode{codecvt} -converts between the UTF-32 and UTF-8 encoding forms. +the specializations \tcode{codecvt} and +\tcode{codecvt} +convert between the UTF-32 and UTF-8 encoding forms. + +\rSec1[depr.format]{Deprecated formatting} + +\rSec2[depr.format.syn]{Header \tcode{} synopsis} + +\pnum +The header \libheaderref{format} has the following additions: + +\begin{codeblock} +namespace std { + template + decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg arg); +} +\end{codeblock} + +\rSec2[depr.format.arg]{Formatting arguments} + +\indexlibraryglobal{visit_format_arg}% +\begin{itemdecl} +template + decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg arg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return visit(std::forward(vis), arg.value);} +\end{itemdescr} -\rSec1[depr.fs.path.factory]{Deprecated filesystem path factory functions} +\rSec1[depr.ctime]{Deprecated time formatting} + +\pnum +The header \libheaderref{ctime} has the following additions: +\begin{codeblock} +char* asctime(const tm* timeptr); +char* ctime(const time_t* timer); +\end{codeblock} + +\pnum +The functions \tcode{asctime} and \tcode{ctime} +are not required to avoid data races\iref{res.on.data.races}. + +\xrefc{7.29} + +\rSec1[depr.filesystems]{Deprecated file systems} + +\rSec2[depr.fs.path.factory]{Deprecated filesystem path factory functions} \pnum The header \libheaderrefx{filesystem}{fs.filesystem.syn} has the following additions: @@ -2512,6 +873,45 @@ \end{note} \end{itemdescr} +\rSec2[depr.fs.path.obs]{Deprecated filesystem path format observers} + +\indexlibraryglobal{path}% +\pnum +The following members are declared in addition to those members +specified in \ref{fs.path.member}: + +\begin{codeblock} +namespace std::filesystem { + class path { + public: + std::string string() const; + std::string generic_string() const; + }; +} +\end{codeblock} + +\indexlibrarymember{string}{path}% +\begin{itemdecl} +std::string string() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{system_encoded_string()}. +\end{itemdescr} + +\indexlibrarymember{generic_string}{path}% +\begin{itemdecl} +std::string generic_string() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{generic_system_encoded_string()}. +\end{itemdescr} + \rSec1[depr.atomics]{Deprecated atomic operations} \rSec2[depr.atomics.general]{General} @@ -2525,8 +925,11 @@ void atomic_init(volatile atomic*, typename atomic::value_type) noexcept; template void atomic_init(atomic*, typename atomic::value_type) noexcept; + template + constexpr T kill_dependency(T y) noexcept; // freestanding + inline constexpr memory_order memory_order_consume = memory_order::consume; // freestanding - #define ATOMIC_VAR_INIT(value) @\seebelow@ + #define @\libmacro{ATOMIC_VAR_INIT}@(value) @\seebelow@ } \end{codeblock} @@ -2575,13 +978,13 @@ \indexlibraryglobal{ATOMIC_VAR_INIT}% \begin{itemdecl} -#define ATOMIC_VAR_INIT(value) @\seebelow@ +#define @\libmacro{ATOMIC_VAR_INIT}@(value) @\seebelow@ \end{itemdecl} \begin{itemdescr} \pnum The macro expands to a token sequence suitable for constant initialization of -an atomic variable of static storage duration of a type that +an atomic variable with static storage duration of a type that is initialization-compatible with \tcode{value}. \begin{note} This operation possibly needs to initialize locks. @@ -2595,3 +998,25 @@ \end{codeblock} \end{example} \end{itemdescr} + +\rSec2[depr.atomics.order]{\tcode{memory_order::consume}} + +\indexlibraryglobal{memory_order}% +\indexlibrarymember{consume}{memory_order}% +\pnum +The \tcode{memory_order} enumeration contains an additional enumerator: +\begin{codeblock} +consume = 1 +\end{codeblock} +The \tcode{memory_order::consume} enumerator is allowed wherever +\tcode{memory_order::acquire} is allowed, and it has the same meaning. + +\begin{itemdecl} +template constexpr T kill_dependency(T y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{y}. +\end{itemdescr} diff --git a/source/grammar.tex b/source/grammar.tex index 8501d39453..db27a2f510 100644 --- a/source/grammar.tex +++ b/source/grammar.tex @@ -58,4 +58,4 @@ identifier \end{ncbnf} -\FlushAndPrintGrammar +\input{std-gram.ext} diff --git a/source/intro.tex b/source/intro.tex index a4fff15300..e4014b9674 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -1,6 +1,17 @@ %!TEX root = std.tex +\clearpage +\bigskip\noindent\textlarger{\textbf{Programming languages --- \Cpp{}}} +\bigskip\bigskip + +\begingroup +\let\clearpage\relax \rSec0[intro.scope]{Scope} +\endgroup +\copypagestyle{cpppageone}{cpppage} +\makeoddhead{cpppageone}{\textbf{WORKING DRAFT}}{}{\leaders\hrule height 2pt\hfill\kern0pt\\\textbf{\docno}} +\makeheadrule{cpppageone}{\textwidth}{2pt} +\thispagestyle{cpppageone} \pnum \indextext{scope|(}% @@ -36,24 +47,19 @@ \item ISO/IEC 2382, \doccite{Information technology --- Vocabulary} \item ISO 8601-1:2019, \doccite{Date and time --- Representations for information interchange --- Part 1: Basic rules} \item \IsoC{}, \doccite{Information technology --- Programming languages --- C} -\item ISO/IEC/IEEE 9945:2009, \doccite{Information Technology --- Portable -Operating System Interface (POSIX -\begin{footnote} +\item \IsoPosix{}, \doccite{Information Technology --- Portable Operating System Interface (POSIX\textregistered)\begin{footnote} POSIX\textregistered\ is a registered trademark of the Institute of Electrical and Electronic Engineers, Inc. This information is given for the convenience of users of this document and does not constitute an endorsement by ISO or IEC of this product. -\end{footnote}% -)} -\item ISO/IEC/IEEE 9945:2009/Cor 1:2013, \doccite{Information Technology --- Portable -Operating System Interface (POSIX), Technical Corrigendum 1} -\item ISO/IEC/IEEE 9945:2009/Cor 2:2017, \doccite{Information Technology --- Portable -Operating System Interface (POSIX), Technical Corrigendum 2} -\item ISO/IEC/IEEE 60559:2020, \doccite{Information technology --- -Microprocessor Systems --- Floating-Point arithmetic} -\item ISO 80000-2:2009, \doccite{Quantities and units --- -Part 2: Mathematical signs and symbols -to be used in the natural sciences and technology} +\end{footnote} +Base Specifications, Issue 7} +\item \IsoPosix{}/Cor 1:2013, \doccite{Information Technology --- Portable Operating System Interface +(POSIX\textregistered) Base Specifications, Issue 7 --- Technical Corrigendum 1} +\item \IsoPosix{}/Cor 2:2017, \doccite{Information Technology --- Portable Operating System Interface +(POSIX\textregistered) Base Specifications, Issue 7 --- Technical Corrigendum 2} +\item \IsoFloatUndated{}:2020, \doccite{Information technology --- Microprocessor Systems --- Floating-Point arithmetic} +\item ISO 80000-2:2019, \doccite{Quantities and units --- Part 2: Mathematics} % Other international standards. \item Ecma International, \doccite{ECMAScript \begin{footnote} @@ -65,8 +71,8 @@ Language Specification}, Standard Ecma-262, third edition, 1999. \item -The Unicode Consortium. \doccite{The Unicode Standard}. -Available from: \url{https://www.unicode.org/versions/latest/} +The Unicode Consortium. \doccite{The Unicode Standard}, Version 15.1. +Available from: \url{https://www.unicode.org/versions/Unicode15.1.0/} \end{itemize} \indextext{references!normative|)} @@ -76,7 +82,7 @@ \indextext{definitions|(}% For the purposes of this document, the terms and definitions -given in ISO/IEC 2382 and ISO 80000-2:2009, +given in ISO/IEC 2382, ISO 80000-2:2019, and the following apply. \pnum @@ -94,10 +100,10 @@ read or modify the value of an object \begin{defnote} -Only glvalues of scalar type can be used to access objects. +Only glvalues of scalar type\iref{basic.types.general} can be used to access objects. Reads of scalar objects are described in \ref{conv.lval} and modifications of scalar objects are described in -\ref{expr.ass}, \ref{expr.post.incr}, and \ref{expr.pre.incr}. +\ref{expr.assign}, \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} or assignment operator\iref{class.copy.assign}; @@ -108,8 +114,9 @@ \indexdefn{argument}% \indexdefn{argument!function call expression} \definition{argument}{defns.argument} -\defncontext{function call expression} expression in the -comma-separated list bounded by the parentheses +\defncontext{function call expression} +expression or \grammarterm{braced-init-list} +in the comma-separated list bounded by the parentheses \indexdefn{argument}% \indexdefn{argument!function-like macro}% @@ -211,6 +218,11 @@ constructs that it does not support. \end{defnote} +\definition{constant evaluation}{defns.const.eval} +\indexdefn{constant evaluation}% +evaluation that is performed as part of evaluating an expression +as a core constant expression\iref{expr.const} + \definition{constant subexpression}{defns.const.subexpr} \indexdefn{constant subexpression}% expression whose evaluation as subexpression of a @@ -242,8 +254,9 @@ glvalue refers \begin{example} -If a pointer\iref{dcl.ptr} \tcode{p} whose static type is ``pointer to -class \tcode{B}'' is pointing to an object of class \tcode{D}, derived +If a pointer\iref{dcl.ptr} \tcode{p} whose type is ``pointer to +class \tcode{B}'' is pointing to a base class subobject +of class \tcode{B}, whose most derived object is of class \tcode{D}, derived from \tcode{B}\iref{class.derived}, the dynamic type of the expression \tcode{*p} is ``\tcode{D}''. References\iref{dcl.ref} are treated similarly. @@ -253,6 +266,17 @@ \definition{dynamic type}{defns.dynamic.type.prvalue} \defncontext{prvalue} \termref{defns.static.type}{static type}{} of the prvalue expression +\indexdefn{behavior!erroneous}% +\definition{erroneous behavior}{defns.erroneous} +well-defined behavior that the implementation is recommended to diagnose +\begin{defnote} +Erroneous behavior is always the consequence of incorrect program code. +Implementations are allowed, but not required, +to diagnose it\iref{intro.compliance.general}. +Evaluation of a constant expression\iref{expr.const} +never exhibits behavior specified as erroneous in \ref{intro} through \ref{\lastcorechapter}. +\end{defnote} + \definition{expression-equivalent}{defns.expression.equivalent} \defncontext{library} \indexdefn{expression-equivalent}% @@ -286,7 +310,7 @@ \definition{format specifier}{defns.regex.format.specifier} \defncontext{regular expression} \indexdefn{format specifier}% -sequence of one or more \termref{defns.character}{character}{s} that is to be +sequence of one or more \termref{defns.character}{character}{s} that is expected to be replaced with some part of a \termref{defns.regex.regular.expression}{regular expression}{} match \definition{handler function}{defns.handler} @@ -297,7 +321,7 @@ \begin{defnote} A \Cpp{} program may designate a handler function at various points in its execution by supplying a pointer to the function when calling any of the library functions that install -handler functions\iref{support}. +handler functions (see \ref{support}). \end{defnote} \indexdefn{program!ill-formed}% @@ -316,7 +340,7 @@ \impldef{strict total order over pointer values} strict total ordering over all pointer values such that the ordering is consistent with the partial order -imposed by the builtin operators +imposed by the built-in operators \tcode{<}, \tcode{>}, \tcode{<=}, \tcode{>=}, and \tcode{<=>} \indexdefn{limits!implementation}% @@ -406,7 +430,7 @@ set of one or more \termref{defns.character}{character}{s} which share the same primary sort key: that is the sort key weighting that depends only upon character shape, and not accents, case, or -locale specific tailorings +locale-specific tailorings \definition{program-defined specialization}{defns.prog.def.spec} \defncontext{library} @@ -498,6 +522,23 @@ \indextext{undefined} \end{defnote} +\definition{runtime-undefined behavior}{defns.undefined.runtime} +\indexdefn{behavior!runtime-undefined}% +behavior that is undefined except when it occurs during constant evaluation + +\begin{defnote} +During constant evaluation, +\begin{itemize} +\item +it is +\impldef{whether runtime-undefined behavior results in the expression being deemed non-constant} +whether runtime-undefined behavior results in the expression being deemed non-constant +(as specified in~\ref{expr.const}) and +\item +runtime-undefined behavior has no other effect. +\end{itemize} +\end{defnote} + \indexdefn{signature}% \definition{signature}{defns.signature} \defncontext{function} @@ -619,7 +660,7 @@ \indexdefn{unblock}% \definition{unblock}{defns.unblock} -satisfy a condition that one or more \termref{defns.block}{block}{ed} threads of execution are waiting for +satisfy a condition that one or more \termref{defns.block}{blocked}{} threads of execution are waiting for \indexdefn{behavior!undefined}% \definition{undefined behavior}{defns.undefined} @@ -629,16 +670,16 @@ \begin{defnote} Undefined behavior may be expected when this document omits any explicit -definition of behavior or when a program uses an erroneous construct or erroneous data. +definition of behavior or when a program uses an incorrect construct or invalid data. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a \termref{defns.diagnostic}{diagnostic message}{}), to terminating a translation or execution (with the -issuance of a diagnostic message). Many erroneous program constructs do +issuance of a diagnostic message). Many incorrect program constructs do not engender undefined behavior; they are required to be diagnosed. Evaluation of a constant expression\iref{expr.const} never exhibits behavior explicitly -specified as undefined in \ref{intro} through \ref{cpp}. +specified as undefined in \ref{intro} through \ref{\lastcorechapter}. \end{defnote} \indexdefn{behavior!unspecified}% @@ -716,25 +757,43 @@ \begin{itemize} \item If a program contains no violations of the rules in -\ref{lex} through \ref{\lastlibchapter} and \ref{depr}, -a conforming implementation shall, -within its resource limits as described in \ref{implimits}, -accept and correctly execute +\ref{lex} through \ref{\lastlibchapter} as well as those specified in \ref{depr}, +a conforming implementation shall accept and correctly execute \begin{footnote} -``Correct execution'' can include undefined behavior, depending on +``Correct execution'' can include undefined behavior +and erroneous behavior, depending on the data being processed; see \ref{intro.defs} and~\ref{intro.execution}. \end{footnote} -that program. +that program, +except when the implementation's limitations (see below) are exceeded. \item \indextext{behavior!undefined}% If a program contains a violation of a rule for which no diagnostic is required, this document places no requirement on implementations with respect to that program. + \item \indextext{message!diagnostic}% -Otherwise, if a program contains a violation of any diagnosable rule or an occurrence +\indextext{contract evaluation semantics!checking}% +\indextext{contract evaluation semantics!terminating}% +Otherwise, if a program contains +\begin{itemize} +\item +a violation of any diagnosable rule, +\item +a preprocessing translation unit with +a \tcode{\#warning} preprocessing directive\iref{cpp.error}, +\item +an occurrence of a construct described in this document as ``conditionally-supported'' when -the implementation does not support that construct, a conforming implementation +the implementation does not support that construct, or +\item +a contract assertion\iref{basic.contract.eval} +evaluated with a checking semantic +in a manifestly constant-evaluated context\iref{expr.const} +resulting in a contract violation, +\end{itemize} +a conforming implementation shall issue at least one diagnostic message. \end{itemize} \begin{note} @@ -744,18 +803,18 @@ see~\ref{temp.deduct}. \end{note} Furthermore, a conforming implementation +shall not accept \begin{itemize} \item -shall not accept a preprocessing translation unit containing +a preprocessing translation unit containing a \tcode{\#error} preprocessing directive\iref{cpp.error}, \item -shall issue at least one diagnostic message for -each \tcode{\#warning} or \tcode{\#error} preprocessing directive -not following a \tcode{\#error} preprocessing directive in -a preprocessing translation unit, and +a translation unit with +a \grammarterm{static_assert-declaration} that fails\iref{dcl.pre}, or \item -shall not accept a translation unit with -a \grammarterm{static_assert-declaration} that fails\iref{dcl.pre}. +a contract assertion evaluated with a terminating semantic\iref{basic.contract.eval} +in a manifestly constant-evaluated context\iref{expr.const} +resulting in a contract violation. \end{itemize} \pnum @@ -786,7 +845,8 @@ \indextext{conformance requirements!library|)} \pnum -Two kinds of implementations are defined: a \defnadj{hosted}{implementation} and a +An implementation is either a +\defnadj{hosted}{implementation} or a \defnadj{freestanding}{implementation}. A freestanding implementation is one in which execution may take place without the benefit of @@ -795,9 +855,30 @@ supports all the facilities described in this document, while a freestanding implementation supports the entire \Cpp{} language -described in \ref{lex} through \ref{cpp} and +described in \ref{lex} through \ref{\lastcorechapter} and the subset of the library facilities described in \ref{compliance}. +\pnum +It is +\impldef{whether the implementation is a hardened implementation} +whether the implementation is a +\defnadj{hardened}{implementation}. +If it is a hardened implementation, +violating a hardened precondition +results in a contract violation\iref{structure.specifications}. + +\pnum +An implementation is encouraged to document its limitations in +the size or complexity of the programs it can successfully process, +if possible and where known. +\ref{implimits} lists some quantities that can be subject to limitations and +a potential minimum supported value for each quantity. + +\pnum +A conforming implementation may use an implementation-defined version +of the Unicode Standard that is a later version than the one +referenced in \ref{intro.refs}. + \pnum A conforming implementation may have extensions (including additional library functions), provided they do not alter the @@ -876,43 +957,82 @@ Certain other operations are described in this document as undefined behavior (for example, the effect of attempting to modify a const object). + +\pnum +Certain events in the execution of a program +are termed \defnadj{observable}{checkpoints}. \begin{note} -This document imposes no requirements on the -behavior of programs that contain undefined behavior. +A call to \tcode{std::observable_checkpoint}\iref{utility.undefined} +is an observable checkpoint, +as are certain parts of +the evaluation of contract assertions\iref{basic.contract}. \end{note} \pnum \indextext{program!well-formed}% \indextext{behavior!observable}% +The \defnadj{defined}{prefix} of an execution +comprises the operations $O$ +for which for every undefined operation $U$ +there is an observable checkpoint $C$ +such that $O$ happens before $C$ and +$C$ happens before $U$. + +\begin{note} +The undefined behavior that arises from a data race\iref{intro.races} +occurs on all participating threads. +\end{note} + A conforming implementation executing a well-formed program shall -produce the same observable behavior as one of the possible executions -of the corresponding instance of the abstract machine with the +produce the observable behavior +of the defined prefix +of one of the possible executions +of the corresponding instance +of the abstract machine with the same program and the same input. \indextext{behavior!undefined}% -However, if any such execution contains an undefined operation, this document places no -requirement on the implementation executing that program with that input -(not even with regard to operations preceding the first undefined -operation). +If the selected execution contains an undefined operation, +the implementation executing that program with that input +may produce arbitrary additional observable behavior afterwards. +If the execution contains an operation specified as having erroneous behavior, +the implementation is permitted to issue a diagnostic and +is permitted to terminate the execution +at an unspecified time after that operation. + +\pnum +\recommended +An implementation should issue a diagnostic when such an operation is executed. +\begin{note} +An implementation can issue a diagnostic +if it can determine that erroneous behavior is reachable +under an implementation-specific set of assumptions about the program behavior, +which can result in false positives. +\end{note} \pnum \indextext{conformance requirements}% -The least requirements on a conforming implementation are: +The following specify the +\defnadj{observable}{behavior} +of the program: \begin{itemize} \item Accesses through volatile glvalues are evaluated strictly according to the rules of the abstract machine. \item -At program termination, all data written into files shall be -identical to one of the possible results that execution of the program -according to the abstract semantics would have produced. +Data is delivered to the host environment to be written into files (\xrefc{7.21.3}). + +\begin{note} +Delivering such data +is followed by an observable checkpoint\iref{cstdio.syn}. +Not all host environments provide access to file contents before program termination. +\end{note} + \item The input and output dynamics of interactive devices shall take place in such a fashion that prompting output is actually delivered before a program waits for input. What constitutes an interactive device is \impldef{interactive device}. \end{itemize} -These collectively are referred to as the -\defnx{observable behavior}{behavior!observable} of the program. \begin{note} More stringent correspondences between abstract and actual semantics can be defined by each implementation. @@ -924,7 +1044,7 @@ \pnum \indextext{standard!structure of|(}% \indextext{standard!structure of}% -\ref{lex} through \ref{cpp} describe the \Cpp{} programming +\ref{lex} through \ref{\lastcorechapter} describe the \Cpp{} programming language. That description includes detailed syntactic specifications in a form described in~\ref{syntax}. For convenience, \ref{gram} repeats all such syntactic specifications. diff --git a/source/iostreams.tex b/source/iostreams.tex index cc90aecef8..edbd0554b0 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -86,7 +86,7 @@ It is used to represent the number of characters transferred in an I/O operation, or the size of I/O buffers. \begin{footnote} -Most places where \tcode{streamsize} is used would use \tcode{size_t} in ISO C, +Most places where \tcode{streamsize} is used would use \tcode{size_t} in C, or \tcode{ssize_t} in POSIX. \end{footnote} \end{itemdescr} @@ -225,17 +225,13 @@ template> class basic_iostream; - template, - class Allocator = allocator> + template, class Allocator = allocator> class basic_stringbuf; - template, - class Allocator = allocator> + template, class Allocator = allocator> class basic_istringstream; - template, - class Allocator = allocator> + template, class Allocator = allocator> class basic_ostringstream; - template, - class Allocator = allocator> + template, class Allocator = allocator> class basic_stringstream; template> @@ -256,11 +252,9 @@ template> class basic_fstream; - template, - class Allocator = allocator> + template, class Allocator = allocator> class basic_syncbuf; - template, - class Allocator = allocator> + template, class Allocator = allocator> class basic_osyncstream; template> @@ -480,6 +474,12 @@ declares objects that associate objects with the standard C streams provided for by the functions declared in \libheader{cstdio}, and includes all the headers necessary to use these objects. +The dynamic types of the stream buffers +initially associated with these objects are unspecified, +but they have the behavior specified for +\tcode{std::basic_filebuf} +or +\tcode{std::basic_filebuf}. \pnum The objects are constructed and the associations are established at some @@ -683,11 +683,15 @@ #include // see \ref{iosfwd.syn} namespace std { + // \ref{stream.types}, types using streamoff = @\impdef@; using streamsize = @\impdef@; + // \ref{fpos}, class template \tcode{fpos} template class fpos; + // \ref{ios.base}, class \tcode{ios_base} class ios_base; + // \ref{ios}, class template \tcode{basic_ios} template> class basic_ios; @@ -730,8 +734,8 @@ ios_base& defaultfloat(ios_base& str); // \ref{error.reporting}, error reporting - enum class io_errc { - stream = 1 + enum class @\libglobal{io_errc}@ { + @\libmember{stream}{io_errc}@ = 1 }; template<> struct is_error_code_enum : public true_type { }; @@ -827,7 +831,7 @@ virtual ~ios_base(); // \ref{ios.base.callback}, callbacks - enum event { erase_event, imbue_event, copyfmt_event }; + enum @\libmember{event}{ios_base}@ { erase_event, imbue_event, copyfmt_event }; using event_callback = void (*)(event, ios_base&, int idx); void register_callback(event_callback fn, int idx); @@ -840,9 +844,9 @@ ios_base(); private: - static int index; // \expos - long* iarray; // \expos - void** parray; // \expos + static int @\exposid{index}@; // \expos + long* @\exposid{iarray}@; // \expos + void** @\exposid{parray}@; // \expos }; } \end{codeblock} @@ -878,19 +882,19 @@ For the sake of exposition, the maintained data is presented here as: \begin{itemize} \item -\tcode{static int index}, +\tcode{static int \exposid{index}}, specifies the next available unique index for the integer or pointer arrays maintained for the private use of the program, initialized to an unspecified value; \item -\tcode{long* iarray}, +\tcode{long* \exposid{iarray}}, points to the first element of an arbitrary-length \tcode{long} array maintained for the private use of the program; \item -\tcode{void** parray}, +\tcode{void** \exposid{parray}}, points to the first element of an arbitrary-length pointer array maintained for the private use of the program. \end{itemize} @@ -1128,9 +1132,6 @@ Init(const Init&) = default; ~Init(); Init& operator=(const Init&) = default; - - private: - static int init_cnt; // \expos }; } \end{codeblock} @@ -1144,17 +1145,6 @@ provided for by the functions declared in \libheaderref{cstdio}. -\pnum -For the sake of exposition, the maintained data is presented here as: -\begin{itemize} -\item -\tcode{static int init_cnt}, -counts the number of -constructor and destructor calls for class -\tcode{Init}, -initialized to zero. -\end{itemize} - \indexlibraryctor{ios_base::Init}% \begin{itemdecl} Init(); @@ -1442,7 +1432,7 @@ \begin{itemdescr} \pnum \returns -\tcode{index} +\exposid{index} \tcode{++}. \pnum @@ -1463,20 +1453,20 @@ \pnum \effects -If \tcode{iarray} is a null pointer, allocates an array of +If \exposid{iarray} is a null pointer, allocates an array of \tcode{long} of unspecified size and stores a pointer to its first element in -\tcode{iarray}. +\exposid{iarray}. The function then extends the array pointed at by -\tcode{iarray} as necessary to include the element -\tcode{iarray[idx]}. +\exposid{iarray} as necessary to include the element +\tcode{\exposid{iarray}[idx]}. Each newly allocated element of the array is initialized to zero. The reference returned is invalid after any other operation on the object. \begin{footnote} An implementation is free to implement both the integer -array pointed at by \tcode{iarray} and the pointer array pointed at by -\tcode{parray} as sparse data structures, possibly with a one-element +array pointed at by \exposid{iarray} and the pointer array pointed at by +\exposid{parray} as sparse data structures, possibly with a one-element cache for each. \end{footnote} However, the value of the storage referred to is retained, so @@ -1501,7 +1491,7 @@ \pnum \returns On success -\tcode{iarray[idx]}. +\tcode{\exposid{iarray}[idx]}. On failure, a valid \tcode{long\&} initialized to 0. @@ -1519,13 +1509,13 @@ \pnum \effects -If \tcode{parray} is a null pointer, allocates an array of +If \exposid{parray} is a null pointer, allocates an array of pointers to \keyword{void} of unspecified size and stores a pointer to its -first element in \tcode{parray}. +first element in \exposid{parray}. The function then extends the array -pointed at by \tcode{parray} as necessary to include the element -\tcode{parray[idx]}. +pointed at by \exposid{parray} as necessary to include the element +\tcode{\exposid{parray}[idx]}. Each newly allocated element of the array is initialized to a null pointer. The reference returned is invalid after any other operation on the @@ -1641,6 +1631,8 @@ \rSec2[fpos]{Class template \tcode{fpos}} +\rSec3[fpos.general]{General} + \indexlibraryglobal{fpos}% \begin{codeblock} namespace std { @@ -1651,7 +1643,7 @@ void state(stateT); private: - stateT st; // \expos + stateT @\exposid{st}@; // \expos }; } \end{codeblock} @@ -1666,7 +1658,7 @@ \begin{itemdescr} \pnum \effects -Assigns \tcode{s} to \tcode{st}. +Assigns \tcode{s} to \exposid{st}. \end{itemdescr} \indexlibrarymember{state}{fpos}% @@ -1677,7 +1669,7 @@ \begin{itemdescr} \pnum \returns -Current value of \tcode{st}. +Current value of \exposid{st}. \end{itemdescr} \rSec3[fpos.operations]{Requirements} @@ -2054,7 +2046,7 @@ \begin{itemdescr} \pnum \returns -\tcode{use_facet>(getloc()).narrow(c, dfault)} +\tcode{use_facet>(getloc()).narrow(c, dfault)}. \end{itemdescr} \indexlibrarymember{widen}{basic_ios}% @@ -2065,7 +2057,7 @@ \begin{itemdescr} \pnum \returns -\tcode{use_facet>(getloc()).widen(c)} +\tcode{use_facet>(getloc()).widen(c)}. \end{itemdescr} \indexlibrarymember{fill}{basic_ios}% @@ -2318,7 +2310,7 @@ \begin{itemdescr} \pnum \returns -\tcode{rdstate() == 0} +\tcode{rdstate() == 0}. \end{itemdescr} \indexlibrarymember{eof}{basic_ios}% @@ -2883,6 +2875,7 @@ \indexlibraryglobal{basic_streambuf}% \begin{codeblock} namespace std { + // \ref{streambuf}, class template \tcode{basic_streambuf} template> class basic_streambuf; using streambuf = basic_streambuf; @@ -3513,6 +3506,11 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\range{gbeg}{gnext}, \range{gbeg}{gend}, and \range{gnext}{gend} +are all valid ranges. + \pnum \ensures \tcode{gbeg == eback()}, @@ -3573,6 +3571,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\range{pbeg}{pend} is a valid range. + \pnum \ensures \tcode{pbeg == pbase()}, @@ -3634,7 +3636,7 @@ \begin{itemdecl} pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which - = ios_base::in | ios_base::out); + = ios_base::in | ios_base::out); \end{itemdecl} \begin{itemdescr} @@ -3656,7 +3658,7 @@ \begin{itemdecl} pos_type seekpos(pos_type sp, ios_base::openmode which - = ios_base::in | ios_base::out); + = ios_base::in | ios_base::out); \end{itemdecl} \begin{itemdescr} @@ -4138,21 +4140,25 @@ \indexheader{istream}% \begin{codeblock} namespace std { + // \ref{istream}, class template \tcode{basic_istream} template> class basic_istream; using istream = basic_istream; using wistream = basic_istream; + // \ref{iostreamclass}, class template \tcode{basic_iostream} template> class basic_iostream; using iostream = basic_iostream; using wiostream = basic_iostream; + // \ref{istream.manip}, standard \tcode{basic_istream} manipulators template basic_istream& ws(basic_istream& is); + // \ref{istream.rvalue}, rvalue stream extraction template Istream&& operator>>(Istream&& is, T&& x); } @@ -4168,12 +4174,14 @@ \indexheader{ostream}% \begin{codeblock} namespace std { + // \ref{ostream}, class template \tcode{basic_ostream} template> class basic_ostream; using ostream = basic_ostream; using wostream = basic_ostream; + // \ref{ostream.manip}, standard \tcode{basic_ostream} manipulators template basic_ostream& endl(basic_ostream& os); template @@ -4188,6 +4196,7 @@ template basic_ostream& flush_emit(basic_ostream& os); + // \ref{ostream.rvalue}, rvalue stream insertion template Ostream&& operator<<(Ostream&& os, const T& x); @@ -4196,6 +4205,7 @@ void print(ostream& os, format_string fmt, Args&&... args); template void println(ostream& os, format_string fmt, Args&&... args); + void println(ostream& os); void vprint_unicode(ostream& os, string_view fmt, format_args args); void vprint_nonunicode(ostream& os, string_view fmt, format_args args); @@ -4212,17 +4222,21 @@ \indexheader{iomanip}% \begin{codeblock} namespace std { + // \ref{std.manip}, standard manipulators @\unspec@ resetiosflags(ios_base::fmtflags mask); @\unspec@ setiosflags (ios_base::fmtflags mask); @\unspec@ setbase(int base); template @\unspec@ setfill(charT c); @\unspec@ setprecision(int n); @\unspec@ setw(int n); + + // \ref{ext.manip}, extended manipulators template @\unspec@ get_money(moneyT& mon, bool intl = false); template @\unspec@ put_money(const moneyT& mon, bool intl = false); template @\unspec@ get_time(tm* tmb, const charT* fmt); template @\unspec@ put_time(const tm* tmb, const charT* fmt); + // \ref{quoted.manip}, quoted manipulators template @\unspec@ quoted(const charT* s, charT delim = charT('"'), charT escape = charT('\\')); @@ -4253,14 +4267,18 @@ template void println(format_string fmt, Args&&... args); + void println(); template void println(FILE* stream, format_string fmt, Args&&... args); + void println(FILE* stream); void vprint_unicode(string_view fmt, format_args args); void vprint_unicode(FILE* stream, string_view fmt, format_args args); + void vprint_unicode_buffered(FILE* stream, string_view fmt, format_args args); void vprint_nonunicode(string_view fmt, format_args args); void vprint_nonunicode(FILE* stream, string_view fmt, format_args args); + void vprint_nonunicode_buffered(FILE* stream, string_view fmt, format_args args); } \end{codeblock} @@ -4339,6 +4357,7 @@ basic_istream& getline(char_type* s, streamsize n, char_type delim); basic_istream& ignore(streamsize n = 1, int_type delim = traits::eof()); + basic_istream& ignore(streamsize n, char_type delim); int_type peek(); basic_istream& read (char_type* s, streamsize n); streamsize readsome(char_type* s, streamsize n); @@ -4489,12 +4508,12 @@ namespace std { template class basic_istream::sentry { - bool ok_; // \expos + bool @\exposid{ok_}@; // \expos public: explicit sentry(basic_istream& is, bool noskipws = false); ~sentry(); - explicit operator bool() const { return ok_; } + explicit operator bool() const { return @\exposid{ok_}@; } sentry(const sentry&) = delete; sentry& operator=(const sentry&) = delete; }; @@ -4591,9 +4610,9 @@ \tcode{is.good()} is \tcode{true}, -\tcode{ok_ != false} +\tcode{\exposid{ok_} != false} otherwise, -\tcode{ok_ == false}. +\tcode{\exposid{ok_} == false}. During preparation, the constructor may call \tcode{setstate(failbit)} (which may throw @@ -4628,7 +4647,7 @@ \begin{itemdescr} \pnum \returns -\tcode{ok_}. +\exposid{ok_}. \end{itemdescr} \rSec3[istream.formatted]{Formatted input functions} @@ -4924,7 +4943,7 @@ \pnum Characters are extracted and stored until any of the following occurs: \begin{itemize} -\item \tcode{n-1} characters are stored; +\item \tcode{n - 1} characters are stored; \item end of file occurs on the input sequence; \item letting \tcode{ct} be \tcode{use_facet>(in.getloc())}, \tcode{ct.is(ct.space, c)} is \tcode{true}. @@ -5360,7 +5379,7 @@ \begin{itemdescr} \pnum \returns -\tcode{getline(s, n, widen('\textbackslash n'))} +\tcode{getline(s, n, widen('\textbackslash n'))}. \end{itemdescr} \indexlibrarymember{ignore}{basic_istream}% @@ -5380,7 +5399,7 @@ \item \tcode{n != numeric_limits::max()}\iref{numeric.limits} and -\tcode{n} characters have been extracted so far +\tcode{n} characters have been extracted so far; \item end-of-file occurs on the input sequence (in which case the function calls @@ -5402,6 +5421,21 @@ \tcode{*this}. \end{itemdescr} +\indexlibrarymember{ignore}{basic_istream}% +\begin{itemdecl} +basic_istream& ignore(streamsize n, char_type delim); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_same_v} is \tcode{true}. + +\pnum +\effects +Equivalent to: \tcode{return ignore(n, traits::to_int_type(delim));} +\end{itemdescr} + \indexlibrarymember{peek}{basic_istream}% \begin{itemdecl} int_type peek(); @@ -6157,12 +6191,12 @@ namespace std { template class basic_ostream::sentry { - bool ok_; // \expos + bool @\exposid{ok_}@; // \expos public: explicit sentry(basic_ostream& os); ~sentry(); - explicit operator bool() const { return ok_; } + explicit operator bool() const { return @\exposid{ok_}@; } sentry(const sentry&) = delete; sentry& operator=(const sentry&) = delete; @@ -6203,9 +6237,9 @@ \tcode{os.good()} is \tcode{true}, -\tcode{ok_ == true} +\tcode{\exposid{ok_} == true} otherwise, -\tcode{ok_ == false}. +\tcode{\exposid{ok_} == false}. During preparation, the constructor may call \tcode{setstate(failbit)} (which may throw @@ -6233,7 +6267,8 @@ is \tcode{true}, calls -\tcode{os.rdbuf()->pubsync()}. If that function returns $-1$, sets \tcode{badbit} in +\tcode{os.rdbuf()->pubsync()}. If that function returns $-1$ or +exits via an exception, sets \tcode{badbit} in \tcode{os.rdstate()} without propagating an exception. \end{itemdescr} @@ -6246,7 +6281,7 @@ \pnum \effects Returns -\tcode{ok_}. +\exposid{ok_}. \end{itemdescr} \rSec4[ostream.seeks]{Seek members} @@ -6342,7 +6377,7 @@ \tcode{*this}'s error state. If -\tcode{(exceptions()\&badbit) != 0} +\tcode{(exceptions() \& badbit) != 0} then the exception is rethrown. Whether or not an exception is thrown, the \tcode{sentry} @@ -6414,9 +6449,8 @@ \tcode{const void*}, the formatting conversion occurs as if it performed the following code fragment: \begin{codeblock} -bool failed = use_facet< - num_put> - >(getloc()).put(*this, *this, fill(), val).failed(); +bool failed = use_facet>>( + getloc()).put(*this, *this, fill(), val).failed(); \end{codeblock} When \tcode{val} is of type @@ -6424,9 +6458,8 @@ the formatting conversion occurs as if it performed the following code fragment: \begin{codeblock} ios_base::fmtflags baseflags = ios_base::flags() & ios_base::basefield; -bool failed = use_facet< - num_put> - >(getloc()).put(*this, *this, fill(), +bool failed = use_facet>>( + getloc()).put(*this, *this, fill(), baseflags == ios_base::oct || baseflags == ios_base::hex ? static_cast(static_cast(val)) : static_cast(val)).failed(); @@ -6437,9 +6470,8 @@ the formatting conversion occurs as if it performed the following code fragment: \begin{codeblock} ios_base::fmtflags baseflags = ios_base::flags() & ios_base::basefield; -bool failed = use_facet< - num_put> - >(getloc()).put(*this, *this, fill(), +bool failed = use_facet>>( + getloc()).put(*this, *this, fill(), baseflags == ios_base::oct || baseflags == ios_base::hex ? static_cast(static_cast(val)) : static_cast(val)).failed(); @@ -6451,20 +6483,16 @@ \tcode{unsigned int} the formatting conversion occurs as if it performed the following code fragment: \begin{codeblock} -bool failed = use_facet< - num_put> - >(getloc()).put(*this, *this, fill(), - static_cast(val)).failed(); +bool failed = use_facet>>( + getloc()).put(*this, *this, fill(), static_cast(val)).failed(); \end{codeblock} When \tcode{val} is of type \tcode{float} the formatting conversion occurs as if it performed the following code fragment: \begin{codeblock} -bool failed = use_facet< - num_put> - >(getloc()).put(*this, *this, fill(), - static_cast(val)).failed(); +bool failed = use_facet>>( + getloc()).put(*this, *this, fill(), static_cast(val)).failed(); \end{codeblock} \pnum @@ -6521,20 +6549,16 @@ is less than or equal to that of \tcode{double}, the formatting conversion occurs as if it performed the following code fragment: \begin{codeblock} -bool failed = use_facet< - num_put> - >(getloc()).put(*this, *this, fill(), - static_cast(val)).failed(); +bool failed = use_facet>>( + getloc()).put(*this, *this, fill(), static_cast(val)).failed(); \end{codeblock} Otherwise, if the floating-point conversion rank of \tcode{\placeholder{extended-floating-point-type}} is less than or equal to that of \tcode{long double}, the formatting conversion occurs as if it performed the following code fragment: \begin{codeblock} -bool failed = use_facet< - num_put> - >(getloc()).put(*this, *this, fill(), - static_cast(val)).failed(); +bool failed = use_facet>>( + getloc()).put(*this, *this, fill(), static_cast(val)).failed(); \end{codeblock} Otherwise, an invocation of the operator function is conditionally supported with \impldef{\tcode{operator<<} for large extended floating-point types} @@ -6809,7 +6833,21 @@ \effects Equivalent to: \begin{codeblock} -print(os, "{}\n", format(fmt, std::forward(args)...)); +print(os, "{}\n", format(os.getloc(), fmt, std::forward(args)...)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{println}% +\begin{itemdecl} +void println(ostream& os); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +print(os, "\n"); \end{codeblock} \end{itemdescr} @@ -6833,25 +6871,32 @@ without regard to the value of \tcode{os.exceptions()} and without turning on \tcode{ios_base::badbit} in the error state of \tcode{os}. \end{itemize} + +\par % This paragraph is part of the \effects clause. After constructing a \tcode{sentry} object, -the function initializes an automatic variable via +the function initializes a variable with automatic storage duration via \begin{codeblock} string out = vformat(os.getloc(), fmt, args); \end{codeblock} +\begin{itemize} +\item If the function is \tcode{vprint_unicode} and -\tcode{os} is a stream that refers to a terminal capable of displaying Unicode +\tcode{os} is a stream that refers to a terminal that +is capable of displaying Unicode only via a native Unicode API, which is determined in an implementation-defined manner, +flushes \tcode{os} and then writes \tcode{out} to the terminal using the native Unicode API; if \tcode{out} contains invalid code units, \indextext{undefined}% -the behavior is undefined and -implementations are encouraged to diagnose it. -If the native Unicode API is used, -the function flushes \tcode{os} before writing \tcode{out}. -Otherwise (if \tcode{os} is not such a stream or -the function is \tcode{vprint_nonunicode}), +the behavior is undefined. +Then establishes an observable checkpoint\iref{intro.abstract}. +\item +Otherwise inserts the character sequence \range{out.begin()}{out.end()} into \tcode{os}. +\end{itemize} + +\par % This paragraph is part of the \effects clause. If writing to the terminal or inserting into \tcode{os} fails, calls \tcode{os.setstate(ios_base::badbit)} (which may throw \tcode{ios_base::failure}). @@ -6989,7 +7034,7 @@ \tcode{*this}. \end{itemdescr} -\rSec3[ostream.manip]{Standard manipulators} +\rSec3[ostream.manip]{Standard \tcode{basic_ostream} manipulators} \pnum Each instantiation of any of the function templates @@ -7068,7 +7113,7 @@ To work around the issue that the \tcode{Allocator} template argument cannot be deduced, implementations can introduce an intermediate base class -to \tcode{basic_syncbuf} that manages its \tcode{emit_on_sync} flag. +to \tcode{basic_syncbuf} that manages its \exposid{emit-on-sync} flag. \end{note} \pnum @@ -7697,13 +7742,19 @@ \begin{itemdescr} \pnum \effects +Let \tcode{locksafe} be +\tcode{(enable_nonlocking_formatter_optimization> \&\& ...)}. If the ordinary literal encoding\iref{lex.charset} is UTF-8, equivalent to: \begin{codeblock} -vprint_unicode(stream, fmt.@\exposid{str}@, make_format_args(args...)); +locksafe + ? vprint_unicode(stream, fmt.str, make_format_args(args...)) + : vprint_unicode_buffered(stream, fmt.str, make_format_args(args...)); \end{codeblock} Otherwise, equivalent to: \begin{codeblock} -vprint_nonunicode(stream, fmt.@\exposid{str}@, make_format_args(args...)); +locksafe + ? vprint_nonunicode(stream, fmt.str, make_format_args(args...)) + : vprint_nonunicode_buffered(stream, fmt.str, make_format_args(args...)); \end{codeblock} \end{itemdescr} @@ -7722,6 +7773,20 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{println}% +\begin{itemdecl} +void println(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +println(stdout); +\end{codeblock} +\end{itemdescr} + \indexlibraryglobal{println}% \begin{itemdecl} template @@ -7733,7 +7798,21 @@ \effects Equivalent to: \begin{codeblock} -print(stream, "{}\n", format(fmt, std::forward(args)...)); +print(stream, runtime_format(string(fmt.get()) + '\n'), std::forward(args)...); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{println}% +\begin{itemdecl} +void println(FILE* stream); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +print(stream, "\n"); \end{codeblock} \end{itemdescr} @@ -7751,6 +7830,21 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{vprint_unicode_buffered}% +\begin{itemdecl} +void vprint_unicode_buffered(FILE* stream, string_view fmt, format_args args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +string out = vformat(fmt, args); +vprint_unicode(stream, "{}", make_format_args(out)); +\end{codeblock} +\end{itemdescr} + \indexlibraryglobal{vprint_unicode}% \begin{itemdecl} void vprint_unicode(FILE* stream, string_view fmt, format_args args); @@ -7763,28 +7857,32 @@ \pnum \effects -The function initializes an automatic variable via -\begin{codeblock} -string out = vformat(fmt, args); -\end{codeblock} -If \tcode{stream} refers to a terminal capable of displaying Unicode, +Locks \tcode{stream}. +Let \tcode{out} denote the character representation of +formatting arguments provided by \tcode{args} +formatted according to specifications given in \tcode{fmt}. +\begin{itemize} +\item +If \tcode{stream} refers to a terminal that +is capable of displaying Unicode only via a native Unicode API, +flushes \tcode{stream} and then writes \tcode{out} to the terminal using the native Unicode API; if \tcode{out} contains invalid code units, \indextext{undefined}% -the behavior is undefined and -implementations are encouraged to diagnose it. +the behavior is undefined. +Then establishes an observable checkpoint\iref{intro.abstract}. +\item Otherwise writes \tcode{out} to \tcode{stream} unchanged. -If the native Unicode API is used, -the function flushes \tcode{stream} before writing \tcode{out}. +\end{itemize} +Unconditionally unlocks \tcode{stream} on function exit. + +\xrefc{7.21.2}. + \begin{note} -On POSIX and Windows, \tcode{stream} referring to a terminal means that, -respectively, -\tcode{isatty(fileno(\linebreak{}stream))} and +On Windows the native Unicode API is \tcode{WriteConsoleW} and +\tcode{stream} referring to a terminal means that \tcode{GetConsoleMode(_get_osfhandle(_fileno(stream)), ...)} -return nonzero. -\end{note} -\begin{note} -On Windows, the native Unicode API is \tcode{WriteConsoleW}. +returns nonzero. \end{note} \pnum @@ -7815,6 +7913,21 @@ \end{codeblock} \end{itemdescr} +\indexlibraryglobal{vprint_nonunicode_buffered}% +\begin{itemdecl} +void vprint_nonunicode_buffered(FILE* stream, string_view fmt, format_args args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +string out = vformat(fmt, args); +vprint_nonunicode("{}", make_format_args(out)); +\end{codeblock} +\end{itemdescr} + \indexlibraryglobal{vprint_nonunicode}% \begin{itemdecl} void vprint_nonunicode(FILE* stream, string_view fmt, format_args args); @@ -7827,7 +7940,10 @@ \pnum \effects -Writes the result of \tcode{vformat(fmt, args)} to \tcode{stream}. +While holding the lock on \tcode{stream}, +writes the character representation of +formatting arguments provided by \tcode{args} +formatted according to specifications given in \tcode{fmt} to \tcode{stream}. \pnum \throws @@ -7859,8 +7975,8 @@ \indexlibraryglobal{basic_stringstream}% \begin{codeblock} namespace std { - template, - class Allocator = allocator> + // \ref{stringbuf}, class template \tcode{basic_stringbuf} + template, class Allocator = allocator> class basic_stringbuf; template @@ -7870,8 +7986,8 @@ using stringbuf = basic_stringbuf; using wstringbuf = basic_stringbuf; - template, - class Allocator = allocator> + // \ref{istringstream}, class template \tcode{basic_istringstream} + template, class Allocator = allocator> class basic_istringstream; template @@ -7881,8 +7997,8 @@ using istringstream = basic_istringstream; using wistringstream = basic_istringstream; - template, - class Allocator = allocator> + // \ref{ostringstream}, class template \tcode{basic_ostringstream} + template, class Allocator = allocator> class basic_ostringstream; template @@ -7892,8 +8008,8 @@ using ostringstream = basic_ostringstream; using wostringstream = basic_ostringstream; - template, - class Allocator = allocator> + // \ref{stringstream}, class template \tcode{basic_stringstream} + template, class Allocator = allocator> class basic_stringstream; template @@ -7918,8 +8034,7 @@ \indexlibraryglobal{basic_stringbuf}% \begin{codeblock} namespace std { - template, - class Allocator = allocator> + template, class Allocator = allocator> class basic_stringbuf : public basic_streambuf { public: using char_type = charT; @@ -7994,15 +8109,15 @@ pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which - = ios_base::in | ios_base::out) override; + = ios_base::in | ios_base::out) override; pos_type seekpos(pos_type sp, ios_base::openmode which - = ios_base::in | ios_base::out) override; + = ios_base::in | ios_base::out) override; private: - ios_base::openmode mode; // \expos - basic_string buf; // \expos - void init_buf_ptrs(); // \expos + ios_base::openmode @\exposid{mode}@; // \expos + basic_string @\exposid{buf}@; // \expos + void @\exposid{init-buf-ptrs}@(); // \expos }; } \end{codeblock} @@ -8023,17 +8138,17 @@ the maintained data and internal pointer initialization is presented here as: \begin{itemize} \item - \tcode{ios_base::openmode mode}, has + \tcode{ios_base::openmode \exposid{mode}}, has \tcode{in} set if the input sequence can be read, and \tcode{out} set if the output sequence can be written. \item - \tcode{basic_string buf} + \tcode{basic_string \exposid{buf}} contains the underlying character sequence. \item - \tcode{init_buf_ptrs()} sets the base class' + \tcode{\exposid{init-buf-ptrs}()} sets the base class' get area\iref{streambuf.get.area} and put area\iref{streambuf.put.area} pointers - after initializing, moving from, or assigning to \tcode{buf} accordingly. + after initializing, moving from, or assigning to \exposid{buf} accordingly. \end{itemize} \rSec3[stringbuf.cons]{Constructors} @@ -8048,7 +8163,7 @@ \effects Initializes the base class with \tcode{basic_streambuf()}\iref{streambuf.cons}, and -\tcode{mode} +\exposid{mode} with \tcode{which}. It is \impldef{whether sequence pointers are initialized to null pointers} @@ -8074,9 +8189,9 @@ \effects Initializes the base class with \tcode{basic_streambuf()}\iref{streambuf.cons}, -\tcode{mode} with \tcode{which}, and -\tcode{buf} with \tcode{s}, -then calls \tcode{init_buf_ptrs()}. +\exposid{mode} with \tcode{which}, and +\exposid{buf} with \tcode{s}, +then calls \tcode{\exposid{init-buf-ptrs}()}. \end{itemdescr} \indexlibraryctor{basic_stringbuf}% @@ -8089,9 +8204,9 @@ \effects Initializes the base class with \tcode{basic_streambuf()}\iref{streambuf.cons}, -\tcode{mode} with \tcode{which}, and -\tcode{buf} with \tcode{a}, -then calls \tcode{init_buf_ptrs()}. +\exposid{mode} with \tcode{which}, and +\exposid{buf} with \tcode{a}, +then calls \tcode{\exposid{init-buf-ptrs}()}. \pnum \ensures @@ -8109,9 +8224,9 @@ \pnum \effects Initializes the base class with \tcode{basic_streambuf()}\iref{streambuf.cons}, -\tcode{mode} with \tcode{which}, and -\tcode{buf} with \tcode{std::move(s)}, -then calls \tcode{init_buf_ptrs()}. +\exposid{mode} with \tcode{which}, and +\exposid{buf} with \tcode{std::move(s)}, +then calls \tcode{\exposid{init-buf-ptrs}()}. \end{itemdescr} \indexlibraryctor{basic_stringbuf}% @@ -8126,9 +8241,9 @@ \pnum \effects Initializes the base class with \tcode{basic_streambuf()}\iref{streambuf.cons}, -\tcode{mode} with \tcode{which}, and -\tcode{buf} with \tcode{\{s,a\}}, -then calls \tcode{init_buf_ptrs()}. +\exposid{mode} with \tcode{which}, and +\exposid{buf} with \tcode{\{s,a\}}, +then calls \tcode{\exposid{init-buf-ptrs}()}. \end{itemdescr} \indexlibraryctor{basic_stringbuf}% @@ -8147,9 +8262,9 @@ \pnum \effects Initializes the base class with \tcode{basic_streambuf()}\iref{streambuf.cons}, -\tcode{mode} with \tcode{which}, and -\tcode{buf} with \tcode{s}, -then calls \tcode{init_buf_ptrs()}. +\exposid{mode} with \tcode{which}, and +\exposid{buf} with \tcode{s}, +then calls \tcode{\exposid{init-buf-ptrs}()}. \end{itemdescr} \indexlibraryctor{basic_stringbuf}% @@ -8178,9 +8293,9 @@ Creates a variable \tcode{sv} as if by \tcode{basic_string_view sv = t}, then value-initializes the base class, -initializes \tcode{mode} with \tcode{which}, and -direct-non-list-initializes \tcode{buf} with \tcode{sv, a}, -then calls \tcode{init_buf_ptrs()}. +initializes \exposid{mode} with \tcode{which}, and +direct-non-list-initializes \exposid{buf} with \tcode{sv, a}, +then calls \tcode{\exposid{init-buf-ptrs}()}. \end{itemdescr} \indexlibraryctor{basic_stringbuf}% @@ -8193,10 +8308,10 @@ \pnum \effects Copy constructs the base class from \tcode{rhs} and -initializes \tcode{mode} with \tcode{rhs.mode}. +initializes \exposid{mode} with \tcode{rhs.mode}. In the first form \tcode{buf} is initialized from \tcode{std::move(rhs).str()}. -In the second form \tcode{buf} is initialized +In the second form \exposid{buf} is initialized from \tcode{\{std::move(rhs).str(), a\}}. It is \impldef{whether sequence pointers are copied by \tcode{basic_stringbuf} move @@ -8301,39 +8416,39 @@ (except for those characters re-initialized by the new \tcode{basic_string}). \begin{itemdecl} -void init_buf_ptrs(); // \expos +void @\exposid{init-buf-ptrs}@(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes the input and output sequences from \tcode{buf} -according to \tcode{mode}. +Initializes the input and output sequences from \exposid{buf} +according to \exposid{mode}. \pnum \ensures \begin{itemize} -\item If \tcode{ios_base::out} is set in \tcode{mode}, - \tcode{pbase()} points to \tcode{buf.front()} and - \tcode{epptr() >= pbase() + buf.size()} is \tcode{true}; +\item If \tcode{ios_base::out} is set in \exposid{mode}, + \tcode{pbase()} points to \tcode{\exposid{buf}.front()} and + \tcode{epptr() >= pbase() + \exposid{buf}.size()} is \tcode{true}; \begin{itemize} - \item in addition, if \tcode{ios_base::ate} is set in \tcode{mode}, - \tcode{pptr() == pbase() + buf.size()} is \tcode{true}, + \item in addition, if \tcode{ios_base::ate} is set in \exposid{mode}, + \tcode{pptr() == pbase() + \exposid{buf}.size()} is \tcode{true}, \item otherwise \tcode{pptr() == pbase()} is \tcode{true}. \end{itemize} -\item If \tcode{ios_base::in} is set in \tcode{mode}, - \tcode{eback()} points to \tcode{buf.front()}, and - \tcode{(gptr() == eback() \&\& egptr() == eback() + buf.size())} +\item If \tcode{ios_base::in} is set in \exposid{mode}, + \tcode{eback()} points to \tcode{\exposid{buf}.front()}, and + \tcode{(gptr() == eback() \&\& egptr() == eback() + \exposid{buf}.size())} is \tcode{true}. \end{itemize} \pnum \begin{note} For efficiency reasons, -stream buffer operations can violate invariants of \tcode{buf} +stream buffer operations can violate invariants of \exposid{buf} while it is held encapsulated in the \tcode{basic_stringbuf}, e.g., by writing to characters in the range -\range{\tcode{buf.data() + buf.size()}}{\tcode{buf.data() + buf.capacity()}}. +\range{\tcode{\exposid{buf}.data() + \exposid{buf}.size()}}{\tcode{\exposid{buf}.data() + \exposid{buf}.capacity()}}. All operations retrieving a \tcode{basic_string} from \tcode{buf} ensure that the \tcode{basic_string} invariants hold on the returned value. \end{note} @@ -8347,7 +8462,7 @@ \begin{itemdescr} \pnum \returns -\tcode{buf.get_allocator()}. +\tcode{\exposid{buf}.get_allocator()}. \end{itemdescr} \indexlibrarymember{str}{basic_stringbuf}% @@ -8394,7 +8509,7 @@ The underlying character sequence \tcode{buf} is empty and \tcode{pbase()}, \tcode{pptr()}, \tcode{epptr()}, \tcode{eback()}, \tcode{gptr()}, and \tcode{egptr()} -are initialized as if by calling \tcode{init_buf_ptrs()} +are initialized as if by calling \tcode{\exposid{init-buf-ptrs}()} with an empty \tcode{buf}. \pnum @@ -8420,10 +8535,10 @@ A \tcode{sv} object referring to the \tcode{basic_stringbuf}'s underlying character sequence in \tcode{buf}: \begin{itemize} -\item If \tcode{ios_base::out} is set in \tcode{mode}, - then \tcode{sv(pbase(), high_mark-pbase())} is returned. -\item Otherwise, if \tcode{ios_base::in} is set in \tcode{mode}, - then \tcode{sv(eback(), egptr()-eback())} is returned. +\item If \tcode{ios_base::out} is set in \exposid{mode}, + then \tcode{sv(pbase(), high_mark - pbase())} is returned. +\item Otherwise, if \tcode{ios_base::in} is set in \exposid{mode}, + then \tcode{sv(eback(), egptr() - eback())} is returned. \item Otherwise, \tcode{sv()} is returned. \end{itemize} @@ -8445,8 +8560,8 @@ \effects Equivalent to: \begin{codeblock} -buf = s; -init_buf_ptrs(); +@\exposid{buf}@ = s; +@\exposid{init-buf-ptrs}@(); \end{codeblock} \end{itemdescr} @@ -8459,14 +8574,14 @@ \begin{itemdescr} \pnum \constraints -\tcode{is_same_v} is \tcode{false}. +\tcode{is_same_v} is \tcode{false}. \pnum \effects Equivalent to: \begin{codeblock} -buf = s; -init_buf_ptrs(); +@\exposid{buf}@ = s; +@\exposid{init-buf-ptrs}@(); \end{codeblock} \end{itemdescr} @@ -8480,8 +8595,8 @@ \effects Equivalent to: \begin{codeblock} -buf = std::move(s); -init_buf_ptrs(); +@\exposid{buf}@ = std::move(s); +@\exposid{init-buf-ptrs}@(); \end{codeblock} \end{itemdescr} @@ -8502,8 +8617,8 @@ Equivalent to: \begin{codeblock} basic_string_view sv = t; -buf = sv; -init_buf_ptrs(); +@\exposid{buf}@ = sv; +@\exposid{init-buf-ptrs}@(); \end{codeblock} \end{itemdescr} @@ -8562,7 +8677,7 @@ \tcode{false} and if the input sequence has a putback position available, and -if \tcode{mode} +if \exposid{mode} \tcode{\&} \tcode{ios_base::out} is nonzero, @@ -8648,14 +8763,14 @@ \pnum The function can make a write position available only if -\tcode{ios_base::out} is set in \tcode{mode}. +\tcode{ios_base::out} is set in \exposid{mode}. To make a write position available, the function reallocates (or initially allocates) an array object with a sufficient number of elements to hold the current array object (if any), plus at least one additional write position. -If \tcode{ios_base::in} is set in \tcode{mode}, +If \tcode{ios_base::in} is set in \exposid{mode}, the function alters the read end pointer \tcode{egptr()} to point just past the new write position. @@ -8779,8 +8894,7 @@ \indexlibraryglobal{basic_istringstream}% \begin{codeblock} namespace std { - template, - class Allocator = allocator> + template, class Allocator = allocator> class basic_istringstream : public basic_istream { public: using char_type = charT; @@ -8843,7 +8957,7 @@ void str(const T& t); private: - basic_stringbuf sb; // \expos + basic_stringbuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -8859,7 +8973,7 @@ For the sake of exposition, the maintained data is presented here as: \begin{itemize} \item -\tcode{sb}, the \tcode{stringbuf} object. +\exposid{sb}, the \tcode{stringbuf} object. \end{itemize} \rSec3[istringstream.cons]{Constructors} @@ -8873,8 +8987,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_istream(addressof(sb))}\iref{istream} -and \tcode{sb} with +\tcode{basic_istream(addressof(\exposid{sb}))}\iref{istream} +and \exposid{sb} with \tcode{basic_stringbuf(which | ios_base::in)}\iref{stringbuf.cons}. \end{itemdescr} @@ -8889,8 +9003,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_istream(addressof(sb))}\iref{istream} -and \tcode{sb} with +\tcode{basic_istream(addressof(\exposid{sb}))}\iref{istream} +and \exposid{sb} with \tcode{basic_stringbuf(s, which | ios_base::in)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} @@ -8903,8 +9017,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_istream(addressof(sb))}\iref{istream} -and \tcode{sb} with +\tcode{basic_istream(addressof(\exposid{sb}))}\iref{istream} +and \exposid{sb} with \tcode{basic_stringbuf(which | ios_base::in, a)}\iref{stringbuf.cons}. \end{itemdescr} @@ -8919,8 +9033,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_istream(addressof(sb))}\iref{istream} -and \tcode{sb} with +\tcode{basic_istream(addressof(\exposid{sb}))}\iref{istream} +and \exposid{sb} with \tcode{basic_stringbuf(std::move(s), which | ios_base::\brk{}in)}\iref{stringbuf.cons}. \end{itemdescr} @@ -8936,8 +9050,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_istream(addressof(sb))}\iref{istream} -and \tcode{sb} with +\tcode{basic_istream(addressof(\exposid{sb}))}\iref{istream} +and \exposid{sb} with \tcode{basic_stringbuf(s, which | ios_base::in, a)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} @@ -8957,8 +9071,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_istream(addressof(sb))}\iref{istream} -and \tcode{sb} with +\tcode{basic_istream(addressof(\exposid{sb}))}\iref{istream} +and \exposid{sb} with \tcode{basic_stringbuf(s, which | ios_base::in)}\iref{stringbuf.cons}. \end{itemdescr} @@ -8985,8 +9099,8 @@ \pnum \effects -Initializes the base class with \tcode{addressof(sb)}, and -direct-non-list-initializes \tcode{sb} with \tcode{t, which | ios_base::in, a}. +Initializes the base class with \tcode{addressof(\exposid{sb})}, and +direct-non-list-initializes \exposid{sb} with \tcode{t, which | ios_base::in, a}. \end{itemdescr} \indexlibraryctor{basic_istringstream}% @@ -9000,7 +9114,7 @@ Move constructs from the rvalue \tcode{rhs}. This is accomplished by move constructing the base class, and the contained \tcode{basic_stringbuf}. -Then calls \tcode{basic_istream::set_rdbuf(addressof(sb))} +Then calls \tcode{basic_istream::set_rdbuf(addressof(\exposid{sb}))} to install the contained \tcode{basic_stringbuf}. \end{itemdescr} @@ -9017,7 +9131,7 @@ Equivalent to: \begin{codeblock} basic_istream::swap(rhs); -sb.swap(rhs.sb); +@\exposid{sb}@.swap(rhs.@\exposid{sb}@); \end{codeblock} \end{itemdescr} @@ -9045,7 +9159,7 @@ \begin{itemdescr} \pnum \returns -\tcode{const_cast*>(addressof(sb))}. +\tcode{const_cast*>(addressof(\exposid{sb}))}. \end{itemdescr} \indexlibrarymember{str}{basic_istringstream}% @@ -9151,8 +9265,7 @@ \indexlibraryglobal{basic_ostringstream}% \begin{codeblock} namespace std { - template, - class Allocator = allocator> + template, class Allocator = allocator> class basic_ostringstream : public basic_ostream { public: using char_type = charT; @@ -9216,7 +9329,7 @@ void str(const T& t); private: - basic_stringbuf sb; // \expos + basic_stringbuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -9232,7 +9345,7 @@ For the sake of exposition, the maintained data is presented here as: \begin{itemize} \item -\tcode{sb}, the \tcode{stringbuf} object. +\exposid{sb}, the \tcode{stringbuf} object. \end{itemize} \rSec3[ostringstream.cons]{Constructors} @@ -9246,8 +9359,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_ostream(addressof(sb))}\iref{ostream} -and \tcode{sb} with +\tcode{basic_ostream(addressof(\exposid{sb}))}\iref{ostream} +and \exposid{sb} with \tcode{basic_stringbuf(which | ios_base::out)}\iref{stringbuf.cons}. \end{itemdescr} @@ -9262,8 +9375,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_ostream(addressof(sb))}\iref{ostream} -and \tcode{sb} with +\tcode{basic_ostream(addressof(\exposid{sb}))}\iref{ostream} +and \exposid{sb} with \tcode{basic_stringbuf(s, which | ios_base::out)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} @@ -9276,8 +9389,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_ostream(addressof(sb))}\iref{ostream} -and \tcode{sb} with +\tcode{basic_ostream(addressof(\exposid{sb}))}\iref{ostream} +and \exposid{sb} with \tcode{basic_stringbuf(which | ios_base::out, a)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} @@ -9292,8 +9405,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_ostream(addressof(sb))}\iref{ostream} -and \tcode{sb} with +\tcode{basic_ostream(addressof(\exposid{sb}))}\iref{ostream} +and \exposid{sb} with \tcode{basic_stringbuf(std::move(s), which | ios_base::\brk{}out)}\iref{stringbuf.cons}. \end{itemdescr} @@ -9309,8 +9422,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_ostream(addressof(sb))}\iref{ostream} -and \tcode{sb} with +\tcode{basic_ostream(addressof(\exposid{sb}))}\iref{ostream} +and \exposid{sb} with \tcode{basic_stringbuf(s, which | ios_base::out, a)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} @@ -9325,13 +9438,13 @@ \begin{itemdescr} \pnum \constraints -\tcode{is_same_v} is \tcode{false}. +\tcode{is_same_v} is \tcode{false}. \pnum \effects Initializes the base class with -\tcode{basic_ostream(addressof(sb))}\iref{ostream} -and \tcode{sb} with +\tcode{basic_ostream(addressof(\exposid{sb}))}\iref{ostream} +and \exposid{sb} with \tcode{basic_stringbuf(s, which | ios_base::out)}\linebreak\iref{stringbuf.cons}. % avoid Overfull \end{itemdescr} @@ -9358,8 +9471,8 @@ \pnum \effects -Initializes the base class with \tcode{addressof(sb)}, and -direct-non-list-initializes \tcode{sb} with \tcode{t, which | ios_base::out, a}. +Initializes the base class with \tcode{addressof(\exposid{sb})}, and +direct-non-list-initializes \exposid{sb} with \tcode{t, which | ios_base::out, a}. \end{itemdescr} \indexlibraryctor{basic_ostringstream}% @@ -9373,7 +9486,7 @@ Move constructs from the rvalue \tcode{rhs}. This is accomplished by move constructing the base class, and the contained \tcode{basic_stringbuf}. -Then calls \tcode{basic_ostream::set_rdbuf(addressof(sb))} +Then calls \tcode{basic_ostream::set_rdbuf(addressof(\exposid{sb}))} to install the contained \tcode{basic_stringbuf}. \end{itemdescr} @@ -9390,7 +9503,7 @@ Equivalent to: \begin{codeblock} basic_ostream::swap(rhs); -sb.swap(rhs.sb); +@\exposid{sb}@.swap(rhs.@\exposid{sb}@); \end{codeblock} \end{itemdescr} @@ -9417,7 +9530,7 @@ \begin{itemdescr} \pnum \returns -\tcode{const_cast*>(addressof(sb))}. +\tcode{const_cast*>(addressof(\exposid{sb}))}. \end{itemdescr} \indexlibrarymember{str}{basic_ostringstream}% @@ -9523,8 +9636,7 @@ \indexlibraryglobal{basic_stringstream}% \begin{codeblock} namespace std { - template, - class Allocator = allocator> + template, class Allocator = allocator> class basic_stringstream : public basic_iostream { public: using char_type = charT; @@ -9589,7 +9701,7 @@ void str(const T& t); private: - basic_stringbuf sb; // \expos + basic_stringbuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -9606,7 +9718,7 @@ For the sake of exposition, the maintained data is presented here as \begin{itemize} \item -\tcode{sb}, the \tcode{stringbuf} object. +\exposid{sb}, the \tcode{stringbuf} object. \end{itemize} \rSec3[stringstream.cons]{Constructors} @@ -9620,9 +9732,9 @@ \pnum \effects Initializes the base class with -\tcode{basic_iostream(addressof(sb))}\iref{iostream.cons} +\tcode{basic_iostream(addressof(\exposid{sb}))}\iref{iostream.cons} and -\tcode{sb} +\exposid{sb} with \tcode{basic_string\-buf(which)}. \end{itemdescr} @@ -9638,9 +9750,9 @@ \pnum \effects Initializes the base class with -\tcode{basic_iostream(addressof(sb))}\iref{iostream.cons} +\tcode{basic_iostream(addressof(\exposid{sb}))}\iref{iostream.cons} and -\tcode{sb} +\exposid{sb} with \tcode{basic_string\-buf(s, which)}. \end{itemdescr} @@ -9654,8 +9766,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_iostream(addressof(sb))}\iref{iostream.cons} -and \tcode{sb} with +\tcode{basic_iostream(addressof(\exposid{sb}))}\iref{iostream.cons} +and \exposid{sb} with \tcode{basic_stringbuf(which, a)}\iref{stringbuf.cons}. \end{itemdescr} @@ -9670,8 +9782,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_iostream(addressof(sb))}\iref{iostream.cons} -and \tcode{sb} with +\tcode{basic_iostream(addressof(\exposid{sb}))}\iref{iostream.cons} +and \exposid{sb} with \tcode{basic_stringbuf(std::move(s), which)}\iref{stringbuf.cons}. \end{itemdescr} @@ -9687,8 +9799,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_iostream(addressof(sb))}\iref{iostream.cons} -and \tcode{sb} with +\tcode{basic_iostream(addressof(\exposid{sb}))}\iref{iostream.cons} +and \exposid{sb} with \tcode{basic_stringbuf(s, which, a)}\iref{stringbuf.cons}. \end{itemdescr} @@ -9703,13 +9815,13 @@ \begin{itemdescr} \pnum \constraints -\tcode{is_same_v} is \tcode{false}. +\tcode{is_same_v} is \tcode{false}. \pnum \effects Initializes the base class with -\tcode{basic_iostream(addressof(sb))}\iref{iostream.cons} -and \tcode{sb} with +\tcode{basic_iostream(addressof(\exposid{sb}))}\iref{iostream.cons} +and \exposid{sb} with \tcode{basic_stringbuf(s, which)}\iref{stringbuf.cons}. \end{itemdescr} @@ -9736,8 +9848,8 @@ \pnum \effects -Initializes the base class with \tcode{addressof(sb)}, and -direct-non-list-initializes \tcode{sb} with \tcode{t, which, a}. +Initializes the base class with \tcode{addressof(\exposid{sb})}, and +direct-non-list-initializes \exposid{sb} with \tcode{t, which, a}. \end{itemdescr} \indexlibraryctor{basic_stringstream}% @@ -9751,7 +9863,7 @@ Move constructs from the rvalue \tcode{rhs}. This is accomplished by move constructing the base class, and the contained \tcode{basic_stringbuf}. -Then calls \tcode{basic_istream::set_rdbuf(addressof(sb))} +Then calls \tcode{basic_istream::set_rdbuf(addressof(\exposid{sb}))} to install the contained \tcode{basic_stringbuf}. \end{itemdescr} @@ -9768,7 +9880,7 @@ Equivalent to: \begin{codeblock} basic_iostream::swap(rhs); -sb.swap(rhs.sb); +@\exposid{sb}@.swap(rhs.@\exposid{sb}@); \end{codeblock} \end{itemdescr} @@ -9795,7 +9907,7 @@ \begin{itemdescr} \pnum \returns -\tcode{const_cast*>(addressof(sb))}. +\tcode{const_cast*>(addressof(\exposid{sb}))}. \end{itemdescr} \indexlibrarymember{str}{basic_stringstream}% @@ -9905,7 +10017,7 @@ \begin{note} A user of these classes is responsible for ensuring that the character sequence represented by the given \tcode{span} -outlives the use of the sequence by objects of the classes in subclause \ref{span.streams}. +outlives the use of the sequence by objects of the classes in \ref{span.streams}. Using multiple \tcode{basic_spanbuf} objects referring to overlapping underlying sequences from different threads, where at least one \tcode{basic_spanbuf} object is used @@ -9925,6 +10037,7 @@ \indexlibraryglobal{wspanstream}% \begin{codeblock} namespace std { + // \ref{spanbuf}, class template \tcode{basic_spanbuf} template> class basic_spanbuf; @@ -9934,6 +10047,7 @@ using spanbuf = basic_spanbuf; using wspanbuf = basic_spanbuf; + // \ref{ispanstream}, class template \tcode{basic_ispanstream} template> class basic_ispanstream; @@ -9943,6 +10057,7 @@ using ispanstream = basic_ispanstream; using wispanstream = basic_ispanstream; + // \ref{ospanstream}, class template \tcode{basic_ospanstream} template> class basic_ospanstream; @@ -9952,6 +10067,7 @@ using ospanstream = basic_ospanstream; using wospanstream = basic_ospanstream; + // \ref{spanstream}, class template \tcode{basic_spanstream} template> class basic_spanstream; @@ -10009,7 +10125,7 @@ private: ios_base::openmode @\exposid{mode}@; // \expos std::span @\exposid{buf}@; // \expos -}; + }; } \end{codeblock} @@ -10240,7 +10356,7 @@ if \tcode{ios_base::out} is set in \exposid{mode} and \tcode{ios_base::in} is not set in \exposid{mode}, \item -\tcode{buf.size()} otherwise. +\tcode{\exposid{buf}.size()} otherwise. \end{itemize} \end{itemize} @@ -10328,7 +10444,7 @@ template void span(ROS&& s) noexcept; private: - basic_spanbuf sb; // \expos + basic_spanbuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -10351,8 +10467,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_istream(addressof(sb))} -and \tcode{sb} with +\tcode{basic_istream(addressof(\exposid{sb}))} +and \exposid{sb} with \tcode{basic_spanbuf(s, which | ios_base::in)}\iref{spanbuf.cons}. \end{itemdescr} @@ -10365,9 +10481,9 @@ \pnum \effects Initializes the base class with \tcode{std::move(rhs)} -and \tcode{sb} with \tcode{std::move(rhs.sb)}. -Next, \tcode{basic_istream::set_rdbuf(addressof(sb))} is called -to install the contained \tcode{basic_spanbuf}. +and \exposid{sb} with \tcode{std::move(rhs.\exposid{sb})}. +Next, \tcode{basic_istream::set_rdbuf(addressof(\exposid{sb}))} is called +to install the contained \tcode{ba\-sic_\-span\-buf}. \end{itemdescr} \indexlibraryctor{basic_ispanstream}% @@ -10404,7 +10520,7 @@ Equivalent to: \begin{codeblock} basic_istream::swap(rhs); -sb.swap(rhs.sb); +@\exposid{sb}@.swap(rhs.@\exposid{sb}@); \end{codeblock} \end{itemdescr} @@ -10432,7 +10548,7 @@ \effects Equivalent to: \begin{codeblock} -return const_cast*>(addressof(sb)); +return const_cast*>(addressof(@\exposid{sb}@)); \end{codeblock} \end{itemdescr} @@ -10514,7 +10630,7 @@ void span(std::span s) noexcept; private: - basic_spanbuf sb; // \expos + basic_spanbuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -10531,8 +10647,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_ostream(addressof(sb))} -and \tcode{sb} with +\tcode{basic_ostream(addressof(\exposid{sb}))} +and \exposid{sb} with \tcode{basic_spanbuf(s, which | ios_base::out)}\iref{spanbuf.cons}. \end{itemdescr} @@ -10545,9 +10661,9 @@ \pnum \effects Initializes the base class with \tcode{std::move(rhs)} -and \tcode{sb} with \tcode{std::move(rhs.sb)}. -Next, \tcode{basic_ostream::set_rdbuf(addressof(sb))} -is called to install the contained \tcode{basic_spanbuf}. +and \exposid{sb} with \tcode{std::move(rhs.\exposid{sb})}. +Next, \tcode{basic_ostream::set_rdbuf(addressof(\exposid{sb}))} +is called to install the contained \tcode{ba\-sic_\-span\-buf}. \end{itemdescr} \rSec3[ospanstream.swap]{Swap} @@ -10563,7 +10679,7 @@ Equivalent to: \begin{codeblock} basic_ostream::swap(rhs); -sb.swap(rhs.sb); +@\exposid{sb}@.swap(rhs.@\exposid{sb}@); \end{codeblock} \end{itemdescr} @@ -10591,7 +10707,7 @@ \effects Equivalent to: \begin{codeblock} -return const_cast*>(addressof(sb)); +return const_cast*>(addressof(@\exposid{sb}@)); \end{codeblock} \end{itemdescr} @@ -10653,7 +10769,7 @@ void span(std::span s) noexcept; private: - basic_spanbuf sb; // \expos + basic_spanbuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -10670,8 +10786,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_iostream(addressof(sb))} -and \tcode{sb} with +\tcode{basic_iostream(addressof(\exposid{sb}))} +and \exposid{sb} with \tcode{basic_spanbuf(s, which)}\iref{spanbuf.cons}. \end{itemdescr} @@ -10684,8 +10800,8 @@ \pnum \effects Initializes the base class with \tcode{std::move(rhs)} -and \tcode{sb} with \tcode{std::move(rhs.sb)}. -Next, \tcode{basic_iostream::set_rdbuf(addressof(sb))} +and \exposid{sb} with \tcode{std::move(rhs.\exposid{sb})}. +Next, \tcode{basic_iostream::set_rdbuf(addressof(\exposid{sb}))} is called to install the contained \tcode{basic_spanbuf}. \end{itemdescr} @@ -10702,7 +10818,7 @@ Equivalent to: \begin{codeblock} basic_iostream::swap(rhs); -sb.swap(rhs.sb); +@\exposid{sb}@.swap(rhs.@\exposid{sb}@); \end{codeblock} \end{itemdescr} @@ -10730,7 +10846,7 @@ \effects Equivalent to: \begin{codeblock} -return const_cast*>(addressof(sb)); +return const_cast*>(addressof(@\exposid{sb}@)); \end{codeblock} \end{itemdescr} @@ -10779,6 +10895,7 @@ \indexlibraryglobal{basic_fstream}% \begin{codeblock} namespace std { + // \ref{filebuf}, class template \tcode{basic_filebuf} template> class basic_filebuf; @@ -10788,6 +10905,7 @@ using filebuf = basic_filebuf; using wfilebuf = basic_filebuf; + // \ref{ifstream}, class template \tcode{basic_ifstream} template> class basic_ifstream; @@ -10797,6 +10915,7 @@ using ifstream = basic_ifstream; using wifstream = basic_ifstream; + // \ref{ofstream}, class template \tcode{basic_ofstream} template> class basic_ofstream; @@ -10806,6 +10925,7 @@ using ofstream = basic_ofstream; using wofstream = basic_ofstream; + // \ref{fstream}, class template \tcode{basic_fstream} template> class basic_fstream; @@ -11117,7 +11237,7 @@ \begin{itemdescr} \pnum \expects -\tcode{s} points to a NTCTS\iref{defns.ntcts}. +\tcode{s} points to an NTCTS\iref{defns.ntcts}. \pnum \effects @@ -11462,6 +11582,7 @@ At this point if \tcode{b != p} and \tcode{b == end} (\tcode{xbuf} isn't large enough) then increase \tcode{XSIZE} and repeat from the beginning. \end{itemize} +Then establishes an observable checkpoint\iref{intro.abstract}. \pnum \returns @@ -11705,7 +11826,7 @@ void close(); private: - basic_filebuf sb; // \expos + basic_filebuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -11721,7 +11842,7 @@ For the sake of exposition, the maintained data is presented here as: \begin{itemize} \item -\tcode{sb}, the \tcode{filebuf} object. +\exposid{sb}, the \tcode{filebuf} object. \end{itemize} \rSec3[ifstream.cons]{Constructors} @@ -11735,8 +11856,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_istream(addressof(sb))}\iref{istream.cons} -and \tcode{sb} with +\tcode{basic_istream(addressof(\exposid{sb}))}\iref{istream.cons} +and \exposid{sb} with \tcode{basic_filebuf()}\iref{filebuf.cons}. \end{itemdescr} @@ -11752,8 +11873,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_istream(addressof(sb))}\iref{istream.cons} -and \tcode{sb} with +\tcode{basic_istream(addressof(\exposid{sb}))}\iref{istream.cons} +and \exposid{sb} with \tcode{basic_filebuf()}\iref{filebuf.cons}, then calls \tcode{rdbuf()->open(s, mode | ios_base::in)}. @@ -11798,7 +11919,7 @@ \pnum \effects Move constructs the base class, and the contained \tcode{basic_filebuf}. -Then calls \tcode{basic_istream::set_rdbuf(\brk{}addressof(sb))} +Then calls \tcode{basic_istream::set_rdbuf(\brk{}addressof(\exposid{sb}))} to install the contained \tcode{basic_filebuf}. \end{itemdescr} @@ -11815,7 +11936,7 @@ Exchanges the state of \tcode{*this} and \tcode{rhs} by calling \tcode{basic_istream::swap(rhs)} and -\tcode{sb.swap(rhs.sb)}. +\tcode{\exposid{sb}.swap(rhs.\exposid{sb})}. \end{itemdescr} \indexlibrarymember{swap}{basic_ifstream}% @@ -11840,7 +11961,7 @@ \begin{itemdescr} \pnum \returns -\tcode{const_cast*>(addressof(sb))}. +\tcode{const_cast*>(addressof(\exposid{sb}))}. \end{itemdescr} \indexlibrarymember{native_handle}{basic_ifstream}% @@ -11964,7 +12085,7 @@ void close(); private: - basic_filebuf sb; // \expos + basic_filebuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -11980,7 +12101,7 @@ For the sake of exposition, the maintained data is presented here as: \begin{itemize} \item -\tcode{sb}, the \tcode{filebuf} object. +\exposid{sb}, the \tcode{filebuf} object. \end{itemize} \rSec3[ofstream.cons]{Constructors} @@ -11994,8 +12115,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_ostream(addressof(sb))}\iref{ostream.cons} -and \tcode{sb} with +\tcode{basic_ostream(addressof(\exposid{sb}))}\iref{ostream.cons} +and \exposid{sb} with \tcode{basic_filebuf()}\iref{filebuf.cons}. \end{itemdescr} @@ -12011,8 +12132,8 @@ \pnum \effects Initializes the base class with -\tcode{basic_ostream(addressof(sb))}\iref{ostream.cons} -and \tcode{sb} with +\tcode{basic_ostream(addressof(\exposid{sb}))}\iref{ostream.cons} +and \exposid{sb} with \tcode{basic_filebuf()}\iref{filebuf.cons}, then calls \tcode{rdbuf()->open(s, mode | ios_base::out)}. @@ -12057,7 +12178,7 @@ \pnum \effects Move constructs the base class, and the contained \tcode{basic_filebuf}. -Then calls \tcode{basic_ostream::set_rdbuf(\brk{}addressof(sb))} +Then calls \tcode{basic_ostream::set_rdbuf(\brk{}addressof(\exposid{sb}))} to install the contained \tcode{basic_filebuf}. \end{itemdescr} @@ -12074,7 +12195,7 @@ Exchanges the state of \tcode{*this} and \tcode{rhs} by calling \tcode{basic_ostream::swap(rhs)} and -\tcode{sb.swap(rhs.sb)}. +\tcode{\exposid{sb}.swap(rhs.\exposid{sb})}. \end{itemdescr} \indexlibrarymember{swap}{basic_ofstream}% @@ -12099,7 +12220,7 @@ \begin{itemdescr} \pnum \returns -\tcode{const_cast*>(addressof(sb))}. +\tcode{const_cast*>(addressof(\exposid{sb}))}. \end{itemdescr} \indexlibrarymember{native_handle}{basic_ofstream}% @@ -12196,7 +12317,7 @@ ios_base::openmode mode = ios_base::in | ios_base::out); explicit basic_fstream( const filesystem::path::value_type* s, - ios_base::openmode mode = ios_base::in|ios_base::out); // wide systems only; see \ref{fstream.syn} + ios_base::openmode mode = ios_base::in | ios_base::out); // wide systems only; see \ref{fstream.syn} explicit basic_fstream( const string& s, ios_base::openmode mode = ios_base::in | ios_base::out); @@ -12221,7 +12342,7 @@ ios_base::openmode mode = ios_base::in | ios_base::out); void open( const filesystem::path::value_type* s, - ios_base::openmode mode = ios_base::in|ios_base::out); // wide systems only; see \ref{fstream.syn} + ios_base::openmode mode = ios_base::in | ios_base::out); // wide systems only; see \ref{fstream.syn} void open( const string& s, ios_base::openmode mode = ios_base::in | ios_base::out); @@ -12231,7 +12352,7 @@ void close(); private: - basic_filebuf sb; // \expos + basic_filebuf @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -12247,7 +12368,7 @@ For the sake of exposition, the maintained data is presented here as: \begin{itemize} \item -\tcode{sb}, the \tcode{basic_filebuf} object. +\exposid{sb}, the \tcode{basic_filebuf} object. \end{itemize} \rSec3[fstream.cons]{Constructors} @@ -12261,9 +12382,9 @@ \pnum \effects Initializes the base class with -\tcode{basic_iostream(addressof(sb))}\iref{iostream.cons} +\tcode{basic_iostream(addressof(\exposid{sb}))}\iref{iostream.cons} and -\tcode{sb} with \tcode{basic_filebuf()}. +\exposid{sb} with \tcode{basic_filebuf()}. \end{itemdescr} \indexlibraryctor{basic_fstream}% @@ -12280,9 +12401,9 @@ \pnum \effects Initializes the base class with -\tcode{basic_iostream(addressof(sb))}\iref{iostream.cons} +\tcode{basic_iostream(addressof(\exposid{sb}))}\iref{iostream.cons} and -\tcode{sb} with \tcode{basic_filebuf()}. +\exposid{sb} with \tcode{basic_filebuf()}. Then calls \tcode{rdbuf()->open(s, mode)}. If that function returns a null pointer, calls @@ -12327,7 +12448,7 @@ \pnum \effects Move constructs the base class, and the contained \tcode{basic_filebuf}. -Then calls \tcode{basic_istream::set_rdbuf(\brk{}addressof(sb))} +Then calls \tcode{basic_istream::set_rdbuf(\brk{}addressof(\exposid{sb}))} to install the contained \tcode{basic_filebuf}. \end{itemdescr} @@ -12344,7 +12465,7 @@ Exchanges the state of \tcode{*this} and \tcode{rhs} by calling \tcode{basic_iostream::swap(rhs)} and -\tcode{sb.swap(rhs.sb)}. +\tcode{\exposid{sb}.swap(rhs.\exposid{sb})}. \end{itemdescr} \indexlibrarymember{swap}{basic_fstream}% @@ -12370,7 +12491,7 @@ \begin{itemdescr} \pnum \returns -\tcode{const_cast*>(addressof(sb))}. +\tcode{const_cast*>(addressof(\exposid{sb}))}. \end{itemdescr} \indexlibrarymember{native_handle}{basic_fstream}% @@ -12464,6 +12585,7 @@ #include // see \ref{ostream.syn} namespace std { + // \ref{syncstream.syncbuf}, class template \tcode{basic_syncbuf} template, class Allocator = allocator> class basic_syncbuf; @@ -12475,6 +12597,7 @@ using syncbuf = basic_syncbuf; using wsyncbuf = basic_syncbuf; + // \ref{syncstream.osyncstream}, class template \tcode{basic_osyncstream} template, class Allocator = allocator> class basic_osyncstream; @@ -12530,8 +12653,8 @@ int sync() override; private: - streambuf_type* wrapped; // \expos - bool emit_on_sync{}; // \expos + streambuf_type* @\exposid{wrapped}@; // \expos + bool @\exposid{emit-on-sync}@{}; // \expos }; } \end{codeblock} @@ -12541,7 +12664,7 @@ written to it, known as the associated output, into internal buffers allocated using the object's allocator. The associated output is transferred to the -wrapped stream buffer object \tcode{*wrapped} +wrapped stream buffer object \tcode{*\exposid{wrapped}} when \tcode{emit()} is called or when the \tcode{basic_syncbuf} object is destroyed. Such transfers are atomic with respect to transfers @@ -12558,7 +12681,7 @@ \begin{itemdescr} \pnum \effects -Sets \tcode{wrapped} to \tcode{obuf}. +Sets \exposid{wrapped} to \tcode{obuf}. \pnum \ensures @@ -12692,10 +12815,10 @@ \pnum \effects Atomically transfers the associated output of \tcode{*this} -to the stream buffer \tcode{*wrapped}, +to the stream buffer \tcode{*\exposid{wrapped}}, so that it appears in the output stream as a contiguous sequence of characters. -\tcode{wrapped->pubsync()} is called +\tcode{\exposid{wrapped}->pubsync()} is called if and only if a call was made to \tcode{sync()} since the most recent call to \tcode{emit()}, if any. @@ -12718,15 +12841,15 @@ \tcode{true} if all of the following conditions hold; otherwise \tcode{false}: \begin{itemize} -\item \tcode{wrapped == nullptr} is \tcode{false}. +\item \tcode{\exposid{wrapped} == nullptr} is \tcode{false}. \item All of the characters in the associated output were successfully transferred. -\item The call to \tcode{wrapped->pubsync()} (if any) succeeded. +\item The call to \tcode{\exposid{wrapped}->pubsync()} (if any) succeeded. \end{itemize} \pnum \remarks -May call member functions of \tcode{wrapped} -while holding a lock uniquely associated with \tcode{wrapped}. +May call member functions of \exposid{wrapped} +while holding a lock uniquely associated with \exposid{wrapped}. \end{itemdescr} \indexlibrarymember{get_wrapped}{basic_syncbuf}% @@ -12737,7 +12860,7 @@ \begin{itemdescr} \pnum \returns -\tcode{wrapped}. +\exposid{wrapped}. \end{itemdescr} \indexlibrarymember{get_allocator}{basic_syncbuf}% @@ -12759,7 +12882,7 @@ \begin{itemdescr} \pnum \effects -\tcode{emit_on_sync = b}. +\tcode{\exposid{emit-on-sync} = b}. \end{itemdescr} \rSec3[syncstream.syncbuf.virtuals]{Overridden virtual functions} @@ -12773,9 +12896,9 @@ \pnum \effects Records that the wrapped stream buffer is to be flushed. -Then, if \tcode{emit_on_sync} is \tcode{true}, calls \tcode{emit()}. +Then, if \exposid{emit-on-sync} is \tcode{true}, calls \tcode{emit()}. \begin{note} -If \tcode{emit_on_sync} is \tcode{false}, +If \exposid{emit-on-sync} is \tcode{false}, the actual flush is delayed until a call to \tcode{emit()}. \end{note} @@ -12837,10 +12960,10 @@ // \ref{syncstream.osyncstream.members}, member functions void emit(); streambuf_type* get_wrapped() const noexcept; - syncbuf_type* rdbuf() const noexcept { return const_cast(addressof(sb)); } + syncbuf_type* rdbuf() const noexcept { return const_cast(addressof(@\exposid{sb}@)); } private: - syncbuf_type sb; // \expos + syncbuf_type @\exposid{sb}@; // \expos }; } \end{codeblock} @@ -12882,8 +13005,8 @@ \begin{itemdescr} \pnum \effects -Initializes \tcode{sb} from \tcode{buf} and \tcode{allocator}. -Initializes the base class with \tcode{basic_ostream(addressof(sb))}. +Initializes \exposid{sb} from \tcode{buf} and \tcode{allocator}. +Initializes the base class with \tcode{basic_ostream(addressof(\exposid{sb}))}. \pnum \begin{note} @@ -12906,8 +13029,8 @@ \pnum \effects Move constructs the base class -and \tcode{sb} from the corresponding subobjects of \tcode{other}, -and calls \tcode{basic_ostream::set_rdbuf(addressof(sb))}. +and \exposid{sb} from the corresponding subobjects of \tcode{other}, +and calls \tcode{basic_ostream::set_rdbuf(addressof(\exposid{sb}))}. \pnum \ensures @@ -12928,7 +13051,7 @@ \pnum \effects Behaves as an unformatted output function\iref{ostream.unformatted}. -After constructing a \tcode{sentry} object, calls \tcode{sb.emit()}. +After constructing a \tcode{sentry} object, calls \tcode{\exposid{sb}.emit()}. If that call returns \tcode{false}, calls \tcode{setstate(ios_base::badbit)}. @@ -12973,7 +13096,7 @@ \begin{itemdescr} \pnum \returns -\tcode{sb.get_wrapped()}. +\tcode{\exposid{sb}.get_wrapped()}. \pnum \begin{example} @@ -13359,8 +13482,11 @@ path weakly_canonical(const path& p, error_code& ec); } -// \ref{fs.path.hash}, hash support namespace std { + // \ref{fs.path.fmtr}, formatting support + template struct formatter; + + // \ref{fs.path.hash}, hash support template struct hash; template<> struct hash; } @@ -13453,7 +13579,10 @@ \pnum \begin{note} -Class \tcode{path} is used to support the differences between the string types used by different operating systems to represent pathnames, and to perform conversions between encodings when necessary. +Class \tcode{path} is used to support the differences +between the string types used by different operating systems +to represent pathnames, +and to perform conversions between encodings when necessary. \end{note} \pnum @@ -13495,7 +13624,8 @@ a pathname to a particular file in a file hierarchy. There may be multiple pathnames that resolve to the same file. \begin{example} -POSIX specifies the mechanism in section 4.12, Pathname resolution. +For POSIX-based operating systems, +this mechanism is specified in POSIX, section 4.12, Pathname resolution. \end{example} \begin{codeblock} @@ -13583,7 +13713,8 @@ class Allocator = allocator> basic_string string(const Allocator& a = Allocator()) const; - std::string string() const; + std::string display_string() const; + std::string system_encoded_string() const; std::wstring wstring() const; std::u8string u8string() const; std::u16string u16string() const; @@ -13594,7 +13725,8 @@ class Allocator = allocator> basic_string generic_string(const Allocator& a = Allocator()) const; - std::string generic_string() const; + std::string generic_display_string() const; + std::string generic_system_encoded_string() const; std::wstring generic_wstring() const; std::u8string generic_u8string() const; std::u16string generic_u16string() const; @@ -13617,7 +13749,7 @@ path extension() const; // \ref{fs.path.query}, query - [[nodiscard]] bool empty() const noexcept; + bool empty() const noexcept; bool has_root_name() const; bool has_root_directory() const; bool has_root_path() const; @@ -13964,14 +14096,14 @@ \item \tcode{basic_string_view}. A function argument \tcode{const Source\&} \tcode{source} shall have an effective range \range{source.begin()}{source.end()}. -\item A type meeting the \oldconcept{InputIterator} requirements that iterates over a NTCTS\@. +\item A type meeting the \oldconcept{InputIterator} requirements that iterates over an NTCTS\@. The value type shall be an encoded character type. A function argument \tcode{const Source\&} \tcode{source} shall have an effective range \range{source}{end} where \tcode{end} is the first iterator value with an element value equal to \tcode{iterator_traits::value_type()}. \item A character array that after array-to-pointer decay results in a - pointer to the start of a NTCTS\@. The value type shall be an encoded character type. A + pointer to the start of an NTCTS\@. The value type shall be an encoded character type. A function argument \tcode{const Source\&} \tcode{source} shall have an effective range \range{source}{end} where \tcode{end} is the first iterator value with an element value equal to @@ -14547,10 +14679,8 @@ \indexlibrarymember{string}{path}% \begin{itemdecl} -template, - class Allocator = allocator> - basic_string - string(const Allocator& a = Allocator()) const; +template, class Allocator = allocator> + basic_string string(const Allocator& a = Allocator()) const; \end{itemdecl} \begin{itemdescr} @@ -14565,13 +14695,13 @@ \ref{fs.path.cvt}. \end{itemdescr} -\indexlibrarymember{string}{path}% +\indexlibrarymember{system_encoded_string}{path}% \indexlibrarymember{wstring}{path}% \indexlibrarymember{u8string}{path}% \indexlibrarymember{u16string}{path}% \indexlibrarymember{u32string}{path}% \begin{itemdecl} -std::string string() const; +std::string system_encoded_string() const; std::wstring wstring() const; std::u8string u8string() const; std::u16string u16string() const; @@ -14589,6 +14719,20 @@ by \ref{fs.path.cvt}. \end{itemdescr} +\indexlibrarymember{display_string}{path}% +\begin{itemdecl} +std::string display_string() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{format("\{\}", *this)}. +\begin{note} +The returned string is suitable for use with formatting\iref{format.functions} +and print functions\iref{print.fun}. +\end{note} +\end{itemdescr} \rSec4[fs.path.generic.obs]{Generic format observers} @@ -14610,10 +14754,8 @@ \indexlibrarymember{generic_string}{path}% \begin{itemdecl} -template, - class Allocator = allocator> - basic_string - generic_string(const Allocator& a = Allocator()) const; +template, class Allocator = allocator> + basic_string generic_string(const Allocator& a = Allocator()) const; \end{itemdecl} \begin{itemdescr} @@ -14628,13 +14770,13 @@ \ref{fs.path.cvt}. \end{itemdescr} -\indexlibrarymember{generic_string}{path}% +\indexlibrarymember{generic_system_encoded_string}{path}% \indexlibrarymember{generic_wstring}{path}% \indexlibrarymember{generic_u8string}{path}% \indexlibrarymember{generic_u16string}{path}% \indexlibrarymember{generic_u32string}{path}% \begin{itemdecl} -std::string generic_string() const; +std::string generic_system_encoded_string() const; std::wstring generic_wstring() const; std::u8string generic_u8string() const; std::u16string generic_u16string() const; @@ -14651,6 +14793,21 @@ Conversion, if any, is specified by~\ref{fs.path.cvt}. \end{itemdescr} +\indexlibrarymember{generic_display_string}{path}% +\begin{itemdecl} +std::string generic_display_string() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{format("\{:g\}", *this)}. +\begin{note} +The returned string is suitable for use with formatting\iref{format.functions} +and print functions\iref{print.fun}. +\end{note} +\end{itemdescr} + \rSec4[fs.path.compare]{Compare} \indexlibrarymember{compare}{path}% @@ -14863,7 +15020,7 @@ \indexlibrarymember{empty}{path}% \begin{itemdecl} -[[nodiscard]] bool empty() const noexcept; +bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -15315,6 +15472,102 @@ Equivalent to: \tcode{return path(lhs) /= rhs;} \end{itemdescr} +\rSec3[fs.path.fmtr]{Formatting support} + +\rSec4[fs.path.fmtr.general]{Formatting support overview} + +\indexlibraryglobal{formatter}% +\begin{codeblock} +namespace std { + template struct formatter { + constexpr void set_debug_format(); + + constexpr typename basic_format_parse_context::iterator + parse(basic_format_parse_context& ctx); + + template + typename FormatContext::iterator + format(const filesystem::path& path, FormatContext& ctx) const; + }; +} +\end{codeblock} + +\rSec4[fs.path.fmtr.funcs]{Formatting support functions} + +\pnum +Formatting of paths uses formatting specifiers of the form +\begin{ncbnf} +\nontermdef{path-format-spec}\br + \opt{fill-and-align} \opt{width} \opt{\terminal{?}} \opt{\terminal{g}} +\end{ncbnf} +where the productions \fmtgrammarterm{fill-and-align} and \fmtgrammarterm{width} +are described in \ref{format.string}. +If the \tcode{?} option is used then +the path is formatted as an escaped string\iref{format.string.escaped}. + +\indexlibrarymember{formatter}{set_debug_format}% +\begin{itemdecl} +constexpr void set_debug_format(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Modifies the state of the \tcode{formatter} to be as if +the \fmtgrammarterm{path-format-spec} parsed by the last call to \tcode{parse} +contained the \tcode{?} option. +\end{itemdescr} + +\indexlibrarymember{formatter}{basic_format_parse_context}% +\begin{itemdecl} +constexpr typename basic_format_parse_context::iterator + parse(basic_format_parse_context& ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Parses the format specifier as a \fmtgrammarterm{path-format-spec} and +stores the parsed specifiers in \tcode{*this}. + +\pnum +\returns +An iterator past the end of the \fmtgrammarterm{path-format-spec}. +\end{itemdescr} + +\indexlibrarymember{formatter}{format}% +\begin{itemdecl} +template + typename FormatContext::iterator + format(const filesystem::path& p, FormatContext& ctx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \tcode{s} be \tcode{p.generic_string()} +if the \tcode{g} option is used, +otherwise \tcode{p.native()}. +Writes \tcode{s} into \tcode{ctx.out()}, +adjusted according to the \fmtgrammarterm{path-format-spec}. +If \tcode{charT} is \keyword{char}, +\tcode{path::value_type} is \keyword{wchar_t}, and +the literal encoding is UTF-8, +then the escaped path is transcoded from the native encoding for +wide character strings to UTF-8 with +maximal subparts of ill-formed subsequences +substituted with \ucode{fffd} \uname{replacement character} +per the Unicode Standard, Chapter 3.9 \ucode{fffd} Substitution in Conversion. +If \tcode{charT} and \tcode{path::value_type} are the same +then no transcoding is performed. +Otherwise, transcoding is +\impldef{transcoding of a formatted path when \tcode{charT} and \tcode{path::value_type} differ}. + +\pnum +\returns +An iterator past the end of the output range. +\end{itemdescr} + \rSec3[fs.path.hash]{Hash support} \begin{itemdecl} @@ -15490,10 +15743,10 @@ \lhdr{Constant} & \rhdr{Meaning} \\ \capsep -\tcode{none} & +\tcode{\libmember{none}{file_type}} & The type of the file has not been determined or an error occurred while trying to determine the type. \\ \rowsep -\tcode{not_found} & +\tcode{\libmember{not_found}{file_type}} & Pseudo-type indicating the file was not found. \begin{tailnote} The file @@ -15501,13 +15754,13 @@ type of a file. \end{tailnote} \\ \rowsep -\tcode{regular} & Regular file \\ \rowsep -\tcode{directory} & Directory file \\ \rowsep -\tcode{symlink} & Symbolic link file \\ \rowsep -\tcode{block} & Block special file \\ \rowsep -\tcode{character} & Character special file \\ \rowsep -\tcode{fifo} & FIFO or pipe file \\ \rowsep -\tcode{socket} & Socket file \\ \rowsep +\tcode{\libmember{regular}{file_type}} & Regular file \\ \rowsep +\tcode{\libmember{directory}{file_type}} & Directory file \\ \rowsep +\tcode{\libmember{symlink}{file_type}} & Symbolic link file \\ \rowsep +\tcode{\libmember{block}{file_type}} & Block special file \\ \rowsep +\tcode{\libmember{character}{file_type}} & Character special file \\ \rowsep +\tcode{\libmember{fifo}{file_type}} & FIFO or pipe file \\ \rowsep +\tcode{\libmember{socket}{file_type}} & Socket file \\ \rowsep \tcode{\textit{\impldef{additional \tcode{file_type} enumerators for file systems supporting additional types of file}}} & Implementations that support file systems having file types @@ -15517,7 +15770,7 @@ for file systems supporting additional types of file} \tcode{file_type} constants to separately identify each of those additional file types \\ \rowsep -\tcode{unknown} & +\tcode{\libmember{unknown}{file_type}} & The file exists but the type cannot be determined \\ \end{floattable} @@ -15539,42 +15792,42 @@ \topline \ohdrx{2}{Option group controlling \tcode{copy_file} function effects for existing target files} \\ \rowsep \lhdr{Constant} & \rhdr{Meaning} \\ \capsep -\tcode{none} & +\tcode{\libmember{none}{copy_options}} & (Default) Error; file already exists. \\ \rowsep -\tcode{skip_existing} & +\tcode{\libmember{skip_existing}{copy_options}} & Do not overwrite existing file, do not report an error. \\ \rowsep -\tcode{overwrite_existing} & +\tcode{\libmember{overwrite_existing}{copy_options}} & Overwrite the existing file. \\ \rowsep -\tcode{update_existing} & +\tcode{\libmember{update_existing}{copy_options}} & Overwrite the existing file if it is older than the replacement file. \\ \capsep \ohdrx{2}{Option group controlling \tcode{copy} function effects for subdirectories} \\ \rowsep \lhdr{Constant} & \rhdr{Meaning} \\ \capsep -\tcode{none} & +\tcode{\libmember{none}{copy_options}} & (Default) Do not copy subdirectories. \\ \rowsep -\tcode{recursive} & +\tcode{\libmember{recursive}{copy_options}} & Recursively copy subdirectories and their contents. \\ \capsep \ohdrx{2}{Option group controlling \tcode{copy} function effects for symbolic links} \\ \rowsep \lhdr{Constant} & \rhdr{Meaning} \\ \capsep -\tcode{none} & +\tcode{\libmember{none}{copy_options}} & (Default) Follow symbolic links. \\ \rowsep -\tcode{copy_symlinks} & +\tcode{\libmember{copy_symlinks}{copy_options}} & Copy symbolic links as symbolic links rather than copying the files that they point to. \\ \rowsep -\tcode{skip_symlinks} & +\tcode{\libmember{skip_symlinks}{copy_options}} & Ignore symbolic links. \\ \capsep \ohdrx{2}{Option group controlling \tcode{copy} function effects for choosing the form of copying} \\ \rowsep \lhdr{Constant} & \rhdr{Meaning} \\ \capsep -\tcode{none} & +\tcode{\libmember{none}{copy_options}} & (Default) Copy content. \\ \rowsep -\tcode{directories_only} & +\tcode{\libmember{directories_only}{copy_options}} & Copy directory structure only, do not copy non-directory files. \\ \rowsep -\tcode{create_symlinks} & +\tcode{\libmember{create_symlinks}{copy_options}} & Make symbolic links instead of copies of files. The source path shall be an absolute path unless the destination path is in the current directory. \\ \rowsep -\tcode{create_hard_links} & +\tcode{\libmember{create_hard_links}{copy_options}} & Make hard links instead of copies of files. \\ \end{floattable} @@ -15593,46 +15846,46 @@ \lhdr{Name} & \chdr{Value} & \chdr{POSIX} & \rhdr{Definition or notes} \\ & \chdr{(octal)} & \chdr{macro} & \\ \capsep -\tcode{none} & \tcode{0} & & +\tcode{\libmember{none}{perms}} & \tcode{0} & & There are no permissions set for the file. \\ \rowsep -\tcode{owner_read} & \tcode{0400} & \tcode{S_IRUSR} & +\tcode{\libmember{owner_read}{perms}} & \tcode{0400} & \tcode{S_IRUSR} & Read permission, owner \\ \rowsep -\tcode{owner_write} & \tcode{0200} & \tcode{S_IWUSR} & +\tcode{\libmember{owner_write}{perms}} & \tcode{0200} & \tcode{S_IWUSR} & Write permission, owner \\ \rowsep -\tcode{owner_exec} & \tcode{0100} & \tcode{S_IXUSR} & +\tcode{\libmember{owner_exec}{perms}} & \tcode{0100} & \tcode{S_IXUSR} & Execute/search permission, owner \\ \rowsep -\tcode{owner_all} & \tcode{0700} & \tcode{S_IRWXU} & +\tcode{\libmember{owner_all}{perms}} & \tcode{0700} & \tcode{S_IRWXU} & Read, write, execute/search by owner;\br \tcode{owner_read | owner_write | owner_exec} \\ \rowsep -\tcode{group_read} & \tcode{040} & \tcode{S_IRGRP} & +\tcode{\libmember{group_read}{perms}} & \tcode{040} & \tcode{S_IRGRP} & Read permission, group \\ \rowsep -\tcode{group_write} & \tcode{020} & \tcode{S_IWGRP} & +\tcode{\libmember{group_write}{perms}} & \tcode{020} & \tcode{S_IWGRP} & Write permission, group \\ \rowsep -\tcode{group_exec} & \tcode{010} & \tcode{S_IXGRP} & +\tcode{\libmember{group_exec}{perms}} & \tcode{010} & \tcode{S_IXGRP} & Execute/search permission, group \\ \rowsep -\tcode{group_all} & \tcode{070} & \tcode{S_IRWXG} & +\tcode{\libmember{group_all}{perms}} & \tcode{070} & \tcode{S_IRWXG} & Read, write, execute/search by group;\br \tcode{group_read | group_write | group_exec} \\ \rowsep -\tcode{others_read} & \tcode{04} & \tcode{S_IROTH} & +\tcode{\libmember{others_read}{perms}} & \tcode{04} & \tcode{S_IROTH} & Read permission, others \\ \rowsep -\tcode{others_write} & \tcode{02} & \tcode{S_IWOTH} & +\tcode{\libmember{others_write}{perms}} & \tcode{02} & \tcode{S_IWOTH} & Write permission, others \\ \rowsep -\tcode{others_exec} & \tcode{01} & \tcode{S_IXOTH} & +\tcode{\libmember{others_exec}{perms}} & \tcode{01} & \tcode{S_IXOTH} & Execute/search permission, others \\ \rowsep -\tcode{others_all} & \tcode{07} & \tcode{S_IRWXO} & +\tcode{\libmember{others_all}{perms}} & \tcode{07} & \tcode{S_IRWXO} & Read, write, execute/search by others;\br \tcode{others_read | others_write | others_exec} \\ \rowsep -\tcode{all} & \tcode{0777} & & +\tcode{\libmember{all}{perms}} & \tcode{0777} & & \tcode{owner_all | group_all | others_all} \\ \rowsep -\tcode{set_uid} & \tcode{04000} & \tcode{S_ISUID} & +\tcode{\libmember{set_uid}{perms}} & \tcode{04000} & \tcode{S_ISUID} & Set-user-ID on execution \\ \rowsep -\tcode{set_gid} & \tcode{02000} & \tcode{S_ISGID} & +\tcode{\libmember{set_gid}{perms}} & \tcode{02000} & \tcode{S_ISGID} & Set-group-ID on execution \\ \rowsep -\tcode{sticky_bit} & \tcode{01000} & \tcode{S_ISVTX} & +\tcode{\libmember{sticky_bit}{perms}} & \tcode{01000} & \tcode{S_ISVTX} & Operating system dependent. \\ \rowsep -\tcode{mask} & \tcode{07777} & & +\tcode{\libmember{mask}{perms}} & \tcode{07777} & & \tcode{all | set_uid | set_gid | sticky_bit} \\ \rowsep -\tcode{unknown} & \tcode{0xFFFF} & & +\tcode{\libmember{unknown}{perms}} & \tcode{0xFFFF} & & The permissions are not known, such as when a \tcode{file_status} object is created without specifying the permissions \\ \end{floattable} @@ -15654,15 +15907,15 @@ \topline \lhdr{Name} & \rhdr{Meaning} \\ \capsep -\tcode{replace} & +\tcode{\libmember{replace}{perm_options}} & \tcode{permissions} shall replace the file's permission bits with \tcode{perm} \\ \rowsep -\tcode{add} & +\tcode{\libmember{add}{perm_options}} & \tcode{permissions} shall replace the file's permission bits with the bitwise \logop{or} of \tcode{perm} and the file's current permission bits. \\ \rowsep -\tcode{remove} & +\tcode{\libmember{remove}{perm_options}} & \tcode{permissions} shall replace the file's permission bits with the bitwise \logop{and} of the complement of \tcode{perm} and the file's current permission bits. \\ \rowsep -\tcode{nofollow} & +\tcode{\libmember{nofollow}{perm_options}} & \tcode{permissions} shall change the permissions of a symbolic link itself rather than the permissions of the file the link resolves to. \\ \end{floattable} @@ -15685,11 +15938,11 @@ \lhdr{Name} & \rhdr{Meaning} \\ \capsep -\tcode{none} & +\tcode{\libmember{none}{directory_options}} & (Default) Skip directory symlinks, permission denied is an error. \\ \rowsep -\tcode{follow_directory_symlink} & +\tcode{\libmember{follow_directory_symlink}{directory_options}} & Follow rather than skip directory symlinks. \\ \rowsep -\tcode{skip_permission_denied} & +\tcode{\libmember{skip_permission_denied}{directory_options}} & Skip directories that would otherwise result in permission denied. \\ \end{floattable} @@ -15864,8 +16117,7 @@ operator<<(basic_ostream& os, const directory_entry& d); private: - filesystem::path pathobject; // \expos - friend class directory_iterator; // \expos + filesystem::path @\exposid{path-object}@; // \expos }; } \end{codeblock} @@ -15884,13 +16136,10 @@ \pnum \begin{note} -For purposes of exposition, -class \tcode{directory_iterator}\iref{fs.class.directory.iterator} -is shown above as a friend of class \tcode{directory_entry}. -Friendship allows the \tcode{directory_iterator} implementation to cache +\tcode{directory_iterator} can cache already available attribute values directly into a \tcode{directory_entry} object -without the cost of an unneeded call to \tcode{refresh()}. +without the cost of a call to \tcode{refresh()}. \end{note} \pnum @@ -15959,7 +16208,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to \tcode{pathobject = p}, +Equivalent to \tcode{\exposid{path-object} = p}, then \tcode{refresh()} or \tcode{refresh(ec)}, respectively. If an error occurs, the values of any cached attributes are unspecified. @@ -15977,7 +16226,7 @@ \begin{itemdescr} \pnum \effects -Equivalent to \tcode{pathobject.replace_filename(p)}, +Equivalent to \tcode{\exposid{path-object}.replace_filename(p)}, then \tcode{refresh()} or \tcode{refresh(ec)}, respectively. If an error occurs, the values of any cached attributes are unspecified. @@ -16028,7 +16277,7 @@ \begin{itemdescr} \pnum \returns -\tcode{pathobject}. +\exposid{path-object}. \end{itemdescr} \indexlibrarymember{exists}{directory_entry}% @@ -16268,7 +16517,7 @@ \begin{itemdescr} \pnum \returns -\tcode{pathobject == rhs.pathobject}. +\tcode{\exposid{path-object} == rhs.\exposid{path-object}}. \end{itemdescr} \indexlibrarymember{operator<=>}{directory_entry}% @@ -16279,7 +16528,7 @@ \begin{itemdescr} \pnum \returns -\tcode{pathobject <=> rhs.pathobject}. +\tcode{\exposid{path-object} <=> rhs.\exposid{path-object}}. \end{itemdescr} \rSec3[fs.dir.entry.io]{Inserter} @@ -16389,8 +16638,6 @@ any \tcode{directory_entry} \tcode{refresh} function. \begin{note} The exact mechanism for storing cached attribute values is not exposed to users. -For exposition, class \tcode{directory_iterator} is shown in \ref{fs.class.directory.entry} -as a friend of class \tcode{directory_entry}. \end{note} \pnum @@ -16880,7 +17127,7 @@ \pnum \begin{note} -\tcode{disable_recursion_pending}\tcode{()} is used to prevent +\tcode{disable_recursion_pending()} is used to prevent unwanted recursion into a directory. \end{note} \end{itemdescr} @@ -17040,7 +17287,7 @@ \begin{itemdecl} void filesystem::copy(const path& from, const path& to, copy_options options); void filesystem::copy(const path& from, const path& to, copy_options options, - error_code& ec); + error_code& ec); \end{itemdecl} \begin{itemdescr} @@ -17075,7 +17322,7 @@ \impldef{effect of \tcode{filesystem::copy}}. \item -Otherwise, an error is reported as specified in~\ref{fs.err.report} if: +Otherwise, an error is reported as specified in~\ref{fs.err.report} if \begin{itemize} \item \tcode{exists(f)} is \tcode{false}, or \item \tcode{equivalent(from, to)} is \tcode{true}, or @@ -17158,16 +17405,16 @@ \pnum \begin{example} Given this directory structure: -\begin{codeblock} +\begin{outputblock} /dir1 file1 file2 dir2 file3 -\end{codeblock} +\end{outputblock} Calling \tcode{copy("/dir1", "/dir3")} would result in: -\begin{codeblock} +\begin{outputblock} /dir1 file1 file2 @@ -17176,10 +17423,10 @@ /dir3 file1 file2 -\end{codeblock} +\end{outputblock} Alternatively, calling \tcode{copy("/dir1", "/dir3", copy_options::recursive)} would result in: -\begin{codeblock} +\begin{outputblock} /dir1 file1 file2 @@ -17190,7 +17437,7 @@ file2 dir2 file3 -\end{codeblock} +\end{outputblock} \end{example} \end{itemdescr} @@ -17218,7 +17465,7 @@ \begin{itemdecl} bool filesystem::copy_file(const path& from, const path& to, copy_options options); bool filesystem::copy_file(const path& from, const path& to, copy_options options, - error_code& ec); + error_code& ec); \end{itemdecl} \begin{itemdescr} @@ -17233,7 +17480,7 @@ As follows: \begin{itemize} \item -Report an error as specified in~\ref{fs.err.report} if: +Report an error as specified in~\ref{fs.err.report} if \begin{itemize} \item \tcode{is_regular_file(from)} is \tcode{false}, or \item \tcode{exists(to)} is \tcode{true} and \tcode{is_regular_file(to)} is \tcode{false}, or @@ -17248,7 +17495,7 @@ \item Otherwise, copy the contents and attributes of the file \tcode{from} - resolves to, to the file \tcode{to} resolves to, if: + resolves to, to the file \tcode{to} resolves to, if \begin{itemize} \item \tcode{exists(to)} is \tcode{false}, or \item \tcode{(options \& copy_options::overwrite_existing) != copy_options::none}, or @@ -17281,7 +17528,7 @@ \begin{itemdecl} void filesystem::copy_symlink(const path& existing_symlink, const path& new_symlink); void filesystem::copy_symlink(const path& existing_symlink, const path& new_symlink, - error_code& ec) noexcept; + error_code& ec) noexcept; \end{itemdecl} \begin{itemdescr} @@ -17310,7 +17557,7 @@ \begin{itemdescr} \pnum \effects -Calls \tcode{create_directory()} for each element of \tcode{p} +Calls \tcode{create_directory} for each element of \tcode{p} that does not exist. \pnum @@ -17397,13 +17644,13 @@ \begin{itemdecl} void filesystem::create_directory_symlink(const path& to, const path& new_symlink); void filesystem::create_directory_symlink(const path& to, const path& new_symlink, - error_code& ec) noexcept; + error_code& ec) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Establishes the postcondition, as if by POSIX \tcode{symlink()}. +Establishes the postcondition, as if by POSIX \tcode{symlink}. \pnum \ensures @@ -17418,7 +17665,7 @@ \begin{note} Some operating systems require symlink creation to identify that the link is to a directory. -Thus, \tcode{create_symlink()} (instead of \tcode{create_directory_symlink()}) +Thus, \tcode{create_symlink} (instead of \tcode{create_directory_symlink}) cannot be used reliably to create directory symlinks. \end{note} @@ -17444,7 +17691,7 @@ \begin{itemdescr} \pnum \effects -Establishes the postcondition, as if by POSIX \tcode{link()}. +Establishes the postcondition, as if by POSIX \tcode{link}. \pnum \ensures @@ -17479,7 +17726,7 @@ \begin{itemdescr} \pnum \effects -Establishes the postcondition, as if by POSIX \tcode{symlink()}. +Establishes the postcondition, as if by POSIX \tcode{symlink}. \pnum \ensures @@ -17512,7 +17759,7 @@ \returns The absolute path of the current working directory, whose pathname in the native format is - obtained as if by POSIX \tcode{getcwd()}. + obtained as if by POSIX \tcode{getcwd}. The signature with argument \tcode{ec} returns \tcode{path()} if an error occurs. @@ -17526,12 +17773,6 @@ with the process, that is used as the starting location in pathname resolution for relative paths. -\pnum -\begin{note} -The \tcode{current_path()} name was chosen to emphasize that the returned value is a - path, not just a single directory name. -\end{note} - \pnum \begin{note} The current path as returned by many operating systems is a dangerous @@ -17549,7 +17790,7 @@ \begin{itemdescr} \pnum \effects -Establishes the postcondition, as if by POSIX \tcode{chdir()}. +Establishes the postcondition, as if by POSIX \tcode{chdir}. \pnum \ensures @@ -17582,7 +17823,7 @@ \begin{note} On POSIX platforms, this is determined as if by the values of the POSIX \tcode{stat} class, - obtained as if by \tcode{stat()} for the two paths, having equal \tcode{st_dev} values + obtained as if by \tcode{stat} for the two paths, having equal \tcode{st_dev} values and equal \tcode{st_ino} values. \end{note} @@ -17660,7 +17901,7 @@ \item If \tcode{is_regular_file(p)}, the size in bytes of the file \tcode{p} resolves to, determined as if by the value of the POSIX \tcode{stat} - class member \tcode{st_size} obtained as if by POSIX \tcode{stat()}. + class member \tcode{st_size} obtained as if by POSIX \tcode{stat}. \item Otherwise, the result is \impldef{result of \tcode{filesystem::file_size}}. \end{itemize} @@ -18022,7 +18263,7 @@ \returns The time of last data modification of \tcode{p}, determined as if by the value of the POSIX \tcode{stat} class member \tcode{st_mtime} - obtained as if by POSIX \tcode{stat()}. + obtained as if by POSIX \tcode{stat}. The signature with argument \tcode{ec} returns \tcode{file_time_type::min()} if an error occurs. @@ -18042,7 +18283,7 @@ \pnum \effects Sets the time of last data modification of the file - resolved to by \tcode{p} to \tcode{new_time}, as if by POSIX \tcode{futimens()}. + resolved to by \tcode{p} to \tcode{new_time}, as if by POSIX \tcode{futimens}. \pnum \throws @@ -18076,7 +18317,7 @@ to the file \tcode{p} resolves to, or to file \tcode{p} itself if \tcode{p} is a symbolic link and \tcode{perm_options::nofollow} is set in \tcode{opts}. -The action is applied as if by POSIX \tcode{fchmodat()}. +The action is applied as if by POSIX \tcode{fchmodat}. \pnum \begin{note} @@ -18213,7 +18454,7 @@ \pnum \effects If \tcode{exists(symlink_status(p, ec))}, the file \tcode{p} is - removed as if by POSIX \tcode{remove()}. + removed as if by POSIX \tcode{remove}. \begin{note} A symbolic link is itself removed, rather than the file it resolves to. @@ -18225,9 +18466,10 @@ \pnum \returns -\tcode{false} if \tcode{p} did not exist, - otherwise \tcode{true}. The signature with argument \tcode{ec} - returns \tcode{false} if an error occurs. +\tcode{true} if a file \tcode{p} has been removed and \tcode{false} otherwise. +\begin{note} +Absence of a file \tcode{p} is not an error. +\end{note} \pnum \throws @@ -18247,7 +18489,7 @@ \pnum \effects Recursively deletes the contents of \tcode{p} if it exists, - then deletes file \tcode{p} itself, as if by POSIX \tcode{remove()}. + then deletes file \tcode{p} itself, as if by POSIX \tcode{remove}. \begin{note} A symbolic link is itself removed, rather than the file it resolves to. @@ -18281,7 +18523,7 @@ \pnum \effects Renames \tcode{old_p} to \tcode{new_p}, as if by - POSIX \tcode{rename()}. + POSIX \tcode{rename}. \begin{note} \begin{itemize} @@ -18317,7 +18559,7 @@ \pnum \effects Causes the size that would be returned by \tcode{file_size(p)} to be -equal to \tcode{new_size}, as if by POSIX \tcode{truncate()}. +equal to \tcode{new_size}, as if by POSIX \tcode{truncate}. \pnum \throws @@ -18372,7 +18614,7 @@ \begin{itemdescr} \pnum \effects -As if: +As if by: \begin{codeblock} error_code ec; file_status result = status(p, ec); @@ -18404,14 +18646,14 @@ \pnum \effects If possible, determines the attributes - of the file \tcode{p} resolves to, as if by using POSIX \tcode{stat()} + of the file \tcode{p} resolves to, as if by using POSIX \tcode{stat} to obtain a POSIX \tcode{struct stat}. If, during attribute determination, the underlying file system API reports an error, sets \tcode{ec} to indicate the specific error reported. Otherwise, \tcode{ec.clear()}. \begin{note} This allows users to inspect the specifics of underlying - API errors even when the value returned by \tcode{status()} is not + API errors even when the value returned by \tcode{status} is not \tcode{file_status(file_type::none)}. \end{note} @@ -18505,9 +18747,9 @@ \begin{itemdescr} \pnum \effects -Same as \tcode{status()}, above, +Same as \tcode{status}, above, except that the attributes - of \tcode{p} are determined as if by using POSIX \tcode{lstat()} + of \tcode{p} are determined as if by using POSIX \tcode{lstat} to obtain a POSIX \tcode{struct stat}. \pnum @@ -18517,7 +18759,7 @@ \pnum \returns -Same as \tcode{status()}, above, except +Same as \tcode{status}, above, except that if the attributes indicate a symbolic link, as if by POSIX \tcode{S_ISLNK}, returns \tcode{file_status(file_type::symlink, prms)}. The signature with argument \tcode{ec} returns @@ -18586,14 +18828,14 @@ Using \tcode{status(p)} or \tcode{status(p, ec)}, respectively, to determine existence, return a path composed by \tcode{operator/=} - from the result of calling \tcode{canonical()} + from the result of calling \tcode{canonical} with a path argument composed of the leading elements of \tcode{p} that exist, if any, followed by the elements of \tcode{p} that do not exist, if any. For the first form, - \tcode{canonical()} is called without an \tcode{error_code} argument. + \tcode{canonical} is called without an \tcode{error_code} argument. For the second form, - \tcode{canonical()} is called + \tcode{canonical} is called with \tcode{ec} as an \tcode{error_code} argument, and \tcode{path()} is returned at the first error occurrence, if any. @@ -18619,22 +18861,6 @@ \indexlibraryglobal{size_t}% \indexlibraryglobal{FILE}% \indexlibraryglobal{fpos_t}% -\indexlibraryglobal{NULL}% -\indexlibraryglobal{_IOFBF}% -\indexlibraryglobal{_IOLBF}% -\indexlibraryglobal{_IONBF}% -\indexlibraryglobal{BUFSIZ}% -\indexlibraryglobal{EOF}% -\indexlibraryglobal{FOPEN_MAX}% -\indexlibraryglobal{FILENAME_MAX}% -\indexlibraryglobal{L_tmpnam}% -\indexlibraryglobal{SEEK_CUR}% -\indexlibraryglobal{SEEK_END}% -\indexlibraryglobal{SEEK_SET}% -\indexlibraryglobal{TMP_MAX}% -\indexlibraryglobal{stderr}% -\indexlibraryglobal{stdin}% -\indexlibraryglobal{stdout}% \indexlibraryglobal{remove}% \indexlibraryglobal{rename}% \indexlibraryglobal{tmpfile}% @@ -18681,28 +18907,31 @@ \indexlibraryglobal{ferror}% \indexlibraryglobal{perror}% \begin{codeblock} +#define __STDC_VERSION_STDIO_H__ 202311L + namespace std { using size_t = @\textit{see \ref{support.types.layout}}@; using FILE = @\seebelow@; using fpos_t = @\seebelow@; } -#define NULL @\textit{see \ref{support.types.nullptr}}@ -#define _IOFBF @\seebelow@ -#define _IOLBF @\seebelow@ -#define _IONBF @\seebelow@ -#define BUFSIZ @\seebelow@ -#define EOF @\seebelow@ -#define FOPEN_MAX @\seebelow@ -#define FILENAME_MAX @\seebelow@ -#define L_tmpnam @\seebelow@ -#define SEEK_CUR @\seebelow@ -#define SEEK_END @\seebelow@ -#define SEEK_SET @\seebelow@ -#define TMP_MAX @\seebelow@ -#define stderr @\seebelow@ -#define stdin @\seebelow@ -#define stdout @\seebelow@ +#define @\libmacro{NULL}@ @\textit{see \ref{support.types.nullptr}}@ +#define @\libmacro{_IOFBF}@ @\seebelow@ +#define @\libmacro{_IOLBF}@ @\seebelow@ +#define @\libmacro{_IONBF}@ @\seebelow@ +#define @\libmacro{BUFSIZ}@ @\seebelow@ +#define @\libmacro{EOF}@ @\seebelow@ +#define @\libmacro{FOPEN_MAX}@ @\seebelow@ +#define @\libmacro{FILENAME_MAX}@ @\seebelow@ +#define @\libmacro{_PRINTF_NAN_LEN_MAX}@ @\seebelow@ +#define @\libmacro{L_tmpnam}@ @\seebelow@ +#define @\libmacro{SEEK_CUR}@ @\seebelow@ +#define @\libmacro{SEEK_END}@ @\seebelow@ +#define @\libmacro{SEEK_SET}@ @\seebelow@ +#define @\libmacro{TMP_MAX}@ @\seebelow@ +#define @\libmacro{stderr}@ @\seebelow@ +#define @\libmacro{stdin}@ @\seebelow@ +#define @\libmacro{stdout}@ @\seebelow@ namespace std { int remove(const char* filename); @@ -18757,12 +18986,19 @@ The contents and meaning of the header \libheader{cstdio} are the same as the C standard library header \libheader{stdio.h}. +\pnum +The return from each function call +that delivers data +to the host environment +to be written to a file (\xrefc{7.21.3}) +is an observable checkpoint\iref{intro.abstract}. + \pnum Calls to the function \tcode{tmpnam} with an argument that is a null pointer value may introduce a data race\iref{res.on.data.races} with other calls to \tcode{tmpnam} with an argument that is a null pointer value. -\xrefc{7.21} +\xrefc{7.23} \rSec2[cinttypes.syn]{Header \tcode{} synopsis} @@ -18782,55 +19018,42 @@ \indexlibraryglobal{PRIuN}% \indexlibraryglobal{PRIxN}% \indexlibraryglobal{PRIXN}% +\indexlibraryglobal{PRIbN}% +\indexlibraryglobal{PRIBN}% \indexlibraryglobal{SCNdN}% \indexlibraryglobal{SCNiN}% \indexlibraryglobal{SCNoN}% \indexlibraryglobal{SCNuN}% \indexlibraryglobal{SCNxN}% +\indexlibraryglobal{SCNbN}% \indexlibraryglobal{PRIdLEASTN}% \indexlibraryglobal{PRIiLEASTN}% \indexlibraryglobal{PRIoLEASTN}% \indexlibraryglobal{PRIuLEASTN}% \indexlibraryglobal{PRIxLEASTN}% \indexlibraryglobal{PRIXLEASTN}% +\indexlibraryglobal{PRIbLEASTN}% +\indexlibraryglobal{PRIBLEASTN}% \indexlibraryglobal{SCNdLEASTN}% \indexlibraryglobal{SCNiLEASTN}% \indexlibraryglobal{SCNoLEASTN}% \indexlibraryglobal{SCNuLEASTN}% \indexlibraryglobal{SCNxLEASTN}% +\indexlibraryglobal{SCNbLEASTN}% \indexlibraryglobal{PRIdFASTN}% \indexlibraryglobal{PRIiFASTN}% \indexlibraryglobal{PRIoFASTN}% \indexlibraryglobal{PRIuFASTN}% \indexlibraryglobal{PRIxFASTN}% \indexlibraryglobal{PRIXFASTN}% +\indexlibraryglobal{PRIbFASTN}% +\indexlibraryglobal{PRIBFASTN}% \indexlibraryglobal{SCNdFASTN}% \indexlibraryglobal{SCNiFASTN}% \indexlibraryglobal{SCNoFASTN}% \indexlibraryglobal{SCNuFASTN}% \indexlibraryglobal{SCNxFASTN}% -\indexlibraryglobal{PRIdMAX}% -\indexlibraryglobal{PRIiMAX}% -\indexlibraryglobal{PRIoMAX}% -\indexlibraryglobal{PRIuMAX}% -\indexlibraryglobal{PRIxMAX}% -\indexlibraryglobal{PRIXMAX}% -\indexlibraryglobal{SCNdMAX}% -\indexlibraryglobal{SCNiMAX}% -\indexlibraryglobal{SCNoMAX}% -\indexlibraryglobal{SCNuMAX}% -\indexlibraryglobal{SCNxMAX}% -\indexlibraryglobal{PRIdPTR}% -\indexlibraryglobal{PRIiPTR}% -\indexlibraryglobal{PRIoPTR}% -\indexlibraryglobal{PRIuPTR}% -\indexlibraryglobal{PRIxPTR}% -\indexlibraryglobal{PRIXPTR}% -\indexlibraryglobal{SCNdPTR}% -\indexlibraryglobal{SCNiPTR}% -\indexlibraryglobal{SCNoPTR}% -\indexlibraryglobal{SCNuPTR}% -\indexlibraryglobal{SCNxPTR}% +\indexlibraryglobal{SCNbFASTN}% \begin{codeblock} #include // see \ref{cstdint.syn} @@ -18848,61 +19071,78 @@ constexpr imaxdiv_t div(intmax_t, intmax_t); // optional, see below } +#define __STDC_VERSION_INTTYPES_H__ 202311L + #define PRId@\placeholdernc{N}@ @\seebelow@ #define PRIi@\placeholdernc{N}@ @\seebelow@ #define PRIo@\placeholdernc{N}@ @\seebelow@ #define PRIu@\placeholdernc{N}@ @\seebelow@ #define PRIx@\placeholdernc{N}@ @\seebelow@ #define PRIX@\placeholdernc{N}@ @\seebelow@ +#define PRIb@\placeholdernc{N}@ @\seebelow@ +#define PRIB@\placeholdernc{N}@ @\seebelow@ #define SCNd@\placeholdernc{N}@ @\seebelow@ #define SCNi@\placeholdernc{N}@ @\seebelow@ #define SCNo@\placeholdernc{N}@ @\seebelow@ #define SCNu@\placeholdernc{N}@ @\seebelow@ #define SCNx@\placeholdernc{N}@ @\seebelow@ +#define SCNb@\placeholdernc{N}@ @\seebelow@ #define PRIdLEAST@\placeholdernc{N}@ @\seebelow@ #define PRIiLEAST@\placeholdernc{N}@ @\seebelow@ #define PRIoLEAST@\placeholdernc{N}@ @\seebelow@ #define PRIuLEAST@\placeholdernc{N}@ @\seebelow@ #define PRIxLEAST@\placeholdernc{N}@ @\seebelow@ #define PRIXLEAST@\placeholdernc{N}@ @\seebelow@ +#define PRIbLEAST@\placeholdernc{N}@ @\seebelow@ +#define PRIBLEAST@\placeholdernc{N}@ @\seebelow@ #define SCNdLEAST@\placeholdernc{N}@ @\seebelow@ #define SCNiLEAST@\placeholdernc{N}@ @\seebelow@ #define SCNoLEAST@\placeholdernc{N}@ @\seebelow@ #define SCNuLEAST@\placeholdernc{N}@ @\seebelow@ #define SCNxLEAST@\placeholdernc{N}@ @\seebelow@ +#define SCNbLEAST@\placeholdernc{N}@ @\seebelow@ #define PRIdFAST@\placeholdernc{N}@ @\seebelow@ #define PRIiFAST@\placeholdernc{N}@ @\seebelow@ #define PRIoFAST@\placeholdernc{N}@ @\seebelow@ #define PRIuFAST@\placeholdernc{N}@ @\seebelow@ #define PRIxFAST@\placeholdernc{N}@ @\seebelow@ #define PRIXFAST@\placeholdernc{N}@ @\seebelow@ +#define PRIbFAST@\placeholdernc{N}@ @\seebelow@ +#define PRIBFAST@\placeholdernc{N}@ @\seebelow@ #define SCNdFAST@\placeholdernc{N}@ @\seebelow@ #define SCNiFAST@\placeholdernc{N}@ @\seebelow@ #define SCNoFAST@\placeholdernc{N}@ @\seebelow@ #define SCNuFAST@\placeholdernc{N}@ @\seebelow@ #define SCNxFAST@\placeholdernc{N}@ @\seebelow@ -#define PRIdMAX @\seebelow@ -#define PRIiMAX @\seebelow@ -#define PRIoMAX @\seebelow@ -#define PRIuMAX @\seebelow@ -#define PRIxMAX @\seebelow@ -#define PRIXMAX @\seebelow@ -#define SCNdMAX @\seebelow@ -#define SCNiMAX @\seebelow@ -#define SCNoMAX @\seebelow@ -#define SCNuMAX @\seebelow@ -#define SCNxMAX @\seebelow@ -#define PRIdPTR @\seebelow@ -#define PRIiPTR @\seebelow@ -#define PRIoPTR @\seebelow@ -#define PRIuPTR @\seebelow@ -#define PRIxPTR @\seebelow@ -#define PRIXPTR @\seebelow@ -#define SCNdPTR @\seebelow@ -#define SCNiPTR @\seebelow@ -#define SCNoPTR @\seebelow@ -#define SCNuPTR @\seebelow@ -#define SCNxPTR @\seebelow@ +#define SCNbFAST@\placeholdernc{N}@ @\seebelow@ +#define @\libmacro{PRIdMAX}@ @\seebelow@ +#define @\libmacro{PRIiMAX}@ @\seebelow@ +#define @\libmacro{PRIoMAX}@ @\seebelow@ +#define @\libmacro{PRIuMAX}@ @\seebelow@ +#define @\libmacro{PRIxMAX}@ @\seebelow@ +#define @\libmacro{PRIXMAX}@ @\seebelow@ +#define @\libmacro{PRIbMAX}@ @\seebelow@ +#define @\libmacro{PRIBMAX}@ @\seebelow@ +#define @\libmacro{SCNdMAX}@ @\seebelow@ +#define @\libmacro{SCNiMAX}@ @\seebelow@ +#define @\libmacro{SCNoMAX}@ @\seebelow@ +#define @\libmacro{SCNuMAX}@ @\seebelow@ +#define @\libmacro{SCNxMAX}@ @\seebelow@ +#define @\libmacro{SCNbMAX}@ @\seebelow@ +#define @\libmacro{PRIdPTR}@ @\seebelow@ +#define @\libmacro{PRIiPTR}@ @\seebelow@ +#define @\libmacro{PRIoPTR}@ @\seebelow@ +#define @\libmacro{PRIuPTR}@ @\seebelow@ +#define @\libmacro{PRIxPTR}@ @\seebelow@ +#define @\libmacro{PRIXPTR}@ @\seebelow@ +#define @\libmacro{PRIbPTR}@ @\seebelow@ +#define @\libmacro{PRIBPTR}@ @\seebelow@ +#define @\libmacro{SCNdPTR}@ @\seebelow@ +#define @\libmacro{SCNiPTR}@ @\seebelow@ +#define @\libmacro{SCNoPTR}@ @\seebelow@ +#define @\libmacro{SCNuPTR}@ @\seebelow@ +#define @\libmacro{SCNxPTR}@ @\seebelow@ +#define @\libmacro{SCNbPTR}@ @\seebelow@ \end{codeblock} \pnum @@ -18914,10 +19154,6 @@ The header \libheader{cinttypes} includes the header \libheaderref{cstdint} instead of \libheader{stdint.h}, and \item -\tcode{intmax_t} and \tcode{uintmax_t} are not required -to be able to represent all values of extended integer types -wider than \tcode{long long} and \tcode{unsigned long long}, respectively, and -\item if and only if the type \tcode{intmax_t} designates an extended integer type\iref{basic.fundamental}, the following function signatures are added: \begin{codeblock} @@ -18939,3 +19175,6 @@ is defined if and only if the implementation defines the corresponding \grammarterm{typedef-name} in~\ref{cstdint.syn} and has a suitable \tcode{fscanf} length modifier for the type. +Each of the \tcode{PRIB} macros listed in this subclause +is defined if and only if \tcode{fprintf} supports +the \tcode{B} conversion specifier. diff --git a/source/iterators.tex b/source/iterators.tex index d4a1bfaebb..e0116c79d8 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -84,6 +84,7 @@ template concept indirectly_readable = @\seebelow@; // freestanding + // \ref{indirectcallable.traits}, indirect callable traits template<@\libconcept{indirectly_readable}@ T> using @\exposidnc{indirect-value-t}@ = @\seebelow@; // \expos @@ -168,10 +169,11 @@ // \ref{projected}, projected template<@\libconcept{indirectly_readable}@ I, @\libconcept{indirectly_regular_unary_invocable}@ Proj> - struct projected; // freestanding + using projected = @\seebelow@; // freestanding - template<@\libconcept{weakly_incrementable}@ I, class Proj> - struct incrementable_traits>; // freestanding + template<@\libconcept{indirectly_readable}@ I, @\libconcept{indirectly_regular_unary_invocable}@ Proj> + using projected_value_t = // freestanding + remove_cvref_t&>>; // \ref{alg.req}, common algorithm requirements // \ref{alg.req.ind.move}, concept \libconcept{indirectly_movable} @@ -202,7 +204,7 @@ // \ref{alg.req.mergeable}, concept \libconcept{mergeable} template + class R = ranges::less, class P1 = identity, class P2 = identity> concept mergeable = @\seebelow@; // freestanding // \ref{alg.req.sortable}, concept \libconcept{sortable} @@ -319,7 +321,7 @@ constexpr reverse_iterator make_reverse_iterator(Iterator i); // freestanding template - requires (!@\libconcept{sized_sentinel_for}@) + requires (!@\libconcept{sized_sentinel_for}@) constexpr bool @\libspec{disable_sized_sentinel_for}{reverse_iterator}@, // freestanding reverse_iterator> = true; @@ -409,7 +411,7 @@ constexpr move_iterator make_move_iterator(Iterator i); // freestanding template - requires (!@\libconcept{sized_sentinel_for}@) + requires (!@\libconcept{sized_sentinel_for}@) constexpr bool @\libspec{disable_sized_sentinel_for}{move_iterator}@, // freestanding move_iterator> = true; @@ -450,7 +452,7 @@ const istream_iterator& y); template> - class ostream_iterator; + class ostream_iterator; template> class istreambuf_iterator; @@ -498,11 +500,11 @@ template constexpr ptrdiff_t ssize(const T (&array)[N]) noexcept; // freestanding - template [[nodiscard]] constexpr auto + template constexpr auto empty(const C& c) -> decltype(c.empty()); // freestanding - template [[nodiscard]] constexpr bool + template constexpr bool empty(const T (&array)[N]) noexcept; // freestanding - template [[nodiscard]] constexpr bool + template constexpr bool empty(initializer_list il) noexcept; // freestanding template constexpr auto data(C& c) -> decltype(c.data()); // freestanding @@ -514,7 +516,7 @@ \rSec1[iterator.requirements]{Iterator requirements} -\rSec2[iterator.requirements.general]{In general} +\rSec2[iterator.requirements.general]{General} \pnum \indextext{requirements!iterator}% @@ -533,7 +535,7 @@ \defn{value type} of the iterator. An output iterator \tcode{i} has a non-empty set of types that are -\libconcept{indirectly_writable} to the iterator; +\defn{writable} to the iterator; for each such type \tcode{T}, the expression \tcode{*i = o} is valid where \tcode{o} is a value of type \tcode{T}. For every iterator type @@ -687,6 +689,24 @@ The result of the application of library functions to invalid ranges is undefined. +\pnum +For an iterator \tcode{i} of a type that +models \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}, +library functions are permitted +to replace \range{i}{s} with +\range{to_address(i)}{to_address(i + ranges::distance(i, s))}, and +to replace \countedrange{i}{n} with \range{to_address(i)}{to_address(i + n)}. +\begin{note} +This means a program cannot rely on any side effects of +dereferencing a contiguous iterator \tcode{i}, +because library functions might operate on +pointers obtained by \tcode{to_address(i)} +instead of operating on \tcode{i}. +Similarly, a program cannot rely on any side effects of +individual increments on a contiguous iterator \tcode{i}, +because library functions might advance \tcode{i} only once. +\end{note} + \pnum All the categories of iterators require only those functions that are realizable for a given category in constant time (amortized). @@ -709,12 +729,12 @@ \pnum \indextext{iterator!constexpr}% -Iterators are called \defn{constexpr iterators} +Iterators meet the \defn{constexpr iterator} requirements if all operations provided to meet iterator category requirements are constexpr functions. \begin{note} For example, the types ``pointer to \tcode{int}'' and -\tcode{reverse_iterator} are constexpr iterators. +\tcode{reverse_iterator} meet the constexpr iterator requirements. \end{note} \rSec2[iterator.assoc.types]{Associated types} @@ -1111,12 +1131,10 @@ \begin{codeblock} template void reverse(BI first, BI last) { - typename iterator_traits::difference_type n = - distance(first, last); + typename iterator_traits::difference_type n = distance(first, last); --n; - while(n > 0) { - typename iterator_traits::value_type - tmp = *first; + while (n > 0) { + typename iterator_traits::value_type tmp = *first; *first++ = *--last; *last = tmp; n -= 2; @@ -1333,7 +1351,7 @@ \pnum Let \tcode{E} be an expression such that \tcode{decltype((E))} is \tcode{T}, and let \tcode{o} be a dereferenceable object of type \tcode{Out}. -\tcode{Out} and \tcode{T} model \tcode{\libconcept{indirectly_writable}} only if +\tcode{Out} and \tcode{T} model \tcode{\libconcept{indirectly_writable}} only if: \begin{itemize} \item If \tcode{Out} and \tcode{T} model \tcode{\libconcept{indirectly_readable} \&\& \libconcept{same_as}, decay_t>}, @@ -1539,7 +1557,7 @@ \pnum Let \tcode{i} be an object of type \tcode{I}. When \tcode{i} is in the domain of both pre- and post-increment, \tcode{i} is said to be \defn{incrementable}. -\tcode{I} models \tcode{\libconcept{weakly_incrementable}} only if +\tcode{I} models \tcode{\libconcept{weakly_incrementable}} only if: \begin{itemize} \item The expressions \tcode{++i} and \tcode{i++} have the same domain. \item If \tcode{i} is incrementable, then both \tcode{++i} @@ -1586,7 +1604,7 @@ \pnum Let \tcode{a} and \tcode{b} be incrementable objects of type \tcode{I}. -\tcode{I} models \libconcept{incrementable} only if +\tcode{I} models \libconcept{incrementable} only if: \begin{itemize} \item If \tcode{bool(a == b)} then \tcode{bool(a++ == b)}. \item If \tcode{bool(a == b)} then \tcode{bool(((void)a++, a) == ++b)}. @@ -1649,7 +1667,7 @@ \pnum Let \tcode{s} and \tcode{i} be values of type \tcode{S} and \tcode{I} such that \range{i}{s} denotes a range. Types -\tcode{S} and \tcode{I} model \tcode{\libconcept{sentinel_for}} only if +\tcode{S} and \tcode{I} model \tcode{\libconcept{sentinel_for}} only if: \begin{itemize} \item \tcode{i == s} is well-defined. @@ -1694,7 +1712,7 @@ a sentinel of type \tcode{S} such that \range{i}{s} denotes a range. Let $N$ be the smallest number of applications of \tcode{++i} necessary to make \tcode{bool(i == s)} be \tcode{true}. -\tcode{S} and \tcode{I} model \tcode{\libconcept{sized_sentinel_for}} only if +\tcode{S} and \tcode{I} model \tcode{\libconcept{sized_sentinel_for}} only if: \begin{itemize} \item If $N$ is representable by \tcode{iter_difference_t}, then \tcode{s - i} is well-defined and equals $N$. @@ -1824,7 +1842,7 @@ \pnum Two dereferenceable iterators \tcode{a} and \tcode{b} of type \tcode{X} -offer the \defn{multi-pass guarantee} if: +offer the \defn{multi-pass guarantee} if \begin{itemize} \item \tcode{a == b} implies \tcode{++a == ++b} and \item the expression @@ -1913,7 +1931,7 @@ after \tcode{n} applications of \tcode{++a}, let \tcode{D} be \tcode{iter_difference_t}, and let \tcode{n} denote a value of type \tcode{D}. -\tcode{I} models \libconcept{random_access_iterator} only if +\tcode{I} models \libconcept{random_access_iterator} only if: \begin{itemize} \item \tcode{(a += n)} is equal to \tcode{b}. \item \tcode{addressof(a += n)} is equal to \tcode{addressof(a)}. @@ -1963,6 +1981,7 @@ \item \tcode{to_address(a) == addressof(*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{to_address(I\{\})} is well-defined, \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, @@ -2016,7 +2035,7 @@ bidirectional.iterators,random.access.iterators}. \pnum -A type \tcode{X} meets the \defnoldconcept{Iterator} requirements if: +A type \tcode{X} meets the \defnoldconcept{Iterator} requirements if \begin{itemize} \item \tcode{X} meets the \oldconcept{CopyConstructible}, \oldconcept{CopyAssignable}, \oldconcept{Swappable}, and \oldconcept{Destructible} requirements\iref{utility.arg.requirements,swappable.requirements}, and @@ -2241,7 +2260,7 @@ \pnum Two dereferenceable iterators \tcode{a} and \tcode{b} of type \tcode{X} offer the -\defn{multi-pass guarantee} if: +\defn{multi-pass guarantee} if \begin{itemize} \item \tcode{a == b} implies \tcode{++a == ++b} and \item \tcode{X} is a pointer type or the expression @@ -2444,7 +2463,6 @@ @\libconcept{copy_constructible}@ && @\libconcept{invocable}@> && @\libconcept{invocable}@> && - @\libconcept{invocable}@> && @\libconcept{common_reference_with}@< invoke_result_t>, invoke_result_t>>; @@ -2455,7 +2473,6 @@ @\libconcept{copy_constructible}@ && @\libconcept{regular_invocable}@> && @\libconcept{regular_invocable}@> && - @\libconcept{regular_invocable}@> && @\libconcept{common_reference_with}@< invoke_result_t>, invoke_result_t>>; @@ -2465,8 +2482,7 @@ @\libconcept{indirectly_readable}@ && @\libconcept{copy_constructible}@ && @\libconcept{predicate}@> && - @\libconcept{predicate}@> && - @\libconcept{predicate}@>; + @\libconcept{predicate}@>; template concept @\deflibconcept{indirect_binary_predicate}@ = @@ -2475,8 +2491,7 @@ @\libconcept{predicate}@, @\exposidnc{indirect-value-t}@> && @\libconcept{predicate}@, iter_reference_t> && @\libconcept{predicate}@, @\exposidnc{indirect-value-t}@> && - @\libconcept{predicate}@, iter_reference_t> && - @\libconcept{predicate}@, iter_common_reference_t>; + @\libconcept{predicate}@, iter_reference_t>; template concept @\deflibconcept{indirect_equivalence_relation}@ = @@ -2485,8 +2500,7 @@ @\libconcept{equivalence_relation}@, @\exposidnc{indirect-value-t}@> && @\libconcept{equivalence_relation}@, iter_reference_t> && @\libconcept{equivalence_relation}@, @\exposidnc{indirect-value-t}@> && - @\libconcept{equivalence_relation}@, iter_reference_t> && - @\libconcept{equivalence_relation}@, iter_common_reference_t>; + @\libconcept{equivalence_relation}@, iter_reference_t>; template concept @\deflibconcept{indirect_strict_weak_order}@ = @@ -2495,15 +2509,14 @@ @\libconcept{strict_weak_order}@, @\exposidnc{indirect-value-t}@> && @\libconcept{strict_weak_order}@, iter_reference_t> && @\libconcept{strict_weak_order}@, @\exposidnc{indirect-value-t}@> && - @\libconcept{strict_weak_order}@, iter_reference_t> && - @\libconcept{strict_weak_order}@, iter_common_reference_t>; + @\libconcept{strict_weak_order}@, iter_reference_t>; } \end{codeblock} -\rSec3[projected]{Class template \tcode{projected}} +\rSec3[projected]{Alias template \tcode{projected}} \pnum -Class template \tcode{projected} is used to constrain algorithms +Alias template \tcode{projected} is used to constrain algorithms that accept callable objects and projections\iref{defns.projection}. It combines an \libconcept{indirectly_readable} type \tcode{I} and a callable object type \tcode{Proj} into a new \libconcept{indirectly_readable} type @@ -2932,32 +2945,8 @@ \end{example} \pnum -The function templates defined in \ref{range.iter.ops} are not found by -argument-dependent name lookup\iref{basic.lookup.argdep}. When found by -unqualified\iref{basic.lookup.unqual} name lookup for the -\grammarterm{postfix-expression} in a function call\iref{expr.call}, they -inhibit argument-dependent name lookup. - -\begin{example} -\begin{codeblock} -void foo() { - using namespace std::ranges; - std::vector vec{1,2,3}; - distance(begin(vec), end(vec)); // \#1 -} -\end{codeblock} -The function call expression at \tcode{\#1} invokes \tcode{std::ranges::distance}, -not \tcode{std::distance}, despite that -(a) the iterator type returned from \tcode{begin(vec)} and \tcode{end(vec)} -may be associated with namespace \tcode{std} and -(b) \tcode{std::distance} is more specialized\iref{temp.func.order} than -\tcode{std::ranges::distance} since the former requires its first two parameters -to have the same type. -\end{example} - -\pnum -The number and order of deducible template parameters for the function templates defined -in \ref{range.iter.ops} is unspecified, except where explicitly stated otherwise. +The entities defined in \ref{range.iter.ops} are +algorithm function objects\iref{alg.func.obj}. \rSec3[range.iter.op.advance]{\tcode{ranges::advance}} @@ -3077,7 +3066,13 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return last - static_cast\&>(first);} +Equivalent to: +\begin{codeblock} +if constexpr (!is_array_v>) + return last - first; +else + return last - static_cast>(first); +\end{codeblock} \end{itemdescr} \indexlibraryglobal{distance}% @@ -3318,9 +3313,6 @@ \effects Value-initializes \tcode{current}. -Iterator operations applied to the resulting iterator have defined behavior -if and only if the corresponding operations are defined on a value-initialized iterator of type -\tcode{Iterator}. \end{itemdescr} \indexlibraryctor{reverse_iterator}% @@ -3436,7 +3428,7 @@ \begin{itemdescr} \pnum \returns -\tcode{current[-n-1]}. +\tcode{current[-n - 1]}. \end{itemdescr} \rSec3[reverse.iter.nav]{Navigation} @@ -3449,7 +3441,7 @@ \begin{itemdescr} \pnum \returns -\tcode{reverse_iterator(current-n)}. +\tcode{reverse_iterator(current - n)}. \end{itemdescr} \indexlibrarymember{operator-}{reverse_iterator}% @@ -3460,7 +3452,7 @@ \begin{itemdescr} \pnum \returns -\tcode{reverse_iterator(current+n)}. +\tcode{reverse_iterator(current + n)}. \end{itemdescr} \indexlibrarymember{operator++}{reverse_iterator}% @@ -3837,6 +3829,8 @@ \rSec3[back.insert.iterator]{Class template \tcode{back_insert_iterator}} +\rSec4[back.insert.iter.general]{General} + \indexlibraryglobal{back_insert_iterator}% \begin{codeblock} namespace std { @@ -3948,6 +3942,8 @@ \rSec3[front.insert.iterator]{Class template \tcode{front_insert_iterator}} +\rSec4[front.insert.iter.general]{General} + \indexlibraryglobal{front_insert_iterator}% \begin{codeblock} namespace std { @@ -4059,6 +4055,8 @@ \rSec3[insert.iterator]{Class template \tcode{insert_iterator}} +\rSec4[insert.iter.general]{General} + \indexlibraryglobal{insert_iterator}% \begin{codeblock} namespace std { @@ -4259,7 +4257,7 @@ template<@\libconcept{convertible_to}@ U> constexpr basic_const_iterator(basic_const_iterator current); template<@\exposconcept{different-from}@ T> - requires @\libconcept{convertible_to}@ + requires @\libconcept{convertible_to}@ constexpr basic_const_iterator(T&& current); constexpr const Iterator& base() const & noexcept; @@ -4267,8 +4265,8 @@ constexpr @\exposid{reference}@ operator*() const; constexpr const auto* operator->() const - requires is_lvalue_reference_v> && - @\libconcept{same_as}@>, value_type>; + requires is_lvalue_reference_v> && + @\libconcept{same_as}@>, value_type>; constexpr basic_const_iterator& operator++(); constexpr void operator++(int); @@ -5296,7 +5294,7 @@ \indexlibraryglobal{make_move_iterator}% \begin{itemdecl} template -constexpr move_iterator make_move_iterator(Iterator i); + constexpr move_iterator make_move_iterator(Iterator i); \end{itemdecl} \begin{itemdescr} @@ -5580,7 +5578,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{x.v_.valueless_by_exception()} is \tcode{false}. \pnum @@ -5600,7 +5598,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{x.v_.valueless_by_exception()} is \tcode{false}. \pnum @@ -5630,7 +5628,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{holds_alternative(v_)} is \tcode{true}. \pnum @@ -5655,7 +5653,7 @@ \end{codeblock} \pnum -\expects +\hardexpects \tcode{holds_alternative(v_)} is \tcode{true}. \pnum @@ -5700,7 +5698,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{holds_alternative(v_)} is \tcode{true}. \pnum @@ -5719,7 +5717,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{holds_alternative(v_)} is \tcode{true}. \pnum @@ -5774,7 +5772,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{x.v_.valueless_by_exception()} and \tcode{y.v_.valueless_by_exception()} are each \tcode{false}. @@ -5795,7 +5793,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{x.v_.valueless_by_exception()} and \tcode{y.v_.valueless_by_exception()} are each \tcode{false}. @@ -5816,7 +5814,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{x.v_.valueless_by_exception()} and \tcode{y.v_.valueless_by_exception()} are each \tcode{false}. @@ -5838,7 +5836,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{holds_alternative(i.v_)} is \tcode{true}. \pnum @@ -5855,7 +5853,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{holds_alternative(x.v_)} and \tcode{holds_alternative(y.v_)} are each \tcode{true}. @@ -5971,9 +5969,9 @@ friend constexpr iter_difference_t operator-( const counted_iterator& x, const counted_iterator& y); friend constexpr iter_difference_t operator-( - const counted_iterator& x, default_sentinel_t); + const counted_iterator& x, default_sentinel_t) noexcept; friend constexpr iter_difference_t operator-( - default_sentinel_t, const counted_iterator& y); + default_sentinel_t, const counted_iterator& y) noexcept; constexpr counted_iterator& operator-=(iter_difference_t n) requires @\libconcept{random_access_iterator}@; @@ -5984,7 +5982,7 @@ friend constexpr bool operator==( const counted_iterator& x, const counted_iterator& y); friend constexpr bool operator==( - const counted_iterator& x, default_sentinel_t); + const counted_iterator& x, default_sentinel_t) noexcept; template<@\libconcept{common_with}@ I2> friend constexpr strong_ordering operator<=>( @@ -6020,8 +6018,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{n >= 0}. +\hardexpects +\tcode{n >= 0} is \tcode{true}. \pnum \effects @@ -6107,7 +6105,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{length > 0} is \tcode{true}. \pnum @@ -6135,8 +6133,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{n < length}. +\hardexpects +\tcode{n < length} is \tcode{true}. \pnum \effects @@ -6152,8 +6150,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{length > 0}. +\hardexpects +\tcode{length > 0} is \tcode{true}. \pnum \effects @@ -6172,8 +6170,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{length > 0}. +\hardexpects +\tcode{length > 0} is \tcode{true}. \pnum \effects @@ -6269,8 +6267,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{n <= length}. +\hardexpects +\tcode{n <= length} is \tcode{true}. \pnum \effects @@ -6315,7 +6313,7 @@ \indexlibrarymember{operator-}{counted_iterator}% \begin{itemdecl} friend constexpr iter_difference_t operator-( - const counted_iterator& x, default_sentinel_t); + const counted_iterator& x, default_sentinel_t) noexcept; \end{itemdecl} \begin{itemdescr} @@ -6328,7 +6326,7 @@ \indexlibrarymember{operator-}{counted_iterator}% \begin{itemdecl} friend constexpr iter_difference_t operator-( - default_sentinel_t, const counted_iterator& y); + default_sentinel_t, const counted_iterator& y) noexcept; \end{itemdecl} \begin{itemdescr} @@ -6345,8 +6343,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{-n <= length}. +\hardexpects +\tcode{-n <= length} is \tcode{true}. \pnum \effects @@ -6381,7 +6379,7 @@ \indexlibrarymember{operator==}{counted_iterator}% \begin{itemdecl} friend constexpr bool operator==( - const counted_iterator& x, default_sentinel_t); + const counted_iterator& x, default_sentinel_t) noexcept; \end{itemdecl} \begin{itemdescr} @@ -6426,7 +6424,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects \tcode{i.length > 0} is \tcode{true}. \pnum @@ -6444,7 +6442,7 @@ \begin{itemdescr} \pnum -\expects +\hardexpects Both \tcode{x.length > 0} and \tcode{y.length > 0} are \tcode{true}. \pnum @@ -7249,6 +7247,8 @@ \libheaderrefx{flat_map}{flat.map.syn}, \libheaderrefx{flat_set}{flat.set.syn}, \libheaderrefx{forward_list}{forward.list.syn}, +\libheaderref{hive}, +\libheaderrefx{inplace_vector}{inplace.vector.syn}, \libheaderref{list}, \libheaderrefx{map}{associative.map.syn}, \libheaderrefx{regex}{re.syn}, @@ -7456,7 +7456,7 @@ \indexlibrary{\idxcode{empty(C\& c)}}% \begin{itemdecl} -template [[nodiscard]] constexpr auto empty(const C& c) -> decltype(c.empty()); +template constexpr auto empty(const C& c) -> decltype(c.empty()); \end{itemdecl} \begin{itemdescr} \pnum @@ -7466,7 +7466,7 @@ \indexlibrary{\idxcode{empty(T (\&array)[N])}}% \begin{itemdecl} -template [[nodiscard]] constexpr bool empty(const T (&array)[N]) noexcept; +template constexpr bool empty(const T (&array)[N]) noexcept; \end{itemdecl} \begin{itemdescr} \pnum @@ -7476,7 +7476,7 @@ \indexlibrary{\idxcode{empty(initializer_list)}}% \begin{itemdecl} -template [[nodiscard]] constexpr bool empty(initializer_list il) noexcept; +template constexpr bool empty(initializer_list il) noexcept; \end{itemdecl} \begin{itemdescr} \pnum diff --git a/source/layout.tex b/source/layout.tex index b74849dd00..98564d8bd0 100644 --- a/source/layout.tex +++ b/source/layout.tex @@ -10,7 +10,7 @@ %%-------------------------------------------------- %% set header and footer positions and sizes -\setheadfoot{\onelineskip}{2\onelineskip} +\setheadfoot{3\onelineskip}{4\onelineskip} \setheaderspaces{*}{2\onelineskip}{*} %%-------------------------------------------------- diff --git a/source/lex.tex b/source/lex.tex index cd23d40013..3f27aed6af 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -32,23 +32,15 @@ A source file together with all the headers\iref{headers} and source files included\iref{cpp.include} via the preprocessing directive \tcode{\#include}, less any source lines skipped by any of the -conditional inclusion\iref{cpp.cond} preprocessing directives, is +conditional inclusion\iref{cpp.cond} preprocessing directives, +as modified by the implementation-defined behavior of any +conditionally-supported-directives\iref{cpp.pre} and pragmas\iref{cpp.pragma}, +if any, is called a \defnadj{preprocessing}{translation unit}. \begin{note} A \Cpp{} program need not all be translated at the same time. -\end{note} - -\pnum -\begin{note} -Previously translated translation units and instantiation -units can be preserved individually or in libraries. The separate -translation units of a program communicate\iref{basic.link} by (for -example) -calls to functions whose identifiers have external or module linkage, -manipulation of objects whose identifiers have external or module linkage, or -manipulation of data files. Translation units can be separately -translated and then later linked to produce an executable -program\iref{basic.link}. +Translation units can be separately translated and then later linked +to produce an executable program\iref{basic.link}. \end{note} \indextext{compilation!separate|)} @@ -80,8 +72,14 @@ \end{note} If an input file is determined to be a UTF-8 file, then it shall be a well-formed UTF-8 code unit sequence and -it is decoded to produce a sequence of Unicode scalar values. -A sequence of translation character set elements is then formed +it is decoded to produce a sequence of Unicode +\begin{footnote} +Unicode\textregistered\ is a registered trademark of Unicode, Inc. +This information is given for the convenience of users of this document and +does not constitute an endorsement by ISO or IEC of this product. +\end{footnote} +scalar values. +A sequence of translation character set elements\iref{lex.charset} is then formed by mapping each Unicode scalar value to the corresponding translation character set element. In the resulting sequence, @@ -93,8 +91,8 @@ For any other kind of input file supported by the implementation, characters are mapped, in an -\impldef{mapping physical source file characters to translation character set} manner, -to a sequence of translation character set elements\iref{lex.charset}, +\impldef{mapping input file characters to translation character set} manner, +to a sequence of translation character set elements, representing end-of-line indicators as new-line characters. \item @@ -105,7 +103,7 @@ immediately followed by zero or more whitespace characters other than new-line followed by a new-line character is deleted, splicing -physical source lines to form logical source lines. Only the last +physical source lines to form \defnx{logical source lines}{source line!logical}. Only the last backslash on any physical source line shall be eligible for being part of such a splice. \begin{note} @@ -131,9 +129,9 @@ would arise from a source file ending with an unclosed \tcode{/*} comment. \end{footnote} -Each comment is replaced by one space character. New-line characters are +Each comment\iref{lex.comment} is replaced by one \unicode{0020}{space} character. New-line characters are retained. Whether each nonempty sequence of whitespace characters other -than new-line is retained or replaced by one space character is +than new-line is retained or replaced by one \unicode{0020}{space} character is unspecified. As characters from the source file are consumed to form the next preprocessing token @@ -144,37 +142,40 @@ \grammarterm{r-char-sequence}, \grammarterm{h-char-sequence}, or \grammarterm{q-char-sequence}, -\grammarterm{universal-character-name}s are recognized and -replaced by the designated element of the translation character set. +\grammarterm{universal-character-name}s are recognized\iref{lex.universal.char} and +replaced by the designated element of the translation character set\iref{lex.charset}. The process of dividing a source file's characters into preprocessing tokens is context-dependent. \begin{example} See the handling of \tcode{<} within a \tcode{\#include} preprocessing -directive\iref{cpp.include}. +directive\iref{lex.header,cpp.include}. \end{example} -\item Preprocessing directives are executed, macro invocations are -expanded, and \tcode{_Pragma} unary operator expressions are executed. -A \tcode{\#include} preprocessing directive causes the named header or +\item The source file is analyzed as a \grammarterm{preprocessing-file}\iref{cpp.pre}. +Preprocessing directives\iref{cpp} are executed, macro invocations are +expanded\iref{cpp.replace}, and \tcode{_Pragma} unary operator expressions are executed\iref{cpp.pragma.op}. +A \tcode{\#include} preprocessing directive\iref{cpp.include} causes the named header or source file to be processed from phase 1 through phase 4, recursively. All preprocessing directives are then deleted. \item -For a sequence of two or more adjacent \grammarterm{string-literal} tokens, +For a sequence of two or more adjacent \grammarterm{string-literal} preprocessing tokens, a common \grammarterm{encoding-prefix} is determined as specified in \ref{lex.string}. -Each such \grammarterm{string-literal} token is then considered to have +Each such \grammarterm{string-literal} preprocessing token is then considered to have that common \grammarterm{encoding-prefix}. \item -Adjacent \grammarterm{string-literal} tokens are concatenated\iref{lex.string}. +\indextext{concatenation!string}% +Adjacent \grammarterm{string-literal} preprocessing tokens are concatenated\iref{lex.string}. -\item Whitespace characters separating tokens are no longer -significant. Each preprocessing token is converted into a -token\iref{lex.token}. The resulting tokens -constitute a \defn{translation unit} and +\item +Each preprocessing token is converted into a token\iref{lex.token}. +Whitespace characters separating tokens are no longer significant. +The resulting tokens constitute a \defn{translation unit} and are syntactically and -semantically analyzed and translated. +semantically analyzed as a \grammarterm{translation-unit}\iref{basic.link} and +translated. \begin{note} The process of analyzing and translating the tokens can occasionally result in one token being replaced by a sequence of other @@ -197,42 +198,92 @@ entities and any external representation. The description is conceptual only, and does not specify any particular implementation. \end{note} - -\item Translated translation units and instantiation units are combined -as follows: \begin{note} -Some or all of these can be supplied from a -library. +Previously translated translation units can be preserved individually or in libraries. +The separate translation units of a program communicate\iref{basic.link} by (for example) +calls to functions whose names have external or module linkage, +manipulation of variables whose names have external or module linkage, or +manipulation of data files. \end{note} -Each translated translation unit is examined to -produce a list of required instantiations. + +While the tokens constituting translation units +are being analyzed and translated, +required instantiations are performed. \begin{note} This can include instantiations which have been explicitly requested\iref{temp.explicit}. \end{note} -The definitions of the -required templates are located. It is \impldef{whether source of translation units must -be available to locate template definitions} whether the -source of the translation units containing these definitions is required -to be available. -\begin{note} -An implementation can choose to encode sufficient -information into the translated translation unit so as to ensure the -source is not required here. -\end{note} -All the required instantiations -are performed to produce -\defn{instantiation units}. + +The contexts from which instantiations may be performed +are determined by their respective points of instantiation\iref{temp.point}. + \begin{note} -These are similar -to translated translation units, but contain no references to -uninstantiated templates and no template definitions. +Other requirements in this document can further constrain +the context from which an instantiation can be performed. +For example, a constexpr function template specialization +might have a point of instantiation at the end of a translation unit, +but its use in certain constant expressions could require +that it be instantiated at an earlier point\iref{temp.inst}. \end{note} -The -program is ill-formed if any instantiation fails. -\item All external entity references are resolved. Library +Each instantiation results in new program constructs. +The program is ill-formed if any instantiation fails. + +During the analysis and translation of tokens, +certain expressions are evaluated\iref{expr.const}. +Constructs appearing at a program point $P$ are analyzed +in a context where each side effect of evaluating an expression $E$ +as a full-expression is complete if and only if +\begin{itemize} +\item +$E$ is the expression corresponding to +a \grammarterm{consteval-block-declaration}\iref{dcl.pre}, and +\item +either that \grammarterm{consteval-block-declaration} or +the template definition from which it is instantiated +is reachable from\iref{module.reach} +\begin{itemize} +\item +$P$, or +\item +the point immediately following +the \grammarterm{class-specifier} of the outermost class +for which $P$ is in a complete-class context\iref{class.mem.general}. +\end{itemize} +\end{itemize} +\begin{example} +\begin{codeblock} +class S { + class Incomplete; + + class Inner { + void fn() { + /* @$p_1$@ */ Incomplete i; // OK + } + }; /* @$p_2$@ */ + + consteval { + define_aggregate(^^Incomplete, {}); + } +}; /* @$p_3$@ */ +\end{codeblock} +Constructs at $p_1$ are analyzed in a context +where the side effect of the call to \tcode{define_aggregate} is evaluated +because +\begin{itemize} +\item +$E$ is the expression corresponding to a consteval block, and +\item +$p_1$ is in a complete-class context of \tcode{S} and +the consteval block is reachable from $p_3$. +\end{itemize} +\end{example} + +\item +\indextext{linking}% +Translated translation units are combined, and +all external entity references are resolved. Library components are linked to satisfy external references to entities not defined in the current translation. All such translator output is collected into a program image which contains information @@ -240,7 +291,9 @@ \indextext{translation!phases|)} \end{enumerate} -\rSec1[lex.charset]{Character sets} +\rSec1[lex.char]{Characters}% + +\rSec2[lex.charset]{Character sets} \pnum \indextext{character set|(}% @@ -317,18 +370,75 @@ \end{floattable} \pnum -The \grammarterm{universal-character-name} construct provides a way to name -other characters. +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{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{alert} \\ +\ucode{0008} & \uname{backspace} \\ +\ucode{000d} & \uname{carriage return} \\ +\end{floattable} + +\pnum +A \defn{code unit} is an integer value +of character type\iref{basic.fundamental}. +Characters in a \grammarterm{character-literal} +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}\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. +The \defnadj{wide literal}{encoding} is the encoding applied +to a wide character or string literal. + +\pnum +A literal encoding or a locale-specific encoding of one of +the execution character sets\iref{character.seq} +encodes each element of the basic literal character set as +a single code unit with non-negative value, +distinct from the code unit for any other such element. +\begin{note} +A character not in the basic literal character set +can be encoded with more than one code unit; +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 \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} (\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}. +\indextext{UTF-8}% +\indextext{UTF-16}% +\indextext{UTF-32}% +For a UTF-8, UTF-16, or UTF-32 literal, +the implementation shall encode +the Unicode scalar value +corresponding to each character of the translation character set +as specified in the Unicode Standard +for the respective Unicode encoding form. +\indextext{character set|)} + +\rSec2[lex.universal.char]{Universal character names} \begin{bnf} -\nontermdef{n-char} \textnormal{one of}\br +\nontermdef{n-char}\br \textnormal{any member of the translation character set except the \unicode{007d}{right curly bracket} or new-line character} \end{bnf} \begin{bnf} \nontermdef{n-char-sequence}\br - n-char\br - n-char-sequence n-char + n-char \opt{n-char-sequence} \end{bnf} \begin{bnf} @@ -343,8 +453,7 @@ \begin{bnf} \nontermdef{simple-hexadecimal-digit-sequence}\br - hexadecimal-digit\br - simple-hexadecimal-digit-sequence hexadecimal-digit + hexadecimal-digit \opt{simple-hexadecimal-digit-sequence} \end{bnf} \begin{bnf} @@ -355,6 +464,22 @@ named-universal-character \end{bnf} +\pnum +The \grammarterm{universal-character-name} construct provides a way to name any +element in the translation character set using just the basic character set. +If a \grammarterm{universal-character-name} outside +the \grammarterm{c-char-sequence}, \grammarterm{s-char-sequence}, or +\grammarterm{r-char-sequence} of a \grammarterm{character-literal} or +\grammarterm{string-literal} +(in either case, including within a \grammarterm{user-defined-literal}) +corresponds to a control character or to a character in the basic character set, +the program is ill-formed. +\begin{note} +A sequence of characters resembling a \grammarterm{universal-character-name} in an +\grammarterm{r-char-sequence}\iref{lex.string} does not form a +\grammarterm{universal-character-name}. +\end{note} + \pnum A \grammarterm{universal-character-name} of the form \tcode{\textbackslash u} \grammarterm{hex-quad}, @@ -382,79 +507,25 @@ None of these names or aliases have leading or trailing spaces. \end{note} -\pnum -If a \grammarterm{universal-character-name} outside -the \grammarterm{c-char-sequence}, \grammarterm{s-char-sequence}, or -\grammarterm{r-char-sequence} of -a \grammarterm{character-literal} or \grammarterm{string-literal} -(in either case, including within a \grammarterm{user-defined-literal}) -corresponds to a control character or -to a character in the basic character set, the program is ill-formed. -\begin{note} -A sequence of characters resembling a \grammarterm{universal-character-name} in an -\grammarterm{r-char-sequence}\iref{lex.string} does not form a -\grammarterm{universal-character-name}. -\end{note} - -\pnum -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{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{alert} \\ -\ucode{0008} & \uname{backspace} \\ -\ucode{000d} & \uname{carriage return} \\ -\end{floattable} - -\pnum -A \defn{code unit} is an integer value -of character type\iref{basic.fundamental}. -Characters in a \grammarterm{character-literal} -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}\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. -The \defnadj{wide literal}{encoding} is the encoding applied -to a wide character or string literal. +\rSec1[lex.comment]{Comments} \pnum -A literal encoding or a locale-specific encoding of one of -the execution character sets\iref{character.seq} -encodes each element of the basic literal character set as -a single code unit with non-negative value, -distinct from the code unit for any other such element. +\indextext{comment|(}% +\indextext{comment!\tcode{/*} \tcode{*/}}% +\indextext{comment!\tcode{//}}% +The characters \tcode{/*} start a comment, which terminates with the +characters \tcode{*/}. These comments do not nest. +\indextext{comment!\tcode{//}}% +The characters \tcode{//} start a comment, which terminates immediately before the +next new-line character. \begin{note} -A character not in the basic literal character set -can be encoded with more than one code unit; -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. +The comment characters \tcode{//}, \tcode{/*}, +and \tcode{*/} have no special meaning within a \tcode{//} comment and +are treated just like other characters. Similarly, the comment +characters \tcode{//} and \tcode{/*} have no special meaning within a +\tcode{/*} comment. \end{note} -\indextext{character!null}% -\indextext{wide-character!null}% -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} (\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}. -\indextext{UTF-8}% -\indextext{UTF-16}% -\indextext{UTF-32}% -For a UTF-8, UTF-16, or UTF-32 literal, -the implementation shall encode -the Unicode scalar value -corresponding to each character of the translation character set -as specified in the Unicode Standard -for the respective Unicode encoding form. -\indextext{character set|)} +\indextext{comment|)} \rSec1[lex.pptoken]{Preprocessing tokens} @@ -475,11 +546,6 @@ \textnormal{each non-whitespace character that cannot be one of the above} \end{bnf} -\pnum -Each preprocessing token that is converted to a token\iref{lex.token} -shall have the lexical form of a keyword, an identifier, a literal, -or an operator or punctuator. - \pnum A preprocessing token is the minimal lexical element of the language in translation phases 3 through 6. @@ -514,6 +580,22 @@ between the quotation characters in a character literal or string literal. +\pnum +Each preprocessing token that is converted to a token\iref{lex.token} +shall have the lexical form of a keyword, an identifier, a literal, +or an operator or punctuator. + +\pnum +The \grammarterm{import-keyword} is produced +by processing an \keyword{import} directive\iref{cpp.import}, +the \grammarterm{module-keyword} is produced +by preprocessing a \keyword{module} directive\iref{cpp.module}, and +the \grammarterm{export-keyword} is produced +by preprocessing either of the previous two directives. +\begin{note} +None has any observable spelling. +\end{note} + \pnum If the input stream has been parsed into preprocessing tokens up to a given character: @@ -536,23 +618,41 @@ is neither \tcode{:} nor \tcode{>}, the \tcode{<} is treated as a preprocessing token by itself and not as the first character of the alternative token \tcode{<:}. +\item +Otherwise, if the next three characters are \tcode{[::} and +the subsequent character is not \tcode{:}, or +if the next three characters are \tcode{[:>}, +the \tcode{[} is treated as a preprocessing token by itself and +not as the first character of the preprocessing token \tcode{[:}. +\begin{note} +The tokens \tcode{[:} and \tcode{:]} cannot be composed from digraphs. +\end{note} + \item Otherwise, the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token, even if that would cause further lexical analysis to fail, -except that a \grammarterm{header-name}\iref{lex.header} is only formed +except that \begin{itemize} \item -after the \tcode{include} or \tcode{import} preprocessing token in an -\tcode{\#include}\iref{cpp.include} or -\tcode{import}\iref{cpp.import} directive, or - +a \grammarterm{string-literal} token is never formed +when a \grammarterm{header-name} token can be formed, and \item -within a \grammarterm{has-include-expression}. - +a \grammarterm{header-name}\iref{lex.header} is only formed +\begin{itemize} +\item +immediately after the \tcode{include}, \tcode{embed}, or \tcode{import} preprocessing token in a +\tcode{\#include}\iref{cpp.include}, \tcode{\#embed}\iref{cpp.embed}, or +\tcode{import}\iref{cpp.import} directive, respectively, or +\item +immediately after a preprocessing token sequence of \xname{has_include} +or \xname{has_embed} immediately followed by \tcode{(} +in a \tcode{\#if}, \tcode{\#elif}, or \tcode{\#embed} directive\iref{cpp.cond,cpp.embed}. +\end{itemize} \end{itemize} \end{itemize} +\pnum \begin{example} \begin{codeblock} #define R "x" @@ -560,17 +660,6 @@ \end{codeblock} \end{example} -\pnum -The \grammarterm{import-keyword} is produced -by processing an \keyword{import} directive\iref{cpp.import}, -the \grammarterm{module-keyword} is produced -by preprocessing a \keyword{module} directive\iref{cpp.module}, and -the \grammarterm{export-keyword} is produced -by preprocessing either of the previous two directives. -\begin{note} -None has any observable spelling. -\end{note} - \pnum \begin{example} The program fragment \tcode{0xe+foo} is parsed as a @@ -593,111 +682,11 @@ \end{example} \indextext{token!preprocessing|)} -\rSec1[lex.digraph]{Alternative tokens} - -\pnum -\indextext{token!alternative|(}% -Alternative token representations are provided for some operators and -punctuators. -\begin{footnote} -\indextext{digraph}% -These include ``digraphs'' and additional reserved words. The term -``digraph'' (token consisting of two characters) is not perfectly -descriptive, since one of the alternative \grammarterm{preprocessing-token}s is -\tcode{\%:\%:} and of course several primary tokens contain two -characters. Nonetheless, those alternative tokens that aren't lexical -keywords are colloquially known as ``digraphs''. -\end{footnote} - -\pnum -In all respects of the language, each alternative token behaves the -same, respectively, as its primary token, except for its spelling. -\begin{footnote} -Thus the ``stringized'' values\iref{cpp.stringize} of -\tcode{[} and \tcode{<:} will be different, maintaining the source -spelling, but the tokens can otherwise be freely interchanged. -\end{footnote} -The set of alternative tokens is defined in -\tref{lex.digraph}. - -\begin{tokentable}{Alternative tokens}{lex.digraph}{Alternative}{Primary} -\tcode{<\%} & \tcode{\{} & -\keyword{and} & \tcode{\&\&} & -\keyword{and_eq} & \tcode{\&=} \\ \rowsep -\tcode{\%>} & \tcode{\}} & -\keyword{bitor} & \tcode{|} & -\keyword{or_eq} & \tcode{|=} \\ \rowsep -\tcode{<:} & \tcode{[} & -\keyword{or} & \tcode{||} & -\keyword{xor_eq} & \tcode{\caret=} \\ \rowsep -\tcode{:>} & \tcode{]} & -\keyword{xor} & \tcode{\caret} & -\keyword{not} & \tcode{!} \\ \rowsep -\tcode{\%:} & \tcode{\#} & -\keyword{compl} & \tcode{\~} & -\keyword{not_eq} & \tcode{!=} \\ \rowsep -\tcode{\%:\%:} & \tcode{\#\#} & -\keyword{bitand} & \tcode{\&} & - & \\ -\end{tokentable}% -\indextext{token!alternative|)} - -\rSec1[lex.token]{Tokens} - -\indextext{token|(}% -\begin{bnf} -\nontermdef{token}\br - identifier\br - keyword\br - literal\br - operator-or-punctuator -\end{bnf} - -\pnum -\indextext{\idxgram{token}}% -There are five kinds of tokens: identifiers, keywords, literals,% -\begin{footnote} -Literals include strings and character and numeric literals. -\end{footnote} -operators, and other separators. -\indextext{whitespace}% -Blanks, horizontal and vertical tabs, newlines, formfeeds, and comments -(collectively, ``whitespace''), as described below, are ignored except -as they serve to separate tokens. -\begin{note} -Whitespace can separate otherwise adjacent identifiers, keywords, numeric -literals, and alternative tokens containing alphabetic characters. -\end{note} -\indextext{token|)} - -\rSec1[lex.comment]{Comments} - -\pnum -\indextext{comment|(}% -\indextext{comment!\tcode{/*} \tcode{*/}}% -\indextext{comment!\tcode{//}}% -The characters \tcode{/*} start a comment, which terminates with the -characters \tcode{*/}. These comments do not nest. -\indextext{comment!\tcode{//}}% -The characters \tcode{//} start a comment, which terminates immediately before the -next new-line character. If there is a form-feed or a vertical-tab -character in such a comment, only whitespace characters shall appear -between it and the new-line that terminates the comment; no diagnostic -is required. -\begin{note} -The comment characters \tcode{//}, \tcode{/*}, -and \tcode{*/} have no special meaning within a \tcode{//} comment and -are treated just like other characters. Similarly, the comment -characters \tcode{//} and \tcode{/*} have no special meaning within a -\tcode{/*} comment. -\end{note} -\indextext{comment|)} - \rSec1[lex.header]{Header names} \indextext{header!name|(}% \begin{bnf} -\microtypesetup{protrusion=false}\obeyspaces +\microtypesetup{protrusion=false} \nontermdef{header-name}\br \terminal{<} h-char-sequence \terminal{>}\br \terminal{"} q-char-sequence \terminal{"} @@ -705,8 +694,7 @@ \begin{bnf} \nontermdef{h-char-sequence}\br - h-char\br - h-char-sequence h-char + h-char \opt{h-char-sequence} \end{bnf} \begin{bnf} @@ -716,8 +704,7 @@ \begin{bnf} \nontermdef{q-char-sequence}\br - q-char\br - q-char-sequence q-char + q-char \opt{q-char-sequence} \end{bnf} \begin{bnf} @@ -726,16 +713,16 @@ \end{bnf} \pnum +The sequences in both forms of \grammarterm{header-name}{s} are mapped in an +\impldef{mapping header name to header or external source file} manner to headers or to +external source file names as specified in~\ref{cpp.include}. \begin{note} -Header name preprocessing tokens only appear within +Header name preprocessing tokens appear only within a \tcode{\#include} preprocessing directive, a \tcode{__has_include} preprocessing expression, or after certain occurrences of an \tcode{import} token (see~\ref{lex.pptoken}). \end{note} -The sequences in both forms of \grammarterm{header-name}{s} are mapped in an -\impldef{mapping header name to header or external source file} manner to headers or to -external source file names as specified in~\ref{cpp.include}. \pnum The appearance of either of the characters \tcode{'} or \tcode{\textbackslash} or of @@ -745,12 +732,12 @@ \tcode{/*}, or \tcode{//} in a \grammarterm{q-char-sequence} or an \grammarterm{h-char-sequence}} semantics, as is the appearance of the character \tcode{"} in an \grammarterm{h-char-sequence}. -\begin{footnote} +\begin{note} Thus, a sequence of characters that resembles an escape sequence can result in an error, be interpreted as the character corresponding to the escape sequence, or have a completely different meaning, depending on the implementation. -\end{footnote} +\end{note} \indextext{header!name|)} \rSec1[lex.ppnumber]{Preprocessing numbers} @@ -782,7 +769,128 @@ a \grammarterm{floating-point-literal} token.% \indextext{number!preprocessing|)} +\rSec1[lex.operators]{Operators and punctuators} + +\pnum +\indextext{operator|(}% +\indextext{punctuator|(}% +The lexical representation of \Cpp{} programs includes a number of +preprocessing tokens that are used in the syntax of the preprocessor or +are converted into tokens for operators and punctuators: + +\begin{bnf} +\nontermdef{preprocessing-op-or-punc}\br + preprocessing-operator\br + operator-or-punctuator +\end{bnf} + +\begin{bnf} +%% Ed. note: character protrusion would misalign various operators. +\microtypesetup{protrusion=false} +\nontermdef{preprocessing-operator} \textnormal{one of}\br + \terminal{\# \ \ \ \ \ \ \ \#\# \ \ \ \ \ \ \%: \ \ \ \ \ \ \%:\%:} +\end{bnf} + +\begin{bnf} +\microtypesetup{protrusion=false} +\nontermdef{operator-or-punctuator} \textnormal{one of}\br + \terminal{\{ \ \ \ \ \ \ \ \} \ \ \ \ \ \ \ [ \ \ \ \ \ \ \ ] \ \ \ \ \ \ \ ( \ \ \ \ \ \ \ ) \ \ \ \ \ \ \ [: \ \ \ \ \ \ :]}\br + \terminal{<\% \ \ \ \ \ \ \%> \ \ \ \ \ \ <: \ \ \ \ \ \ :> \ \ \ \ \ \ ; \ \ \ \ \ \ \ : \ \ \ \ \ \ \ ...}\br + \terminal{? \ \ \ \ \ \ \ :: \ \ \ \ \ \ . \ \ \ \ \ \ \ .* \ \ \ \ \ \ -> \ \ \ \ \ \ ->* \ \ \ \ \ \caret{}\caret{} \ \ \ \ \ \ \~}\br + \terminal{! \ \ \ \ \ \ \ + \ \ \ \ \ \ \ - \ \ \ \ \ \ \ * \ \ \ \ \ \ \ / \ \ \ \ \ \ \ \% \ \ \ \ \ \ \ \caret{} \ \ \ \ \ \ \ \& \ \ \ \ \ \ \ |}\br + \terminal{= \ \ \ \ \ \ \ += \ \ \ \ \ \ -= \ \ \ \ \ \ *= \ \ \ \ \ \ /= \ \ \ \ \ \ \%= \ \ \ \ \ \ \caret{}= \ \ \ \ \ \ \&= \ \ \ \ \ \ |=}\br + \terminal{== \ \ \ \ \ \ != \ \ \ \ \ \ < \ \ \ \ \ \ \ > \ \ \ \ \ \ \ <= \ \ \ \ \ \ >= \ \ \ \ \ \ <=> \ \ \ \ \ \&\& \ \ \ \ \ \ ||}\br + \terminal{<< \ \ \ \ \ \ >> \ \ \ \ \ \ <<= \ \ \ \ \ >>= \ \ \ \ \ ++ \ \ \ \ \ \ -- \ \ \ \ \ \ ,}\br + \terminal{\keyword{and} \ \ \ \ \ \keyword{or} \ \ \ \ \ \ \keyword{xor} \ \ \ \ \ \keyword{not} \ \ \ \ \ \keyword{bitand} \ \ \keyword{bitor} \ \ \ \keyword{compl}}\br + \terminal{\keyword{and_eq} \ \ \keyword{or_eq} \ \ \ \keyword{xor_eq} \ \ \keyword{not_eq}} +\end{bnf} + +Each \grammarterm{operator-or-punctuator} is converted to a single token +in translation phase 7\iref{lex.phases}.% +\indextext{punctuator|)}% +\indextext{operator|)} + +\rSec1[lex.digraph]{Alternative tokens} + +\pnum +\indextext{token!alternative|(}% +Alternative token representations are provided for some operators and +punctuators. +\begin{footnote} +\indextext{digraph}% +These include ``digraphs'' and additional reserved words. The term +``digraph'' (token consisting of two characters) is not perfectly +descriptive, since one of the alternative \grammarterm{preprocessing-token}s is +\tcode{\%:\%:} and of course several primary tokens contain two +characters. Nonetheless, those alternative tokens that aren't lexical +keywords are colloquially known as ``digraphs''. +\end{footnote} + +\pnum +In all respects of the language, each alternative token behaves the +same, respectively, as its primary token, except for its spelling. +\begin{footnote} +Thus the ``stringized'' values\iref{cpp.stringize} of +\tcode{[} and \tcode{<:} will be different, maintaining the source +spelling, but the tokens can otherwise be freely interchanged. +\end{footnote} +The set of alternative tokens is defined in +\tref{lex.digraph}. + +\begin{tokentable}{Alternative tokens}{lex.digraph}{Alternative}{Primary} +\tcode{<\%} & \tcode{\{} & +\keyword{and} & \tcode{\&\&} & +\keyword{and_eq} & \tcode{\&=} \\ \rowsep +\tcode{\%>} & \tcode{\}} & +\keyword{bitor} & \tcode{|} & +\keyword{or_eq} & \tcode{|=} \\ \rowsep +\tcode{<:} & \tcode{[} & +\keyword{or} & \tcode{||} & +\keyword{xor_eq} & \tcode{\caret=} \\ \rowsep +\tcode{:>} & \tcode{]} & +\keyword{xor} & \tcode{\caret} & +\keyword{not} & \tcode{!} \\ \rowsep +\tcode{\%:} & \tcode{\#} & +\keyword{compl} & \tcode{\~} & +\keyword{not_eq} & \tcode{!=} \\ \rowsep +\tcode{\%:\%:} & \tcode{\#\#} & +\keyword{bitand} & \tcode{\&} & + & \\ +\end{tokentable}% +\indextext{token!alternative|)} + +\rSec1[lex.token]{Tokens} + +\indextext{token|(}% +\begin{bnf} +\nontermdef{token}\br + identifier\br + keyword\br + literal\br + operator-or-punctuator +\end{bnf} + +\pnum +\indextext{\idxgram{token}}% +There are five kinds of tokens: identifiers, keywords, literals,% +\begin{footnote} +Literals include strings and character and numeric literals. +\end{footnote} +operators, and other separators. +\indextext{whitespace}% +Comments and the characters \unicode{0020}{space}, \unicode{0009}{character tabulation}, +\unicode{000b}{line tabulation}, \unicode{000c}{form feed}, and new-line +(collectively, ``whitespace''), as described below, are ignored except +as they serve to separate tokens. +\begin{note} +Whitespace can separate otherwise adjacent identifiers, keywords, numeric +literals, and alternative tokens containing alphabetic characters. +\end{note} +\indextext{token|)} + \rSec1[lex.name]{Identifiers} +\indextext{XID_Start}% +\indextext{XID_Continue}% \indextext{identifier|(}% \begin{bnf} @@ -821,8 +929,7 @@ \indextext{name!length of}% \indextext{name}% \begin{note} -The character properties XID_Start and XID_Continue are Derived Core Properties -as described by \UAX{44} of the Unicode Standard. +The character properties XID_Start and XID_Continue are described by \UAX{44} of the Unicode Standard. \begin{footnote} On systems in which linkers cannot accept extended characters, an encoding of the \grammarterm{universal-character-name} can be used in @@ -857,6 +964,8 @@ \indextext{\idxcode{final}}% \indextext{\idxcode{module}}% \indextext{\idxcode{override}}% +\indextext{\idxcode{replaceable_if_eligible}}% +\indextext{\idxcode{trivially_relocatable_if_eligible}}% The identifiers in \tref{lex.name.special} have a special meaning when appearing in a certain context. When referred to in the grammar, these identifiers are used explicitly rather than using the \grammarterm{identifier} grammar production. @@ -866,13 +975,14 @@ \begin{multicolfloattable}{Identifiers with special meaning}{lex.name.special} {llll} -\keyword{final} \\ -\columnbreak -\keyword{import} \\ -\columnbreak -\keyword{module} \\ -\columnbreak -\keyword{override} \\ +\keyword{final} \\ +\keyword{override} \\\columnbreak +\keyword{import} \\ +\keyword{module} \\\columnbreak +\keyword{post} \\ +\keyword{pre} \\\columnbreak +\keyword{replaceable_if_eligible} \\ +\keyword{trivially_relocatable_if_eligible} \\ \end{multicolfloattable} \pnum @@ -890,7 +1000,9 @@ \tcode{\unun} \indextext{character!underscore}% or begins with an underscore followed by -an uppercase letter +an uppercase letter, +other than those specified in this document +(for example, \xname{cplusplus}\iref{cpp.predefined}), \indextext{uppercase}% is reserved to the implementation for any use. \item @@ -944,6 +1056,7 @@ \keyword{constinit} \\ \keyword{const_cast} \\ \keyword{continue} \\ +\keyword{contract_assert} \\ \keyword{co_await} \\ \keyword{co_return} \\ \keyword{co_yield} \\ @@ -957,8 +1070,8 @@ \keyword{enum} \\ \keyword{explicit} \\ \keyword{export} \\ -\keyword{extern} \\ \columnbreak +\keyword{extern} \\ \keyword{false} \\ \keyword{float} \\ \keyword{for} \\ @@ -975,8 +1088,8 @@ \keyword{nullptr} \\ \keyword{operator} \\ \keyword{private} \\ -\keyword{protected} \\ \columnbreak +\keyword{protected} \\ \keyword{public} \\ \keyword{register} \\ \keyword{reinterpret_cast} \\ @@ -993,8 +1106,8 @@ \keyword{template} \\ \keyword{this} \\ \keyword{thread_local} \\ -\keyword{throw} \\ \columnbreak +\keyword{throw} \\ \keyword{true} \\ \keyword{try} \\ \keyword{typedef} \\ @@ -1025,47 +1138,6 @@ \indextext{keyword|)}% -\rSec1[lex.operators]{Operators and punctuators} - -\pnum -\indextext{operator|(}% -\indextext{punctuator|(}% -The lexical representation of \Cpp{} programs includes a number of -preprocessing tokens that are used in the syntax of the preprocessor or -are converted into tokens for operators and punctuators: - -\begin{bnf} -\nontermdef{preprocessing-op-or-punc}\br - preprocessing-operator\br - operator-or-punctuator -\end{bnf} - -\begin{bnf} -%% Ed. note: character protrusion would misalign various operators. -\microtypesetup{protrusion=false}\obeyspaces -\nontermdef{preprocessing-operator} \textnormal{one of}\br - \terminal{\# \#\# \%: \%:\%:} -\end{bnf} - -\begin{bnf} -\microtypesetup{protrusion=false}\obeyspaces -\nontermdef{operator-or-punctuator} \textnormal{one of}\br - \terminal{\{ \} [ ] ( )}\br - \terminal{<: :> <\% \%> ; : ...}\br - \terminal{? :: . .* -> ->* \~}\br - \terminal{! + - * / \% \caret{} \& |}\br - \terminal{= += -= *= /= \%= \caret{}= \&= |=}\br - \terminal{== != < > <= >= <=> \&\& ||}\br - \terminal{<< >> <<= >>= ++ -- ,}\br - \terminal{\keyword{and} \keyword{or} \keyword{xor} \keyword{not} \keyword{bitand} \keyword{bitor} \keyword{compl}}\br - \terminal{\keyword{and_eq} \keyword{or_eq} \keyword{xor_eq} \keyword{not_eq}} -\end{bnf} - -Each \grammarterm{operator-or-punctuator} is converted to a single token -in translation phase 7\iref{lex.phases}.% -\indextext{punctuator|)}% -\indextext{operator|)} - \rSec1[lex.literal]{Literals}% \indextext{literal|(} @@ -1077,8 +1149,7 @@ There are several kinds of literals. \begin{footnote} The term ``literal'' generally designates, in this -document, those tokens that are called ``constants'' in -ISO C. +document, those tokens that are called ``constants'' in C. \end{footnote} \begin{bnf} @@ -1204,7 +1275,7 @@ \grammarterm{octal-digit}s, \grammarterm{digit}s, or \grammarterm{hexadecimal-digit}s -is interpreted as a base $N$ integer as shown in table \tref{lex.icon.base}; +is interpreted as a base $N$ integer as shown in \tref{lex.icon.base}; the lexically first digit of the sequence of digits is the most significant. \begin{note} The prefix and any optional separating single quotes are ignored @@ -1363,8 +1434,7 @@ \begin{bnf} \nontermdef{c-char-sequence}\br - c-char\br - c-char-sequence c-char + c-char \opt{c-char-sequence} \end{bnf} \begin{bnf} @@ -1405,8 +1475,7 @@ \begin{bnf} \nontermdef{simple-octal-digit-sequence}\br - octal-digit\br - simple-octal-digit-sequence octal-digit + octal-digit \opt{simple-octal-digit-sequence} \end{bnf} \begin{bnf} @@ -1414,7 +1483,7 @@ \terminal{\textbackslash} octal-digit\br \terminal{\textbackslash} octal-digit octal-digit\br \terminal{\textbackslash} octal-digit octal-digit octal-digit\br - \terminal{\textbackslash o\{} simple-octal-digit-sequence \terminal{\}}\br + \terminal{\textbackslash o\{} simple-octal-digit-sequence \terminal{\}} \end{bnf} \begin{bnf} @@ -1463,8 +1532,8 @@ \begin{floattable}{Character literals}{lex.ccon.literal} {l|l|l|l|l} \topline -Encoding & Kind & Type & Associated char- & Example \\ -prefix & & & acter encoding & \\ +\lhdr{Encoding} & \chdr{Kind} & \chdr{Type} & \chdr{Associated char-} & \rhdr{Example} \\ +\lhdr{prefix} & \chdr{} & \chdr{} & \chdr{acter encoding} & \\ \capsep none & \defnx{ordinary character literal}{literal!character!ordinary} & @@ -1565,7 +1634,7 @@ is specified in \tref{lex.ccon.esc}. \begin{note} Using an escape sequence for a question mark -is supported for compatibility with ISO \CppXIV{} and ISO C. +is supported for compatibility with \CppXIV{} and C. \end{note} \begin{floattable}{Simple escape sequences}{lex.ccon.esc} @@ -1671,7 +1740,7 @@ \topline \lhdr{\grammarterm{floating-point-suffix}} & \rhdr{type} \\ \capsep none & \keyword{double} \\ -\tcode{f} or \tcode{F} & \keyword {float} \\ +\tcode{f} or \tcode{F} & \keyword{float} \\ \tcode{l} or \tcode{L} & \keyword{long} \keyword{double} \\ \tcode{f16} or \tcode{F16} & \tcode{std::float16_t} \\ \tcode{f32} or \tcode{F32} & \tcode{std::float32_t} \\ @@ -1734,8 +1803,7 @@ \begin{bnf} \nontermdef{s-char-sequence}\br - s-char\br - s-char-sequence s-char + s-char \opt{s-char-sequence} \end{bnf} \begin{bnf} @@ -1758,8 +1826,7 @@ \begin{bnf} \nontermdef{r-char-sequence}\br - r-char\br - r-char-sequence r-char + r-char \opt{r-char-sequence} \end{bnf} \begin{bnf} @@ -1770,8 +1837,7 @@ \begin{bnf} \nontermdef{d-char-sequence}\br - d-char\br - d-char-sequence d-char + d-char \opt{d-char-sequence} \end{bnf} \begin{bnf} @@ -1797,14 +1863,16 @@ are determined by its encoding prefix and sequence of \grammarterm{s-char}s or \grammarterm{r-char}s as defined by \tref{lex.string.literal} -where $n$ is the number of encoded code units as described below. +where $n$ is the number of encoded code units +that would result from an evaluation of the \grammarterm{string-literal} +(see below). \begin{floattable}{String literals}{lex.string.literal} {llp{2.6cm}p{2.3cm}p{4.7cm}} \topline -Encoding & Kind & Type & Associated & Examples \\ -prefix & & & character & \\ - & & & encoding & \\ +\lhdr{Enco-} & \chdr{Kind} & \chdr{Type} & \chdr{Associated} & \rhdr{Examples} \\ +\lhdr{ding} & \chdr{} & \chdr{} & \chdr{character} & \rhdr{} \\ +\lhdr{prefix} & \chdr{} & \chdr{} & \chdr{encoding} & \rhdr{} \\ \capsep none & \defnx{ordinary string literal}{literal!string!ordinary} & @@ -1891,16 +1959,11 @@ \pnum \indextext{concatenation!string}% -The common \grammarterm{encoding-prefix} -for a sequence of adjacent \grammarterm{string-literal}s -is determined pairwise as follows: -If two \grammarterm{string-literal}{s} have -the same \grammarterm{encoding-prefix}, -the common \grammarterm{encoding-prefix} is that \grammarterm{encoding-prefix}. -If one \grammarterm{string-literal} has no \grammarterm{encoding-prefix}, -the common \grammarterm{encoding-prefix} is that -of the other \grammarterm{string-literal}. -Any other combinations are ill-formed. +The \grammarterm{string-literal}{s} in +any sequence of adjacent \grammarterm{string-literal}{s} +shall have at most one unique \grammarterm{encoding-prefix} among them. +The common \grammarterm{encoding-prefix} of the sequence is +that \grammarterm{encoding-prefix}, if any. \begin{note} A \grammarterm{string-literal}'s rawness has no effect on the determination of the common \grammarterm{encoding-prefix}. @@ -2068,8 +2131,8 @@ \indextext{literal!boolean}% \begin{bnf} \nontermdef{boolean-literal}\br - \terminal{false}\br - \terminal{true} + \keyword{false}\br + \keyword{true} \end{bnf} \pnum @@ -2082,7 +2145,7 @@ \indextext{literal!pointer}% \begin{bnf} \nontermdef{pointer-literal}\br - \terminal{nullptr} + \keyword{nullptr} \end{bnf} \pnum @@ -2218,7 +2281,7 @@ and let \placeholder{len} be the number of code units in \placeholder{str} (i.e., its length excluding the terminating null character). If \placeholder{S} contains a literal operator template with -a non-type template parameter for which \placeholder{str} is +a constant template parameter for which \placeholder{str} is a well-formed \grammarterm{template-argument}, the literal \placeholder{L} is treated as a call of the form \begin{codeblock} diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 1368929680..b78c4f80eb 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -32,21 +32,21 @@ \ref{mem} & Memory management library \\ \ref{meta} & Metaprogramming library \\ \ref{utilities} & General utilities library \\ -\ref{strings} & Strings library \\ \ref{containers} & Containers library \\ \ref{iterators} & Iterators library \\ \ref{ranges} & Ranges library \\ \ref{algorithms} & Algorithms library \\ +\ref{strings} & Strings library \\ +\ref{text} & Text processing library \\ \ref{numerics} & Numerics library \\ \ref{time} & Time library \\ -\ref{localization} & Localization library \\ \ref{input.output} & Input/output library \\ -\ref{re} & Regular expressions library \\ \ref{thread} & Concurrency support library \\ +\ref{exec} & Execution control library \\ \end{floattable} \pnum -The operating system interface described in ISO/IEC/IEEE 9945:2009 is +The operating system interface described in \IsoPosix{} is hereinafter called \defn{POSIX}. \pnum @@ -82,8 +82,13 @@ such as tuples and function wrappers. \pnum -The strings library\iref{strings} provides support for manipulating text represented -as sequences of type \tcode{char}, +The containers\iref{containers}, iterators\iref{iterators}, ranges\iref{ranges}, +and algorithms\iref{algorithms} libraries provide a \Cpp{} program with access +to a subset of the most widely used algorithms and data structures. + +\pnum +The strings library\iref{strings} provides support +for manipulating sequences of type \tcode{char}, sequences of type \keyword{char8_t}, sequences of type \keyword{char16_t}, sequences of type \keyword{char32_t}, @@ -91,9 +96,9 @@ and sequences of any other character-like type. \pnum -The containers\iref{containers}, iterators\iref{iterators}, ranges\iref{ranges}, -and algorithms\iref{algorithms} libraries provide a \Cpp{} program with access -to a subset of the most widely used algorithms and data structures. +The text processing library\iref{text} provides support for text processing, +including formatting, internationalization support and +regular expression matching and searching. \pnum The numerics library\iref{numerics} provides @@ -110,10 +115,6 @@ The time library\iref{time} provides generally useful time utilities. -\pnum -The localization library\iref{localization} provides extended internationalization -support for text processing. - \pnum The input/output library\iref{input.output} provides the \tcode{iostream} @@ -121,14 +122,15 @@ They can be used with other elements of the library, particularly strings, locales, and iterators. -\pnum -The regular expressions library\iref{re} provides regular expression matching and searching. - \pnum The concurrency support library\iref{thread} provides components to create and manage threads, including atomic operations, mutual exclusion, and interthread communication. +\pnum +The execution control library\iref{exec} provides components +supporting execution of function objects. + \rSec1[library.c]{The C standard library} \pnum @@ -144,8 +146,8 @@ may be different from the signatures in the C standard library, and additional overloads may be declared in this document, but the behavior and the preconditions -(including any preconditions implied by the use of an -ISO C \tcode{restrict} qualifier) +(including any preconditions implied by the use of +a C \tcode{restrict} qualifier) are the same unless otherwise stated. \pnum @@ -161,7 +163,7 @@ 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 +\IsoC{}, 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} @@ -366,11 +368,39 @@ and also define the function as deleted. \end{example} +\item +\constantwhen +the conditions that are required for a call to the function +to be a constant subexpression\iref{defns.const.subexpr}. + \item \expects -the conditions -that the function assumes to hold whenever it is called; +conditions that the function assumes to hold whenever it is called; violation of any preconditions results in undefined behavior. +\begin{example} +An implementation can express some such conditions +via the use of a contract assertion, +such as a precondition assertion\iref{dcl.contract.func}. +\end{example} + +\item +\hardexpects +conditions that the function assumes to hold whenever it is called. +\begin{itemize} +\item +When invoking the function in a hardened implementation, +prior to any other observable side effects of the function, +one or more contract assertions +whose predicates are as described in the hardened precondition +are evaluated with a checking semantic\iref{basic.contract.eval}. +If any of these assertions is evaluated with a non-terminating semantic +and the contract-violation handler returns, +the program has undefined behavior. +\item +When invoking the function in a non-hardened implementation, +if any hardened precondition is violated, +the program has undefined behavior. +\end{itemize} \item \effects @@ -384,12 +414,17 @@ \ensures the conditions (sometimes termed observable results) established by the function. +\begin{example} +An implementation can express some such conditions +via the use of a contract assertion, +such as a postcondition assertion\iref{dcl.contract.func}. +\end{example} \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; +a description of the type and value category 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. @@ -422,9 +457,19 @@ If \tcode{F}'s semantics specifies any \Fundescx{Constraints} or \Fundescx{Mandates} elements, then those requirements are logically imposed prior to the \term{equivalent-to} semantics. Next, the semantics of the code sequence are determined by the -\Fundescx{Constraints}, \Fundescx{Mandates}, \Fundescx{Preconditions}, \Fundescx{Effects}, -\Fundescx{Synchronization}, \Fundescx{Postconditions}, \Fundescx{Returns}, \Fundescx{Throws}, -\Fundescx{Complexity}, \Fundescx{Remarks}, and \Fundescx{Error conditions} +\Fundescx{Constraints}, +\Fundescx{Mandates}, +\Fundescx{Constant When}, +\Fundescx{Preconditions}, +\Fundescx{Hardened preconditions}, +\Fundescx{Effects}, +\Fundescx{Synchronization}, +\Fundescx{Postconditions}, +\Fundescx{Returns}, +\Fundescx{Throws}, +\Fundescx{Complexity}, +\Fundescx{Remarks}, and +\Fundescx{Error conditions} specified for the function invocations contained in the code sequence. The value returned from \tcode{F} is specified by \tcode{F}'s \Fundescx{Returns} element, or if \tcode{F} has no \Fundescx{Returns} element, @@ -499,11 +544,11 @@ namespace std { template requires @\libconcept{convertible_to}@> - constexpr decay_t @\placeholdernc{decay-copy}@(T&& v) - noexcept(is_nothrow_convertible_v>) // \expos + constexpr decay_t @\placeholdernc{decay-copy}@(T&& v) // \expos + noexcept(is_nothrow_convertible_v>) { return std::forward(v); } - constexpr auto @\placeholdernc{synth-three-way}@ = + constexpr auto @\placeholdernc{synth-three-way}@ = // \expos [](const T& t, const U& u) requires requires { { t < u } -> @\exposconcept{boolean-testable}@; @@ -519,11 +564,20 @@ } }; - template - using @\placeholdernc{synth-three-way-result}@ = decltype(@\placeholdernc{synth-three-way}@(declval(), declval())); + template + using @\placeholdernc{synth-three-way-result}@ = // \expos + decltype(@\placeholdernc{synth-three-way}@(declval(), declval())); } \end{codeblock} +\pnum +An object \tcode{dst} is said to be \defn{decay-copied from} +a subexpression \tcode{src} +if the type of \tcode{dst} is +\begin{codeblock} +decay_t +\end{codeblock} and \tcode{dst} is copy-initialized from \tcode{src}. + \rSec3[type.descriptions]{Type descriptions} \rSec4[type.descriptions.general]{General} @@ -845,9 +899,40 @@ \item \tcode{std::move(as_const(p))(args...)} \end{itemize} +\rSec3[alg.func.obj]{Algorithm function objects} + \pnum -Each customization point object type constrains its return type to model a -particular concept. +An \defn{algorithm function object} is +a customization point object\iref{customization.point.object} +that is specified as one or more overloaded function templates. +The name of these function templates designates +the corresponding algorithm function object. + +\pnum +For an algorithm function object \tcode{o}, +let $S$ be the corresponding set of function templates. +Then for any sequence of arguments $\tcode{args} \dotsc$, +$\tcode{o(args} \dotsc \tcode{)}$ is expression-equivalent to +$\tcode{s(args} \dotsc \tcode{)}$, +where the result of name lookup for \tcode{s} is the overload set $S$. +\begin{note} +Algorithm function objects are not found by +argument-dependent name lookup\iref{basic.lookup.argdep}. +When found by unqualified name lookup\iref{basic.lookup.unqual} +for the \grammarterm{postfix-expression} in a function call\iref{expr.call}, +they inhibit argument-dependent name lookup. +\begin{example} +\begin{codeblock} +void foo() { + using namespace std::ranges; + std::vector vec{1,2,3}; + find(begin(vec), end(vec), 2); // \#1 +} +\end{codeblock} +The function call expression at \#1 invokes \tcode{std::ranges::find}, +not \tcode{std::find}. +\end{example} +\end{note} \rSec3[functions.within.classes]{Functions within classes} @@ -950,8 +1035,9 @@ \indextext{entity!freestanding item}% \indextext{deduction guide!freestanding item}% \indextext{\idxgram{typedef-name}!freestanding item}% -An entity, deduction guide, or \grammarterm{typedef-name} is -a freestanding item if it is: +An entity, deduction guide, or \grammarterm{typedef-name} +is a freestanding item if its introducing declaration is not followed by +a comment that includes \textit{hosted}, and is: \begin{itemize} \item introduced by a declaration that is a freestanding item, \item a member of a freestanding item other than a namespace, @@ -1069,7 +1155,8 @@ \pnum Whenever an unqualified name other than -\tcode{swap}, \tcode{make_error_code}, \tcode{make_error_condition}, or +\tcode{swap}, \tcode{make_error_code}, \tcode{make_error_condition}, +\tcode{from_stream}, or \tcode{submdspan_mapping} is used in the specification of a declaration \tcode{D} in \ref{\firstlibchapter} through \ref{\lastlibchapter} or \ref{depr}, @@ -1093,7 +1180,8 @@ in an overload resolution context for swappable values\iref{swappable.requirements}. The meanings of the unqualified names -\tcode{make_error_code}, \tcode{make_error_condition}, and +\tcode{make_error_code}, \tcode{make_error_condition}, +\tcode{from_stream}, and \tcode{submdspan_mapping} are established as-if by performing argument-dependent lookup\iref{basic.lookup.argdep}. @@ -1130,6 +1218,7 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1139,15 +1228,17 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\columnbreak \tcode{} \\ +\columnbreak \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1163,8 +1254,9 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \columnbreak +\tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1181,20 +1273,20 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\columnbreak \tcode{} \\ \tcode{} \\ -\columnbreak \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1444,12 +1536,19 @@ \pnum The named module \tcode{std.compat} exports the same declarations as the named module \tcode{std}, and -additionally exports declarations in the global namespace +additionally exports +\begin{itemize} +\item +declarations in the global namespace corresponding to the declarations in namespace \tcode{std} that are provided by the \Cpp{} headers for C library facilities~(\tref{headers.cpp.c}), except the explicitly excluded declarations -described in \ref{support.c.headers.other}. +described in \ref{support.c.headers.other} and +\item +declarations provided by +the headers \libheaderref{stdbit.h} and \libheaderref{stdckdint.h}. +\end{itemize} \pnum It is unspecified to which module a declaration in the standard library @@ -1507,18 +1606,20 @@ \ref{support.limits} & Implementation properties & \tcode{}, \tcode{}, \tcode{}, \\ & & \tcode{} \\ \rowsep -\ref{cstdint.syn} & Integer types & \tcode{} \\ \rowsep +\ref{cstdint.syn} & Integer types & \tcode{} \\ \rowsep \ref{support.dynamic} & Dynamic memory management & \tcode{} \\ \rowsep \ref{support.rtti} & Type identification & \tcode{} \\ \rowsep \ref{support.srcloc} & Source location & \tcode{} \\ \rowsep \ref{support.exception} & Exception handling & \tcode{} \\ \rowsep \ref{support.initlist} & Initializer lists & \tcode{} \\ \rowsep \ref{cmp} & Comparisons & \tcode{} \\ \rowsep +\ref{support.contract} & Contract-violation handling & \tcode{} \\ \rowsep \ref{support.coroutine} & Coroutines support & \tcode{} \\ \rowsep \ref{support.runtime} & Other runtime support & \tcode{} \\ \rowsep \ref{concepts} & Concepts library & \tcode{} \\ \rowsep \ref{errno} & Error numbers & \tcode{} \\ \rowsep \ref{syserr} & System error support & \tcode{} \\ \rowsep +\ref{debugging} & Debugging & \tcode{} \\ \rowsep \ref{memory} & Memory & \tcode{} \\ \rowsep \ref{type.traits} & Type traits & \tcode{} \\ \rowsep \ref{ratio} & Compile-time rational arithmetic & \tcode{} \\ \rowsep @@ -1528,20 +1629,23 @@ \ref{variant} & Variants & \tcode{} \\ \rowsep \ref{expected} & Expected objects & \tcode{} \\ \rowsep \ref{function.objects} & Function objects & \tcode{} \\ \rowsep -\ref{charconv} & Primitive numeric conversions & \tcode{} \\ \rowsep \ref{bit} & Bit manipulation & \tcode{} \\ \rowsep -\ref{string.view} & String view classes & \tcode{} \\ \rowsep -\ref{string.classes} & String classes & \tcode{} \\ \rowsep -\ref{c.strings} & Null-terminated sequence utilities & \tcode{}, \tcode{} \\ \rowsep +\ref{stdbit.h.syn} & C-compatible bit manipulation & \tcode{} \\ \rowsep \ref{array} & Class template \tcode{array} & \tcode{} \\ \rowsep +\ref{inplace.vector} & Class template \tcode{inplace_vector} & \tcode{} \\ \rowsep \ref{views.contiguous} & Contiguous access & \tcode{} \\ \rowsep \ref{views.multidim} & Multidimensional access & \tcode{} \\ \rowsep \ref{iterators} & Iterators library & \tcode{} \\ \rowsep \ref{ranges} & Ranges library & \tcode{} \\ \rowsep \ref{algorithms} & Algorithms library & \tcode{}, \tcode{} \\ \rowsep +\ref{execpol} & Execution policies & \tcode{} \\ \rowsep +\ref{string.view} & String view classes & \tcode{} \\ \rowsep +\ref{string.classes} & String classes & \tcode{} \\ \rowsep +\ref{c.strings} & Null-terminated sequence utilities & \tcode{}, \tcode{} \\ \rowsep +\ref{charconv} & Primitive numeric conversions & \tcode{} \\ \rowsep +\ref{rand} & Random number generation & \tcode{} \\ \rowsep \ref{c.math} & Mathematical functions for floating-point types & \tcode{} \\ \rowsep \ref{atomics} & Atomics & \tcode{} \\ \rowsep -\ref{debugging} & Debugging & \tcode{} \\ \rowsep \end{libsumtab} \pnum @@ -1822,7 +1926,7 @@ denote an expression of type \tcode{U}. \pnum -An object \tcode{t} is \defn{swappable with} an object \tcode{u} if and only if: +An object \tcode{t} is \defn{swappable with} an object \tcode{u} if and only if \begin{itemize} \item the expressions \tcode{swap(t, u)} and \tcode{swap(u, t)} are valid when evaluated in the context described below, and @@ -1863,12 +1967,12 @@ swappable with any rvalue or lvalue, respectively, of type \tcode{T}. \pnum -A type \tcode{X} meets the \oldconcept{Swappable} requirements +A type \tcode{X} meets the \defnoldconcept{Swappable} requirements if lvalues of type \tcode{X} are swappable. \pnum A type \tcode{X} meeting any of the iterator requirements\iref{iterator.requirements} -meets the \oldconcept{ValueSwappable} requirements if, +meets the \defnoldconcept{ValueSwappable} requirements if, for any dereferenceable object \tcode{x} of type \tcode{X}, \tcode{*x} is swappable. @@ -1924,7 +2028,7 @@ \pnum A \oldconcept{NullablePointer} type is a pointer-like type that supports null values. -A type \tcode{P} meets the \oldconcept{\-Nullable\-Pointer} requirements if: +A type \tcode{P} meets the \oldconcept{\-Nullable\-Pointer} requirements if \begin{itemize} \item \tcode{P} meets the \oldconcept{EqualityComparable}, \oldconcept{DefaultConstructible}, \oldconcept{CopyConstructible}, \oldconcept{\-Copy\-Assign\-able}, @@ -1939,10 +2043,10 @@ \pnum A value-initialized object of type \tcode{P} produces the null value of the type. The null value shall be equivalent only to itself. A default-initialized object -of type \tcode{P} may have an indeterminate value. +of type \tcode{P} may have an indeterminate or erroneous value. \begin{note} -Operations involving -indeterminate values can cause undefined behavior. +Operations involving indeterminate values can cause undefined behavior, and +operations involving erroneous values can cause erroneous behavior\iref{basic.indet}. \end{note} \pnum @@ -2000,7 +2104,7 @@ \rSec3[hash.requirements]{\oldconcept{Hash} requirements} \pnum -A type \tcode{H} meets the \defnoldconcept{Hash} requirements if: +A type \tcode{H} meets the \defnoldconcept{Hash} requirements if \begin{itemize} \item it is a function object type\iref{function.objects}, \item it meets the \oldconcept{CopyConstructible} (\tref{cpp17.copyconstructible}) and @@ -2048,13 +2152,13 @@ difference, the type of the size of objects in this allocation model, as well as the memory allocation and deallocation primitives for it. All of the string types\iref{strings}, -containers\iref{containers} (except \tcode{array}), +containers\iref{containers} (except \tcode{array} and \tcode{inplace_vector}), string buffers and string streams\iref{input.output}, and \tcode{match_results}\iref{re} are parameterized in terms of allocators. \pnum -In subclause \ref{allocator.requirements}, +In \ref{allocator.requirements}, \begin{itemize} \item \tcode{T}, \tcode{U}, \tcode{C} denote @@ -2222,7 +2326,7 @@ \end{itemdescr} \begin{itemdecl} -typename X::template rebind::other +typename X::rebind::other \end{itemdecl} \begin{itemdescr} @@ -2850,6 +2954,22 @@ \end{codeblock} \end{example} +\pnum +The following exposition-only concept defines +the minimal requirements on an Allocator type. +\begin{codeblock} +template +concept @\defexposconcept{simple-allocator}@ = + requires(Alloc alloc, size_t n) { + { *alloc.allocate(n) } -> @\libconcept{same_as}@; + { alloc.deallocate(alloc.allocate(n), n) }; + } && + @\libconcept{copy_constructible}@ && + @\libconcept{equality_comparable}@; +\end{codeblock} +A type \tcode{Alloc} models \exposconcept{simple-allocator} +if it meets the requirements of \ref{allocator.requirements.general}. + \rSec4[allocator.requirements.completeness]{Allocator completeness requirements} \pnum @@ -2970,6 +3090,26 @@ either a standard library non-static member function\iref{member.functions} or an instantiation of a standard library member function template. +\pnum +Let \tcode{\placeholder{F}} denote +a standard library function or function template. +Unless \tcode{\placeholder{F}} is designated an addressable function, +it is unspecified if or how +a reflection value designating the associated entity can be formed. +%FIXME: Why is this not an example, but a note that begins with "For example"? +\begin{note} +For example, it is possible that \tcode{std::meta::members_of} +will not return reflections of standard library functions +that an implementation handles through an extra-linguistic mechanism. +\end{note} + +\pnum +Let \tcode{\placeholder{C}} denote +a standard library class or class template specialization. +It is unspecified if or how +a reflection value can be formed to any private member of \tcode{\placeholder{C}}, +or what the names of such members may be. + \pnum A translation unit shall not declare namespace \tcode{std} to be an inline namespace\iref{namespace.def}. @@ -2981,7 +3121,7 @@ or to a namespace within namespace \tcode{posix} unless otherwise specified. The namespace \tcode{posix} is reserved for use by -ISO/IEC/IEEE 9945 and other POSIX standards. +\IsoPosixUndated{} and other POSIX standards. \rSec4[namespace.future]{Namespaces for future standardization} @@ -3021,91 +3161,132 @@ \indextext{brains!names that want to eat your}% \pnum -In namespace \tcode{std}, the following names are reserved for previous standardization: -\begin{itemize} -\item \indexlibraryzombie{auto_ptr} \tcode{auto_ptr}, -\item \indexlibraryzombie{auto_ptr_ref} \tcode{auto_ptr_ref}, -\item \indexlibraryzombie{binary_function} \tcode{binary_function}, -\item \indexlibraryzombie{binary_negate} \tcode{binary_negate}, -\item \indexlibraryzombie{bind1st} \tcode{bind1st}, -\item \indexlibraryzombie{bind2nd} \tcode{bind2nd}, -\item \indexlibraryzombie{binder1st} \tcode{binder1st}, -\item \indexlibraryzombie{binder2nd} \tcode{binder2nd}, -\item \indexlibraryzombie{codecvt_mode} \tcode{codecvt_mode}, -\item \indexlibraryzombie{codecvt_utf16} \tcode{codecvt_utf16}, -\item \indexlibraryzombie{codecvt_utf8} \tcode{codecvt_utf8}, -\item \indexlibraryzombie{codecvt_utf8_utf16} \tcode{codecvt_utf8_utf16}, -\item \indexlibraryzombie{const_mem_fun1_ref_t} \tcode{const_mem_fun1_ref_t}, -\item \indexlibraryzombie{const_mem_fun1_t} \tcode{const_mem_fun1_t}, -\item \indexlibraryzombie{const_mem_fun_ref_t} \tcode{const_mem_fun_ref_t}, -\item \indexlibraryzombie{const_mem_fun_t} \tcode{const_mem_fun_t}, -\item \indexlibraryzombie{consume_header} \tcode{consume_header}, -\item \indexlibraryzombie{declare_no_pointers} \tcode{declare_no_pointers}, -\item \indexlibraryzombie{declare_reachable} \tcode{declare_reachable}, -\item \indexlibraryzombie{generate_header} \tcode{generate_header}, -\item \indexlibraryzombie{get_pointer_safety} \tcode{get_pointer_safety}, -\item \indexlibraryzombie{get_temporary_buffer} \tcode{get_temporary_buffer}, -\item \indexlibraryzombie{get_unexpected} \tcode{get_unexpected}, -\item \indexlibraryzombie{gets} \tcode{gets}, -\item \indexlibraryzombie{is_literal_type} \tcode{is_literal_type}, -\item \indexlibraryzombie{is_literal_type_v} \tcode{is_literal_type_v}, -\item \indexlibraryzombie{little_endian} \tcode{little_endian}, -\item \indexlibraryzombie{mem_fun1_ref_t} \tcode{mem_fun1_ref_t}, -\item \indexlibraryzombie{mem_fun1_t} \tcode{mem_fun1_t}, -\item \indexlibraryzombie{mem_fun_ref_t} \tcode{mem_fun_ref_t}, -\item \indexlibraryzombie{mem_fun_ref} \tcode{mem_fun_ref}, -\item \indexlibraryzombie{mem_fun_t} \tcode{mem_fun_t}, -\item \indexlibraryzombie{mem_fun} \tcode{mem_fun}, -\item \indexlibraryzombie{not1} \tcode{not1}, -\item \indexlibraryzombie{not2} \tcode{not2}, -\item \indexlibraryzombie{pointer_safety} \tcode{pointer_safety}, -\item \indexlibraryzombie{pointer_to_binary_function} \tcode{pointer_to_binary_function}, -\item \indexlibraryzombie{pointer_to_unary_function} \tcode{pointer_to_unary_function}, -\item \indexlibraryzombie{ptr_fun} \tcode{ptr_fun}, -\item \indexlibraryzombie{random_shuffle} \tcode{random_shuffle}, -\item \indexlibraryzombie{raw_storage_iterator} \tcode{raw_storage_iterator}, -\item \indexlibraryzombie{result_of} \tcode{result_of}, -\item \indexlibraryzombie{result_of_t} \tcode{result_of_t}, -\item \indexlibraryzombie{return_temporary_buffer} \tcode{return_temporary_buffer}, -\item \indexlibraryzombie{set_unexpected} \tcode{set_unexpected}, -\item \indexlibraryzombie{unary_function} \tcode{unary_function}, -\item \indexlibraryzombie{unary_negate} \tcode{unary_negate}, -\item \indexlibraryzombie{uncaught_exception} \tcode{uncaught_exception}, -\item \indexlibraryzombie{undeclare_no_pointers} \tcode{undeclare_no_pointers}, -\item \indexlibraryzombie{undeclare_reachable} \tcode{undeclare_reachable}, -and -\item \indexlibraryzombie{unexpected_handler} \tcode{unexpected_handler}. -\end{itemize} +In namespace \tcode{std}, the names shown in \tref{zombie.names.std} are +reserved for previous standardization: + +\begin{multicolfloattable}{Zombie names in namespace \tcode{std}}{zombie.names.std} +{lll} +\indexlibraryzombie{auto_ptr} \tcode{auto_ptr} \\ +\indexlibraryzombie{auto_ptr_ref} \tcode{auto_ptr_ref} \\ +\indexlibraryzombie{binary_function} \tcode{binary_function} \\ +\indexlibraryzombie{binary_negate} \tcode{binary_negate} \\ +\indexlibraryzombie{bind1st} \tcode{bind1st} \\ +\indexlibraryzombie{bind2nd} \tcode{bind2nd} \\ +\indexlibraryzombie{binder1st} \tcode{binder1st} \\ +\indexlibraryzombie{binder2nd} \tcode{binder2nd} \\ +\indexlibraryzombie{codecvt_mode} \tcode{codecvt_mode} \\ +\indexlibraryzombie{codecvt_utf16} \tcode{codecvt_utf16} \\ +\indexlibraryzombie{codecvt_utf8} \tcode{codecvt_utf8} \\ +\indexlibraryzombie{codecvt_utf8_utf16} \tcode{codecvt_utf8_utf16} \\ +\indexlibraryzombie{const_mem_fun1_ref_t} \tcode{const_mem_fun1_ref_t} \\ +\indexlibraryzombie{const_mem_fun1_t} \tcode{const_mem_fun1_t} \\ +\indexlibraryzombie{const_mem_fun_ref_t} \tcode{const_mem_fun_ref_t} \\ +\indexlibraryzombie{const_mem_fun_t} \tcode{const_mem_fun_t} \\ +\indexlibraryzombie{consume_header} \tcode{consume_header} \\ +\indexlibraryzombie{declare_no_pointers} \tcode{declare_no_pointers} \\ +\indexlibraryzombie{declare_reachable} \tcode{declare_reachable} \\ +\columnbreak +\indexlibraryzombie{generate_header} \tcode{generate_header} \\ +\indexlibraryzombie{get_pointer_safety} \tcode{get_pointer_safety} \\ +\indexlibraryzombie{get_temporary_buffer} \tcode{get_temporary_buffer} \\ +\indexlibraryzombie{get_unexpected} \tcode{get_unexpected} \\ +\indexlibraryzombie{gets} \tcode{gets} \\ +\indexlibraryzombie{is_literal_type} \tcode{is_literal_type} \\ +\indexlibraryzombie{is_literal_type_v} \tcode{is_literal_type_v} \\ +\indexlibraryzombie{istrstream} \tcode{istrstream} \\ +\indexlibraryzombie{little_endian} \tcode{little_endian} \\ +\indexlibraryzombie{mem_fun1_ref_t} \tcode{mem_fun1_ref_t} \\ +\indexlibraryzombie{mem_fun1_t} \tcode{mem_fun1_t} \\ +\indexlibraryzombie{mem_fun_ref_t} \tcode{mem_fun_ref_t} \\ +\indexlibraryzombie{mem_fun_ref} \tcode{mem_fun_ref} \\ +\indexlibraryzombie{mem_fun_t} \tcode{mem_fun_t} \\ +\indexlibraryzombie{mem_fun} \tcode{mem_fun} \\ +\indexlibraryzombie{not1} \tcode{not1} \\ +\indexlibraryzombie{not2} \tcode{not2} \\ +\indexlibraryzombie{ostrstream} \tcode{ostrstream} \\ +\indexlibraryzombie{pointer_safety} \tcode{pointer_safety} \\ +\columnbreak +\indexlibraryzombie{pointer_to_binary_function} \tcode{pointer_to_binary_function} \\ +\indexlibraryzombie{pointer_to_unary_function} \tcode{pointer_to_unary_function} \\ +\indexlibraryzombie{ptr_fun} \tcode{ptr_fun} \\ +\indexlibraryzombie{random_shuffle} \tcode{random_shuffle} \\ +\indexlibraryzombie{raw_storage_iterator} \tcode{raw_storage_iterator} \\ +\indexlibraryzombie{result_of} \tcode{result_of} \\ +\indexlibraryzombie{result_of_t} \tcode{result_of_t} \\ +\indexlibraryzombie{return_temporary_buffer} \tcode{return_temporary_buffer} \\ +\indexlibraryzombie{set_unexpected} \tcode{set_unexpected} \\ +\indexlibraryzombie{strstream} \tcode{strstream} \\ +\indexlibraryzombie{strstreambuf} \tcode{strstreambuf} \\ +\indexlibraryzombie{unary_function} \tcode{unary_function} \\ +\indexlibraryzombie{unary_negate} \tcode{unary_negate} \\ +\indexlibraryzombie{uncaught_exception} \tcode{uncaught_exception} \\ +\indexlibraryzombie{undeclare_no_pointers} \tcode{undeclare_no_pointers} \\ +\indexlibraryzombie{undeclare_reachable} \tcode{undeclare_reachable} \\ +\indexlibraryzombie{unexpected_handler} \tcode{unexpected_handler} \\ +\indexlibraryzombie{wbuffer_convert} \tcode{wbuffer_convert} \\ +\indexlibraryzombie{wstring_convert} \tcode{wstring_convert} \\ +\end{multicolfloattable} + \pnum -The following names are reserved as members for previous standardization, -and may not be used as a name for object-like macros in portable code: -\begin{itemize} -\item \indexlibraryzombie{argument_type} \tcode{argument_type}, -\item \indexlibraryzombie{first_argument_type} \tcode{first_argument_type}, -\item \indexlibraryzombie{io_state} \tcode{io_state}, -\item \indexlibraryzombie{op} \tcode{op}, -\item \indexlibraryzombie{open_mode} \tcode{open_mode}, -\item \indexlibraryzombie{preferred} \tcode{preferred}, -\item \indexlibraryzombie{second_argument_type} \tcode{second_argument_type}, -\item \indexlibraryzombie{seek_dir} \tcode{seek_dir}, and -\item \indexlibraryzombie{strict} \tcode{strict}. -\end{itemize} +The names shown in \tref{zombie.names.objmacro} are reserved as members for +previous standardization, and may not be used as a name for object-like macros +in portable code: + +\begin{multicolfloattable}{Zombie object-like macros}{zombie.names.objmacro} +{lll} +\indexlibraryzombie{argument_type} \tcode{argument_type} \\ +\indexlibraryzombie{first_argument_type} \tcode{first_argument_type} \\ +\indexlibraryzombie{io_state} \tcode{io_state} \\ +\columnbreak +\indexlibraryzombie{op} \tcode{op} \\ +\indexlibraryzombie{open_mode} \tcode{open_mode} \\ +\indexlibraryzombie{preferred} \tcode{preferred} \\ +\columnbreak +\indexlibraryzombie{second_argument_type} \tcode{second_argument_type} \\ +\indexlibraryzombie{seek_dir} \tcode{seek_dir} \\ +\indexlibraryzombie{strict} \tcode{strict} \\ +\end{multicolfloattable} + \pnum -The name \indexlibraryzombie{stossc} \tcode{stossc} is reserved as a -member function for previous standardization, and may not be used as a name for -function-like macros in portable code. +The names shown in \tref{zombie.names.fnmacro} are reserved as member functions +for previous standardization, and may not be used as a name for function-like +macros in portable code: + +\begin{multicolfloattable}{Zombie function-like macros}{zombie.names.fnmacro} +{llllll} +\indexlibraryzombie{converted} \tcode{converted} \\ +\columnbreak +\indexlibraryzombie{freeze} \tcode{freeze} \\ +\columnbreak +\indexlibraryzombie{from_bytes} \tcode{from_bytes} \\ +\columnbreak +\indexlibraryzombie{pcount} \tcode{pcount} \\ +\columnbreak +\indexlibraryzombie{stossc} \tcode{stossc} \\ +\columnbreak +\indexlibraryzombie{to_bytes} \tcode{to_bytes} \\ +\end{multicolfloattable} \pnum -The header names -\libnoheader{ccomplex}, -\libnoheader{ciso646}, -\libnoheader{codecvt}, -\libnoheader{cstdalign}, -\libnoheader{cstdbool}, and -\libnoheader{ctgmath} -are reserved for previous standardization. +The header names shown in \tref{zombie.names.header} are reserved for previous +standardization: + +\begin{multicolfloattable}{Zombie headers}{zombie.names.header} +{lllll} +\libnoheader{ccomplex} \\ +\libnoheader{ciso646} \\ +\columnbreak +\libnoheader{codecvt} \\ +\libnoheader{cstdalign} \\ +\columnbreak +\libnoheader{cstdbool} \\ +\columnbreak +\libnoheader{ctgmath} \\ +\columnbreak +\libnoheader{strstream} \\ +\end{multicolfloattable} \rSec4[macro.names]{Macro names} @@ -3116,16 +3297,6 @@ \tcode{\#define} or \tcode{\#undef} names declared in any standard library header. -\pnum -\indextext{unit!translation}% -A translation unit shall not \tcode{\#define} or \tcode{\#undef} -names lexically identical -to keywords, -to the identifiers listed in \tref{lex.name.special}, or -to the \grammarterm{attribute-token}{s} described in~\ref{dcl.attr}, -except that the names \tcode{likely} and \tcode{unlikely} may be -defined as function-like macros~\iref{cpp.replace}. - \rSec4[extern.names]{External linkage} \pnum @@ -3243,65 +3414,13 @@ \rSec3[replacement.functions]{Replacement functions} \pnum -\indextext{definition!alternate}% +If a function defined in \ref{\firstlibchapter} through \ref{\lastlibchapter} and \ref{depr} -describe the behavior of numerous functions defined by -the \Cpp{} standard library. -Under some circumstances, -\indextext{library!\Cpp{} standard}% -however, certain of these function descriptions also apply to replacement functions defined -in the program. +is specified as replaceable\iref{dcl.fct.def.replace}, +the description of function semantics apply +to both the default version defined by the \Cpp{} standard library and +the replacement function defined by the program. -\pnum -A \Cpp{} program may provide the definition for any of the following -dynamic memory allocation function signatures declared in header -\tcode{}\iref{basic.stc.dynamic,new.syn}: - -\indextext{\idxcode{new}!\idxcode{operator}!replaceable}% -\indexlibrarymember{new}{operator}% -\begin{codeblock} -operator new(std::size_t) -operator new(std::size_t, std::align_val_t) -operator new(std::size_t, const std::nothrow_t&) -operator new(std::size_t, std::align_val_t, const std::nothrow_t&) -\end{codeblock}% -\indextext{\idxcode{delete}!\idxcode{operator}!replaceable}% -\indexlibrarymember{delete}{operator}% -\begin{codeblock} -operator delete(void*) -operator delete(void*, std::size_t) -operator delete(void*, std::align_val_t) -operator delete(void*, std::size_t, std::align_val_t) -operator delete(void*, const std::nothrow_t&) -operator delete(void*, std::align_val_t, const std::nothrow_t&) -\end{codeblock}% -\indextext{\idxcode{new}!\idxcode{operator}!replaceable}% -\indexlibrarymember{new}{operator}% -\begin{codeblock} -operator new[](std::size_t) -operator new[](std::size_t, std::align_val_t) -operator new[](std::size_t, const std::nothrow_t&) -operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) -\end{codeblock}% -\indextext{\idxcode{delete}!\idxcode{operator}!replaceable}% -\indexlibrarymember{delete}{operator}% -\begin{codeblock} -operator delete[](void*) -operator delete[](void*, std::size_t) -operator delete[](void*, std::align_val_t) -operator delete[](void*, std::size_t, std::align_val_t) -operator delete[](void*, const std::nothrow_t&) -operator delete[](void*, std::align_val_t, const std::nothrow_t&) -\end{codeblock} - -\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\iref{basic.def.odr,basic.start}. -\indextext{startup!program}% -The program's declarations shall not be specified as -\keyword{inline}. -No diagnostic is required. \rSec3[handler.functions]{Handler functions} @@ -3341,7 +3460,7 @@ \pnum Calling the \tcode{set_*} and \tcode{get_*} functions shall not incur a data race\iref{intro.races}. -A call to any of the \tcode{set_*} functions shall synchronize with subsequent calls to the same +A call to any of the \tcode{set_*} functions synchronizes with subsequent calls to the same \tcode{set_*} function and to the corresponding \tcode{get_*} function. \rSec3[res.on.functions]{Other functions} @@ -3358,7 +3477,7 @@ \begin{itemize} \item -For replacement functions\iref{new.delete}, if the installed replacement function does not +For replacement functions\iref{replacement.functions}, if the installed replacement function does not implement the semantics of the applicable \required paragraph. @@ -3486,12 +3605,18 @@ Subclause \ref{conforming} describes the constraints upon, and latitude of, implementations of the \Cpp{} standard library. \pnum -An implementation's use of headers is discussed in~\ref{res.on.headers}, its use -of macros in~\ref{res.on.macro.definitions}, non-member functions -in~\ref{global.functions}, member functions in~\ref{member.functions}, data race -avoidance in~\ref{res.on.data.races}, access specifiers -in~\ref{protection.within.classes}, class derivation in~\ref{derivation}, and -exceptions in~\ref{res.on.exception.handling}. +An implementation's use of +\begin{itemize} +\item headers is discussed in~\ref{res.on.headers}, +\item macros in~\ref{res.on.macro.definitions}, +\item non-member functions in~\ref{global.functions}, +\item member functions in~\ref{member.functions}, +\item data race avoidance in~\ref{res.on.data.races}, +\item access specifiers in~\ref{protection.within.classes}, +\item class derivation in~\ref{derivation}, +\item exceptions in~\ref{res.on.exception.handling}, and +\item contract assertions in~\ref{res.contract.assertions}. +\end{itemize} \rSec3[res.on.headers]{Headers} @@ -3711,6 +3836,28 @@ side effects. \end{note} +\rSec3[library.class.props]{Properties of library classes} + +\pnum +Unless explicitly stated otherwise, it is unspecified whether any class +described in \ref{\firstlibchapter} through \ref{\lastlibchapter} and +\ref{depr} is a trivially copyable class, a standard-layout class, or an +implicit-lifetime class\iref{class.prop}. + +\pnum +Unless explicitly stated otherwise, it is unspecified whether any class for +which trivial relocation (i.e., the effects of +\tcode{trivially_relocate}\iref{obj.lifetime}) would be semantically equivalent +to move-construction of the destination object followed by destruction of the +source object is a trivially relocatable class\iref{class.prop}. + +\pnum +Unless explicitly stated otherwise, it is unspecified whether a class \tcode{C} +is a replaceable class\iref{class.prop} if assigning an xvalue \tcode{a} of +type \tcode{C} to an object \tcode{b} of type \tcode{C} is semantically +equivalent to destroying \tcode{b} and then constructing from \tcode{a} in +\tcode{b}'s place. + \rSec3[protection.within.classes]{Protection within classes} \pnum @@ -3772,7 +3919,7 @@ can report a failure by throwing an exception of a type described in its \throws paragraph, or of a type derived from a type named in the \throws paragraph -that would be caught by an exception handler for the base type. +that would be caught by a \grammarterm{handler}\iref{except.handle} for the base type. \pnum Functions from the C standard library shall not throw exceptions% @@ -3796,7 +3943,7 @@ Destructor operations defined in the \Cpp{} standard library shall not throw exceptions. Every destructor in the \Cpp{} standard library shall behave as if it had a -non-throwing exception specification. +non-throwing exception specification\iref{except.spec}. \pnum Functions defined in the @@ -3824,12 +3971,21 @@ for a non-virtual function by adding a non-throwing exception specification. +\rSec3[res.contract.assertions]{Contract assertions} + +\pnum +Unless specified otherwise, +an implementation may check +the specified preconditions and postconditions of a function +in the \Cpp{} standard library using contract +assertions\iref{basic.contract,structure.specifications}. + \rSec3[value.error.codes]{Value of error codes} \pnum Certain functions in the \Cpp{} standard library report errors via a -\tcode{std::error_code}\iref{syserr.errcode.overview} object. That object's -\tcode{category()} member shall return \tcode{std::system_category()} for +\tcode{error_code}\iref{syserr.errcode.overview} object. That object's +\tcode{category()} member shall return \tcode{system_category()} for errors originating from the operating system, or a reference to an \impldef{\tcode{error_category} for errors originating outside the operating system} \tcode{error_category} object for errors originating elsewhere. @@ -3851,7 +4007,7 @@ Objects of types defined in the \Cpp{} standard library may be moved from\iref{class.copy.ctor}. Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall -be placed in a valid but unspecified state. +be placed in a valid but unspecified state\iref{defns.valid}. \pnum An object of a type defined in the \Cpp{} standard library may be diff --git a/source/limits.tex b/source/limits.tex index 60c9dc3b69..bdc1f3deb6 100644 --- a/source/limits.tex +++ b/source/limits.tex @@ -1,22 +1,11 @@ %!TEX root = std.tex -\normannex{implimits}{Implementation quantities} +\infannex{implimits}{Implementation quantities} \pnum -Because computers are finite, \Cpp{} implementations are inevitably -limited in the size of the programs they can successfully process. -Every implementation shall -document those limitations where known. -This documentation may cite fixed limits where they -exist, say how to compute variable limits as a function -of available resources, or say that fixed limits do not exist -or are unknown. - -\pnum -The limits may constrain quantities -that include those described below or others. -The bracketed number following each quantity is recommended -as the minimum for that quantity. -However, these quantities are only guidelines and do not determine compliance. +Implementations can exhibit limitations for various quantities; +some possibilities are presented in the following list. +The bracketed number following each quantity is +a potential minimum value for that quantity. \begin{itemize} \item% Nesting levels of compound statements\iref{stmt.block}, diff --git a/source/locales.tex b/source/locales.tex deleted file mode 100644 index 2d6fe5ce14..0000000000 --- a/source/locales.tex +++ /dev/null @@ -1,5371 +0,0 @@ -%!TEX root = std.tex -\rSec0[localization]{Localization library} - -\rSec1[localization.general]{General} - -\pnum -This Clause describes components that \Cpp{} programs may use to -encapsulate (and therefore be more portable when confronting) -cultural differences. -The locale facility includes -internationalization support for character classification and string collation, -numeric, monetary, and date/time formatting and parsing, and -message retrieval. - -\pnum -The following subclauses describe components for -locales themselves, -the standard facets, and -facilities from the ISO C library, -as summarized in \tref{localization.summary}. - -\begin{libsumtab}{Localization library summary}{localization.summary} -\ref{locales} & Locales & \tcode{} \\ -\ref{locale.categories} & Standard \tcode{locale} categories & \\ \rowsep -\ref{c.locales} & C library locales & \tcode{} \\ \rowsep -\ref{text.encoding} & Text encodings identification & \tcode{} \\ -\end{libsumtab} - -\rSec1[locale.syn]{Header \tcode{} synopsis} - -\indexheader{locale}% -\begin{codeblock} -namespace std { - // \ref{locale}, locale - class locale; - template const Facet& use_facet(const locale&); - template bool has_facet(const locale&) noexcept; - - // \ref{locale.convenience}, convenience interfaces - template bool isspace (charT c, const locale& loc); - template bool isprint (charT c, const locale& loc); - template bool iscntrl (charT c, const locale& loc); - template bool isupper (charT c, const locale& loc); - template bool islower (charT c, const locale& loc); - template bool isalpha (charT c, const locale& loc); - template bool isdigit (charT c, const locale& loc); - template bool ispunct (charT c, const locale& loc); - template bool isxdigit(charT c, const locale& loc); - template bool isalnum (charT c, const locale& loc); - template bool isgraph (charT c, const locale& loc); - template bool isblank (charT c, const locale& loc); - template charT toupper(charT c, const locale& loc); - template charT tolower(charT c, const locale& loc); - - // \ref{category.ctype}, ctype - class ctype_base; - template class ctype; - template<> class ctype; // specialization - template class ctype_byname; - class codecvt_base; - template class codecvt; - template class codecvt_byname; - - // \ref{category.numeric}, numeric - template> - class num_get; - template> - class num_put; - template - class numpunct; - template - class numpunct_byname; - - // \ref{category.collate}, collation - template class collate; - template class collate_byname; - - // \ref{category.time}, date and time - class time_base; - template> - class time_get; - template> - class time_get_byname; - template> - class time_put; - template> - class time_put_byname; - - // \ref{category.monetary}, money - class money_base; - template> - class money_get; - template> - class money_put; - template - class moneypunct; - template - class moneypunct_byname; - - // \ref{category.messages}, message retrieval - class messages_base; - template class messages; - template class messages_byname; -} -\end{codeblock} - -\pnum -The header \libheader{locale} -defines classes and declares functions -that encapsulate and manipulate the information peculiar to a locale. -\begin{footnote} -In this subclause, the type name \tcode{tm} -is an incomplete type that is defined in \libheaderref{ctime}. -\end{footnote} - -\rSec1[locales]{Locales} - -\rSec2[locale]{Class \tcode{locale}} - -\rSec3[locale.general]{General} - -\begin{codeblock} -namespace std { - class locale { - public: - // \ref{locale.types}, types - // \ref{locale.facet}, class \tcode{locale::facet} - class facet; - // \ref{locale.id}, class \tcode{locale::id} - class id; - // \ref{locale.category}, type \tcode{locale::category} - using category = int; - static const category // values assigned here are for exposition only - none = 0, - collate = 0x010, ctype = 0x020, - monetary = 0x040, numeric = 0x080, - time = 0x100, messages = 0x200, - all = collate | ctype | monetary | numeric | time | messages; - - // \ref{locale.cons}, construct/copy/destroy - locale() noexcept; - locale(const locale& other) noexcept; - explicit locale(const char* std_name); - explicit locale(const string& std_name); - locale(const locale& other, const char* std_name, category); - locale(const locale& other, const string& std_name, category); - template locale(const locale& other, Facet* f); - locale(const locale& other, const locale& one, category); - ~locale(); // not virtual - const locale& operator=(const locale& other) noexcept; - - // \ref{locale.members}, locale operations - template locale combine(const locale& other) const; - string name() const; - text_encoding encoding() const; - - bool operator==(const locale& other) const; - - template - bool operator()(const basic_string& s1, - const basic_string& s2) const; - - // \ref{locale.statics}, global locale objects - static locale global(const locale&); - static const locale& classic(); - }; -} -\end{codeblock} - -\pnum -Class \tcode{locale} implements a type-safe polymorphic set of facets, -indexed by facet \textit{type}. -In other words, a facet has a dual role: -in one sense, it's just a class interface; -at the same time, it's an index into a locale's set of facets. - -\pnum -Access to the facets of a \tcode{locale} is via two function templates, -\tcode{use_facet<>} and \tcode{has_facet<>}. - -\pnum -\begin{example} -An iostream \tcode{operator<<} can be implemented as: -\begin{footnote} -Note that in the call to \tcode{put}, -the stream is implicitly converted -to an \tcode{ostreambuf_iterator}. -\end{footnote} - -\begin{codeblock} -template -basic_ostream& -operator<< (basic_ostream& s, Date d) { - typename basic_ostream::sentry cerberos(s); - if (cerberos) { - tm tmbuf; d.extract(tmbuf); - bool failed = - use_facet>>( - s.getloc()).put(s, s, s.fill(), &tmbuf, 'x').failed(); - if (failed) - s.setstate(s.badbit); // can throw - } - return s; -} -\end{codeblock} -\end{example} - -\pnum -In the call to \tcode{use_facet(loc)}, -the type argument chooses a facet, -making available all members of the named type. -If \tcode{Facet} is not present in a locale, -it throws the standard exception \tcode{bad_cast}. -A \Cpp{} program can check if a locale implements a particular facet -with the function template \tcode{has_facet()}. -User-defined facets may be installed in a locale, and -used identically as may standard facets. - -\pnum -\begin{note} -All locale semantics are accessed via -\tcode{use_facet<>} and \tcode{has_facet<>}, -except that: - -\begin{itemize} -\item -A member operator template -\begin{codeblock} -operator()(const basic_string&, const basic_string&) -\end{codeblock} -is provided so that a locale can be used as a predicate argument to -the standard collections, to collate strings. -\item -Convenient global interfaces are provided for -traditional \tcode{ctype} functions such as -\tcode{isdigit()} and \tcode{isspace()}, -so that given a locale object \tcode{loc} -a \Cpp{} program can call \tcode{isspace(c, loc)}. -(This eases upgrading existing extractors\iref{istream.formatted}.) -\end{itemize} -\end{note} - -\pnum -Once a facet reference is obtained from a locale object -by calling \tcode{use_facet<>}, -that reference remains usable, -and the results from member functions of it may be cached and re-used, -as long as some locale object refers to that facet. - -\pnum -In successive calls to a locale facet member function -on a facet object installed in the same locale, -the returned result shall be identical. - -\pnum -A \tcode{locale} constructed -from a name string (such as \tcode{"POSIX"}), or -from parts of two named locales, has a name; -all others do not. -Named locales may be compared for equality; -an unnamed locale is equal only to (copies of) itself. -For an unnamed locale, \tcode{locale::name()} returns the string \tcode{"*"}. - -\pnum -Whether there is -one global locale object for the entire program or -one global locale object per thread -is \impldef{whether locale object is global or per-thread}. -Implementations should provide one global locale object per thread. -If there is a single global locale object for the entire program, -implementations are not required to -avoid data races on it\iref{res.on.data.races}. - -\rSec3[locale.types]{Types} - -\rSec4[locale.category]{Type \tcode{locale::category}} - -\indexlibrarymember{locale}{category}% -\begin{itemdecl} -using category = int; -\end{itemdecl} - -\pnum -\textit{Valid} \tcode{category} values -include the \tcode{locale} member bitmask elements -\tcode{collate}, -\tcode{ctype}, -\tcode{monetary}, -\tcode{numeric}, -\tcode{time}, -and -\tcode{messages}, -each of which represents a single locale category. -In addition, \tcode{locale} member bitmask constant \tcode{none} -is defined as zero and represents no category. -And \tcode{locale} member bitmask constant \tcode{all} -is defined such that the expression -\begin{codeblock} -(collate | ctype | monetary | numeric | time | messages | all) == all -\end{codeblock} -is \tcode{true}, -and represents the union of all categories. -Further, the expression \tcode{(X | Y)}, -where \tcode{X} and \tcode{Y} each represent a single category, -represents the union of the two categories. - -\pnum -\tcode{locale} member functions -expecting a \tcode{category} argument -require one of the \tcode{category} values defined above, or -the union of two or more such values. -Such a \tcode{category} value identifies a set of locale categories. -Each locale category, in turn, identifies a set of locale facets, -including at least those shown in \tref{locale.category.facets}. - -\begin{floattable}{Locale category facets}{locale.category.facets} -{ll} -\topline -\lhdr{Category} & \rhdr{Includes facets} \\ \capsep -collate & \tcode{collate}, \tcode{collate} \\ \rowsep -ctype & \tcode{ctype}, \tcode{ctype} \\ - & \tcode{codecvt} \\ - & \tcode{codecvt} \\ - & \tcode{codecvt} \\ - & \tcode{codecvt} \\ \rowsep -monetary & \tcode{moneypunct}, \tcode{moneypunct} \\ - & \tcode{moneypunct}, \tcode{moneypunct} \\ - & \tcode{money_get}, \tcode{money_get} \\ - & \tcode{money_put}, \tcode{money_put} \\ \rowsep -numeric & \tcode{numpunct}, \tcode{numpunct} \\ - & \tcode{num_get}, \tcode{num_get} \\ - & \tcode{num_put}, \tcode{num_put} \\ \rowsep -time & \tcode{time_get}, \tcode{time_get} \\ - & \tcode{time_put}, \tcode{time_put} \\ \rowsep -messages & \tcode{messages}, \tcode{messages} \\ -\end{floattable} - -\pnum -For any locale \tcode{loc} -either constructed, or returned by \tcode{locale::classic()}, -and any facet \tcode{Facet} shown in \tref{locale.category.facets}, -\tcode{has_facet(loc)} is \tcode{true}. -Each \tcode{locale} member function -which takes a \tcode{locale::category} argument -operates on the corresponding set of facets. - -\pnum -An implementation is required to provide those specializations -for facet templates identified as members of a category, and -for those shown in \tref{locale.spec}. - -\begin{floattable}{Required specializations}{locale.spec} -{ll} -\topline -\lhdr{Category} & \rhdr{Includes facets} \\ \capsep -collate & \tcode{collate_byname}, \tcode{collate_byname} \\ \rowsep -ctype & \tcode{ctype_byname}, \tcode{ctype_byname} \\ - & \tcode{codecvt_byname} \\ - & \tcode{codecvt_byname} \\ - & \tcode{codecvt_byname} \\ - & \tcode{codecvt_byname} \\ \rowsep -monetary & \tcode{moneypunct_byname} \\ - & \tcode{moneypunct_byname} \\ - & \tcode{money_get} \\ - & \tcode{money_put} \\ \rowsep -numeric & \tcode{numpunct_byname}, \tcode{numpunct_byname} \\ - & \tcode{num_get}, \tcode{num_put} \\ \rowsep -time & \tcode{time_get} \\ - & \tcode{time_get_byname} \\ - & \tcode{time_get} \\ - & \tcode{time_get_byname} \\ - & \tcode{time_put} \\ - & \tcode{time_put_byname} \\ - & \tcode{time_put} \\ - & \tcode{time_put_byname} \\ \rowsep -messages & \tcode{messages_byname}, \tcode{messages_byname} \\ -\end{floattable} - - -\pnum -The provided implementation of members of -facets \tcode{num_get} and \tcode{num_put} -calls \tcode{use_fac\-et(l)} only for facet \tcode{F} of -types \tcode{numpunct} and \tcode{ctype}, -and for locale \tcode{l} the value obtained by calling member \tcode{getloc()} -on the \tcode{ios_base\&} argument to these functions. - -\pnum -In declarations of facets, -a template parameter with name \tcode{InputIterator} or \tcode{OutputIterator} -indicates the set of all possible specializations on parameters that meet the -\oldconcept{InputIterator} requirements or -\oldconcept{OutputIterator} requirements, -respectively\iref{iterator.requirements}. -A template parameter with name \tcode{C} represents -the set of types containing \keyword{char}, \keyword{wchar_t}, and any other -\impldef{set of character container types -that iostreams templates can be instantiated for} -character container types\iref{defns.character.container} -that meet the requirements for a character -on which any of the iostream components can be instantiated. -A template parameter with name \tcode{International} -represents the set of all possible specializations on a bool parameter. - -\rSec4[locale.facet]{Class \tcode{locale::facet}} - -\indexlibrarymember{locale}{facet}% -\begin{codeblock} -namespace std { - class locale::facet { - protected: - explicit facet(size_t refs = 0); - virtual ~facet(); - facet(const facet&) = delete; - void operator=(const facet&) = delete; - }; -} -\end{codeblock} - -\pnum -Class \tcode{facet} is the base class for locale feature sets. -A class is a \defn{facet} -if it is publicly derived from another facet, or -if it is a class derived from \tcode{locale::facet} and -contains a publicly accessible declaration as follows: -\begin{footnote} -This is a complete list of requirements; there are no other requirements. -Thus, a facet class need not have a public -copy constructor, assignment, default constructor, destructor, etc. -\end{footnote} -\begin{codeblock} -static ::std::locale::id id; -\end{codeblock} - -\pnum -Template parameters in this Clause -which are required to be facets -are those named \tcode{Facet} in declarations. -A program that passes -a type that is \textit{not} a facet, or -a type that refers to a volatile-qualified facet, -as an (explicit or deduced) template parameter to -a locale function expecting a facet, -is ill-formed. -A const-qualified facet is a valid template argument to -any locale function that expects a \tcode{Facet} template parameter. - -\pnum -The \tcode{refs} argument to the constructor is used for lifetime management. -For \tcode{refs == 0}, -the implementation performs \tcode{delete static_cast(f)} -(where \tcode{f} is a point\-er to the facet) -when the last \tcode{locale} object containing the facet is destroyed; -for \tcode{refs == 1}, the implementation never destroys the facet. - -\pnum -Constructors of all facets defined in this Clause -take such an argument and pass it along to -their \tcode{facet} base class constructor. -All one-argument constructors defined in this Clause are \term{explicit}, -preventing their participation in implicit conversions. - -\pnum -For some standard facets a standard ``$\ldots$\tcode{_byname}'' class, -derived from it, implements the virtual function semantics -equivalent to that facet of the locale -constructed by \tcode{locale(const char*)} with the same name. -Each such facet provides a constructor that takes -a \tcode{const char*} argument, which names the locale, and -a \tcode{refs} argument, which is passed to the base class constructor. -Each such facet also provides a constructor that takes -a \tcode{string} argument \tcode{str} and -a \tcode{refs} argument, -which has the same effect as calling the first constructor -with the two arguments \tcode{str.c_str()} and \tcode{refs}. -If there is no ``$\ldots$\tcode{_byname}'' version of a facet, -the base class implements named locale semantics itself -by reference to other facets. - -\rSec4[locale.id]{Class \tcode{locale::id}} - -\indexlibrarymember{locale}{id}% -\begin{codeblock} -namespace std { - class locale::id { - public: - id(); - void operator=(const id&) = delete; - id(const id&) = delete; - }; -} -\end{codeblock} - -\pnum -The class \tcode{locale::id} provides -identification of a locale facet interface, -used as an index for lookup and to encapsulate initialization. - -\pnum -\begin{note} -Because facets are used by iostreams, -potentially while static constructors are running, -their initialization cannot depend on programmed static initialization. -One initialization strategy is for \tcode{locale} -to initialize each facet's \tcode{id} member -the first time an instance of the facet is installed into a locale. -This depends only on static storage being zero -before constructors run\iref{basic.start.static}. -\end{note} - -\rSec3[locale.cons]{Constructors and destructor} - -\indexlibraryctor{locale}% -\begin{itemdecl} -locale() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs a copy of the argument last passed to -\tcode{locale::global(locale\&)}, -if it has been called; -else, the resulting facets have virtual function semantics identical to -those of \tcode{locale::classic()}. -\begin{note} -This constructor yields a copy of the current global locale. -It is commonly used as a default argument for -function parameters of type \tcode{const locale\&}. -\end{note} -\end{itemdescr} - -\indexlibraryctor{locale}% -\begin{itemdecl} -explicit locale(const char* std_name); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs a locale using standard C locale names, e.g., \tcode{"POSIX"}. -The resulting locale implements semantics defined to be associated -with that name. - -\pnum -\throws -\tcode{runtime_error} if the argument is not valid, or is null. - -\pnum -\remarks -The set of valid string argument values is -\tcode{"C"}, \tcode{""}, and any \impldef{locale names} values. -\end{itemdescr} - -\indexlibraryctor{locale}% -\begin{itemdecl} -explicit locale(const string& std_name); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{locale(std_name.c_str())}. -\end{itemdescr} - -\indexlibraryctor{locale}% -\begin{itemdecl} -locale(const locale& other, const char* std_name, category cats); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{cats} is a valid \tcode{category} value\iref{locale.category}. - -\pnum -\effects -Constructs a locale as a copy of \tcode{other} -except for the facets identified by the \tcode{category} argument, -which instead implement the same semantics as \tcode{locale(std_name)}. - -\pnum -\throws -\tcode{runtime_error} if the second argument is not valid, or is null. - -\pnum -\remarks -The locale has a name if and only if \tcode{other} has a name. -\end{itemdescr} - -\indexlibraryctor{locale}% -\begin{itemdecl} -locale(const locale& other, const string& std_name, category cats); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{locale(other, std_name.c_str(), cats)}. -\end{itemdescr} - -\indexlibraryctor{locale}% -\begin{itemdecl} -template locale(const locale& other, Facet* f); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs a locale incorporating all facets from the first argument -except that of type \tcode{Facet}, -and installs the second argument as the remaining facet. -If \tcode{f} is null, the resulting object is a copy of \tcode{other}. - -\pnum -\remarks -If \tcode{f} is null, -the resulting locale has the same name as \tcode{other}. -Otherwise, the resulting locale has no name. -\end{itemdescr} - -\indexlibraryctor{locale}% -\begin{itemdecl} -locale(const locale& other, const locale& one, category cats); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{cats} is a valid \tcode{category} value. - -\pnum -\effects -Constructs a locale incorporating all facets from the first argument -except those that implement \tcode{cats}, -which are instead incorporated from the second argument. - -\pnum -\remarks -If \tcode{cats} is equal to \tcode{locale::none}, -the resulting locale has a name if and only if the first argument has a name. -Otherwise, the resulting locale has a name if and only if -the first two arguments both have names. -\end{itemdescr} - -\indexlibrarymember{operator=}{locale}% -\begin{itemdecl} -const locale& operator=(const locale& other) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Creates a copy of \tcode{other}, replacing the current value. - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\rSec3[locale.members]{Members} - -\indexlibrarymember{locale}{combine}% -\begin{itemdecl} -template locale combine(const locale& other) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs a locale incorporating all facets from \tcode{*this} -except for that one facet of \tcode{other} that is identified by \tcode{Facet}. - -\pnum -\returns -The newly created locale. - -\pnum -\throws -\tcode{runtime_error} if \tcode{has_facet(other)} is \tcode{false}. - -\pnum -\remarks -The resulting locale has no name. -\end{itemdescr} - -\indexlibrarymember{locale}{name}% -\begin{itemdecl} -string name() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The name of \tcode{*this}, if it has one; -otherwise, the string \tcode{"*"}. -\end{itemdescr} - -\indexlibrarymember{locale}{encoding}% -\begin{itemdecl} -text_encoding encoding() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{CHAR_BIT == 8} is \tcode{true}. - -\pnum -\returns -A \tcode{text_encoding} object representing -the implementation-defined encoding scheme -associated with the locale \tcode{*this}. -\end{itemdescr} - -\rSec3[locale.operators]{Operators} - -\indexlibrarymember{locale}{operator==}% -\begin{itemdecl} -bool operator==(const locale& other) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if -both arguments are the same locale, or -one is a copy of the other, or -each has a name and the names are identical; -\tcode{false} otherwise. -\end{itemdescr} - -\indexlibrarymember{locale}{operator()}% -\begin{itemdecl} -template - bool operator()(const basic_string& s1, - const basic_string& s2) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Compares two strings according to the \tcode{collate} facet. - -\pnum -\returns -\begin{codeblock} -use_facet>(*this).compare(s1.data(), s1.data() + s1.size(), - s2.data(), s2.data() + s2.size()) < 0 -\end{codeblock} - -\pnum -\remarks -This member operator template (and therefore \tcode{locale} itself) -meets the requirements for -a comparator predicate template argument\iref{algorithms} applied to strings. - -\pnum -\begin{example} -A vector of strings \tcode{v} -can be collated according to collation rules in locale \tcode{loc} -simply by\iref{alg.sort,vector}: - -\begin{codeblock} -std::sort(v.begin(), v.end(), loc); -\end{codeblock} -\end{example} -\end{itemdescr} - -\rSec3[locale.statics]{Static members} - -\indexlibrarymember{locale}{global}% -\begin{itemdecl} -static locale global(const locale& loc); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Sets the global locale to its argument. -Causes future calls to the constructor \tcode{locale()} -to return a copy of the argument. -If the argument has a name, does -\begin{codeblock} -setlocale(LC_ALL, loc.name().c_str()); -\end{codeblock} -otherwise, the effect on the C locale, if any, is -\impldef{effect on C locale of calling \tcode{locale::global}}. - -\pnum -\returns -The previous value of \tcode{locale()}. - -\pnum -\remarks -No library function other than \tcode{locale::global()} -affects the value returned by \tcode{locale()}. -\begin{note} -See~\ref{c.locales} for data race considerations -when \tcode{setlocale} is invoked. -\end{note} -\end{itemdescr} - -\indexlibrarymember{locale}{classic}% -\begin{itemdecl} -static const locale& classic(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -The \tcode{"C"} locale. - -\pnum -\returns -A locale that implements the classic \tcode{"C"} locale semantics, -equivalent to the value \tcode{locale("C")}. - -\pnum -\remarks -This locale, its facets, and their member functions, do not change with time. -\end{itemdescr} - -\rSec2[locale.global.templates]{\tcode{locale} globals} - -\indexlibrarymember{locale}{use_facet}% -\begin{itemdecl} -template const Facet& use_facet(const locale& loc); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{Facet} is a facet class -whose definition contains the public static member \tcode{id} -as defined in~\ref{locale.facet}. - -\pnum -\returns -A reference to the corresponding facet of \tcode{loc}, if present. - -\pnum -\throws -\tcode{bad_cast} if \tcode{has_facet(loc)} is \tcode{false}. - -\pnum -\remarks -The reference returned remains valid -at least as long as any copy of \tcode{loc} exists. -\end{itemdescr} - -\indexlibrarymember{locale}{has_facet}% -\begin{itemdecl} -template bool has_facet(const locale& loc) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if the facet requested is present in \tcode{loc}; -otherwise \tcode{false}. -\end{itemdescr} - -\rSec2[locale.convenience]{Convenience interfaces} - -\rSec3[classification]{Character classification} - -\indexlibraryglobal{isspace}% -\indexlibraryglobal{isprint}% -\indexlibraryglobal{iscntrl}% -\indexlibraryglobal{isupper}% -\indexlibraryglobal{islower}% -\indexlibraryglobal{isalpha}% -\indexlibraryglobal{isdigit}% -\indexlibraryglobal{ispunct}% -\indexlibraryglobal{isxdigit}% -\indexlibraryglobal{isalnum}% -\indexlibraryglobal{isgraph}% -\indexlibraryglobal{isblank}% -\begin{itemdecl} -template bool isspace (charT c, const locale& loc); -template bool isprint (charT c, const locale& loc); -template bool iscntrl (charT c, const locale& loc); -template bool isupper (charT c, const locale& loc); -template bool islower (charT c, const locale& loc); -template bool isalpha (charT c, const locale& loc); -template bool isdigit (charT c, const locale& loc); -template bool ispunct (charT c, const locale& loc); -template bool isxdigit(charT c, const locale& loc); -template bool isalnum (charT c, const locale& loc); -template bool isgraph (charT c, const locale& loc); -template bool isblank (charT c, const locale& loc); -\end{itemdecl} - -\pnum -Each of these functions \tcode{is\placeholder{F}} -returns the result of the expression: -\begin{codeblock} -use_facet>(loc).is(ctype_base::@\placeholder{F}@, c) -\end{codeblock} -where \tcode{\placeholder{F}} is the \tcode{ctype_base::mask} value -corresponding to that function\iref{category.ctype}. -\begin{footnote} -When used in a loop, -it is faster to cache the \tcode{ctype<>} facet and use it directly, or -use the vector form of \tcode{ctype<>::is}. -\end{footnote} - -\rSec3[conversions.character]{Character conversions} - -\indexlibraryglobal{toupper}% -\begin{itemdecl} -template charT toupper(charT c, const locale& loc); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{use_facet>(loc).toupper(c)}. -\end{itemdescr} - -\indexlibraryglobal{tolower}% -\begin{itemdecl} -template charT tolower(charT c, const locale& loc); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{use_facet>(loc).tolower(c)}. -\end{itemdescr} - -\rSec1[locale.categories]{Standard \tcode{locale} categories} - -\rSec2[locale.categories.general]{General} - -\pnum -Each of the standard categories includes a family of facets. -Some of these implement formatting or parsing of a datum, -for use by standard or users' iostream operators \tcode{<<} and \tcode{>>}, -as members \tcode{put()} and \tcode{get()}, respectively. -Each such member function takes an -\indexlibrarymember{flags}{ios_base}% -\tcode{ios_base\&} argument whose members -\indexlibrarymember{flags}{ios_base}% -\tcode{flags()}, -\indexlibrarymember{precision}{ios_base}% -\tcode{precision()}, -and -\indexlibrarymember{width}{ios_base}% -\tcode{width()}, -specify the format of the corresponding datum\iref{ios.base}. -Those functions which need to use other facets call its member \tcode{getloc()} -to retrieve the locale imbued there. -Formatting facets use the character argument \tcode{fill} -to fill out the specified width where necessary. - -\pnum -The \tcode{put()} members make no provision for error reporting. -(Any failures of the OutputIterator argument can be extracted from -the returned iterator.) -The \tcode{get()} members take an \tcode{ios_base::iostate\&} argument -whose value they ignore, -but set to \tcode{ios_base::failbit} in case of a parse error. - -\pnum -Within subclause \ref{locale.categories} it is unspecified whether -one virtual function calls another virtual function. - -\rSec2[category.ctype]{The \tcode{ctype} category} - -\rSec3[category.ctype.general]{General} - -\indexlibraryglobal{ctype_base}% -\begin{codeblock} -namespace std { - class ctype_base { - public: - using mask = @\seebelow@; - - // numeric values are for exposition only. - static const mask space = 1 << 0; - static const mask print = 1 << 1; - static const mask cntrl = 1 << 2; - static const mask upper = 1 << 3; - static const mask lower = 1 << 4; - static const mask alpha = 1 << 5; - static const mask digit = 1 << 6; - static const mask punct = 1 << 7; - static const mask xdigit = 1 << 8; - static const mask blank = 1 << 9; - static const mask alnum = alpha | digit; - static const mask graph = alnum | punct; - }; -} -\end{codeblock} - -\pnum -The type \tcode{mask} is a bitmask type\iref{bitmask.types}. - -\rSec3[locale.ctype]{Class template \tcode{ctype}} - -\rSec4[locale.ctype.general]{General} - -\indexlibraryglobal{ctype}% -\begin{codeblock} -namespace std { - template - class ctype : public locale::facet, public ctype_base { - public: - using char_type = charT; - - explicit ctype(size_t refs = 0); - - bool is(mask m, charT c) const; - const charT* is(const charT* low, const charT* high, mask* vec) const; - const charT* scan_is(mask m, const charT* low, const charT* high) const; - const charT* scan_not(mask m, const charT* low, const charT* high) const; - charT toupper(charT c) const; - const charT* toupper(charT* low, const charT* high) const; - charT tolower(charT c) const; - const charT* tolower(charT* low, const charT* high) const; - - charT widen(char c) const; - const char* widen(const char* low, const char* high, charT* to) const; - char narrow(charT c, char dfault) const; - const charT* narrow(const charT* low, const charT* high, char dfault, char* to) const; - - static locale::id id; - - protected: - ~ctype(); - virtual bool do_is(mask m, charT c) const; - virtual const charT* do_is(const charT* low, const charT* high, mask* vec) const; - virtual const charT* do_scan_is(mask m, const charT* low, const charT* high) const; - virtual const charT* do_scan_not(mask m, const charT* low, const charT* high) const; - virtual charT do_toupper(charT) const; - virtual const charT* do_toupper(charT* low, const charT* high) const; - virtual charT do_tolower(charT) const; - virtual const charT* do_tolower(charT* low, const charT* high) const; - virtual charT do_widen(char) const; - virtual const char* do_widen(const char* low, const char* high, charT* dest) const; - virtual char do_narrow(charT, char dfault) const; - virtual const charT* do_narrow(const charT* low, const charT* high, - char dfault, char* dest) const; - }; -} -\end{codeblock} - -\pnum -Class \tcode{ctype} encapsulates the C library \libheader{cctype} features. -\tcode{istream} members are required to use \tcode{ctype<>} -for character classing during input parsing. - -\pnum -The specializations -required in \tref{locale.category.facets}\iref{locale.category}, -namely \tcode{ctype} and \tcode{ctype}, -implement character classing appropriate -to the implementation's native character set. - -\rSec4[locale.ctype.members]{\tcode{ctype} members} - -\indexlibrarymember{ctype}{is}% -\begin{itemdecl} -bool is(mask m, charT c) const; -const charT* is(const charT* low, const charT* high, mask* vec) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_is(m, c)} or \tcode{do_is(low, high, vec)}. -\end{itemdescr} - -\indexlibrarymember{ctype}{scan_is}% -\begin{itemdecl} -const charT* scan_is(mask m, const charT* low, const charT* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_scan_is(m, low, high)}. -\end{itemdescr} - -\indexlibrarymember{ctype}{scan_not}% -\begin{itemdecl} -const charT* scan_not(mask m, const charT* low, const charT* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_scan_not(m, low, high)}. -\end{itemdescr} - -\indexlibrarymember{ctype}{toupper}% -\begin{itemdecl} -charT toupper(charT c) const; -const charT* toupper(charT* low, const charT* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_toupper(c)} or \tcode{do_toupper(low, high)}. -\end{itemdescr} - -\indexlibrarymember{ctype}{tolower}% -\begin{itemdecl} -charT tolower(charT c) const; -const charT* tolower(charT* low, const charT* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_tolower(c)} or \tcode{do_tolower(low, high)}. -\end{itemdescr} - -\indexlibrarymember{ctype}{widen}% -\begin{itemdecl} -charT widen(char c) const; -const char* widen(const char* low, const char* high, charT* to) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_widen(c)} or \tcode{do_widen(low, high, to)}. -\end{itemdescr} - -\indexlibrarymember{ctype}{narrow}% -\begin{itemdecl} -char narrow(charT c, char dfault) const; -const charT* narrow(const charT* low, const charT* high, char dfault, char* to) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_narrow(c, dfault)} or \tcode{do_narrow(low, high, dfault, to)}. -\end{itemdescr} - -\rSec4[locale.ctype.virtuals]{\tcode{ctype} virtual functions} - -\indexlibrarymember{ctype}{do_is}% -\begin{itemdecl} -bool do_is(mask m, charT c) const; -const charT* do_is(const charT* low, const charT* high, mask* vec) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Classifies a character or sequence of characters. -For each argument character, -identifies a value \tcode{M} of type \tcode{ctype_base::mask}. -The second form identifies a value \tcode{M} of type \tcode{ctype_base::mask} -for each \tcode{*p} where \tcode{(low <= p \&\& p < high)}, -and places it into \tcode{vec[p - low]}. - -\pnum -\returns -The first form returns the result of the expression \tcode{(M \& m) != 0}; -i.e., \tcode{true} if the character has the characteristics specified. -The second form returns \tcode{high}. -\end{itemdescr} - -\indexlibrarymember{ctype_base}{do_scan_is}% -\begin{itemdecl} -const charT* do_scan_is(mask m, const charT* low, const charT* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Locates a character in a buffer that conforms to a classification \tcode{m}. - -\pnum -\returns -The smallest pointer \tcode{p} in the range \range{low}{high} -such that \tcode{is(m, *p)} would return \tcode{true}; -otherwise, returns \tcode{high}. -\end{itemdescr} - -\indexlibrarymember{ctype}{do_scan_not}% -\begin{itemdecl} -const charT* do_scan_not(mask m, const charT* low, const charT* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Locates a character in a buffer that fails to conform to a classification -\tcode{m}. - -\pnum -\returns -The smallest pointer \tcode{p}, if any, in the range \range{low}{high} -such that \tcode{is(m, *p)} would return \tcode{false}; -otherwise, returns \tcode{high}. -\end{itemdescr} - -\indexlibrarymember{ctype}{do_toupper}% -\begin{itemdecl} -charT do_toupper(charT c) const; -const charT* do_toupper(charT* low, const charT* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Converts a character or characters to upper case. -The second form replaces -each character \tcode{*p} in the range \range{low}{high} -for which a corresponding upper-case character exists, -with that character. - -\pnum -\returns -The first form returns -the corresponding upper-case character if it is known to exist, or -its argument if not. -The second form returns \tcode{high}. -\end{itemdescr} - -\indexlibrarymember{ctype}{do_tolower}% -\begin{itemdecl} -charT do_tolower(charT c) const; -const charT* do_tolower(charT* low, const charT* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Converts a character or characters to lower case. -The second form replaces -each character \tcode{*p} in the range \range{low}{high} -and for which a corresponding lower-case character exists, -with that character. - -\pnum -\returns -The first form returns -the corresponding lower-case character if it is known to exist, or -its argument if not. -The second form returns \tcode{high}. -\end{itemdescr} - -\indexlibrarymember{ctype}{do_widen}% -\begin{itemdecl} -charT do_widen(char c) const; -const char* do_widen(const char* low, const char* high, charT* dest) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Applies the simplest reasonable transformation -from a \tcode{char} value or sequence of \tcode{char} values -to the corresponding \tcode{charT} value or values. -\begin{footnote} -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} -The only characters for which unique transformations are required -are those in the basic character set\iref{lex.charset}. - -For any named \tcode{ctype} category with -a \tcode{ctype} facet \tcode{ctc} and -valid \tcode{ctype_base::mask} value \tcode{M}, -\tcode{(ctc.\brk{}is(M, c) || !is(M, do_widen(c)) )} is \tcode{true}. -\begin{footnote} -In other words, the transformed character is not -a member of any character classification -that \tcode{c} is not also a member of. -\end{footnote} - -The second form transforms -each character \tcode{*p} in the range \range{low}{high}, -placing the result in \tcode{dest[p - low]}. - -\pnum -\returns -The first form returns the transformed value. -The second form returns \tcode{high}. -\end{itemdescr} - -\indexlibrarymember{ctype}{do_narrow}% -\begin{itemdecl} -char do_narrow(charT c, char dfault) const; -const charT* do_narrow(const charT* low, const charT* high, char dfault, char* dest) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Applies the simplest reasonable transformation -from a \tcode{charT} value or sequence of \tcode{charT} values -to the corresponding \tcode{char} value or values. - -For any character \tcode{c} in the basic character set\iref{lex.charset} -the transformation is such that -\begin{codeblock} -do_widen(do_narrow(c, 0)) == c -\end{codeblock} - -For any named \tcode{ctype} category with -a \tcode{ctype} facet \tcode{ctc} however, and -\tcode{ctype_base::mask} value \tcode{M}, -\begin{codeblock} -(is(M, c) || !ctc.is(M, do_narrow(c, dfault)) ) -\end{codeblock} -is \tcode{true} (unless \tcode{do_narrow} returns \tcode{dfault}). -In addition, for any digit character \tcode{c}, -the expression \tcode{(do_narrow(c, dfault) - '0')} -evaluates to the digit value of the character. -The second form transforms -each character \tcode{*p} in the range \range{low}{high}, -placing the result -(or \tcode{dfault} if no simple transformation is readily available) -in \tcode{dest[p - low]}. - -\pnum -\returns -The first form returns the transformed value; -or \tcode{dfault} if no mapping is readily available. -The second form returns \tcode{high}. -\end{itemdescr} - -\rSec3[locale.ctype.byname]{Class template \tcode{ctype_byname}} - -\indexlibraryglobal{ctype_byname}% -\begin{codeblock} -namespace std { - template - class ctype_byname : public ctype { - public: - using mask = typename ctype::mask; - explicit ctype_byname(const char*, size_t refs = 0); - explicit ctype_byname(const string&, size_t refs = 0); - - protected: - ~ctype_byname(); - }; -} -\end{codeblock} - -\rSec3[facet.ctype.special]{\tcode{ctype} specialization} - -\rSec4[facet.ctype.special.general]{General} - -\indexlibraryglobal{ctype}% -\begin{codeblock} -namespace std { - template<> - class ctype : public locale::facet, public ctype_base { - public: - using char_type = char; - - explicit ctype(const mask* tab = nullptr, bool del = false, size_t refs = 0); - - bool is(mask m, char c) const; - const char* is(const char* low, const char* high, mask* vec) const; - const char* scan_is (mask m, const char* low, const char* high) const; - const char* scan_not(mask m, const char* low, const char* high) const; - - char toupper(char c) const; - const char* toupper(char* low, const char* high) const; - char tolower(char c) const; - const char* tolower(char* low, const char* high) const; - - char widen(char c) const; - const char* widen(const char* low, const char* high, char* to) const; - char narrow(char c, char dfault) const; - const char* narrow(const char* low, const char* high, char dfault, char* to) const; - - static locale::id id; - static const size_t table_size = @\impdef@; - - const mask* table() const noexcept; - static const mask* classic_table() noexcept; - - protected: - ~ctype(); - virtual char do_toupper(char c) const; - virtual const char* do_toupper(char* low, const char* high) const; - virtual char do_tolower(char c) const; - virtual const char* do_tolower(char* low, const char* high) const; - - virtual char do_widen(char c) const; - virtual const char* do_widen(const char* low, const char* high, char* to) const; - virtual char do_narrow(char c, char dfault) const; - virtual const char* do_narrow(const char* low, const char* high, - char dfault, char* to) const; - }; -} -\end{codeblock} - -\pnum -A specialization \tcode{ctype} is provided -so that the member functions on type \tcode{char} can be implemented inline. -\begin{footnote} -Only the \tcode{char} (not \tcode{unsigned char} and \tcode{signed char}) -form is provided. -The specialization is specified in the standard, -and not left as an implementation detail, -because it affects the derivation interface for \tcode{ctype}. -\end{footnote} -The \impldef{value of \tcode{ctype::table_size}} value of -member \tcode{table_size} is at least 256. - -\rSec4[facet.ctype.char.dtor]{Destructor} - -\indexlibrarydtor{ctype}% -\begin{itemdecl} -~ctype(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If the constructor's first argument was nonzero, and -its second argument was \tcode{true}, -does \tcode{delete [] table()}. -\end{itemdescr} - -\rSec4[facet.ctype.char.members]{Members} - -\pnum -\indexlibrarymember{ctype}{ctype}% -In the following member descriptions, -for \tcode{unsigned char} values \tcode{v} where \tcode{v >= table_size}, -\tcode{table()[v]} is assumed to have an implementation-specific value -(possibly different for each such value \tcode{v}) -without performing the array lookup. - -\indexlibraryctor{ctype}% -\begin{itemdecl} -explicit ctype(const mask* tbl = nullptr, bool del = false, size_t refs = 0); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -Either \tcode{tbl == nullptr} is \tcode{true} or -\range{tbl}{tbl+table_size} is a valid range. - -\pnum -\effects -Passes its \tcode{refs} argument to its base class constructor. -\end{itemdescr} - -\indexlibrarymember{ctype}{is}% -\begin{itemdecl} -bool is(mask m, char c) const; -const char* is(const char* low, const char* high, mask* vec) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -The second form, for all \tcode{*p} in the range \range{low}{high}, -assigns into \tcode{vec[p - low]} the value \tcode{table()[(unsigned char)*p]}. - -\pnum -\returns -The first form returns \tcode{table()[(unsigned char)c] \& m}; -the second form returns \tcode{high}. -\end{itemdescr} - -\indexlibrarymember{ctype}{scan_is}% -\begin{itemdecl} -const char* scan_is(mask m, const char* low, const char* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The smallest \tcode{p} in the range \range{low}{high} such that -\begin{codeblock} -table()[(unsigned char) *p] & m -\end{codeblock} -is \tcode{true}. -\end{itemdescr} - -\indexlibrarymember{ctype}{scan_not}% -\begin{itemdecl} -const char* scan_not(mask m, const char* low, const char* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The smallest \tcode{p} in the range \range{low}{high} such that -\begin{codeblock} -table()[(unsigned char) *p] & m -\end{codeblock} -is \tcode{false}. -\end{itemdescr} - -\indexlibrarymember{ctype}{toupper}% -\begin{itemdecl} -char toupper(char c) const; -const char* toupper(char* low, const char* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_toupper(c)} or \tcode{do_toupper(low, high)}, respectively. -\end{itemdescr} - -\indexlibrarymember{ctype}{tolower}% -\begin{itemdecl} -char tolower(char c) const; -const char* tolower(char* low, const char* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_tolower(c)} or \tcode{do_tolower(low, high)}, respectively. -\end{itemdescr} - -\indexlibrarymember{ctype}{widen}% -\begin{itemdecl} -char widen(char c) const; -const char* widen(const char* low, const char* high, char* to) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_widen(c)} or -\indexlibraryglobal{do_widen}% -\tcode{do_widen(low, high, to)}, respectively. -\end{itemdescr} - -\indexlibrarymember{ctype}{narrow}% -\begin{itemdecl} -char narrow(char c, char dfault) const; -const char* narrow(const char* low, const char* high, char dfault, char* to) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\indexlibraryglobal{do_narrow}% -\tcode{do_narrow(c, dfault)} or -\indexlibraryglobal{do_narrow}% -\tcode{do_narrow(low, high, dfault, to)}, -respectively. -\end{itemdescr} - -\indexlibrarymember{ctype}{table}% -\begin{itemdecl} -const mask* table() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The first constructor argument, if it was nonzero, -otherwise \tcode{classic_table()}. -\end{itemdescr} - -\rSec4[facet.ctype.char.statics]{Static members} - -\indexlibrarymember{ctype}{classic_table}% -\begin{itemdecl} -static const mask* classic_table() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A pointer to the initial element of an array of size \tcode{table_size} -which represents the classifications of characters in the \tcode{"C"} locale. -\end{itemdescr} - -\rSec4[facet.ctype.char.virtuals]{Virtual functions} - -\indexlibrarymember{ctype}{do_toupper}% -\indexlibrarymember{ctype}{do_tolower}% -\indexlibrarymember{ctype}{do_widen}% -\indexlibrarymember{ctype}{do_narrow}% -\begin{codeblock} -char do_toupper(char) const; -const char* do_toupper(char* low, const char* high) const; -char do_tolower(char) const; -const char* do_tolower(char* low, const char* high) const; - -virtual char do_widen(char c) const; -virtual const char* do_widen(const char* low, const char* high, char* to) const; -virtual char do_narrow(char c, char dfault) const; -virtual const char* do_narrow(const char* low, const char* high, - char dfault, char* to) const; -\end{codeblock} - -\pnum -These functions are described identically as those members of the same name -in the \tcode{ctype} class template\iref{locale.ctype.members}. - -\rSec3[locale.codecvt]{Class template \tcode{codecvt}} - -\rSec4[locale.codecvt.general]{General} - -\indexlibraryglobal{codecvt}% -\begin{codeblock} -namespace std { - class codecvt_base { - public: - enum result { ok, partial, error, noconv }; - }; - - template - class codecvt : public locale::facet, public codecvt_base { - public: - using intern_type = internT; - using extern_type = externT; - using state_type = stateT; - - explicit codecvt(size_t refs = 0); - - result out( - stateT& state, - const internT* from, const internT* from_end, const internT*& from_next, - externT* to, externT* to_end, externT*& to_next) const; - - result unshift( - stateT& state, - externT* to, externT* to_end, externT*& to_next) const; - - result in( - stateT& state, - const externT* from, const externT* from_end, const externT*& from_next, - internT* to, internT* to_end, internT*& to_next) const; - - int encoding() const noexcept; - bool always_noconv() const noexcept; - int length(stateT&, const externT* from, const externT* end, size_t max) const; - int max_length() const noexcept; - - static locale::id id; - - protected: - ~codecvt(); - virtual result do_out( - stateT& state, - const internT* from, const internT* from_end, const internT*& from_next, - externT* to, externT* to_end, externT*& to_next) const; - virtual result do_in( - stateT& state, - const externT* from, const externT* from_end, const externT*& from_next, - internT* to, internT* to_end, internT*& to_next) const; - virtual result do_unshift( - stateT& state, - externT* to, externT* to_end, externT*& to_next) const; - - virtual int do_encoding() const noexcept; - virtual bool do_always_noconv() const noexcept; - virtual int do_length(stateT&, const externT* from, const externT* end, size_t max) const; - virtual int do_max_length() const noexcept; - }; -} -\end{codeblock} - -\pnum -The class \tcode{codecvt} is for use -when converting from one character encoding to another, -such as from wide characters to multibyte characters or -between wide character encodings such as UTF-32 and EUC. - -\pnum -The \tcode{stateT} argument selects -the pair of character encodings being mapped between. - -\pnum -The specializations required -in \tref{locale.category.facets}\iref{locale.category} -convert the implementation-defined native character set. -\tcode{codecvt} implements a degenerate conversion; -it does not convert at all. -\indextext{UTF-8}% -\indextext{UTF-16}% -\indextext{UTF-32}% -The specialization \tcode{codecvt} -converts between the UTF-16 and UTF-8 encoding forms, and -the specialization \tcode{codecvt} -converts between the UTF-32 and UTF-8 encoding forms. -\tcode{codecvt} -converts between the native character sets for ordinary and wide characters. -Specializations on \tcode{mbstate_t} -perform conversion between encodings known to the library implementer. -Other encodings can be converted by specializing on -a program-defined \tcode{stateT} type. -Objects of type \tcode{stateT} can contain any state -that is useful to communicate to or from -the specialized \tcode{do_in} or \tcode{do_out} members. - -\rSec4[locale.codecvt.members]{Members} - -\indexlibrarymember{codecvt}{out}% -\begin{itemdecl} -result out( - stateT& state, - const internT* from, const internT* from_end, const internT*& from_next, - externT* to, externT* to_end, externT*& to_next) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_out(state, from, from_end, from_next, to, to_end, to_next)}. -\end{itemdescr} - -\indexlibrarymember{codecvt}{unshift}% -\begin{itemdecl} -result unshift(stateT& state, externT* to, externT* to_end, externT*& to_next) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_unshift(state, to, to_end, to_next)}. -\end{itemdescr} - -\indexlibrarymember{codecvt}{in}% -\begin{itemdecl} -result in( - stateT& state, - const externT* from, const externT* from_end, const externT*& from_next, - internT* to, internT* to_end, internT*& to_next) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_in(state, from, from_end, from_next, to, to_end, to_next)}. -\end{itemdescr} - -\indexlibrarymember{codecvt}{encoding}% -\begin{itemdecl} -int encoding() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_encoding()}. -\end{itemdescr} - -\indexlibrarymember{codecvt}{always_noconv}% -\begin{itemdecl} -bool always_noconv() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_always_noconv()}. -\end{itemdescr} - -\indexlibrarymember{codecvt}{length}% -\begin{itemdecl} -int length(stateT& state, const externT* from, const externT* from_end, size_t max) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_length(state, from, from_end, max)}. -\end{itemdescr} - -\indexlibrarymember{codecvt}{max_length}% -\begin{itemdecl} -int max_length() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_max_length()}. -\end{itemdescr} - -\rSec4[locale.codecvt.virtuals]{Virtual functions} - -\indexlibrarymember{codecvt}{do_out}% -\indexlibrarymember{codecvt}{do_in}% -\begin{itemdecl} -result do_out( - stateT& state, - const internT* from, const internT* from_end, const internT*& from_next, - externT* to, externT* to_end, externT*& to_next) const; - -result do_in( - stateT& state, - const externT* from, const externT* from_end, const externT*& from_next, - internT* to, internT* to_end, internT*& to_next) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{(from <= from_end \&\& to <= to_end)} is well-defined and \tcode{true}; -\tcode{state} is initialized, if at the beginning of a sequence, -or else is equal to the result of converting -the preceding characters in the sequence. - -\pnum -\effects -Translates characters in the source range \range{from}{from_end}, -placing the results in sequential positions starting at destination \tcode{to}. -Converts no more than \tcode{(from_end - from)} source elements, and -stores no more than \tcode{(to_end - to)} destination elements. - -\pnum -Stops if it encounters a character it cannot convert. -It always leaves the \tcode{from_next} and \tcode{to_next} pointers -pointing one beyond the last element successfully converted. -If returns \tcode{noconv}, -\tcode{internT} and \tcode{externT} are the same type and -the converted sequence is identical to -the input sequence \range{from}{from\textunderscore\nobreak next}. -\tcode{to_next} is set equal to \tcode{to}, -the value of \tcode{state} is unchanged, and -there are no changes to the values in \range{to}{to_end}. - -\pnum -A \tcode{codecvt} facet -that is used by \tcode{basic_filebuf}\iref{file.streams} -shall have the property that if -\begin{codeblock} -do_out(state, from, from_end, from_next, to, to_end, to_next) -\end{codeblock} -would return \tcode{ok}, -where \tcode{from != from_end}, -then -\begin{codeblock} -do_out(state, from, from + 1, from_next, to, to_end, to_next) -\end{codeblock} -shall also return \tcode{ok}, -and that if -\begin{codeblock} -do_in(state, from, from_end, from_next, to, to_end, to_next) -\end{codeblock} -would return \tcode{ok}, -where \tcode{to != to_end}, -then -\begin{codeblock} -do_in(state, from, from_end, from_next, to, to + 1, to_next) -\end{codeblock} -shall also return \tcode{ok}. -\begin{footnote} -Informally, this means that \tcode{basic_filebuf} -assumes that the mappings from internal to external characters is 1 to N: -that a \tcode{codecvt} facet that is used by \tcode{basic_filebuf} -can translate characters one internal character at a time. -\end{footnote} -\begin{note} -As a result of operations on \tcode{state}, -it can return \tcode{ok} or \tcode{partial} and -set \tcode{from_next == from} and \tcode{to_next != to}. -\end{note} - -\pnum -\returns -An enumeration value, as summarized in \tref{locale.codecvt.inout}. - -\begin{floattable}{\tcode{do_in/do_out} result values}{locale.codecvt.inout} -{lp{3in}} -\topline -\lhdr{Value} & \rhdr{Meaning} \\ \capsep -\tcode{ok} & completed the conversion \\ -\tcode{partial} & not all source characters converted \\ -\tcode{error} & -encountered a character in \range{from}{from_end} -that cannot be converted \\ -\tcode{noconv} & -\tcode{internT} and \tcode{externT} are the same type, and input -sequence is identical to converted sequence \\ -\end{floattable} - -A return value of \tcode{partial}, -if \tcode{(from_next == from_end)}, -indicates -that either the destination sequence has not absorbed -all the available destination elements, or -that additional source elements are needed -before another destination element can be produced. - -\pnum -\remarks -Its operations on \tcode{state} are unspecified. -\begin{note} -This argument can be used, for example, -to maintain shift state, -to specify conversion options (such as count only), or -to identify a cache of seek offsets. -\end{note} -\end{itemdescr} - -\indexlibrarymember{codecvt}{do_unshift}% -\begin{itemdecl} -result do_unshift(stateT& state, externT* to, externT* to_end, externT*& to_next) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{(to <= to_end)} is well-defined and \tcode{true}; -\tcode{state} is initialized, if at the beginning of a sequence, -or else is equal to the result of converting -the preceding characters in the sequence. - -\pnum -\effects -Places characters starting at \tcode{to} -that should be appended to terminate a sequence -when the current \tcode{stateT} is given by \tcode{state}. -\begin{footnote} -Typically these will be characters to return the state to \tcode{stateT()}. -\end{footnote} -Stores no more than \tcode{(to_end - to)} destination elements, and -leaves the \tcode{to_next} pointer -pointing one beyond the last element successfully stored. - -\pnum -\returns -An enumeration value, as summarized in \tref{locale.codecvt.unshift}. - -\begin{floattable}{\tcode{do_unshift} result values}{locale.codecvt.unshift} -{lp{.50\hsize}} -\topline -\lhdr{Value} & \rhdr{Meaning} \\ \capsep -\tcode{ok} & completed the sequence \\ -\tcode{partial} & -space for more than \tcode{to_end - to} destination elements was needed -to terminate a sequence given the value of \tcode{state}\\ -\tcode{error} & an unspecified error has occurred \\ -\tcode{noconv} & no termination is needed for this \tcode{state_type} \\ -\end{floattable} -\end{itemdescr} - -\indexlibrarymember{codecvt}{do_encoding}% -\begin{itemdecl} -int do_encoding() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{-1} if the encoding of the \tcode{externT} sequence is state-dependent; -else the constant number of \tcode{externT} characters -needed to produce an internal character; -or \tcode{0} if this number is not a constant. -\begin{footnote} -If \tcode{encoding()} yields \tcode{-1}, -then more than \tcode{max_length()} \tcode{externT} elements -can be consumed when producing a single \tcode{internT} character, and -additional \tcode{externT} elements can appear at the end of a sequence -after those that yield the final \tcode{internT} character. -\end{footnote} -\end{itemdescr} - -\indexlibrarymember{codecvt}{do_always_noconv}% -\begin{itemdecl} -bool do_always_noconv() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if \tcode{do_in()} and \tcode{do_out()} return \tcode{noconv} -for all valid argument values. -\tcode{codecvt} returns \tcode{true}. -\end{itemdescr} - -\indexlibrarymember{codecvt}{do_length}% -\begin{itemdecl} -int do_length(stateT& state, const externT* from, const externT* from_end, size_t max) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{(from <= from_end)} is well-defined and \tcode{true}; -\tcode{state} is initialized, if at the beginning of a sequence, -or else is equal to the result of converting -the preceding characters in the sequence. - -\pnum -\effects -The effect on the \tcode{state} argument is as if -it called \tcode{do_in(state, from, from_end, from, to, to+max, to)} -for \tcode{to} pointing to a buffer of at least \tcode{max} elements. - -\pnum -\returns -\tcode{(from_next-from)} where -\tcode{from_next} is the largest value in the range \crange{from}{from_end} -such that the sequence of values in the range \range{from}{from_next} -represents -\tcode{max} or fewer valid complete characters of type \tcode{internT}. -The specialization \tcode{codecvt}, -returns the lesser of \tcode{max} and \tcode{(from_end-from)}. -\end{itemdescr} - -\indexlibrarymember{codecvt}{do_max_length}% -\begin{itemdecl} -int do_max_length() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The maximum value that \tcode{do_length(state, from, from_end, 1)} can return -for any valid range \range{from}{from_end} -and \tcode{stateT} value \tcode{state}. -The specialization \tcode{codecvt::do_max_length()} -returns 1. -\end{itemdescr} - -\rSec3[locale.codecvt.byname]{Class template \tcode{codecvt_byname}} - -\indexlibraryglobal{codecvt_byname}% -\begin{codeblock} -namespace std { - template - class codecvt_byname : public codecvt { - public: - explicit codecvt_byname(const char*, size_t refs = 0); - explicit codecvt_byname(const string&, size_t refs = 0); - - protected: - ~codecvt_byname(); - }; -} -\end{codeblock} - -\rSec2[category.numeric]{The numeric category} - -\rSec3[category.numeric.general]{General} - -\pnum -The classes \tcode{num_get<>} and \tcode{num_put<>} -handle numeric formatting and parsing. -Virtual functions are provided for several numeric types. -Implementations may (but are not required to) delegate -extraction of smaller types to extractors for larger types. -\begin{footnote} -Parsing \tcode{"-1"} correctly into, e.g., an \tcode{unsigned short} -requires that the corresponding member \tcode{get()} -at least extract the sign before delegating. -\end{footnote} - -\pnum -All specifications of member functions for \tcode{num_put} and \tcode{num_get} -in the subclauses of~\ref{category.numeric} only apply to -the specializations required in Tables~\ref{tab:locale.category.facets} -and~\ref{tab:locale.spec}\iref{locale.category}, namely -\tcode{num_get}, -\tcode{num_get}, -\tcode{num_get}, -\tcode{num_put}, -\tcode{num_put}, and -\tcode{num_put}. -These specializations refer to the \tcode{ios_base\&} argument for -formatting specifications\iref{locale.categories}, -and to its imbued locale for the \tcode{numpunct<>} facet to -identify all numeric punctuation preferences, -and also for the \tcode{ctype<>} facet to perform character classification. - -\pnum -Extractor and inserter members of the standard iostreams use -\tcode{num_get<>} and \tcode{num_put<>} member functions for -formatting and parsing -numeric values\iref{istream.formatted.reqmts,ostream.formatted.reqmts}. - -\rSec3[locale.num.get]{Class template \tcode{num_get}} - -\rSec4[locale.num.get.general]{General} - -\indexlibraryglobal{num_get}% -\begin{codeblock} -namespace std { - template> - class num_get : public locale::facet { - public: - using char_type = charT; - using iter_type = InputIterator; - - explicit num_get(size_t refs = 0); - - iter_type get(iter_type in, iter_type end, ios_base&, - ios_base::iostate& err, bool& v) const; - iter_type get(iter_type in, iter_type end, ios_base&, - ios_base::iostate& err, long& v) const; - iter_type get(iter_type in, iter_type end, ios_base&, - ios_base::iostate& err, long long& v) const; - iter_type get(iter_type in, iter_type end, ios_base&, - ios_base::iostate& err, unsigned short& v) const; - iter_type get(iter_type in, iter_type end, ios_base&, - ios_base::iostate& err, unsigned int& v) const; - iter_type get(iter_type in, iter_type end, ios_base&, - ios_base::iostate& err, unsigned long& v) const; - iter_type get(iter_type in, iter_type end, ios_base&, - ios_base::iostate& err, unsigned long long& v) const; - iter_type get(iter_type in, iter_type end, ios_base&, - ios_base::iostate& err, float& v) const; - iter_type get(iter_type in, iter_type end, ios_base&, - ios_base::iostate& err, double& v) const; - iter_type get(iter_type in, iter_type end, ios_base&, - ios_base::iostate& err, long double& v) const; - iter_type get(iter_type in, iter_type end, ios_base&, - ios_base::iostate& err, void*& v) const; - - static locale::id id; - - protected: - ~num_get(); - virtual iter_type do_get(iter_type, iter_type, ios_base&, - ios_base::iostate& err, bool& v) const; - virtual iter_type do_get(iter_type, iter_type, ios_base&, - ios_base::iostate& err, long& v) const; - virtual iter_type do_get(iter_type, iter_type, ios_base&, - ios_base::iostate& err, long long& v) const; - virtual iter_type do_get(iter_type, iter_type, ios_base&, - ios_base::iostate& err, unsigned short& v) const; - virtual iter_type do_get(iter_type, iter_type, ios_base&, - ios_base::iostate& err, unsigned int& v) const; - virtual iter_type do_get(iter_type, iter_type, ios_base&, - ios_base::iostate& err, unsigned long& v) const; - virtual iter_type do_get(iter_type, iter_type, ios_base&, - ios_base::iostate& err, unsigned long long& v) const; - virtual iter_type do_get(iter_type, iter_type, ios_base&, - ios_base::iostate& err, float& v) const; - virtual iter_type do_get(iter_type, iter_type, ios_base&, - ios_base::iostate& err, double& v) const; - virtual iter_type do_get(iter_type, iter_type, ios_base&, - ios_base::iostate& err, long double& v) const; - virtual iter_type do_get(iter_type, iter_type, ios_base&, - ios_base::iostate& err, void*& v) const; - }; -} -\end{codeblock} - -\pnum -The facet \tcode{num_get} is used to parse numeric values -from an input sequence such as an istream. - -\rSec4[facet.num.get.members]{Members} - -\indexlibrarymember{num_get}{get}% -\begin{itemdecl} -iter_type get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, bool& val) const; -iter_type get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, long& val) const; -iter_type get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, long long& val) const; -iter_type get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, unsigned short& val) const; -iter_type get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, unsigned int& val) const; -iter_type get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, unsigned long& val) const; -iter_type get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, unsigned long long& val) const; -iter_type get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, float& val) const; -iter_type get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, double& val) const; -iter_type get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, long double& val) const; -iter_type get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, void*& val) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_get(in, end, str, err, val)}. -\end{itemdescr} - -\rSec4[facet.num.get.virtuals]{Virtual functions} - -\indexlibrarymember{num_get}{do_get}% -\begin{itemdecl} -iter_type do_get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, long& val) const; -iter_type do_get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, long long& val) const; -iter_type do_get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, unsigned short& val) const; -iter_type do_get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, unsigned int& val) const; -iter_type do_get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, unsigned long& val) const; -iter_type do_get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, unsigned long long& val) const; -iter_type do_get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, float& val) const; -iter_type do_get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, double& val) const; -iter_type do_get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, long double& val) const; -iter_type do_get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, void*& val) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Reads characters from \tcode{in}, -interpreting them according to -\tcode{str.flags()}, -\tcode{use_facet>(loc)}, and -\tcode{use_facet>(loc)}, -where \tcode{loc} is \tcode{str.getloc()}. - -\pnum -The details of this operation occur in three stages - -\begin{itemize} -\item -Stage 1: -Determine a conversion specifier -\item -Stage 2: -Extract characters from \tcode{in} and -determine a corresponding \tcode{char} value for -the format expected by the conversion specification determined in stage 1. -\item -Stage 3: -Store results -\end{itemize} - -\pnum -The details of the stages are presented below. - -\begin{description} -\stage{1} -The function initializes local variables via -\begin{codeblock} -fmtflags flags = str.flags(); -fmtflags basefield = (flags & ios_base::basefield); -fmtflags uppercase = (flags & ios_base::uppercase); -fmtflags boolalpha = (flags & ios_base::boolalpha); -\end{codeblock} - -For conversion to an integral type, -the function determines the integral conversion specifier -as indicated in \tref{facet.num.get.int}. -The table is ordered. -That is, the first line whose condition is true applies. - -\begin{floattable}{Integer conversions}{facet.num.get.int} -{lc} -\topline -\lhdr{State} & \tcode{stdio} equivalent \\ \capsep -\tcode{basefield == oct} & \tcode{\%o} \\ \rowsep -\tcode{basefield == hex} & \tcode{\%X} \\ \rowsep -\tcode{basefield == 0} & \tcode{\%i} \\ \capsep -\tcode{signed} integral type & \tcode{\%d} \\ \rowsep -\tcode{unsigned} integral type & \tcode{\%u} \\ -\end{floattable} - -For conversions to a floating-point type the specifier is \tcode{\%g}. - -For conversions to \tcode{void*} the specifier is \tcode{\%p}. - -A length modifier is added to the conversion specification, if needed, -as indicated in \tref{facet.num.get.length}. - -\begin{floattable}{Length modifier}{facet.num.get.length} -{lc} -\topline -\lhdr{Type} & Length modifier \\ \capsep -\tcode{short} & \tcode{h} \\ \rowsep -\tcode{unsigned short} & \tcode{h} \\ \rowsep -\tcode{long} & \tcode{l} \\ \rowsep -\tcode{unsigned long} & \tcode{l} \\ \rowsep -\tcode{long long} & \tcode{ll} \\ \rowsep -\tcode{unsigned long long} & \tcode{ll} \\ \rowsep -\tcode{double} & \tcode{l} \\ \rowsep -\tcode{long double} & \tcode{L} \\ -\end{floattable} - -\stage{2} -If \tcode{in == end} then stage 2 terminates. -Otherwise a \tcode{charT} is taken from \tcode{in} and -local variables are initialized as if by -\begin{codeblock} -char_type ct = *in; -char c = src[find(atoms, atoms + sizeof(src) - 1, ct) - atoms]; -if (ct == use_facet>(loc).decimal_point()) - c = '.'; -bool discard = - ct == use_facet>(loc).thousands_sep() - && use_facet>(loc).grouping().length() != 0; -\end{codeblock} -where the values \tcode{src} and \tcode{atoms} are defined as if by: -\begin{codeblock} -static const char src[] = "0123456789abcdefpxABCDEFPX+-"; -char_type atoms[sizeof(src)]; -use_facet>(loc).widen(src, src + sizeof(src), atoms); -\end{codeblock} -for this value of \tcode{loc}. - -If \tcode{discard} is \tcode{true}, -then if \tcode{'.'} has not yet been accumulated, -then the position of the character is remembered, -but the character is otherwise ignored. -Otherwise, if \tcode{'.'} has already been accumulated, -the character is discarded and Stage 2 terminates. -If it is not discarded, -then a check is made to determine -if \tcode{c} is allowed as the next character of -an input field of the conversion specifier returned by Stage 1. -If so, it is accumulated. - -If the character is either discarded or accumulated -then \tcode{in} is advanced by \tcode{++in} -and processing returns to the beginning of stage 2. - -\begin{example} -Given an input sequence of \tcode{"0x1a.bp+07p"}, -\begin{itemize} -\item -if the conversion specifier returned by Stage 1 is \tcode{\%d}, -\tcode{"0"} is accumulated; -\item -if the conversion specifier returned by Stage 1 is \tcode{\%i}, -\tcode{"0x1a"} are accumulated; -\item -if the conversion specifier returned by Stage 1 is \tcode{\%g}, -\tcode{"0x1a.bp+07"} are accumulated. -\end{itemize} -In all cases, the remainder is left in the input. -\end{example} - -\stage{3} -The sequence of \tcode{char}{s} accumulated in stage 2 (the field) -is converted to a numeric value by the rules of one of the functions -declared in the header \libheader{cstdlib}: - -\begin{itemize} -\item -For a signed integer value, the function \tcode{strtoll}. -\item -For an unsigned integer value, the function \tcode{strtoull}. -\item -For a \tcode{float} value, the function \tcode{strtof}. -\item -For a \tcode{double} value, the function \tcode{strtod}. -\item -For a \tcode{long double} value, the function \tcode{strtold}. -\end{itemize} - -The numeric value to be stored can be one of: -\begin{itemize} -\item -zero, if the conversion function does not convert the entire field. -\item -the most positive (or negative) representable value, -if the field to be converted to a signed integer type represents a value -too large positive (or negative) to be represented in \tcode{val}. -\item -the most positive representable value, -if the field to be converted to an unsigned integer type represents a value -that cannot be represented in \tcode{val}. -\item -the converted value, otherwise. -\end{itemize} - -The resultant numeric value is stored in \tcode{val}. -If the conversion function does not convert the entire field, or -if the field represents a value outside the range of representable values, -\tcode{ios_base::failbit} is assigned to \tcode{err}. - -\end{description} - -\pnum -Digit grouping is checked. -That is, the positions of discarded -separators are examined for consistency with -\tcode{use_facet>(loc).grouping()}. -If they are not consistent -then \tcode{ios_base::failbit} is assigned to \tcode{err}. - -\pnum -In any case, -if stage 2 processing was terminated by the test for \tcode{in == end} -then \tcode{err |= ios_base::eofbit} is performed. -\end{itemdescr} - -\indexlibrarymember{do_get}{num_get}% -\begin{itemdecl} -iter_type do_get(iter_type in, iter_type end, ios_base& str, - ios_base::iostate& err, bool& val) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If \tcode{(str.flags()\&ios_base::boolalpha) == 0} -then input proceeds as it would for a \tcode{long} -except that if a value is being stored into \tcode{val}, -the value is determined according to the following: -If the value to be stored is 0 then \tcode{false} is stored. -If the value is \tcode{1} then \tcode{true} is stored. -Otherwise \tcode{true} is stored and -\tcode{ios_base::failbit} is assigned to \tcode{err}. - -\pnum -Otherwise target sequences are determined ``as if'' by -calling the members \tcode{falsename()} and \tcode{truename()} of -the facet obtained by \tcode{use_facet>(str.getloc())}. -Successive characters in the range \range{in}{end} (see~\ref{sequence.reqmts}) -are obtained and matched against -corresponding positions in the target sequences -only as necessary to identify a unique match. -The input iterator \tcode{in} is compared to \tcode{end} -only when necessary to obtain a character. -If a target sequence is uniquely matched, -\tcode{val} is set to the corresponding value. -Otherwise \tcode{false} is stored and -\tcode{ios_base::failbit} is assigned to \tcode{err}. - -\pnum -The \tcode{in} iterator is always left pointing one position beyond -the last character successfully matched. -If \tcode{val} is set, then \tcode{err} is set to \tcode{str.goodbit}; -or to \tcode{str.eofbit} if, -when seeking another character to match, -it is found that \tcode{(in == end)}. -If \tcode{val} is not set, then \tcode{err} is set to \tcode{str.failbit}; -or to \tcode{(str.failbit|str.eofbit)} -if the reason for the failure was that \tcode{(in == end)}. -\begin{example} -For targets \tcode{true}: \tcode{"a"} and \tcode{false}: \tcode{"abb"}, -the input sequence \tcode{"a"} yields -\tcode{val == true} and \tcode{err == str.eofbit}; -the input sequence \tcode{"abc"} yields -\tcode{err = str.failbit}, with \tcode{in} ending at the \tcode{'c'} element. -For targets \tcode{true}: \tcode{"1"} and \tcode{false}: \tcode{"0"}, -the input sequence \tcode{"1"} yields -\tcode{val == true} and \tcode{err == str.goodbit}. -For empty targets \tcode{("")}, -any input sequence yields \tcode{err == str.failbit}. -\end{example} - -\pnum -\returns -\tcode{in}. -\end{itemdescr} - -\rSec3[locale.nm.put]{Class template \tcode{num_put}} - -\rSec4[locale.nm.put.general]{General} - -\indexlibraryglobal{num_put}% -\begin{codeblock} -namespace std { - template> - class num_put : public locale::facet { - public: - using char_type = charT; - using iter_type = OutputIterator; - - explicit num_put(size_t refs = 0); - - iter_type put(iter_type s, ios_base& f, char_type fill, bool v) const; - iter_type put(iter_type s, ios_base& f, char_type fill, long v) const; - iter_type put(iter_type s, ios_base& f, char_type fill, long long v) const; - iter_type put(iter_type s, ios_base& f, char_type fill, unsigned long v) const; - iter_type put(iter_type s, ios_base& f, char_type fill, unsigned long long v) const; - iter_type put(iter_type s, ios_base& f, char_type fill, double v) const; - iter_type put(iter_type s, ios_base& f, char_type fill, long double v) const; - iter_type put(iter_type s, ios_base& f, char_type fill, const void* v) const; - - static locale::id id; - - protected: - ~num_put(); - virtual iter_type do_put(iter_type, ios_base&, char_type fill, bool v) const; - virtual iter_type do_put(iter_type, ios_base&, char_type fill, long v) const; - virtual iter_type do_put(iter_type, ios_base&, char_type fill, long long v) const; - virtual iter_type do_put(iter_type, ios_base&, char_type fill, unsigned long) const; - virtual iter_type do_put(iter_type, ios_base&, char_type fill, unsigned long long) const; - virtual iter_type do_put(iter_type, ios_base&, char_type fill, double v) const; - virtual iter_type do_put(iter_type, ios_base&, char_type fill, long double v) const; - virtual iter_type do_put(iter_type, ios_base&, char_type fill, const void* v) const; - }; -} -\end{codeblock} - -\pnum -The facet -\tcode{num_put} -is used to format numeric values to a character sequence such as an ostream. - -\rSec4[facet.num.put.members]{Members} - -\indexlibrarymember{num_put}{put}% -\begin{itemdecl} -iter_type put(iter_type out, ios_base& str, char_type fill, bool val) const; -iter_type put(iter_type out, ios_base& str, char_type fill, long val) const; -iter_type put(iter_type out, ios_base& str, char_type fill, long long val) const; -iter_type put(iter_type out, ios_base& str, char_type fill, unsigned long val) const; -iter_type put(iter_type out, ios_base& str, char_type fill, unsigned long long val) const; -iter_type put(iter_type out, ios_base& str, char_type fill, double val) const; -iter_type put(iter_type out, ios_base& str, char_type fill, long double val) const; -iter_type put(iter_type out, ios_base& str, char_type fill, const void* val) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_put(out, str, fill, val)}. -\end{itemdescr} - -\rSec4[facet.num.put.virtuals]{Virtual functions} - -\indexlibrarymember{num_put}{do_put}% -\begin{itemdecl} -iter_type do_put(iter_type out, ios_base& str, char_type fill, long val) const; -iter_type do_put(iter_type out, ios_base& str, char_type fill, long long val) const; -iter_type do_put(iter_type out, ios_base& str, char_type fill, unsigned long val) const; -iter_type do_put(iter_type out, ios_base& str, char_type fill, unsigned long long val) const; -iter_type do_put(iter_type out, ios_base& str, char_type fill, double val) const; -iter_type do_put(iter_type out, ios_base& str, char_type fill, long double val) const; -iter_type do_put(iter_type out, ios_base& str, char_type fill, const void* val) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Writes characters to the sequence \tcode{out}, -formatting \tcode{val} as desired. -In the following description, \tcode{loc} names a local variable initialized as -\begin{codeblock} -locale loc = str.getloc(); -\end{codeblock} - -\pnum -The details of this operation occur in several stages: - -\begin{itemize} -\item -Stage 1: -Determine a printf conversion specifier \tcode{spec} and -determine the characters -that would be printed by \tcode{printf}\iref{c.files} -given this conversion specifier for -\begin{codeblock} -printf(spec, val) -\end{codeblock} -assuming that the current locale is the \tcode{"C"} locale. -\item -Stage 2: -Adjust the representation by converting -each \tcode{char} determined by stage 1 to a \tcode{charT} -using a conversion and -values returned by members of \tcode{use_facet>(loc)}. -\item -Stage 3: -Determine where padding is required. -\item -Stage 4: -Insert the sequence into the \tcode{out}. -\end{itemize} - -\pnum -Detailed descriptions of each stage follow. - -\pnum -\returns -\tcode{out}. - -\pnum -\begin{description} -\stage{1} -The first action of stage 1 is to determine a conversion specifier. -The tables that describe this determination use the following local variables - -\begin{codeblock} -fmtflags flags = str.flags(); -fmtflags basefield = (flags & (ios_base::basefield)); -fmtflags uppercase = (flags & (ios_base::uppercase)); -fmtflags floatfield = (flags & (ios_base::floatfield)); -fmtflags showpos = (flags & (ios_base::showpos)); -fmtflags showbase = (flags & (ios_base::showbase)); -fmtflags showpoint = (flags & (ios_base::showpoint)); -\end{codeblock} - -All tables used in describing stage 1 are ordered. -That is, the first line whose condition is true applies. -A line without a condition is the default behavior -when none of the earlier lines apply. - -For conversion from an integral type other than a character type, -the function determines the integral conversion specifier -as indicated in \tref{facet.num.put.int}. - -\begin{floattable}{Integer conversions}{facet.num.put.int} -{lc} -\topline -\lhdr{State} & \tcode{stdio} equivalent \\ \capsep -\tcode{basefield == ios_base::oct} & \tcode{\%o} \\ \rowsep -\tcode{(basefield == ios_base::hex) \&\& !uppercase} & \tcode{\%x} \\ \rowsep -\tcode{(basefield == ios_base::hex)} & \tcode{\%X} \\ \rowsep -for a \tcode{signed} integral type & \tcode{\%d} \\ \rowsep -for an \tcode{unsigned} integral type & \tcode{\%u} \\ -\end{floattable} - -For conversion from a floating-point type, -the function determines the floating-point conversion specifier -as indicated in \tref{facet.num.put.fp}. - -\begin{floattable}{Floating-point conversions}{facet.num.put.fp} -{lc} -\topline -\lhdr{State} & \tcode{stdio} equivalent \\ \capsep -\tcode{floatfield == ios_base::fixed} & \tcode{\%f} \\ \rowsep -\tcode{floatfield == ios_base::scientific \&\& !uppercase} & \tcode{\%e} \\ \rowsep -\tcode{floatfield == ios_base::scientific} & \tcode{\%E} \\ \rowsep -\tcode{floatfield == (ios_base::fixed | ios_base::scientific) \&\& !uppercase} & \tcode{\%a} \\ \rowsep -\tcode{floatfield == (ios_base::fixed | ios_base::scientific)} & \tcode{\%A} \\ \rowsep -\tcode{!uppercase} & \tcode{\%g} \\ \rowsep -\textit{otherwise} & \tcode{\%G} \\ -\end{floattable} - -For conversions from an integral or floating-point type -a length modifier is added to the conversion specifier -as indicated in \tref{facet.num.put.length}. - -\begin{floattable}{Length modifier}{facet.num.put.length} -{lc} -\topline -\lhdr{Type} & Length modifier \\ \capsep -\tcode{long} & \tcode{l} \\ \rowsep -\tcode{long long} & \tcode{ll} \\ \rowsep -\tcode{unsigned long} & \tcode{l} \\ \rowsep -\tcode{unsigned long long} & \tcode{ll} \\ \rowsep -\tcode{long double} & \tcode{L} \\ \rowsep -\textit{otherwise} & \textit{none} \\ -\end{floattable} - -The conversion specifier has the following optional additional qualifiers -prepended as indicated in \tref{facet.num.put.conv}. - -\begin{floattable}{Numeric conversions}{facet.num.put.conv} -{llc} -\topline -\lhdr{Type(s)} & \chdr{State} & \tcode{stdio} equivalent \\ \capsep -an integral type & \tcode{showpos} & \tcode{+} \\ - & \tcode{showbase} & \tcode{\#} \\ \rowsep -a floating-point type & \tcode{showpos} & \tcode{+} \\ - & \tcode{showpoint} & \tcode{\#} \\ -\end{floattable} - -For conversion from a floating-point type, -if \tcode{floatfield != (ios_base::fixed | ios_base::\brk{}scientific)}, -\tcode{str.precision()} is specified as precision -in the conversion specification. -Otherwise, no precision is specified. - -For conversion from \tcode{void*} the specifier is \tcode{\%p}. - -The representations at the end of stage 1 consists of the \tcode{char}'s -that would be printed by a call of \tcode{printf(s, val)} -where \tcode{s} is the conversion specifier determined above. - -\stage{2} -Any character \tcode{c} other than a decimal point(.) is converted to -a \tcode{charT} via -\begin{codeblock} -use_facet>(loc).widen(c) -\end{codeblock} - -A local variable \tcode{punct} is initialized via -\begin{codeblock} -const numpunct& punct = use_facet>(loc); -\end{codeblock} - -For arithmetic types, -\tcode{punct.thousands_sep()} characters are inserted into -the sequence as determined by the value returned by \tcode{punct.do_grouping()} -using the method described in~\ref{facet.numpunct.virtuals}. - -Decimal point characters(.) are replaced by \tcode{punct.decimal_point()}. - -\stage{3} -A local variable is initialized as -\begin{codeblock} -fmtflags adjustfield = (flags & (ios_base::adjustfield)); -\end{codeblock} - -The location of any padding -\begin{footnote} -The conversion specification \tcode{\#o} generates a leading \tcode{0} -which is \textit{not} a padding character. -\end{footnote} -is determined according to \tref{facet.num.put.fill}. - -\begin{floattable}{Fill padding}{facet.num.put.fill} -{p{3in}l} -\topline -\lhdr{State} & \rhdr{Location} \\ \capsep -\tcode{adjustfield == ios_base::left} & pad after \\ \rowsep -\tcode{adjustfield == ios_base::right} & pad before \\ \rowsep -\tcode{adjustfield == internal} and a sign occurs in the representation - & pad after the sign \\ \rowsep -\tcode{adjustfield == internal} and representation after stage 1 -began with 0x or 0X & pad after x or X \\ \rowsep -\textit{otherwise} & pad before \\ -\end{floattable} - -If \tcode{str.width()} is nonzero and the number of \tcode{charT}'s -in the sequence after stage 2 is less than \tcode{str.\brk{}width()}, -then enough \tcode{fill} characters are added to the sequence -at the position indicated for padding -to bring the length of the sequence to \tcode{str.width()}. - -\tcode{str.width(0)} is called. - -\stage{4} -The sequence of \tcode{charT}'s at the end of stage 3 are output via -\begin{codeblock} -*out++ = c -\end{codeblock} -\end{description} -\end{itemdescr} - -\indexlibrarymember{do_put}{num_put}% -\begin{itemdecl} -iter_type do_put(iter_type out, ios_base& str, char_type fill, bool val) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -If \tcode{(str.flags() \& ios_base::boolalpha) == 0} -returns \tcode{do_put(out, str, fill,\\(int)val)}, -otherwise obtains a string \tcode{s} as if by -\begin{codeblock} -string_type s = - val ? use_facet>(loc).truename() - : use_facet>(loc).falsename(); -\end{codeblock} -and then inserts each character \tcode{c} of \tcode{s} into \tcode{out} -via \tcode{*out++ = c} -and returns \tcode{out}. -\end{itemdescr} - -\rSec2[facet.numpunct]{The numeric punctuation facet} - -\rSec3[locale.numpunct]{Class template \tcode{numpunct}} - -\rSec4[locale.numpunct.general]{General} - -\indexlibraryglobal{numpunct}% -\begin{codeblock} -namespace std { - template - class numpunct : public locale::facet { - public: - using char_type = charT; - using string_type = basic_string; - - explicit numpunct(size_t refs = 0); - - char_type decimal_point() const; - char_type thousands_sep() const; - string grouping() const; - string_type truename() const; - string_type falsename() const; - - static locale::id id; - - protected: - ~numpunct(); // virtual - virtual char_type do_decimal_point() const; - virtual char_type do_thousands_sep() const; - virtual string do_grouping() const; - virtual string_type do_truename() const; // for \tcode{bool} - virtual string_type do_falsename() const; // for \tcode{bool} - }; -} -\end{codeblock} - -\pnum -\tcode{numpunct<>} specifies numeric punctuation. -The specializations -required in \tref{locale.category.facets}\iref{locale.category}, -namely \tcode{numpunct<\brk{}wchar_t>} and \tcode{numpunct}, -provide classic \tcode{"C"} numeric formats, -i.e., they contain information -equivalent to that contained in the \tcode{"C"} locale or -their wide character counterparts as if obtained by a call to \tcode{widen}. - -% FIXME: For now, keep the locale grammar productions out of the index; -% they are conceptually unrelated to the main C++ grammar. -% Consider renaming these en masse (to locale-* ?) to avoid this problem. -\newcommand{\locnontermdef}[1]{{\BnfNontermshape#1\itcorr}\textnormal{:}} -\newcommand{\locgrammarterm}[1]{\gterm{#1}} - -\pnum -The syntax for number formats is as follows, -where \locgrammarterm{digit} represents the radix set -specified by the \tcode{fmtflags} argument value, and -\locgrammarterm{thousands-sep} and \locgrammarterm{decimal-point} -are the results of corresponding \tcode{numpunct} members. -Integer values have the format: -\begin{ncbnf} -\locnontermdef{intval}\br - \opt{sign} units -\end{ncbnf} -\begin{ncbnf} -\locnontermdef{sign}\br - \terminal{+}\br - \terminal{-} -\end{ncbnf} -\begin{ncbnf} -\locnontermdef{units}\br - digits\br - digits thousands-sep units -\end{ncbnf} -\begin{ncbnf} -\locnontermdef{digits}\br - digit \opt{digits} -\end{ncbnf} -and floating-point values have: -\begin{ncbnf} -\locnontermdef{floatval}\br - \opt{sign} units \opt{fractional} \opt{exponent}\br - \opt{sign} decimal-point digits \opt{exponent} -\end{ncbnf} -\begin{ncbnf} -\locnontermdef{fractional}\br - decimal-point \opt{digits} -\end{ncbnf} -\begin{ncbnf} -\locnontermdef{exponent}\br - e \opt{sign} digits -\end{ncbnf} -\begin{ncbnf} -\locnontermdef{e}\br - \terminal{e}\br - \terminal{E} -\end{ncbnf} -where the number of digits between \locgrammarterm{thousands-sep}{s} -is as specified by \tcode{do_grouping()}. -For parsing, -if the \locgrammarterm{digits} portion contains no thousands-separators, -no grouping constraint is applied. - -\rSec4[facet.numpunct.members]{Members} - -\indexlibrarymember{numpunct}{decimal_point}% -\begin{itemdecl} -char_type decimal_point() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_decimal_point()}. -\end{itemdescr} - -\indexlibrarymember{numpunct}{thousands_sep}% -\begin{itemdecl} -char_type thousands_sep() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_thousands_sep()}. -\end{itemdescr} - -\indexlibrarymember{numpunct}{grouping}% -\begin{itemdecl} -string grouping() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_grouping()}. -\end{itemdescr} - -\indexlibrarymember{numpunct}{truename}% -\indexlibrarymember{numpunct}{falsename}% -\begin{itemdecl} -string_type truename() const; -string_type falsename() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_truename()} -or -\tcode{do_falsename()}, -respectively. -\end{itemdescr} - -\rSec4[facet.numpunct.virtuals]{Virtual functions} - -\indexlibrarymember{numpunct}{do_decimal_point}% -\begin{itemdecl} -char_type do_decimal_point() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A character for use as the decimal radix separator. -The required specializations return \tcode{'.'} or \tcode{L'.'}. -\end{itemdescr} - -\indexlibrarymember{numpunct}{do_thousands_sep}% -\begin{itemdecl} -char_type do_thousands_sep() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A character for use as the digit group separator. -The required specializations return \tcode{','} or \tcode{L','}. -\end{itemdescr} - -\indexlibrarymember{numpunct}{do_grouping}% -\begin{itemdecl} -string do_grouping() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A \tcode{string} \tcode{vec} used as a vector of integer values, -in which each element \tcode{vec[i]} represents the number of digits -\begin{footnote} -Thus, -the string \tcode{"\textbackslash003"} specifies groups of 3 digits each, and -\tcode{"3"} probably indicates groups of 51 (!) digits each, -because 51 is the ASCII value of \tcode{"3"}. -\end{footnote} -in the group at position \tcode{i}, -starting with position 0 as the rightmost group. -If \tcode{vec.size() <= i}, -the number is the same as group \tcode{(i - 1)}; -if \tcode{(i < 0 || vec[i] <= 0 || vec[i] == CHAR_MAX)}, -the size of the digit group is unlimited. - -\pnum -The required specializations return the empty string, indicating no grouping. -\end{itemdescr} - -\indexlibrarymember{numpunct}{do_truename}% -\indexlibrarymember{numpunct}{do_falsename}% -\begin{itemdecl} -string_type do_truename() const; -string_type do_falsename() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A string representing the name of -the boolean value \tcode{true} or \tcode{false}, respectively. - -\pnum -In the base class implementation -these names are \tcode{"true"} and \tcode{"false"}, -or \tcode{L"true"} and \tcode{L"false"}. -\end{itemdescr} - -\rSec3[locale.numpunct.byname]{Class template \tcode{numpunct_byname}} - -\indexlibraryglobal{numpunct_byname}% -\begin{codeblock} -namespace std { - template - class numpunct_byname : public numpunct { - // this class is specialized for \tcode{char} and \keyword{wchar_t}. - public: - using char_type = charT; - using string_type = basic_string; - - explicit numpunct_byname(const char*, size_t refs = 0); - explicit numpunct_byname(const string&, size_t refs = 0); - - protected: - ~numpunct_byname(); - }; -} -\end{codeblock} - -\rSec2[category.collate]{The collate category} - -\rSec3[locale.collate]{Class template \tcode{collate}} - -\rSec4[locale.collate.general]{General} - -\indexlibraryglobal{collate}% -\begin{codeblock} -namespace std { - template - class collate : public locale::facet { - public: - using char_type = charT; - using string_type = basic_string; - - explicit collate(size_t refs = 0); - - int compare(const charT* low1, const charT* high1, - const charT* low2, const charT* high2) const; - string_type transform(const charT* low, const charT* high) const; - long hash(const charT* low, const charT* high) const; - - static locale::id id; - - protected: - ~collate(); - virtual int do_compare(const charT* low1, const charT* high1, - const charT* low2, const charT* high2) const; - virtual string_type do_transform(const charT* low, const charT* high) const; - virtual long do_hash (const charT* low, const charT* high) const; - }; -} -\end{codeblock} - -\pnum -The class \tcode{collate} provides features -for use in the collation (comparison) and hashing of strings. -A locale member function template, \tcode{operator()}, -uses the collate facet to allow a locale to act directly as -the predicate argument for standard algorithms\iref{algorithms} and -containers operating on strings. -The specializations -required in \tref{locale.category.facets}\iref{locale.category}, -namely \tcode{collate} and \tcode{collate}, -apply lexicographical ordering\iref{alg.lex.comparison}. - -\pnum -Each function compares a string of characters \tcode{*p} -in the range \range{low}{high}. - -\rSec4[locale.collate.members]{Members} - -\indexlibrarymember{collate}{compare}% -\begin{itemdecl} -int compare(const charT* low1, const charT* high1, - const charT* low2, const charT* high2) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_compare(low1, high1, low2, high2)}. -\end{itemdescr} - -\indexlibrarymember{collate}{transform}% -\begin{itemdecl} -string_type transform(const charT* low, const charT* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_transform(low, high)}. -\end{itemdescr} - -\indexlibrarymember{collate}{hash}% -\begin{itemdecl} -long hash(const charT* low, const charT* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_hash(low, high)}. -\end{itemdescr} - -\rSec4[locale.collate.virtuals]{Virtual functions} - -\indexlibrarymember{collate}{do_compare}% -\begin{itemdecl} -int do_compare(const charT* low1, const charT* high1, - const charT* low2, const charT* high2) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{1} if the first string is greater than the second, -\tcode{-1} if less, -zero otherwise. -The specializations -required in \tref{locale.category.facets}\iref{locale.category}, -namely \tcode{collate} and \tcode{collate}, -implement a lexicographical comparison\iref{alg.lex.comparison}. -\end{itemdescr} - -\indexlibrarymember{collate}{do_transform}% -\begin{itemdecl} -string_type do_transform(const charT* low, const charT* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A \tcode{basic_string} value that, -compared lexicographically with -the result of calling \tcode{transform()} on another string, -yields the same result as calling \tcode{do_compare()} on the same two strings. -\begin{footnote} -This function is useful when one string is being compared to many other strings. -\end{footnote} -\end{itemdescr} - -\indexlibrarymember{collate}{do_hash}% -\begin{itemdecl} -long do_hash(const charT* low, const charT* high) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -An integer value equal to the result of calling \tcode{hash()} -on any other string for which \tcode{do_compare()} returns 0 (equal) -when passed the two strings. - -\pnum -\recommended -The probability that the result equals that for another string -which does not compare equal should be very small, -approaching \tcode{(1.0/numeric_limits::max())}. -\end{itemdescr} - -\rSec3[locale.collate.byname]{Class template \tcode{collate_byname}} - -\indexlibraryglobal{collate_byname}% -\begin{codeblock} -namespace std { - template - class collate_byname : public collate { - public: - using string_type = basic_string; - - explicit collate_byname(const char*, size_t refs = 0); - explicit collate_byname(const string&, size_t refs = 0); - - protected: - ~collate_byname(); - }; -} -\end{codeblock} - -\rSec2[category.time]{The time category} - -\rSec3[category.time.general]{General} - -\pnum -Templates -\tcode{time_get} and -\tcode{time_put} -provide date and time formatting and parsing. -All specifications of member functions for \tcode{time_put} and \tcode{time_get} -in the subclauses of~\ref{category.time} only apply to the -specializations required in Tables~\ref{tab:locale.category.facets} -and~\ref{tab:locale.spec}\iref{locale.category}. -Their members use their -\tcode{ios_base\&}, \tcode{ios_base::iostate\&}, and \tcode{fill} arguments -as described in~\ref{locale.categories}, -and the \tcode{ctype<>} facet, -to determine formatting details. - -\rSec3[locale.time.get]{Class template \tcode{time_get}} - -\rSec4[locale.time.get.general]{General} - -\indexlibraryglobal{time_get}% -\begin{codeblock} -namespace std { - class time_base { - public: - enum dateorder { no_order, dmy, mdy, ymd, ydm }; - }; - - template> - class time_get : public locale::facet, public time_base { - public: - using char_type = charT; - using iter_type = InputIterator; - - explicit time_get(size_t refs = 0); - - dateorder date_order() const { return do_date_order(); } - iter_type get_time(iter_type s, iter_type end, ios_base& f, - ios_base::iostate& err, tm* t) const; - iter_type get_date(iter_type s, iter_type end, ios_base& f, - ios_base::iostate& err, tm* t) const; - iter_type get_weekday(iter_type s, iter_type end, ios_base& f, - ios_base::iostate& err, tm* t) const; - iter_type get_monthname(iter_type s, iter_type end, ios_base& f, - ios_base::iostate& err, tm* t) const; - iter_type get_year(iter_type s, iter_type end, ios_base& f, - ios_base::iostate& err, tm* t) const; - iter_type get(iter_type s, iter_type end, ios_base& f, - ios_base::iostate& err, tm* t, char format, char modifier = 0) const; - iter_type get(iter_type s, iter_type end, ios_base& f, - ios_base::iostate& err, tm* t, const char_type* fmt, - const char_type* fmtend) const; - - static locale::id id; - - protected: - ~time_get(); - virtual dateorder do_date_order() const; - virtual iter_type do_get_time(iter_type s, iter_type end, ios_base&, - ios_base::iostate& err, tm* t) const; - virtual iter_type do_get_date(iter_type s, iter_type end, ios_base&, - ios_base::iostate& err, tm* t) const; - virtual iter_type do_get_weekday(iter_type s, iter_type end, ios_base&, - ios_base::iostate& err, tm* t) const; - virtual iter_type do_get_monthname(iter_type s, iter_type end, ios_base&, - ios_base::iostate& err, tm* t) const; - virtual iter_type do_get_year(iter_type s, iter_type end, ios_base&, - ios_base::iostate& err, tm* t) const; - virtual iter_type do_get(iter_type s, iter_type end, ios_base& f, - ios_base::iostate& err, tm* t, char format, char modifier) const; - }; -} -\end{codeblock} - -\pnum -\tcode{time_get} is used to parse a character sequence, -extracting components of a time or date into a \tcode{tm} object. -Each \tcode{get} member parses a format as produced by a corresponding format specifier to -\tcode{time_put<>::put}. -If the sequence being parsed matches the correct format, the corresponding -members of the -\tcode{tm} -argument are set to the values used to produce the sequence; otherwise -either an error is reported or unspecified values are assigned. -\begin{footnote} -In -other words, user confirmation is required for reliable parsing of -user-entered dates and times, but machine-generated formats can be -parsed reliably. -This allows parsers to be aggressive about -interpreting user variations on standard formats. -\end{footnote} - -\pnum -If the end iterator is reached during parsing by any of the -\tcode{get()} -member functions, the member sets -\tcode{ios_base::eof\-bit} -in \tcode{err}. - -\rSec4[locale.time.get.members]{Members} - -\indexlibrarymember{time_get}{date_order}% -\begin{itemdecl} -dateorder date_order() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_date_order()}. -\end{itemdescr} - -\indexlibrarymember{time_get}{get_time}% -\begin{itemdecl} -iter_type get_time(iter_type s, iter_type end, ios_base& str, - ios_base::iostate& err, tm* t) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_get_time(s, end, str, err, t)}. -\end{itemdescr} - -\indexlibrarymember{time_get}{get_date}% -\begin{itemdecl} -iter_type get_date(iter_type s, iter_type end, ios_base& str, - ios_base::iostate& err, tm* t) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_get_date(s, end, str, err, t)}. -\end{itemdescr} - -\indexlibrarymember{time_get}{get_weekday}% -\indexlibrarymember{time_get}{get_monthname}% -\begin{itemdecl} -iter_type get_weekday(iter_type s, iter_type end, ios_base& str, - ios_base::iostate& err, tm* t) const; -iter_type get_monthname(iter_type s, iter_type end, ios_base& str, - ios_base::iostate& err, tm* t) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_get_weekday(s, end, str, err, t)} -or -\tcode{do_get_monthname(s, end, str, err, t)}. -\end{itemdescr} - -\indexlibrarymember{time_get}{get_year}% -\begin{itemdecl} -iter_type get_year(iter_type s, iter_type end, ios_base& str, - ios_base::iostate& err, tm* t) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_get_year(s, end, str, err, t)}. -\end{itemdescr} - -\indexlibrarymember{get}{time_get}% -\begin{itemdecl} -iter_type get(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, - tm* t, char format, char modifier = 0) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_get(s, end, f, err, t, format, modifier)}. -\end{itemdescr} - -\indexlibrarymember{get}{time_get}% -\begin{itemdecl} -iter_type get(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, - tm* t, const char_type* fmt, const char_type* fmtend) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\range{fmt}{fmtend} is a valid range. - -\pnum -\effects -The function starts by evaluating \tcode{err = ios_base::goodbit}. -It then enters a loop, -reading zero or more characters from \tcode{s} at each iteration. -Unless otherwise specified below, -the loop terminates when the first of the following conditions holds: - -\begin{itemize} -\item -The expression \tcode{fmt == fmtend} evaluates to \tcode{true}. -\item -The expression \tcode{err == ios_base::goodbit} evaluates to \tcode{false}. -\item -The expression \tcode{s == end} evaluates to \tcode{true}, -in which case -the function evaluates \tcode{err = ios_base::eofbit | ios_base::failbit}. -\item -The next element of \tcode{fmt} is equal to \tcode{'\%'}, -optionally followed by a modifier character, -followed by a conversion specifier character, \tcode{format}, -together forming a conversion specification -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, -the function evaluates \tcode{err = ios_base::failbit}. -Otherwise, -the function evaluates \tcode{s = do_get(s, end, f, err, t, format, modifier)}, -where the value of \tcode{modifier} is \tcode{'\textbackslash0'} -when the optional modifier is absent from the conversion specification. -If \tcode{err == ios_base::goodbit} holds -after the evaluation of the expression, -the function increments \tcode{fmt} -to point just past the end of the conversion specification and -continues looping. - -\item -The expression \tcode{isspace(*fmt, f.getloc())} evaluates to \tcode{true}, -in which case the function first increments \tcode{fmt} until -\tcode{fmt == fmtend || !isspace(*fmt, f.getloc())} evaluates to \tcode{true}, -then advances \tcode{s} -until \tcode{s == end || !isspace(*s, f.getloc())} is \tcode{true}, and -finally resumes looping. - -\item -The next character read from \tcode{s} -matches the element pointed to by \tcode{fmt} in a case-insensitive comparison, -in which case the function evaluates \tcode{++fmt, ++s} and continues looping. -Otherwise, the function evaluates \tcode{err = ios_base::failbit}. -\end{itemize} - -\pnum -\begin{note} -The function uses the \tcode{ctype} facet -installed in \tcode{f}'s locale -to determine valid whitespace characters. -It is unspecified -by what means the function performs case-insensitive comparison or -whether multi-character sequences are considered while doing so. -\end{note} - -\pnum -\returns -\tcode{s}. -\end{itemdescr} - -\rSec4[locale.time.get.virtuals]{Virtual functions} - -\indexlibrarymember{time_get}{do_date_order}% -\begin{itemdecl} -dateorder do_date_order() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -An enumeration value indicating the preferred order of components -for those date formats that are composed of day, month, and year. -\begin{footnote} -This function is intended as a convenience only, for common formats, and -can return \tcode{no_order} in valid locales. -\end{footnote} -Returns \tcode{no_order} if the date format specified by \tcode{'x'} -contains other variable components (e.g., Julian day, week number, week day). -\end{itemdescr} - -\indexlibrarymember{time_get}{do_get_time}% -\begin{itemdecl} -iter_type do_get_time(iter_type s, iter_type end, ios_base& str, - ios_base::iostate& err, tm* t) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Reads characters starting at \tcode{s} -until it has extracted those \tcode{tm} members, and -remaining format characters, -used by \tcode{time_put<>::put} -to produce the format specified by \tcode{"\%H:\%M:\%S"}, -or until it encounters an error or end of sequence. - -\pnum -\returns -An iterator pointing immediately beyond -the last character recognized as possibly part of a valid time. -\end{itemdescr} - -\indexlibrarymember{time_get}{do_get_date}% -\begin{itemdecl} -iter_type do_get_date(iter_type s, iter_type end, ios_base& str, - ios_base::iostate& err, tm* t) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Reads characters starting at \tcode{s} -until it has extracted those \tcode{tm} members and -remaining format characters -used by \tcode{time_put<>::put} -to produce one of the following formats, -or until it encounters an error. -The format depends on the value returned by \tcode{date_order()} -as shown in \tref{locale.time.get.dogetdate}. - -\begin{libtab2}{\tcode{do_get_date} effects}{locale.time.get.dogetdate} -{ll}{\tcode{date_order()}}{Format} -\tcode{no_order} & \tcode{"\%m\%d\%y"} \\ -\tcode{dmy} & \tcode{"\%d\%m\%y"} \\ -\tcode{mdy} & \tcode{"\%m\%d\%y"} \\ -\tcode{ymd} & \tcode{"\%y\%m\%d"} \\ -\tcode{ydm} & \tcode{"\%y\%d\%m"} \\ -\end{libtab2} - -\pnum -An implementation may also accept additional -\impldef{additional formats for \tcode{time_get::do_get_date}} formats. - -\pnum -\returns -An iterator pointing immediately beyond -the last character recognized as possibly part of a valid date. -\end{itemdescr} - -\indexlibrarymember{time_get}{do_get_weekday}% -\indexlibrarymember{time_get}{do_get_monthname}% -\begin{itemdecl} -iter_type do_get_weekday(iter_type s, iter_type end, ios_base& str, - ios_base::iostate& err, tm* t) const; -iter_type do_get_monthname(iter_type s, iter_type end, ios_base& str, - ios_base::iostate& err, tm* t) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Reads characters starting at \tcode{s} -until it has extracted the (perhaps abbreviated) name of a weekday or month. -If it finds an abbreviation -that is followed by characters that can match a full name, -it continues reading until it matches the full name or fails. -It sets the appropriate \tcode{tm} member accordingly. - -\pnum -\returns -An iterator pointing immediately beyond the last character recognized -as part of a valid name. -\end{itemdescr} - -\indexlibrarymember{time_get}{do_get_year}% -\begin{itemdecl} -iter_type do_get_year(iter_type s, iter_type end, ios_base& str, - ios_base::iostate& err, tm* t) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Reads characters starting at \tcode{s} -until it has extracted an unambiguous year identifier. -It is -\impldef{whether \tcode{time_get::do_get_year} accepts two-digit year numbers} -whether two-digit year numbers are accepted, -and (if so) what century they are assumed to lie in. -Sets the \tcode{t->tm_year} member accordingly. - -\pnum -\returns -An iterator pointing immediately beyond -the last character recognized as part of a valid year identifier. -\end{itemdescr} - -\indexlibrarymember{do_get}{time_get}% -\begin{itemdecl} -iter_type do_get(iter_type s, iter_type end, ios_base& f, - ios_base::iostate& err, tm* t, char format, char modifier) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{t} points to an object. - -\pnum -\effects -The function starts by evaluating \tcode{err = ios_base::goodbit}. -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 specification appropriate for -the POSIX function \tcode{strptime}, -formed by concatenating \tcode{'\%'}, -the \tcode{modifier} character, when non-NUL, and -the \tcode{format} character. -When the concatenation fails to yield a complete valid directive -the function leaves the object pointed to by \tcode{t} unchanged and -evaluates \tcode{err |= ios_base::failbit}. -When \tcode{s == end} evaluates to \tcode{true} after reading a character -the function evaluates \tcode{err |= ios_base::eofbit}. - -\pnum -For complex conversion specifications -such as \tcode{\%c}, \tcode{\%x}, or \tcode{\%X}, or -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}. -In such cases the values of those \tcode{tm} members are unspecified -and may be outside their valid range. - -\pnum -\returns -An iterator pointing immediately beyond -the last character recognized as possibly part of -a valid input sequence for the given \tcode{format} and \tcode{modifier}. - -\pnum -\remarks -It is unspecified whether multiple calls to \tcode{do_get()} -with the address of the same \tcode{tm} object -will update the current contents of the object or simply overwrite its members. -Portable programs should zero out the object before invoking the function. -\end{itemdescr} - -\rSec3[locale.time.get.byname]{Class template \tcode{time_get_byname}} - -\indexlibraryglobal{time_get_byname}% -\begin{codeblock} -namespace std { - template> - class time_get_byname : public time_get { - public: - using dateorder = time_base::dateorder; - using iter_type = InputIterator; - - explicit time_get_byname(const char*, size_t refs = 0); - explicit time_get_byname(const string&, size_t refs = 0); - - protected: - ~time_get_byname(); - }; -} -\end{codeblock} - -\rSec3[locale.time.put]{Class template \tcode{time_put}} - -\indexlibraryglobal{time_put}% -\begin{codeblock} -namespace std { - template> - class time_put : public locale::facet { - public: - using char_type = charT; - using iter_type = OutputIterator; - - explicit time_put(size_t refs = 0); - - // the following is implemented in terms of other member functions. - iter_type put(iter_type s, ios_base& f, char_type fill, const tm* tmb, - const charT* pattern, const charT* pat_end) const; - iter_type put(iter_type s, ios_base& f, char_type fill, - const tm* tmb, char format, char modifier = 0) const; - - static locale::id id; - - protected: - ~time_put(); - virtual iter_type do_put(iter_type s, ios_base&, char_type, const tm* t, - char format, char modifier) const; - }; -} -\end{codeblock} - -\rSec4[locale.time.put.members]{Members} - -\indexlibrarymember{time_put}{put}% -\begin{itemdecl} -iter_type put(iter_type s, ios_base& str, char_type fill, const tm* t, - const charT* pattern, const charT* pat_end) const; -iter_type put(iter_type s, ios_base& str, char_type fill, const tm* t, - char format, char modifier = 0) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -The first form steps through the sequence -from \tcode{pattern} to \tcode{pat_end}, -identifying characters that are part of a format sequence. -Each character that is not part of a format sequence -is written to \tcode{s} immediately, and -each format sequence, as it is identified, results in a call to \tcode{do_put}; -thus, format elements and other characters are interleaved in the output -in the order in which they appear in the pattern. -Format sequences are identified by converting each character \tcode{c} to -a \tcode{char} value as if by \tcode{ct.narrow(c, 0)}, -where \tcode{ct} is a reference to \tcode{ctype} -obtained from \tcode{str.getloc()}. -The first character of each sequence is equal to \tcode{'\%'}, -followed by an optional modifier character \tcode{mod} -\begin{footnote} -Although the C programming language defines no modifiers, most vendors do. -\end{footnote} -and a format specifier character \tcode{spec} -as defined for the function \tcode{strftime}. -If no modifier character is present, \tcode{mod} is zero. -For each valid format sequence identified, -calls \tcode{do_put(s, str, fill, t, spec, mod)}. - -\pnum -The second form calls \tcode{do_put(s, str, fill, t, format, modifier)}. - -\pnum -\begin{note} -The \tcode{fill} argument can be used -in the implementation-defined formats or by derivations. -A space character is a reasonable default for this argument. -\end{note} - -\pnum -\returns -An iterator pointing immediately after the last character produced. -\end{itemdescr} - -\rSec4[locale.time.put.virtuals]{Virtual functions} - -\indexlibrarymember{time_put}{do_put}% -\begin{itemdecl} -iter_type do_put(iter_type s, ios_base&, char_type fill, const tm* t, - char format, char modifier) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Formats the contents of the parameter \tcode{t} -into characters placed on the output sequence \tcode{s}. -Formatting is controlled by the parameters \tcode{format} and \tcode{modifier}, -interpreted identically as the format specifiers -in the string argument to the standard library function -\indexlibraryglobal{strftime}% -\tcode{strftime()}, -except that the sequence of characters produced for those specifiers -that are described as depending on the C locale -are instead -\impldef{formatted character sequence generated by \tcode{time_put::do_put} -in C locale}. -\begin{note} -Interpretation of the \tcode{modifier} argument is implementation-defined. -\end{note} - -\pnum -\returns -An iterator pointing immediately after the last character produced. -\begin{note} -The \tcode{fill} argument can be used -in the implementation-defined formats or by derivations. -A space character is a reasonable default for this argument. -\end{note} - -\pnum -\recommended -Interpretation of the \tcode{modifier} should follow POSIX conventions. -Implementations should refer to other standards such as POSIX -for a specification of the character sequences produced for -those specifiers described as depending on the C locale. -\end{itemdescr} - -\rSec3[locale.time.put.byname]{Class template \tcode{time_put_byname}} - -\indexlibraryglobal{time_put_byname}% -\begin{codeblock} -namespace std { - template> - class time_put_byname : public time_put { - public: - using char_type = charT; - using iter_type = OutputIterator; - - explicit time_put_byname(const char*, size_t refs = 0); - explicit time_put_byname(const string&, size_t refs = 0); - - protected: - ~time_put_byname(); - }; -} -\end{codeblock} - -\rSec2[category.monetary]{The monetary category} - -\rSec3[category.monetary.general]{General} - -\pnum -These templates handle monetary formats. -A template parameter indicates -whether local or international monetary formats are to be used. - -\pnum -All specifications of member functions -for \tcode{money_put} and \tcode{money_get} -in the subclauses of~\ref{category.monetary} only apply to -the specializations required in Tables~\ref{tab:locale.category.facets} -and~\ref{tab:locale.spec}\iref{locale.category}. -Their members use their \tcode{ios_base\&}, \tcode{ios_base::io\-state\&}, -and \tcode{fill} arguments as described in~\ref{locale.categories}, and -the \tcode{moneypunct<>} and \tcode{ctype<>} facets, -to determine formatting details. - -\rSec3[locale.money.get]{Class template \tcode{money_get}} - -\indexlibraryglobal{money_get}% -\begin{codeblock} -namespace std { - template> - class money_get : public locale::facet { - public: - using char_type = charT; - using iter_type = InputIterator; - using string_type = basic_string; - - explicit money_get(size_t refs = 0); - - iter_type get(iter_type s, iter_type end, bool intl, - ios_base& f, ios_base::iostate& err, - long double& units) const; - iter_type get(iter_type s, iter_type end, bool intl, - ios_base& f, ios_base::iostate& err, - string_type& digits) const; - - static locale::id id; - - protected: - ~money_get(); - virtual iter_type do_get(iter_type, iter_type, bool, ios_base&, - ios_base::iostate& err, long double& units) const; - virtual iter_type do_get(iter_type, iter_type, bool, ios_base&, - ios_base::iostate& err, string_type& digits) const; - }; -} -\end{codeblock} - -\rSec4[locale.money.get.members]{Members} - -\indexlibrarymember{money_get}{get}% -\begin{itemdecl} -iter_type get(iter_type s, iter_type end, bool intl, ios_base& f, - ios_base::iostate& err, long double& quant) const; -iter_type get(iter_type s, iter_type end, bool intl, ios_base& f, - ios_base::iostate& err, string_type& quant) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_get(s, end, intl, f, err, quant)}. -\end{itemdescr} - -\rSec4[locale.money.get.virtuals]{Virtual functions} - -\indexlibrarymember{money_get}{do_get}% -\begin{itemdecl} -iter_type do_get(iter_type s, iter_type end, bool intl, ios_base& str, - ios_base::iostate& err, long double& units) const; -iter_type do_get(iter_type s, iter_type end, bool intl, ios_base& str, - ios_base::iostate& err, string_type& digits) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Reads characters from \tcode{s} to parse and construct a monetary value -according to the format specified by -a \tcode{moneypunct} facet reference \tcode{mp} -and the character mapping specified by -a \tcode{ctype} facet reference \tcode{ct} -obtained from the locale returned by \tcode{str.getloc()}, and -\tcode{str.flags()}. -If a valid sequence is recognized, does not change \tcode{err}; -otherwise, sets \tcode{err} to \tcode{(err|str.failbit)}, or -\tcode{(err|str.failbit|str.eof\-bit)} if no more characters are available, -and does not change \tcode{units} or \tcode{digits}. -Uses the pattern returned by \tcode{mp.neg_format()} to parse all values. -The result is returned as an integral value stored in \tcode{units} -or as a sequence of digits possibly preceded by a minus sign -(as produced by \tcode{ct.widen(c)} -where \tcode{c} is \tcode{'-'} or -in the range from \tcode{'0'} through \tcode{'9'} (inclusive)) -stored in \tcode{digits}. -\begin{example} -The sequence \tcode{\$1,056.23} in a common United States locale would yield, -for \tcode{units}, \tcode{105623}, or, -for \tcode{digits}, \tcode{"105623"}. -\end{example} -If \tcode{mp.grouping()} indicates that no thousands separators are permitted, -any such characters are not read, and -parsing is terminated at the point where they first appear. -Otherwise, thousands separators are optional; -if present, they are checked for correct placement only after -all format components have been read. - -\pnum -Where \tcode{money_base::space} or \tcode{money_base::none} -appears as the last element in the format pattern, -no whitespace is consumed. -Otherwise, where \tcode{money_base::space} appears in any of -the initial elements of the format pattern, -at least one whitespace character is required. -Where \tcode{money_base::none} appears -in any of the initial elements of the format pattern, -whitespace is allowed but not required. -If \tcode{(str.flags() \& str.showbase)} is \tcode{false}, -the currency symbol is optional and -is consumed only if other characters are needed to complete the format; -otherwise, the currency symbol is required. - -\pnum -If the first character (if any) in -the string \tcode{pos} returned by \tcode{mp.positive_sign()} or -the string \tcode{neg} returned by \tcode{mp.negative_sign()} -is recognized in the position indicated by \tcode{sign} in the format pattern, -it is consumed and -any remaining characters in the string are required -after all the other format components. -\begin{example} -If \tcode{showbase} is off, -then for a \tcode{neg} value of \tcode{"()"} and -a currency symbol of \tcode{"L"}, -in \tcode{"(100 L)"} the \tcode{"L"} is consumed; -but if \tcode{neg} is \tcode{"-"}, -the \tcode{"L"} in \tcode{"-100 L"} is not consumed. -\end{example} -If \tcode{pos} or \tcode{neg} is empty, -the sign component is optional, and -if no sign is detected, -the result is given the sign that corresponds to the source of the empty string. -Otherwise, -the character in the indicated position must match -the first character of \tcode{pos} or \tcode{neg}, -and the result is given the corresponding sign. -If the first character of \tcode{pos} is equal to -the first character of \tcode{neg}, -or if both strings are empty, -the result is given a positive sign. - -\pnum -Digits in the numeric monetary component are extracted and -placed in \tcode{digits}, or into a character buffer \tcode{buf1} -for conversion to produce a value for \tcode{units}, -in the order in which they appear, -preceded by a minus sign if and only if the result is negative. -The value \tcode{units} is produced as if by -\begin{footnote} -The semantics here are different from \tcode{ct.narrow}. -\end{footnote} -\begin{codeblock} -for (int i = 0; i < n; ++i) - buf2[i] = src[find(atoms, atoms+sizeof(src), buf1[i]) - atoms]; -buf2[n] = 0; -sscanf(buf2, "%Lf", &units); -\end{codeblock} -where \tcode{n} is the number of characters placed in \tcode{buf1}, -\tcode{buf2} is a character buffer, and -the values \tcode{src} and \tcode{atoms} are defined as if by -\begin{codeblock} -static const char src[] = "0123456789-"; -charT atoms[sizeof(src)]; -ct.widen(src, src + sizeof(src) - 1, atoms); -\end{codeblock} - -\pnum -\returns -An iterator pointing immediately beyond -the last character recognized as part of a valid monetary quantity. -\end{itemdescr} - -\rSec3[locale.money.put]{Class template \tcode{money_put}} - -\indexlibraryglobal{money_put}% -\begin{codeblock} -namespace std { - template> - class money_put : public locale::facet { - public: - using char_type = charT; - using iter_type = OutputIterator; - using string_type = basic_string; - - explicit money_put(size_t refs = 0); - - iter_type put(iter_type s, bool intl, ios_base& f, - char_type fill, long double units) const; - iter_type put(iter_type s, bool intl, ios_base& f, - char_type fill, const string_type& digits) const; - - static locale::id id; - - protected: - ~money_put(); - virtual iter_type do_put(iter_type, bool, ios_base&, char_type fill, - long double units) const; - virtual iter_type do_put(iter_type, bool, ios_base&, char_type fill, - const string_type& digits) const; - }; -} -\end{codeblock} - -\rSec4[locale.money.put.members]{Members} - -\indexlibrarymember{money_put}{put}% -\begin{itemdecl} -iter_type put(iter_type s, bool intl, ios_base& f, char_type fill, long double quant) const; -iter_type put(iter_type s, bool intl, ios_base& f, char_type fill, const string_type& quant) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_put(s, intl, f, loc, quant)}. -\end{itemdescr} - -\rSec4[locale.money.put.virtuals]{Virtual functions} - -\indexlibrarymember{money_put}{do_put}% -\begin{itemdecl} -iter_type do_put(iter_type s, bool intl, ios_base& str, - char_type fill, long double units) const; -iter_type do_put(iter_type s, bool intl, ios_base& str, - char_type fill, const string_type& digits) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Writes characters to \tcode{s} according to -the format specified by -a \tcode{moneypunct} facet reference \tcode{mp} and -the character mapping specified by -a \tcode{ctype} facet reference \tcode{ct} -obtained from the locale returned by \tcode{str.getloc()}, -and \tcode{str.flags()}. -The argument \tcode{units} is transformed into -a sequence of wide characters as if by -\begin{codeblock} -ct.widen(buf1, buf1 + sprintf(buf1, "%.0Lf", units), buf2) -\end{codeblock} -for character buffers \tcode{buf1} and \tcode{buf2}. -If the first character in \tcode{digits} or \tcode{buf2} -is equal to \tcode{ct.widen('-')}, -then the pattern used for formatting is the result of \tcode{mp.neg_format()}; -otherwise the pattern is the result of \tcode{mp.pos_format()}. -Digit characters are written, -interspersed with any thousands separators and decimal point -specified by the format, -in the order they appear (after the optional leading minus sign) in -\tcode{digits} or \tcode{buf2}. -In \tcode{digits}, -only the optional leading minus sign and -the immediately subsequent digit characters -(as classified according to \tcode{ct}) -are used; -any trailing characters -(including digits appearing after a non-digit character) -are ignored. -Calls \tcode{str.width(0)}. - -\pnum -\returns -An iterator pointing immediately after the last character produced. - -\pnum -\remarks -% issues 22-021, 22-030, 22-034 from 97-0058/N1096, 97-0036/N1074 -The currency symbol is generated -if and only if \tcode{(str.flags() \& str.showbase)} is nonzero. -If the number of characters generated for the specified format -is less than the value returned by \tcode{str.width()} on entry to the function, -then copies of \tcode{fill} are inserted as necessary -to pad to the specified width. -For the value \tcode{af} equal to \tcode{(str.flags() \& str.adjustfield)}, -if \tcode{(af == str.internal)} is \tcode{true}, -the fill characters are placed -where \tcode{none} or \tcode{space} appears in the formatting pattern; -otherwise if \tcode{(af == str.left)} is \tcode{true}, -they are placed after the other characters; -otherwise, they are placed before the other characters. -\begin{note} -It is possible, with some combinations of format patterns and flag values, -to produce output that cannot be parsed using \tcode{num_get<>::get}. -\end{note} -\end{itemdescr} - -\rSec3[locale.moneypunct]{Class template \tcode{moneypunct}} - -\rSec4[locale.moneypunct.general]{General} - -\indexlibraryglobal{moneypunct}% -\begin{codeblock} -namespace std { - class money_base { - public: - enum part { none, space, symbol, sign, value }; - struct pattern { char field[4]; }; - }; - - template - class moneypunct : public locale::facet, public money_base { - public: - using char_type = charT; - using string_type = basic_string; - - explicit moneypunct(size_t refs = 0); - - charT decimal_point() const; - charT thousands_sep() const; - string grouping() const; - string_type curr_symbol() const; - string_type positive_sign() const; - string_type negative_sign() const; - int frac_digits() const; - pattern pos_format() const; - pattern neg_format() const; - - static locale::id id; - static const bool intl = International; - - protected: - ~moneypunct(); - virtual charT do_decimal_point() const; - virtual charT do_thousands_sep() const; - virtual string do_grouping() const; - virtual string_type do_curr_symbol() const; - virtual string_type do_positive_sign() const; - virtual string_type do_negative_sign() const; - virtual int do_frac_digits() const; - virtual pattern do_pos_format() const; - virtual pattern do_neg_format() const; - }; -} -\end{codeblock} - -\pnum -The \tcode{moneypunct<>} facet defines monetary formatting parameters -used by \tcode{money_get<>} and \tcode{money_put<>}. -A monetary format is a sequence of four components, -specified by a \tcode{pattern} value \tcode{p}, -such that the \tcode{part} value \tcode{static_cast(p.field[i])} -determines the $\tcode{i}^\text{th}$ component of the format -\begin{footnote} -An array of \tcode{char}, -rather than an array of \tcode{part}, -is specified for \tcode{pattern::field} purely for efficiency. -\end{footnote} -In the \tcode{field} member of a \tcode{pattern} object, -each value \tcode{symbol}, \tcode{sign}, \tcode{value}, and -either \tcode{space} or \tcode{none} -appears exactly once. -The value \tcode{none}, if present, is not first; -the value \tcode{space}, if present, is neither first nor last. - -\pnum -Where \tcode{none} or \tcode{space} appears, -whitespace is permitted in the format, -except where \tcode{none} appears at the end, -in which case no whitespace is permitted. -The value \tcode{space} indicates that -at least one space is required at that position. -Where \tcode{symbol} appears, -the sequence of characters returned by \tcode{curr_symbol()} is permitted, and -can be required. -Where \tcode{sign} appears, -the first (if any) of the sequence of characters returned by -\tcode{positive_sign()} or \tcode{negative_sign()} -(respectively as the monetary value is non-negative or negative) is required. -Any remaining characters of the sign sequence are required after -all other format components. -Where \tcode{value} appears, the absolute numeric monetary value is required. - -\pnum -The format of the numeric monetary value is a decimal number: -\begin{ncbnf} -\locnontermdef{value}\br - units \opt{fractional}\br - decimal-point digits -\end{ncbnf} -\begin{ncbnf} -\locnontermdef{fractional}\br - decimal-point \opt{digits} -\end{ncbnf} -if \tcode{frac_digits()} returns a positive value, or -\begin{ncbnf} -\locnontermdef{value}\br - units -\end{ncbnf} -otherwise. -The symbol \locgrammarterm{decimal-point} -indicates the character returned by \tcode{decimal_point()}. -The other symbols are defined as follows: - -\begin{ncbnf} -\locnontermdef{units}\br - digits\br - digits thousands-sep units -\end{ncbnf} - -\begin{ncbnf} -\locnontermdef{digits}\br - adigit \opt{digits} -\end{ncbnf} - -In the syntax specification, -the symbol \locgrammarterm{adigit} is any of the values \tcode{ct.widen(c)} -for \tcode{c} in the range \tcode{'0'} through \tcode{'9'} (inclusive) and -\tcode{ct} is a reference of type \tcode{const ctype\&} -obtained as described in the definitions -of \tcode{money_get<>} and \tcode{money_put<>}. -The symbol \locgrammarterm{thousands-sep} -is the character returned by \tcode{thousands_sep()}. -The space character used is the value \tcode{ct.widen(' ')}. -Whitespace characters are those characters \tcode{c} -for which \tcode{ci.is(space, c)} returns \tcode{true}. -The number of digits required after the decimal point (if any) -is exactly the value returned by \tcode{frac_digits()}. - -\pnum -The placement of thousands-separator characters (if any) -is determined by the value returned by \tcode{grouping()}, -defined identically as the member \tcode{numpunct<>::do_grouping()}. - -\rSec4[locale.moneypunct.members]{Members} - -\indexlibrarymember{moneypunct}{decimal_point}% -\indexlibrarymember{moneypunct}{thousands_sep}% -\indexlibrarymember{moneypunct}{grouping}% -\indexlibrarymember{moneypunct}{curr_symbol}% -\indexlibrarymember{moneypunct}{positive_sign}% -\indexlibrarymember{moneypunct}{negative_sign}% -\indexlibrarymember{moneypunct}{frac_digits}% -\indexlibrarymember{moneypunct}{positive_sign}% -\indexlibrarymember{moneypunct}{negative_sign}% -\begin{codeblock} -charT decimal_point() const; -charT thousands_sep() const; -string grouping() const; -string_type curr_symbol() const; -string_type positive_sign() const; -string_type negative_sign() const; -int frac_digits() const; -pattern pos_format() const; -pattern neg_format() const; -\end{codeblock} - -\pnum -Each of these functions \tcode{\placeholder{F}} -returns the result of calling the corresponding -virtual member function -\tcode{do_\placeholder{F}()}. - -\rSec4[locale.moneypunct.virtuals]{Virtual functions} - -\indexlibrarymember{moneypunct}{do_decimal_point}% -\begin{itemdecl} -charT do_decimal_point() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The radix separator to use -in case \tcode{do_frac_digits()} is greater than zero. -\begin{footnote} -In common U.S. locales this is \tcode{'.'}. -\end{footnote} -\end{itemdescr} - -\indexlibrarymember{moneypunct}{do_thousands_sep}% -\begin{itemdecl} -charT do_thousands_sep() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The digit group separator to use -in case \tcode{do_grouping()} specifies a digit grouping pattern. -\begin{footnote} -In common U.S. locales this is \tcode{','}. -\end{footnote} -\end{itemdescr} - -\indexlibrarymember{moneypunct}{do_grouping}% -\begin{itemdecl} -string do_grouping() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A pattern defined identically as, but not necessarily equal to, -the result of \tcode{numpunct::\brk{}do_grouping()}. -\begin{footnote} -To specify grouping by 3s, -the value is \tcode{"\textbackslash003"} \textit{not} \tcode{"3"}. -\end{footnote} -\end{itemdescr} - -\indexlibrarymember{moneypunct}{do_curr_symbol}% -\begin{itemdecl} -string_type do_curr_symbol() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A string to use as the currency identifier symbol. -\begin{note} -For specializations where the second template parameter is \tcode{true}, -this is typically four characters long: -a three-letter code as specified by ISO 4217\supercite{iso4217} -followed by a space. -\end{note} -\end{itemdescr} - -\indexlibrarymember{moneypunct}{do_positive_sign}% -\indexlibrarymember{moneypunct}{do_negative_sign}% -\begin{itemdecl} -string_type do_positive_sign() const; -string_type do_negative_sign() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_positive_sign()} -returns the string to use to indicate a positive monetary value; -\begin{footnote} -This is usually the empty string. -\end{footnote} -\tcode{do_negative_sign()} -returns the string to use to indicate a negative value. -\end{itemdescr} - -\indexlibrarymember{moneypunct}{do_frac_digits}% -\begin{itemdecl} -int do_frac_digits() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The number of digits after the decimal radix separator, if any. -\begin{footnote} -In common U.S.\ locales, this is 2. -\end{footnote} -\end{itemdescr} - -\indexlibrarymember{moneypunct}{do_pos_format}% -\indexlibrarymember{moneypunct}{do_neg_format}% -\begin{itemdecl} -pattern do_pos_format() const; -pattern do_neg_format() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The specializations required in \tref{locale.spec}\iref{locale.category}, namely -\begin{itemize} -\item \tcode{moneypunct}, -\item \tcode{moneypunct}, -\item \tcode{moneypunct}, and -\item \tcode{moneypunct}, -\end{itemize} -return an object of type \tcode{pattern} -initialized to \tcode{\{ symbol, sign, none, value \}}. -\begin{footnote} -Note that the international symbol returned by \tcode{do_curr_symbol()} -usually contains a space, itself; -for example, \tcode{"USD "}. -\end{footnote} -\end{itemdescr} - -\rSec3[locale.moneypunct.byname]{Class template \tcode{moneypunct_byname}} - -\indexlibraryglobal{moneypunct_byname}% -\begin{codeblock} -namespace std { - template - class moneypunct_byname : public moneypunct { - public: - using pattern = money_base::pattern; - using string_type = basic_string; - - explicit moneypunct_byname(const char*, size_t refs = 0); - explicit moneypunct_byname(const string&, size_t refs = 0); - - protected: - ~moneypunct_byname(); - }; -} -\end{codeblock} - -\rSec2[category.messages]{The message retrieval category} - -\rSec3[category.messages.general]{General} - -\pnum -Class \tcode{messages} -implements retrieval of strings from message catalogs. - -\rSec3[locale.messages]{Class template \tcode{messages}} - -\rSec4[locale.messages.general]{General} - -\indexlibraryglobal{messages}% -\begin{codeblock} -namespace std { - class messages_base { - public: - using catalog = @\textit{unspecified signed integer type}@; - }; - - template - class messages : public locale::facet, public messages_base { - public: - using char_type = charT; - using string_type = basic_string; - - explicit messages(size_t refs = 0); - - catalog open(const string& fn, const locale&) const; - string_type get(catalog c, int set, int msgid, - const string_type& dfault) const; - void close(catalog c) const; - - static locale::id id; - - protected: - ~messages(); - virtual catalog do_open(const string&, const locale&) const; - virtual string_type do_get(catalog, int set, int msgid, - const string_type& dfault) const; - virtual void do_close(catalog) const; - }; -} -\end{codeblock} - -\pnum -Values of type \tcode{messages_base::catalog} -usable as arguments to members \tcode{get} and \tcode{close} -can be obtained only by calling member \tcode{open}. - -\rSec4[locale.messages.members]{Members} - -\indexlibrarymember{messages}{open}% -\begin{itemdecl} -catalog open(const string& name, const locale& loc) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_open(name, loc)}. -\end{itemdescr} - -\indexlibrarymember{messages}{get}% -\begin{itemdecl} -string_type get(catalog cat, int set, int msgid, const string_type& dfault) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{do_get(cat, set, msgid, dfault)}. -\end{itemdescr} - -\indexlibrarymember{messages}{close}% -\begin{itemdecl} -void close(catalog cat) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls \tcode{do_close(cat)}. -\end{itemdescr} - -\rSec4[locale.messages.virtuals]{Virtual functions} - -\indexlibrarymember{messages}{do_open}% -\begin{itemdecl} -catalog do_open(const string& name, const locale& loc) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A value that may be passed to \tcode{get()} -to retrieve a message from the message catalog -identified by the string \tcode{name} -according to an \impldef{mapping from name to catalog when calling -\tcode{mes\-sages::do_open}} mapping. -The result can be used until it is passed to \tcode{close()}. - -\pnum -Returns a value less than 0 if no such catalog can be opened. - -\pnum -\remarks -The locale argument \tcode{loc} is used for -character set code conversion when retrieving messages, if needed. -\end{itemdescr} - -\indexlibrarymember{messages}{do_get}% -\begin{itemdecl} -string_type do_get(catalog cat, int set, int msgid, const string_type& dfault) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{cat} is a catalog obtained from \tcode{open()} and not yet closed. - -\pnum -\returns -A message identified by -arguments \tcode{set}, \tcode{msgid}, and \tcode{dfault}, -according to -an \impldef{mapping to message when calling \tcode{messages::do_get}} mapping. -If no such message can be found, returns \tcode{dfault}. -\end{itemdescr} - -\indexlibrarymember{message}{do_close}% -\begin{itemdecl} -void do_close(catalog cat) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{cat} is a catalog obtained from \tcode{open()} and not yet closed. - -\pnum -\effects -Releases unspecified resources associated with \tcode{cat}. - -\pnum -\remarks -The limit on such resources, if any, is -\impldef{resource limits on a message catalog}. -\end{itemdescr} - -\rSec3[locale.messages.byname]{Class template \tcode{messages_byname}} - -\indexlibraryglobal{messages_byname}% -\begin{codeblock} -namespace std { - template - class messages_byname : public messages { - public: - using catalog = messages_base::catalog; - using string_type = basic_string; - - explicit messages_byname(const char*, size_t refs = 0); - explicit messages_byname(const string&, size_t refs = 0); - - protected: - ~messages_byname(); - }; -} -\end{codeblock} - -\rSec1[c.locales]{C library locales} - -\rSec2[clocale.syn]{Header \tcode{} synopsis} - -\indexlibraryglobal{lconv}% -\indexlibraryglobal{setlocale}% -\indexlibraryglobal{localeconv}% -\indexlibraryglobal{NULL}% -\indexlibraryglobal{LC_ALL}% -\indexlibraryglobal{LC_COLLATE}% -\indexlibraryglobal{LC_CTYPE}% -\indexlibraryglobal{LC_MONETARY}% -\indexlibraryglobal{LC_NUMERIC}% -\indexlibraryglobal{LC_TIME}% -\begin{codeblock} -namespace std { - struct lconv; - - char* setlocale(int category, const char* locale); - lconv* localeconv(); -} - -#define NULL @\textit{see \ref{support.types.nullptr}}@ -#define LC_ALL @\seebelow@ -#define LC_COLLATE @\seebelow@ -#define LC_CTYPE @\seebelow@ -#define LC_MONETARY @\seebelow@ -#define LC_NUMERIC @\seebelow@ -#define LC_TIME @\seebelow@ -\end{codeblock} - -\pnum -The contents and meaning of the header \libheaderdef{clocale} -are the same as the C standard library header \libheader{locale.h}. - -\rSec2[clocale.data.races]{Data races} - -\pnum -Calls to the function \tcode{setlocale} -may introduce a data race\iref{res.on.data.races} -with other calls to \tcode{setlocale} or -with calls to the functions listed in \tref{setlocale.data.races}. - -\xrefc{7.11} - -\begin{floattable} -{Potential \tcode{setlocale} data races} -{setlocale.data.races} -{lllll} -\topline - -\tcode{fprintf} & -\tcode{isprint} & -\tcode{iswdigit} & -\tcode{localeconv} & -\tcode{tolower} \\ - -\tcode{fscanf} & -\tcode{ispunct} & -\tcode{iswgraph} & -\tcode{mblen} & -\tcode{toupper} \\ - -\tcode{isalnum} & -\tcode{isspace} & -\tcode{iswlower} & -\tcode{mbstowcs} & -\tcode{towlower} \\ - -\tcode{isalpha} & -\tcode{isupper} & -\tcode{iswprint} & -\tcode{mbtowc} & -\tcode{towupper} \\ - -\tcode{isblank} & -\tcode{iswalnum} & -\tcode{iswpunct} & -\tcode{setlocale} & -\tcode{wcscoll} \\ - -\tcode{iscntrl} & -\tcode{iswalpha} & -\tcode{iswspace} & -\tcode{strcoll} & -\tcode{wcstod} \\ - -\tcode{isdigit} & -\tcode{iswblank} & -\tcode{iswupper} & -\tcode{strerror} & -\tcode{wcstombs} \\ - -\tcode{isgraph} & -\tcode{iswcntrl} & -\tcode{iswxdigit} & -\tcode{strtod} & -\tcode{wcsxfrm} \\ - -\tcode{islower} & -\tcode{iswctype} & -\tcode{isxdigit} & -\tcode{strxfrm} & -\tcode{wctomb} \\ -\end{floattable} - -\rSec1[text.encoding]{Text encodings identification} - -\rSec2[text.encoding.syn]{Header \tcode{} synopsis} - -\indexheader{text_encoding}% -\begin{codeblock} -namespace std { - struct text_encoding; - - // \ref{text.encoding.hash}, hash support - template struct hash; - template<> struct hash; -} -\end{codeblock} - -\rSec2[text.encoding.class]{Class \tcode{text_encoding}} - -\rSec3[text.encoding.overview]{Overview} - -\pnum -The class \tcode{text_encoding} describes an interface -for accessing the IANA Character Sets registry\supercite{iana-charset}. - -\indexlibraryglobal{text_encoding}% -\begin{codeblock} -namespace std { - struct text_encoding { - static constexpr size_t max_name_length = 63; - - // \ref{text.encoding.id}, enumeration \tcode{text_encoding::id} - enum class id : int_least32_t { - @\seebelow@ - }; - using enum id; - - constexpr text_encoding() = default; - constexpr explicit text_encoding(string_view enc) noexcept; - constexpr text_encoding(id i) noexcept; - - constexpr id mib() const noexcept; - constexpr const char* name() const noexcept; - - struct aliases_view; - constexpr aliases_view aliases() const noexcept; - - friend constexpr bool operator==(const text_encoding& a, - const text_encoding& b) noexcept; - friend constexpr bool operator==(const text_encoding& encoding, id i) noexcept; - - static consteval text_encoding literal() noexcept; - static text_encoding environment(); - template static bool environment_is(); - - private: - id @\exposid{mib_}@ = id::unknown; // \expos - char @\exposid{name_}@[max_name_length + 1] = {0}; // \expos - static constexpr bool @\exposidnc{comp-name}@(string_view a, string_view b); // \expos - }; -} -\end{codeblock} - -\pnum -Class \tcode{text_encoding} is -a trivially copyable type\iref{term.trivially.copyable.type}. - -\rSec3[text.encoding.general]{General} - -\pnum -A \defnadj{registered character}{encoding} is -a character encoding scheme in the IANA Character Sets registry. -\begin{note} -The IANA Character Sets registry uses the term ``character sets'' -to refer to character encodings. -\end{note} -The primary name of a registered character encoding is -the name of that encoding specified in the IANA Character Sets registry. - -\pnum -The set of known registered character encodings contains -every registered character encoding -specified in the IANA Character Sets registry except for the following: -\begin{itemize} -\item NATS-DANO (33) -\item NATS-DANO-ADD (34) -\end{itemize} - -\pnum -Each known registered character encoding -is identified by an enumerator in \tcode{text_encoding::id}, and -has a set of zero or more \defnx{aliases}{encoding!registered character!alias}. - -\pnum -The set of aliases of a known registered character encoding is an -\impldef{set of aliases of a known registered character encoding} -superset of the aliases specified in the IANA Character Sets registry. -No two aliases or primary names of distinct registered character encodings -are equivalent when compared by \tcode{text_encoding::\exposid{comp-name}}. - -\pnum -How a \tcode{text_encoding} object -is determined to be representative of a character encoding scheme -implemented in the translation or execution environment is -\impldef{how \tcode{text_encoding} objects are -determined to be representative of a character encoding scheme}. - -\pnum -An object \tcode{e} of type \tcode{text_encoding} such that -\tcode{e.mib() == text_encoding::id::unknown} is \tcode{false} and -\tcode{e.mib() == text_encoding::id::other} is \tcode{false} -maintains the following invariants: -\begin{itemize} -\item \tcode{e.name() == nullptr} is \tcode{false}, and -\item \tcode{e.mib() == text_encoding(e.name()).mib()} is \tcode{true}. -\end{itemize} - -\pnum -\recommended -\begin{itemize} -\item -Implementations should not consider registered encodings to be interchangeable. -\begin{example} -Shift_JIS and Windows-31J denote different encodings. -\end{example} -\item -Implementations should not use the name of a registered encoding -to describe another similar yet different non-registered encoding -unless there is a precedent on that implementation. -\begin{example} -Big5 -\end{example} -\end{itemize} - -\rSec3[text.encoding.members]{Members} - -\indexlibraryctor{text_encoding}% -\begin{itemdecl} -constexpr explicit text_encoding(string_view enc) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\begin{itemize} -\item -\tcode{enc} represents a string in the ordinary literal encoding -consisting only of elements of the basic character set\iref{lex.charset}. -\item -\tcode{enc.size() <= max_name_length} is \tcode{true}. -\item -\tcode{enc.contains('\textbackslash 0')} is \tcode{false}. -\end{itemize} - -\pnum -\ensures -\begin{itemize} -\item -If there exists a primary name or alias \tcode{a} -of a known registered character encoding such that -\tcode{\exposid{comp-name}(a, enc)} is \tcode{true}, -\exposid{mib_} has the value of the enumerator of \tcode{id} -associated with that registered character encoding. -Otherwise, \tcode{\exposid{mib_} == id::other} is \tcode{true}. -\item -\tcode{enc.compare(\exposid{name_}) == 0} is \tcode{true}. -\end{itemize} -\end{itemdescr} - -\indexlibraryctor{text_encoding}% -\begin{itemdecl} -constexpr text_encoding(id i) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{i} has the value of one of the enumerators of \tcode{id}. - -\pnum -\ensures -\begin{itemize} -\item -\tcode{\exposid{mib_} == i} is \tcode{true}. -\item -If \tcode{(\exposid{mib_} == id::unknown || \exposid{mib_} == id::other)} -is \tcode{true}, -\tcode{strlen(\exposid{name_}) == 0} is \tcode{true}. -Otherwise, -\tcode{ranges::contains(aliases(), string_view(\exposid{name_}))} -is \tcode{true}. -\end{itemize} -\end{itemdescr} - -\indexlibrarymember{mib}{text_encoding}% -\begin{itemdecl} -constexpr id mib() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\exposid{mib_}. -\end{itemdescr} - -\indexlibrarymember{name}{text_encoding}% -\begin{itemdecl} -constexpr const char* name() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\exposid{name_} if \tcode{(\exposid{name_}[0] != '\textbackslash 0')} -is \tcode{true}, and -\keyword{nullptr} otherwise. - -\pnum -\remarks -If \tcode{name() == nullptr} is \tcode{false}, -\tcode{name()} is an \ntbs{} and -accessing elements of \exposid{name_} -outside of the range \countedrange{name()}{strlen(name()) + 1} -is undefined behavior. -\end{itemdescr} - -\indexlibrarymember{aliases}{text_encoding}% -\begin{itemdecl} -constexpr aliases_view aliases() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -Let \tcode{r} denote an instance of \tcode{aliases_view}. -If \tcode{*this} represents a known registered character encoding, then: -\begin{itemize} -\item -\tcode{r.front()} is the primary name of the registered character encoding, -\item -\tcode{r} contains the aliases of the registered character encoding, and -\item -\tcode{r} does not contain duplicate values when compared with \tcode{strcmp}. -\end{itemize} -Otherwise, \tcode{r} is an empty range. - -\pnum -Each element in \tcode{r} -is a non-null, non-empty \ntbs{} encoded in the literal character encoding and -comprising only characters from the basic character set. - -\pnum -\returns -\tcode{r}. - -\pnum -\begin{note} -The order of aliases in \tcode{r} is unspecified. -\end{note} -\end{itemdescr} - -\indexlibrarymember{literal}{text_encoding}% -\begin{itemdecl} -static consteval text_encoding literal() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{CHAR_BIT == 8} is \tcode{true}. - -\pnum -\returns -A \tcode{text_encoding} object representing -the ordinary character literal encoding\iref{lex.charset}. -\end{itemdescr} - -\indexlibrarymember{environment}{text_encoding}% -\begin{itemdecl} -static text_encoding environment(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{CHAR_BIT == 8} is \tcode{true}. - -\pnum -\returns -A \tcode{text_encoding} object representing -the \impldef{character encoding scheme of the environment} -character encoding scheme of the environment. -On a POSIX implementation, this is the encoding scheme associated with -the POSIX locale denoted by the empty string \tcode{""}. - -\pnum -\begin{note} -This function is not affected by calls to \tcode{setlocale}. -\end{note} - -\pnum -\recommended -Implementations should return a value that is not affected by calls to -the POSIX function \tcode{setenv} and -other functions which can modify the environment\iref{support.runtime}. -\end{itemdescr} - -\indexlibrarymember{environment_is}{text_encoding}% -\begin{itemdecl} -template - static bool environment_is(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{CHAR_BIT == 8} is \tcode{true}. - -\pnum -\returns -\tcode{environment() == i}. -\end{itemdescr} - -\indexlibrarymember{\exposid{comp-name}}{text_encoding}% -\begin{itemdecl} -static constexpr bool @\exposid{comp-name}@(string_view a, string_view b); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if the two strings \tcode{a} and \tcode{b} -encoded in the ordinary literal encoding -are equal, ignoring, from left-to-right, -\begin{itemize} -\item -all elements that are not digits or letters\iref{character.seq.general}, -\item -character case, and -\item -any sequence of one or more \tcode{0} characters -not immediately preceded by a numeric prefix, where -a numeric prefix is a sequence consisting of -a digit in the range \crange{1}{9} -optionally followed by one or more elements which are not digits or letters, -\end{itemize} -and \tcode{false} otherwise. - -\begin{note} -This comparison is identical to -the ``Charset Alias Matching'' algorithm -described in the Unicode Technical Standard 22\supercite{unicode-charmap}. -\end{note} - -\begin{example} -\begin{codeblock} -static_assert(@\exposid{comp-name}@("UTF-8", "utf8") == true); -static_assert(@\exposid{comp-name}@("u.t.f-008", "utf8") == true); -static_assert(@\exposid{comp-name}@("ut8", "utf8") == false); -static_assert(@\exposid{comp-name}@("utf-80", "utf8") == false); -\end{codeblock} -\end{example} -\end{itemdescr} - -\rSec3[text.encoding.cmp]{Comparison functions} - -\indexlibrarymember{operator==}{text_encoding}% -\begin{itemdecl} -friend constexpr bool operator==(const text_encoding& a, const text_encoding& b) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -If \tcode{a.\exposid{mib_} == id::other \&\& b.\exposid{mib_} == id::other} -is \tcode{true}, -then \tcode{\exposid{comp-name}(a.\exposid{name_},\linebreak{}b.\exposid{name_})}. -Otherwise, \tcode{a.\exposid{mib_} == b.\exposid{mib_}}. -\end{itemdescr} - -\indexlibrarymember{operator==}{text_encoding}% -\begin{itemdecl} -friend constexpr bool operator==(const text_encoding& encoding, id i) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{encoding.\exposid{mib_} == i}. - -\pnum -\remarks -This operator induces an equivalence relation on its arguments -if and only if \tcode{i != id::other} is \tcode{true}. -\end{itemdescr} - -\rSec3[text.encoding.aliases]{Class \tcode{text_encoding::aliases_view}} - -\indexlibrarymember{aliases_view}{text_encoding}% -\indexlibrarymember{begin}{text_encoding::aliases_view}% -\indexlibrarymember{end}{text_encoding::aliases_view}% -\begin{itemdecl} -struct text_encoding::aliases_view : ranges::view_interface { - constexpr @\impdefx{type of \tcode{text_encoding::aliases_view::begin()}}@ begin() const; - constexpr @\impdefx{type of \tcode{text_encoding::aliases_view::end()}}@ end() const; -}; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\tcode{text_encoding::aliases_view} models -\libconcept{copyable}, -\tcode{ranges::\libconcept{view}}, -\tcode{ranges::\libconcept{random_access_range}}, and -\tcode{ranges::\libconcept{borrowed_range}}. - -\pnum -Both -\tcode{ranges::range_value_t} and -\tcode{ranges::range_reference_t} -denote \tcode{const char*}. -\end{itemdescr} - -\rSec3[text.encoding.id]{Enumeration \tcode{text_encoding::id}} - -\indexlibrarymember{id}{text_encoding}% -\begin{codeblock} -namespace std { - enum class text_encoding::id : int_least32_t { - other = 1, - unknown = 2, - ASCII = 3, - ISOLatin1 = 4, - ISOLatin2 = 5, - ISOLatin3 = 6, - ISOLatin4 = 7, - ISOLatinCyrillic = 8, - ISOLatinArabic = 9, - ISOLatinGreek = 10, - ISOLatinHebrew = 11, - ISOLatin5 = 12, - ISOLatin6 = 13, - ISOTextComm = 14, - HalfWidthKatakana = 15, - JISEncoding = 16, - ShiftJIS = 17, - EUCPkdFmtJapanese = 18, - EUCFixWidJapanese = 19, - ISO4UnitedKingdom = 20, - ISO11SwedishForNames = 21, - ISO15Italian = 22, - ISO17Spanish = 23, - ISO21German = 24, - ISO60DanishNorwegian = 25, - ISO69French = 26, - ISO10646UTF1 = 27, - ISO646basic1983 = 28, - INVARIANT = 29, - ISO2IntlRefVersion = 30, - NATSSEFI = 31, - NATSSEFIADD = 32, - ISO10Swedish = 35, - KSC56011987 = 36, - ISO2022KR = 37, - EUCKR = 38, - ISO2022JP = 39, - ISO2022JP2 = 40, - ISO13JISC6220jp = 41, - ISO14JISC6220ro = 42, - ISO16Portuguese = 43, - ISO18Greek7Old = 44, - ISO19LatinGreek = 45, - ISO25French = 46, - ISO27LatinGreek1 = 47, - ISO5427Cyrillic = 48, - ISO42JISC62261978 = 49, - ISO47BSViewdata = 50, - ISO49INIS = 51, - ISO50INIS8 = 52, - ISO51INISCyrillic = 53, - ISO54271981 = 54, - ISO5428Greek = 55, - ISO57GB1988 = 56, - ISO58GB231280 = 57, - ISO61Norwegian2 = 58, - ISO70VideotexSupp1 = 59, - ISO84Portuguese2 = 60, - ISO85Spanish2 = 61, - ISO86Hungarian = 62, - ISO87JISX0208 = 63, - ISO88Greek7 = 64, - ISO89ASMO449 = 65, - ISO90 = 66, - ISO91JISC62291984a = 67, - ISO92JISC62991984b = 68, - ISO93JIS62291984badd = 69, - ISO94JIS62291984hand = 70, - ISO95JIS62291984handadd = 71, - ISO96JISC62291984kana = 72, - ISO2033 = 73, - ISO99NAPLPS = 74, - ISO102T617bit = 75, - ISO103T618bit = 76, - ISO111ECMACyrillic = 77, - ISO121Canadian1 = 78, - ISO122Canadian2 = 79, - ISO123CSAZ24341985gr = 80, - ISO88596E = 81, - ISO88596I = 82, - ISO128T101G2 = 83, - ISO88598E = 84, - ISO88598I = 85, - ISO139CSN369103 = 86, - ISO141JUSIB1002 = 87, - ISO143IECP271 = 88, - ISO146Serbian = 89, - ISO147Macedonian = 90, - ISO150 = 91, - ISO151Cuba = 92, - ISO6937Add = 93, - ISO153GOST1976874 = 94, - ISO8859Supp = 95, - ISO10367Box = 96, - ISO158Lap = 97, - ISO159JISX02121990 = 98, - ISO646Danish = 99, - USDK = 100, - DKUS = 101, - KSC5636 = 102, - Unicode11UTF7 = 103, - ISO2022CN = 104, - ISO2022CNEXT = 105, - UTF8 = 106, - ISO885913 = 109, - ISO885914 = 110, - ISO885915 = 111, - ISO885916 = 112, - GBK = 113, - GB18030 = 114, - OSDEBCDICDF0415 = 115, - OSDEBCDICDF03IRV = 116, - OSDEBCDICDF041 = 117, - ISO115481 = 118, - KZ1048 = 119, - UCS2 = 1000, - UCS4 = 1001, - UnicodeASCII = 1002, - UnicodeLatin1 = 1003, - UnicodeJapanese = 1004, - UnicodeIBM1261 = 1005, - UnicodeIBM1268 = 1006, - UnicodeIBM1276 = 1007, - UnicodeIBM1264 = 1008, - UnicodeIBM1265 = 1009, - Unicode11 = 1010, - SCSU = 1011, - UTF7 = 1012, - UTF16BE = 1013, - UTF16LE = 1014, - UTF16 = 1015, - CESU8 = 1016, - UTF32 = 1017, - UTF32BE = 1018, - UTF32LE = 1019, - BOCU1 = 1020, - UTF7IMAP = 1021, - Windows30Latin1 = 2000, - Windows31Latin1 = 2001, - Windows31Latin2 = 2002, - Windows31Latin5 = 2003, - HPRoman8 = 2004, - AdobeStandardEncoding = 2005, - VenturaUS = 2006, - VenturaInternational = 2007, - DECMCS = 2008, - PC850Multilingual = 2009, - PC8DanishNorwegian = 2012, - PC862LatinHebrew = 2013, - PC8Turkish = 2014, - IBMSymbols = 2015, - IBMThai = 2016, - HPLegal = 2017, - HPPiFont = 2018, - HPMath8 = 2019, - HPPSMath = 2020, - HPDesktop = 2021, - VenturaMath = 2022, - MicrosoftPublishing = 2023, - Windows31J = 2024, - GB2312 = 2025, - Big5 = 2026, - Macintosh = 2027, - IBM037 = 2028, - IBM038 = 2029, - IBM273 = 2030, - IBM274 = 2031, - IBM275 = 2032, - IBM277 = 2033, - IBM278 = 2034, - IBM280 = 2035, - IBM281 = 2036, - IBM284 = 2037, - IBM285 = 2038, - IBM290 = 2039, - IBM297 = 2040, - IBM420 = 2041, - IBM423 = 2042, - IBM424 = 2043, - PC8CodePage437 = 2011, - IBM500 = 2044, - IBM851 = 2045, - PCp852 = 2010, - IBM855 = 2046, - IBM857 = 2047, - IBM860 = 2048, - IBM861 = 2049, - IBM863 = 2050, - IBM864 = 2051, - IBM865 = 2052, - IBM868 = 2053, - IBM869 = 2054, - IBM870 = 2055, - IBM871 = 2056, - IBM880 = 2057, - IBM891 = 2058, - IBM903 = 2059, - IBM904 = 2060, - IBM905 = 2061, - IBM918 = 2062, - IBM1026 = 2063, - IBMEBCDICATDE = 2064, - EBCDICATDEA = 2065, - EBCDICCAFR = 2066, - EBCDICDKNO = 2067, - EBCDICDKNOA = 2068, - EBCDICFISE = 2069, - EBCDICFISEA = 2070, - EBCDICFR = 2071, - EBCDICIT = 2072, - EBCDICPT = 2073, - EBCDICES = 2074, - EBCDICESA = 2075, - EBCDICESS = 2076, - EBCDICUK = 2077, - EBCDICUS = 2078, - Unknown8BiT = 2079, - Mnemonic = 2080, - Mnem = 2081, - VISCII = 2082, - VIQR = 2083, - KOI8R = 2084, - HZGB2312 = 2085, - IBM866 = 2086, - PC775Baltic = 2087, - KOI8U = 2088, - IBM00858 = 2089, - IBM00924 = 2090, - IBM01140 = 2091, - IBM01141 = 2092, - IBM01142 = 2093, - IBM01143 = 2094, - IBM01144 = 2095, - IBM01145 = 2096, - IBM01146 = 2097, - IBM01147 = 2098, - IBM01148 = 2099, - IBM01149 = 2100, - Big5HKSCS = 2101, - IBM1047 = 2102, - PTCP154 = 2103, - Amiga1251 = 2104, - KOI7switched = 2105, - BRF = 2106, - TSCII = 2107, - CP51932 = 2108, - windows874 = 2109, - windows1250 = 2250, - windows1251 = 2251, - windows1252 = 2252, - windows1253 = 2253, - windows1254 = 2254, - windows1255 = 2255, - windows1256 = 2256, - windows1257 = 2257, - windows1258 = 2258, - TIS620 = 2259, - CP50220 = 2260 - }; -} -\end{codeblock} - -\begin{note} -The \tcode{text_encoding::id} enumeration -contains an enumerator for each known registered character encoding. -For each encoding, the corresponding enumerator is derived from -the alias beginning with ``\tcode{cs}'', as follows -\begin{itemize} -\item -\tcode{csUnicode} is mapped to \tcode{text_encoding::id::UCS2}, -\item -\tcode{csIBBM904} is mapped to \tcode{text_encoding::id::IBM904}, and -\item -the ``\tcode{cs}'' prefix is removed from other names. -\end{itemize} -\end{note} - -\rSec3[text.encoding.hash]{Hash support} - -\indexlibrarymember{hash}{text_encoding}% -\begin{itemdecl} -template<> struct hash; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The specialization is enabled\iref{unord.hash}. -\end{itemdescr} diff --git a/source/macros.tex b/source/macros.tex index bff719918e..39577ed108 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -39,20 +39,18 @@ \newenvironment{addedblock}{\color{addclr}}{\color{black}} \newenvironment{removedblock}{\color{remclr}}{\color{black}} -%%-------------------------------------------------- +%%------------------------------------------------------------- %% Grammar extraction. -%%-------------------------------------------------- -\def\gramSec[#1]#2{} - +%% Assumes that the output file \gramout is managed externally. +%%------------------------------------------------------------- \makeatletter -\newcommand{\FlushAndPrintGrammar}{% -\immediate\closeout\XTR@out% -\immediate\openout\XTR@out=std-gram-dummy.tmp% -\def\gramSec[##1]##2{\rSec1[##1]{##2}}% -\input{std-gram.ext}% -} +\newcommand{\gramWrite}[1]{\protected@write\gramout{}{#1}} +\newcommand{\meaningbody}[1]{\expandafter\strip@prefix\meaning#1} \makeatother +\newcommand{\gramSec}[2][]{\gramWrite{% +\string\rSec1\string[\string#1\string]\string{\string#2\string}}} + %%-------------------------------------------------- % Escaping for index entries. Replaces ! with "! throughout its argument. %%-------------------------------------------------- @@ -147,7 +145,7 @@ % \indeximpldef synthesizes a collation key from the argument; that is, an % invocation \indeximpldef{arg} emits an index entry `key@arg`, where `key` -% is derived from `arg` by replacing the folowing list of commands with their +% is derived from `arg` by replacing the following list of commands with their % bare content. This allows, say, collating plain text and code. \newcommand{\indeximpldef}[1]{% \let\otextup\textup% @@ -214,12 +212,21 @@ \newcommand{\libmember}[2]{\indexlibrarymember{#1}{#2}#1} \newcommand{\libspec}[2]{\indexlibrarymemberx{#1}{#2}#1} +% index for macros +% \libmacro is suitable for use directly in header synopses to add the macro +% to both the text and the library index. \libxmacro does the same, but +% prepends a well-rendered double underscore. +\newcommand{\libmacro}[1]{\indexlibraryglobal{#1}\CodeStylex{#1}} +\newcommand{\libxmacro}[1]{\indexlibraryglobal{\idxxname{#1}}\CodeStylex{\xname{#1}}} + % index for library headers -\newcommand{\libheader}[1]{\indexhdr{#1}\tcode{<#1>}} +\newcommand{\libheaderx}[2]{\indexhdr{#1}\tcode{<#2>}} +\newcommand{\libheader}[1]{\libheaderx{#1}{#1}} \newcommand{\indexheader}[1]{\index[headerindex]{\idxhdr{#1}|idxbfpage}} \newcommand{\libheaderdef}[1]{\indexheader{#1}\tcode{<#1>}} \newcommand{\libnoheader}[1]{\indextext{\idxhdr{#1}!absence thereof}\tcode{<#1>}} -\newcommand{\libheaderrefx}[2]{\libheader{#1}\iref{#2}} +\newcommand{\libheaderrefxx}[3]{\libheaderx{#1}{#2}\iref{#3}} +\newcommand{\libheaderrefx}[2]{\libheaderrefxx{#1}{#1}{#2}} \newcommand{\libheaderref}[1]{\libheaderrefx{#1}{#1.syn}} \newcommand{\libdeprheaderref}[1]{\libheaderrefx{#1}{depr.#1.syn}} @@ -285,7 +292,10 @@ \newcommand{\CppXXIII}{\Cpp{} 2023} \newcommand{\CppXXVI}{\Cpp{} 2026} \newcommand{\IsoCUndated}{ISO/IEC 9899} -\newcommand{\IsoC}{\IsoCUndated{}:2018} +\newcommand{\IsoC}{\IsoCUndated{}:2024} +\newcommand{\IsoFloatUndated}{ISO/IEC 60559} +\newcommand{\IsoPosixUndated}{ISO/IEC/IEEE 9945} +\newcommand{\IsoPosix}{\IsoPosixUndated{}:2009} \newcommand{\opt}[1]{#1\ensuremath{_\mathit{\color{black}opt}}} \newcommand{\bigoh}[1]{\ensuremath{\mathscr{O}(#1)}} @@ -318,7 +328,7 @@ \newcommand{\newnoteenvironment}[3]{ \newsubclausecounter{#1} \newenvironment{tail#1} -{\par\small\stepcounter{#1}\noteintro{#2}} +{\par\small\penalty -200\stepcounter{#1}\noteintro{#2}} {\noteoutro{#3}} \newenvironment{#1} {\begin{tail#1}} @@ -353,7 +363,9 @@ \newcommand{\required}{\Fundesc{Required behavior}} \newcommand{\constraints}{\Fundesc{Constraints}} \newcommand{\mandates}{\Fundesc{Mandates}} +\newcommand{\constantwhen}{\Fundesc{Constant When}} \newcommand{\expects}{\Fundesc{Preconditions}} +\newcommand{\hardexpects}{\Fundesc{Hardened preconditions}} \newcommand{\effects}{\Fundesc{Effects}} \newcommand{\ensures}{\Fundesc{Postconditions}} \newcommand{\returns}{\Fundesc{Returns}} @@ -364,15 +376,14 @@ \newcommand{\errors}{\Fundesc{Error conditions}} \newcommand{\sync}{\Fundesc{Synchronization}} \newcommand{\implimits}{\Fundesc{Implementation limits}} -\newcommand{\replaceable}{\Fundesc{Replaceable}} \newcommand{\result}{\Fundesc{Result}} \newcommand{\returntype}{\Fundesc{Return type}} \newcommand{\ctype}{\Fundesc{Type}} \newcommand{\templalias}{\Fundesc{Alias template}} %% Cross-reference -\newcommand{\xref}{\textsc{See also:}\space} -\newcommand{\xrefc}[1]{\xref{} \IsoC{}, #1} +\newcommand{\xref}[1]{\textsc{See also:}\space #1} +\newcommand{\xrefc}[1]{\xref{\IsoC{}, #1}} \newcommand{\termref}[3]{\textit{#2}{#3}\iref{#1}} % in Clause 3 %% Inline comma-separated parenthesized references @@ -452,9 +463,15 @@ \newcommand{\unspecbool}{\UNSP{unspecified-bool-type}} \newcommand{\seebelow}{\UNSP{see below}} % macro length: 0 \newcommand{\seebelownc}{\UNSPnc{see below}} % macro length: 2 +\newcommand{\seeabove}{\UNSP{see above}} % macro length: 0 +\newcommand{\seeabovenc}{\UNSPnc{see above}} % macro length: 2 \newcommand{\unspecuniqtype}{\UNSP{unspecified unique type}} \newcommand{\unspecalloctype}{\UNSP{unspecified allocator type}} +%% Convenience macro for double carets in expressions, +%% particularly within \tcode. +\newcommand{\reflexpr}[1]{\caret\caret#1} + %% Manual insertion of italic corrections, for aligning in the presence %% of the above annotations. \newlength{\itcorrwidth} @@ -544,6 +561,9 @@ \newcommand{\cv}{\ifmmode\mathit{cv}\else\cvqual{cv}\fi} \newcommand{\numconst}[1]{\textsl{#1}} \newcommand{\logop}[1]{\textsc{#1}} +\DeclareMathOperator{\mullo}{mullo} +\DeclareMathOperator{\mulhi}{mulhi} +\newcommand{\cedef}{\mathrel{\mathop:}=} % "colon-equals definition" %%-------------------------------------------------- %% Environments for code listings. @@ -579,22 +599,6 @@ \lstnewenvironment{codeblock}{\CodeBlockSetup}{} -% Left-align listings titles -\makeatletter -\def\lst@maketitle{\@makeleftcaption\lst@title@dropdelim} -\long\def\@makeleftcaption#1#2{% - \vskip\abovecaptionskip - \sbox\@tempboxa{#1: #2}% - \ifdim \wd\@tempboxa >\hsize - #1: #2\par - \else - \global \@minipagefalse - \hb@xt@\hsize{%\hfil -- REMOVED - \box\@tempboxa\hfil}% - \fi - \vskip\belowcaptionskip}% -\makeatother - \lstnewenvironment{codeblocktu}[1]{% \lstset{title={%\parabullnum{Bullets1}{0pt} #1:}}\CodeBlockSetup}{} @@ -614,6 +618,17 @@ \newcommand{\atsign}{@} \makeatother +%%-------------------------------------------------- +%% Formulae +%%-------------------------------------------------- + +% usage: \begin{formula}{XREF} +\newenvironment{formula}[1] +{\begin{equation}\label{eq:#1}} +{\end{equation}} + +\renewcommand{\eqref}[1]{Formula \nolinebreak[3] \hyperref[eq:#1]{\ref*{eq:#1}}} + %%-------------------------------------------------- %% Indented text %%-------------------------------------------------- @@ -628,9 +643,9 @@ { \lstset{escapechar=@, xleftmargin=0em, - midpenalty=500, + midpenalty=3000, semicolonpenalty=-50, - endpenalty=3000, + endpenalty=2000, aboveskip=2ex, belowskip=0ex % leave this alone: it keeps these things out of the % footnote area @@ -657,7 +672,17 @@ \setlength{\BnfInc}{\BnfIndent} \newlength{\BnfRest} \setlength{\BnfRest}{2\BnfIndent} -\newcommand{\BnfNontermshape}{\small\color{grammar-gray}\sffamily\itshape} +\newcommand{\BnfNontermshape}{% + \small% + \color{grammar-gray}% + % The color setting inserts a \pdfcolorstack entry into the vertical list, + % breaking the connection of the \penalty entry from a preceding heading + % with the \glue entries that precede the grammar snippet. + % Add a penalty here that prevents making those \glue entries page-breaking + % opportunities. + \penalty10000% + \sffamily% + \itshape} \newcommand{\BnfReNontermshape}{\small\rmfamily\itshape} \newcommand{\BnfTermshape}{\small\ttfamily\upshape} @@ -681,7 +706,12 @@ \nonfrenchspacing } -\newenvironment{simplebnf} +% "ncbnf" is the non-copied "base" versions of the bnf environment; +% instances of the full "bnf" environment is copied to the grammar +% extraction file. +% (Similarly for "ncsimplebnf", though in fact we never extract any +% hypothetical "simplebnf" environments.) +\newenvironment{ncsimplebnf} { \begin{bnfbase} \BnfNontermshape @@ -692,7 +722,7 @@ \end{bnfbase} } -\newenvironment{bnf} +\newenvironment{ncbnf} { \begin{bnfbase} \begin{bnflist} @@ -704,6 +734,7 @@ \end{bnfbase} } +% The regex grammar is never copied. \newenvironment{ncrebnf} { \begin{bnfbase} @@ -717,11 +748,10 @@ \end{bnfbase} } -% non-copied versions of bnf environments -\let\ncsimplebnf\simplebnf -\let\endncsimplebnf\endsimplebnf -\let\ncbnf\bnf -\let\endncbnf\endbnf +\NewEnviron{bnf}{\begin{ncbnf}% +\BODY% +\gramWrite{\string\begin{ncbnf}\meaningbody\BODY\string\end{ncbnf}}% +\end{ncbnf}}{} %%-------------------------------------------------- %% Environment for imported graphics diff --git a/source/memory.tex b/source/memory.tex index f65e2de029..8ad74c9351 100644 --- a/source/memory.tex +++ b/source/memory.tex @@ -13,14 +13,15 @@ \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{smartptr} & Smart pointers & \tcode{} \\ \rowsep +\ref{mem.composite.types} & Types for composite class design & \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} +\rSec2[memory.general]{General} \pnum Subclause~\ref{memory} describes the contents of the header @@ -82,7 +83,9 @@ // \ref{ptr.align}, pointer alignment void* align(size_t alignment, size_t size, void*& ptr, size_t& space); // freestanding template - [[nodiscard]] constexpr T* assume_aligned(T* ptr); // freestanding + constexpr T* assume_aligned(T* ptr); // freestanding + template + bool is_sufficiently_aligned(T* ptr); // \ref{obj.lifetime}, explicit lifetime management template @@ -102,6 +105,10 @@ template const volatile T* start_lifetime_as_array(const volatile void* p, // freestanding size_t n) noexcept; + template + T* trivially_relocate(T* first, T* last, T* result); // freestanding + template + constexpr T* relocate(T* first, T* last, T* result); // freestanding // \ref{allocator.tag}, allocator argument tag struct allocator_arg_t { explicit allocator_arg_t() = default; }; // freestanding @@ -174,178 +181,286 @@ // \ref{specialized.algorithms}, specialized algorithms // \ref{special.mem.concepts}, special memory concepts template - concept @\exposconcept{nothrow-input-iterator}@ = @\seebelow@; // \expos + concept @\exposconcept{nothrow-input-iterator}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-forward-iterator}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-bidirectional-iterator}@ = @\seebelow@; // \expos template - concept @\exposconcept{nothrow-forward-iterator}@ = @\seebelow@; // \expos + concept @\exposconcept{nothrow-random-access-iterator}@ = @\seebelow@; // \expos template - concept @\exposconcept{nothrow-sentinel-for}@ = @\seebelow@; // \expos + concept @\exposconcept{nothrow-sentinel-for}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-sized-sentinel-for}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-input-range}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-forward-range}@ = @\seebelow@; // \expos + template + concept @\exposconcept{nothrow-bidirectional-range}@ = @\seebelow@; // \expos template - concept @\exposconcept{nothrow-input-range}@ = @\seebelow@; // \expos + concept @\exposconcept{nothrow-random-access-range}@ = @\seebelow@; // \expos template - concept @\exposconcept{nothrow-forward-range}@ = @\seebelow@; // \expos + concept @\exposconcept{nothrow-sized-random-access-range}@ = @\seebelow@; // \expos template - void uninitialized_default_construct(NoThrowForwardIterator first, // freestanding - NoThrowForwardIterator last); + constexpr void uninitialized_default_construct(NoThrowForwardIterator first, // freestanding + NoThrowForwardIterator last); template - void uninitialized_default_construct(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, + void uninitialized_default_construct(ExecutionPolicy&& exec, // freestanding-deleted, + NoThrowForwardIterator first, // see \ref{algorithms.parallel.overloads} NoThrowForwardIterator last); template - NoThrowForwardIterator + constexpr NoThrowForwardIterator uninitialized_default_construct_n(NoThrowForwardIterator first, Size n); // freestanding template NoThrowForwardIterator - uninitialized_default_construct_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, Size n); + uninitialized_default_construct_n(ExecutionPolicy&& exec, // freestanding-deleted, + NoThrowForwardIterator first, // see \ref{algorithms.parallel.overloads} + 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); // freestanding + constexpr I uninitialized_default_construct(I first, S last); // freestanding template<@\exposconcept{nothrow-forward-range}@ R> requires @\libconcept{default_initializable}@> - borrowed_iterator_t uninitialized_default_construct(R&& r); // freestanding + constexpr borrowed_iterator_t uninitialized_default_construct(R&& r); // freestanding template<@\exposconcept{nothrow-forward-iterator}@ I> requires @\libconcept{default_initializable}@> - I uninitialized_default_construct_n(I first, iter_difference_t n); // freestanding + constexpr I uninitialized_default_construct_n(I first, // freestanding + iter_difference_t n); + + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I, + @\exposconcept{nothrow-sized-sentinel-for}@ S> + requires @\libconcept{default_initializable}@> + I uninitialized_default_construct(Ep&& exec, I first, S last); // freestanding-deleted, + // see \ref{algorithms.parallel.overloads} + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-sized-random-access-range}@ R> + requires @\libconcept{default_initializable}@> + borrowed_iterator_t uninitialized_default_construct(Ep&& exec, // freestanding-deleted, + R&& r); // see \ref{algorithms.parallel.overloads} + + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I> + requires @\libconcept{default_initializable}@> + I uninitialized_default_construct_n(Ep&& exec, I first, // freestanding-deleted, + iter_difference_t n); // see \ref{algorithms.parallel.overloads} } template - void uninitialized_value_construct(NoThrowForwardIterator first, // freestanding - NoThrowForwardIterator last); + constexpr void uninitialized_value_construct(NoThrowForwardIterator first, // freestanding + NoThrowForwardIterator last); template - void uninitialized_value_construct(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, + void uninitialized_value_construct(ExecutionPolicy&& exec, // freestanding-deleted, + NoThrowForwardIterator first, // see \ref{algorithms.parallel.overloads} NoThrowForwardIterator last); template - NoThrowForwardIterator + constexpr NoThrowForwardIterator uninitialized_value_construct_n(NoThrowForwardIterator first, Size n); // freestanding template NoThrowForwardIterator - uninitialized_value_construct_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, Size n); + uninitialized_value_construct_n(ExecutionPolicy&& exec, // freestanding-deleted, + NoThrowForwardIterator first, // see \ref{algorithms.parallel.overloads} + 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); // freestanding + constexpr I uninitialized_value_construct(I first, S last); // freestanding template<@\exposconcept{nothrow-forward-range}@ R> requires @\libconcept{default_initializable}@> - borrowed_iterator_t uninitialized_value_construct(R&& r); // freestanding + constexpr borrowed_iterator_t uninitialized_value_construct(R&& r); // freestanding template<@\exposconcept{nothrow-forward-iterator}@ I> requires @\libconcept{default_initializable}@> - I uninitialized_value_construct_n(I first, iter_difference_t n); // freestanding + constexpr I uninitialized_value_construct_n(I first, // freestanding + iter_difference_t n); + + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I, + @\exposconcept{nothrow-sized-sentinel-for}@ S> + requires @\libconcept{default_initializable}@> + I uninitialized_value_construct(Ep&& exec, I first, S last); // freestanding-deleted, + // see \ref{algorithms.parallel.overloads} + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-sized-random-access-range}@ R> + requires @\libconcept{default_initializable}@> + borrowed_iterator_t uninitialized_value_construct(Ep&& exec, // freestanding-deleted, + R&& r); // see \ref{algorithms.parallel.overloads} + + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I> + requires @\libconcept{default_initializable}@> + I uninitialized_value_construct_n(Ep&& exec, I first, // freestanding-deleted, + iter_difference_t n); // see \ref{algorithms.parallel.overloads} } template - NoThrowForwardIterator uninitialized_copy(InputIterator first, // freestanding - InputIterator last, - NoThrowForwardIterator result); + constexpr NoThrowForwardIterator uninitialized_copy(InputIterator first, // freestanding + InputIterator last, + NoThrowForwardIterator result); template - NoThrowForwardIterator uninitialized_copy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - ForwardIterator first, ForwardIterator last, + NoThrowForwardIterator uninitialized_copy(ExecutionPolicy&& exec, // freestanding-deleted, + ForwardIterator first, // see \ref{algorithms.parallel.overloads} + ForwardIterator last, NoThrowForwardIterator result); template - NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n, // freestanding - NoThrowForwardIterator result); + constexpr NoThrowForwardIterator uninitialized_copy_n(InputIterator first, // freestanding + Size n, + NoThrowForwardIterator result); template - NoThrowForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - ForwardIterator first, Size n, + NoThrowForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, // freestanding-deleted, + ForwardIterator first, // see \ref{algorithms.parallel.overloads} + Size n, NoThrowForwardIterator result); namespace ranges { template - using uninitialized_copy_result = in_out_result; // freestanding + using @\libglobal{uninitialized_copy_result}@ = in_out_result; // freestanding 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 + constexpr uninitialized_copy_result uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast); // freestanding template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> requires @\libconcept{constructible_from}@, range_reference_t> - uninitialized_copy_result, borrowed_iterator_t> + constexpr uninitialized_copy_result, borrowed_iterator_t> uninitialized_copy(IR&& in_range, OR&& out_range); // freestanding template - using uninitialized_copy_n_result = in_out_result; // freestanding + using @\libglobal{uninitialized_copy_n_result}@ = in_out_result; // freestanding 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 + constexpr uninitialized_copy_n_result uninitialized_copy_n(I ifirst, iter_difference_t n, // freestanding O ofirst, S olast); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S1, + @\exposconcept{nothrow-random-access-iterator}@ O, @\exposconcept{nothrow-sized-sentinel-for}@ S2> + requires @\libconcept{constructible_from}@, iter_reference_t> + uninitialized_copy_result + uninitialized_copy(Ep&& exec, I ifirst, S1 ilast, // freestanding-deleted, + O ofirst, S2 olast); // see \ref{algorithms.parallel.overloads} + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ IR, + @\exposconcept{nothrow-sized-random-access-range}@ OR> + requires @\libconcept{constructible_from}@, range_reference_t> + uninitialized_copy_result, borrowed_iterator_t> + uninitialized_copy(Ep&& exec, IR&& in_range, OR&& out_range); // freestanding-deleted, + // see \ref{algorithms.parallel.overloads} + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\exposconcept{nothrow-random-access-iterator}@ O, + @\exposconcept{nothrow-sized-sentinel-for}@ S> + requires @\libconcept{constructible_from}@, iter_reference_t> + uninitialized_copy_n_result + uninitialized_copy_n(Ep&& exec, I ifirst, iter_difference_t n, // freestanding-deleted, + O ofirst, S olast); // see \ref{algorithms.parallel.overloads} } template - NoThrowForwardIterator uninitialized_move(InputIterator first, // freestanding - InputIterator last, - NoThrowForwardIterator result); + constexpr NoThrowForwardIterator uninitialized_move(InputIterator first, // freestanding + InputIterator last, + NoThrowForwardIterator result); template - NoThrowForwardIterator uninitialized_move(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - ForwardIterator first, ForwardIterator last, + NoThrowForwardIterator uninitialized_move(ExecutionPolicy&& exec, // freestanding-deleted, + ForwardIterator first, // see \ref{algorithms.parallel.overloads} + ForwardIterator last, NoThrowForwardIterator result); template - pair + constexpr pair uninitialized_move_n(InputIterator first, Size n, // freestanding NoThrowForwardIterator result); template pair - uninitialized_move_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - ForwardIterator first, Size n, NoThrowForwardIterator result); + uninitialized_move_n(ExecutionPolicy&& exec, // freestanding-deleted, + ForwardIterator first, Size n, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator result); namespace ranges { template - using uninitialized_move_result = in_out_result; // freestanding + using @\libglobal{uninitialized_move_result}@ = in_out_result; // freestanding 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 + constexpr uninitialized_move_result uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast); // freestanding template<@\libconcept{input_range}@ IR, @\exposconcept{nothrow-forward-range}@ OR> requires @\libconcept{constructible_from}@, range_rvalue_reference_t> - uninitialized_move_result, borrowed_iterator_t> + constexpr uninitialized_move_result, borrowed_iterator_t> uninitialized_move(IR&& in_range, OR&& out_range); // freestanding template - using uninitialized_move_n_result = in_out_result; // freestanding + using @\libglobal{uninitialized_move_n_result}@ = in_out_result; // freestanding 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 + constexpr uninitialized_move_n_result uninitialized_move_n(I ifirst, iter_difference_t n, // freestanding O ofirst, S olast); + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S1, + @\exposconcept{nothrow-random-access-iterator}@ O, @\exposconcept{nothrow-sized-sentinel-for}@ S2> + requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> + uninitialized_move_result + uninitialized_move(Ep&& exec, I ifirst, S1 ilast, // freestanding-deleted, + O ofirst, S2 olast); // see \ref{algorithms.parallel.overloads} + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ IR, + @\exposconcept{nothrow-sized-random-access-range}@ OR> + requires @\libconcept{constructible_from}@, range_rvalue_reference_t> + uninitialized_move_result, borrowed_iterator_t> + uninitialized_move(Ep&& exec, IR&& in_range, OR&& out_range); // freestanding-deleted, + // see \ref{algorithms.parallel.overloads} + + template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, + @\exposconcept{nothrow-random-access-iterator}@ O, @\exposconcept{nothrow-sized-sentinel-for}@ S> + requires @\libconcept{constructible_from}@, iter_rvalue_reference_t> + uninitialized_move_n_result + uninitialized_move_n(Ep&& exec, I ifirst, iter_difference_t n, // freestanding-deleted, + O ofirst, S olast); // see \ref{algorithms.parallel.overloads} } template - void uninitialized_fill(NoThrowForwardIterator first, // freestanding - NoThrowForwardIterator last, const T& x); + constexpr void uninitialized_fill(NoThrowForwardIterator first, // freestanding + NoThrowForwardIterator last, const T& x); template - void uninitialized_fill(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, NoThrowForwardIterator last, + void uninitialized_fill(ExecutionPolicy&& exec, // freestanding-deleted, + NoThrowForwardIterator first, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator last, const T& x); template - NoThrowForwardIterator + constexpr NoThrowForwardIterator uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); // freestanding template NoThrowForwardIterator - uninitialized_fill_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, Size n, const T& x); + uninitialized_fill_n(ExecutionPolicy&& exec, // freestanding-deleted, + NoThrowForwardIterator first, // see \ref{algorithms.parallel.overloads} + 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); // freestanding + constexpr I uninitialized_fill(I first, S last, const T& x); // freestanding template<@\exposconcept{nothrow-forward-range}@ R, class T> requires @\libconcept{constructible_from}@, const T&> - borrowed_iterator_t uninitialized_fill(R&& r, const T& x); // freestanding + constexpr borrowed_iterator_t uninitialized_fill(R&& r, const T& x); // freestanding 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); // freestanding + constexpr I uninitialized_fill_n(I first, // freestanding + iter_difference_t n, const T& x); + + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I, + @\exposconcept{nothrow-sized-sentinel-for}@ S, class T> + requires @\libconcept{constructible_from}@, const T&> + I uninitialized_fill(Ep&& exec, I first, S last, const T& x); // freestanding-deleted, + // see \ref{algorithms.parallel.overloads} + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-sized-random-access-range}@ R, class T> + requires @\libconcept{constructible_from}@, const T&> + borrowed_iterator_t uninitialized_fill(Ep&& exec, R&& r, // freestanding-deleted, + const T& x); // see \ref{algorithms.parallel.overloads} + + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I, class T> + requires @\libconcept{constructible_from}@, const T&> + I uninitialized_fill_n(Ep&& exec, I first, // freestanding-deleted, + iter_difference_t n, const T& x); // see \ref{algorithms.parallel.overloads} } // \ref{specialized.construct}, \tcode{construct_at} @@ -364,14 +479,15 @@ constexpr void destroy(NoThrowForwardIterator first, // freestanding NoThrowForwardIterator last); template - void destroy(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, NoThrowForwardIterator last); + void destroy(ExecutionPolicy&& exec, // freestanding-deleted, + NoThrowForwardIterator first, // see \ref{algorithms.parallel.overloads} + NoThrowForwardIterator last); template constexpr NoThrowForwardIterator destroy_n(NoThrowForwardIterator first, // freestanding Size n); template - NoThrowForwardIterator destroy_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} - NoThrowForwardIterator first, Size n); + NoThrowForwardIterator destroy_n(ExecutionPolicy&& exec, // freestanding-deleted, + NoThrowForwardIterator first, Size n); // see \ref{algorithms.parallel.overloads} namespace ranges { template<@\libconcept{destructible}@ T> @@ -387,6 +503,20 @@ template<@\exposconcept{nothrow-input-iterator}@ I> requires @\libconcept{destructible}@> constexpr I destroy_n(I first, iter_difference_t n) noexcept; // freestanding + + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I, + @\exposconcept{nothrow-sized-sentinel-for}@ S> + requires @\libconcept{destructible}@> + I destroy(Ep&& exec, I first, S last) noexcept; // freestanding-deleted, + // see \ref{algorithms.parallel.overloads} + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-sized-random-access-range}@ R> + requires @\libconcept{destructible}@> + borrowed_iterator_t destroy(Ep&& exec, R&& r) noexcept; // freestanding-deleted, + // see \ref{algorithms.parallel.overloads} + template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I> + requires @\libconcept{destructible}@> + I destroy_n(Ep&& exec, I first, iter_difference_t n) noexcept; // freestanding-deleted, + // see \ref{algorithms.parallel.overloads} } // \ref{unique.ptr}, class template \tcode{unique_ptr} @@ -416,18 +546,22 @@ constexpr bool operator==(const unique_ptr& x, // freestanding const unique_ptr& y); template - bool operator<(const unique_ptr& x, const unique_ptr& y); // freestanding + constexpr bool operator<(const unique_ptr& x, // freestanding + const unique_ptr& y); template - bool operator>(const unique_ptr& x, const unique_ptr& y); // freestanding + constexpr bool operator>(const unique_ptr& x, // freestanding + const unique_ptr& y); template - bool operator<=(const unique_ptr& x, const unique_ptr& y); // freestanding + constexpr bool operator<=(const unique_ptr& x, // freestanding + const unique_ptr& y); template - bool operator>=(const unique_ptr& x, const unique_ptr& y); // freestanding + constexpr bool operator>=(const unique_ptr& x, // freestanding + 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> + constexpr compare_three_way_result_t::pointer, + typename unique_ptr::pointer> operator<=>(const unique_ptr& x, const unique_ptr& y); // freestanding template @@ -464,69 +598,71 @@ // \ref{util.smartptr.shared.create}, \tcode{shared_ptr} creation template - shared_ptr make_shared(Args&&... args); // \tcode{T} is not array + constexpr 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 + constexpr 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[]} + constexpr 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[]} + constexpr 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]} + constexpr shared_ptr make_shared(); // \tcode{T} is \tcode{U[N]} template - shared_ptr allocate_shared(const A& a); // \tcode{T} is \tcode{U[N]} + constexpr 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[]} + constexpr 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[]} + constexpr 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]} + constexpr 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]} + constexpr shared_ptr allocate_shared(const A& a, // \tcode{T} is \tcode{U[N]} + const remove_extent_t& u); template - shared_ptr make_shared_for_overwrite(); // \tcode{T} is not \tcode{U[]} + constexpr 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[]} + constexpr 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[]} + constexpr 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[]} + constexpr 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; + constexpr bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept; template - strong_ordering operator<=>(const shared_ptr& a, const shared_ptr& b) noexcept; + constexpr strong_ordering operator<=>(const shared_ptr& a, + const shared_ptr& b) noexcept; template - bool operator==(const shared_ptr& x, nullptr_t) noexcept; + constexpr bool operator==(const shared_ptr& x, nullptr_t) noexcept; template - strong_ordering operator<=>(const shared_ptr& x, nullptr_t) noexcept; + constexpr 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; + constexpr 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; + constexpr shared_ptr static_pointer_cast(const shared_ptr& r) noexcept; template - shared_ptr static_pointer_cast(shared_ptr&& r) noexcept; + constexpr shared_ptr static_pointer_cast(shared_ptr&& r) noexcept; template - shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept; + constexpr shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept; template - shared_ptr dynamic_pointer_cast(shared_ptr&& r) noexcept; + constexpr shared_ptr dynamic_pointer_cast(shared_ptr&& r) noexcept; template - shared_ptr const_pointer_cast(const shared_ptr& r) noexcept; + constexpr shared_ptr const_pointer_cast(const shared_ptr& r) noexcept; template - shared_ptr const_pointer_cast(shared_ptr&& r) noexcept; + constexpr shared_ptr const_pointer_cast(shared_ptr&& r) noexcept; template shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept; template @@ -534,7 +670,7 @@ // \ref{util.smartptr.getdeleter}, \tcode{shared_ptr} \tcode{get_deleter} template - D* get_deleter(const shared_ptr& p) noexcept; + constexpr D* get_deleter(const shared_ptr& p) noexcept; // \ref{util.smartptr.shared.io}, \tcode{shared_ptr} I/O template @@ -544,7 +680,7 @@ template class weak_ptr; // \ref{util.smartptr.weak.spec}, \tcode{weak_ptr} specialized algorithms - template void swap(weak_ptr& a, weak_ptr& b) noexcept; + template constexpr void swap(weak_ptr& a, weak_ptr& b) noexcept; // \ref{util.smartptr.ownerless}, class template \tcode{owner_less} template struct owner_less; @@ -574,7 +710,7 @@ // \ref{out.ptr}, function template \tcode{out_ptr} template - auto out_ptr(Smart& s, Args&&... args); // freestanding + constexpr auto out_ptr(Smart& s, Args&&... args); // freestanding // \ref{inout.ptr.t}, class template \tcode{inout_ptr_t} template @@ -582,7 +718,23 @@ // \ref{inout.ptr}, function template \tcode{inout_ptr} template - auto inout_ptr(Smart& s, Args&&... args); // freestanding + constexpr auto inout_ptr(Smart& s, Args&&... args); // freestanding + + // \ref{indirect}, class template \tcode{indirect} + template> + class indirect; + + // \ref{indirect.hash}, hash support + template struct hash>; + + // \ref{polymorphic}, class template \tcode{polymorphic} + template> + class polymorphic; + + namespace pmr { + template using indirect = indirect>; + template using polymorphic = polymorphic>; + } } \end{codeblock} @@ -829,7 +981,7 @@ \indexlibraryglobal{assume_aligned}% \begin{itemdecl} template - [[nodiscard]] constexpr T* assume_aligned(T* ptr); + constexpr T* assume_aligned(T* ptr); \end{itemdecl} \begin{itemdescr} @@ -839,9 +991,9 @@ \pnum \expects -\tcode{ptr} points to an object \tcode{X} of +\tcode{ptr} points to an object $X$ of a type similar\iref{conv.qual} to \tcode{T}, -where \tcode{X} has alignment \tcode{N}\iref{basic.align}. +where $X$ has alignment \tcode{N}\iref{basic.align}. \pnum \returns @@ -853,17 +1005,39 @@ \pnum \begin{note} -The alignment assumption on an object \tcode{X} +The alignment assumption on an object $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} +for those operations on $X$ that access $X$ through the pointer returned by \tcode{assume_aligned}. \end{note} \end{itemdescr} +\indexlibraryglobal{is_sufficiently_aligned}% +\begin{itemdecl} +template + bool is_sufficiently_aligned(T* ptr); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{p} points to +an object \tcode{X} of a type similar\iref{conv.qual} to \tcode{T}. + +\pnum +\returns +\tcode{true} if \tcode{X} has alignment at least \tcode{Alignment}, +otherwise \tcode{false}. + +\pnum +\throws +Nothing. +\end{itemdescr} + \rSec2[obj.lifetime]{Explicit lifetime management} \indexlibraryglobal{start_lifetime_as}% @@ -961,6 +1135,128 @@ a pointer that compares equal to \tcode{p}\iref{expr.eq}. \end{itemdescr} +\indexlibraryglobal{trivially_relocate}% +\begin{itemdecl} +template + T* trivially_relocate(T* first, T* last, T* result); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_trivially_relocatable_v \&\& !is_const_v} is \tcode{true}. +\tcode{T} is not an array of unknown bound. + +\pnum +\expects +\begin{itemize} +\item + \range{first}{last} is a valid range. +\item + \range{result}{result + (last - first)} denotes a region of storage that + is a subset of the region reachable through \tcode{result}\iref{basic.compound} + and suitably aligned for the type \tcode{T}. +\item + No element in the range \range{first}{last} is a potentially-overlapping subobject. +\end{itemize} + +\pnum +\ensures +No effect if \tcode{result == first} is \tcode{true}. +Otherwise, the range denoted by \range{result}{result + (last - first)} +contains objects (including subobjects) whose lifetime has begun and whose +object representations are the original object representations of the +corresponding objects in the source range \range{first}{last} except +for any parts of the object representations used by the implementation to +represent type information\iref{intro.object}. If any of the objects has +union type, its active member is the same as that of the corresponding object +in the source range. If any of the aforementioned objects has a non-static +data member of reference type, that reference refers to the same entity as +does the corresponding reference in the source range. The lifetimes of the +original objects in the source range have ended. + +\pnum +\returns +\tcode{result + (last - first)}. + +\pnum +\throws +Nothing. + +\pnum +\complexity +Linear in the length of the source range. + +\pnum +\remarks +The destination region of storage is considered reused\iref{basic.life}. +No constructors or destructors are invoked. + +\begin{note} +Overlapping ranges are supported. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{relocate}% +\begin{itemdecl} +template + constexpr T* relocate(T* first, T* last, T* result); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_nothrow_relocatable_v \&\& !is_const_v} is \tcode{true}. +\tcode{T} is not an array of unknown bound. + +\pnum +\expects +\begin{itemize} +\item + \range{first}{last} is a valid range. +\item + \range{result}{result + (last - first)} denotes a region of storage that is + a subset of the region reachable through \tcode{result}\iref{basic.compound} + and suitably aligned for the type \tcode{T}. +\item + No element in the range \range{first}{last} is a potentially-overlapping + subobject. +\end{itemize} + +\pnum +\effects +\begin{itemize} +\item + If \tcode{result == first} is \tcode{true}, no effect; +\item + otherwise, if not called during constant evaluation and + \tcode{is_trivially_relocatable_v} is \tcode{true}, then has + effects equivalent to: \tcode{trivially_relocate(first, last, result);} +\item + otherwise, for each integer \tcode{i} in \range{0}{last - first}, + \begin{itemize} + \item + if \tcode{T} is an array type, equivalent to: + \tcode{relocate(begin(first[i]), end(first[i]), *start_lifetime_as(result + i));} + \item + otherwise, equivalent to: + \tcode{construct_at(result + i, std::move(first[i])); destroy_at(first + i);} + \end{itemize} +\end{itemize} + +\pnum +\returns +\tcode{result + (last - first)}. + +\pnum +\throws +Nothing. + +\begin{note} +Overlapping ranges are supported. +\end{note} +\end{itemdescr} + \rSec2[allocator.tag]{Allocator argument tag} \indexlibraryglobal{allocator_arg_t}% @@ -1379,10 +1675,9 @@ 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); - [[nodiscard]] static constexpr allocation_result + static constexpr pointer allocate(Alloc& a, size_type n); + static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint); + static constexpr allocation_result allocate_at_least(Alloc& a, size_type n); static constexpr void deallocate(Alloc& a, pointer p, size_type n); @@ -1550,7 +1845,7 @@ \indexlibrarymember{allocate}{allocator_traits}% \begin{itemdecl} -[[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n); +static constexpr pointer allocate(Alloc& a, size_type n); \end{itemdecl} \begin{itemdescr} @@ -1561,7 +1856,7 @@ \indexlibrarymember{allocate}{allocator_traits}% \begin{itemdecl} -[[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint); +static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint); \end{itemdecl} \begin{itemdescr} @@ -1572,8 +1867,7 @@ \indexlibrarymember{allocate_at_least}{allocator_traits}% \begin{itemdecl} -[[nodiscard]] static constexpr allocation_result - allocate_at_least(Alloc& a, size_type n); +static constexpr allocation_result allocate_at_least(Alloc& a, size_type n); \end{itemdecl} \begin{itemdescr} @@ -1634,7 +1928,7 @@ \pnum \returns \tcode{a.max_size()} if that expression is well-formed; otherwise, -\tcode{numeric_limits::\brk{}max()/sizeof(value_type)}. +\tcode{numeric_limits::\brk{}max() / sizeof(value_type)}. \end{itemdescr} \indexlibrarymember{select_on_container_copy_construction}{allocator_traits}% @@ -1673,7 +1967,7 @@ \begin{codeblock} namespace std { template class allocator { - public: + public: using value_type = T; using size_type = size_t; using difference_type = ptrdiff_t; @@ -1685,8 +1979,8 @@ 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 T* allocate(size_t n); + constexpr allocation_result allocate_at_least(size_t n); constexpr void deallocate(T* p, size_t n); }; } @@ -1707,7 +2001,7 @@ \indexlibrarymember{allocate}{allocator}% \begin{itemdecl} -[[nodiscard]] constexpr T* allocate(size_t n); +constexpr T* allocate(size_t n); \end{itemdecl} \begin{itemdescr} @@ -1737,7 +2031,7 @@ \indexlibrarymember{allocate_at_least}{allocator}% \begin{itemdecl} -[[nodiscard]] constexpr allocation_result allocate_at_least(size_t n); +constexpr allocation_result allocate_at_least(size_t n); \end{itemdecl} \begin{itemdescr} @@ -1844,12 +2138,10 @@ \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} @@ -1867,8 +2159,35 @@ 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. +In the case of \tcode{calloc}, +the objects are created before the storage is zeroed. +\end{itemdescr} + +\indexlibraryglobal{realloc}% +\begin{itemdecl} +void* realloc(void* ptr, size_t size); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{free(ptr)} has well-defined behavior. + +\pnum +\effects +If \tcode{ptr} is not null and \tcode{size} is zero, +the behavior is erroneous and the effects are implementation-defined. +Otherwise, this function has the semantics specified in the C standard library. + +\pnum +\remarks +This function does not attempt to allocate storage +by calling \tcode{::operator new()}\iref{new.delete}. +When a non-null pointer is returned, +this function implicitly creates objects\iref{intro.object} +in the returned region of storage and +returns a pointer to a suitable created object. +The objects are created before the storage is copied. \end{itemdescr} \indexlibraryglobal{free}% @@ -1935,7 +2254,7 @@ \rSec3[unique.ptr.dltr]{Default deleters} -\rSec4[unique.ptr.dltr.general]{In general} +\rSec4[unique.ptr.dltr.general]{General} \pnum The class template \tcode{default_delete} serves as the default deleter (destruction policy) @@ -2086,6 +2405,14 @@ } \end{codeblock} +\pnum +A program that instantiates the definition of \tcode{unique_ptr} +is ill-formed if \tcode{T*} is an invalid type. +\begin{note} +This prevents the instantiation of specializations such as +\tcode{unique_ptr} and \tcode{unique_ptr}. +\end{note} + \pnum The default type for the template parameter \tcode{D} is \tcode{default_delete}. A client-supplied template argument @@ -2436,9 +2763,13 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{reference_converts_from_temporary_v, decltype(\linebreak{}*declval())>} is \tcode{false}. + \pnum \expects -\tcode{get() != nullptr}. +\tcode{get() != nullptr} is \tcode{true}. \pnum \returns @@ -2916,7 +3247,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} @@ -2948,7 +3279,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} @@ -2960,7 +3291,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} @@ -2972,7 +3303,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} @@ -2986,8 +3317,8 @@ template requires @\libconcept{three_way_comparable_with}@::pointer, typename unique_ptr::pointer> - compare_three_way_result_t::pointer, - typename unique_ptr::pointer> + constexpr compare_three_way_result_t::pointer, + typename unique_ptr::pointer> operator<=>(const unique_ptr& x, const unique_ptr& y); \end{itemdecl} @@ -3130,7 +3461,7 @@ class bad_weak_ptr : public exception { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -3141,7 +3472,7 @@ \indexlibrarymember{what}{bad_weak_ptr}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3173,69 +3504,69 @@ constexpr shared_ptr() noexcept; constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { } template - explicit shared_ptr(Y* p); + constexpr explicit shared_ptr(Y* p); template - shared_ptr(Y* p, D d); + constexpr shared_ptr(Y* p, D d); template - shared_ptr(Y* p, D d, A a); + constexpr shared_ptr(Y* p, D d, A a); template - shared_ptr(nullptr_t p, D d); + constexpr shared_ptr(nullptr_t p, D d); template - shared_ptr(nullptr_t p, D d, A a); + constexpr shared_ptr(nullptr_t p, D d, A a); template - shared_ptr(const shared_ptr& r, element_type* p) noexcept; + constexpr 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; + constexpr shared_ptr(shared_ptr&& r, element_type* p) noexcept; + constexpr shared_ptr(const shared_ptr& r) noexcept; template - shared_ptr(const shared_ptr& r) noexcept; - shared_ptr(shared_ptr&& r) noexcept; + constexpr shared_ptr(const shared_ptr& r) noexcept; + constexpr shared_ptr(shared_ptr&& r) noexcept; template - shared_ptr(shared_ptr&& r) noexcept; + constexpr shared_ptr(shared_ptr&& r) noexcept; template - explicit shared_ptr(const weak_ptr& r); + constexpr explicit shared_ptr(const weak_ptr& r); template - shared_ptr(unique_ptr&& r); + constexpr shared_ptr(unique_ptr&& r); // \ref{util.smartptr.shared.dest}, destructor - ~shared_ptr(); + constexpr ~shared_ptr(); // \ref{util.smartptr.shared.assign}, assignment - shared_ptr& operator=(const shared_ptr& r) noexcept; + constexpr shared_ptr& operator=(const shared_ptr& r) noexcept; template - shared_ptr& operator=(const shared_ptr& r) noexcept; - shared_ptr& operator=(shared_ptr&& r) noexcept; + constexpr shared_ptr& operator=(const shared_ptr& r) noexcept; + constexpr shared_ptr& operator=(shared_ptr&& r) noexcept; template - shared_ptr& operator=(shared_ptr&& r) noexcept; + constexpr shared_ptr& operator=(shared_ptr&& r) noexcept; template - shared_ptr& operator=(unique_ptr&& r); + constexpr shared_ptr& operator=(unique_ptr&& r); // \ref{util.smartptr.shared.mod}, modifiers - void swap(shared_ptr& r) noexcept; - void reset() noexcept; + constexpr void swap(shared_ptr& r) noexcept; + constexpr void reset() noexcept; template - void reset(Y* p); + constexpr void reset(Y* p); template - void reset(Y* p, D d); + constexpr void reset(Y* p, D d); template - void reset(Y* p, D d, A a); + constexpr 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; + constexpr element_type* get() const noexcept; + constexpr T& operator*() const noexcept; + constexpr T* operator->() const noexcept; + constexpr element_type& operator[](ptrdiff_t i) const; + constexpr long use_count() const noexcept; + constexpr explicit operator bool() const noexcept; template - bool owner_before(const shared_ptr& b) const noexcept; + constexpr bool owner_before(const shared_ptr& b) const noexcept; template - bool owner_before(const weak_ptr& b) const noexcept; + constexpr bool owner_before(const weak_ptr& b) const noexcept; size_t owner_hash() const noexcept; template - bool owner_equal(const shared_ptr& b) const noexcept; + constexpr bool owner_equal(const shared_ptr& b) const noexcept; template - bool owner_equal(const weak_ptr& b) const noexcept; + constexpr bool owner_equal(const weak_ptr& b) const noexcept; }; template @@ -3275,7 +3606,7 @@ reflect modifications that can introduce data races. \pnum -For the purposes of subclause \ref{smartptr}, +For the purposes of \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 @@ -3293,10 +3624,10 @@ 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)); +if (p != nullptr && p->@\exposid{weak-this}@.expired()) + p->@\exposid{weak-this}@ = shared_ptr>(*this, const_cast*>(p)); \end{codeblock} -The assignment to the \tcode{weak_this} member is not atomic and +The assignment to the \exposid{weak-this} member is not atomic and conflicts with any potentially concurrent access to the same object\iref{intro.multithread}. \indexlibraryctor{shared_ptr}% @@ -3312,7 +3643,7 @@ \indexlibraryctor{shared_ptr}% \begin{itemdecl} -template explicit shared_ptr(Y* p); +template constexpr explicit shared_ptr(Y* p); \end{itemdecl} \begin{itemdescr} @@ -3363,10 +3694,10 @@ \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); +template constexpr shared_ptr(Y* p, D d); +template constexpr shared_ptr(Y* p, D d, A a); +template constexpr shared_ptr(nullptr_t p, D d); +template constexpr shared_ptr(nullptr_t p, D d, A a); \end{itemdecl} \begin{itemdescr} @@ -3418,8 +3749,8 @@ \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; +template constexpr shared_ptr(const shared_ptr& r, element_type* p) noexcept; +template constexpr shared_ptr(shared_ptr&& r, element_type* p) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3451,8 +3782,8 @@ \indexlibraryctor{shared_ptr}% \begin{itemdecl} -shared_ptr(const shared_ptr& r) noexcept; -template shared_ptr(const shared_ptr& r) noexcept; +constexpr shared_ptr(const shared_ptr& r) noexcept; +template constexpr shared_ptr(const shared_ptr& r) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3473,8 +3804,8 @@ \indexlibraryctor{shared_ptr}% \begin{itemdecl} -shared_ptr(shared_ptr&& r) noexcept; -template shared_ptr(shared_ptr&& r) noexcept; +constexpr shared_ptr(shared_ptr&& r) noexcept; +template constexpr shared_ptr(shared_ptr&& r) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3495,7 +3826,7 @@ \indexlibraryctor{shared_ptr}% \indexlibraryglobal{weak_ptr}% \begin{itemdecl} -template explicit shared_ptr(const weak_ptr& r); +template constexpr explicit shared_ptr(const weak_ptr& r); \end{itemdecl} \begin{itemdescr} @@ -3521,7 +3852,7 @@ \indexlibraryctor{shared_ptr}% \indexlibraryglobal{unique_ptr}% \begin{itemdecl} -template shared_ptr(unique_ptr&& r); +template constexpr shared_ptr(unique_ptr&& r); \end{itemdecl} \begin{itemdescr} @@ -3543,7 +3874,7 @@ \indexlibrarydtor{shared_ptr}% \begin{itemdecl} -~shared_ptr(); +constexpr ~shared_ptr(); \end{itemdecl} \begin{itemdescr} @@ -3577,8 +3908,8 @@ \indexlibrarymember{operator=}{shared_ptr}% \begin{itemdecl} -shared_ptr& operator=(const shared_ptr& r) noexcept; -template shared_ptr& operator=(const shared_ptr& r) noexcept; +constexpr shared_ptr& operator=(const shared_ptr& r) noexcept; +template constexpr shared_ptr& operator=(const shared_ptr& r) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3609,8 +3940,8 @@ \indexlibrarymember{operator=}{shared_ptr}% \begin{itemdecl} -shared_ptr& operator=(shared_ptr&& r) noexcept; -template shared_ptr& operator=(shared_ptr&& r) noexcept; +constexpr shared_ptr& operator=(shared_ptr&& r) noexcept; +template constexpr shared_ptr& operator=(shared_ptr&& r) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3625,7 +3956,7 @@ \indexlibrarymember{operator=}{shared_ptr}% \begin{itemdecl} -template shared_ptr& operator=(unique_ptr&& r); +template constexpr shared_ptr& operator=(unique_ptr&& r); \end{itemdecl} \begin{itemdescr} @@ -3642,7 +3973,7 @@ \indexlibrarymember{swap}{shared_ptr}% \begin{itemdecl} -void swap(shared_ptr& r) noexcept; +constexpr void swap(shared_ptr& r) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3654,7 +3985,7 @@ \indexlibrarymember{reset}{shared_ptr}% \begin{itemdecl} -void reset() noexcept; +constexpr void reset() noexcept; \end{itemdecl} \begin{itemdescr} @@ -3665,7 +3996,7 @@ \indexlibrarymember{reset}{shared_ptr}% \begin{itemdecl} -template void reset(Y* p); +template constexpr void reset(Y* p); \end{itemdecl} \begin{itemdescr} @@ -3676,7 +4007,7 @@ \indexlibrarymember{reset}{shared_ptr}% \begin{itemdecl} -template void reset(Y* p, D d); +template constexpr void reset(Y* p, D d); \end{itemdecl} \begin{itemdescr} @@ -3687,7 +4018,7 @@ \indexlibrarymember{reset}{shared_ptr}% \begin{itemdecl} -template void reset(Y* p, D d, A a); +template constexpr void reset(Y* p, D d, A a); \end{itemdecl} \begin{itemdescr} @@ -3699,7 +4030,7 @@ \rSec4[util.smartptr.shared.obs]{Observers} \indexlibrarymember{get}{shared_ptr}% \begin{itemdecl} -element_type* get() const noexcept; +constexpr element_type* get() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3710,7 +4041,7 @@ \indexlibrarymember{operator*}{shared_ptr}% \begin{itemdecl} -T& operator*() const noexcept; +constexpr T& operator*() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3733,7 +4064,7 @@ \indexlibrarymember{operator->}{shared_ptr}% \begin{itemdecl} -T* operator->() const noexcept; +constexpr T* operator->() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3756,14 +4087,17 @@ \indexlibrarymember{operator[]}{shared_ptr}% \begin{itemdecl} -element_type& operator[](ptrdiff_t i) const; +constexpr element_type& operator[](ptrdiff_t i) const; \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{get() != nullptr \&\& i >= 0}. -If \tcode{T} is \tcode{U[N]}, \tcode{i < N}. +\tcode{get() != nullptr} is \tcode{true}. + +\pnum +\hardexpects +$\tcode{i} \ge 0$. If \tcode{T} is \tcode{U[N]}, $\tcode{i} < \tcode{N}$. \pnum \returns @@ -3784,7 +4118,7 @@ \indexlibrarymember{use_count}{shared_ptr}% \begin{itemdecl} -long use_count() const noexcept; +constexpr long use_count() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3822,7 +4156,7 @@ \indexlibrarymember{operator bool}{shared_ptr}% \begin{itemdecl} -explicit operator bool() const noexcept; +constexpr explicit operator bool() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3833,8 +4167,8 @@ \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; +template constexpr bool owner_before(const shared_ptr& b) const noexcept; +template constexpr bool owner_before(const weak_ptr& b) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3866,9 +4200,9 @@ \indexlibrarymember{owner_equal}{shared_ptr}% \begin{itemdecl} template - bool owner_equal(const shared_ptr& b) const noexcept; + constexpr bool owner_equal(const shared_ptr& b) const noexcept; template - bool owner_equal(const weak_ptr& b) const noexcept; + constexpr bool owner_equal(const weak_ptr& b) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3897,13 +4231,13 @@ \indexlibraryglobal{allocate_shared}% \begin{itemdecl} template - shared_ptr make_shared(@\placeholdernc{args}@); + constexpr shared_ptr make_shared(@\placeholdernc{args}@); template - shared_ptr allocate_shared(const A& a, @\placeholdernc{args}@); + constexpr shared_ptr allocate_shared(const A& a, @\placeholdernc{args}@); template - shared_ptr make_shared_for_overwrite(@\placeholdernc{args}@); + constexpr shared_ptr make_shared_for_overwrite(@\placeholdernc{args}@); template - shared_ptr allocate_shared_for_overwrite(const A& a, @\placeholdernc{args}@); + constexpr shared_ptr allocate_shared_for_overwrite(const A& a, @\placeholdernc{args}@); \end{itemdecl} \begin{itemdescr} @@ -3972,15 +4306,15 @@ \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...)} + \item \tcode{allocator_traits::construct(a2, pu, v)} or + \item \tcode{allocator_traits::construct(a2, pu, 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}. + where \tcode{pu} is a pointer of type \tcode{remove_cv_t*} + pointing to storage + suitable to hold an object of type \tcode{remove_cv_t} and + \tcode{a2} of type \tcode{A2} is a potentially rebound copy of + the allocator \tcode{a} passed to \tcode{allocate_shared}. \item When a (sub)object of non-array type \tcode{U} is specified to have a default initial value, @@ -3991,13 +4325,13 @@ \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}. + \tcode{allocate_shared} initializes this (sub)object + via the expression \tcode{allocator_traits::construct(a2, pu)}, + where \tcode{pu} is a pointer of type \tcode{remove_cv_t*} + pointing to storage + suitable to hold an object of type \tcode{remove_cv_t} and + \tcode{a2} of type \tcode{A2} is a potentially rebound copy of + the allocator \tcode{a} passed to \tcode{allocate_shared}. \item When a (sub)object of non-array type \tcode{U} is initialized by \tcode{make_shared_for_overwrite} or\linebreak % avoid Overfull @@ -4014,18 +4348,20 @@ 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}. + that was initialized by \tcode{make_shared}, + \tcode{make_shared_for_overwrite}, or \tcode{allocate_shared_for_overwrite} + is to be destroyed, + it is destroyed via the expression \tcode{pu->\~{}U()} where + \tcode{pu} 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}. + \tcode{allocator_traits::destroy(a2, pu)} where + \tcode{pu} is a pointer of type \tcode{remove_cv_t*} + pointing to that object of type \tcode{remove_cv_t} and + \tcode{a2} of type \tcode{A2} is a potentially rebound copy of + the allocator \tcode{a} passed to \tcode{allocate_shared}. \end{itemize} \begin{note} These functions will typically allocate more memory than \tcode{sizeof(T)} to @@ -4037,9 +4373,9 @@ \indexlibraryglobal{allocate_shared}% \begin{itemdecl} template - shared_ptr make_shared(Args&&... args); // \tcode{T} is not array + constexpr 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 + constexpr shared_ptr allocate_shared(const A& a, Args&&... args); // \tcode{T} is not array \end{itemdecl} \begin{itemdescr} @@ -4071,10 +4407,10 @@ \indexlibraryglobal{make_shared}% \indexlibraryglobal{allocate_shared}% \begin{itemdecl} -template shared_ptr - make_shared(size_t N); // \tcode{T} is \tcode{U[]} +template + constexpr 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[]} + constexpr shared_ptr allocate_shared(const A& a, size_t N); // \tcode{T} is \tcode{U[]} \end{itemdecl} \begin{itemdescr} @@ -4103,9 +4439,9 @@ \indexlibraryglobal{allocate_shared}% \begin{itemdecl} template - shared_ptr make_shared(); // \tcode{T} is \tcode{U[N]} + constexpr shared_ptr make_shared(); // \tcode{T} is \tcode{U[N]} template - shared_ptr allocate_shared(const A& a); // \tcode{T} is \tcode{U[N]} + constexpr shared_ptr allocate_shared(const A& a); // \tcode{T} is \tcode{U[N]} \end{itemdecl} \begin{itemdescr} @@ -4133,11 +4469,11 @@ \indexlibraryglobal{allocate_shared}% \begin{itemdecl} template - shared_ptr make_shared(size_t N, - const remove_extent_t& u); // \tcode{T} is \tcode{U[]} + constexpr 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[]} + constexpr shared_ptr allocate_shared(const A& a, size_t N, + const remove_extent_t& u); // \tcode{T} is \tcode{U[]} \end{itemdecl} \begin{itemdescr} @@ -4168,10 +4504,10 @@ \indexlibraryglobal{allocate_shared}% \begin{itemdecl} template - shared_ptr make_shared(const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} + constexpr 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]} + constexpr shared_ptr allocate_shared(const A& a, + const remove_extent_t& u); // \tcode{T} is \tcode{U[N]} \end{itemdecl} \begin{itemdescr} @@ -4202,9 +4538,9 @@ \indexlibraryglobal{allocate_shared}% \begin{itemdecl} template - shared_ptr make_shared_for_overwrite(); + constexpr shared_ptr make_shared_for_overwrite(); template - shared_ptr allocate_shared_for_overwrite(const A& a); + constexpr shared_ptr allocate_shared_for_overwrite(const A& a); \end{itemdecl} \begin{itemdescr} @@ -4233,9 +4569,9 @@ \indexlibraryglobal{allocate_shared}% \begin{itemdecl} template - shared_ptr make_shared_for_overwrite(size_t N); + constexpr shared_ptr make_shared_for_overwrite(size_t N); template - shared_ptr allocate_shared_for_overwrite(const A& a, size_t N); + constexpr shared_ptr allocate_shared_for_overwrite(const A& a, size_t N); \end{itemdecl} \begin{itemdescr} @@ -4262,7 +4598,7 @@ \indexlibrarymember{operator==}{shared_ptr}% \begin{itemdecl} template - bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept; + constexpr bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4274,7 +4610,7 @@ \indexlibrarymember{operator==}{shared_ptr}% \begin{itemdecl} template - bool operator==(const shared_ptr& a, nullptr_t) noexcept; + constexpr bool operator==(const shared_ptr& a, nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4286,7 +4622,7 @@ \indexlibrarymember{operator<=>}{shared_ptr}% \begin{itemdecl} template - strong_ordering operator<=>(const shared_ptr& a, const shared_ptr& b) noexcept; + constexpr strong_ordering operator<=>(const shared_ptr& a, const shared_ptr& b) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4304,7 +4640,7 @@ \indexlibrarymember{operator<=>}{shared_ptr}% \begin{itemdecl} template - strong_ordering operator<=>(const shared_ptr& a, nullptr_t) noexcept; + constexpr strong_ordering operator<=>(const shared_ptr& a, nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4320,7 +4656,7 @@ \indexlibrarymember{swap}{shared_ptr}% \begin{itemdecl} template - void swap(shared_ptr& a, shared_ptr& b) noexcept; + constexpr void swap(shared_ptr& a, shared_ptr& b) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4334,9 +4670,9 @@ \indexlibrarymember{static_pointer_cast}{shared_ptr}% \begin{itemdecl} template - shared_ptr static_pointer_cast(const shared_ptr& r) noexcept; + constexpr shared_ptr static_pointer_cast(const shared_ptr& r) noexcept; template - shared_ptr static_pointer_cast(shared_ptr&& r) noexcept; + constexpr shared_ptr static_pointer_cast(shared_ptr&& r) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4356,7 +4692,7 @@ \begin{note} The seemingly equivalent expression \tcode{shared_ptr(static_cast(r.get()))} -will eventually result in undefined behavior, attempting to delete the +can result in undefined behavior, attempting to delete the same object twice. \end{note} \end{itemdescr} @@ -4364,9 +4700,9 @@ \indexlibrarymember{dynamic_pointer_cast}{shared_ptr}% \begin{itemdecl} template - shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept; + constexpr shared_ptr dynamic_pointer_cast(const shared_ptr& r) noexcept; template - shared_ptr dynamic_pointer_cast(shared_ptr&& r) noexcept; + constexpr shared_ptr dynamic_pointer_cast(shared_ptr&& r) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4393,7 +4729,7 @@ \pnum \begin{note} The seemingly equivalent expression -\tcode{shared_ptr(dynamic_cast(r.get()))} will eventually result in +\tcode{shared_ptr(dynamic_cast(r.get()))} can result in undefined behavior, attempting to delete the same object twice. \end{note} \end{itemdescr} @@ -4401,9 +4737,9 @@ \indexlibrarymember{const_pointer_cast}{shared_ptr}% \begin{itemdecl} template - shared_ptr const_pointer_cast(const shared_ptr& r) noexcept; + constexpr shared_ptr const_pointer_cast(const shared_ptr& r) noexcept; template - shared_ptr const_pointer_cast(shared_ptr&& r) noexcept; + constexpr shared_ptr const_pointer_cast(shared_ptr&& r) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4422,7 +4758,7 @@ \pnum \begin{note} The seemingly equivalent expression -\tcode{shared_ptr(const_cast(r.get()))} will eventually result in +\tcode{shared_ptr(const_cast(r.get()))} can result in undefined behavior, attempting to delete the same object twice. \end{note} \end{itemdescr} @@ -4451,7 +4787,7 @@ \pnum \begin{note} The seemingly equivalent expression -\tcode{shared_ptr(reinterpret_cast(r.get()))} will eventually result in +\tcode{shared_ptr(reinterpret_cast(r.get()))} can result in undefined behavior, attempting to delete the same object twice. \end{note} \end{itemdescr} @@ -4461,7 +4797,7 @@ \indexlibrarymember{get_deleter}{shared_ptr}% \begin{itemdecl} template - D* get_deleter(const shared_ptr& p) noexcept; + constexpr D* get_deleter(const shared_ptr& p) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4518,44 +4854,44 @@ // \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; + constexpr weak_ptr(const shared_ptr& r) noexcept; + constexpr weak_ptr(const weak_ptr& r) noexcept; template - weak_ptr(const weak_ptr& r) noexcept; - weak_ptr(weak_ptr&& r) noexcept; + constexpr weak_ptr(const weak_ptr& r) noexcept; + constexpr weak_ptr(weak_ptr&& r) noexcept; template - weak_ptr(weak_ptr&& r) noexcept; + constexpr weak_ptr(weak_ptr&& r) noexcept; // \ref{util.smartptr.weak.dest}, destructor - ~weak_ptr(); + constexpr ~weak_ptr(); // \ref{util.smartptr.weak.assign}, assignment - weak_ptr& operator=(const weak_ptr& r) noexcept; + constexpr weak_ptr& operator=(const weak_ptr& r) noexcept; template - weak_ptr& operator=(const weak_ptr& r) noexcept; + constexpr weak_ptr& operator=(const weak_ptr& r) noexcept; template - weak_ptr& operator=(const shared_ptr& r) noexcept; - weak_ptr& operator=(weak_ptr&& r) noexcept; + constexpr weak_ptr& operator=(const shared_ptr& r) noexcept; + constexpr weak_ptr& operator=(weak_ptr&& r) noexcept; template - weak_ptr& operator=(weak_ptr&& r) noexcept; + constexpr weak_ptr& operator=(weak_ptr&& r) noexcept; // \ref{util.smartptr.weak.mod}, modifiers - void swap(weak_ptr& r) noexcept; - void reset() noexcept; + constexpr void swap(weak_ptr& r) noexcept; + constexpr void reset() noexcept; // \ref{util.smartptr.weak.obs}, observers - long use_count() const noexcept; - bool expired() const noexcept; - shared_ptr lock() const noexcept; + constexpr long use_count() const noexcept; + constexpr bool expired() const noexcept; + constexpr shared_ptr lock() const noexcept; template - bool owner_before(const shared_ptr& b) const noexcept; + constexpr bool owner_before(const shared_ptr& b) const noexcept; template - bool owner_before(const weak_ptr& b) const noexcept; + constexpr bool owner_before(const weak_ptr& b) const noexcept; size_t owner_hash() const noexcept; template - bool owner_equal(const shared_ptr& b) const noexcept; + constexpr bool owner_equal(const shared_ptr& b) const noexcept; template - bool owner_equal(const weak_ptr& b) const noexcept; + constexpr bool owner_equal(const weak_ptr& b) const noexcept; }; template @@ -4588,9 +4924,9 @@ \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; +constexpr weak_ptr(const weak_ptr& r) noexcept; +template constexpr weak_ptr(const weak_ptr& r) noexcept; +template constexpr weak_ptr(const shared_ptr& r) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4613,8 +4949,8 @@ \indexlibraryctor{weak_ptr}% \begin{itemdecl} -weak_ptr(weak_ptr&& r) noexcept; -template weak_ptr(weak_ptr&& r) noexcept; +constexpr weak_ptr(weak_ptr&& r) noexcept; +template constexpr weak_ptr(weak_ptr&& r) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4636,7 +4972,7 @@ \indexlibrarydtor{weak_ptr}% \begin{itemdecl} -~weak_ptr(); +constexpr ~weak_ptr(); \end{itemdecl} \begin{itemdescr} @@ -4650,9 +4986,9 @@ \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; +constexpr weak_ptr& operator=(const weak_ptr& r) noexcept; +template constexpr weak_ptr& operator=(const weak_ptr& r) noexcept; +template constexpr weak_ptr& operator=(const shared_ptr& r) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4672,8 +5008,8 @@ \indexlibrarymember{operator=}{weak_ptr}% \begin{itemdecl} -weak_ptr& operator=(weak_ptr&& r) noexcept; -template weak_ptr& operator=(weak_ptr&& r) noexcept; +constexpr weak_ptr& operator=(weak_ptr&& r) noexcept; +template constexpr weak_ptr& operator=(weak_ptr&& r) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4689,7 +5025,7 @@ \rSec4[util.smartptr.weak.mod]{Modifiers} \indexlibrarymember{swap}{weak_ptr}% \begin{itemdecl} -void swap(weak_ptr& r) noexcept; +constexpr void swap(weak_ptr& r) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4700,7 +5036,7 @@ \indexlibrarymember{reset}{weak_ptr}% \begin{itemdecl} -void reset() noexcept; +constexpr void reset() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4712,7 +5048,7 @@ \rSec4[util.smartptr.weak.obs]{Observers} \indexlibrarymember{use_count}{weak_ptr}% \begin{itemdecl} -long use_count() const noexcept; +constexpr long use_count() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4725,7 +5061,7 @@ \indexlibrarymember{expired}{weak_ptr}% \begin{itemdecl} -bool expired() const noexcept; +constexpr bool expired() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4736,7 +5072,7 @@ \indexlibrarymember{lock}{weak_ptr}% \begin{itemdecl} -shared_ptr lock() const noexcept; +constexpr shared_ptr lock() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4747,8 +5083,8 @@ \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; +template constexpr bool owner_before(const shared_ptr& b) const noexcept; +template constexpr bool owner_before(const weak_ptr& b) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4779,9 +5115,9 @@ \indexlibrarymember{owner_equal}{weak_ptr}% \begin{itemdecl} template - bool owner_equal(const shared_ptr& b) const noexcept; + constexpr bool owner_equal(const shared_ptr& b) const noexcept; template - bool owner_equal(const weak_ptr& b) const noexcept; + constexpr bool owner_equal(const weak_ptr& b) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4801,7 +5137,7 @@ \indexlibrarymember{swap}{weak_ptr}% \begin{itemdecl} template - void swap(weak_ptr& a, weak_ptr& b) noexcept; + constexpr void swap(weak_ptr& a, weak_ptr& b) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4822,26 +5158,26 @@ 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; + constexpr bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; + constexpr bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + constexpr 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; + constexpr bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; + constexpr bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + constexpr 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; + constexpr bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; template - bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + constexpr bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; template - bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; + constexpr bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; template - bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; + constexpr bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; using is_transparent = @\unspec@; }; @@ -4913,13 +5249,13 @@ namespace std { struct owner_equal { template - bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; + constexpr bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; template - bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + constexpr bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; template - bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; + constexpr bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; template - bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; + constexpr bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; using is_transparent = @\unspec@; }; @@ -4929,13 +5265,13 @@ \indexlibrarymember{operator()}{owner_equal}% \begin{itemdecl} template - bool operator()(const shared_ptr& x, const shared_ptr& y) const noexcept; + constexpr bool operator()(const shared_ptr& x, const shared_ptr& y) const noexcept; template - bool operator()(const shared_ptr& x, const weak_ptr& y) const noexcept; + constexpr bool operator()(const shared_ptr& x, const weak_ptr& y) const noexcept; template - bool operator()(const weak_ptr& x, const shared_ptr& y) const noexcept; + constexpr bool operator()(const weak_ptr& x, const shared_ptr& y) const noexcept; template - bool operator()(const weak_ptr& x, const weak_ptr& y) const noexcept; + constexpr bool operator()(const weak_ptr& x, const weak_ptr& y) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4977,18 +5313,18 @@ 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(); + constexpr enable_shared_from_this(const enable_shared_from_this&) noexcept; + constexpr enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; + constexpr ~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; + constexpr shared_ptr shared_from_this(); + constexpr shared_ptr shared_from_this() const; + constexpr weak_ptr weak_from_this() noexcept; + constexpr weak_ptr weak_from_this() const noexcept; private: - mutable weak_ptr weak_this; // \expos + mutable weak_ptr @\exposid{weak-this}@; // \expos }; } \end{codeblock} @@ -5000,18 +5336,18 @@ \indexlibraryctor{enable_shared_from_this}% \begin{itemdecl} constexpr enable_shared_from_this() noexcept; -enable_shared_from_this(const enable_shared_from_this&) noexcept; +constexpr enable_shared_from_this(const enable_shared_from_this&) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Value-initializes \tcode{weak_this}. +Value-initializes \exposid{weak-this}. \end{itemdescr} \indexlibrarymember{operator=}{enable_shared_from_this}% \begin{itemdecl} -enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; +constexpr enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5021,34 +5357,34 @@ \pnum \begin{note} -\tcode{weak_this} is not changed. +\exposid{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; +constexpr shared_ptr shared_from_this(); +constexpr shared_ptr shared_from_this() const; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{shared_ptr(weak_this)}. +\tcode{shared_ptr(\exposid{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; +constexpr weak_ptr weak_from_this() noexcept; +constexpr weak_ptr weak_from_this() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{weak_this}. +\exposid{weak-this}. \end{itemdescr} \rSec2[util.smartptr.hash]{Smart pointer hash support} @@ -5127,12 +5463,12 @@ template class out_ptr_t { public: - explicit out_ptr_t(Smart&, Args...); + constexpr explicit out_ptr_t(Smart&, Args...); out_ptr_t(const out_ptr_t&) = delete; - ~out_ptr_t(); + constexpr ~out_ptr_t(); - operator Pointer*() const noexcept; + constexpr operator Pointer*() const noexcept; operator void**() const noexcept; private: @@ -5166,7 +5502,7 @@ \indexlibraryctor{out_ptr_t}% \begin{itemdecl} -explicit out_ptr_t(Smart& smart, Args... args); +constexpr explicit out_ptr_t(Smart& smart, Args... args); \end{itemdecl} \begin{itemdescr} @@ -5178,6 +5514,8 @@ Then, 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} s.reset(); \end{codeblock} @@ -5208,7 +5546,7 @@ \indexlibrarydtor{out_ptr_t}% \begin{itemdecl} -~out_ptr_t(); +constexpr ~out_ptr_t(); \end{itemdecl} \begin{itemdescr} @@ -5247,7 +5585,7 @@ \end{itemdescr} \begin{itemdecl} -operator Pointer*() const noexcept; +constexpr operator Pointer*() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -5307,7 +5645,7 @@ \indexlibraryglobal{out_ptr}% \begin{itemdecl} template - auto out_ptr(Smart& s, Args&&... args); + constexpr auto out_ptr(Smart& s, Args&&... args); \end{itemdecl} \begin{itemdescr} @@ -5318,7 +5656,7 @@ \pnum \returns -\tcode{out_ptr_t(s, std::forward(args)...)} +\tcode{out_ptr_t(s, std::forward(args)...)}. \end{itemdescr} \rSec3[inout.ptr.t]{Class template \tcode{inout_ptr_t}} @@ -5365,12 +5703,12 @@ template class inout_ptr_t { public: - explicit inout_ptr_t(Smart&, Args...); + constexpr explicit inout_ptr_t(Smart&, Args...); inout_ptr_t(const inout_ptr_t&) = delete; - ~inout_ptr_t(); + constexpr ~inout_ptr_t(); - operator Pointer*() const noexcept; + constexpr operator Pointer*() const noexcept; operator void**() const noexcept; private: @@ -5401,7 +5739,7 @@ \indexlibraryctor{inout_ptr_t}% \begin{itemdecl} -explicit inout_ptr_t(Smart& smart, Args... args); +constexpr explicit inout_ptr_t(Smart& smart, Args... args); \end{itemdecl} \begin{itemdescr} @@ -5430,7 +5768,7 @@ \indexlibrarydtor{inout_ptr_t}% \begin{itemdecl} -~inout_ptr_t(); +constexpr ~inout_ptr_t(); \end{itemdecl} \begin{itemdescr} @@ -5483,7 +5821,7 @@ \end{itemdescr} \begin{itemdecl} -operator Pointer*() const noexcept; +constexpr operator Pointer*() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -5543,7 +5881,7 @@ \indexlibraryglobal{inout_ptr}% \begin{itemdecl} template - auto inout_ptr(Smart& s, Args&&... args); + constexpr auto inout_ptr(Smart& s, Args&&... args); \end{itemdecl} \begin{itemdescr} @@ -5556,70 +5894,1622 @@ \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; +\rSec1[mem.composite.types]{Types for composite class design} - bool operator==(const memory_resource& a, const memory_resource& b) noexcept; +\rSec2[indirect]{Class template \tcode{indirect}} - // \ref{mem.poly.allocator.class}, class template \tcode{polymorphic_allocator} - template class polymorphic_allocator; +\rSec3[indirect.general]{General} - template - bool operator==(const polymorphic_allocator& a, - const polymorphic_allocator& b) noexcept; +\pnum +An indirect object manages the lifetime of an owned object. +An indirect object is +\defnx{valueless}{valueless!indirect object} if it has no owned object. +An indirect object may become valueless only after it has been moved from. - // \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; +\pnum +In every specialization \tcode{indirect}, +if the type \tcode{allocator_traits::value_type} +is not the same type as \tcode{T}, +the program is ill-formed. +Every object of type \tcode{indirect} +uses an object of type \tcode{Allocator} to allocate and free storage +for the owned object as needed. + +\pnum +Constructing an owned object with \tcode{args...} +using the allocator \tcode{a} means calling +\tcode{allocator_traits::construct(a, \exposid{p}, args...)} where +\tcode{args} is an expression pack, +\tcode{a} is an allocator, and +\exposid{p} is a pointer obtained by +calling \tcode{allocator_traits::allocate}. + +\pnum +The member \exposid{alloc} is used for +any memory allocation and element construction +performed by member functions +during the lifetime of each indirect object. +The allocator \exposid{alloc} may be replaced +only via assignment or \tcode{swap()}. +\tcode{Allocator} replacement is performed by +copy assignment, +move assignment, or +swapping of the allocator +only if\iref{container.reqmts}: +\begin{itemize} +\item +\tcode{allocator_traits::propagate_on_container_copy_assignment::value}, or +\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 \tcode{indirect} operation. - // \ref{mem.res.pool}, pool resource classes - struct pool_options; - class synchronized_pool_resource; - class unsynchronized_pool_resource; - class monotonic_buffer_resource; -} -\end{codeblock} +\pnum +A program that instantiates the definition of +the template \tcode{indirect} with +a type for the \tcode{T} parameter that is +a non-object type, +an array type, +\tcode{in_place_t}, +a specialization of \tcode{in_place_type_t}, or +a cv-qualified type +is ill-formed. -\rSec2[mem.res.class]{Class \tcode{memory_resource}} +\pnum +The template parameter \tcode{T} of \tcode{indirect} +may be an incomplete type. -\rSec3[mem.res.class.general]{General} +\pnum +The template parameter \tcode{Allocator} of \tcode{indirect} +shall meet the \oldconcept{Allocator} requirements. \pnum -The \tcode{memory_resource} class is an abstract interface to an unbounded set of classes encapsulating memory resources. +If a program declares an explicit or partial specialization of \tcode{indirect}, +the behavior is undefined. -\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 +\rSec3[indirect.syn]{Synopsis} +\indexlibraryglobal{indirect}% +\begin{codeblock} +namespace std { + template> + class indirect { 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; + using value_type = T; + using allocator_type = Allocator; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + + // \ref{indirect.ctor}, constructors + constexpr explicit indirect(); + constexpr explicit indirect(allocator_arg_t, const Allocator& a); + constexpr indirect(const indirect& other); + constexpr indirect(allocator_arg_t, const Allocator& a, const indirect& other); + constexpr indirect(indirect&& other) noexcept; + constexpr indirect(allocator_arg_t, const Allocator& a, indirect&& other) + noexcept(@\seebelow@); + template + constexpr explicit indirect(U&& u); + template + constexpr explicit indirect(allocator_arg_t, const Allocator& a, U&& u); + template + constexpr explicit indirect(in_place_t, Us&&... us); + template + constexpr explicit indirect(allocator_arg_t, const Allocator& a, + in_place_t, Us&&... us); + template + constexpr explicit indirect(in_place_t, initializer_list ilist, Us&&... us); + template + constexpr explicit indirect(allocator_arg_t, const Allocator& a, + in_place_t, initializer_list ilist, Us&&... us); + + // \ref{indirect.dtor}, destructor + constexpr ~indirect(); + + // \ref{indirect.assign}, assignment + constexpr indirect& operator=(const indirect& other); + constexpr indirect& operator=(indirect&& other) noexcept(@\seebelow@); + template + constexpr indirect& operator=(U&& u); + + // \ref{indirect.obs}, observers + constexpr const T& operator*() const & noexcept; + constexpr T& operator*() & noexcept; + constexpr const T&& operator*() const && noexcept; + constexpr T&& operator*() && noexcept; + constexpr const_pointer operator->() const noexcept; + constexpr pointer operator->() noexcept; + constexpr bool valueless_after_move() const noexcept; + constexpr allocator_type get_allocator() const noexcept; + + // \ref{indirect.swap}, swap + constexpr void swap(indirect& other) noexcept(@\seebelow@); + friend constexpr void swap(indirect& lhs, indirect& rhs) noexcept(@\seebelow@); + + // \ref{indirect.relops}, relational operators + template + friend constexpr bool operator==(const indirect& lhs, const indirect& rhs) + noexcept(@\seebelow@); + template + friend constexpr auto operator<=>(const indirect& lhs, const indirect& rhs) + -> @\exposid{synth-three-way-result}@; + + // \ref{indirect.comp.with.t}, comparison with \tcode{T} + template + friend constexpr bool operator==(const indirect& lhs, const U& rhs) noexcept(@\seebelow@); + template + friend constexpr auto operator<=>(const indirect& lhs, const U& rhs) + -> @\exposid{synth-three-way-result}@; 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; + pointer @\exposid{p}@; // \expos + Allocator @\exposid{alloc}@ = Allocator(); // \expos + }; + template + indirect(Value) -> indirect; + template + indirect(allocator_arg_t, Allocator, Value) + -> indirect::template rebind_alloc>; +} +\end{codeblock} + +\rSec3[indirect.ctor]{Constructors} + +\pnum +The following element applies to all functions in~\ref{indirect.ctor}: + +\begin{itemdescr} +\pnum +\throws +Nothing unless \tcode{allocator_traits::allocate} or +\tcode{allocator_traits::construct} throws. +\end{itemdescr} + +\indexlibraryctor{indirect}% +\begin{itemdecl} +constexpr explicit indirect(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_default_constructible_v} is \tcode{true}. + +\pnum +\mandates +\tcode{is_default_constructible_v} is \tcode{true}. + +\pnum +\effects +Constructs an owned object of type \tcode{T} with an empty argument list, +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{indirect}% +\begin{itemdecl} +constexpr explicit indirect(allocator_arg_t, const Allocator& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_default_constructible_v} is \tcode{true}. + +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with \tcode{a}. +Constructs an owned object of type \tcode{T} with an empty argument list, +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{indirect}% +\begin{itemdecl} +constexpr indirect(const indirect& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_copy_constructible_v} is \tcode{true}. + +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with +\tcode{allocator_traits::select_on_contai\-ner_copy_construction(other.\exposid{alloc})}. +If \tcode{other} is valueless, \tcode{*this} is valueless. +Otherwise, +constructs an owned object of type \tcode{T} with \tcode{*other}, +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{indirect}% +\begin{itemdecl} +constexpr indirect(allocator_arg_t, const Allocator& a, const indirect& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_copy_constructible_v} is \tcode{true}. + +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with \tcode{a}. +If \tcode{other} is valueless, \tcode{*this} is valueless. +Otherwise, +constructs an owned object of type \tcode{T} with \tcode{*other}, +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{indirect}% +\begin{itemdecl} +constexpr indirect(indirect&& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized from +\tcode{std::move(other.\exposid{alloc})}. +If \tcode{other} is valueless, \tcode{*this} is valueless. +Otherwise \tcode{*this} takes ownership of the owned object of \tcode{other}. + +\pnum +\ensures +\tcode{other} is valueless. +\end{itemdescr} + +\indexlibraryctor{indirect}% +\begin{itemdecl} +constexpr indirect(allocator_arg_t, const Allocator& a, indirect&& other) + noexcept(allocator_traits::is_always_equal::value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +If \tcode{allocator_traits::is_always_equal::value} is \tcode{false} +then \tcode{T} is a complete type. + +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with \tcode{a}. +If \tcode{other} is valueless, \tcode{*this} is valueless. +Otherwise, +if \tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true}, +constructs an object of type \tcode{indirect} that +takes ownership of the owned object of \tcode{other}. +Otherwise, +constructs an owned object of type \tcode{T} with \tcode{*std::move(other)}, +using the allocator \exposid{alloc}. + +\pnum +\ensures +\tcode{other} is valueless. +\end{itemdescr} + +\indexlibraryctor{indirect}% +\begin{itemdecl} +template + constexpr explicit indirect(U&& u); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_same_v, indirect>} is \tcode{false}, +\item +\tcode{is_same_v, in_place_t>} is \tcode{false}, +\item +\tcode{is_constructible_v} is \tcode{true}, and +\item +\tcode{is_default_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Constructs an owned object of type \tcode{T} with \tcode{std::forward(u)}, +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{indirect}% +\begin{itemdecl} +template + constexpr explicit indirect(allocator_arg_t, const Allocator& a, U&& u); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_same_v, indirect>} is \tcode{false}, +\item +\tcode{is_same_v, in_place_t>} is \tcode{false}, and +\item +\tcode{is_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with \tcode{a}. +Constructs an owned object of type \tcode{T} with +\tcode{std::forward(u)}, +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{indirect}% +\begin{itemdecl} +template + constexpr explicit indirect(in_place_t, Us&&... us); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_constructible_v} is \tcode{true}, and +\item +\tcode{is_default_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Constructs an owned object of type \tcode{T} with +\tcode{std::forward(us)...}, +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{indirect}% +\begin{itemdecl} +template + constexpr explicit indirect(allocator_arg_t, const Allocator& a, + in_place_t, Us&& ...us); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with \tcode{a}. +Constructs an owned object of type \tcode{T} with +\tcode{std::forward(us)...}, +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{indirect}% +\begin{itemdecl} +template + constexpr explicit indirect(in_place_t, initializer_list ilist, Us&&... us); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_constructible_v\&, Us...>} is \tcode{true}, and +\item +\tcode{is_default_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Constructs an owned object of type \tcode{T} with the arguments +\tcode{ilist, std::forward(us)...}, +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{indirect}% +\begin{itemdecl} +template + constexpr explicit indirect(allocator_arg_t, const Allocator& a, + in_place_t, initializer_list ilist, Us&&... us); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v\&, Us...>} is \tcode{true}. + +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with \tcode{a}. +Constructs an owned object of type \tcode{T} with the arguments +\tcode{ilist, std::forward(us)...}, +using the allocator \exposid{alloc}. +\end{itemdescr} + +\rSec3[indirect.dtor]{Destructor} + +\indexlibrarydtor{indirect}% +\begin{itemdecl} +constexpr ~indirect(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is a complete type. + +\pnum +\effects +If \tcode{*this} is not valueless, +destroys the owned object +using \tcode{allocator_traits::de\-stroy} and +then the storage is deallocated. +\end{itemdescr} + +\rSec3[indirect.assign]{Assignment} + +\indexlibrarymember{operator=}{indirect}% +\begin{itemdecl} +constexpr indirect& operator=(const indirect& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates + +\begin{itemize} +\item +\tcode{is_copy_assignable_v} is \tcode{true}, and +\item +\tcode{is_copy_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +If \tcode{addressof(other) == this} is \tcode{true}, there are no effects. +Otherwise: + +\begin{itemize} +\item +%FIXME: We're defining what it means for an allocator to "need updating" here? +%FIXME: (Note: that this concept is used elsewhere so it must be defined)... +%FIXME: How is this an "effect"? +The allocator needs updating if +\tcode{allocator_traits::propagate_on_container_copy_assignment::value} +is \tcode{true}. + +\item +If \tcode{other} is valueless, +\tcode{*this} becomes valueless and +the owned object in \tcode{*this}, if any, +is destroyed using \tcode{allocator_traits::destroy} and +then the storage is deallocated. + +\item +Otherwise, +if \tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true} and +\tcode{*this} is not valueless, +equivalent to \tcode{**this = *other}. + +\item +Otherwise a new owned object is constructed in \tcode{*this} +using \tcode{allocator_traits::con\linebreak{}struct} with +the owned object from \tcode{other} as the argument, +using either the allocator in \tcode{*this} or +%FIXME: Concept "allocator needs updating" not defined/referenced. +%FIXME: Same for all usages below. +the allocator in \tcode{other} if the allocator needs updating. + +\item +The previously owned object in \tcode{*this}, if any, +is destroyed using \tcode{allocator_traits::\linebreak{}destroy} and +then the storage is deallocated. + +\item +If the allocator needs updating, +the allocator in \tcode{*this} is replaced with +a copy of the allocator in \tcode{other}. +\end{itemize} + +\pnum +\returns +A reference to \tcode{*this}. + +\pnum +\remarks +If any exception is thrown, +the result of the expression \tcode{this->valueless_after_move()} +remains unchanged. +If an exception is thrown during +the call to \tcode{T}{'s} selected copy constructor, no effect. +If an exception is thrown during the call to \tcode{T}{'s} copy assignment, +the state of its owned object +is as defined by the exception safety guarantee of +\tcode{T}{'s} copy assignment. +\end{itemdescr} + +\indexlibrarymember{operator=}{indirect}% +\begin{itemdecl} +constexpr indirect& operator=(indirect&& other) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_copy_constructible_t} is \tcode{true}. + +\pnum +\effects +If \tcode{addressof(other) == this} is \tcode{true}, there are no effects. +Otherwise: + +\begin{itemize} +\item +%FIXME: We're defining "allocator needs updating" as an effect? +%FIXME: (Same issue as above) +The allocator needs updating if +\tcode{allocator_traits::propagate_on_container_move_assignment::value} +is \tcode{true}. + +\item +If \tcode{other} is valueless, +\tcode{*this} becomes valueless and +the owned object in \tcode{*this}, if any, +is destroyed using \tcode{allocator_traits::destroy} and +then the storage is deallocated. + +\item +Otherwise, +if \tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true}, +swaps the owned objects in \tcode{*this} and \tcode{other}; +the owned object in \tcode{other}, if any, +is then destroyed using \tcode{allocator_traits::destroy} and +then the storage is deallocated. + +\item +Otherwise, +constructs a new owned object with +%FIXME: "as the argument as an rvalue" is awkward. +the owned object of \tcode{other} as the argument as an rvalue, +using either +the allocator in \tcode{*this} or +the allocator in \tcode{other} +if the allocator needs updating. + +\item +The previously owned object in \tcode{*this}, if any, +is destroyed using \tcode{allocator_traits::\linebreak{}destroy} and +then the storage is deallocated. + +\item +If the allocator needs updating, +the allocator in \tcode{*this} is replaced with +a copy of the allocator in \tcode{other}. +\end{itemize} + +\pnum +\ensures +\tcode{other} is valueless. + +\pnum +\returns +A reference to \tcode{*this}. + +\pnum +\remarks +If any exception is thrown, +there are no effects on \tcode{*this} or \tcode{other}. +\end{itemdescr} + +\indexlibrarymember{operator=}{indirect}% +\begin{itemdecl} +template + constexpr indirect& operator=(U&& u); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_same_v, indirect>} is \tcode{false}, +\item +\tcode{is_constructible_v} is \tcode{true}, and +\item +\tcode{is_assignable_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +If \tcode{*this} is valueless then +constructs an owned object of type \tcode{T} with \tcode{std::forward(u)} +using the allocator \exposid{alloc}. +Otherwise, +equivalent to \tcode{**this = std::forward(u)}. + +\pnum +\returns +A reference to \tcode{*this}. +\end{itemdescr} + +\rSec3[indirect.obs]{Observers} + +\indexlibrarymember{operator*}{indirect}% +\begin{itemdecl} +constexpr const T& operator*() const & noexcept; +constexpr T& operator*() & noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{*this} is not valueless. + +\pnum +\returns +\tcode{*\exposid{p}}. +\end{itemdescr} + +\indexlibrarymember{operator*}{indirect}% +\begin{itemdecl} +constexpr const T&& operator*() const && noexcept; +constexpr T&& operator*() && noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{*this} is not valueless. + +\pnum +\returns +\tcode{std::move(*\exposid{p})}. +\end{itemdescr} + +\indexlibrarymember{operator->}{indirect}% +\begin{itemdecl} +constexpr const_pointer operator->() const noexcept; +constexpr pointer operator->() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{*this} is not valueless. + +\pnum +\returns +\exposid{p}. +\end{itemdescr} + +\indexlibrarymember{valueless_after_move}{indirect}% +\begin{itemdecl} +constexpr bool valueless_after_move() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{*this} is valueless, otherwise \tcode{false}. +\end{itemdescr} + +\indexlibrarymember{get_allocator}{indirect}% +\begin{itemdecl} +constexpr allocator_type get_allocator() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{alloc}. +\end{itemdescr} + +\rSec3[indirect.swap]{Swap} + +\indexlibrarymember{swap}{indirect}% +\begin{itemdecl} +constexpr void swap(indirect& other) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +If +\tcode{allocator_traits::propagate_on_container_swap::value} +is \tcode{true}, then +\tcode{Allocator} meets the \oldconcept{Swappable} requirements. +Otherwise \tcode{get_allocator() == other.\linebreak{}get_allocator()} is \tcode{true}. + +\pnum +\effects +Swaps the states of \tcode{*this} and \tcode{other}, +exchanging owned objects or valueless states. +If \tcode{allocator_traits::propagate_on_container_swap::value} +is \tcode{true}, +then the allocators of \tcode{*this} and \tcode{other} +are exchanged by calling \tcode{swap} as described in~\ref{swappable.requirements}. +Otherwise, +the allocators are not swapped. +\begin{note} +Does not call \tcode{swap} on the owned objects directly. +\end{note} +\end{itemdescr} + +\indexlibrarymember{swap}{indirect}% +%FIXME: "friend" included on declaration in synopsis but not here. +\begin{itemdecl} +constexpr void swap(indirect& lhs, indirect& rhs) noexcept(noexcept(lhs.swap(rhs))); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{lhs.swap(rhs)}. +\end{itemdescr} + +\rSec3[indirect.relops]{Relational operators} + +\indexlibrarymember{operator==}{indirect}% +%FIXME: "friend" included on declaration in synopsis but not here. +\begin{itemdecl} +template + constexpr bool operator==(const indirect& lhs, const indirect& rhs) + noexcept(noexcept(*lhs == *rhs)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{*lhs == *rhs} is well-formed and +its result is convertible to \tcode{bool}. + +\pnum +\returns +If \tcode{lhs} is valueless or \tcode{rhs} is valueless, +\tcode{lhs.valueless_after_move() == rhs.valueless_after_move()}; +otherwise \tcode{*lhs == *rhs}. +\end{itemdescr} + +\indexlibrarymember{\exposid{synth-three-way-result}}{indirect}% +%FIXME: "friend" included on declaration in synopsis but not here. +\begin{itemdecl} +template + constexpr @\exposid{synth-three-way-result}@ + operator<=>(const indirect& lhs, const indirect& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \tcode{lhs} is valueless or \tcode{rhs} is valueless, +\tcode{!lhs.valueless_after_move() <=> !rhs.value\-less_after_move()}; +otherwise +\tcode{\exposid{synth-three-way}(*lhs, *rhs)}. +\end{itemdescr} + +\rSec3[indirect.comp.with.t]{Comparison with \tcode{T}} + +\indexlibrarymember{operator==}{indirect}% +%FIXME: "friend" included on declaration in synopsis but not here. +\begin{itemdecl} +template + constexpr bool operator==(const indirect& lhs, const U& rhs) noexcept(noexcept(*lhs == rhs)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +The expression \tcode{*lhs == rhs} is well-formed and +its result is convertible to \tcode{bool}. + +\pnum +\returns +If \tcode{lhs} is valueless, \tcode{false}; +otherwise \tcode{*lhs == rhs}. +\end{itemdescr} + +\indexlibrarymember{\exposid{synth-three-way-result}}{indirect}% +%FIXME: "friend" included on declaration in synopsis but not here. +\begin{itemdecl} +template + constexpr @\exposid{synth-three-way-result}@ + operator<=>(const indirect& lhs, const U& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \tcode{lhs} is valueless, \tcode{strong_ordering::less}; +otherwise \tcode{\exposid{synth-three-way}(*lhs, rhs)}. +\end{itemdescr} + +\rSec3[indirect.hash]{Hash support} + +\indexlibrarymember{hash}{indirect}% +\begin{itemdecl} +template +struct hash>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The specialization \tcode{hash>} +is enabled\iref{unord.hash} if and only if \tcode{hash} is enabled. +When enabled for an object \tcode{i} of type \tcode{indirect}, +%FIXME: Cleanup wording/punctuation and make consistent. +\tcode{hash>()(i)} evaluates to +either the same value as \tcode{hash()(*i)}, +if \tcode{i} is not valueless; +otherwise to an +\impldef{result of evaluating \tcode{hash>()(i)} if \tcode{i} is valueless} +value. +The member functions are not guaranteed to be \tcode{noexcept}. +\end{itemdescr} + +\rSec2[polymorphic]{Class template \tcode{polymorphic}} + +\rSec3[polymorphic.general]{General} + +\pnum +A polymorphic object manages the lifetime of an owned object. +A polymorphic object may own objects of +different types at different points in its lifetime. +A polymorphic object is +\defnx{valueless}{valueless!polymorphic object} +if it has no owned object. +A polymorphic object may become valueless only after it has been moved from. + +\pnum +In every specialization \tcode{polymorphic}, +if the type \tcode{allocator_traits::value_type} +is not the same type as \tcode{T}, the program is ill-formed. +Every object of type \tcode{polymorphic} +uses an object of type \tcode{Allocator} to +allocate and free storage for the owned object as needed. + +\pnum +Constructing an owned object of type \tcode{U} with \tcode{args...} +using the allocator \tcode{a} means calling +\tcode{allocator_traits::construct(a, \exposid{p}, args...)} where +\tcode{args} is an expression pack, +\tcode{a} is an allocator, and +\exposid{p} points to storage suitable for an owned object of type \tcode{U}. + +\pnum +The member \exposid{alloc} is used for +any memory allocation and element construction +performed by member functions +during the lifetime of each polymorphic value object, or +until the allocator is replaced. +The allocator may be replaced only via +assignment or \tcode{swap()}. +\tcode{Allocator} replacement is performed by +copy assignment, +move assignment, or +swapping of the allocator +only if\iref{container.reqmts}: +\begin{itemize} +\item +\tcode{allocator_traits::propagate_on_container_copy_assignment::value}, or +\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 \tcode{polymorphic} operation. + +\pnum +A program that instantiates the definition of \tcode{polymorphic} for +a non-object type, +an array type, +\tcode{in_place_t}, +a specialization of \tcode{in_place_type_t}, or +a cv-qualified type +is ill-formed. + +\pnum +The template parameter \tcode{T} of \tcode{polymorphic} +may be an incomplete type. + +\pnum +The template parameter \tcode{Allocator} of \tcode{polymorphic} +shall meet the requirements of \oldconcept{Allocator}. + +\pnum +If a program declares an explicit or +partial specialization of \tcode{polymorphic}, +the behavior is undefined. + +\rSec3[polymorphic.syn]{Synopsis} + +\indexlibraryglobal{polymorphic}% +\begin{codeblock} +namespace std { + template> + class polymorphic { + public: + using value_type = T; + using allocator_type = Allocator; + using pointer = typename allocator_traits::pointer; + using const_pointer = typename allocator_traits::const_pointer; + + // \ref{polymorphic.ctor}, constructors + constexpr explicit polymorphic(); + constexpr explicit polymorphic(allocator_arg_t, const Allocator& a); + constexpr polymorphic(const polymorphic& other); + constexpr polymorphic(allocator_arg_t, const Allocator& a, const polymorphic& other); + constexpr polymorphic(polymorphic&& other) noexcept; + constexpr polymorphic(allocator_arg_t, const Allocator& a, polymorphic&& other) + noexcept(@\seebelow@); + template + constexpr explicit polymorphic(U&& u); + template + constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, U&& u); + template + constexpr explicit polymorphic(in_place_type_t, Ts&&... ts); + template + constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, + in_place_type_t, Ts&&... ts); + template + constexpr explicit polymorphic(in_place_type_t, initializer_list ilist, Us&&... us); + template + constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, + in_place_type_t, initializer_list ilist, Us&&... us); + + // \ref{polymorphic.dtor}, destructor + constexpr ~polymorphic(); + + // \ref{polymorphic.assign}, assignment + constexpr polymorphic& operator=(const polymorphic& other); + constexpr polymorphic& operator=(polymorphic&& other) noexcept(@\seebelow@); + + // \ref{polymorphic.obs}, observers + constexpr const T& operator*() const noexcept; + constexpr T& operator*() noexcept; + constexpr const_pointer operator->() const noexcept; + constexpr pointer operator->() noexcept; + constexpr bool valueless_after_move() const noexcept; + constexpr allocator_type get_allocator() const noexcept; + + // \ref{polymorphic.swap}, swap + constexpr void swap(polymorphic& other) noexcept(@\seebelow@); + friend constexpr void swap(polymorphic& lhs, polymorphic& rhs) noexcept(@\seebelow@); + + private: + Allocator @\exposid{alloc}@ = Allocator(); // \expos + }; +} +\end{codeblock} + +\rSec3[polymorphic.ctor]{Constructors} + +\pnum +The following element applies to all functions in~\ref{polymorphic.ctor}: + +\begin{itemdescr} +\pnum +\throws +Nothing unless \tcode{allocator_traits::allocate} or +\tcode{allocator_traits::construct} throws. +\end{itemdescr} + +\indexlibraryctor{polymorphic}% +\begin{itemdecl} +constexpr explicit polymorphic(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_default_constructible_v} is \tcode{true}. + +\pnum +\mandates +\begin{itemize} +\item +\tcode{is_default_constructible_v} is \tcode{true}, and +\item +\tcode{is_copy_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Constructs an owned object of type \tcode{T} with an empty argument list +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{indirect}% +\begin{itemdecl} +constexpr explicit polymorphic(allocator_arg_t, const Allocator& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\begin{itemize} +\item +\tcode{is_default_constructible_v} is \tcode{true}, and +\item +\tcode{is_copy_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with \tcode{a}. +Constructs an owned object of type \tcode{T} with an empty argument list +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{polymorphic}% +\begin{itemdecl} +constexpr polymorphic(const polymorphic& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with +\tcode{allocator_traits::select_on_contai\-ner_copy_construction(other.\exposid{alloc})}. +If \tcode{other} is valueless, \tcode{*this} is valueless. +Otherwise, +constructs an owned object of type \tcode{U}, where +\tcode{U} is the type of the owned object in \tcode{other}, with +the owned object in \tcode{other} using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{polymorphic}% +\begin{itemdecl} +constexpr polymorphic(allocator_arg_t, const Allocator& a, const polymorphic& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with \tcode{a}. +If \tcode{other} is valueless, \tcode{*this} is valueless. +Otherwise, +constructs an owned object of type \tcode{U}, where +\tcode{U} is the type of the owned object in \tcode{other}, with +the owned object in \tcode{other} using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{polymorphic}% +\begin{itemdecl} +constexpr polymorphic(polymorphic&& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with +\tcode{std::move(other.\exposid{alloc})}. +If \tcode{other} is valueless, \tcode{*this} is valueless. +Otherwise, +either \tcode{*this} +takes ownership of the owned object of \tcode{other} or, +%FIXME: Cleanup awkward wording. +owns an object of the same type +constructed from the owned object of \tcode{other} +considering that owned object as an rvalue, +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{polymorphic}% +\begin{itemdecl} +constexpr polymorphic(allocator_arg_t, const Allocator& a, polymorphic&& other) + noexcept(allocator_traits::is_always_equal::value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with \tcode{a}. +If \tcode{other} is valueless, \tcode{*this} is valueless. +Otherwise, +if \tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true}, +either constructs an object of type \tcode{polymorphic} that +owns the owned object of \tcode{other}, +making \tcode{other} valueless; or, +%FIXME: Cleanup awkward wording. (And similar wording elsewhere). +owns an object of the same type constructed from +the owned object of \tcode{other} +considering that owned object as an rvalue. +Otherwise, +if \tcode{\exposid{alloc} != other.\exposid{alloc}} is \tcode{true}, +constructs an object of type \tcode{polymorphic}, +considering the owned object in \tcode{other} as an rvalue, +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{polymorphic}% +\begin{itemdecl} +template + constexpr explicit polymorphic(U&& u); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +Where \tcode{UU} is \tcode{remove_cvref_t}, +\begin{itemize} +\item +\tcode{is_same_v} is \tcode{false}, +\item +\tcode{derived_from} is \tcode{true}, +\item +\tcode{is_constructible_v} is \tcode{true}, +\item +\tcode{is_copy_constructible_v} is \tcode{true}, +\item +\tcode{UU} is not a specialization of \tcode{in_place_type_t}, and +\item +\tcode{is_default_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Constructs an owned object of type \tcode{UU} with \tcode{std::forward(u)} +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{polymorphic}% +\begin{itemdecl} +template + constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, U&& u); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +Where \tcode{UU} is \tcode{remove_cvref_t}, +\begin{itemize} +\item +\tcode{is_same_v} is \tcode{false}, +\item +\tcode{derived_from} is \tcode{true}, +\item +\tcode{is_constructible_v} is \tcode{true}, +\item +\tcode{is_copy_constructible_v} is \tcode{true}, and +\item +\tcode{UU} is not a specialization of \tcode{in_place_type_t}. +\end{itemize} + +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with \tcode{a}. +Constructs an owned object of type \tcode{UU} with \tcode{std::forward(u)} +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{polymorphic}% +\begin{itemdecl} +template + constexpr explicit polymorphic(in_place_type_t, Ts&&... ts); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_same_v, U>} is \tcode{true}, +\item +\tcode{derived_from} is \tcode{true}, +\item +\tcode{is_constructible_v} is \tcode{true}, +\item +\tcode{is_copy_constructible_v} is \tcode{true}, and +\item +\tcode{is_default_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Constructs an owned object of type \tcode{U} with +\tcode{std::forward(ts)...} +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{polymorphic}% +\begin{itemdecl} +template + constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, + in_place_type_t, Ts&&... ts); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_same_v, U>} is \tcode{true}, +\item +\tcode{derived_from} is \tcode{true}, +\item +\tcode{is_constructible_v} is \tcode{true}, and +\item +\tcode{is_copy_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with \tcode{a}. +Constructs an owned object of type \tcode{U} with +\tcode{std::forward(ts)...} +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{polymorphic}% +\begin{itemdecl} +template + constexpr explicit polymorphic(in_place_type_t, initializer_list ilist, Us&&... us); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_same_v, U>} is \tcode{true}, +\item +\tcode{derived_from} is \tcode{true}, +\item +\tcode{is_constructible_v\&, Us...>} is \tcode{true}, +\item +\tcode{is_copy_constructible_v} is \tcode{true}, and +\item +\tcode{is_default_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Constructs an owned object of type \tcode{U} with +the arguments \tcode{ilist, std::forward(us)...} +using the allocator \exposid{alloc}. +\end{itemdescr} + +\indexlibraryctor{polymorphic}% +\begin{itemdecl} +template + constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, + in_place_type_t, initializer_list ilist, Us&&... us); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints + +\begin{itemize} +\item +\tcode{is_same_v, U>} is \tcode{true}, +\item +\tcode{derived_from} is \tcode{true}, +\item +\tcode{is_constructible_v\&, Us...>} is \tcode{true}, and +\item +\tcode{is_copy_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +\exposid{alloc} is direct-non-list-initialized with \tcode{a}. +Constructs an owned object of type \tcode{U} with the arguments +\tcode{ilist, std::forward(us)...} +using the allocator \exposid{alloc}. +\end{itemdescr} + +\rSec3[polymorphic.dtor]{Destructor} + +\indexlibrarydtor{polymorphic}% +\begin{itemdecl} +constexpr ~polymorphic(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is a complete type. + +\pnum +\effects +If \tcode{*this} is not valueless, +destroys the owned object using \tcode{allocator_traits::de\-stroy} and +then the storage is deallocated. +\end{itemdescr} + +\rSec3[polymorphic.assign]{Assignment} + +\indexlibrarymember{operator=}{polymorphic}% +\indexlibrarydtor{polymorphic}% +\begin{itemdecl} +constexpr polymorphic& operator=(const polymorphic& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is a complete type. + +\pnum +\effects +If \tcode{addressof(other) == this} is \tcode{true}, there are no effects. +Otherwise: + +\begin{itemize} +\item +%FIXME: We're defining "allocator needs updating" as an effect? +%FIXME: (Same issue as above) +The allocator needs updating if +\tcode{allocator_traits::propagate_on_contai\-ner_copy_assignment::value} +is \tcode{true}. + +\item +If \tcode{other} is not valueless, +a new owned object is constructed in \tcode{*this} using +\tcode{allocator_traits::construct} with +the owned object from \tcode{other} as the argument, using either +the allocator in \tcode{*this} or +the allocator in \tcode{other} if the allocator needs updating. + +\item +The previously owned object in \tcode{*this}, if any, +is destroyed using \tcode{allocator_traits::\linebreak{}destroy} and +then the storage is deallocated. + +\item +If the allocator needs updating, +the allocator in \tcode{*this} is replaced with +a copy of the allocator in \tcode{other}. +\end{itemize} + +\pnum +\returns +A reference to \tcode{*this}. + +\pnum +\remarks +If any exception is thrown, there are no effects on \tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{operator=}{polymorphic}% +\begin{itemdecl} +constexpr polymorphic& operator=(polymorphic&& other) + noexcept(allocator_traits::propagate_on_container_move_assignment::value || + allocator_traits::is_always_equal::value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +If \tcode{allocator_traits::is_always_equal::value} is \tcode{false}, +\tcode{T} is a complete type. + +\pnum +\effects +If \tcode{addressof(other) == this} is \tcode{true}, there are no effects. +Otherwise: + +\begin{itemize} +\item +%FIXME: We're defining "allocator needs updating" as an effect? +%FIXME: (Same issue as above) +The allocator needs updating if +\tcode{allocator_traits::propagate_on_container_move_assignment::value} +is \tcode{true}. + +\item +If \tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true}, +swaps the owned objects in \tcode{*this} and \tcode{other}; +the owned object in \tcode{other}, if any, +is then destroyed using \tcode{allocator_traits::destroy} and +then the storage is deallocated. + +\item +Otherwise, +if \tcode{\exposid{alloc} != other.\exposid{alloc}} is \tcode{true}; +if \tcode{other} is not valueless, +a new owned object is constructed in \tcode{*this} +using \tcode{allocator_traits::construct} with +%FIXME: Cleanup wording. +the owned object from \tcode{other} as the argument as an rvalue, +using either the allocator in \tcode{*this} or +the allocator in \tcode{other} if the allocator needs updating. + +\item +The previously owned object in \tcode{*this}, if any, +is destroyed using \tcode{allocator_traits::\linebreak{}destroy} and +then the storage is deallocated. + +\item +If the allocator needs updating, +the allocator in \tcode{*this} is replaced with +a copy of the allocator in \tcode{other}. +\end{itemize} + +\pnum +\returns +A reference to \tcode{*this}. + +\pnum +\remarks +If any exception is thrown, +there are no effects on \tcode{*this} or \tcode{other}. +\end{itemdescr} + +\rSec3[polymorphic.obs]{Observers} + +\indexlibrarymember{operator*}{polymorphic}% +\begin{itemdecl} +constexpr const T& operator*() const noexcept; +constexpr T& operator*() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{*this} is not valueless. + +\pnum +\returns +A reference to the owned object. +\end{itemdescr} + +\indexlibrarymember{operator->}{polymorphic}% +\begin{itemdecl} +constexpr const_pointer operator->() const noexcept; +constexpr pointer operator->() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{*this} is not valueless. + +\pnum +\returns +A pointer to the owned object. +\end{itemdescr} + +\indexlibrarymember{valueless_after_move}{polymorphic}% +\begin{itemdecl} +constexpr bool valueless_after_move() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{*this} is valueless, otherwise \tcode{false}. +\end{itemdescr} + +\indexlibrarymember{get_allocator}{polymorphic}% +\begin{itemdecl} +constexpr allocator_type get_allocator() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{alloc}. +\end{itemdescr} + +\rSec3[polymorphic.swap]{Swap} + +\indexlibrarymember{swap}{polymorphic}% +\begin{itemdecl} +constexpr void swap(polymorphic& other) + noexcept(allocator_traits::propagate_on_container_swap::value || + allocator_traits::is_always_equal::value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +If \tcode{allocator_traits::propagate_on_container_swap::value} +is \tcode{true}, then +\tcode{Allocator} meets the \oldconcept{Swappable} requirements. +Otherwise \tcode{get_allocator() == other.\linebreak{}get_allocator()} is \tcode{true}. + +\pnum +\effects +Swaps the states of \tcode{*this} and \tcode{other}, +exchanging owned objects or valueless states. +If \tcode{allocator_traits::propagate_on_container_swap::value} +is \tcode{true}, then +the allocators of \tcode{*this} and \tcode{other} +are exchanged by calling \tcode{swap} +as described in~\ref{swappable.requirements}. +Otherwise, +the allocators are not swapped. +\begin{note} +Does not call \tcode{swap} on the owned objects directly. +\end{note} +\end{itemdescr} + +\indexlibrarymember{swap}{polymorphic}% +%FIXME: "friend" included on declaration in synopsis but not here. +\begin{itemdecl} +constexpr void swap(polymorphic& lhs, polymorphic& rhs) noexcept(noexcept(lhs.swap(rhs))); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{lhs.swap(rhs)}. +\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; + + 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} @@ -5640,7 +7530,7 @@ \indexlibrarymember{allocate}{memory_resource}% \begin{itemdecl} -[[nodiscard]] void* allocate(size_t bytes, size_t alignment = max_align); +void* allocate(size_t bytes, size_t alignment = max_align); \end{itemdecl} \begin{itemdescr} @@ -5800,19 +7690,22 @@ polymorphic_allocator& operator=(const polymorphic_allocator&) = delete; // \ref{mem.poly.allocator.mem}, member functions - [[nodiscard]] Tp* allocate(size_t n); + 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* 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 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 T* new_object(CtorArgs&&... ctor_args); template void delete_object(T* p); template void construct(T* p, Args&&... args); + template + void destroy(T* p); + polymorphic_allocator select_on_container_copy_construction() const; memory_resource* resource() const; @@ -5879,7 +7772,7 @@ \indexlibrarymember{allocate}{polymorphic_allocator}% \begin{itemdecl} -[[nodiscard]] Tp* allocate(size_t n); +Tp* allocate(size_t n); \end{itemdecl} \begin{itemdescr} @@ -5916,7 +7809,7 @@ \indexlibrarymember{allocate_bytes}{polymorphic_allocator}% \begin{itemdecl} -[[nodiscard]] void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t)); +void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t)); \end{itemdecl} \begin{itemdescr} @@ -5947,7 +7840,7 @@ \indexlibrarymember{allocate_object}{polymorphic_allocator}% \begin{itemdecl} template - [[nodiscard]] T* allocate_object(size_t n = 1); + T* allocate_object(size_t n = 1); \end{itemdecl} \begin{itemdescr} @@ -5987,7 +7880,7 @@ \indexlibrarymember{new_object}{polymorphic_allocator}% \begin{itemdecl} template - [[nodiscard]] T* new_object(CtorArgs&&... ctor_args); + T* new_object(CtorArgs&&... ctor_args); \end{itemdecl} \begin{itemdescr} @@ -6023,7 +7916,7 @@ \effects Equivalent to: \begin{codeblock} -allocator_traits::destroy(*this, p); +destroy(p); deallocate_object(p); \end{codeblock} \end{itemdescr} @@ -6043,7 +7936,7 @@ \pnum \effects -Construct a \tcode{T} object in the storage +Constructs 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)...}. @@ -6053,6 +7946,18 @@ Nothing unless the constructor for \tcode{T} throws. \end{itemdescr} +\indexlibrarymember{destroy}{polymorphic_allocator}% +\begin{itemdecl} +template + void destroy(T* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{p->\~T()}. +\end{itemdescr} + \indexlibrarymember{select_on_container_copy_construction}{polymorphic_allocator}% \begin{itemdecl} polymorphic_allocator select_on_container_copy_construction() const; @@ -6154,9 +8059,9 @@ \pnum \remarks Calling the \tcode{set_default_resource} and -\tcode{get_default_resource} functions shall not incur a data race. +\tcode{get_default_resource} functions shall not incur a data race\iref{intro.races}. A call to the \tcode{set_default_resource} function -shall synchronize with subsequent calls to +synchronizes with subsequent calls to the \tcode{set_default_resource} and \tcode{get_default_resource} functions. \end{itemdescr} @@ -6788,8 +8693,8 @@ 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); + pointer allocate(size_type n); + pointer allocate(size_type n, const_void_pointer hint); void deallocate(pointer p, size_type n); size_type max_size() const; @@ -7021,7 +8926,7 @@ \indexlibrarymember{allocate}{scoped_allocator_adaptor}% \begin{itemdecl} -[[nodiscard]] pointer allocate(size_type n); +pointer allocate(size_type n); \end{itemdecl} \begin{itemdescr} @@ -7032,7 +8937,7 @@ \indexlibrarymember{allocate}{scoped_allocator_adaptor}% \begin{itemdecl} -[[nodiscard]] pointer allocate(size_type n, const_void_pointer hint); +pointer allocate(size_type n, const_void_pointer hint); \end{itemdecl} \begin{itemdescr} diff --git a/source/meta.tex b/source/meta.tex index 17cbbf91dd..e848e048f8 100644 --- a/source/meta.tex +++ b/source/meta.tex @@ -8,14 +8,15 @@ 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{} \\ +\ref{intseq} & Integer sequences & \tcode{} \\ \rowsep +\ref{type.traits} & Type traits & \tcode{} \\ \rowsep +\ref{meta.reflection} & Reflection & \tcode{} \\ \rowsep +\ref{ratio} & Rational arithmetic & \tcode{} \\ \end{libsumtab} \rSec1[intseq]{Compile-time integer sequences} -\rSec2[intseq.general]{In general} +\rSec2[intseq.general]{General} \pnum The library provides a class template that can represent an integer sequence. @@ -59,9 +60,9 @@ \pnum The alias template \tcode{make_integer_sequence} denotes a specialization of -\tcode{integer_sequence} with \tcode{N} non-type template arguments. +\tcode{integer_sequence} with \tcode{N} constant template arguments. The type \tcode{make_integer_sequence} is an alias for the type -\tcode{integer_sequence}. +\tcode{integer_sequence}. \begin{note} \tcode{make_integer_sequence} is an alias for the type \tcode{integer_sequence}. @@ -138,7 +139,7 @@ \pnum Unless otherwise specified, an incomplete type may be used to instantiate a template specified in \ref{type.traits}. -The behavior of a program is undefined if: +The behavior of a program is undefined if \begin{itemize} \item an instantiation of a template specified in \ref{type.traits} @@ -160,9 +161,25 @@ template struct integral_constant; template - using bool_constant = integral_constant; - using true_type = bool_constant; - using false_type = bool_constant; + using @\libglobal{bool_constant}@ = integral_constant; + using @\libglobal{true_type}@ = bool_constant; + using @\libglobal{false_type}@ = bool_constant; + + // \ref{const.wrap.class}, class template \tcode{constant_wrapper} + template + struct @\exposidnc{cw-fixed-value}@; // \expos + + template<@\exposidnc{cw-fixed-value}@ X, class = typename decltype(@\exposid{cw-fixed-value}@(X))::@\exposid{type}@> + struct constant_wrapper; + + template + concept @\defexposconceptnc{constexpr-param}@ = // \expos + requires { typename constant_wrapper; }; + + struct @\exposidnc{cw-operators}@; // \expos + + template<@\exposid{cw-fixed-value}@ X> + constexpr auto @\libglobal{cw}@ = constant_wrapper{}; // \ref{meta.unary.cat}, primary type categories template struct is_void; @@ -179,6 +196,7 @@ template struct is_union; template struct is_class; template struct is_function; + template struct is_reflection; // \ref{meta.unary.comp}, composite type categories template struct is_reference; @@ -192,14 +210,16 @@ // \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_trivially_relocatable; + template struct is_replaceable; 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_consteval_only; template struct is_signed; template struct is_unsigned; @@ -244,6 +264,7 @@ template struct is_nothrow_swappable; template struct is_nothrow_destructible; + template struct is_nothrow_relocatable; template struct is_implicit_lifetime; @@ -262,6 +283,7 @@ // \ref{meta.rel}, type relations template struct is_same; template struct is_base_of; + template struct is_virtual_base_of; template struct is_convertible; template struct is_nothrow_convertible; template struct is_layout_compatible; @@ -273,6 +295,9 @@ template struct is_nothrow_invocable; template struct is_nothrow_invocable_r; + template struct is_applicable; + template struct is_nothrow_applicable; + // \ref{meta.trans.cv}, const-volatile modifications template struct remove_const; template struct remove_volatile; @@ -345,6 +370,7 @@ template struct common_reference; template struct underlying_type; template struct invoke_result; + template struct apply_result; template struct unwrap_reference; template struct unwrap_ref_decay; @@ -366,6 +392,8 @@ using @\libglobal{underlying_type_t}@ = typename underlying_type::type; template using @\libglobal{invoke_result_t}@ = typename invoke_result::type; + template + using @\libglobal{apply_result_t}@ = typename apply_result::type; template using unwrap_reference_t = typename unwrap_reference::type; template @@ -407,6 +435,8 @@ constexpr bool @\libglobal{is_class_v}@ = is_class::value; template constexpr bool @\libglobal{is_function_v}@ = is_function::value; + template + constexpr bool @\libglobal{is_reflection_v}@ = is_reflection::value; // \ref{meta.unary.comp}, composite type categories template @@ -429,10 +459,10 @@ constexpr bool @\libglobal{is_const_v}@ = is_const::value; template constexpr bool @\libglobal{is_volatile_v}@ = is_volatile::value; - template - constexpr bool @\libglobal{is_trivial_v}@ = is_trivial::value; template constexpr bool @\libglobal{is_trivially_copyable_v}@ = is_trivially_copyable::value; + template + constexpr bool @\libglobal{is_trivially_relocatable_v}@ = is_trivially_relocatable::value; template constexpr bool @\libglobal{is_standard_layout_v}@ = is_standard_layout::value; template @@ -445,6 +475,8 @@ constexpr bool @\libglobal{is_final_v}@ = is_final::value; template constexpr bool @\libglobal{is_aggregate_v}@ = is_aggregate::value; + template + constexpr bool @\libglobal{is_consteval_only_v}@ = is_consteval_only::value; template constexpr bool @\libglobal{is_signed_v}@ = is_signed::value; template @@ -476,39 +508,31 @@ template constexpr bool @\libglobal{is_destructible_v}@ = is_destructible::value; template - constexpr bool is_trivially_constructible_v - = is_trivially_constructible::value; + constexpr bool is_trivially_constructible_v = is_trivially_constructible::value; template constexpr bool is_trivially_default_constructible_v = is_trivially_default_constructible::value; template - constexpr bool is_trivially_copy_constructible_v - = is_trivially_copy_constructible::value; + constexpr bool is_trivially_copy_constructible_v = is_trivially_copy_constructible::value; template - constexpr bool is_trivially_move_constructible_v - = is_trivially_move_constructible::value; + constexpr bool is_trivially_move_constructible_v = is_trivially_move_constructible::value; template constexpr bool @\libglobal{is_trivially_assignable_v}@ = is_trivially_assignable::value; template - constexpr bool is_trivially_copy_assignable_v - = is_trivially_copy_assignable::value; + constexpr bool is_trivially_copy_assignable_v = is_trivially_copy_assignable::value; template - constexpr bool is_trivially_move_assignable_v - = is_trivially_move_assignable::value; + constexpr bool is_trivially_move_assignable_v = is_trivially_move_assignable::value; template constexpr bool @\libglobal{is_trivially_destructible_v}@ = is_trivially_destructible::value; template - constexpr bool is_nothrow_constructible_v - = is_nothrow_constructible::value; + constexpr bool is_nothrow_constructible_v = is_nothrow_constructible::value; template constexpr bool is_nothrow_default_constructible_v = is_nothrow_default_constructible::value; template - constexpr bool is_nothrow_copy_constructible_v - = is_nothrow_copy_constructible::value; + constexpr bool is_nothrow_copy_constructible_v = is_nothrow_copy_constructible::value; template - constexpr bool is_nothrow_move_constructible_v - = is_nothrow_move_constructible::value; + constexpr bool is_nothrow_move_constructible_v = is_nothrow_move_constructible::value; template constexpr bool @\libglobal{is_nothrow_assignable_v}@ = is_nothrow_assignable::value; template @@ -521,8 +545,12 @@ constexpr bool @\libglobal{is_nothrow_swappable_v}@ = is_nothrow_swappable::value; template constexpr bool @\libglobal{is_nothrow_destructible_v}@ = is_nothrow_destructible::value; + template + constexpr bool @\libglobal{is_nothrow_relocatable_v}@ = is_nothrow_relocatable::value; template constexpr bool @\libglobal{is_implicit_lifetime_v}@ = is_implicit_lifetime::value; + template + constexpr bool @\libglobal{is_replaceable_v}@ = is_replaceable::value; template constexpr bool @\libglobal{has_virtual_destructor_v}@ = has_virtual_destructor::value; template @@ -548,6 +576,8 @@ constexpr bool @\libglobal{is_same_v}@ = is_same::value; template constexpr bool @\libglobal{is_base_of_v}@ = is_base_of::value; + template + constexpr bool @\libglobal{is_virtual_base_of_v}@ = is_virtual_base_of::value; template constexpr bool @\libglobal{is_convertible_v}@ = is_convertible::value; template @@ -564,8 +594,11 @@ template constexpr bool @\libglobal{is_nothrow_invocable_v}@ = is_nothrow_invocable::value; template - constexpr bool is_nothrow_invocable_r_v - = is_nothrow_invocable_r::value; + constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r::value; + template + constexpr bool @\libglobal{is_applicable_v}@ = is_applicable::value; + template + constexpr bool @\libglobal{is_nothrow_applicable_v}@ = is_nothrow_applicable::value; // \ref{meta.logical}, logical operator traits template @@ -592,7 +625,7 @@ \indexlibrarymember{value_type}{integral_constant}% \begin{codeblock} namespace std { - template struct integral_constant { + template struct @\libglobal{integral_constant}@ { static constexpr T value = v; using value_type = T; @@ -604,7 +637,6 @@ } \end{codeblock} -\indexlibraryglobal{integral_constant}% \indexlibraryglobal{bool_constant}% \indexlibraryglobal{true_type}% \indexlibraryglobal{false_type}% @@ -616,6 +648,264 @@ are used as base classes to define the interface for various type traits. +\rSec2[const.wrap.class]{Class template \tcode{constant_wrapper}} + +\begin{codeblock} +template +struct @\exposidnc{cw-fixed-value}@ { // \expos + using @\exposidnc{type}@ = T; // \expos + constexpr @\exposidnc{cw-fixed-value}@(@\exposidnc{type}@ v) noexcept : @\exposidnc{data}@(v) {} + T @\exposidnc{data}@; // \expos +}; + +template +struct @\exposidnc{cw-fixed-value}@ { // \expos + using @\exposidnc{type}@ = T[Extent]; // \expos + constexpr @\exposidnc{cw-fixed-value}@(T (&arr)[Extent]) noexcept; + T @\exposidnc{data}@[Extent]; // \expos +}; + +template + @\exposidnc{cw-fixed-value}@(T (&)[Extent]) -> @\exposidnc{cw-fixed-value}@; // \expos + +struct @\exposidnc{cw-operators}@ { // \expos + // unary operators + template<@\exposconcept{constexpr-param}@ T> + friend constexpr auto operator+(T) noexcept -> constant_wrapper<(+T::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ T> + friend constexpr auto operator-(T) noexcept -> constant_wrapper<(-T::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ T> + friend constexpr auto operator~(T) noexcept -> constant_wrapper<(~T::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ T> + friend constexpr auto operator!(T) noexcept -> constant_wrapper<(!T::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ T> + friend constexpr auto operator&(T) noexcept -> constant_wrapper<(&T::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ T> + friend constexpr auto operator*(T) noexcept -> constant_wrapper<(*T::value)> + { return {}; } + + // binary operators + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator+(L, R) noexcept -> constant_wrapper<(L::value + R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator-(L, R) noexcept -> constant_wrapper<(L::value - R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator*(L, R) noexcept -> constant_wrapper<(L::value * R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator/(L, R) noexcept -> constant_wrapper<(L::value / R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator%(L, R) noexcept -> constant_wrapper<(L::value % R::value)> + { return {}; } + + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator<<(L, R) noexcept -> constant_wrapper<(L::value << R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator>>(L, R) noexcept -> constant_wrapper<(L::value >> R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator&(L, R) noexcept -> constant_wrapper<(L::value & R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator|(L, R) noexcept -> constant_wrapper<(L::value | R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator^(L, R) noexcept -> constant_wrapper<(L::value ^ R::value)> + { return {}; } + + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + requires (!is_constructible_v || + !is_constructible_v) + friend constexpr auto operator&&(L, R) noexcept -> constant_wrapper<(L::value && R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + requires (!is_constructible_v || + !is_constructible_v) + friend constexpr auto operator||(L, R) noexcept -> constant_wrapper<(L::value || R::value)> + { return {}; } + + // comparisons + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator<=>(L, R) noexcept -> constant_wrapper<(L::value <=> R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator<(L, R) noexcept -> constant_wrapper<(L::value < R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator<=(L, R) noexcept -> constant_wrapper<(L::value <= R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator==(L, R) noexcept -> constant_wrapper<(L::value == R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator!=(L, R) noexcept -> constant_wrapper<(L::value != R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator>(L, R) noexcept -> constant_wrapper<(L::value > R::value)> + { return {}; } + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator>=(L, R) noexcept -> constant_wrapper<(L::value >= R::value)> + { return {}; } + + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator,(L, R) noexcept = delete; + template<@\exposconcept{constexpr-param}@ L, @\exposconcept{constexpr-param}@ R> + friend constexpr auto operator->*(L, R) noexcept -> constant_wrapper*(R::value)> + { return {}; } + + // call and index + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@... Args> + constexpr auto operator()(this T, Args...) noexcept + requires requires(Args...) { constant_wrapper(); } + { return constant_wrapper{}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@... Args> + constexpr auto operator[](this T, Args...) noexcept + -> constant_wrapper<(T::value[Args::value...])> + { return {}; } + + // pseudo-mutators + template<@\exposconcept{constexpr-param}@ T> + constexpr auto operator++(this T) noexcept + requires requires(T::value_type x) { ++x; } + { return constant_wrapper<[] { auto c = T::value; return ++c; }()>{}; } + template<@\exposconcept{constexpr-param}@ T> + constexpr auto operator++(this T, int) noexcept + requires requires(T::value_type x) { x++; } + { return constant_wrapper<[] { auto c = T::value; return c++; }()>{}; } + + template<@\exposconcept{constexpr-param}@ T> + constexpr auto operator--(this T) noexcept + requires requires(T::value_type x) { --x; } + { return constant_wrapper<[] { auto c = T::value; return --c; }()>{}; } + template<@\exposconcept{constexpr-param}@ T> + constexpr auto operator--(this T, int) noexcept + requires requires(T::value_type x) { x--; } + { return constant_wrapper<[] { auto c = T::value; return c--; }()>{}; } + + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator+=(this T, R) noexcept + requires requires(T::value_type x) { x += R::value; } + { return constant_wrapper<[] { auto v = T::value; return v += R::value; }()>{}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator-=(this T, R) noexcept + requires requires(T::value_type x) { x -= R::value; } + { return constant_wrapper<[] { auto v = T::value; return v -= R::value; }()>{}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator*=(this T, R) noexcept + requires requires(T::value_type x) { x *= R::value; } + { return constant_wrapper<[] { auto v = T::value; return v *= R::value; }()>{}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator/=(this T, R) noexcept + requires requires(T::value_type x) { x /= R::value; } + { return constant_wrapper<[] { auto v = T::value; return v /= R::value; }()>{}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator%=(this T, R) noexcept + requires requires(T::value_type x) { x %= R::value; } + { return constant_wrapper<[] { auto v = T::value; return v %= R::value; }()>{}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator&=(this T, R) noexcept + requires requires(T::value_type x) { x &= R::value; } + { return constant_wrapper<[] { auto v = T::value; return v &= R::value; }()>{}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator|=(this T, R) noexcept + requires requires(T::value_type x) { x |= R::value; } + { return constant_wrapper<[] { auto v = T::value; return v |= R::value; }()>{}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator^=(this T, R) noexcept + requires requires(T::value_type x) { x ^= R::value; } + { return constant_wrapper<[] { auto v = T::value; return v ^= R::value; }()>{}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator<<=(this T, R) noexcept + requires requires(T::value_type x) { x <<= R::value; } + { return constant_wrapper<[] { auto v = T::value; return v <<= R::value; }()>{}; } + template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> + constexpr auto operator>>=(this T, R) noexcept + requires requires(T::value_type x) { x >>= R::value; } + { return constant_wrapper<[] { auto v = T::value; return v >>= R::value; }()>{}; } +}; + +template<@\exposid{cw-fixed-value}@ X, class> +struct constant_wrapper : cw-operators { + static constexpr const auto & value = X.@\exposid{data}@; + using type = constant_wrapper; + using value_type = typename decltype(X)::@\exposid{type}@; + + template<@\exposconcept{constexpr-param}@ R> + constexpr auto operator=(R) const noexcept + requires requires(value_type x) { x = R::value; } + { return constant_wrapper<[] { auto v = value; return v = R::value; }()>{}; } + + constexpr operator decltype(auto)() const noexcept { return value; } +}; +\end{codeblock} + +\pnum +The class template \tcode{constant_wrapper} aids in metaprogramming by ensuring +that the evaluation of expressions comprised entirely of \tcode{constant_wrapper} +are core constant expressions\iref{expr.const}, +regardless of the context in which they appear. +In particular, this enables use of \tcode{constant_wrapper} values +that are passed as arguments to constexpr functions to be used in constant expressions. + +\pnum +\begin{note} +The unnamed second template parameter to \tcode{constant_wrapper} is present +to aid argument-dependent lookup\iref{basic.lookup.argdep} +in finding overloads for which \tcode{constant_wrapper}'s wrapped value is a suitable argument, +but for which the \tcode{constant_wrapper} itself is not. +\end{note} + +\pnum +\begin{example} +\begin{codeblock} + constexpr auto initial_phase(auto quantity_1, auto quantity_2) { + return quantity_1 + quantity_2; + } + + constexpr auto middle_phase(auto tbd) { + return tbd; + } + + void final_phase(auto gathered, auto available) { + if constexpr (gathered == available) + std::cout << "Profit!\n"; + } + + void impeccable_underground_planning() { + auto gathered_quantity = middle_phase(initial_phase(std::cw<42>, std::cw<13>)); + static_assert(gathered_quantity == 55); + auto all_available = std::cw<55>; + final_phase(gathered_quantity, all_available); + } + + void deeply_flawed_underground_planning() { + constexpr auto gathered_quantity = middle_phase(initial_phase(42, 13)); + constexpr auto all_available = 55; + final_phase(gathered_quantity, all_available); // error: \tcode{gathered == available} + // is not a constant expression + } +\end{codeblock} +\end{example} + +\begin{itemdecl} +constexpr @\exposid{cw-fixed-value}@(T (&arr)[Extent]) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initialize elements of \exposid{data} with corresponding elements of \tcode{arr}. +\end{itemdescr} + \rSec2[meta.unary]{Unary type traits} \rSec3[meta.unary.general]{General} @@ -715,7 +1005,11 @@ \indexlibraryglobal{is_function}% \tcode{template}\br \tcode{struct is_function;} & -\tcode{T} is a function type\iref{basic.compound} & \\ +\tcode{T} is a function type\iref{basic.compound} & \\ \rowsep +\indexlibraryglobal{is_reflection}% +\tcode{template}\br + \tcode{struct is_reflection;} & +\tcode{T} is \tcode{std::meta::info}\iref{basic.fundamental} & \\ \end{libreqtab3e} \rSec3[meta.unary.comp]{Composite type traits} @@ -830,13 +1124,6 @@ \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;} & @@ -844,6 +1131,20 @@ \tcode{remove_all_extents_t} shall be a complete type or \cv{}~\keyword{void}. \\ \rowsep +\indexlibraryglobal{is_trivially_relocatable}% +\tcode{template}\br + \tcode{struct is_trivially_relocatable;} & + \tcode{T} is a trivially relocatable type\iref{basic.types.general} & + \tcode{remove_all_extents_t} shall be a complete type or + \cv{}~\keyword{void}. \\ \rowsep + +\indexlibraryglobal{is_replaceable}% +\tcode{template}\br + \tcode{struct is_replaceable;} & + \tcode{T} is a replaceable type\iref{basic.types.general} & + \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;} & @@ -875,7 +1176,7 @@ \indexlibraryglobal{is_final}% \tcode{template}\br \tcode{struct is_final;} & - \tcode{T} is a class type marked with the \grammarterm{class-virt-specifier} + \tcode{T} is a class type marked with the \grammarterm{class-property-specifier} \tcode{final}\iref{class.pre}. \begin{tailnote} A union is a class type that @@ -890,6 +1191,12 @@ \tcode{T} is an aggregate type\iref{dcl.init.aggr} & \tcode{T} shall be an array type, a complete type, or \cv~\keyword{void}. \\ \rowsep +\indexlibraryglobal{is_consteval_only}% +\tcode{template}\br + \tcode{struct is_consteval_only;} & + \tcode{T} is consteval-only\iref{basic.types.general} & + \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;} & @@ -1206,6 +1513,16 @@ \cv{}~\keyword{void}, or an array of unknown bound. \\ \rowsep +\indexlibraryglobal{is_nothrow_relocatable}% +\tcode{template}\br + \tcode{struct is_nothrow_relocatable;} & + \tcode{is_trivially_relocatable_v ||} + \tcode{(is_nothrow_move_constructible_v<} + \tcode{remove_all_extents_t> \&\& is_nothrow_destructible_v<} + \tcode{remove_all_extents_t>)} & + \tcode{remove_all_extents_t} shall be a complete type or + \cv{}~\keyword{void}. \\ \rowsep + \indexlibraryglobal{is_implicit_lifetime}% \tcode{template}\br \tcode{struct is_implicit_lifetime;} & @@ -1225,8 +1542,8 @@ 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 + \tcode{remove_all_extents_t} shall be a complete type or + \cv{}~\keyword{void}. \\ \rowsep \indexlibraryglobal{reference_constructs_from_temporary}% \tcode{template}\br @@ -1341,7 +1658,7 @@ \pnum The predicate condition for a template specialization \tcode{has_unique_object_representations} -shall be satisfied if and only if: +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 @@ -1441,6 +1758,13 @@ \tcode{true_type} if the corresponding condition is true, otherwise \tcode{false_type}. +\pnum +Let \tcode{\placeholdernc{ELEMS-OF}(T)} be the parameter pack +\tcode{get<\exposid{N}>(declval())}, where \exposid{N} is the pack of +\tcode{size_t} template arguments of the specialization of +\tcode{index_sequence} denoted by +\tcode{make_index_sequence>>}. + \begin{libreqtab3f}{Type relationship predicates}{meta.rel} \\ \topline \lhdr{Template} & \chdr{Condition} & \rhdr{Comments} \\ \capsep @@ -1463,15 +1787,31 @@ 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, + 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 + Base classes that are private, protected, or ambiguous are, nonetheless, base classes. \end{tailnote} \\ \rowsep +\indexlibraryglobal{is_virtual_base_of}% +\tcode{template}\br + \tcode{struct is_virtual_base_of;} & + \tcode{Base} is a virtual base class of \tcode{Derived}\iref{class.mi} + without regard to cv-qualifiers. & + If \tcode{Base} and + \tcode{Derived} are non-union class types, + \tcode{Derived} shall be a complete type. + \begin{note} + Virtual base classes that are private, protected, or ambiguous + are, nonetheless, virtual base classes. + \end{note} + \begin{tailnote} + A class is never a virtual base class of itself. + \end{tailnote} \\ \rowsep + \indexlibraryglobal{is_convertible}% \tcode{template}\br \tcode{struct is_convertible;} & @@ -1486,7 +1826,7 @@ 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 + \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep \indexlibraryglobal{is_layout_compatible}% \tcode{template}\br @@ -1547,6 +1887,27 @@ 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. \\ \rowsep + +\indexlibraryglobal{is_applicable}% +\tcode{template}\br + \tcode{struct is_applicable;} & + \tcode{\exposconcept{tuple-like}} is \tcode{true} and + the expression + \tcode{\placeholdernc{INVOKE}(declval(), \placeholdernc{ELEMS-OF}(Tuple)...)} + is well-formed when treated as an unevaluated operand. & + \tcode{Fn} and \tcode{Tuple} + shall be complete types, \cv{}~\keyword{void}, or + arrays of unknown bound. \\ \rowsep + +\indexlibraryglobal{is_nothrow_applicable}% +\tcode{template}\br + \tcode{struct is_nothrow_applicable;} & + \tcode{is_applicable_v<}\br\tcode{Fn, Tuple>} is \tcode{true} and + the expression \tcode{\placeholdernc{INVOKE}(declval(), \placeholdernc{ELEMS-OF}(Tuple)...)} + is known not to throw any exceptions\iref{expr.unary.noexcept}. & + \tcode{Fn} and \tcode{Tuple} + shall be complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \end{libreqtab3f} @@ -1671,16 +2032,22 @@ \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} denotes \tcode{T}, otherwise - \tcode{T const}. \\ \rowsep + The member typedef \tcode{type} denotes \tcode{const T}. +\begin{tailnote} +\keyword{const} has no effect when \tcode{T} is a reference, function, or +top-level const-qualified type. +\end{tailnote} +\\ \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} denotes \tcode{T}, otherwise - \tcode{T volatile}. \\ \rowsep + The member typedef \tcode{type} denotes \tcode{volatile T}. +\begin{tailnote} +\keyword{volatile} has no effect when \tcode{T} is a reference, function, or +top-level volatile-qualified type. +\end{tailnote} +\\ \rowsep \indexlibraryglobal{add_cv}% \tcode{template\br @@ -1888,21 +2255,18 @@ \lhdr{Template} & \rhdr{Comments} \\ \capsep \endhead -\indexlibraryglobal{type_identity}% \tcode{template\br - struct type_identity;} + struct \libglobal{type_identity};} & The member typedef \tcode{type} denotes \tcode{T}. \\ \rowsep -\indexlibraryglobal{remove_cvref}% -\tcode{template\br struct remove_cvref;} +\tcode{template\br struct \libglobal{remove_cvref};} & The member typedef \tcode{type} denotes \tcode{remove_cv_t>}. \\ \rowsep -\indexlibraryglobal{decay}% -\tcode{template\br struct decay;} +\tcode{template\br struct \libglobal{decay};} & Let \tcode{U} be \tcode{remove_reference_t}. If \tcode{is_array_v} is \tcode{true}, the member typedef \tcode{type} denotes @@ -1918,8 +2282,7 @@ \end{tailnote} \\ \rowsep -\indexlibraryglobal{enable_if}% -\tcode{template} \tcode{struct enable_if;} +\tcode{template} \tcode{struct \libglobal{enable_if};} & If \tcode{B} is \tcode{true}, the member typedef \tcode{type} denotes \tcode{T}; otherwise, there shall be no member @@ -1927,49 +2290,45 @@ \tcode{template}\br - \tcode{struct conditional;} + \tcode{struct \libglobal{conditional};} & If \tcode{B} is \tcode{true}, the member typedef \tcode{type} denotes \tcode{T}. If \tcode{B} is \tcode{false}, the member typedef \tcode{type} denotes \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. + Unless this trait is specialized, + the member \tcode{type} is defined or omitted as specified 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;} + \hspace*{2ex}\tcode{\libglobal{basic_common_reference};} & - Unless this trait is specialized (as specified in Note D, below), + Unless this trait is specialized, there shall be no member \tcode{type}. \\ \rowsep -\indexlibraryglobal{common_reference}% -\tcode{template} \tcode{struct common_reference;} +\tcode{template} \tcode{struct \libglobal{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 + as specified 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;} + \tcode{struct \libglobal{underlying_type};} & If \tcode{T} is an enumeration type, the member typedef \tcode{type} denotes 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 -\indexlibraryglobal{invoke_result}% \tcode{template}\br - \tcode{struct invoke_result;} + \tcode{struct \libglobal{invoke_result};} & If the expression \tcode{\placeholdernc{INVOKE}(declval(), declval()...)}\iref{func.require} is well-formed when treated as an unevaluated operand\iref{term.unevaluated.operand}, @@ -1990,8 +2349,33 @@ are complete types, \cv{}~\keyword{void}, or arrays of unknown bound.\\ \rowsep -\indexlibraryglobal{unwrap_reference}% -\tcode{template} \tcode{struct unwrap_reference;} +\tcode{template}\br + \tcode{struct \libglobal{apply_result};} + & + If \tcode{\exposconcept{tuple-like}} is \tcode{true} + and the expression + \tcode{\placeholdernc{INVOKE}(declval(), \placeholdernc{ELEMS-OF}(Tuple)...)}\iref{func.require} + is well-formed + when treated as an unevaluated operand\iref{term.unevaluated.operand}, + the member typedef \tcode{type} denotes the type + \tcode{decltype(\placeholdernc{INVOKE}(declval(), \placeholdernc{ELEMS-OF}(Tuple)...))}; + otherwise, there shall be no member \tcode{type}. + Access checking is performed as if in a context unrelated to \tcode{Fn} + and \tcode{Tuple}. + 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 \tcode{Tuple} are complete types, \cv{}~\keyword{void}, + or arrays of unknown bound.\\ \rowsep + +\tcode{template} \tcode{struct \libglobal{unwrap_reference};} & If \tcode{T} is a specialization \tcode{reference_wrapper} for some type \tcode{X}, @@ -1999,8 +2383,7 @@ denotes \tcode{X\&}, otherwise \tcode{type} denotes \tcode{T}. \\ \rowsep -\indexlibraryglobal{unwrap_ref_decay}% -\tcode{template} \tcode{unwrap_ref_decay;} +\tcode{template} \tcode{\libglobal{unwrap_ref_decay};} & The member typedef \tcode{type} of \tcode{unwrap_ref_decay} denotes the type \tcode{unwrap_reference_t>}.\\ @@ -2066,7 +2449,6 @@ \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: @@ -2120,7 +2502,7 @@ \end{itemize} \pnum -Note B: Notwithstanding the provisions of \ref{meta.type.synop}, and +Notwithstanding the provisions of \ref{meta.rqmts}, and pursuant to \ref{namespace.std}, a program may specialize \tcode{common_type} for types \tcode{T1} and \tcode{T2} such that @@ -2140,7 +2522,7 @@ 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 +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} @@ -2186,7 +2568,7 @@ \end{itemize} \pnum -Note D: Notwithstanding the provisions of \ref{meta.type.synop}, and +Notwithstanding the provisions of \ref{meta.rqmts}, and pursuant to \ref{namespace.std}, a program may partially specialize \tcode{basic_common_reference} for types \tcode{T} and \tcode{U} such that @@ -2504,7 +2886,7 @@ } } - constexpr auto operator*() -> bool& { + constexpr auto operator*() const -> const bool& { return b; } }; @@ -2518,9 +2900,4144 @@ \end{example} \end{itemdescr} +\rSec1[meta.reflection]{Reflection} + +\rSec2[meta.syn]{Header \tcode{} synopsis} + +\indexheader{meta}% +\begin{codeblock} +#include // see \ref{initializer.list.syn} + +namespace std { + // \ref{meta.string.literal}, checking string literals + consteval bool is_string_literal(const char* p); + consteval bool is_string_literal(const wchar_t* p); + consteval bool is_string_literal(const char8_t* p); + consteval bool is_string_literal(const char16_t* p); + consteval bool is_string_literal(const char32_t* p); + + // \ref{meta.define.static}, promoting to static storage strings + template + consteval const ranges::range_value_t* define_static_string(R&& r); + template + consteval span> define_static_array(R&& r); + template + consteval const remove_cvref_t* define_static_object(T&& r); +} + +namespace std::meta { + using info = decltype(^^::); + + // \ref{meta.reflection.exception}, class \tcode{exception} + class exception; + + // \ref{meta.reflection.operators}, operator representations + enum class operators { + @\seebelow@; + }; + using enum operators; + consteval operators operator_of(info r); + consteval string_view symbol_of(operators op); + consteval u8string_view u8symbol_of(operators op); + + // \ref{meta.reflection.names}, reflection names and locations + consteval bool has_identifier(info r); + + consteval string_view identifier_of(info r); + consteval u8string_view u8identifier_of(info r); + + consteval string_view display_string_of(info r); + consteval u8string_view u8display_string_of(info r); + + consteval source_location source_location_of(info r); + + // \ref{meta.reflection.queries}, reflection queries + consteval info type_of(info r); + consteval info object_of(info r); + consteval info constant_of(info r); + + consteval bool is_public(info r); + consteval bool is_protected(info r); + consteval bool is_private(info r); + + consteval bool is_virtual(info r); + consteval bool is_pure_virtual(info r); + consteval bool is_override(info r); + consteval bool is_final(info r); + + consteval bool is_deleted(info r); + consteval bool is_defaulted(info r); + consteval bool is_user_provided(info r); + consteval bool is_user_declared(info r); + consteval bool is_explicit(info r); + consteval bool is_noexcept(info r); + + consteval bool is_bit_field(info r); + consteval bool is_enumerator(info r); + consteval bool is_annotation(info r); + + consteval bool is_const(info r); + consteval bool is_volatile(info r); + consteval bool is_mutable_member(info r); + consteval bool is_lvalue_reference_qualified(info r); + consteval bool is_rvalue_reference_qualified(info r); + + consteval bool has_static_storage_duration(info r); + consteval bool has_thread_storage_duration(info r); + consteval bool has_automatic_storage_duration(info r); + + consteval bool has_internal_linkage(info r); + consteval bool has_module_linkage(info r); + consteval bool has_external_linkage(info r); + consteval bool has_c_language_linkage(info r); + consteval bool has_linkage(info r); + + consteval bool is_complete_type(info r); + consteval bool is_enumerable_type(info r); + + consteval bool is_variable(info r); + consteval bool is_type(info r); + consteval bool is_namespace(info r); + consteval bool is_type_alias(info r); + consteval bool is_namespace_alias(info r); + + consteval bool is_function(info r); + consteval bool is_conversion_function(info r); + consteval bool is_operator_function(info r); + consteval bool is_literal_operator(info r); + consteval bool is_special_member_function(info r); + consteval bool is_constructor(info r); + consteval bool is_default_constructor(info r); + consteval bool is_copy_constructor(info r); + consteval bool is_move_constructor(info r); + consteval bool is_assignment(info r); + consteval bool is_copy_assignment(info r); + consteval bool is_move_assignment(info r); + consteval bool is_destructor(info r); + + consteval bool is_function_parameter(info r); + consteval bool is_explicit_object_parameter(info r); + consteval bool has_default_argument(info r); + consteval bool has_ellipsis_parameter(info r); + + consteval bool is_template(info r); + consteval bool is_function_template(info r); + consteval bool is_variable_template(info r); + consteval bool is_class_template(info r); + consteval bool is_alias_template(info r); + consteval bool is_conversion_function_template(info r); + consteval bool is_operator_function_template(info r); + consteval bool is_literal_operator_template(info r); + consteval bool is_constructor_template(info r); + consteval bool is_concept(info r); + + consteval bool is_value(info r); + consteval bool is_object(info r); + + consteval bool is_structured_binding(info r); + + consteval bool is_class_member(info r); + consteval bool is_namespace_member(info r); + consteval bool is_nonstatic_data_member(info r); + consteval bool is_static_member(info r); + consteval bool is_base(info r); + + consteval bool has_default_member_initializer(info r); + + consteval bool has_parent(info r); + consteval info parent_of(info r); + + consteval info dealias(info r); + + consteval bool has_template_arguments(info r); + consteval info template_of(info r); + consteval vector template_arguments_of(info r); + consteval vector parameters_of(info r); + consteval info variable_of(info r); + consteval info return_type_of(info r); + + // \ref{meta.reflection.access.context}, access control context + struct access_context; + + // \ref{meta.reflection.access.queries}, member accessibility queries + consteval bool is_accessible(info r, access_context ctx); + consteval bool has_inaccessible_nonstatic_data_members(info r, access_context ctx); + consteval bool has_inaccessible_bases(info r, access_context ctx); + consteval bool has_inaccessible_subobjects(info r, access_context ctx); + + // \ref{meta.reflection.member.queries}, reflection member queries + consteval vector members_of(info r, access_context ctx); + consteval vector bases_of(info type, access_context ctx); + consteval vector static_data_members_of(info type, access_context ctx); + consteval vector nonstatic_data_members_of(info type, access_context ctx); + consteval vector subobjects_of(info type, access_context ctx); + consteval vector enumerators_of(info type_enum); + + // \ref{meta.reflection.layout}, reflection layout queries + struct member_offset; + consteval member_offset offset_of(info r); + consteval size_t size_of(info r); + consteval size_t alignment_of(info r); + consteval size_t bit_size_of(info r); + + // \ref{meta.reflection.extract}, value extraction + template + consteval T extract(info); + + // \ref{meta.reflection.substitute}, reflection substitution + template + concept reflection_range = @\seebelow@; + + template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool can_substitute(info templ, R&& arguments); + template<@\libconcept{reflection_range}@ R = initializer_list> + consteval info substitute(info templ, R&& arguments); + + // \ref{meta.reflection.result}, expression result reflection + template + consteval info reflect_constant(const T& value); + template + consteval info reflect_object(T& object); + template + consteval info reflect_function(T& fn); + + // \ref{meta.reflection.array}, promoting to static storage arrays + template + consteval info reflect_constant_string(R&& r); + + template + consteval info reflect_constant_array(R&& r); + + // \ref{meta.reflection.define.aggregate}, class definition generation + struct data_member_options; + consteval info data_member_spec(info type, data_member_options options); + consteval bool is_data_member_spec(info r); + template<@\libconcept{reflection_range}@ R = initializer_list> + consteval info define_aggregate(info type_class, R&&); + + // associated with \ref{meta.unary.cat}, primary type categories + consteval bool is_void_type(info type); + consteval bool is_null_pointer_type(info type); + consteval bool is_integral_type(info type); + consteval bool is_floating_point_type(info type); + consteval bool is_array_type(info type); + consteval bool is_pointer_type(info type); + consteval bool is_lvalue_reference_type(info type); + consteval bool is_rvalue_reference_type(info type); + consteval bool is_member_object_pointer_type(info type); + consteval bool is_member_function_pointer_type(info type); + consteval bool is_enum_type(info type); + consteval bool is_union_type(info type); + consteval bool is_class_type(info type); + consteval bool is_function_type(info type); + consteval bool is_reflection_type(info type); + + // associated with \ref{meta.unary.comp}, composite type categories + consteval bool is_reference_type(info type); + consteval bool is_arithmetic_type(info type); + consteval bool is_fundamental_type(info type); + consteval bool is_object_type(info type); + consteval bool is_scalar_type(info type); + consteval bool is_compound_type(info type); + consteval bool is_member_pointer_type(info type); + + // associated with \ref{meta.unary.prop}, type properties + consteval bool is_const_type(info type); + consteval bool is_volatile_type(info type); + consteval bool is_trivially_copyable_type(info type); + consteval bool is_trivially_relocatable_type(info type); + consteval bool is_replaceable_type(info type); + consteval bool is_standard_layout_type(info type); + consteval bool is_empty_type(info type); + consteval bool is_polymorphic_type(info type); + consteval bool is_abstract_type(info type); + consteval bool is_final_type(info type); + consteval bool is_aggregate_type(info type); + consteval bool is_consteval_only_type(info type); + consteval bool is_signed_type(info type); + consteval bool is_unsigned_type(info type); + consteval bool is_bounded_array_type(info type); + consteval bool is_unbounded_array_type(info type); + consteval bool is_scoped_enum_type(info type); + + template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool is_constructible_type(info type, R&& type_args); + consteval bool is_default_constructible_type(info type); + consteval bool is_copy_constructible_type(info type); + consteval bool is_move_constructible_type(info type); + + consteval bool is_assignable_type(info type_dst, info type_src); + consteval bool is_copy_assignable_type(info type); + consteval bool is_move_assignable_type(info type); + + consteval bool is_swappable_with_type(info type1, info type2); + consteval bool is_swappable_type(info type); + + consteval bool is_destructible_type(info type); + + template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool is_trivially_constructible_type(info type, R&& type_args); + consteval bool is_trivially_default_constructible_type(info type); + consteval bool is_trivially_copy_constructible_type(info type); + consteval bool is_trivially_move_constructible_type(info type); + + consteval bool is_trivially_assignable_type(info type_dst, info type_src); + consteval bool is_trivially_copy_assignable_type(info type); + consteval bool is_trivially_move_assignable_type(info type); + consteval bool is_trivially_destructible_type(info type); + + template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool is_nothrow_constructible_type(info type, R&& type_args); + consteval bool is_nothrow_default_constructible_type(info type); + consteval bool is_nothrow_copy_constructible_type(info type); + consteval bool is_nothrow_move_constructible_type(info type); + + consteval bool is_nothrow_assignable_type(info type_dst, info type_src); + consteval bool is_nothrow_copy_assignable_type(info type); + consteval bool is_nothrow_move_assignable_type(info type); + + consteval bool is_nothrow_swappable_with_type(info type1, info type2); + consteval bool is_nothrow_swappable_type(info type); + + consteval bool is_nothrow_destructible_type(info type); + consteval bool is_nothrow_relocatable_type(info type); + + consteval bool is_implicit_lifetime_type(info type); + + consteval bool has_virtual_destructor(info type); + + consteval bool has_unique_object_representations(info type); + + consteval bool reference_constructs_from_temporary(info type_dst, info type_src); + consteval bool reference_converts_from_temporary(info type_dst, info type_src); + + // associated with \ref{meta.unary.prop.query}, type property queries + consteval size_t rank(info type); + consteval size_t extent(info type, unsigned i = 0); + + // associated with \ref{meta.rel}, type relations + consteval bool is_same_type(info type1, info type2); + consteval bool is_base_of_type(info type_base, info type_derived); + consteval bool is_virtual_base_of_type(info type_base, info type_derived); + consteval bool is_convertible_type(info type_src, info type_dst); + consteval bool is_nothrow_convertible_type(info type_src, info type_dst); + consteval bool is_layout_compatible_type(info type1, info type2); + consteval bool is_pointer_interconvertible_base_of_type(info type_base, info type_derived); + + template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool is_invocable_type(info type, R&& type_args); + template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool is_invocable_r_type(info type_result, info type, R&& type_args); + + template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool is_nothrow_invocable_type(info type, R&& type_args); + template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool is_nothrow_invocable_r_type(info type_result, info type, R&& type_args); + + // associated with \ref{meta.trans.cv}, const-volatile modifications + consteval info remove_const(info type); + consteval info remove_volatile(info type); + consteval info remove_cv(info type); + consteval info add_const(info type); + consteval info add_volatile(info type); + consteval info add_cv(info type); + + // associated with \ref{meta.trans.ref}, reference modifications + consteval info remove_reference(info type); + consteval info add_lvalue_reference(info type); + consteval info add_rvalue_reference(info type); + + // associated with \ref{meta.trans.sign}, sign modifications + consteval info make_signed(info type); + consteval info make_unsigned(info type); + + // associated with \ref{meta.trans.arr}, array modifications + consteval info remove_extent(info type); + consteval info remove_all_extents(info type); + + // associated with \ref{meta.trans.ptr}, pointer modifications + consteval info remove_pointer(info type); + consteval info add_pointer(info type); + + // associated with \ref{meta.trans.other}, other transformations + consteval info remove_cvref(info type); + consteval info decay(info type); + template<@\libconcept{reflection_range}@ R = initializer_list> + consteval info common_type(R&& type_args); + template<@\libconcept{reflection_range}@ R = initializer_list> + consteval info common_reference(R&& type_args); + consteval info underlying_type(info type); + template<@\libconcept{reflection_range}@ R = initializer_list> + consteval info invoke_result(info type, R&& type_args); + consteval info unwrap_reference(info type); + consteval info unwrap_ref_decay(info type); + + consteval size_t tuple_size(info type); + consteval info tuple_element(size_t index, info type); + + consteval size_t variant_size(info type); + consteval info variant_alternative(size_t index, info type); + + consteval strong_ordering type_order(info type_a, info type_b); + + // \ref{meta.reflection.annotation}, annotation reflection + consteval vector annotations_of(info item); + consteval vector annotations_of_with_type(info item, info type); +} +\end{codeblock} + +\pnum +Unless otherwise specified, +each function, and each specialization of any function template, +specified in this header +is a designated addressable function\iref{namespace.std}. + +\pnum +The behavior of any function specified in namespace \tcode{std::meta} is +\impldef{behavior of any function in \tcode{std::meta} +for implementation-specific constructs} +when a reflection of a construct not otherwise specified by this document +is provided as an argument. +\begin{note} +Values of type \tcode{std::meta::info} +can represent implementation-specific constructs\iref{basic.fundamental}. +\end{note} +\begin{note} +The behavior of many of the functions specified in namespace \tcode{std::meta} +have semantics that can be affected by +the completeness of class types represented by reflection values. +For such functions, +for any reflection \tcode{r} such that \tcode{dealias(r)} +represents a specialization of a templated class with a reachable definition, +the specialization is implicitly instantiated\iref{temp.inst}. +\begin{example} +\begin{codeblock} +template +struct X { + T mem; +}; + +static_assert(size_of(^^X) == sizeof(int)); // instantiates \tcode{X} +\end{codeblock} +\end{example} +\end{note} + +\pnum +Any function in namespace \tcode{std::meta} +whose return type is \tcode{string_view} or \tcode{u8string_view} +returns an object \exposid{V} such that +\tcode{\exposid{V}.data()[\exposid{V}.size()]} equals \tcode{'\textbackslash 0'}. +\begin{example} +\begin{codeblock} +struct C { }; + +constexpr string_view sv = identifier_of(^^C); +static_assert(sv == "C"); +static_assert(sv.data()[0] == 'C'); +static_assert(sv.data()[1] == '@\textbackslash{}@0'); +\end{codeblock} +\end{example} + +\pnum +For the purpose of exposition, +throughout this clause \tcode{\caret\caret\placeholder{E}} is used +to indicate a reflection representing source construct \tcode{\placeholder{E}}. + +\rSec2[meta.string.literal]{Checking string literals} + +\indexlibraryglobal{is_string_literal}% +\begin{itemdecl} +consteval bool is_string_literal(const char* p); +consteval bool is_string_literal(const wchar_t* p); +consteval bool is_string_literal(const char8_t* p); +consteval bool is_string_literal(const char16_t* p); +consteval bool is_string_literal(const char32_t* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item + If \tcode{p} points to an unspecified object\iref{expr.const}, + \tcode{false}. +\item + Otherwise, if \tcode{p} points to a subobject + of a string literal object\iref{lex.string}, + \tcode{true}. +\item + Otherwise, \tcode{false}. +\end{itemize} +\end{itemdescr} + +\rSec2[meta.define.static]{Promoting to static storage strings} + +\pnum +The functions in this subclause promote compile-time storage into static storage. + +\indexlibraryglobal{define_static_string}% +\begin{itemdecl} +template + consteval const ranges::range_value_t* define_static_string(R&& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return extract*>(meta::reflect_constant_string(r)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{define_static_array}% +\begin{itemdecl} +template + consteval span> define_static_array(R&& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +using T = ranges::range_value_t; +meta::info array = meta::reflect_constant_array(r); +if (is_array_type(type_of(array))) { + return span(extract(array), extent(type_of(array))); +} else { + return span(); +} +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{define_static_object}% +\begin{itemdecl} +template + consteval const remove_cvref_t* define_static_object(T&& t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +using U = remove_cvref_t; +if constexpr (is_class_type(^^U)) { + return addressof(extract(meta::reflect_constant(std::forward(t)))); +} else { + return define_static_array(span(addressof(t), 1)).data(); +} +\end{codeblock} + +\pnum +\begin{note} +For class types, +\tcode{define_static_object} provides +the address of the template parameter object\iref{temp.param} +that is template-argument equivalent to \tcode{t}. +\end{note} +\end{itemdescr} + +\rSec2[meta.reflection.exception]{Class \tcode{exception}} + +\indexlibraryglobal{exception}% +\begin{codeblock} +namespace std::meta { + class exception : public std::exception { + private: + optional @\exposidnc{what_}@; // \expos + u8string @\exposidnc{u8what_}@; // \expos + info @\exposidnc{from_}@; // \expos + source_location @\exposidnc{where_}@; // \expos + + public: + consteval exception(u8string_view what, info from, + source_location where = source_location::current()) noexcept; + + consteval exception(string_view what, info from, + source_location where = source_location::current()) noexcept; + + exception(const exception&) = default; + exception(exception&&) = default; + + exception& operator=(const exception&) = default; + exception& operator=(exception&&) = default; + + constexpr const char* what() const noexcept override; + consteval u8string_view u8what() const noexcept; + consteval info from() const noexcept; + consteval source_location where() const noexcept; + }; +} +\end{codeblock} + +\pnum +Reflection functions throw exceptions of type \tcode{meta::exception} +to signal an error. +\tcode{meta::exception} is a consteval-only type. + +\indexlibraryctor{exception}% +\begin{itemdecl} +consteval exception(u8string_view what, info from, + source_location where = source_location::current()) noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Initializes +\exposid{u8what_} with \tcode{what}, +\exposid{from_} with \tcode{from}, and +\exposid{where_} with \tcode{where}. +If \tcode{what} can be represented in the ordinary literal encoding, +initializes \exposid{what_} with \tcode{what}, +transcoded from UTF-8 to the ordinary literal encoding. +Otherwise, \exposid{what_} is value-initialized. +\end{itemdescr} + +\indexlibraryctor{exception}% +\begin{itemdecl} +consteval exception(string_view what, info from, + source_location where = source_location::current()) noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\constantwhen +\tcode{what} designates a sequence of characters +that can be encoded in UTF-8. + +\pnum +\effects +Initializes +\exposid{what_} with \tcode{what}, +\exposid{u8what_} with \tcode{what} +transcoded from the ordinary literal encoding to UTF-8, +%FIXME: Oxford comma before "and" +\exposid{from_} with \tcode{from} and +\exposid{where_} with \tcode{where}. +\end{itemdescr} + +\indexlibrarymember{what}{exception}% +\begin{itemdecl} +constexpr const char* what() const noexcept override; +\end{itemdecl} +\begin{itemdescr} +\pnum +\constantwhen +\tcode{\exposid{what_}.has_value()} is \tcode{true}. + +\pnum +\returns +\tcode{\exposid{what_}->c_str()}. +\end{itemdescr} + +\indexlibrarymember{u8what}{exception}% +\begin{itemdecl} +consteval u8string_view u8what() const noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\returns +\exposid{u8what_}. +\end{itemdescr} + +\indexlibrarymember{from}{exception}% +\begin{itemdecl} +consteval info from() const noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\returns +\exposid{from_}. +\end{itemdescr} + +\indexlibrarymember{where}{exception}% +\begin{itemdecl} +consteval source_location where() const noexcept; +\end{itemdecl} +\begin{itemdescr} +\pnum +\returns +\exposid{where_}. +\end{itemdescr} + +\rSec2[meta.reflection.operators]{Operator representations} + +\begin{itemdecl} +enum class @\libglobal{operators}@ { + @\seebelow@; +}; +using enum operators; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The enumeration type \tcode{operators} specifies +constants used to identify operators that can be overloaded, +with the meanings listed in~\tref{meta.reflection.operators}. +The values of the constants are distinct. +\end{itemdescr} + +%TODO: double-check if this is the right table environment for the job +%TODO: What is the best way to index these enum members? +\begin{floattable}{Enum class \tcode{operators}}{meta.reflection.operators} +{lcc} +\topline +\chdr{Constant} & +\chdr{Corresponding \grammarterm{operator-function-id}} & +\chdr{Operator symbol name} \\ \capsep +\tcode{op_new} & \tcode{operator new} & \tcode{new} \\ \rowsep +\tcode{op_delete} & \tcode{operator delete} & \tcode{delete} \\ \rowsep +\tcode{op_array_new} & \tcode{operator new[]} & \tcode{new[]} \\ \rowsep +\tcode{op_array_delete} & \tcode{operator delete[]} & \tcode{delete[]} \\ \rowsep +\tcode{op_co_await} & \tcode{operator co_await} & \tcode{co_await} \\ \rowsep +\tcode{op_parentheses} & \tcode{operator()} & \tcode{()} \\ \rowsep +\tcode{op_square_brackets} & \tcode{operator[]} & \tcode{[]} \\ \rowsep +\tcode{op_arrow} & \tcode{operator->} & \tcode{->} \\ \rowsep +\tcode{op_arrow_star} & \tcode{operator->*} & \tcode{->*} \\ \rowsep +\tcode{op_tilde} & \tcode{operator\~} & \tcode{\~} \\ \rowsep +\tcode{op_exclamation} & \tcode{operator!} & \tcode{!} \\ \rowsep +\tcode{op_plus} & \tcode{operator+} & \tcode{+} \\ \rowsep +\tcode{op_minus} & \tcode{operator-} & \tcode{-} \\ \rowsep +\tcode{op_star} & \tcode{operator*} & \tcode{*} \\ \rowsep +\tcode{op_slash} & \tcode{operator/} & \tcode{/} \\ \rowsep +\tcode{op_percent} & \tcode{operator\%} & \tcode{\%} \\ \rowsep +\tcode{op_caret} & \tcode{operator\caret} & \tcode{\caret} \\ \rowsep +\tcode{op_ampersand} & \tcode{operator\&} & \tcode{\&} \\ \rowsep +\tcode{op_equals} & \tcode{operator=} & \tcode{=} \\ \rowsep +\tcode{op_pipe} & \tcode{operator|} & \tcode{|} \\ \rowsep +\tcode{op_plus_equals} & \tcode{operator+=} & \tcode{+=} \\ \rowsep +\tcode{op_minus_equals} & \tcode{operator-=} & \tcode{-=} \\ \rowsep +\tcode{op_star_equals} & \tcode{operator*=} & \tcode{*=} \\ \rowsep +\tcode{op_slash_equals} & \tcode{operator/=} & \tcode{/=} \\ \rowsep +\tcode{op_percent_equals} & \tcode{operator\%=} & \tcode{\%=} \\ \rowsep +\tcode{op_caret_equals} & \tcode{operator\caret=} & \tcode{\caret=} \\ \rowsep +\tcode{op_ampersand_equals} & \tcode{operator\&=} & \tcode{\&=} \\ \rowsep +\tcode{op_pipe_equals} & \tcode{operator|=} & \tcode{|=} \\ \rowsep +\tcode{op_equals_equals} & \tcode{operator==} & \tcode{==} \\ \rowsep +\tcode{op_exclamation_equals} & \tcode{operator!=} & \tcode{!=} \\ \rowsep +\tcode{op_less} & \tcode{operator<} & \tcode{<} \\ \rowsep +\tcode{op_greater} & \tcode{operator>} & \tcode{>} \\ \rowsep +\tcode{op_less_equals} & \tcode{operator<=} & \tcode{<=} \\ \rowsep +\tcode{op_greater_equals} & \tcode{operator>=} & \tcode{>=} \\ \rowsep +\tcode{op_spaceship} & \tcode{operator<=>} & \tcode{<=>} \\ \rowsep +\tcode{op_ampersand_ampersand} & \tcode{operator\&\&} & \tcode{\&\&} \\ \rowsep +\tcode{op_pipe_pipe} & \tcode{operator||} & \tcode{||} \\ \rowsep +\tcode{op_less_less} & \tcode{operator<<} & \tcode{<<} \\ \rowsep +\tcode{op_greater_greater} & \tcode{operator>>} & \tcode{>>} \\ \rowsep +\tcode{op_less_less_equals} & \tcode{operator<<=} & \tcode{<<=} \\ \rowsep +\tcode{op_greater_greater_equals} & \tcode{operator>>=} & \tcode{>>=} \\ \rowsep +\tcode{op_plus_plus} & \tcode{operator++} & \tcode{++} \\ \rowsep +\tcode{op_minus_minus} & \tcode{operator--} & \tcode{--} \\ \rowsep +\tcode{op_comma} & \tcode{operator,} & \tcode{,} \\ +\end{floattable} + +\indexlibraryglobal{operator_of}% +\begin{itemdecl} +consteval operators operator_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The value of the enumerator from the \tcode{operators} +whose corresponding \grammarterm{operator-function-id} +is the unqualified name of the entity represented by \tcode{r}. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{r} represents an operator function or operator function template. +\end{itemdescr} + +\indexlibraryglobal{symbol_of}% +\indexlibraryglobal{u8symbol_of}% +\begin{itemdecl} +consteval string_view symbol_of(operators op); +consteval u8string_view u8symbol_of(operators op); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{string_view} or \tcode{u8string_view} +containing the characters of the operator symbol name corresponding to \tcode{op}, +respectively encoded with the ordinary literal encoding or with UTF-8. + +\pnum +\throws +\tcode{meta::exception} unless +the value of \tcode{op} corresponds to one of the enumerators in \tcode{operators}. +\end{itemdescr} + +\rSec2[meta.reflection.names]{Reflection names and locations} + +\indexlibraryglobal{has_identifier}% +\begin{itemdecl} +consteval bool has_identifier(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item + If \tcode{r} represents an entity + that has a typedef name for linkage purposes\iref{dcl.typedef}, + then \tcode{true}. +\item + Otherwise, if \tcode{r} represents an unnamed entity, + then \tcode{false}. +\item + Otherwise, if \tcode{r} represents a class type, + then \tcode{!has_template_arguments(r)}. +\item + Otherwise, if \tcode{r} represents a function, + then \tcode{true} if \tcode{has_template_arguments(r)} is \tcode{false} + and the function is not a + constructor, + destructor, + operator function, or + conversion function. + Otherwise, \tcode{false}. +\item + Otherwise, if \tcode{r} represents a template, + then \tcode{true} if \tcode{r} does not represent a + constructor template, + operator function template, + or conversion function template. + Otherwise, \tcode{false}. +\item + Otherwise, if \tcode{r} represents the $i^\text{th}$ parameter of a function $F$ + that is an (implicit or explicit) specialization of a templated function $T$ + and the $i^\text{th}$ parameter of the instantiated declaration of $T$ + whose template arguments are those of $F$ would be instantiated from a pack, + then \tcode{false}. +\item + Otherwise, if \tcode{r} represents the parameter $P$ of a function $F$, + then let $S$ be the set of declarations, + ignoring any explicit instantiations, + that precede some point in the evaluation context + and that declare either $F$ or a templated function + of which $F$ is a specialization; + \tcode{true} if + \begin{itemize} + \item + there is a declaration $D$ in $S$ that introduces a name $N$ for either $P$ + or the parameter corresponding to $P$ + in the templated function that $D$ declares and + \item + no declaration in $S$ does so using any name other than $N$. + \end{itemize} + Otherwise, \tcode{false}. + \begin{example} +\begin{codeblock} +void fun(int); +constexpr std::meta::info r = parameters_of(^^fun)[0]; +static_assert(!has_identifier(r)); + +void fun(int x); +static_assert(has_identifier(r)); + +void fun(int x); +static_assert(has_identifier(r)); + +void poison() { + void fun(int y); +} +static_assert(!has_identifier(r)); +\end{codeblock} + \end{example} +\item + Otherwise, if \tcode{r} represents a variable, + then \tcode{false} if the declaration of that variable + was instantiated from a function parameter pack. + Otherwise, \tcode{!has_template_arguments(r)}. +\item + Otherwise, if \tcode{r} represents a structured binding, + then \tcode{false} if the declaration of that structured binding + was instantiated from a structured binding pack. + Otherwise, \tcode{true}. +\item + Otherwise, if \tcode{r} represents a type alias, + then \tcode{!has_template_arguments(r)}. +\item + Otherwise, if \tcode{r} represents an + enumerator, + non-static-data member, + namespace, or + namespace alias, + then \tcode{true}. +\item + Otherwise, if \tcode{r} represents a direct base class relationship, + then \tcode{has_identifier(type_of(r))}. +\item + Otherwise, \tcode{r} represents a data member description + $(T, N, A, W, \mathit{NUA})$\iref{class.mem.general}; + \tcode{true} if $N$ is not $\bot$. + Otherwise, \tcode{false}. +\end{itemize} +\end{itemdescr} + +\indexlibraryglobal{identifier_of}% +\indexlibraryglobal{u8identifier_of}% +\begin{itemdecl} +consteval string_view identifier_of(info r); +consteval u8string_view u8identifier_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $E$ be UTF-8 for \tcode{u8identifier_of}, +and otherwise the ordinary literal encoding. + +\pnum +\returns +An \ntmbs{}, encoded with $E$, +determined as follows: +\begin{itemize} +\item + If \tcode{r} represents an entity with a typedef name for linkage purposes, + then that name. +\item + Otherwise, if \tcode{r} represents a literal operator or literal operator template, + then the \grammarterm{ud-suffix} of the operator or operator template. +\item + Otherwise, if \tcode{r} represents the parameter $P$ of a function $F$, + then let $S$ be the set of declarations, + ignoring any explicit instantiations, + that precede some point in the evaluation context + and that declare either $F$ + or a templated function of which $F$ is a specialization; + the name that was introduced by a declaration in $S$ + for the parameter corresponding to $P$. +\item + Otherwise, if \tcode{r} represents an entity, + then the identifier introduced by the declaration of that entity. +\item + Otherwise, if \tcode{r} represents a direct base class relationship, + then \tcode{identifier_of(type_of(r))} or \tcode{u8identifier_of(type_of(r))}, + respectively. +\item + Otherwise, \tcode{r} represents a data member description + $(T, N, A, W, NUA)$\iref{class.mem.general}; + a \tcode{string_view} or \tcode{u8string_view}, respectively, + containing the identifier \tcode{\placeholder{N}}. +\end{itemize} + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{has_identifier(r)} is \tcode{true} +and the identifier that would be returned (see above) +is representable by $E$. +\end{itemdescr} + +\indexlibraryglobal{display_string_of}% +\indexlibraryglobal{u8display_string_of}% +\begin{itemdecl} +consteval string_view display_string_of(info r); +consteval u8string_view u8display_string_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An +\impldef{the result of \tcode{display_string_of} and \tcode{u8display_string_of}} +\tcode{string_view} or \tcode{u8string_view}, respectively. + +\pnum +\recommended +Where possible, +implementations should return a string +suitable for identifying the represented construct. +\end{itemdescr} + +\indexlibraryglobal{source_location_of}% +\begin{itemdecl} +consteval source_location source_location_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \tcode{r} represents +a value, +a type other than a class type or an enumeration type, +the global namespace, or +a data member description, +then \tcode{source_location\{\}}. +Otherwise, an +\impldef{the value returned by \tcode{std::meta::source_location_of}} +\tcode{source_location} value. + +\pnum +\recommended +If \tcode{r} represents an entity with a definition +that is reachable from the evaluation context, +a value corresponding to a definition should be returned. +\end{itemdescr} + +\rSec2[meta.reflection.queries]{Reflection queries} + +\begin{itemdecl} +consteval bool @\exposid{has-type}@(info r); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a +value, +annotation, +object, +variable, +function whose type does not contain an undeduced placeholder type +and that is not a constructor or destructor, +enumerator, +non-static data member, +unnamed bit-field, +direct base class relationship, +data member description, or +function parameter. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{type_of}% +\begin{itemdecl} +consteval info type_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item + If \tcode{r} represents the $i^\text{th}$ parameter of a function $F$, + then the $i^\text{th}$ type + in the parameter-type-list of $F$\iref{dcl.fct}. +\item + Otherwise, if \tcode{r} represents a + value, + object, + variable, + function, + non-static data member, or + unnamed bit-field, + then the type of what is represented by \tcode{r}. +\item + Otherwise, if \tcode{r} represents an annotation, + then \tcode{type_of(constant_of(r))}. +\item + Otherwise, if \tcode{r} represents + an enumerator $N$ of an enumeration $E$, then: + \begin{itemize} + \item + If $E$ is defined by a declaration $D$ + that precedes a point $P$ in the evaluation context + and $P$ does not occur within an \grammarterm{enum-specifier} of $D$, + then a reflection of $E$. + \item + Otherwise, a reflection of the type of $N$ + prior to the closing brace of the \grammarterm{enum-specifier} + as specified in~\ref{dcl.enum}. + \end{itemize} +\item + Otherwise, if \tcode{r} represents + a direct base class relationship $(D, B)$, + then a reflection of $B$. +\item + Otherwise, for a data member description $(T, N, A, W, \mathit{NUA})$\iref{class.mem.general}, + a reflection of the type $T$. +\end{itemize} + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{\exposid{has-type}(r)} is \tcode{true}. +\end{itemdescr} + +\indexlibraryglobal{object_of}% +\begin{itemdecl} +consteval info object_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item + If \tcode{r} represents an object, + then \tcode{r}. +\item + Otherwise, if \tcode{r} represents a reference, + then a reflection of the object referred to by that reference. +\item + Otherwise, \tcode{r} represents a variable; + a reflection of the object declared by that variable. +\end{itemize} +\begin{example} +\begin{codeblock} +int x; +int& y = x; + +static_assert(^^x != ^^y); // OK, \tcode{r} and \tcode{y} are different variables so their + // reflections compare different +static_assert(object_of(^^x) == object_of(^^y)); // OK, because \tcode{y} is a reference + // to \tcode{x}, their underlying objects are the same +\end{codeblock} +\end{example} + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{r} is a reflection representing either +\begin{itemize} +\item + an object with static storage duration\iref{basic.stc.general}, or +\item + a variable that either declares or refers to such an object, + and if that variable is a reference $R$, then either + \begin{itemize} + \item + $R$ is usable in constant expressions\iref{expr.const}, or + \item + the lifetime of $R$ began within the core constant expression + currently under evaluation. + \end{itemize} +\end{itemize} +\end{itemdescr} + +\indexlibraryglobal{constant_of}% +\begin{itemdecl} +consteval info constant_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $R$ be a constant expression of type \tcode{info} +such that \tcode{$R$ == r} is \tcode{true}. +If \tcode{r} represents an annotation, +then let $C$ be its underlying constant. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +if constexpr (is_annotation(@$R$@)) { + return @$C$@; +} else { + return reflect_constant([: @$R$@ :]); +} +\end{codeblock} +\begin{example} +\begin{codeblock} +constexpr int x = 0; +constexpr int y = 0; + +static_assert(^^x != ^^y); // OK, \tcode{x} and \tcode{y} are different variables, + // so their reflections compare different +static_assert(constant_of(^^x) == + constant_of(^^y)); // OK, both \tcode{constant_of(x)} and + // \tcode{constant_of(\reflexpr{y})} represent the value \tcode{0} +static_assert(constant_of(^^x) == + reflect_constant(0)); // OK, likewise + +struct S { int m; }; +constexpr S s {42}; +static_assert(is_object(constant_of(^^s)) && + is_object(reflect_object(s))); +static_assert(constant_of(^^s) != // OK, template parameter object that is template-argument- + reflect_object(s)); // equivalent to \tcode{s} is a different object than \tcode{s} +static_assert(constant_of(^^s) == + constant_of(reflect_object(s))); // OK + +consteval info fn() { + constexpr int x = 42; + return ^^x; +} +constexpr info r = constant_of(fn()); // error: \tcode{x} is outside its lifetime +\end{codeblock} +\end{example} + +\pnum +\throws +\tcode{meta::exception} unless +either \tcode{r} represents an annotation or +\tcode{[: $R$ :]} is a valid +\grammarterm{splice-expression}\iref{expr.prim.splice}. +\end{itemdescr} + +\indexlibraryglobal{is_public}% +\indexlibraryglobal{is_protected}% +\indexlibraryglobal{is_private}% +\begin{itemdecl} +consteval bool is_public(info r); +consteval bool is_protected(info r); +consteval bool is_private(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents either +\begin{itemize} +\item + a class member or unnamed bit-field + that is public, protected, or private, respectively, or +\item + a direct base class relationship $(D, B)$ for which $B$ is, respectively, + a public, protected, or private base class of $D$. +\end{itemize} +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_virtual}% +\begin{itemdecl} +consteval bool is_virtual(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents either a virtual member function +or a direct base class relationship $(D, B)$ +for which $B$ is a virtual base class of $D$. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_pure_virtual}% +\indexlibraryglobal{is_override}% +\begin{itemdecl} +consteval bool is_pure_virtual(info r); +consteval bool is_override(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a member function that is pure virtual +or overrides another member function, respectively. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_final}% +\begin{itemdecl} +consteval bool is_final(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a final class or a final member function. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_deleted}% +\indexlibraryglobal{is_defaulted}% +\begin{itemdecl} +consteval bool is_deleted(info r); +consteval bool is_defaulted(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a function that is +a deleted function\iref{dcl.fct.def.delete} +or defaulted function\iref{dcl.fct.def.default}, respectively. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_user_provided}% +\indexlibraryglobal{is_user_declared}% +\begin{itemdecl} +consteval bool is_user_provided(info r); +consteval bool is_user_declared(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a function that is +user-provided or user-declared\iref{dcl.fct.def.default}, respectively. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_explicit}% +\begin{itemdecl} +consteval bool is_explicit(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a member function that is declared explicit. +Otherwise, \tcode{false}. +\begin{note} +If \tcode{r} represents a member function template that is declared explicit, +\tcode{is_explicit(r)} is still \tcode{false} +because in general, +such queries for templates cannot be answered. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{is_noexcept}% +\begin{itemdecl} +consteval bool is_noexcept(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a \tcode{noexcept} function type +or a function with a non-throwing exception specification\iref{except.spec}. +Otherwise, \tcode{false}. +\begin{note} +If \tcode{r} represents a function template that is declared \tcode{noexcept}, +\tcode{is_noexcept(r)} is still \tcode{false} +because in general, +such queries for templates cannot be answered. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{is_bit_field}% +\begin{itemdecl} +consteval bool is_bit_field(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a bit-field, +or if \tcode{r} represents a data member description +$(T, N, A, W, \mathit{NUA})$\iref{class.mem.general} +for which $W$ is not $\bot$. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_enumerator}% +\indexlibraryglobal{is_annotation}% +\begin{itemdecl} +consteval bool is_enumerator(info r); +consteval bool is_annotation(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents an enumerator or annotation, respectively. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_const}% +\indexlibraryglobal{is_volatile}% +\begin{itemdecl} +consteval bool is_const(info r); +consteval bool is_volatile(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $T$ be \tcode{type_of(r)} if \tcode{\exposid{has-type}(r)} is \tcode{true}. +Otherwise, let $T$ be \tcode{dealias(r)}. + +\pnum +\returns +\tcode{true} if \tcode{T} represents a const or volatile type, respectively, +or a const- or volatile-qualified function type, respectively. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_mutable_member}% +\begin{itemdecl} +consteval bool is_mutable_member(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a \tcode{mutable} non-static data member. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_lvalue_reference_qualified}% +\indexlibraryglobal{is_rvalue_reference_qualified}% +\begin{itemdecl} +consteval bool is_lvalue_reference_qualified(info r); +consteval bool is_rvalue_reference_qualified(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $T$ be \tcode{type_of(r)} if \tcode{\exposid{has-type}(r)} is \tcode{true}. +Otherwise, let $T$ be \tcode{dealias(r)}. + +\pnum +\returns +\tcode{true} if $T$ represents an +lvalue- or rvalue-qualified function type, respectively. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{has_static_storage_duration}% +\indexlibraryglobal{has_thread_storage_duration}% +\indexlibraryglobal{has_automatic_storage_duration}% +\begin{itemdecl} +consteval bool has_static_storage_duration(info r); +consteval bool has_thread_storage_duration(info r); +consteval bool has_automatic_storage_duration(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents an object or variable that has +static, thread, or automatic storage duration, respectively\iref{basic.stc}. +Otherwise, \tcode{false}. +\begin{note} +It is not possible to have a reflection +representing an object or variable having dynamic storage duration. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{has_internal_linkage}% +\indexlibraryglobal{has_module_linkage}% +\indexlibraryglobal{has_external_linkage}% +\indexlibraryglobal{has_c_language_linkage}% +\indexlibraryglobal{has_linkage}% +\begin{itemdecl} +consteval bool has_internal_linkage(info r); +consteval bool has_module_linkage(info r); +consteval bool has_external_linkage(info r); +consteval bool has_c_language_linkage(info r); +consteval bool has_linkage(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a +variable, +function, +type, +template, or +namespace +whose name has +internal linkage, +module linkage, +C language linkage, or +any linkage, respectively\iref{basic.link}. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_complete_type}% +\begin{itemdecl} +consteval bool is_complete_type(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{is_type(r)} is \tcode{true} +and there is some point in the evaluation context +from which the type represented by \tcode{dealias(r)} +is not an incomplete type\iref{basic.types}. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_enumerable_type}% +\begin{itemdecl} +consteval bool is_enumerable_type(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +A type $T$ is \term{enumerable} from a point $P$ if either +\begin{itemize} +\item + $T$ is a class type complete at point $P$ or +\item + $T$ is an enumeration type defined by a declaration $D$ + such that $D$ is reachable from $P$ + but $P$ does not occur within an \grammarterm{enum-specifier} of $D$\iref{dcl.enum}. +\end{itemize} + +\pnum +\returns +\tcode{true} if \tcode{dealias(r)} represents a type that is enumerable +from some point in the evaluation context. +Otherwise, \tcode{false}. +\begin{example} +\begin{codeblock} +class S; +enum class E; +static_assert(!is_enumerable_type(^^S)); +static_assert(!is_enumerable_type(^^E)); + +class S { + void mfn() { + static_assert(is_enumerable_type(^^S)); + } + static_assert(!is_enumerable_type(^^S)); +}; +static_assert(is_enumerable_type(^^S)); + +enum class E { + A = is_enumerable_type(^^E) ? 1 : 2 +}; +static_assert(is_enumerable_type(^^E)); +static_assert(static_cast(E::A) == 2); +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{is_variable}% +\begin{itemdecl} +consteval bool is_variable(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a variable. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_type}% +\indexlibraryglobal{is_namespace}% +\begin{itemdecl} +consteval bool is_type(info r); +consteval bool is_namespace(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents an entity +whose underlying entity is a type or namespace, respectively. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_type_alias}% +\indexlibraryglobal{is_namespace_alias}% +\begin{itemdecl} +consteval bool is_type_alias(info r); +consteval bool is_namespace_alias(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a type alias or namespace alias, respectively. +Otherwise, \tcode{false}. +\begin{note} +A specialization of an alias template is a type alias. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{is_function}% +\begin{itemdecl} +consteval bool is_function(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a function. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_conversion_function}% +\indexlibraryglobal{is_operator_function}% +\indexlibraryglobal{is_literal_operator}% +\begin{itemdecl} +consteval bool is_conversion_function(info r); +consteval bool is_operator_function(info r); +consteval bool is_literal_operator(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a function that is a +conversion function\iref{class.conv.fct}, +operator function\iref{over.oper}, or +literal operator\iref{over.literal}, respectively. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_special_member_function}% +\indexlibraryglobal{is_constructor}% +\indexlibraryglobal{is_default_constructor}% +\indexlibraryglobal{is_copy_constructor}% +\indexlibraryglobal{is_move_constructor}% +\indexlibraryglobal{is_assignment}% +\indexlibraryglobal{is_copy_assignment}% +\indexlibraryglobal{is_move_assignment}% +\indexlibraryglobal{is_destructor}% +\begin{itemdecl} +consteval bool is_special_member_function(info r); +consteval bool is_constructor(info r); +consteval bool is_default_constructor(info r); +consteval bool is_copy_constructor(info r); +consteval bool is_move_constructor(info r); +consteval bool is_assignment(info r); +consteval bool is_copy_assignment(info r); +consteval bool is_move_assignment(info r); +consteval bool is_destructor(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a function that is a +special member function\iref{special}, +a constructor, +a default constructor, +a copy constructor, +a move constructor, +an assignment operator, +a copy assignment operator, +a move assignment operator, or +a destructor, respectively. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_function_parameter}% +\begin{itemdecl} +consteval bool is_function_parameter(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a function parameter. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_explicit_object_parameter}% +\begin{itemdecl} +consteval bool is_explicit_object_parameter(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a function parameter +that is an explicit object parameter\iref{dcl.fct}. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{has_default_argument}% +\begin{itemdecl} +consteval bool has_default_argument(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \tcode{r} represents a parameter $P$ of a function $F$, then: +\begin{itemize} +\item + If $F$ is a specialization of a templated function $T$, + then \tcode{true} if there exists a declaration $D$ of $T$ + that precedes some point in the evaluation context + and $D$ specifies a default argument + for the parameter of $T$ corresponding to $P$. + Otherwise, \tcode{false}. +\item + Otherwise, if there exists a declaration $D$ of $F$ + that precedes some point in the evaluation context + and $D$ specifies a default argument for $P$, + then \tcode{true}. +\end{itemize} +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{has_ellipsis_parameter}% +\begin{itemdecl} +consteval bool has_ellipsis_parameter(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a function or function type +that has an ellipsis in its parameter-type-list\iref{dcl.fct}. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_template}% +\begin{itemdecl} +consteval bool is_template(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a +function template, +class template, +variable template, +alias template, or +concept. +Otherwise, \tcode{false}. + +\pnum +\begin{note} +A template specialization is not a template. +For example, +\tcode{is_template(\brk{}\reflexpr{std::vector})} is \tcode{true} +but \tcode{is_template(\brk{}\reflexpr{std::vector})} is \tcode{false}. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{is_function_template}% +\indexlibraryglobal{is_variable_template}% +\indexlibraryglobal{is_class_template}% +\indexlibraryglobal{is_alias_template}% +\indexlibraryglobal{is_conversion_function_template}% +\indexlibraryglobal{is_operator_function_template}% +\indexlibraryglobal{is_literal_operator_template}% +\indexlibraryglobal{is_constructor_template}% +\indexlibraryglobal{is_concept}% +\begin{itemdecl} +consteval bool is_function_template(info r); +consteval bool is_variable_template(info r); +consteval bool is_class_template(info r); +consteval bool is_alias_template(info r); +consteval bool is_conversion_function_template(info r); +consteval bool is_operator_function_template(info r); +consteval bool is_literal_operator_template(info r); +consteval bool is_constructor_template(info r); +consteval bool is_concept(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a +function template, +variable template, +class template, +alias template, +conversion function template, +operator function template, +literal operator template, +constructor template, or +concept, respectively. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_value}% +\indexlibraryglobal{is_object}% +\begin{itemdecl} +consteval bool is_value(info r); +consteval bool is_object(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a value or object, respectively. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_structured_binding}% +\begin{itemdecl} +consteval bool is_structured_binding(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a structured binding. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{is_class_member}% +\indexlibraryglobal{is_namespace_member}% +\indexlibraryglobal{is_nonstatic_data_member}% +\indexlibraryglobal{is_static_member}% +\indexlibraryglobal{is_base}% +\begin{itemdecl} +consteval bool is_class_member(info r); +consteval bool is_namespace_member(info r); +consteval bool is_nonstatic_data_member(info r); +consteval bool is_static_member(info r); +consteval bool is_base(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a +class member, +namespace member, +non-static data member, +static member, or +direct base class relationship, respectively. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{has_default_member_initializer}% +\begin{itemdecl} +consteval bool has_default_member_initializer(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a non-static data member +that has a default member initializer. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{has_parent}% +\begin{itemdecl} +consteval bool has_parent(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item + If \tcode{r} represents the global namespace, + then \tcode{false}. +\item + Otherwise, if \tcode{r} represents an entity that has C language linkage\iref{dcl.link}, + then \tcode{false}. +\item + Otherwise, if \tcode{r} represents an entity that has a + language linkage other than \Cpp{} language linkage, + then an + \impldef{the result of \tcode{std::meta::has_parent} for entities + with neither C nor \Cpp{} language linkage} + value. +\item + Otherwise, if \tcode{r} represents a type that is neither a class nor enumeration type, + then \tcode{false}. +\item + Otherwise, if \tcode{r} represents an entity or direct base class relationship, + then \tcode{true}. +\item + Otherwise, \tcode{false}. +\end{itemize} +\end{itemdescr} + +\indexlibraryglobal{parent_of}% +\begin{itemdecl} +consteval info parent_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item + If \tcode{r} represents a non-static data member + that is a direct member of an anonymous union, + or an unnamed bit-field declared + within the \grammarterm{member-specification} of such a union, + then a reflection representing the innermost enclosing anonymous union. +\item + Otherwise, if \tcode{r} represents an enumerator, + then a reflection representing the corresponding enumeration type. +\item + Otherwise, if \tcode{r} represents a direct base class relationship $(D, B)$, + then a reflection representing $D$. +\item + Otherwise, let $E$ be a class, function, or namespace + whose class scope, function parameter scope, or namespace scope, respectively, + is the innermost such scope that either is, or encloses, + the target scope of a declaration of what is represented by \tcode{r}. + \begin{itemize} + \item + If $E$ is the function call operator of a closure type + for a \grammarterm{consteval-block-declaration}\iref{dcl.pre}, + then \tcode{parent_of(\brk{}parent_of(\reflexpr{$E$}))}. + \begin{note} + In this case, + the first \tcode{parent_of} will be the closure type, + so the second \tcode{parent_of} is necessary + to give the parent of that closure type. + \end{note} + \item + Otherwise, \tcode{\reflexpr{$E$}}. + \end{itemize} +\end{itemize} +\begin{example} +\begin{codeblock} +struct I { }; + +struct F : I { + union { + int o; + }; + + enum N { + A + }; +}; + +constexpr auto ctx = std::meta::access_context::current(); + +static_assert(parent_of(^^F) == ^^::); +static_assert(parent_of(bases_of(^^F, ctx)[0]) == ^^F); +static_assert(is_union_type(parent_of(^^F::o))); +static_assert(parent_of(^^F::N) == ^^F); +static_assert(parent_of(^^F::A) == ^^F::N); +\end{codeblock} +\end{example} + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{has_parent(r)} is \tcode{true}. +\end{itemdescr} + +\indexlibraryglobal{dealias}% +\begin{itemdecl} +consteval info dealias(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A reflection representing the underlying entity of what \tcode{r} represents. +\begin{example} +\begin{codeblock} +using X = int; +using Y = X; +static_assert(dealias(^^int) == ^^int); +static_assert(dealias(^^X) == ^^int); +static_assert(dealias(^^Y) == ^^int); +\end{codeblock} +\end{example} + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{r} represents an entity. +\end{itemdescr} + +\indexlibraryglobal{has_template_arguments}% +\begin{itemdecl} +consteval bool has_template_arguments(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a specialization of a +function template, +variable template, +class template, or +an alias template. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{template_of}% +\begin{itemdecl} +consteval info template_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A reflection of the template of the specialization represented by \tcode{r}. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{has_template_arguments(r)} is \tcode{true}. +\end{itemdescr} + +\indexlibraryglobal{template_arguments_of}% +\begin{itemdecl} +consteval vector template_arguments_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{vector} containing reflections +of the template arguments +of the template specialization represented by \tcode{r}, +in the order in which they appear in the corresponding template argument list. +For a given template argument $A$, +its corresponding reflection $R$ is determined as follows: +\begin{itemize} +\item + If $A$ denotes a type or type alias, + then $R$ is a reflection representing the underlying entity of $A$. + \begin{note} + $R$ always represents a type, never a type alias. + \end{note} +\item + Otherwise, if $A$ denotes a + class template, + variable template, + concept, or + alias template, + then $R$ is a reflection representing $A$. +\item + Otherwise, $A$ is a constant template argument\iref{temp.arg.nontype}. + Let $P$ be the corresponding template parameter. + \begin{itemize} + \item + If $P$ has reference type, + then $R$ is a reflection + representing the object or function referred to by $A$. + \item + Otherwise, if $P$ has class type, + then $R$ represents the corresponding template parameter object. + \item + Otherwise, $R$ is a reflection representing the value of $A$. + \end{itemize} +\end{itemize} +\begin{example} +\begin{codeblock} +template struct Pair { }; +template struct Pair { }; +template using PairPtr = Pair; + +static_assert(template_of(^^Pair) == ^^Pair); +static_assert(template_of(^^Pair) == ^^Pair); +static_assert(template_arguments_of(^^Pair).size() == 2); +static_assert(template_arguments_of(^^Pair)[0] == ^^int); + +static_assert(template_of(^^PairPtr) == ^^PairPtr); +static_assert(template_arguments_of(^^PairPtr).size() == 1); + +struct S { }; +int i; +template class> + struct X { }; +constexpr auto T = ^^X<1, i, S{}, PairPtr>; +static_assert(is_value(template_arguments_of(T)[0])); +static_assert(is_object(template_arguments_of(T)[1])); +static_assert(is_object(template_arguments_of(T)[2])); +static_assert(template_arguments_of(T)[3] == ^^PairPtr); +\end{codeblock} +\end{example} + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{has_template_arguments(r)} is \tcode{true}. +\end{itemdescr} + +\indexlibraryglobal{parameters_of}% +\begin{itemdecl} +consteval vector parameters_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item + If \tcode{r} represents a function $F$, + then a \tcode{vector} containing reflections of the parameters of $F$, + in the order in which they appear in a declaration of $F$. +\item + Otherwise, \tcode{r} represents a function type $T$; + a \tcode{vector} containing reflections of the types + in parameter-type-list\iref{dcl.fct} of $T$, + in the order in which they appear in the parameter-type-list. +\end{itemize} + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{r} represents a function or a function type. +\end{itemdescr} + +\indexlibraryglobal{variable_of}% +\begin{itemdecl} +consteval info variable_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The reflection of the parameter variable corresponding to \tcode{r}. + +\pnum +\throws +\tcode{meta::exception} unless +\begin{itemize} +\item + \tcode{r} represents a parameter of a function $F$ and +\item + there is a point $P$ in the evaluation context + for which the innermost non-block scope enclosing $P$ + is the function parameter scope\iref{basic.scope.param} + associated with $F$. +\end{itemize} +\end{itemdescr} + +\indexlibraryglobal{return_type_of}% +\begin{itemdecl} +consteval info return_type_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The reflection of the return type +of the function or function type represented by \tcode{r}. + +\pnum +\throws +\tcode{meta::exception} unless +either \tcode{r} represents a function +and \tcode{\exposid{has-type}(r)} is \tcode{true} +or \tcode{r} represents a function type. +\end{itemdescr} + +\rSec2[meta.reflection.access.context]{Access control context} + +\pnum +The \tcode{access_context} class is a non-aggregate type +that represents a namespace, class, or function +from which queries pertaining to access rules may be performed, +as well as the designating class\iref{class.access.base}, if any. + +\indexlibraryglobal{access_context}% +\pnum +An \tcode{access_context} has an associated scope and designating class. + +\indexlibraryglobal{access_context}% +\begin{codeblock} +namespace std::meta { + struct access_context { + access_context() = delete; + + consteval info scope() const; + consteval info designating_class() const; + + static consteval access_context current() noexcept; + static consteval access_context unprivileged() noexcept; + static consteval access_context unchecked() noexcept; + consteval access_context via(info cls) const; + }; +} +\end{codeblock} + +\pnum +\tcode{access_context} is a structural type. +Two values \tcode{ac1} and \tcode{ac2} of type \tcode{access_context} +are template-argument-equivalent\iref{temp.type} +if \tcode{ac1.scope()} and \tcode{ac2.scope()} +are template-argument-equivalent +and \tcode{ac1.desig\-nating_class()} and \tcode{ac2.desig\-nating_class()} +are template-argument-equivalent. + +\begin{itemdecl} +consteval info @\libmember{scope}{access_context}@() const; +consteval info @\libmember{designating_class}{access_context}@() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The \tcode{access_context}'s associated scope +and designating class, respectively. +\end{itemdescr} + +\begin{itemdecl} +static consteval access_context @\libmember{current}{access_context}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Given a program point $P$, +let \tcode{\exposid{eval-point}($P$)} be the following program point: +\begin{itemize} +\item + If a potentially-evaluated subexpression\iref{intro.execution} + of a default member initializer $I$ + for a member of class $C$\iref{class.mem.general} + appears at $P$, + then a point determined as follows: + \begin{itemize} + \item + If an aggregate initialization is using $I$, + \tcode{\exposid{eval-point}($Q$)}, + where $Q$ is the point at which that aggregate initialization appears. + \item + Otherwise, if an initialization + by an inherited constructor\iref{class.inhctor.init} is using $I$, + a point whose immediate scope is the class scope corresponding to $C$. + \item + Otherwise, a point whose immediate scope + is the function parameter scope + corresponding to the constructor definition that is using $I$. + \end{itemize} + \item + Otherwise, if a potentially-evaluated subexpression + of a default argument\iref{dcl.fct.default} appears at $P$, + \tcode{\exposid{eval-point}($Q$)}, + where $Q$ is the point at which the invocation of the function\iref{expr.call} + using that default argument appears. + \item + Otherwise, if the immediate scope of $P$ + is a function parameter scope introduced by a declaration $D$, + and $P$ appears either before the locus of $D$ + or within the trailing \grammarterm{requires-clause} of $D$, + a point whose immediate scope is the innermost scope enclosing the locus of $D$ + that is not a template parameter scope. + \item + Otherwise, if the immediate scope of $P$ + is a function parameter scope + introduced by a \grammarterm{lambda-expression} $L$ + whose \grammarterm{lambda-introducer} appears at point $Q$, + and $P$ appears either within the \grammarterm{trailing-return-type} + or the trailing \grammarterm{requires-clause} of $L$, + \tcode{\exposid{eval-point}($Q$)}. + \item + Otherwise, if the innermost non-block scope enclosing $P$ + is the function parameter scope + introduced by a \grammarterm{consteval-block-declaration}\iref{dcl.pre}, + a point whose immediate scope is that inhabited + by the outermost \grammarterm{consteval-block-declaration} $D$ + containing $P$ such that each scope (if any) that intervenes between $P$ + and the function parameter scope introduced by $D$ is either + \begin{itemize} + \item + a block scope or + \item + a function parameter scope or lambda scope + introduced by a \grammarterm{consteval-block-declaration}. + \end{itemize} + \item + Otherwise, $P$. +\end{itemize} + +\pnum +Given a scope $S$, +let \tcode{\exposid{ctx-scope}($S$)} be the following scope: +\begin{itemize} +\item + If $S$ is a class scope or namespace scope, + $S$. +\item + Otherwise, if $S$ is a function parameter scope + introduced by the declaration of a function, + $S$. +\item + Otherwise, if $S$ is a lambda scope + introduced by a \grammarterm{lambda-expression} $L$, + the function parameter scope + corresponding to the call operator of the closure type of $L$. +\item + Otherwise, \tcode{\exposid{ctx-scope}($S'$)}, + where $S'$ is the parent scope of $S$. +\end{itemize} + +\pnum +\returns +An \tcode{access_context} whose designating class is the null reflection +and whose scope represents the function, class, or namespace +whose corresponding function parameter scope, class scope, or namespace scope, respectively, +is \tcode{\exposid{ctx-scope}($S$)}, +where $S$ is the immediate scope of \tcode{\exposid{eval-point}($P$)} +and $P$ is the point at which the invocation of \tcode{current} lexically appears. +\begin{example} +\begin{codeblock} +struct A { + int a = 0; + consteval A(int p) : a(p) {} +}; +struct B : A { + using A::A; + consteval B(int p, int q) : A(p * q) {} + info s = access_context::current().scope(); +}; +struct C : B { using B::B; }; + +struct Agg { + consteval bool eq(info rhs = access_context::current().scope()) { + return s == rhs; + } + info s = access_context::current().scope(); +}; + +namespace NS { + static_assert(Agg{}.s == access_context::current().scope()); // OK + static_assert(Agg{}.eq()); // OK + static_assert(B(1).s == ^^B); // OK + static_assert(is_constructor(B{1, 2}.s) && parent_of(B{1, 2}.s) == ^^B); // OK + static_assert(is_constructor(C{1, 2}.s) && parent_of(C{1, 2}.s) == ^^B); // OK + + auto fn() -> [:is_namespace(access_context::current().scope()) ? ^^int : ^^bool:]; + static_assert(type_of(^^fn) == ^^auto()->int); // OK + + template + struct TCls { + consteval bool fn() + requires (is_type(access_context::current().scope())) { + return true; // OK, scope is \tcode{TCls}. + } + }; + static_assert(TCls<0>{}.fn()); // OK +} +\end{codeblock} +\end{example} + +\pnum +\remarks +\tcode{current} is not an addressable function\iref{namespace.std}. +An invocation of \tcode{current} that appears at a program point $P$ +is value-dependent\iref{temp.dep.constexpr} +if \tcode{\exposid{eval-point}\brk{}(\brk{}$P$)} is enclosed by a scope +corresponding to a templated entity. +\end{itemdescr} + +\begin{itemdecl} +static consteval access_context @\libmember{unprivileged}{access_context}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An \tcode{access_context} whose designating class is the null reflection +and whose scope is the global namespace. +\end{itemdescr} + +\begin{itemdecl} +static consteval access_context @\libmember{unchecked}{access_context}@() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An \tcode{access_context} whose designating class and scope +are both the null reflection. +\end{itemdescr} + +\begin{itemdecl} +static consteval access_context @\libmember{via}{access_context}@(info cls) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An \tcode{access_context} whose scope is \tcode{this->scope()} +and whose designating class is \tcode{cls}. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{cls} is either the null reflection +or a reflection of a complete class type. +\end{itemdescr} + +\rSec2[meta.reflection.access.queries]{Member accessibility queries} + +\indexlibraryglobal{is_accessible}% +\begin{itemdecl} +consteval bool is_accessible(info r, access_context ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{\exposid{PARENT-CLS}(r)} be: +\begin{itemize} +\item If \tcode{parent_of(r)} represents a class $C$, then $C$. +\item Otherwise, \tcode{\exposid{PARENT-CLS}(parent_of(r))}. +\end{itemize} + +\pnum +Let \tcode{\exposid{DESIGNATING-CLS}(r, ctx)} be: +\begin{itemize} +\item If \tcode{ctx.designating_class()} represents a class $C$, then $C$. +\item Otherwise, \tcode{\exposid{PARENT-CLS}(r)}. +\end{itemize} + +\pnum +\returns +\begin{itemize} +\item + If \tcode{r} represents an unnamed bit-field $F$, + then \tcode{is_accessible($\tcode{r}_H$, ctx)}, + where $\tcode{r}_H$ represents a hypothetical non-static data member + of the class represented by \tcode{\exposid{PARENT-CLS}(r)} + with the same access as $F$. + \begin{note} + Unnamed bit-fields are treated as class members + for the purpose of \tcode{is_accessible}. + \end{note} +\item + Otherwise, if \tcode{r} does not represent a class member + or a direct base class relationship, + then \tcode{true}. +\item + Otherwise, if \tcode{r} represents + \begin{itemize} + \item + a class member that is not a (possibly indirect or variant) + member of \tcode{\exposid{DESIG\-NATING-CLS}(\brk{}r, ctx)} or + \item + a direct base class relationship such that \tcode{parent_of(r)} + does not represent \tcode{\exposid{DESIG\-NATING-CLS}(\brk{}r, ctx)} + or a (direct or indirect) base class thereof, + \end{itemize} + then \tcode{false}. +\item + Otherwise, if \tcode{ctx.scope()} is the null reflection, + then \tcode{true}. +\item + Otherwise, letting $P$ be a program point whose immediate scope is the + function parameter scope, class scope, or namespace scope + corresponding to the + function, class, or namespace + represented by \tcode{ctx.scope()}: + \begin{itemize} + \item + If \tcode{r} represents a direct base class relationship $(D, B)$, + then \tcode{true} if base class $B$ of \tcode{\exposid{DESIG\-NATING-CLS}(\brk{}r, ctx)} + is accessible at $P$\iref{class.access.base}; + otherwise \tcode{false}. + \item + Otherwise, \tcode{r} represents a class member $M$; + \tcode{true} if $M$ would be accessible at $P$ + with the designating class\iref{class.access.base} as \tcode{\exposid{DESIG\-NATING-CLS}(r, ctx)} + if the effect of any \grammarterm{using-declaration}s\iref{namespace.udecl} were ignored. + Otherwise, \tcode{false}. + \end{itemize} +\end{itemize} +\begin{note} +The definitions of when a class member or base class is accessible from a point $P$ +do not consider whether a declaration of that entity is reachable from $P$. +\end{note} +\begin{example} +\begin{codeblock} +consteval access_context fn() { + return access_context::current(); +} + +class Cls { + int mem; + friend consteval access_context fn(); +public: + static constexpr auto r = ^^mem; +}; + +static_assert(is_accessible(Cls::r, fn())); // OK +static_assert(!is_accessible(Cls::r, access_context::current())); // OK +static_assert(is_accessible(Cls::r, access_context::unchecked())); // OK +\end{codeblock} +\end{example} + +\pnum +\throws +\tcode{meta::exception} if +\begin{itemize} +\item + \tcode{r} represents a class member + for which \tcode{\exposid{PARENT-CLS}(r)} is an incomplete class or +\item + \tcode{r} represents a direct base class relationship $(D, B)$ + for which $D$ is incomplete. +\end{itemize} +\end{itemdescr} + +\indexlibraryglobal{has_inaccessible_nonstatic_data_members}% +\begin{itemdecl} +consteval bool has_inaccessible_nonstatic_data_members(info r, access_context ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{is_accessible($R$, ctx)} is \tcode{false} +for any $R$ in \tcode{nonstatic_data_members_of(\brk{}r, access_context\brk{}::unchecked())}. +Otherwise, \tcode{false}. + +\pnum +\throws +\tcode{meta::exception} unless +\begin{itemize} +\item + \tcode{nonstatic_data_members_of(\brk{}r, access_context::\brk{}unchecked())} + is a constant subexpression and +\item + \tcode{r} does not represent a closure type. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +consteval bool has_inaccessible_bases(info r, access_context ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{is_accessible($R$, ctx)} is \tcode{false} +for any $R$ in \tcode{bases_of(\brk{}r, access_context::\brk{}unchecked())}. +Otherwise, \tcode{false}. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{bases_of(r, access_context::unchecked())} +is a constant subexpression. +\end{itemdescr} + +\indexlibraryglobal{has_inaccessible_subobjects}% +\begin{itemdecl} +consteval bool has_inaccessible_subobjects(info r, access_context ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return has_inaccessible_bases(r, ctx) || has_inaccessible_nonstatic_data_members(r, ctx); +\end{codeblock} +\end{itemdescr} + +\rSec2[meta.reflection.member.queries]{Reflection member queries} + +\indexlibraryglobal{members_of}% +\begin{itemdecl} +consteval vector members_of(info r, access_context ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +A declaration $D$ \term{members-of-precedes} a point $P$ +if $D$ precedes either $P$ +or the point immediately following the \grammarterm{class-specifier} +of the outermost class for which $P$ is in a complete-class context. + +\pnum +A declaration $D$ of a member $M$ of a class or namespace $Q$ is +\term{$Q$-members-of-eligible} if +\begin{itemize} +\item + the host scope of $D$\iref{basic.scope.scope} + is the class scope or namespace scope associated with $Q$, +\item + $D$ is not a friend declaration, +\item + $M$ is not a closure type\iref{expr.prim.lambda.closure}, +\item + $M$ is not a specialization of a template\iref{temp.pre}, +\item + if $Q$ is a class that is not a closure type, + then $M$ is a direct member of $Q$\iref{class.mem.general} + that is not a variant member of a + nested anonymous union of $Q$\iref{class.union.anon}, and +\item + if $Q$ is a closure type, + then $M$ is a function call operator or function call operator template. +\end{itemize} +It is \impldef{whether declarations of some members of a closure type $Q$ +are $Q$-members-of-eligible} +whether declarations of other members of a closure type $Q$ +are $Q$-members-of-eligible. + +\pnum +A member $M$ of a class or namespace $Q$ is +\term{$Q$-members-of-representable} from a point $P$ +if a $Q$-members-of-eligible declaration of $M$ members-of-precedes $P$, +and $M$ is +\begin{itemize} +\item + a class or enumeration type +\item + a type alias +\item + a class template, function template, + variable template, alias template, or concept, +\item + a variable or reference $V$ + for which the type of $V$ does not contain an undeduced placeholder type, +\item + a function $F$ for which + \begin{itemize} + \item + the type of $F$ does not contain an undeduced placeholder type, + \item + the constraints (if any) of $F$ are satisfied, and + \item + if $F$ is a prospective destructor, + $F$ is the selected destructor\iref{class.dtor}, + \end{itemize} +\item + a non-static data member, +\item + a namespace, or +\item + a namespace alias. +\end{itemize} +\begin{note} +Examples of direct members that are not $Q$-members-of-representable +for any entity $Q$ include: +unscoped enumerators\iref{enum}, +partial specializations of templates\iref{temp.spec.partial}, and +closure types\iref{expr.prim.lambda.closure}. +\end{note} + +\pnum +\returns +A \tcode{vector} containing reflections of all members $M$ +of the entity $Q$ represented by \tcode{dealias(r)} for which +\begin{itemize} +\item + $M$ is $Q$-members-of-representable + from some point in the evaluation context and +\item + \tcode{is_accessible(\reflexpr{$M$}, ctx)} is \tcode{true}. +\end{itemize} +If \tcode{dealias(r)} represents a class $C$, +then the \tcode{vector} also contains reflections +representing all unnamed bit-fields $B$ +whose declarations inhabit the class scope corresponding to $C$ +for which \tcode{is_accessible(\reflexpr{$B$}, ctx)} is \tcode{true}. +Reflections of class members and unnamed bit-fields that are declared +appear in the order in which they are declared. +\begin{note} +Base classes are not members. +Implicitly-declared special members +appear after any user-declared members\iref{special}. +\end{note} +\begin{example} +\begin{codeblock} +// TU1 +export module M; +namespace NS { + export int m; + static int l; +} +static_assert(members_of(^^NS, access_context::current()).size() == 2); + +// TU2 +import M; + +static_assert( // \tcode{NS::l} does not precede + members_of(^^NS, access_context::current()).size() == 1); // the constant-expression\iref{basic.lookup} + +class B {}; + +struct S : B { +private: + class I; +public: + int m; +}; + +static_assert( // 6 special members, + members_of(^^S, access_context::current()).size() == 7); // 1 public member, + // does not include base + +static_assert( // all of the above, + members_of(^^S, access_context::unchecked()).size() == 8); // as well as a reflection + // representing \tcode{S::I} +\end{codeblock} +\end{example} + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{dealias(r)} is a reflection representing either +a class type that is complete from some point in the evaluation context +or a namespace. +\end{itemdescr} + +\indexlibraryglobal{bases_of}% +\begin{itemdecl} +consteval vector bases_of(info type, access_context ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +Let $C$ be the class represented by \tcode{dealias(type)}. +A \tcode{vector} containing the reflections +of all the direct base class relationships of $B$, if any, +of $C$ such that \tcode{is_accessible(\brk{}\reflexpr{$B$}, ctx)} is \tcode{true}. +The direct base class relationships appear in the order in which +the corresponding base classes appear in the \grammarterm{base-specifier-list} of $C$. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{dealias(type)} represents a class type +that is complete from some point in the evaluation context. +\end{itemdescr} + +\indexlibraryglobal{static_data_members_of}% +\begin{itemdecl} +consteval vector static_data_members_of(info type, access_context ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{vector} containing each element \tcode{e} of \tcode{members_of(type, ctx)} +such that \tcode{is_variable(e)} is \tcode{true}, +preserving their order. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{dealias(type)} represents a class type +that is complete from some point in the evaluation context. +\end{itemdescr} + + +\indexlibraryglobal{nonstatic_data_members_of}% +\begin{itemdecl} +consteval vector nonstatic_data_members_of(info type, access_context ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{vector} containing each element \tcode{e} of \tcode{members_of(type, ctx)} +such that \tcode{is_nonstatic_data_member(e)} is \tcode{true}, +preserving their order. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{dealias(type)} represents a class type +that is complete from some point in the evaluation context. +\end{itemdescr} + +\indexlibraryglobal{subobjects_of}% +\begin{itemdecl} +consteval vector subobjects_of(info type, access_context ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{vector} containing each element of \tcode{bases_of(type, ctx)} +followed by each element of \tcode{non\-static_data_mem\-bers_of(\brk{}type,\brk{} ctx)}, +preserving their order. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{dealias(type)} represents a class type +that is complete from some point in the evaluation context. +\end{itemdescr} + +\indexlibraryglobal{enumerators_of}% +\begin{itemdecl} +consteval vector enumerators_of(info type_enum); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{vector} containing the reflections of each enumerator +of the enumeration represented by \tcode{dealias(type_enum)}, +in the order in which they are declared. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{dealias(type_enum)} represents an enumeration type, +and \tcode{is_enumerable_type(\brk{}type_enum)} is \tcode{true}. +\end{itemdescr} + +\rSec2[meta.reflection.layout]{Reflection layout queries} + +\indexlibraryglobal{member_offset}% +\indexlibrarymember{member_offset}{total_bits}% +\begin{itemdecl} +struct member_offset { + ptrdiff_t bytes; + ptrdiff_t bits; + constexpr ptrdiff_t total_bits() const; + auto operator<=>(const member_offset&) const = default; +}; + +constexpr ptrdiff_t member_offset::total_bits() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{bytes * CHAR_BIT + bits}. +\end{itemdescr} + +\indexlibraryglobal{offset_of}% +\begin{itemdecl} +consteval member_offset offset_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $V$ be the offset in bits from the beginning of a complete object +of the type represented by \tcode{parent_of(r)} +to the subobject associated with the entity represented by \tcode{r}. + +\pnum +\returns +\tcode{\{$V$ / CHAR_BIT, $V$ \% CHAR_BIT\}}. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{r} represents a non-static data member, +unnamed bit-field, or +direct base class relationship $(D, B)$ +for which either $B$ is not a virtual base class +or $D$ is not an abstract class. +\end{itemdescr} + +\indexlibraryglobal{size_of}% +\begin{itemdecl} +consteval size_t size_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \tcode{r} represents +\begin{itemize} +\item a non-static data member of type $T$, +\item a data member description $(T, N, A, W, \mathit{NUA})$, or +\item \tcode{dealias(r)} represents a type $T$, +\end{itemize} +then \tcode{sizeof($T$)} if $T$ is not a reference type +and \tcode{size_of(\brk{}add_pointer(\brk{}\reflexpr{$T$}))} otherwise. +Otherwise, \tcode{size_of(type_of(r))}. +\begin{note} +It is possible that while \tcode{sizeof(char)\brk{} == size_of(\reflexpr{char})} +is \tcode{true}, +that \tcode{sizeof(char\&)\brk{} == size_of(\brk{}\reflexpr{char}\&)} +is \tcode{false}. +If \tcode{b} represents a direct base class relationship of an empty base class, +then \tcode{size_of(b) > 0} is \tcode{true}. +\end{note} + +\pnum +\throws +\tcode{meta::exception} unless +all of the following conditions are met: +\begin{itemize} +\item +\tcode{dealias(r)} is a reflection of a +type, +object, +value, +variable of non-reference type, +non-static data member that is not a bit-field, +direct base class relationship, or +data member description $(T, N, A, W, \mathit{NUA})$\iref{class.mem.general} +where $W$ is not $\bot$. +\item +If \tcode{dealias(r)} represents a type, +then \tcode{is_complete_type(r)} is \tcode{true}. +\end{itemize} +\end{itemdescr} + +\indexlibraryglobal{alignment_of}% +\begin{itemdecl} +consteval size_t alignment_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item + If \tcode{dealias(r)} represents a type $T$, + then \tcode{alignment_of(add_pointer(r))} if $T$ is a reference type + and the alignment requirement of $T$ otherwise. +\item + Otherwise, if \tcode{dealias(r)} represents a variable or object, + then the alignment requirement of the variable or object. +\item + Otherwise, if \tcode{r} represents a direct base class relationship, + then \tcode{alignment_of(type_of(r))}. +\item + Otherwise, if \tcode{r} represents a non-static data member $M$ of a class $C$, + then the alignment of the direct member subobject + corresponding to $M$ of a complete object of type $C$. +\item + Otherwise, \tcode{r} represents a data member description + $(T, N, A, W, \mathit{NUA})$\iref{class.mem.general}. + If $A$ is not $\bot$, + then the value of $A$. + Otherwise, \tcode{alignment_of(\reflexpr{$T$})}. +\end{itemize} + +\pnum +\throws +\tcode{meta::exception} unless +all of the following conditions are met: +\begin{itemize} +\item +\tcode{dealias(r)} is a reflection of a +type, +object, +variable of non-reference type, +non-static data member that is not a bit-field, +direct base class relationship, or +data member description. +\item +If \tcode{dealias(r)} represents a type, +then \tcode{is_complete_type(r)} is \tcode{true}. +\end{itemize} +\end{itemdescr} + +\indexlibraryglobal{bit_size_of}% +\begin{itemdecl} +consteval size_t bit_size_of(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item + If \tcode{r} represents + an unnamed bit-field + or a non-static data member that is a bit-field + with width $W$, + then $W$. +\item + Otherwise, if \tcode{r} represents a data member description + $(T, N, A, W, \mathit{NUA})$\iref{class.mem.general} + and $W$ is not $\bot$, + then $W$. +\item + Otherwise, \tcode{CHAR_BIT * size_of(r)}. +\end{itemize} + +\pnum +\throws +\tcode{meta::exception} unless +all of the following conditions are met: +\begin{itemize} +\item +\tcode{dealias(r)} is a reflection of a +type, +object, +value, +variable of non-reference type, +non-static data member, +unnamed bit-field, +direct base class relationship, or +data member description. +\item +If \tcode{dealias(r)} represents a type $T$, +there is a point within the evaluation context from which $T$ is not incomplete. +\end{itemize} +\end{itemdescr} + +\rSec2[meta.reflection.extract]{Value extraction} + +\pnum +The \tcode{extract} function template may be used +to extract a value out of a reflection when its type is known. + +\pnum +The following are defined for exposition only +to aid in the specification of \tcode{extract}. + +\begin{itemdecl} +template + consteval T @\exposid{extract-ref}@(info r); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +\tcode{T} is a reference type. +\end{note} + +\pnum +\returns +If \tcode{r} represents an object $O$, +then a reference to $O$. +Otherwise, a reference to the object declared, or referred to, +by the variable represented by \tcode{r}. + +\pnum +\throws +\tcode{meta::exception} unless +\begin{itemize} +\item + \tcode{r} represents a variable or object of type \tcode{U}, +\item + \tcode{is_convertible_v(*)[],\brk{} remove_reference_t<\brk{}T>(\brk{}*)[]>} + is \tcode{true},\newline and + \begin{note} + The intent is to allow only qualification conversion from \tcode{U} to \tcode{T}. + \end{note} +\item + If \tcode{r} represents a variable, + then either that variable is usable in constant expressions + or its lifetime began within the core constant expression currently under evaluation. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + consteval T @\exposid{extract-member-or-function}@(info r); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item + If \tcode{T} is a pointer type, + then a pointer value pointing to the function represented by \tcode{r}. +\item + Otherwise, a pointer-to-member value + designating the non-static data member or function represented by \tcode{r}. +\end{itemize} + +\pnum +\throws +\tcode{meta::exception} unless +\begin{itemize} +\item + \tcode{r} represents a non-static data member with type $X$, + that is not a bit-field, + that is a direct member of class \tcode{C}, + \tcode{T} and \tcode{X C::*} are similar types\iref{conv.qual}, and + \tcode{T} is \tcode{is_convertible_v} is \tcode{true}; +\item + \tcode{r} represents an implicit object member function + with type \tcode{F} or \tcode{F noexcept} + that is a direct member of a class \tcode{C}, + and \tcode{T} is \tcode{F C::*}; or +\item + \tcode{r} represents a non-member function, + static member function, or + explicit object member function + of function type \tcode{F} or \tcode{F noexcept}, + and \tcode{T} is \tcode{F*}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template + consteval T @\exposid{extract-value}@(info r); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $U$ be the type of the value or object that \tcode{r} represents. + +\pnum +\returns +\tcode{static_cast([:$R$:])}, +where $R$ is a constant expression of type \tcode{info} +such that \tcode{$R$ == r} is \tcode{true}. + +\pnum +\throws +\tcode{meta::exception} unless +\begin{itemize} +\item + \tcode{U} is a pointer type, + \tcode{T} and \tcode{U} are either similar\iref{conv.qual} + or both function pointer types, and + \tcode{is_convertible_v} is \tcode{true}, +\item + \tcode{U} is not a pointer type + and the cv-unqualified types of \tcode{T} and \tcode{U} are the same, +\item + \tcode{U} is an array type, + \tcode{T} is a pointer type, and + the value \tcode{r} represents is convertible to \tcode{T}, or +\item + \tcode{U} is a closure type, + \tcode{T} is a function pointer type, and + the value that \tcode{r} represents is convertible to \tcode{T}. +\end{itemize} +\end{itemdescr} + +\indexlibraryglobal{extract}% +\begin{itemdecl} +template + consteval T extract(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{U} be \tcode{remove_cv_t}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +if constexpr (is_reference_type(^^T)) { + return @\exposid{extract-ref}@(r); +} else if constexpr (is_nonstatic_data_member(r) || is_function(r)) { + return @\exposid{extract-member-or-function}@(r); +} else { + return @\exposid{extract-value}@(constant_of(r)); +} +\end{codeblock} +\end{itemdescr} + +\rSec2[meta.reflection.substitute]{Reflection substitution} + +\begin{itemdecl} +template +concept @\deflibconcept{reflection_range}@ = + ranges::@\libconcept{input_range}@ && + @\libconcept{same_as}@, info> && + @\libconcept{same_as}@>, info>; + +template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool @\libglobal{can_substitute}@(info templ, R&& arguments); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Z} be the template represented by \tcode{templ} +and let \tcode{Args...} be a sequence of prvalue constant expressions +that compute the reflections held by the elements of \tcode{arguments}. + +\pnum +\returns +\tcode{true} if \tcode{Z<[:Args:]...>} is a valid \grammarterm{template-id}\iref{temp.names} +that does not name a function +whose type contains an undeduced placeholder type. +Otherwise, \tcode{false}. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{templ} represents a template, +and every reflection in \tcode{arguments} represents a construct +usable as a template argument\iref{temp.arg}. + +\pnum +\begin{note} +If forming \tcode{Z<[:Args:]...>} leads to a failure +outside of the immediate context, +the program is ill-formed. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{substitute}% +\begin{itemdecl} +template<@\libconcept{reflection_range}@ R = initializer_list> + consteval info substitute(info templ, R&& arguments); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{Z} be the template represented by \tcode{templ} +and let \tcode{Args...} be a sequence of prvalue constant expressions +that compute the reflections held by the elements of \tcode{arguments}. + +\pnum +\returns +\tcode{\reflexpr{Z<[:Args:]...>}}. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{can_substitute(templ, arguments)} is \tcode{true}. + +\pnum +\begin{note} +If forming \tcode{Z<[:Args:]...>} leads to a failure outside of the immediate context, +the program is ill-formed. +\end{note} + +\pnum +\begin{example} +\begin{codeblock} +template + auto fn1(); + +static_assert(!can_substitute(^^fn1, {^^int})); // OK +constexpr info r1 = substitute(^^fn1, {^^int}); // error: \tcode{fn} contains an undeduced + // placeholder type + +template + auto fn2() { + static_assert(^^T != ^^int); // static assertion failed during instantiation of \tcode{fn} + return 0; + } + +constexpr bool r2 = can_substitute(^^fn2, {^^int}); // error: instantiation of body of \tcode{fn} + // is needed to deduce return type +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblock} +consteval info to_integral_constant(unsigned i) { + return substitute(^^integral_constant, {^^unsigned, reflect_constant(i)}); +} +constexpr info r = to_integral_constant(2); // OK, \tcode{r} represents the type + // \tcode{integral_constant} +\end{codeblock} +\end{example} +\end{itemdescr} + +\rSec2[meta.reflection.result]{Expression result reflection} + +\indexlibraryglobal{reflect_constant}% +\begin{itemdecl} +template + consteval info reflect_constant(T expr); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{is_copy_constructible_v} is \tcode{true} +and \tcode{T} is a cv-unqualified structural type\iref{temp.param} +that is not a reference type. + +\pnum +Let $V$ be: +\begin{itemize} +\item + if \tcode{T} is a class type, + then an object that is template-argument-equivalent to the value of \tcode{expr}; +\item + otherwise, the value of \tcode{expr}. +\end{itemize} + +\pnum +\returns +\tcode{template_arguments_of(\reflexpr{TCls<$V$>})[0]}, +with \tcode{TCls} as defined below. +\begin{note} +This is a reflection of an object for class types, +and a reflection of a value otherwise. +\end{note} + +\pnum +\throws +\tcode{meta::exception} unless +the \grammarterm{template-id} \tcode{TCls<$V$>} would be valid +given the invented template +\begin{codeblock} +template struct TCls; +\end{codeblock} + +\pnum +\begin{example} +\begin{codeblock} +template + struct A { }; + +struct N { int x; }; +struct K { char const* p; }; + +constexpr info r1 = reflect_constant(42); +static_assert(is_value(r1)); +static_assert(r1 == template_arguments_of(^^A<42>)[0]); + +constexpr info r2 = reflect_constant(N{42}); +static_assert(is_object(r2)); +static_assert(r2 == template_arguments_of(^^A)[0]); + +constexpr info r3 = reflect_constant(K{nullptr}); // OK +constexpr info r4 = reflect_constant(K{"ebab"}); // error: constituent pointer + // points to string literal +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibraryglobal{reflect_object}% +\begin{itemdecl} +template + consteval info reflect_object(T& expr); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is an object type. + +\pnum +\returns +A reflection of the object designated by \tcode{expr}. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{expr} is suitable for use as a constant template argument +for a constant template parameter of type \tcode{T\&}\iref{temp.arg.nontype}. +\end{itemdescr} + +\indexlibraryglobal{reflect_function}% +\begin{itemdecl} +template + consteval info reflect_function(T& fn); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is a function type. + +\pnum +\returns +A reflection of the function designated by \tcode{fn}. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{fn} is suitable for use as a constant template argument +for a constant template parameter of type \tcode{T\&}\iref{temp.arg.nontype}. +\end{itemdescr} + +\rSec2[meta.reflection.array]{Promoting to static storage arrays} + +\pnum +The functions in this subclause promote compile-time storage into static storage. + +\indexlibraryglobal{reflect_constant_string}% +\begin{itemdecl} +template + consteval info reflect_constant_string(R&& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{CharT} be \tcode{ranges::range_value_t}. + +\pnum +\mandates +\tcode{CharT} is one of +\tcode{char}, +\tcode{wchar_t}, +\tcode{char8_t}, +\tcode{char16_t}, +\tcode{char32_t}. + +\pnum +Let $V$ be the pack of values of type \tcode{CharT} +whose elements are the corresponding elements of \tcode{r}, +except that if \tcode{r} refers to a string literal object, +then $V$ does not include the trailing null terminator of \tcode{r}. + +\pnum +Let $P$ be the template parameter object\iref{temp.param} +of type \tcode{const CharT[sizeof...(V) + 1]} +initialized with \tcode{\{$V$..., CharT()\}}. + +\pnum +\returns +\tcode{\reflexpr{$P$}}. + +\pnum +\begin{note} +$P$ is a potentially non-unique object\iref{intro.object}. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{reflect_constant_array}% +\begin{itemdecl} +template + consteval info reflect_constant_array(R&& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{T} be \tcode{ranges::range_value_t}. + +\pnum +\mandates +\tcode{T} is a structural type\iref{temp.param}, +\tcode{is_constructible_v>} is \tcode{true}, and +\tcode{is_copy_constructible_v} is \tcode{true}. + +\pnum +Let $V$ be the pack of values of type \tcode{info} +of the same size as \tcode{r}, +where the $i^\text{th}$ element is \tcode{reflect_constant($\tcode{e}_i$)}, +where $\tcode{e}_i$ is the $i^\text{th}$ element of \tcode{r}. + +\pnum +Let $P$ be +\begin{itemize} +\item + If \tcode{sizeof...($V$) > 0} is \tcode{true}, + then the template parameter object\iref{temp.param} + of type \tcode{const T[\brk{}sizeof...(\brk{}$V$)]} + initialized with \tcode{\{[:$V$:]...\}}. +\item + Otherwise, the template parameter object + of type \tcode{array} + initialized with \tcode{\{\}}. +\end{itemize} + +\pnum +\returns +\tcode{\reflexpr{$P$}}. + +\pnum +\throws +\tcode{meta::exception} unless +\tcode{reflect_constant(e)} is a constant subexpression +for every element \tcode{e} of \tcode{r}. + +\pnum +\begin{note} +$P$ is a potentially non-unique object\iref{intro.object}. +\end{note} +\end{itemdescr} + +\rSec2[meta.reflection.define.aggregate]{Reflection class definition generation} + +\indexlibraryglobal{data_member_options}% +\begin{codeblock} +namespace std::meta { + struct data_member_options { + struct @\exposidnc{name-type}@ { // \expos + template + requires @\libconcept{constructible_from}@ + consteval @\exposid{name-type}@(T&&); + + template + requires @\libconcept{constructible_from}@ + consteval @\exposid{name-type}@(T&&); + + private: + variant @\exposidnc{contents}@; // \expos + }; + + optional<@\exposid{name-type}@> name; + optional alignment; + optional bit_width; + bool no_unique_address = false; + }; +} +\end{codeblock} + +\pnum +The classes \tcode{data_member_options} +and \tcode{data_member_options::\brk{}\exposid{name-type}} +are consteval-only types\iref{basic.types.general}, +and are not structural types\iref{temp.param}. + +\begin{itemdecl} +template + requires @\libconcept{constructible_from}@ + consteval data_member_options::@\exposid{name-type}@(T&& value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{contents} +with \tcode{u8string(std::forward(value))}. +\end{itemdescr} + +\begin{itemdecl} +template + requires @\libconcept{constructible_from}@ + consteval data_member_options::@\exposid{name-type}@(T&& value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{contents} +with \tcode{string(std::forward(value))}. +\begin{note} +The class \exposid{name-type} allows +the function \tcode{data_member_spec} to accept +an ordinary string literal (or \tcode{string_view}, \tcode{string}, etc.) +or a UTF-8 string literal (or \tcode{u8string_view}, \tcode{u8string}, etc.) +equally well. +\begin{example} +\begin{codeblock} +consteval void fn() { + data_member_options o1 = {.name = "ordinary_literal_encoding"}; + data_member_options o2 = {.name = u8"utf8_encoding"}; +} +\end{codeblock} +\end{example} +\end{note} +\end{itemdescr} + +\indexlibraryglobal{data_member_spec}% +\begin{itemdecl} +consteval info data_member_spec(info type, data_member_options options); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A reflection of a data member description +$(T, N, A, W, \mathit{NUA})$\iref{class.mem.general} where +\begin{itemize} +\item + $T$ is the type represented by \tcode{dealias(type)}, +\item + $N$ is either the identifier encoded by \tcode{options.name} + or $\bot$ if \tcode{options.name} does not contain a value, +\item + $A$ is either the alignment value held by \tcode{options.alignment} + or $\bot$ if \tcode{options.alignment} does not contain a value, +\item + $W$ is either the value held by \tcode{options.bit_width} + or $\bot$ if \tcode{options.bit_width} does not contain a value, and +\item + $\mathit{NUA}$ is the value held by \tcode{options.no_unique_address}. +\end{itemize} +\begin{note} +The returned reflection value is primarily useful +in conjunction with \tcode{define_aggregate}; +it can also be queried by certain other functions in \tcode{std::meta} +(e.g., \tcode{type_of}, \tcode{identifier_of}). +\end{note} + +\pnum +\throws +\tcode{meta::exception} unless the following conditions are met: +\begin{itemize} +\item + \tcode{dealias(type)} represents either an object type or a reference type; +\item + if \tcode{options.name} contains a value, then: + \begin{itemize} + \item + \tcode{holds_alternative(options.name->\exposid{contents})} is \tcode{true} + and \tcode{get(\brk{}options.name->\exposid{contents})} + contains a valid identifier\iref{lex.name} + that is not a keyword\iref{lex.key} + when interpreted with UTF-8, or + \item + \tcode{holds_alternative(options.name->\exposid{contents})} is \tcode{true} + and \tcode{get(opt\-ions.name->\exposid{contents})} + contains a valid identifier\iref{lex.name} + that is not a keyword\iref{lex.key} + when interpreted with the ordinary literal encoding; + \end{itemize} + \begin{note} + The name corresponds to the spelling of an identifier~token + after phase~6 of translation\iref{lex.phases}. + Lexical constructs like + \grammarterm{universal-character-name}s\iref{lex.universal.char} are not processed + and will cause evaluation to fail. + For example, \tcode{R"(\textbackslash u03B1)"} is an invalid identifier + and is not interpreted as \tcode{"$\alpha$"}. + \end{note} +\item + if \tcode{options.name} does not contain a value, + then \tcode{options.bit_width} contains a value; +\item + if \tcode{options.bit_width} contains a value $V$, then + \begin{itemize} + \item + \tcode{is_integral_type(type) || is_enumeration_type(type)} is \tcode{true}, + \item + \tcode{options.alignment} does not contain a value, + \item + \tcode{options.no_unique_address} is \tcode{false}, and + \item + if $V$ equals \tcode{0}, + then \tcode{options.name} does not contain a value; and + \end{itemize} + \item + if \tcode{options.alignment} contains a value, + it is an alignment value\iref{basic.align} + not less than \tcode{alignment_of(type)}. +\end{itemize} +\end{itemdescr} + +\indexlibraryglobal{is_data_member_spec}% +\begin{itemdecl} +consteval bool is_data_member_spec(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a data member description. +Otherwise, \tcode{false}. +\end{itemdescr} + +\indexlibraryglobal{define_aggregate}% +\begin{itemdecl} +template<@\libconcept{reflection_range}@ R = initializer_list> + consteval info define_aggregate(info class_type, R&& mdescrs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $C$ be the class represented by \tcode{class_type} +and $r_K$ be the $K^\text{th}$ reflection value in \tcode{mdescrs}. +For every $r_K$ in \tcode{mdescrs}, +let $(T_K, N_K, A_K, W_K, \mathit{NUA}_K)$ be +the corresponding data member description represented by $r_K$. + +\pnum +\constantwhen +\begin{itemize} +\item + $C$ is incomplete from every point in the evaluation context; + \begin{note} + $C$ can be a class template specialization + for which there is a reachable definition of the class template. + In this case, + the injected declaration is an explicit specialization. + \end{note} +\item + \tcode{is_data_member_spec($r_K$)} is \tcode{true} for every $r_K$; +\item + \tcode{is_complete_type($T_K$)} is \tcode{true} for every $r_K$; and +\item + for every pair $(r_K, r_L)$ where $K < L$, + if $N_K$ is not $\bot$ and $N_L$ is not $\bot$, + then either: + \begin{itemize} + \item + \tcode{$N_K$ != $N_L$} is \tcode{true} or + \item + \tcode{$N_K$ == u8"_"} is \tcode{true}. + \begin{note} + Every provided identifier is unique or \tcode{"_"}. + \end{note} + \end{itemize} +\end{itemize} + +\pnum +\effects +Produces an injected declaration $D$\iref{expr.const} +that defines $C$ and has properties as follows: +\begin{itemize} +\item + The target scope of $D$ + is the scope to which $C$ belongs\iref{basic.scope.scope}. +\item + The locus of $D$ + follows immediately after the core constant expression + currently under evaluation. +\item + The characteristic sequence of $D$\iref{expr.const} + is the sequence of reflection values $r_K$. +\item + If $C$ is a specialization of a templated class $T$, + and $C$ is not a local class, + then $D$ is an explicit specialization of $T$. +\item + For each $r_K$, + there is a corresponding entity $M_K$ + belonging to the class scope of $D$ + with the following properties: + \begin{itemize} + \item + If $N_K$ is $\bot$, + $M_K$ is an unnamed bit-field. + Otherwise, $M_K$ is a non-static data member whose name is the identifier + determined by the character sequence encoded by $N_K$ in UTF-8. + \item + The type of $M_K$ is $T_K$. + \item + $M_K$ is declared with the attribute \tcode{[[no_unique_address]]} + if and only if $\mathit{NUA}_K$ is \tcode{true}. + \item + If $W_K$ is not $\bot$, + $M_K$ is a bit-field whose width is that value. + Otherwise, $M_K$ is not a bit-field. + \item + If $A_K$ is not $\bot$, + $M_K$ has the \grammarterm{alignment-specifier} \tcode{alignas($A_K$)}. + Otherwise, $M_K$ has no \grammarterm{alignment-specifier}. + \end{itemize} + \item + For every $r_L$ in \tcode{mdescrs} such that $K < L$, + the declaration corresponding to $r_K$ + precedes the declaration corresponding to $r_L$. +\end{itemize} + +\pnum +\returns +\tcode{class_type}. +\end{itemdescr} + +\rSec2[meta.reflection.traits]{Reflection type traits} + +\pnum +This subclause specifies \tcode{consteval} functions to +query the properties of types\iref{meta.unary}, +query the relationships between types\iref{meta.rel}, or +transform types\iref{meta.trans}, +during program translation. +Each \tcode{consteval} function declared in this class +has an associated class template declared elsewhere in this document. + +\pnum +Every function and function template declared in this subclause +throws an exception of type \tcode{meta::exception} +unless the following conditions are met: +\begin{itemize} +\item + For every parameter \tcode{p} of type \tcode{info}, + \tcode{is_type(p)} is \tcode{true}. +\item + For every parameter \tcode{r} + whose type is constrained on \libconcept{reflection_range}, + \tcode{ranges::\brk{}all_of(\brk{}r, is_type)} is \tcode{true}. +\end{itemize} + +\begin{codeblock} +// associated with \ref{meta.unary.cat}, primary type categories +consteval bool @\libglobal{is_void_type}@(info type); +consteval bool @\libglobal{is_null_pointer_type}@(info type); +consteval bool @\libglobal{is_integral_type}@(info type); +consteval bool @\libglobal{is_floating_point_type}@(info type); +consteval bool @\libglobal{is_array_type}@(info type); +consteval bool @\libglobal{is_pointer_type}@(info type); +consteval bool @\libglobal{is_lvalue_reference_type}@(info type); +consteval bool @\libglobal{is_rvalue_reference_type}@(info type); +consteval bool @\libglobal{is_member_object_pointer_type}@(info type); +consteval bool @\libglobal{is_member_function_pointer_type}@(info type); +consteval bool @\libglobal{is_enum_type}@(info type); +consteval bool @\libglobal{is_union_type}@(info type); +consteval bool @\libglobal{is_class_type}@(info type); +consteval bool @\libglobal{is_function_type}@(info type); +consteval bool @\libglobal{is_reflection_type}@(info type); + +// associated with \ref{meta.unary.comp}, composite type categories +consteval bool @\libglobal{is_reference_type}@(info type); +consteval bool @\libglobal{is_arithmetic_type}@(info type); +consteval bool @\libglobal{is_fundamental_type}@(info type); +consteval bool @\libglobal{is_object_type}@(info type); +consteval bool @\libglobal{is_scalar_type}@(info type); +consteval bool @\libglobal{is_compound_type}@(info type); +consteval bool @\libglobal{is_member_pointer_type}@(info type); + +// associated with \ref{meta.unary.prop}, type properties +consteval bool @\libglobal{is_const_type}@(info type); +consteval bool @\libglobal{is_volatile_type}@(info type); +consteval bool @\libglobal{is_trivially_copyable_type}@(info type); +consteval bool @\libglobal{is_trivially_relocatable_type}@(info type); +consteval bool @\libglobal{is_replaceable_type}@(info type); +consteval bool @\libglobal{is_standard_layout_type}@(info type); +consteval bool @\libglobal{is_empty_type}@(info type); +consteval bool @\libglobal{is_polymorphic_type}@(info type); +consteval bool @\libglobal{is_abstract_type}@(info type); +consteval bool @\libglobal{is_final_type}@(info type); +consteval bool @\libglobal{is_aggregate_type}@(info type); +consteval bool @\libglobal{is_consteval_only_type}@(info type); +consteval bool @\libglobal{is_signed_type}@(info type); +consteval bool @\libglobal{is_unsigned_type}@(info type); +consteval bool @\libglobal{is_bounded_array_type}@(info type); +consteval bool @\libglobal{is_unbounded_array_type}@(info type); +consteval bool @\libglobal{is_scoped_enum_type}@(info type); + +template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool @\libglobal{is_constructible_type}@(info type, R&& type_args); +consteval bool @\libglobal{is_default_constructible_type}@(info type); +consteval bool @\libglobal{is_copy_constructible_type}@(info type); +consteval bool @\libglobal{is_move_constructible_type}@(info type); + +consteval bool @\libglobal{is_assignable_type}@(info type_dst, info type_src); +consteval bool @\libglobal{is_copy_assignable_type}@(info type); +consteval bool @\libglobal{is_move_assignable_type}@(info type); + +consteval bool @\libglobal{is_swappable_with_type}@(info type1, info type2); +consteval bool @\libglobal{is_swappable_type}@(info type); + +consteval bool @\libglobal{is_destructible_type}@(info type); + +template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool @\libglobal{is_trivially_constructible_type}@(info type, R&& type_args); +consteval bool @\libglobal{is_trivially_default_constructible_type}@(info type); +consteval bool @\libglobal{is_trivially_copy_constructible_type}@(info type); +consteval bool @\libglobal{is_trivially_move_constructible_type}@(info type); + +consteval bool @\libglobal{is_trivially_assignable_type}@(info type_dst, info type_src); +consteval bool @\libglobal{is_trivially_copy_assignable_type}@(info type); +consteval bool @\libglobal{is_trivially_move_assignable_type}@(info type); +consteval bool @\libglobal{is_trivially_destructible_type}@(info type); + +template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool @\libglobal{is_nothrow_constructible_type}@(info type, R&& type_args); +consteval bool @\libglobal{is_nothrow_default_constructible_type}@(info type); +consteval bool @\libglobal{is_nothrow_copy_constructible_type}@(info type); +consteval bool @\libglobal{is_nothrow_move_constructible_type}@(info type); + +consteval bool @\libglobal{is_nothrow_assignable_type}@(info type_dst, info type_src); +consteval bool @\libglobal{is_nothrow_copy_assignable_type}@(info type); +consteval bool @\libglobal{is_nothrow_move_assignable_type}@(info type); + +consteval bool @\libglobal{is_nothrow_swappable_with_type}@(info type1, info type2); +consteval bool @\libglobal{is_nothrow_swappable_type}@(info type); + +consteval bool @\libglobal{is_nothrow_destructible_type}@(info type); +consteval bool @\libglobal{is_nothrow_relocatable_type}@(info type); + +consteval bool @\libglobal{is_implicit_lifetime_type}@(info type); + +consteval bool @\libglobal{has_virtual_destructor}@(info type); + +consteval bool @\libglobal{has_unique_object_representations}@(info type); + +consteval bool @\libglobal{reference_constructs_from_temporary}@(info type_dst, info type_src); +consteval bool @\libglobal{reference_converts_from_temporary}@(info type_dst, info type_src); + +// associated with \ref{meta.rel}, type relations +consteval bool @\libglobal{is_same_type}@(info type1, info type2); +consteval bool @\libglobal{is_base_of_type}@(info type_base, info type_derived); +consteval bool @\libglobal{is_virtual_base_of_type}@(info type_base, info type_derived); +consteval bool @\libglobal{is_convertible_type}@(info type_src, info type_dst); +consteval bool @\libglobal{is_nothrow_convertible_type}@(info type_src, info type_dst); +consteval bool @\libglobal{is_layout_compatible_type}@(info type1, info type2); +consteval bool @\libglobal{is_pointer_interconvertible_base_of_type}@(info type_base, info type_derived); + +template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool @\libglobal{is_invocable_type}@(info type, R&& type_args); +template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool @\libglobal{is_invocable_r_type}@(info type_result, info type, R&& type_args); + +template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool @\libglobal{is_nothrow_invocable_type}@(info type, R&& type_args); +template<@\libconcept{reflection_range}@ R = initializer_list> + consteval bool @\libglobal{is_nothrow_invocable_r_type}@(info type_result, info type, R&& type_args); + +// associated with \ref{meta.trans.cv}, const-volatile modifications +consteval info @\libglobal{remove_const}@(info type); +consteval info @\libglobal{remove_volatile}@(info type); +consteval info @\libglobal{remove_cv}@(info type); +consteval info @\libglobal{add_const}@(info type); +consteval info @\libglobal{add_volatile}@(info type); +consteval info @\libglobal{add_cv}@(info type); + +// associated with \ref{meta.trans.ref}, reference modifications +consteval info @\libglobal{remove_reference}@(info type); +consteval info @\libglobal{add_lvalue_reference}@(info type); +consteval info @\libglobal{add_rvalue_reference}@(info type); + +// associated with \ref{meta.trans.sign}, sign modifications +consteval info @\libglobal{make_signed}@(info type); +consteval info @\libglobal{make_unsigned}@(info type); + +// associated with \ref{meta.trans.arr}, array modifications +consteval info @\libglobal{remove_extent}@(info type); +consteval info @\libglobal{remove_all_extents}@(info type); + +// associated with \ref{meta.trans.ptr}, pointer modifications +consteval info @\libglobal{remove_pointer}@(info type); +consteval info @\libglobal{add_pointer}@(info type); + +// associated with \ref{meta.trans.other}, other transformations +consteval info @\libglobal{remove_cvref}@(info type); +consteval info @\libglobal{decay}@(info type); +template<@\libconcept{reflection_range}@ R = initializer_list> + consteval info @\libglobal{common_type}@(R&& type_args); +template<@\libconcept{reflection_range}@ R = initializer_list> + consteval info @\libglobal{common_reference}@(R&& type_args); +consteval info @\libglobal{underlying_type}@(info type); +template<@\libconcept{reflection_range}@ R = initializer_list> + consteval info @\libglobal{invoke_result}@(info type, R&& type_args); +consteval info @\libglobal{unwrap_reference}@(info type); +consteval info @\libglobal{unwrap_ref_decay}@(info type); +\end{codeblock} + +\pnum +Each function or function template declared above has the following behavior +based on the signature and return type of that function or function template. +\begin{note} +The associated class template need not be instantiated. +\end{note} + +\begin{libreqtab2b}{Reflection type traits}{meta.reflection.traits} +\\ \topline +\lhdr{Signature and Return Type} & \rhdr{\Fundescx{Returns}} \\ \capsep +\endfirsthead +\continuedcaption\\ +\topline +\lhdr{Signature and Return Type} & \rhdr{\Fundescx{Returns}} \\ \capsep +\endhead + +\tcode{bool meta::\placeholder{UNARY}(info type);\br +bool meta::\placeholder{UNARY}_type(info type);} & +\tcode{std::\placeholder{UNARY}_v<$T$>}, +where $T$ is the type or type alias represented by \tcode{type} +\\ \rowsep + +\tcode{bool meta::\placeholder{BINARY}(info t1, info t2);\br +bool meta::\placeholder{BINARY}_type(info t1, info t2);} & +\tcode{std::\placeholder{BINARY}_v<$T_1$, $T_2$>}, +where $T_1$ and $T_2$ are the types or type aliases +represented by \tcode{t1} and \tcode{t2}, respectively +\\ \rowsep + +\tcode{template\br + bool meta::\placeholder{VARIADIC}_type(info type, R\&\& args);} & +\tcode{std::\placeholder{VARIADIC}_v<$T$, $U$...>}, +where $T$ is the type or type alias represented by \tcode{type} +and \tcode{U...} is the pack of types or type aliases +whose elements are represented by the corresponding elements of \tcode{args} +\\ \rowsep + +\tcode{template\br + bool meta::\placeholder{VARIADIC}_type(info t1, info t2, R\&\& args);} & +\tcode{std::\placeholder{VARIADIC}_v<$T_1$, $T_2$, $U$...>}, +where $T_1$ and $T_2$ are the types or type aliases +represented by \tcode{t1} and \tcode{t2}, respectively, +and \tcode{$U$...} is the pack of types or type aliases +whose elements are represented by the corresponding elements of \tcode{args} +\\ \rowsep + +\tcode{info meta::\placeholder{UNARY}(info type);} & +A reflection representing the type denoted by +\tcode{std::\placeholder{UNARY}_t<\brk{}$T$>}, +where $T$ is the type or type alias represented by \tcode{type} +\\ \rowsep + +\tcode{template\br + info meta::\placeholder{VARIADIC}(R\&\& args);} & +A reflection representing the type denoted by +\tcode{std::\placeholder{VARIADIC}_t<$T$...>}, +where \tcode{$T$...} is the pack of types or type aliases +whose elements are represented by the corresponding elements of \tcode{args} +\\ \rowsep + +\tcode{template\br + info meta::\placeholder{VARIADIC}(info type, R\&\& args);} & +A reflection representing the type denoted by +\tcode{std::\placeholder{VARIADIC}_t<$T$, $U$...>}, +where \tcode{$T$} is the type or type alias represented by \tcode{type} +and \tcode{$U$...} is the pack of types or type aliases +whose elements are represented by the corresponding elements of \tcode{args} +\\ +\end{libreqtab2b} + +\pnum +\begin{note} +For those functions or function templates which return a reflection, +that reflection always represents a type and never a type alias. +\end{note} + +\pnum +\begin{note} +If \tcode{t} is a reflection of the type \tcode{int} +and \tcode{u} is a reflection of an alias to the type \tcode{int}, +then \tcode{t == u} is \tcode{false} +but \tcode{is_same_type(t, u)} is \tcode{true}. +Also, \tcode{t == dealias(u)} is \tcode{true}. +\end{note} + +\indexlibraryglobal{rank}% +\begin{itemdecl} +consteval size_t rank(info type); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{rank_v<$T$>}, +where $T$ is the type represented by \tcode{dealias(type)}. +\end{itemdescr} + +\indexlibraryglobal{extent}% +\begin{itemdecl} +consteval size_t extent(info type, unsigned i = 0); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{extent_v<$T$, $I$>}, +where $T$ is the type represented by \tcode{dealias(type)} +and $I$ is a constant equal to \tcode{i}. +\end{itemdescr} + +\indexlibraryglobal{tuple_size}% +\begin{itemdecl} +consteval size_t tuple_size(info type); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{tuple_size_v<$T$>}, +where $T$ is the type represented by \tcode{dealias(type)}. +\end{itemdescr} + +\indexlibraryglobal{tuple_element}% +\begin{itemdecl} +consteval info tuple_element(size_t index, info type); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A reflection representing +the type denoted by \tcode{tuple_element_t<$I$, $T$>}, +where $T$ is the type represented by \tcode{dealias(type)} +and $I$ is a constant equal to \tcode{index}. +\end{itemdescr} + +\indexlibraryglobal{variant_size}% +\begin{itemdecl} +consteval size_t variant_size(info type); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{variant_size_v<$T$>}, +where $T$ is the type represented by \tcode{dealias(type)}. +\end{itemdescr} + +\indexlibraryglobal{variant_alternative}% +\begin{itemdecl} +consteval info variant_alternative(size_t index, info type); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A reflection representing the type denoted by +\tcode{variant_alternative_t<$I$, $T$>}, +where $T$ is the type represented by \tcode{dealias(type)} +and $I$ is a constant equal to \tcode{index}. +\end{itemdescr} + +\indexlibraryglobal{type_order}% +\begin{itemdecl} +consteval strong_ordering type_order(info t1, info t2); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{type_order_v<$T_1$, $T_2$>}, +where $T_1$ and $T_2$ are the types +represented by \tcode{dealias(t1)} and \tcode{dealias(t2)}, respectively. +\end{itemdescr} + +\rSec2[meta.reflection.annotation]{Annotation reflection} + +\indexlibraryglobal{annotations_of}% +\begin{itemdecl} +consteval vector annotations_of(info item); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let $E$ be +\begin{itemize} +\item + the corresponding \grammarterm{base-specifier} + if \tcode{item} represents a direct base class relationship, +\item + otherwise, the entity represented by \tcode{item}. +\end{itemize} + +\pnum +\returns +A \tcode{vector} containing all of the reflections $R$ +representing each annotation applying to each declaration of $E$ that precedes either +some point in the evaluation context\iref{expr.const} or +a point immediately following the \grammarterm{class-specifier} +of the outermost class for which such a point is in a complete-class context. +For any two reflections $R_1$ and $R_2$ in the returned \tcode{vector}, +if the annotation represented by $R_1$ precedes the annotation represented by $R_2$, +then $R_1$ appears before $R_2$. +If $R_1$ and $R_2$ represent annotations from the same translation unit $T$, +any element in the returned \tcode{vector} between $R_1$ and $R_2$ +represents an annotation from $T$. +\begin{note} +The order in which two annotations appear is otherwise unspecified. +\end{note} +\begin{example} +\begin{codeblock} +[[=1]] void f(); +[[=2, =3]] void g(); +void g [[=4]] (); + +static_assert(annotations_of(^^f).size() == 1); +static_assert(annotations_of(^^g).size() == 3); +static_assert([: constant_of(annotations_of(^^g)[0]) :] == 2); +static_assert(extract(annotations_of(^^g)[1]) == 3); +static_assert(extract(annotations_of(^^g)[2]) == 4); + +struct Option { bool value; }; + +struct C { + [[=Option{true}]] int a; + [[=Option{false}]] int b; +}; + +static_assert(extract

> && - @\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> + && @\exposconcept{concatable}@, Pattern> class join_with_view : public view_interface> { using @\exposid{InnerRng}@ = range_reference_t; // \expos @@ -7043,7 +7277,8 @@ requires @\libconcept{forward_range}@ && @\libconcept{forward_range}@ && is_reference_v> && - @\libconcept{input_range}@> { + @\libconcept{input_range}@> && + @\exposconcept{concatable}@, const Pattern> { return @\exposid{iterator}@{*this, ranges::begin(@\exposid{base_}@)}; } @@ -7058,7 +7293,8 @@ constexpr auto end() const requires @\libconcept{forward_range}@ && @\libconcept{forward_range}@ && is_reference_v> && - @\libconcept{input_range}@> { + @\libconcept{input_range}@> && + @\exposconcept{concatable}@, const Pattern> { using InnerConstRng = range_reference_t; if constexpr (@\libconcept{forward_range}@ && @\libconcept{common_range}@ && @\libconcept{common_range}@) @@ -7077,6 +7313,7 @@ } \end{codeblock} +\indexlibraryctor{join_with_view}% \begin{itemdecl} constexpr explicit join_with_view(V base, Pattern pattern); \end{itemdecl} @@ -7088,6 +7325,7 @@ \exposid{pattern_} with \tcode{std::move(pattern)}. \end{itemdescr} +\indexlibraryctor{join_with_view}% \begin{itemdecl} template<@\libconcept{input_range}@ R> requires @\libconcept{constructible_from}@> && @@ -7104,11 +7342,12 @@ \rSec3[range.join.with.iterator]{Class template \tcode{join_with_view::\exposid{iterator}}} +\indexlibraryglobal{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> + && @\libconcept{view}@ && @\exposconcept{concatable}@, Pattern> template class join_with_view::@\exposid{iterator}@ { using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos @@ -7226,7 +7465,7 @@ \item Otherwise, if \placeholder{OUTERC}, \placeholder{INNERC}, and \placeholder{PATTERNC} -each model \tcode{\libconcept{derived_from}} +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}. @@ -7249,11 +7488,12 @@ \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}@>> + iter_difference_t<@\exposid{OuterIter}@>, + iter_difference_t<@\exposid{InnerIter}@>, + iter_difference_t<@\exposid{PatternIter}@>> \end{codeblock} +\indexlibrarymember{\exposid{outer}}{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{OuterIter}@& @\exposid{outer}@(); constexpr const @\exposid{OuterIter}@& @\exposid{outer}@() const; @@ -7266,6 +7506,7 @@ otherwise, \tcode{*\exposid{parent_}->\exposid{outer_it_}}. \end{itemdescr} +\indexlibrarymember{\exposid{update-inner}}{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr auto& @\exposid{update-inner}@(); \end{itemdecl} @@ -7282,6 +7523,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{\exposid{get-inner}}{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr auto& @\exposid{get-inner}@(); \end{itemdecl} @@ -7298,6 +7540,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{\exposid{satisfy}}{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr void @\exposid{satisfy}@(); \end{itemdecl} @@ -7311,16 +7554,16 @@ if (@\exposid{inner_it_}@.index() == 0) { if (std::get<0>(@\exposid{inner_it_}@) != ranges::end(@\exposid{parent_}@->@\exposid{pattern_}@)) break; - @\exposid{inner_it_}@.emplace<1>(ranges::begin(@\exposid{update-inner}@())); + @\exposid{inner_it_}@.template emplace<1>(ranges::begin(@\exposid{update-inner}@())); } else { if (std::get<1>(@\exposid{inner_it_}@) != ranges::end(@\exposid{get-inner}@())) break; if (++@\exposid{outer}@() == ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { if constexpr (@\exposid{ref-is-glvalue}@) - @\exposid{inner_it_}@.emplace<0>(); + @\exposid{inner_it_}@.template emplace<0>(); break; } - @\exposid{inner_it_}@.emplace<0>(ranges::begin(@\exposid{parent_}@->@\exposid{pattern_}@)); + @\exposid{inner_it_}@.template emplace<0>(ranges::begin(@\exposid{parent_}@->@\exposid{pattern_}@)); } } \end{codeblock} @@ -7331,6 +7574,7 @@ \end{note} \end{itemdescr} +\indexlibraryctor{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{OuterIter}@ outer) requires @\libconcept{forward_range}@<@\exposid{Base}@>; @@ -7347,12 +7591,13 @@ Then, equivalent to: \begin{codeblock} if (@\exposid{outer}@() != ranges::end(@\exposid{parent_}@->@\exposid{base_}@)) { - @\exposid{inner_it_}@.emplace<1>(ranges::begin(@\exposid{update-inner}@())); + @\exposid{inner_it_}@.template emplace<1>(ranges::begin(@\exposid{update-inner}@())); @\exposidnc{satisfy}@(); } \end{codeblock} \end{itemdescr} +\indexlibraryctor{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) requires Const && @\libconcept{convertible_to}@, @\exposid{OuterIter}@> && @@ -7369,9 +7614,9 @@ 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_}@))); + @\exposid{inner_it_}@.template 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_}@))); + @\exposid{inner_it_}@.template emplace<1>(std::get<1>(std::move(i.@\exposid{inner_it_}@))); \end{codeblock} \pnum @@ -7381,6 +7626,7 @@ \end{note} \end{itemdescr} +\indexlibrarymember{operator--}{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr decltype(auto) operator*() const; \end{itemdecl} @@ -7396,6 +7642,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -7411,6 +7658,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr void operator++(int); \end{itemdecl} @@ -7421,6 +7669,7 @@ Equivalent to \tcode{++*this}. \end{itemdescr} +\indexlibrarymember{operator++}{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator++(int) requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_iterator}@<@\exposid{OuterIter}@> && @\libconcept{forward_iterator}@<@\exposid{InnerIter}@>; @@ -7437,6 +7686,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator--() requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && @@ -7450,7 +7700,7 @@ \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)); + @\exposid{inner_it_}@.template emplace<1>(ranges::end(inner)); } while (true) { @@ -7458,7 +7708,7 @@ 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)); + @\exposid{inner_it_}@.template emplace<1>(ranges::end(inner)); } else { break; } @@ -7466,7 +7716,7 @@ 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_}@)); + @\exposid{inner_it_}@.template emplace<0>(ranges::end(@\exposid{parent_}@->@\exposid{pattern_}@)); } else { break; } @@ -7477,6 +7727,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{join_with_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator--(int) requires @\exposid{ref-is-glvalue}@ && @\libconcept{bidirectional_range}@<@\exposid{Base}@> && @@ -7494,6 +7745,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator==}{join_with_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\exposid{ref-is-glvalue}@ && @\libconcept{forward_range}@<@\exposid{Base}@> && @@ -7511,11 +7763,12 @@ \rSec3[range.join.with.sentinel]{Class template \tcode{join_with_view::\exposid{sentinel}}} +\indexlibraryglobal{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> + && @\libconcept{view}@ && @\exposconcept{concatable}@, Pattern> template class join_with_view::@\exposid{sentinel}@ { using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos @@ -7536,6 +7789,7 @@ } \end{codeblock} +\indexlibraryctor{join_with_view::\exposid{sentinel}}% \begin{itemdecl} constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent); \end{itemdecl} @@ -7546,6 +7800,7 @@ Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}. \end{itemdescr} +\indexlibraryctor{join_with_view::\exposid{sentinel}}% \begin{itemdecl} constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ s) requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; @@ -7557,6 +7812,7 @@ Initializes \exposid{end_} with \tcode{std::move(s.\exposid{end_})}. \end{itemdescr} +\indexlibrarymember{operator==}{join_with_view::\exposid{sentinel}}% \begin{itemdecl} template requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> @@ -7909,10 +8165,9 @@ private: @\exposid{outer-iterator}@ @\exposid{i_}@ = @\exposid{outer-iterator}@(); // \expos - public: - value_type() = default; - constexpr explicit value_type(@\exposid{outer-iterator}@ i); + constexpr explicit value_type(@\exposid{outer-iterator}@ i); // \expos + public: constexpr @\exposid{inner-iterator}@ begin() const; constexpr default_sentinel_t end() const noexcept; }; @@ -8162,6 +8417,7 @@ \rSec3[range.split.view]{Class template \tcode{split_view}} +\indexlibraryglobal{split_view} \begin{codeblock} namespace std::ranges { template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern> @@ -8213,6 +8469,7 @@ } \end{codeblock} +\indexlibraryctor{split_view} \begin{itemdecl} constexpr explicit split_view(V base, Pattern pattern); \end{itemdecl} @@ -8239,6 +8496,7 @@ \exposid{pattern_} with \tcode{views::\linebreak single(std::move(e))}. \end{itemdescr} +\indexlibrarymember{begin}{split_view} \begin{itemdecl} constexpr @\exposid{iterator}@ begin(); \end{itemdecl} @@ -8256,6 +8514,7 @@ for use on subsequent calls. \end{itemdescr} +\indexlibrarymember{\exposid{find-next}}{split_view} \begin{itemdecl} constexpr subrange> @\exposid{find-next}@(iterator_t it); \end{itemdecl} @@ -8276,6 +8535,7 @@ \rSec3[range.split.iterator]{Class \tcode{split_view::\exposid{iterator}}} +\indexlibraryglobal{split_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern> @@ -8308,6 +8568,7 @@ } \end{codeblock} +\indexlibraryctor{split_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@(split_view& parent, iterator_t current, subrange> next); \end{itemdecl} @@ -8320,6 +8581,7 @@ \exposid{next_} with \tcode{std::move(next)}. \end{itemdescr} +\indexlibrarymember{base}{split_view::\exposid{iterator}}% \begin{itemdecl} constexpr iterator_t base() const; \end{itemdecl} @@ -8330,6 +8592,7 @@ Equivalent to: \tcode{return \exposid{cur_};} \end{itemdescr} +\indexlibrarymember{operator*}{split_view::\exposid{iterator}}% \begin{itemdecl} constexpr value_type operator*() const; \end{itemdecl} @@ -8340,6 +8603,7 @@ Equivalent to: \tcode{return \{\exposid{cur_}, \exposid{next_}.begin()\};} \end{itemdescr} +\indexlibrarymember{operator++}{split_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -8365,6 +8629,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{split_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} @@ -8380,6 +8645,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator==}{split_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); \end{itemdecl} @@ -8395,6 +8661,7 @@ \rSec3[range.split.sentinel]{Class \tcode{split_view::\exposid{sentinel}}} +\indexlibraryglobal{split_view::\exposid{sentinel}}% \begin{codeblock} namespace std::ranges { template<@\libconcept{forward_range}@ V, @\libconcept{forward_range}@ Pattern> @@ -8413,6 +8680,7 @@ } \end{codeblock} +\indexlibraryctor{split_view::\exposid{sentinel}}% \begin{itemdecl} constexpr explicit @\exposid{sentinel}@(split_view& parent); \end{itemdecl} @@ -8423,6 +8691,7 @@ Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}. \end{itemdescr} +\indexlibrarymember{operator==}{split_view::\exposid{sentinel}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} @@ -8433,539 +8702,2189 @@ Equivalent to: \tcode{return x.\exposid{cur_} == y.\exposid{end_} \&\& !x.\exposid{trailing_empty_};} \end{itemdescr} -\rSec2[range.counted]{Counted view} +\rSec2[range.concat]{Concat view} + +\rSec3[range.concat.overview]{Overview} \pnum -\indextext{range!counted}% -A counted view presents a view of the elements -of the counted range\iref{iterator.requirements.general} \countedrange{i}{n} -for an iterator \tcode{i} and non-negative integer \tcode{n}. +\tcode{concat_view} presents a view that concatenates all the underlying ranges. \pnum -\indexlibrarymember{counted}{views}% -The name \tcode{views::counted} denotes +The name \tcode{views::concat} denotes a customization point object\iref{customization.point.object}. -Let \tcode{E} and \tcode{F} be expressions, -let \tcode{T} be \tcode{decay_t}, and -let \tcode{D} be \tcode{iter_difference_t}. -If \tcode{decltype((F))} does not model -\tcode{\libconcept{convertible_to}}, -\tcode{views::counted(E, F)} is ill-formed. -\begin{note} -This case can result in substitution failure -when \tcode{views::counted(E, F)} -appears in the immediate context of a template instantiation. -\end{note} -Otherwise, \tcode{views::counted(E, F)} -is expression-equivalent to: - +Given a pack of subexpressions \tcode{Es...}, +the expression \tcode{views::concat(Es...)} is expression-equivalent to \begin{itemize} -\item -If \tcode{T} models \libconcept{contiguous_iterator}, -then \tcode{span(to_address(E), static_cast(static_-\linebreak{}cast(F)))}. +\item \tcode{views::all(Es...)} if \tcode{Es} is a pack with only one element +whose type models \libconcept{input_range}, +\item otherwise, \tcode{concat_view(Es...)}. +\end{itemize} +\begin{example} +\begin{codeblock} +vector v1{1, 2, 3}, v2{4, 5}, v3{}; +array a{6, 7, 8}; +auto s = views::single(9); +for (auto&& i : views::concat(v1, v2, v3, a, s)) { + print("{} ", i); // prints \tcode{1 2 3 4 5 6 7 8 9} +} +\end{codeblock} +\end{example} -\item -Otherwise, if \tcode{T} models \libconcept{random_access_iterator}, -then \tcode{subrange(E, E + static_cast(F))}, -except that \tcode{E} is evaluated only once. +\rSec3[range.concat.view]{Class template \tcode{concat_view}} -\item -Otherwise, -\tcode{subrange(counted_iterator(E, F), default_sentinel)}. -\end{itemize} +\indexlibraryglobal{concat_view}% +\begin{codeblock} +namespace std::ranges { + template + using @\exposidnc{concat-reference-t}@ = common_reference_t...>; // \expos + template + using @\exposidnc{concat-value-t}@ = common_type_t...>; // \expos + template + using @\exposidnc{concat-rvalue-reference-t}@ = // \expos + common_reference_t...>; -\rSec2[range.common]{Common view} + template + concept @\exposconcept{concat-indirectly-readable}@ = @\seebelow@; // \expos + template + concept @\exposconcept{concatable}@ = @\seebelow@; // \expos + template + concept @\exposconcept{concat-is-random-access}@ = @\seebelow@; // \expos + template + concept @\exposconcept{concat-is-bidirectional}@ = @\seebelow@; // \expos -\rSec3[range.common.overview]{Overview} + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && + @\exposconcept{concatable}@ + class concat_view : public view_interface> { -\pnum -\tcode{common_view} takes a view which has different types for -its iterator and sentinel and turns it into a view of the same -elements with an iterator and sentinel of the same type. + tuple @\exposidnc{views_}@; // \expos -\pnum -\begin{note} -\tcode{common_view} is useful for calling legacy algorithms that expect -a range's iterator and sentinel types to be the same. -\end{note} + // \ref{range.concat.iterator}, class template \tcode{concat_view::\exposid{iterator}} + template class @\exposidnc{iterator}@; // \expos -\pnum -\indexlibrarymember{common}{views}% -The name \tcode{views::common} denotes a -range adaptor object\iref{range.adaptor.object}. -Given a subexpression \tcode{E}, -the expression \tcode{views::common(E)} is expression-equivalent to: -\begin{itemize} -\item \tcode{views::all(E)}, - if \tcode{decltype((E))} models \libconcept{common_range} - and \tcode{views::all(E)} is a well-formed expression. + public: + constexpr concat_view() = default; + constexpr explicit concat_view(Views... views); -\item Otherwise, \tcode{common_view\{E\}}. -\end{itemize} + constexpr @\exposid{iterator}@ begin() requires (!(@\exposconcept{simple-view}@ && ...)); + constexpr @\exposid{iterator}@ begin() const + requires (@\libconcept{range}@ && ...) && @\exposconcept{concatable}@; -\pnum -\begin{example} -\begin{codeblock} -// Legacy algorithm: -template -size_t count(ForwardIterator first, ForwardIterator last); + constexpr auto end() requires (!(@\exposconcept{simple-view}@ && ...)); + constexpr auto end() const + requires (@\libconcept{range}@ && ...) && @\exposconcept{concatable}@; -template<@\libconcept{forward_range}@ R> -void my_algo(R&& r) { - auto&& common = views::common(r); - auto cnt = count(common.begin(), common.end()); - // ... + constexpr auto size() requires (@\libconcept{sized_range}@ && ...); + constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); + }; + + template + concat_view(R&&...) -> concat_view...>; } \end{codeblock} -\end{example} -\rSec3[range.common.view]{Class template \tcode{common_view}} +\begin{itemdecl} +template + concept @\defexposconcept{concat-indirectly-readable}@ = @\seebelow@; // \expos +\end{itemdecl} -\indexlibraryglobal{common_view}% -\indexlibrarymember{base}{common_view}% -\indexlibrarymember{size}{common_view}% -\indexlibrarymember{begin}{common_view}% -\indexlibrarymember{end}{common_view}% +\begin{itemdescr} +\pnum +The exposition-only \exposconcept{concat-indirectly-readable} concept +is equivalent to: \begin{codeblock} -namespace std::ranges { - template<@\libconcept{view}@ V> - requires (!@\libconcept{common_range}@ && @\libconcept{copyable}@>) - class common_view : public view_interface> { - private: - V @\exposid{base_}@ = V(); // \expos +template + concept @\defexposconcept{concat-indirectly-readable-impl}@ = // \expos + requires (const It it) { + { *it } -> @\libconcept{convertible_to}@; + { ranges::iter_move(it) } -> @\libconcept{convertible_to}@; + }; - public: - common_view() requires @\libconcept{default_initializable}@ = default; +template + concept @\exposconcept{concat-indirectly-readable}@ = // \expos + @\libconcept{common_reference_with}@<@\exposid{concat-reference-t}@&&, + @\exposid{concat-value-t}@&> && + @\libconcept{common_reference_with}@<@\exposid{concat-reference-t}@&&, + @\exposid{concat-rvalue-reference-t}@&&> && + @\libconcept{common_reference_with}@<@\exposid{concat-rvalue-reference-t}@&&, + @\exposid{concat-value-t}@ const&> && + (@\exposconcept{concat-indirectly-readable-impl}@<@\exposid{concat-reference-t}@, + @\exposid{concat-rvalue-reference-t}@, + iterator_t> && ...); +\end{codeblock} +\end{itemdescr} - constexpr explicit common_view(V r); +\begin{itemdecl} +template + concept @\defexposconcept{concatable}@ = @\seebelow@; // \expos +\end{itemdecl} - constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } +\begin{itemdescr} +\pnum +The exposition-only \exposconcept{concatable} concept is equivalent to: +\begin{codeblock} +template + concept @\exposconcept{concatable}@ = requires { // \expos + typename @\exposid{concat-reference-t}@; + typename @\exposid{concat-value-t}@; + typename @\exposid{concat-rvalue-reference-t}@; + } && @\exposconcept{concat-indirectly-readable}@; +\end{codeblock} +\end{itemdescr} - constexpr auto begin() { - if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) - return ranges::begin(@\exposid{base_}@); - else - return common_iterator, sentinel_t>(ranges::begin(@\exposid{base_}@)); - } +\begin{itemdecl} +template + concept @\defexposconcept{concat-is-random-access}@ = @\seebelow@; // \expos +\end{itemdecl} - constexpr auto begin() const requires @\libconcept{range}@ { - if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) - return ranges::begin(@\exposid{base_}@); - else - return common_iterator, sentinel_t>(ranges::begin(@\exposid{base_}@)); - } - - constexpr auto end() { - if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) - return ranges::begin(@\exposid{base_}@) + ranges::distance(@\exposid{base_}@); - else - return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); - } - - constexpr auto end() const requires @\libconcept{range}@ { - if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) - return ranges::begin(@\exposid{base_}@) + ranges::distance(@\exposid{base_}@); - else - return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); - } +\begin{itemdescr} +\pnum +Let \tcode{Fs} be the pack that consists of all elements of \tcode{Rs} +except the last element, +then \exposconceptx{concat-is-ran\-dom-access}{concat-is-random-access} +is equivalent to: +\begin{codeblock} +template + concept @\exposconcept{concat-is-random-access}@ = // \expos + @\exposconcept{all-random-access}@ && + (@\libconcept{common_range}@<@\exposid{maybe-const}@> && ...); +\end{codeblock} +\end{itemdescr} - constexpr auto size() requires @\libconcept{sized_range}@ { - return ranges::size(@\exposid{base_}@); - } - constexpr auto size() const requires @\libconcept{sized_range}@ { - return ranges::size(@\exposid{base_}@); - } - }; +\begin{itemdecl} +template + concept @\defexposconcept{concat-is-bidirectional}@ = @\seebelow@; // \expos +\end{itemdecl} - template - common_view(R&&) -> common_view>; -} +\begin{itemdescr} +\pnum +Let \tcode{Fs} be the pack that consists of all elements of \tcode{Rs} +except the last element, +then \exposconceptx{concat-is-bidirec\-tional}{concat-is-bidirectional} +is equivalent to: +\begin{codeblock} +template + concept @\exposconcept{concat-is-bidirectional}@ = // \expos + @\exposconcept{all-bidirectional}@ && + (@\libconcept{common_range}@<@\exposid{maybe-const}@> && ...); \end{codeblock} +\end{itemdescr} -\indexlibraryctor{common_view}% +\indexlibraryctor{concat_view}% \begin{itemdecl} -constexpr explicit common_view(V base); +constexpr explicit concat_view(Views... views); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{base_} with \tcode{std::move(base)}. +Initializes \exposid{views_} with \tcode{std::move(views)...}. \end{itemdescr} -\rSec2[range.reverse]{Reverse view} - -\rSec3[range.reverse.overview]{Overview} - -\pnum -\tcode{reverse_view} takes a bidirectional view and produces -another view that iterates the same elements in reverse order. +\indexlibrarymember{begin}{concat_view}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ begin() requires (!(@\exposconcept{simple-view}@ && ...)); +constexpr @\exposid{iterator}@ begin() const + requires (@\libconcept{range}@ && ...) && @\exposconcept{concatable}@; +\end{itemdecl} +\begin{itemdescr} \pnum -\indexlibrarymember{reverse}{views}% -The name \tcode{views::reverse} denotes a -range adaptor object\iref{range.adaptor.object}. -Given a subexpression \tcode{E}, the expression -\tcode{views::reverse(E)} is expression-equivalent to: -\begin{itemize} -\item - If the type of \tcode{E} is - a (possibly cv-qualified) specialization of \tcode{reverse_view}, - equivalent to \tcode{E.base()}. -\item - Otherwise, if the type of \tcode{E} is \cv{} \tcode{subrange, reverse_iterator, K>} - for some iterator type \tcode{I} and - value \tcode{K} of type \tcode{subrange_kind}, - \begin{itemize} - \item - if \tcode{K} is \tcode{subrange_kind::sized}, equivalent to: +\effects +Let \exposid{is-const} be +\tcode{true} for the const-qualified overload, and +\tcode{false} otherwise. +Equivalent to: \begin{codeblock} -subrange(E.end().base(), E.begin().base(), E.size()) +@\exposid{iterator}@<@\exposid{is-const}@> it(this, in_place_index<0>, ranges::begin(std::get<0>(@\exposid{views_}@))); +it.template @\exposid{satisfy}@<0>(); +return it; \end{codeblock} - \item - otherwise, equivalent to: +\end{itemdescr} + +\indexlibrarymember{end}{concat_view}% +\begin{itemdecl} +constexpr auto end() requires (!(@\exposconcept{simple-view}@ && ...)); +constexpr auto end() const + requires (@\libconcept{range}@ && ...) && @\exposconcept{concatable}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \exposid{is-const} be +\tcode{true} for the const-qualified overload, and +\tcode{false} otherwise. +Equivalent to: \begin{codeblock} -subrange(E.end().base(), E.begin().base()) +constexpr auto N = sizeof...(Views); +if constexpr (@\libconcept{common_range}@<@\exposid{maybe-const}@<@\exposid{is-const}@, Views...[N - 1]>>) { + return @\exposid{iterator}@<@\exposid{is-const}@>(this, in_place_index, + ranges::end(std::get(@\exposid{views_}@))); +} else { + return default_sentinel; +} \end{codeblock} - \end{itemize} - However, in either case \tcode{E} is evaluated only once. -\item - Otherwise, equivalent to \tcode{reverse_view\{E\}}. -\end{itemize} +\end{itemdescr} + +\indexlibrarymember{size}{concat_view}% +\begin{itemdecl} +constexpr auto size() requires (@\libconcept{sized_range}@ && ...); +constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); +\end{itemdecl} +\begin{itemdescr} \pnum -\begin{example} +\effects +Equivalent to: \begin{codeblock} -vector is {0,1,2,3,4}; -for (int i : is | views::reverse) - cout << i << ' '; // prints \tcode{4 3 2 1 0} +return apply( + [](auto... sizes) { + using CT = @\exposid{make-unsigned-like-t}@>; + return (CT(sizes) + ...); + }, + @\exposid{tuple-transform}@(ranges::size, @\exposid{views_}@)); \end{codeblock} -\end{example} +\end{itemdescr} -\rSec3[range.reverse.view]{Class template \tcode{reverse_view}} +\rSec3[range.concat.iterator]{Class \tcode{concat_view::\exposid{iterator}}} -\indexlibraryglobal{reverse_view}% -\indexlibrarymember{base}{reverse_view}% -\indexlibrarymember{size}{reverse_view}% +\indexlibrarymember{iterator}{concat_view}% +\indexlibraryglobal{concat_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{view}@ V> - requires @\libconcept{bidirectional_range}@ - class reverse_view : public view_interface> { - private: - V @\exposid{base_}@ = V(); // \expos + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && + @\exposconcept{concatable}@ + template + class concat_view::@\exposid{iterator}@ { public: - reverse_view() requires @\libconcept{default_initializable}@ = default; + using iterator_category = @\seebelow@; // not always present + using iterator_concept = @\seebelow@; + using value_type = @\exposid{concat-value-t}@<@\exposid{maybe-const}@...>; + using difference_type = common_type_t>...>; - constexpr explicit reverse_view(V r); + private: + using @\exposid{base-iter}@ = // \expos + variant>...>; - constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } + @\exposid{maybe-const}@* @\exposid{parent_}@ = nullptr; // \expos + @\exposid{base-iter}@ @\exposid{it_}@; // \expos - constexpr reverse_iterator> begin(); - constexpr reverse_iterator> begin() requires @\libconcept{common_range}@; - constexpr auto begin() const requires @\libconcept{common_range}@; + template + constexpr void @\exposid{satisfy}@(); // \expos + template + constexpr void @\exposid{prev}@(); // \expos - constexpr reverse_iterator> end(); - constexpr auto end() const requires @\libconcept{common_range}@; + template + constexpr void @\exposid{advance-fwd}@(difference_type offset, // \expos + difference_type steps); + template + constexpr void @\exposid{advance-bwd}@(difference_type offset, // \expos + difference_type steps); - constexpr auto size() requires @\libconcept{sized_range}@ { - return ranges::size(@\exposid{base_}@); - } + template + constexpr explicit @\exposid{iterator}@(@\exposid{maybe-const}@* parent, // \expos + Args&&... args) + requires @\libconcept{constructible_from}@<@\exposid{base-iter}@, Args&&...>; - constexpr auto size() const requires @\libconcept{sized_range}@ { - return ranges::size(@\exposid{base_}@); - } - }; + public: + @\exposid{iterator}@() = default; - template - reverse_view(R&&) -> reverse_view>; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && (@\libconcept{convertible_to}@, iterator_t> && ...); + + constexpr decltype(auto) operator*() const; + constexpr @\exposid{iterator}@& operator++(); + constexpr void operator++(int); + constexpr @\exposid{iterator}@ operator++(int) + requires @\exposconcept{all-forward}@; + constexpr @\exposid{iterator}@& operator--() + requires @\exposconcept{concat-is-bidirectional}@; + constexpr @\exposid{iterator}@ operator--(int) + requires @\exposconcept{concat-is-bidirectional}@; + constexpr @\exposid{iterator}@& operator+=(difference_type n) + requires @\exposconcept{concat-is-random-access}@; + constexpr @\exposid{iterator}@& operator-=(difference_type n) + requires @\exposconcept{concat-is-random-access}@; + constexpr decltype(auto) operator[](difference_type n) const + requires @\exposconcept{concat-is-random-access}@; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{equality_comparable}@>> && ...); + friend constexpr bool operator==(const @\exposid{iterator}@& it, default_sentinel_t); + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; + friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; + friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; + friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\exposconcept{all-random-access}@ && + (@\libconcept{three_way_comparable}@>> && ...)); + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& it, difference_type n) + requires @\exposconcept{concat-is-random-access}@; + friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& it) + requires @\exposconcept{concat-is-random-access}@; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& it, difference_type n) + requires @\exposconcept{concat-is-random-access}@; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{concat-is-random-access}@; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t) + requires @\seebelow@; + friend constexpr difference_type operator-(default_sentinel_t, const @\exposid{iterator}@& x) + requires @\seebelow@; + friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& it) noexcept(@\seebelow@); + friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept(@\seebelow@) + requires @\seebelow@; + }; } \end{codeblock} -\indexlibraryctor{reverse_view}% -\begin{itemdecl} -constexpr explicit reverse_view(V base); -\end{itemdecl} +\pnum +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +\begin{itemize} +\item +If +\tcode{\exposconcept{concat-is-random-access}} is modeled, +then \tcode{iterator_concept} denotes \tcode{ran\-dom_access_iterator_tag}. +\item +Otherwise, if +\tcode{\exposconcept{concat-is-bidirectional}} is modeled, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, if +\tcode{\exposconcept{all-forward}} is modeled, +then \tcode{iterator_concept} denotes \tcode{for\-ward_iterator_tag}. +\item +Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. +\end{itemize} -\begin{itemdescr} \pnum -\effects -Initializes \exposid{base_} with \tcode{std::move(base)}. -\end{itemdescr} +The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +if and only if +\tcode{\exposconcept{all-forward}} is modeled. +In that case, +\tcode{\exposid{iterator}::iterator_category} is defined as follows: -\indexlibrarymember{begin}{reverse_view}% +\begin{itemize} +\item +If +\tcode{is_reference_v<\exposid{concat-reference-t}<\exposid{maybe-const}...>>} +is \tcode{false}, +then \tcode{iter\-ator_category} denotes \tcode{input_iterator_tag}. + +\item +Otherwise, +let \tcode{Cs} denote the pack of types +\tcode{iterator_traits>>::iterator_category...}. +\begin{itemize} +\item +If +\tcode{(\libconcept{derived_from} \&\& ...) \&\& \exposconceptx{concat-is-random-ac-\linebreak{}cess}{concat-is-random-access}} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, if +\tcode{(\libconcept{derived_from} \&\& ...) \&\& \exposconceptx{concat-is-\linebreak{}bidirectional}{concat-is-bidirectional}} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{bidirectional_iter\-ator_tag}. +\item +Otherwise, if +\tcode{(\libconcept{derived_from} \&\& ...)} +is \tcode{true}, +\tcode{iterator_cate\-gory} denotes \tcode{forward_iterator_tag}. +\item +Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\end{itemize} +\end{itemize} + +\indexlibrarymember{\exposid{satisfy}}{concat_view::\exposid{iterator}}% \begin{itemdecl} -constexpr reverse_iterator> begin(); +template + constexpr void @\exposid{satisfy}@(); \end{itemdecl} \begin{itemdescr} \pnum -\returns +\effects +Equivalent to: \begin{codeblock} -make_reverse_iterator(ranges::next(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@))) +if constexpr (N < (sizeof...(Views) - 1)) { + if (std::get(@\exposid{it_}@) == ranges::end(std::get(@\exposid{parent_}@->@\exposid{views_}@))) { + @\exposid{it_}@.template emplace(ranges::begin(std::get(@\exposid{parent_}@->@\exposid{views_}@))); + @\exposid{satisfy}@(); + } +} \end{codeblock} - -\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{reverse_view} for use on subsequent calls. \end{itemdescr} -\indexlibrarymember{begin}{reverse_view}% +\indexlibrarymember{\exposid{prev}}{concat_view::\exposid{iterator}}% \begin{itemdecl} -constexpr reverse_iterator> begin() requires @\libconcept{common_range}@; -constexpr auto begin() const requires @\libconcept{common_range}@; +template + constexpr void @\exposid{prev}@(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return make_reverse_iterator(ranges::end(\exposid{base_}));} +Equivalent to: +\begin{codeblock} +if constexpr (N == 0) { + --std::get<0>(@\exposid{it_}@); +} else { + if (std::get(@\exposid{it_}@) == ranges::begin(std::get(@\exposid{parent_}@->@\exposid{views_}@))) { + @\exposid{it_}@.template emplace(ranges::end(std::get(@\exposid{parent_}@->@\exposid{views_}@))); + @\exposid{prev}@(); + } else { + --std::get(@\exposid{it_}@); + } +} +\end{codeblock} \end{itemdescr} -\indexlibrarymember{end}{reverse_view}% +\indexlibrarymember{\exposid{advance-fwd}}{concat_view::\exposid{iterator}}% \begin{itemdecl} -constexpr reverse_iterator> end(); -constexpr auto end() const requires @\libconcept{common_range}@; +template + constexpr void @\exposid{advance-fwd}@(difference_type offset, difference_type steps); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return make_reverse_iterator(ranges::begin(\exposid{base_}));} -\end{itemdescr} - +Equivalent to: +\begin{codeblock} +using underlying_diff_type = iter_difference_t>; +if constexpr (N == sizeof...(Views) - 1) { + std::get(@\exposid{it_}@) += static_cast(steps); +} else { + auto n_size = ranges::distance(std::get(@\exposid{parent_}@->@\exposid{views_}@)); + if (offset + steps < n_size) { + std::get(@\exposid{it_}@) += static_cast(steps); + } else { + @\exposid{it_}@.template emplace(ranges::begin(std::get(@\exposid{parent_}@->@\exposid{views_}@))); + @\exposid{advance-fwd}@(0, offset + steps - n_size); + } +} +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{\exposid{advance-bwd}}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +template + constexpr void @\exposid{advance-bwd}@(difference_type offset, difference_type steps); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +using underlying_diff_type = iter_difference_t>; +if constexpr (N == 0) { + std::get(@\exposid{it_}@) -= static_cast(steps); +} else { + if (offset >= steps) { + std::get(@\exposid{it_}@) -= static_cast(steps); + } else { + auto prev_size = ranges::distance(std::get(@\exposid{parent_}@->@\exposid{views_}@)); + @\exposid{it_}@.template emplace(ranges::end(std::get(@\exposid{parent_}@->@\exposid{views_}@))); + @\exposid{advance-bwd}@(prev_size, steps - offset); + } +} +\end{codeblock} +\end{itemdescr} + +\indexlibraryctor{concat_view::\exposid{iterator}}% +\begin{itemdecl} +template + constexpr explicit @\exposid{iterator}@(@\exposid{maybe-const}@* parent, + Args&&... args) + requires @\libconcept{constructible_from}@<@\exposid{base-iter}@, Args&&...>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{parent}, and +initializes \exposid{it_} with \tcode{std::forward(args)...}. +\end{itemdescr} + +\indexlibraryctor{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ it) + requires Const && + (@\libconcept{convertible_to}@, iterator_t> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{it.\exposid{it_}.valueless_by_exception()} is \tcode{false}. + +\pnum +\effects +Initializes \exposid{parent_} with \tcode{it.\exposid{parent_}}, and +let \tcode{$i$} be \tcode{it.\exposid{it_}.index()}, +initializes \exposid{it_} with +\tcode{\exposid{base-iter}(in_place_index<$i$>, std::get<$i$>(std::move(it.\exposid{it_})))}. +\end{itemdescr} + +\indexlibrarymember{operator*}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr decltype(auto) operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{it_}.valueless_by_exception()} is \tcode{false}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +using reference = @\exposid{concat-reference-t}@<@\exposid{maybe-const}@...>; +return std::visit([](auto&& it) -> reference { return *it; }, + @\exposid{it_}@); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator++}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{it_}.valueless_by_exception()} is \tcode{false}. + +\pnum +\effects +Let \tcode{$i$} be \tcode{\exposid{it_}.index()}. +Equivalent to: +\begin{codeblock} +++std::get<@$i$@>(@\exposid{it_}@); +@\exposid{satisfy}@<@$i$@>(); +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator++}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +++*this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator++}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int) + requires @\exposconcept{all-forward}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator--}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() + requires @\exposconcept{concat-is-bidirectional}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{it_}.valueless_by_exception()} is \tcode{false}. + +\pnum +\effects +Let \tcode{$i$} be \tcode{\exposid{it_}.index()}. +Equivalent to: +\begin{codeblock} +@\exposid{prev}@<@$i$@>(); +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator--}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) + requires @\exposconcept{concat-is-bidirectional}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+=}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type n) + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{it_}.valueless_by_exception()} is \tcode{false}. + +\pnum +\effects +Let \tcode{$i$} be \tcode{\exposid{it_}.index()}. +Equivalent to: +\begin{codeblock} +if (n > 0) { + @\exposid{advance-fwd}@<@$i$@>(std::get<@$i$@>(@\exposid{it_}@) - ranges::begin(std::get<@$i$@>(@\exposid{parent_}@->@\exposid{views_}@)), n); +} else if (n < 0) { + @\exposid{advance-bwd}@<@$i$@>(std::get<@$i$@>(@\exposid{it_}@) - ranges::begin(std::get<@$i$@>(@\exposid{parent_}@->@\exposid{views_}@)), -n); +} +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-=}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type n) + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +*this += -n; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator[]}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr decltype(auto) operator[](difference_type n) const + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return *((*this) + n); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator==}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{equality_comparable}@>> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x.\exposid{it_}.valueless_by_exception()} and +\tcode{y.\exposid{it_}.valueless_by_exception()} are each \tcode{false}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return x.@\exposid{it_}@ == y.@\exposid{it_}@; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator==}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& it, default_sentinel_t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{it.\exposid{it_}.valueless_by_exception()} is \tcode{false}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +constexpr auto last_idx = sizeof...(Views) - 1; +return it.@\exposid{it_}@.index() == last_idx && + std::get(it.@\exposid{it_}@) == ranges::end(std::get(it.@\exposid{parent_}@->@\exposid{views_}@)); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator<}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\exposconcept{all-random-access}@ && + (@\libconcept{three_way_comparable}@>> && ...)); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x.\exposid{it_}.valueless_by_exception()} and +\tcode{y.\exposid{it_}.valueless_by_exception()} are each \tcode{false}. + +\pnum +Let \tcode{$op$} be the operator. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return x.@\exposid{it_}@ @$op$@ y.@\exposid{it_}@; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& it, difference_type n) + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = it; +temp += n; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& it) + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return it + n; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& it, difference_type n) + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = it; +temp -= n; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{concat-is-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x.\exposid{it_}.valueless_by_exception()} and +\tcode{y.\exposid{it_}.valueless_by_exception()} are each \tcode{false}. + +\pnum +\effects +Let +\tcode{$i_\tcode{x}$} denote \tcode{x.\exposid{it_}.index()} and +\tcode{$i_\tcode{y}$} denote \tcode{y.\exposid{it_}.index()}. + +\begin{itemize} +\item +%FIXME This is hard to parse. +If \tcode{$i_\tcode{x}$ > $i_\tcode{y}$}, let +\tcode{$d_\tcode{y}$} be +\tcode{ranges::distance(std::get<$i_\tcode{y}$>(y.\exposid{it_}), ranges::end(std::get<$i_\tcode{y}$>(y.\linebreak{}\exposid{parent_}->\exposid{views_})))}, +\tcode{$d_\tcode{x}$} be +\tcode{ranges::distance(ranges::begin(std::get<$i_\tcode{x}$>(x.\exposid{parent_}->\linebreak{}\exposid{views_})), std::get<$i_\tcode{x}$>(x.\exposid{it_}))}. +Let \tcode{$s$} denote the sum of the sizes of all the ranges +\tcode{std::get<\linebreak{}$i$>(x.\exposid{parent_}->\exposid{views_})} +for every integer \tcode{$i$} in the range +\range{$i_\tcode{y}$ + 1}{$i_\tcode{x}$} +if there is any, and +\tcode{0} otherwise, +of type \tcode{difference_type}, +equivalent to: +\begin{codeblock} +return @$d_\tcode{y}$@ + @$s$@ + @$d_\tcode{x}$@; +\end{codeblock} + +\item +otherwise, if \tcode{$i_\tcode{x}$ < $i_\tcode{y}$} is \tcode{true}, +equivalent to: +\begin{codeblock} +return -(y - x); +\end{codeblock} + +\item +otherwise, equivalent to: +\begin{codeblock} +return std::get<@$i_\tcode{x}$@>(x.@\exposid{it_}@) - std::get<@$i_\tcode{y}$@>(y.@\exposid{it_}@); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{operator-}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t) + requires @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x.\exposid{it_}.valueless_by_exception()} is \tcode{false}. + +\pnum +\effects +%FIXME This is hard to parse. +Let +\tcode{$i_\tcode{x}$} denote \tcode{x.\exposid{it_}.index()}, +\tcode{$d_\tcode{x}$} be +\tcode{ranges::distance(std::get<$i_\tcode{x}$>(x.\exposid{it_}), ranges::\linebreak{}end(std::get<$i_\tcode{x}$>(x.\exposid{parent_}->\exposid{views_})))}. +Let \tcode{$s$} denote the sum of the sizes of all the ranges +\tcode{std::get<$i$>(x.\exposid{parent_}->\exposid{views_})} +for every integer \tcode{$i$} in the range +\range{$i_\tcode{x}$ + 1}{sizeof...(Views)} +if there is any, and +\tcode{0} otherwise, +of type difference_type, +equivalent to: +\begin{codeblock} +return -(@$d_\tcode{x}$@ + @$s$@); +\end{codeblock} + +\pnum +\remarks +Let \tcode{Fs} be the pack that consists of all elements of \tcode{Views} +except the first element, +%FIXME Do we want \grammarterm{expression} here? Same elsewhere? +the expression in the \grammarterm{requires-clause} is equivalent to: +\begin{codeblock} +(@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) && +(@\libconcept{sized_range}@<@\exposid{maybe-const}@> && ...) +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr difference_type operator-(default_sentinel_t, const @\exposid{iterator}@& x) + requires @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return -(x - default_sentinel); +\end{codeblock} + +\pnum +\remarks +Let \tcode{Fs} be the pack that consists of all elements of \tcode{Views} +except the first element, +the expression in the \grammarterm{requires-clause} is equivalent to: +\begin{codeblock} +(@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) && +(@\libconcept{sized_range}@<@\exposid{maybe-const}@> && ...) +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{iter_move}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr decltype(auto) iter_move(const @\exposid{iterator}@& it) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{it.\exposid{it_}.valueless_by_exception()} is \tcode{false}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return std::visit([](const auto& i) + -> @\exposid{concat-rvalue-reference-t}@<@\exposid{maybe-const}@...> { + return ranges::iter_move(i); + }, + it.@\exposid{it_}@); +\end{codeblock} + +\pnum +\remarks +The exception specification is equivalent to: +\begin{codeblock} +((is_nothrow_invocable_v>&> && + is_nothrow_convertible_v>, + @\exposid{concat-rvalue-reference-t}@<@\exposid{maybe-const}@...>>) && + ...) +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{iter_swap}{concat_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept(@\seebelow@) + requires @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x.\exposid{it_}.valueless_by_exception()} and +\tcode{y.\exposid{it_}.valueless_by_exception()} are each \tcode{false}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +std::visit([&](const auto& it1, const auto& it2) { + if constexpr (is_same_v) { + ranges::iter_swap(it1, it2); + } else { + ranges::swap(*x, *y); + } + }, + x.@\exposid{it_}@, y.@\exposid{it_}@); +\end{codeblock} + +\pnum +\remarks +The exception specification is equivalent to +\begin{codeblock} +(noexcept(ranges::swap(*x, *y)) && ... && noexcept(ranges::iter_swap(its, its))) +\end{codeblock} +where \tcode{its} is a pack of lvalues of type +%FIXME "respectively" doesn't make sense here. +\tcode{const iterator_t<\exposid{maybe-const}>} respectively. + +\par % This paragraph is part of the \remarks clause. +The expression in the \grammarterm{requires-clause} is equivalent to +\begin{codeblock} +@\libconcept{swappable_with}@, iter_reference_t<@\exposid{iterator}@>> && +(... && @\libconcept{indirectly_swappable}@>>) +\end{codeblock} +\end{itemdescr} + +\rSec2[range.counted]{Counted view} + +\pnum +\indextext{range!counted}% +A counted view presents a view of the elements +of the counted range\iref{iterator.requirements.general} \countedrange{i}{n} +for an iterator \tcode{i} and non-negative integer \tcode{n}. + +\pnum +\indexlibrarymember{counted}{views}% +The name \tcode{views::counted} denotes +a customization point object\iref{customization.point.object}. +Let \tcode{E} and \tcode{F} be expressions, +let \tcode{T} be \tcode{decay_t}, and +let \tcode{D} be \tcode{iter_difference_t}. +If \tcode{decltype((F))} does not model +\tcode{\libconcept{convertible_to}}, +\tcode{views::counted(E, F)} is ill-formed. +\begin{note} +This case can result in substitution failure +when \tcode{views::counted(E, F)} +appears in the immediate context of a template instantiation. +\end{note} +Otherwise, \tcode{views::counted(E, F)} +is expression-equivalent to: + +\begin{itemize} +\item +If \tcode{T} models \libconcept{contiguous_iterator}, +then \tcode{span(to_address(E), static_cast(static_-\linebreak{}cast(F)))}. + +\item +Otherwise, if \tcode{T} models \libconcept{random_access_iterator}, +then \tcode{subrange(E, E + static_cast(F))}, +except that \tcode{E} is evaluated only once. + +\item +Otherwise, +\tcode{subrange(counted_iterator(E, F), default_sentinel)}. +\end{itemize} + +\rSec2[range.common]{Common view} + +\rSec3[range.common.overview]{Overview} + +\pnum +\tcode{common_view} takes a view which has different types for +its iterator and sentinel and turns it into a view of the same +elements with an iterator and sentinel of the same type. + +\pnum +\begin{note} +\tcode{common_view} is useful for calling legacy algorithms that expect +a range's iterator and sentinel types to be the same. +\end{note} + +\pnum +\indexlibrarymember{common}{views}% +The name \tcode{views::common} denotes a +range adaptor object\iref{range.adaptor.object}. +Given a subexpression \tcode{E}, +the expression \tcode{views::common(E)} is expression-equivalent to: +\begin{itemize} +\item \tcode{views::all(E)}, + if \tcode{decltype((E))} models \libconcept{common_range} + and \tcode{views::all(E)} is a well-formed expression. + +\item Otherwise, \tcode{common_view\{E\}}. +\end{itemize} + +\pnum +\begin{example} +\begin{codeblock} +// Legacy algorithm: +template +size_t count(ForwardIterator first, ForwardIterator last); + +template<@\libconcept{forward_range}@ R> +void my_algo(R&& r) { + auto&& common = views::common(r); + auto cnt = count(common.begin(), common.end()); + // ... +} +\end{codeblock} +\end{example} + +\rSec3[range.common.view]{Class template \tcode{common_view}} + +\indexlibraryglobal{common_view}% +\indexlibrarymember{base}{common_view}% +\indexlibrarymember{size}{common_view}% +\indexlibrarymember{begin}{common_view}% +\indexlibrarymember{end}{common_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires (!@\libconcept{common_range}@ && @\libconcept{copyable}@>) + class common_view : public view_interface> { + private: + V @\exposid{base_}@ = V(); // \expos + + public: + common_view() requires @\libconcept{default_initializable}@ = default; + + constexpr explicit common_view(V r); + + 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}@) { + if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) + return ranges::begin(@\exposid{base_}@); + else + return common_iterator, sentinel_t>(ranges::begin(@\exposid{base_}@)); + } + + constexpr auto begin() const requires @\libconcept{range}@ { + if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) + return ranges::begin(@\exposid{base_}@); + else + return common_iterator, sentinel_t>(ranges::begin(@\exposid{base_}@)); + } + + constexpr auto end() requires (!@\exposconcept{simple-view}@) { + if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) + return ranges::begin(@\exposid{base_}@) + ranges::distance(@\exposid{base_}@); + else + return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); + } + + constexpr auto end() const requires @\libconcept{range}@ { + if constexpr (@\libconcept{random_access_range}@ && @\libconcept{sized_range}@) + return ranges::begin(@\exposid{base_}@) + ranges::distance(@\exposid{base_}@); + else + return common_iterator, sentinel_t>(ranges::end(@\exposid{base_}@)); + } + + constexpr auto size() requires @\libconcept{sized_range}@ { + return ranges::size(@\exposid{base_}@); + } + constexpr auto size() const requires @\libconcept{sized_range}@ { + return ranges::size(@\exposid{base_}@); + } + + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@ { + return ranges::reserve_hint(@\exposid{base_}@); + } + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@ { + return ranges::reserve_hint(@\exposid{base_}@); + } + }; + + template + common_view(R&&) -> common_view>; +} +\end{codeblock} + +\indexlibraryctor{common_view}% +\begin{itemdecl} +constexpr explicit common_view(V base); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}. +\end{itemdescr} + +\rSec2[range.reverse]{Reverse view} + +\rSec3[range.reverse.overview]{Overview} + +\pnum +\tcode{reverse_view} takes a bidirectional view and produces +another view that iterates the same elements in reverse order. + +\pnum +\indexlibrarymember{reverse}{views}% +The name \tcode{views::reverse} denotes a +range adaptor object\iref{range.adaptor.object}. +Given a subexpression \tcode{E}, the expression +\tcode{views::reverse(E)} is expression-equivalent to: +\begin{itemize} +\item + If the type of \tcode{E} is + a (possibly cv-qualified) specialization of \tcode{reverse_view}, + then \tcode{E.base()}. +\item + Otherwise, if the type of \tcode{E} is \cv{} \tcode{subrange, reverse_iterator, K>} + for some iterator type \tcode{I} and + value \tcode{K} of type \tcode{subrange_kind}, + \begin{itemize} + \item + if \tcode{K} is \tcode{subrange_kind::sized}, then +\tcode{subrange(E.end().base(), E.begin().base(), E.size())}; + \item + otherwise, \tcode{subrange(E.end().base(), E.begin().base())}. + \end{itemize} + However, in either case \tcode{E} is evaluated only once. +\item + Otherwise, \tcode{reverse_view\{E\}}. +\end{itemize} + +\pnum +\begin{example} +\begin{codeblock} +vector is {0,1,2,3,4}; +for (int i : is | views::reverse) + cout << i << ' '; // prints \tcode{4 3 2 1 0} +\end{codeblock} +\end{example} + +\rSec3[range.reverse.view]{Class template \tcode{reverse_view}} + +\indexlibraryglobal{reverse_view}% +\indexlibrarymember{base}{reverse_view}% +\indexlibrarymember{size}{reverse_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\libconcept{bidirectional_range}@ + class reverse_view : public view_interface> { + private: + V @\exposid{base_}@ = V(); // \expos + + public: + reverse_view() requires @\libconcept{default_initializable}@ = default; + + constexpr explicit reverse_view(V r); + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + + constexpr reverse_iterator> begin(); + constexpr reverse_iterator> begin() requires @\libconcept{common_range}@; + constexpr auto begin() const requires @\libconcept{common_range}@; + + constexpr reverse_iterator> end(); + constexpr auto end() const requires @\libconcept{common_range}@; + + constexpr auto size() requires @\libconcept{sized_range}@ { + return ranges::size(@\exposid{base_}@); + } + + constexpr auto size() const requires @\libconcept{sized_range}@ { + return ranges::size(@\exposid{base_}@); + } + + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@ { + return ranges::reserve_hint(@\exposid{base_}@); + } + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@ { + return ranges::reserve_hint(@\exposid{base_}@); + } + }; + + template + reverse_view(R&&) -> reverse_view>; +} +\end{codeblock} + +\indexlibraryctor{reverse_view}% +\begin{itemdecl} +constexpr explicit reverse_view(V base); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}. +\end{itemdescr} + +\indexlibrarymember{begin}{reverse_view}% +\begin{itemdecl} +constexpr reverse_iterator> begin(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +make_reverse_iterator(ranges::next(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@))) +\end{codeblock} + +\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{reverse_view} for use on subsequent calls. +\end{itemdescr} + +\indexlibrarymember{begin}{reverse_view}% +\begin{itemdecl} +constexpr reverse_iterator> begin() requires @\libconcept{common_range}@; +constexpr auto begin() const requires @\libconcept{common_range}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return make_reverse_iterator(ranges::end(\exposid{base_}));} +\end{itemdescr} + +\indexlibrarymember{end}{reverse_view}% +\begin{itemdecl} +constexpr reverse_iterator> end(); +constexpr auto end() const requires @\libconcept{common_range}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return make_reverse_iterator(ranges::begin(\exposid{base_}));} +\end{itemdescr} + \rSec2[range.as.const]{As const view} -\rSec3[range.as.const.overview]{Overview} +\rSec3[range.as.const.overview]{Overview} + +\pnum +\tcode{as_const_view} presents a view of an underlying sequence as constant. +That is, the elements of an \tcode{as_const_view} cannot be modified. + +\pnum +The name \tcode{views::as_const} denotes +a range adaptor object\iref{range.adaptor.object}. +Let \tcode{E} be an expression, +let \tcode{T} be \tcode{decltype((E))}, and +let \tcode{U} be \tcode{remove_cvref_t}. +The expression \tcode{views::as_const(E)} is expression-equivalent to: +\begin{itemize} +\item +If \tcode{views::all_t} models \libconcept{constant_range}, +then \tcode{views::all(E)}. +\item +Otherwise, +if \tcode{U} denotes \tcode{empty_view} +for some type \tcode{X}, then \tcode{auto(views::empty)}. +\item +Otherwise, +if \tcode{U} denotes \tcode{span} +for some type \tcode{X} and some extent \tcode{Extent}, +then \tcode{span(E)}. +\item +Otherwise, +if \tcode{U} denotes \tcode{ref_view} for some type \tcode{X} and +\tcode{const X} models \libconcept{constant_range}, +then \tcode{ref_view(static_cast(E.base()))}. +\item +Otherwise, +if \tcode{E} is an lvalue, +\tcode{const U} models \libconcept{constant_range}, and +\tcode{U} does not model \libconcept{view}, +then \tcode{ref_view(static_cast(E))}. +\item +Otherwise, \tcode{as_const_view(E)}. +\end{itemize} + +\pnum +\begin{example} +\begin{codeblock} +template<@\libconcept{constant_range}@ R> +void cant_touch_this(R&&); + +vector hammer = {'m', 'c'}; +span beat = hammer; +cant_touch_this(views::as_const(beat)); // will not modify the elements of \tcode{hammer} +\end{codeblock} +\end{example} + +\rSec3[range.as.const.view]{Class template \tcode{as_const_view}} + +\indexlibraryglobal{as_const_view::\exposid{iterator}}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\libconcept{input_range}@ + class as_const_view : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + + public: + as_const_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit as_const_view(V 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}@) { return ranges::cbegin(@\exposid{base_}@); } + constexpr auto begin() const requires @\libconcept{range}@ { return ranges::cbegin(@\exposid{base_}@); } + + constexpr auto end() requires (!@\exposconcept{simple-view}@) { return ranges::cend(@\exposid{base_}@); } + constexpr auto end() const requires @\libconcept{range}@ { return ranges::cend(@\exposid{base_}@); } + + constexpr auto size() requires @\libconcept{sized_range}@ { return ranges::size(@\exposid{base_}@); } + constexpr auto size() const requires @\libconcept{sized_range}@ { return ranges::size(@\exposid{base_}@); } + + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@ + { return ranges::reserve_hint(@\exposid{base_}@); } + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@ + { return ranges::reserve_hint(@\exposid{base_}@); } + }; + + template + as_const_view(R&&) -> as_const_view>; +} +\end{codeblock} + +\indexlibraryctor{as_const_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr explicit as_const_view(V base); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}. +\end{itemdescr} + +\rSec2[range.elements]{Elements view} + +\rSec3[range.elements.overview]{Overview} + +\pnum +\tcode{elements_view} takes +a view of tuple-like values and a \tcode{size_t}, and +produces a view with a value-type of the $N^\text{th}$ element +of the adapted view's value-type. + +\pnum +\indexlibrarymember{elements}{views}% +The name \tcode{views::elements} denotes +a range adaptor object\iref{range.adaptor.object}. +Given a subexpression \tcode{E} and constant expression \tcode{N}, +the expression \tcode{views::elements(E)} is expression-equivalent to +\tcode{elements_view, N>\{E\}}. + +\begin{example} +\begin{codeblock} +auto historical_figures = map{ + pair{"Lovelace"sv, 1815}, + {"Turing"sv, 1912}, + {"Babbage"sv, 1791}, + {"Hamilton"sv, 1936} +}; + +auto names = historical_figures | views::elements<0>; +for (auto&& name : names) { + cout << name << ' '; // prints \tcode{Babbage Hamilton Lovelace Turing } +} + +auto birth_years = historical_figures | views::elements<1>; +for (auto&& born : birth_years) { + cout << born << ' '; // prints \tcode{1791 1936 1815 1912 } +} +\end{codeblock} +\end{example} + +\pnum +\tcode{keys_view} is an alias for \tcode{elements_view}, and +is useful for extracting keys from associative containers. + +\begin{example} +\begin{codeblock} +auto names = historical_figures | views::keys; +for (auto&& name : names) { + cout << name << ' '; // prints \tcode{Babbage Hamilton Lovelace Turing } +} +\end{codeblock} +\end{example} + +\pnum +\tcode{values_view} is an alias for \tcode{elements_view}, and +is useful for extracting values from associative containers. + +\begin{example} +\begin{codeblock} +auto is_even = [](const auto x) { return x % 2 == 0; }; +cout << ranges::count_if(historical_figures | views::values, is_even); // prints \tcode{2} +\end{codeblock} +\end{example} + +\rSec3[range.elements.view]{Class template \tcode{elements_view}} + +\indexlibraryglobal{elements_view}% +\indexlibrarymember{base}{elements_view}% +\indexlibrarymember{begin}{elements_view}% +\indexlibrarymember{end}{elements_view}% +\indexlibrarymember{size}{elements_view}% +\begin{codeblock} +namespace std::ranges { + template + concept @\defexposconcept{has-tuple-element}@ = // \expos + @\exposconcept{tuple-like}@ && N < tuple_size_v; + + template + concept @\defexposconcept{returnable-element}@ = // \expos + is_reference_v || @\libconcept{move_constructible}@>; + + template<@\libconcept{input_range}@ V, size_t N> + requires @\libconcept{view}@ && @\exposconcept{has-tuple-element}@, N> && + @\exposconcept{has-tuple-element}@>, N> && + @\exposconcept{returnable-element}@, N> + class elements_view : public view_interface> { + public: + 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() && { return std::move(@\exposid{base_}@); } + + constexpr auto begin() requires (!@\exposconcept{simple-view}@) + { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@)); } + + constexpr auto begin() const requires @\libconcept{range}@ + { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@)); } + + constexpr auto end() requires (!@\exposconcept{simple-view}@ && !@\libconcept{common_range}@) + { return @\exposid{sentinel}@{ranges::end(@\exposid{base_}@)}; } + + constexpr auto end() requires (!@\exposconcept{simple-view}@ && @\libconcept{common_range}@) + { return @\exposid{iterator}@{ranges::end(@\exposid{base_}@)}; } + + constexpr auto end() const requires @\libconcept{range}@ + { return @\exposid{sentinel}@{ranges::end(@\exposid{base_}@)}; } + + constexpr auto end() const requires @\libconcept{common_range}@ + { return @\exposid{iterator}@{ranges::end(@\exposid{base_}@)}; } + + constexpr auto size() requires @\libconcept{sized_range}@ + { return ranges::size(@\exposid{base_}@); } + + constexpr auto size() const requires @\libconcept{sized_range}@ + { return ranges::size(@\exposid{base_}@); } + + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@ + { return ranges::reserve_hint(@\exposid{base_}@); } + + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@ + { return ranges::reserve_hint(@\exposid{base_}@); } + + private: + // \ref{range.elements.iterator}, class template \tcode{elements_view::\exposid{iterator}} + template class @\exposid{iterator}@; // \expos + + // \ref{range.elements.sentinel}, class template \tcode{elements_view::\exposid{sentinel}} + template class @\exposid{sentinel}@; // \expos + + V @\exposid{base_}@ = V(); // \expos + }; +} +\end{codeblock} + +\indexlibraryctor{elements_view}% +\begin{itemdecl} +constexpr explicit elements_view(V base); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}. +\end{itemdescr} + +\rSec3[range.elements.iterator]{Class template \tcode{elements_view::\exposid{iterator}}} + +\indexlibraryglobal{elements_view::\exposid{iterator}}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@ V, size_t N> + requires @\libconcept{view}@ && @\exposconcept{has-tuple-element}@, N> && + @\exposconcept{has-tuple-element}@>, N> && + @\exposconcept{returnable-element}@, N> + template + class elements_view::@\exposid{iterator}@ { + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + + iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos + + static constexpr decltype(auto) @\exposid{get-element}@(const iterator_t<@\exposid{Base}@>& i); // \expos + + public: + using iterator_concept = @\seebelow@; + using iterator_category = @\seebelow@; // not always present + using value_type = remove_cvref_t>>; + using difference_type = range_difference_t<@\exposid{Base}@>; + + @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; + constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; + + constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; + constexpr iterator_t<@\exposid{Base}@> base() &&; + + constexpr decltype(auto) operator*() const + { return @\exposid{get-element}@(@\exposid{current_}@); } + + constexpr @\exposid{iterator}@& operator++(); + constexpr void operator++(int); + constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; + + 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 decltype(auto) operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@> + { return @\exposid{get-element}@(@\exposid{current_}@ + n); } + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{equality_comparable}@>; + + 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}@& x, difference_type y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) + 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 +The member \grammarterm{typedef-name} \tcode{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, if \exposid{Base} models \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{Base} models \libconcept{forward_range}. +In that case, \tcode{iterator_category} is defined as follows: +Let \tcode{C} denote the type +\tcode{iterator_traits>::iterator_category}. +\begin{itemize} +\item +If \tcode{std::get(*\exposid{current_})} is an rvalue, +\tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\item +Otherwise, if \tcode{C} models \tcode{\libconcept{derived_from}}, +\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, \tcode{iterator_category} denotes \tcode{C}. +\end{itemize} + +\indexlibrarymember{\exposid{get-element}}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +static constexpr decltype(auto) @\exposid{get-element}@(const iterator_t<@\exposid{Base}@>& i); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if constexpr (is_reference_v>) { + return std::get(*i); +} else { + using E = remove_cv_t>>; + return static_cast(std::get(*i)); +} +\end{codeblock} +\end{itemdescr} + +\indexlibraryctor{elements_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{std::move(current)}. +\end{itemdescr} + +\indexlibraryctor{elements_view::\exposid{iterator}}% +\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_})}. +\end{itemdescr} + +\indexlibrarymember{base}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{current_};} +\end{itemdescr} + +\indexlibrarymember{base}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr iterator_t<@\exposid{Base}@> base() &&; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return std::move(\exposid{current_});} +\end{itemdescr} + +\indexlibrarymember{operator++}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +++@\exposid{current_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator++}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{++\exposid{current_}}. +\end{itemdescr} + +\indexlibrarymember{operator++}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = *this; +++@\exposid{current_}@; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator--}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +--@\exposid{current_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator--}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = *this; +--@\exposid{current_}@; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+=}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{current_}@ += n; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-=}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{current_}@ -= n; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator==}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{equality_comparable}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};} +\end{itemdescr} + +\indexlibrarymember{operator<}{elements_view::\exposid{iterator}}% +\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.\exposid{current_} < y.\exposid{current_};} +\end{itemdescr} + +\indexlibrarymember{operator>}{elements_view::\exposid{iterator}}% +\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} + +\indexlibrarymember{operator<=}{elements_view::\exposid{iterator}}% +\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} + +\indexlibrarymember{operator>=}{elements_view::\exposid{iterator}}% +\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} + +\indexlibrarymember{operator<=>}{elements_view::\exposid{iterator}}% +\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 +\effects +Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};} +\end{itemdescr} + +\indexlibrarymember{operator+}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{iterator}\{x\} += y;} +\end{itemdescr} + +\indexlibrarymember{operator+}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(difference_type 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} + +\indexlibrarymember{operator-}{elements_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} +\begin{itemdescr} \pnum -\tcode{as_const_view} presents a view of an underlying sequence as constant. -That is, the elements of an \tcode{as_const_view} cannot be modified. +\effects +Equivalent to: \tcode{return \exposid{iterator}\{x\} -= y;} +\end{itemdescr} -\pnum -The name \tcode{views::as_const} denotes -a range adaptor object\iref{range.adaptor.object}. -Let \tcode{E} be an expression, -let \tcode{T} be \tcode{decltype((E))}, and -let \tcode{U} be \tcode{remove_cvref_t}. -The expression \tcode{views::as_const(E)} is expression-equivalent to: -\begin{itemize} -\item -If \tcode{views::all_t} models \libconcept{constant_range}, -then \tcode{views::all(E)}. -\item -Otherwise, -if \tcode{U} denotes \tcode{empty_view} -for some type \tcode{X}, then \tcode{auto(views::empty)}. -\item -Otherwise, -if \tcode{U} denotes \tcode{span} -for some type \tcode{X} and some extent \tcode{Extent}, -then \tcode{span(E)}. -\item -Otherwise, -if \tcode{U} denotes \tcode{ref_view} for some type \tcode{X} and -\tcode{const X} models \libconcept{constant_range}, -then \tcode{ref_view(static_cast(E.base()))}. -\item -Otherwise, -if \tcode{E} is an lvalue, -\tcode{const U} models \libconcept{constant_range}, and -\tcode{U} does not model \libconcept{view}, -then \tcode{ref_view(static_cast(E))}. -\item -Otherwise, \tcode{as_const_view(E)}. -\end{itemize} +\indexlibrarymember{operator-}{elements_view::\exposid{iterator}}% +\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 -\begin{example} -\begin{codeblock} -template<@\libconcept{constant_range}@ R> -void cant_touch_this(R&&); - -vector hammer = {'m', 'c'}; -span beat = hammer; -cant_touch_this(views::as_const(beat)); // will not modify the elements of \tcode{hammer} -\end{codeblock} -\end{example} +\effects +Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{current_};} +\end{itemdescr} -\rSec3[range.as.const.view]{Class template \tcode{as_const_view}} +\rSec3[range.elements.sentinel]{Class template \tcode{elements_view::\exposid{sentinel}}} +\indexlibraryglobal{elements_view::\exposid{sentinel}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{view}@ V> - requires @\libconcept{input_range}@ - class as_const_view : public view_interface> { - V @\exposid{base_}@ = V(); // \expos + template<@\libconcept{input_range}@ V, size_t N> + requires @\libconcept{view}@ && @\exposconcept{has-tuple-element}@, N> && + @\exposconcept{has-tuple-element}@>, N> && + @\exposconcept{returnable-element}@, N> + template + class elements_view::@\exposid{sentinel}@ { + private: + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos public: - as_const_view() requires @\libconcept{default_initializable}@ = default; - constexpr explicit as_const_view(V base); + @\exposid{sentinel}@() = default; + constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; - constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } + constexpr sentinel_t<@\exposid{Base}@> base() const; - constexpr auto begin() requires (!@\exposconcept{simple-view}@) { return ranges::cbegin(@\exposid{base_}@); } - constexpr auto begin() const requires @\libconcept{range}@ { return ranges::cbegin(@\exposid{base_}@); } + template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); - constexpr auto end() requires (!@\exposconcept{simple-view}@) { return ranges::cend(@\exposid{base_}@); } - constexpr auto end() const requires @\libconcept{range}@ { return ranges::cend(@\exposid{base_}@); } + template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); - constexpr auto size() requires @\libconcept{sized_range}@ { return ranges::size(@\exposid{base_}@); } - constexpr auto size() const requires @\libconcept{sized_range}@ { return ranges::size(@\exposid{base_}@); } + template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); }; - - template - as_const_view(R&&) -> as_const_view>; } \end{codeblock} +\indexlibraryctor{elements_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr explicit as_const_view(V base); +constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{base_} with \tcode{std::move(base)}. +Initializes \exposid{end_} with \tcode{end}. \end{itemdescr} -\rSec2[range.elements]{Elements view} +\indexlibraryctor{elements_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +\end{itemdecl} -\rSec3[range.elements.overview]{Overview} +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{std::move(other.\exposid{end_})}. +\end{itemdescr} +\indexlibrarymember{base}{elements_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr sentinel_t<@\exposid{Base}@> base() const; +\end{itemdecl} + +\begin{itemdescr} \pnum -\tcode{elements_view} takes -a view of tuple-like values and a \tcode{size_t}, and -produces a view with a value-type of the $N^\text{th}$ element -of the adapted view's value-type. +\effects +Equivalent to: \tcode{return \exposid{end_};} +\end{itemdescr} + +\indexlibrarymember{operator==}{elements_view::\exposid{sentinel}}% +\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 -\indexlibrarymember{elements}{views}% -The name \tcode{views::elements} denotes -a range adaptor object\iref{range.adaptor.object}. -Given a subexpression \tcode{E} and constant expression \tcode{N}, -the expression \tcode{views::elements(E)} is expression-equivalent to -\tcode{elements_view, N>\{E\}}. +\effects +Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{end_};} +\end{itemdescr} -\begin{example} -\begin{codeblock} -auto historical_figures = map{ - pair{"Lovelace"sv, 1815}, - {"Turing"sv, 1912}, - {"Babbage"sv, 1791}, - {"Hamilton"sv, 1936} -}; +\indexlibrarymember{operator-}{elements_view::\exposid{sentinel}}% +\begin{itemdecl} +template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} -auto names = historical_figures | views::elements<0>; -for (auto&& name : names) { - cout << name << ' '; // prints \tcode{Babbage Hamilton Lovelace Turing } -} +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{end_};} +\end{itemdescr} -auto birth_years = historical_figures | views::elements<1>; -for (auto&& born : birth_years) { - cout << born << ' '; // prints \tcode{1791 1936 1815 1912 } -} -\end{codeblock} -\end{example} +\indexlibrarymember{operator-}{elements_view::\exposid{sentinel}}% +\begin{itemdecl} +template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); +\end{itemdecl} +\begin{itemdescr} \pnum -\tcode{keys_view} is an alias for \tcode{elements_view}, and -is useful for extracting keys from associative containers. +\effects +Equivalent to: \tcode{return x.\exposid{end_} - y.\exposid{current_};} +\end{itemdescr} -\begin{example} -\begin{codeblock} -auto names = historical_figures | views::keys; -for (auto&& name : names) { - cout << name << ' '; // prints \tcode{Babbage Hamilton Lovelace Turing } -} -\end{codeblock} -\end{example} +\rSec2[range.enumerate]{Enumerate view} + +\rSec3[range.enumerate.overview]{Overview} \pnum -\tcode{values_view} is an alias for \tcode{elements_view}, and -is useful for extracting values from associative containers. +\indexlibraryglobal{enumerate_view}% +\tcode{enumerate_view} is a view whose +elements represent both the position and value from +a sequence of elements. +\pnum +\indexlibrarymember{enumerate}{views}% +The name \tcode{views::enumerate} denotes a range adaptor object\iref{range.adaptor.object}. +Given a subexpression \tcode{E}, +the expression \tcode{views::enumerate(E)} is expression-equivalent to +\tcode{enumerate_view>(E)}. \begin{example} \begin{codeblock} -auto is_even = [](const auto x) { return x % 2 == 0; }; -cout << ranges::count_if(historical_figures | views::values, is_even); // prints \tcode{2} +vector vec{ 1, 2, 3 }; +for (auto [index, value] : views::enumerate(vec)) + cout << index << ":" << value << ' '; // prints \tcode{0:1 1:2 2:3} \end{codeblock} \end{example} -\rSec3[range.elements.view]{Class template \tcode{elements_view}} +\rSec3[range.enumerate.view]{Class template \tcode{enumerate_view}} -\indexlibraryglobal{elements_view}% -\indexlibrarymember{base}{elements_view}% -\indexlibrarymember{begin}{elements_view}% -\indexlibrarymember{end}{elements_view}% -\indexlibrarymember{size}{elements_view}% +\indexlibraryglobal{enumerate_view}% +\indexlibrarymember{begin}{enumerate_view}% +\indexlibrarymember{end}{enumerate_view}% +\indexlibrarymember{size}{enumerate_view}% \begin{codeblock} namespace std::ranges { - template - concept @\defexposconcept{has-tuple-element}@ = // \expos - @\exposconcept{tuple-like}@ && N < tuple_size_v; - - template - concept @\defexposconcept{returnable-element}@ = // \expos - is_reference_v || @\libconcept{move_constructible}@>; - - template<@\libconcept{input_range}@ V, size_t N> - requires @\libconcept{view}@ && @\exposconcept{has-tuple-element}@, N> && - @\exposconcept{has-tuple-element}@>, N> && - @\exposconcept{returnable-element}@, N> - class elements_view : public view_interface> { - public: - 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() && { return std::move(@\exposid{base_}@); } - - constexpr auto begin() requires (!@\exposconcept{simple-view}@) - { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@)); } + template<@\libconcept{view}@ V> + requires @\exposconcept{range-with-movable-references}@ + class enumerate_view : public view_interface> { + V @\exposidnc{base_}@ = V(); // \expos - constexpr auto begin() const requires @\libconcept{range}@ - { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@)); } + // \ref{range.enumerate.iterator}, class template \tcode{enumerate_view::\exposid{iterator}} + template + class @\exposidnc{iterator}@; // \expos - constexpr auto end() requires (!@\exposconcept{simple-view}@ && !@\libconcept{common_range}@) - { return @\exposid{sentinel}@{ranges::end(@\exposid{base_}@)}; } + // \ref{range.enumerate.sentinel}, class template \tcode{enumerate_view::\exposid{sentinel}} + template + class @\exposidnc{sentinel}@; // \expos - constexpr auto end() requires (!@\exposconcept{simple-view}@ && @\libconcept{common_range}@) - { return @\exposid{iterator}@{ranges::end(@\exposid{base_}@)}; } + public: + constexpr enumerate_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit enumerate_view(V base); - constexpr auto end() const requires @\libconcept{range}@ - { return @\exposid{sentinel}@{ranges::end(@\exposid{base_}@)}; } + constexpr auto begin() requires (!@\exposconcept{simple-view}@) + { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), 0); } + constexpr auto begin() const requires @\exposconcept{range-with-movable-references}@ + { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), 0); } - constexpr auto end() const requires @\libconcept{common_range}@ - { return @\exposid{iterator}@{ranges::end(@\exposid{base_}@)}; } + constexpr auto end() requires (!@\exposconcept{simple-view}@) { + if constexpr (@\libconcept{forward_range}@ && @\libconcept{common_range}@ && @\libconcept{sized_range}@) + return @\exposid{iterator}@(ranges::end(@\exposid{base_}@), ranges::distance(@\exposid{base_}@)); + else + return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); + } + constexpr auto end() const requires @\exposconcept{range-with-movable-references}@ { + if constexpr (@\libconcept{forward_range}@ && @\libconcept{common_range}@ && @\libconcept{sized_range}@) + return @\exposid{iterator}@(ranges::end(@\exposid{base_}@), ranges::distance(@\exposid{base_}@)); + else + return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); + } constexpr auto size() requires @\libconcept{sized_range}@ { return ranges::size(@\exposid{base_}@); } - constexpr auto size() const requires @\libconcept{sized_range}@ { return ranges::size(@\exposid{base_}@); } - private: - // \ref{range.elements.iterator}, class template \tcode{elements_view::\exposid{iterator}} - template class @\exposid{iterator}@; // \expos - - // \ref{range.elements.sentinel}, class template \tcode{elements_view::\exposid{sentinel}} - template class @\exposid{sentinel}@; // \expos + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@ + { return ranges::reserve_hint(@\exposid{base_}@); } + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@ + { return ranges::reserve_hint(@\exposid{base_}@); } - V @\exposid{base_}@ = V(); // \expos + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } }; + + template + enumerate_view(R&&) -> enumerate_view>; } \end{codeblock} -\indexlibraryctor{elements_view}% +\indexlibraryctor{enumerate_view}% \begin{itemdecl} -constexpr explicit elements_view(V base); +constexpr explicit enumerate_view(V base); \end{itemdecl} \begin{itemdescr} @@ -8974,38 +10893,45 @@ Initializes \exposid{base_} with \tcode{std::move(base)}. \end{itemdescr} -\rSec3[range.elements.iterator]{Class template \tcode{elements_view::\exposid{iterator}}} +\rSec3[range.enumerate.iterator]{Class template \tcode{enumerate_view::\exposid{iterator}}} +\indexlibraryglobal{enumerate_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{input_range}@ V, size_t N> - requires @\libconcept{view}@ && @\exposconcept{has-tuple-element}@, N> && - @\exposconcept{has-tuple-element}@>, N> && - @\exposconcept{returnable-element}@, N> + template<@\libconcept{view}@ V> + requires @\exposconcept{range-with-movable-references}@ template - class elements_view::@\exposid{iterator}@ { - using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos - - iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos - - static constexpr decltype(auto) @\exposid{get-element}@(const iterator_t<@\exposid{Base}@>& i); // \expos + class enumerate_view::@\exposid{iterator}@ { + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos public: + using iterator_category = input_iterator_tag; using iterator_concept = @\seebelow@; - using iterator_category = @\seebelow@; // not always present - using value_type = remove_cvref_t>>; using difference_type = range_difference_t<@\exposid{Base}@>; + using value_type = tuple>; + + private: + using @\exposidnc{reference-type}@ = // \expos + tuple>; + iterator_t<@\exposidnc{Base}@> @\exposidnc{current_}@ = iterator_t<@\exposidnc{Base}@>(); // \expos + difference_type @\exposidnc{pos_}@ = 0; // \expos + + constexpr explicit + @\exposidnc{iterator}@(iterator_t<@\exposidnc{Base}@> current, difference_type pos); // \expos + public: @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; - constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; constexpr iterator_t<@\exposid{Base}@> base() &&; - constexpr decltype(auto) operator*() const - { return @\exposid{get-element}@(@\exposid{current_}@); } + constexpr difference_type index() const noexcept; + + constexpr auto operator*() const { + return @\exposid{reference-type}@(@\exposid{pos_}@, *@\exposid{current_}@); + } constexpr @\exposid{iterator}@& operator++(); constexpr void operator++(int); @@ -9019,23 +10945,12 @@ constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - constexpr decltype(auto) operator[](difference_type n) const + constexpr auto operator[](difference_type n) const requires @\libconcept{random_access_range}@<@\exposid{Base}@> - { return @\exposid{get-element}@(@\exposid{current_}@ + n); } - - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@>; + { return @\exposid{reference-type}@(@\exposid{pos_}@ + n, @\exposid{current_}@[n]); } - 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 bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; + friend constexpr strong_ordering operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -9043,14 +10958,21 @@ requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) 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-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; + + friend constexpr auto iter_move(const @\exposid{iterator}@& i) + noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)) && + is_nothrow_move_constructible_v>) { + return tuple>(i.@\exposid{pos_}@, ranges::iter_move(i.@\exposid{current_}@)); + } }; } \end{codeblock} \pnum -The member \grammarterm{typedef-name} \tcode{iterator_concept} +The member \grammarterm{typedef-name} +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: \begin{itemize} \item @@ -9066,87 +10988,65 @@ 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{Base} models \libconcept{forward_range}. -In that case, \tcode{iterator_category} is defined as follows: -Let \tcode{C} denote the type -\tcode{iterator_traits>::iterator_category}. -\begin{itemize} -\item -If \tcode{std::get(*\exposid{current_})} is an rvalue, -\tcode{iterator_category} denotes \tcode{input_iterator_tag}. -\item -Otherwise, if \tcode{C} models \tcode{\libconcept{derived_from}}, -\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}. -\item -Otherwise, \tcode{iterator_category} denotes \tcode{C}. -\end{itemize} - +\indexlibraryctor{enumerate_view::\exposid{iterator}}% \begin{itemdecl} -static constexpr decltype(auto) @\exposid{get-element}@(const iterator_t<@\exposid{Base}@>& i); +constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, difference_type pos); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -if constexpr (is_reference_v>) { - return std::get(*i); -} else { - using E = remove_cv_t>>; - return static_cast(std::get(*i)); -} -\end{codeblock} +Initializes \exposid{current_} with \tcode{std::move(current)} and +\exposid{pos_} with \tcode{pos}. \end{itemdescr} -\indexlibraryctor{elements_view::\exposid{iterator}}% +\indexlibraryctor{enumerate_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); +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(current)}. +Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})} and +\exposid{pos_} with \tcode{i.\exposid{pos_}}. \end{itemdescr} -\indexlibraryctor{elements_view::\exposid{iterator}}% +\indexlibrarymember{base}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; +constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}. +Equivalent to: \tcode{return \exposid{current_};} \end{itemdescr} -\indexlibrarymember{base}{elements_view::\exposid{iterator}}% +\indexlibrarymember{base}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} -constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; +constexpr iterator_t<@\exposid{Base}@> base() &&; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{current_};} +Equivalent to: \tcode{return std::move(\exposid{current_});} \end{itemdescr} -\indexlibrarymember{base}{elements_view::\exposid{iterator}}% +\indexlibrarymember{index}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} -constexpr iterator_t<@\exposid{Base}@> base() &&; +constexpr difference_type index() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return std::move(\exposid{current_});} +Equivalent to: \tcode{return \exposid{pos_};} \end{itemdescr} -\indexlibrarymember{operator++}{elements_view::\exposid{iterator}}% +\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -9157,11 +11057,12 @@ Equivalent to: \begin{codeblock} ++@\exposid{current_}@; +++@\exposid{pos_}@; return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{elements_view::\exposid{iterator}}% +\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} constexpr void operator++(int); \end{itemdecl} @@ -9169,10 +11070,10 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{++\exposid{current_}}. +Equivalent to \tcode{++*this}. \end{itemdescr} -\indexlibrarymember{operator++}{elements_view::\exposid{iterator}}% +\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; \end{itemdecl} @@ -9183,12 +11084,12 @@ Equivalent to: \begin{codeblock} auto temp = *this; -++@\exposid{current_}@; +++*this; return temp; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{elements_view::\exposid{iterator}}% +\indexlibrarymember{operator--}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} @@ -9199,11 +11100,12 @@ Equivalent to: \begin{codeblock} --@\exposid{current_}@; +--@\exposid{pos_}@; return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{elements_view::\exposid{iterator}}% +\indexlibrarymember{operator--}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} @@ -9214,12 +11116,12 @@ Equivalent to: \begin{codeblock} auto temp = *this; ---@\exposid{current_}@; +--*this; return temp; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator+=}{elements_view::\exposid{iterator}}% +\indexlibrarymember{operator+=}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator+=(difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -9231,11 +11133,12 @@ Equivalent to: \begin{codeblock} @\exposid{current_}@ += n; +@\exposid{pos_}@ += n; return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-=}{elements_view::\exposid{iterator}}% +\indexlibrarymember{operator-=}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator-=(difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -9247,83 +11150,34 @@ Equivalent to: \begin{codeblock} @\exposid{current_}@ -= n; +@\exposid{pos_}@ -= n; return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator==}{elements_view::\exposid{iterator}}% -\begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@<@\exposid{Base}@>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};} -\end{itemdescr} - -\indexlibrarymember{operator<}{elements_view::\exposid{iterator}}% -\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.\exposid{current_} < y.\exposid{current_};} -\end{itemdescr} - -\indexlibrarymember{operator>}{elements_view::\exposid{iterator}}% -\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} - -\indexlibrarymember{operator<=}{elements_view::\exposid{iterator}}% -\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} - -\indexlibrarymember{operator>=}{elements_view::\exposid{iterator}}% +\indexlibrarymember{operator==}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} -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) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !(x < y);} +Equivalent to: \tcode{return x.\exposid{pos_} == y.\exposid{pos_};} \end{itemdescr} -\indexlibrarymember{operator<=>}{elements_view::\exposid{iterator}}% +\indexlibrarymember{operator<=>}{enumerate_view::\exposid{iterator}}% \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}@>; +friend constexpr strong_ordering operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};} +Equivalent to: \tcode{return x.\exposid{pos_} <=> y.\exposid{pos_};} \end{itemdescr} -\indexlibrarymember{operator+}{elements_view::\exposid{iterator}}% +\indexlibrarymember{operator+}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -9332,10 +11186,15 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{iterator}\{x\} += y;} +Equivalent to: +\begin{codeblock} +auto temp = x; +temp += y; +return temp; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator+}{elements_view::\exposid{iterator}}% +\indexlibrarymember{operator+}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -9347,7 +11206,7 @@ Equivalent to: \tcode{return y + x;} \end{itemdescr} -\indexlibrarymember{operator-}{elements_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; @@ -9356,38 +11215,40 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{iterator}\{x\} -= y;} +Equivalent to: +\begin{codeblock} +auto temp = x; +temp -= y; +return temp; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-}{elements_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{enumerate_view::\exposid{iterator}}% \begin{itemdecl} -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-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{current_};} +Equivalent to: \tcode{return x.\exposid{pos_} - y.\exposid{pos_};} \end{itemdescr} -\rSec3[range.elements.sentinel]{Class template \tcode{elements_view::\exposid{sentinel}}} +\rSec3[range.enumerate.sentinel]{Class template \tcode{enumerate_view::\exposid{sentinel}}} +\indexlibraryglobal{enumerate_view::\exposid{sentinel}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{input_range}@ V, size_t N> - requires @\libconcept{view}@ && @\exposconcept{has-tuple-element}@, N> && - @\exposconcept{has-tuple-element}@>, N> && - @\exposconcept{returnable-element}@, N> + template<@\libconcept{view}@ V> + requires @\exposconcept{range-with-movable-references}@ template - class elements_view::@\exposid{sentinel}@ { - private: - using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos - sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos + class enumerate_view::@\exposid{sentinel}@ { + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + sentinel_t<@\exposidnc{Base}@> @\exposidnc{end_}@ = sentinel_t<@\exposidnc{Base}@>(); // \expos + constexpr explicit @\exposidnc{sentinel}@(sentinel_t<@\exposidnc{Base}@> end); // \expos public: @\exposid{sentinel}@() = default; - constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; @@ -9410,7 +11271,7 @@ } \end{codeblock} -\indexlibraryctor{elements_view::\exposid{sentinel}}% +\indexlibraryctor{enumerate_view::\exposid{sentinel}}% \begin{itemdecl} constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); \end{itemdecl} @@ -9418,10 +11279,10 @@ \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{end}. +Initializes \exposid{end_} with \tcode{std::move(end)}. \end{itemdescr} -\indexlibraryctor{elements_view::\exposid{sentinel}}% +\indexlibraryctor{enumerate_view::\exposid{sentinel}}% \begin{itemdecl} constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; @@ -9433,7 +11294,7 @@ Initializes \exposid{end_} with \tcode{std::move(other.\exposid{end_})}. \end{itemdescr} -\indexlibrarymember{base}{elements_view::\exposid{sentinel}}% +\indexlibrarymember{base}{enumerate_view::\exposid{sentinel}}% \begin{itemdecl} constexpr sentinel_t<@\exposid{Base}@> base() const; \end{itemdecl} @@ -9444,7 +11305,7 @@ Equivalent to: \tcode{return \exposid{end_};} \end{itemdescr} -\indexlibrarymember{operator==}{elements_view::\exposid{sentinel}}% +\indexlibrarymember{operator==}{enumerate_view::\exposid{sentinel}}% \begin{itemdecl} template requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> @@ -9457,7 +11318,7 @@ Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{end_};} \end{itemdescr} -\indexlibrarymember{operator-}{elements_view::\exposid{sentinel}}% +\indexlibrarymember{operator-}{enumerate_view::\exposid{sentinel}}% \begin{itemdecl} template requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> @@ -9471,7 +11332,7 @@ Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{end_};} \end{itemdescr} -\indexlibrarymember{operator-}{elements_view::\exposid{sentinel}}% +\indexlibrarymember{operator-}{enumerate_view::\exposid{sentinel}}% \begin{itemdecl} template requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> @@ -9485,250 +11346,275 @@ Equivalent to: \tcode{return x.\exposid{end_} - y.\exposid{current_};} \end{itemdescr} -\rSec2[range.enumerate]{Enumerate view} +\rSec2[range.zip]{Zip view} -\rSec3[range.enumerate.overview]{Overview} +\rSec3[range.zip.overview]{Overview} \pnum -\indexlibraryglobal{enumerate_view}% -\tcode{enumerate_view} is a view whose -elements represent both the position and value from -a sequence of elements. +\indexlibraryglobal{zip_view}% +\tcode{zip_view} takes any number of views and +produces a view of tuples of references +to the corresponding elements of the constituent views. \pnum -\indexlibrarymember{enumerate}{views}% -The name \tcode{views::enumerate} denotes a range adaptor object\iref{range.adaptor.object}. -Given a subexpression \tcode{E}, -the expression \tcode{views::enumerate(E)} is expression-equivalent to -\tcode{enumerate_view>(E)}. +\indexlibrarymember{zip}{views}% +The name \tcode{views::zip} denotes +a customization point object\iref{customization.point.object}. +Given a pack of subexpressions \tcode{Es...}, +the expression \tcode{views::zip(Es...)} is expression-equivalent to +\begin{itemize} +\item +\tcode{auto(views::empty>)} +if \tcode{Es} is an empty pack, +\item +otherwise, \tcode{zip_view...>(Es...)}. +\end{itemize} + \begin{example} \begin{codeblock} -vector vec{ 1, 2, 3 }; -for (auto [index, value] : views::enumerate(vec)) - cout << index << ":" << value << ' '; // prints \tcode{0:1 1:2 2:3} +vector v = {1, 2}; +list l = {'a', 'b', 'c'}; + +auto z = views::zip(v, l); +range_reference_t f = z.front(); // \tcode{f} is a \tcode{tuple} + // that refers to the first element of \tcode{v} and \tcode{l} + +for (auto&& [x, y] : z) { + cout << '(' << x << ", " << y << ") "; // prints \tcode{(1, a) (2, b)} +} \end{codeblock} \end{example} -\rSec3[range.enumerate.view]{Class template \tcode{enumerate_view}} +\rSec3[range.zip.view]{Class template \tcode{zip_view}} -\indexlibrarymember{begin}{enumerate_view}% -\indexlibrarymember{end}{enumerate_view}% -\indexlibrarymember{size}{enumerate_view}% +\indexlibraryglobal{zip_view}% +\indexlibrarymember{begin}{zip_view}% +\indexlibrarymember{end}{zip_view}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{view}@ V> - requires @\exposconcept{range-with-movable-references}@ - class enumerate_view : public view_interface> { - V @\exposidnc{base_}@ = V(); // \expos + template + concept @\defexposconcept{zip-is-common}@ = // \expos + (sizeof...(Rs) == 1 && (@\libconcept{common_range}@ && ...)) || + (!(@\libconcept{bidirectional_range}@ && ...) && (@\libconcept{common_range}@ && ...)) || + ((@\libconcept{random_access_range}@ && ...) && (@\libconcept{sized_range}@ && ...)); - // \ref{range.enumerate.iterator}, class template \tcode{enumerate_view::\exposid{iterator}} - template - class @\exposidnc{iterator}@; // \expos + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) + class zip_view : public view_interface> { + tuple @\exposid{views_}@; // \expos - // \ref{range.enumerate.sentinel}, class template \tcode{enumerate_view::\exposid{sentinel}} - template - class @\exposidnc{sentinel}@; // \expos + // \ref{range.zip.iterator}, class template \tcode{zip_view::\exposid{iterator}} + template class @\exposidnc{iterator}@; // \expos - public: - constexpr enumerate_view() requires @\libconcept{default_initializable}@ = default; - constexpr explicit enumerate_view(V base); + // \ref{range.zip.sentinel}, class template \tcode{zip_view::\exposid{sentinel}} + template class @\exposidnc{sentinel}@; // \expos - constexpr auto begin() requires (!@\exposconcept{simple-view}@) - { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), 0); } - constexpr auto begin() const requires @\exposconcept{range-with-movable-references}@ - { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), 0); } + public: + zip_view() = default; + constexpr explicit zip_view(Views... views); - constexpr auto end() requires (!@\exposconcept{simple-view}@) { - if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) - return @\exposid{iterator}@(ranges::end(@\exposid{base_}@), ranges::distance(@\exposid{base_}@)); - else - return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); + constexpr auto begin() requires (!(@\exposconcept{simple-view}@ && ...)) { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@)); } - constexpr auto end() const requires @\exposconcept{range-with-movable-references}@ { - if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) - return @\exposid{iterator}@(ranges::end(@\exposid{base_}@), ranges::distance(@\exposid{base_}@)); - else - return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); + constexpr auto begin() const requires (@\libconcept{range}@ && ...) { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@)); } - constexpr auto size() requires @\libconcept{sized_range}@ - { return ranges::size(@\exposid{base_}@); } - constexpr auto size() const requires @\libconcept{sized_range}@ - { return ranges::size(@\exposid{base_}@); } + constexpr auto end() requires (!(@\exposconcept{simple-view}@ && ...)) { + if constexpr (!@\exposconcept{zip-is-common}@) { + return @\exposid{sentinel}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); + } else if constexpr ((@\libconcept{random_access_range}@ && ...)) { + return begin() + iter_difference_t<@\exposid{iterator}@>(size()); + } else { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); + } + } - constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } + constexpr auto end() const requires (@\libconcept{range}@ && ...) { + if constexpr (!@\exposconcept{zip-is-common}@) { + return @\exposid{sentinel}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); + } else if constexpr ((@\libconcept{random_access_range}@ && ...)) { + return begin() + iter_difference_t<@\exposid{iterator}@>(size()); + } else { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); + } + } + + constexpr auto size() requires (@\libconcept{sized_range}@ && ...); + constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); }; - template - enumerate_view(R&&) -> enumerate_view>; + template + zip_view(Rs&&...) -> zip_view...>; } \end{codeblock} +\pnum +Two \tcode{zip_view} objects have the same underlying sequence if and only if +the corresponding elements of \exposid{views_} are equal\iref{concepts.equality} +and have the same underlying sequence. +\begin{note} +In particular, comparison of iterators obtained from \tcode{zip_view} objects +that do not have the same underlying sequence +is not required to produce meaningful results\iref{iterator.concept.forward}. +\end{note} + +\indexlibraryctor{zip_view}% \begin{itemdecl} -constexpr explicit enumerate_view(V base); +constexpr explicit zip_view(Views... views); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{base_} with \tcode{std::move(base)}. +Initializes \exposid{views_} with \tcode{std::move(views)...}. \end{itemdescr} -\rSec3[range.enumerate.iterator]{Class template \tcode{enumerate_view::\exposid{iterator}}} +\indexlibrarymember{size}{zip_view}% +\begin{itemdecl} +constexpr auto size() requires (@\libconcept{sized_range}@ && ...); +constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); +\end{itemdecl} -\indexlibraryglobal{enumerate_view::\exposid{iterator}}% +\begin{itemdescr} +\pnum +\effects +Equivalent to: \begin{codeblock} -namespace std::ranges { - template<@\libconcept{view}@ V> - requires @\exposconcept{range-with-movable-references}@ - template - class enumerate_view::@\exposid{iterator}@ { - using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos - - public: - using iterator_category = input_iterator_tag; - using iterator_concept = @\seebelow@; - using difference_type = range_difference_t<@\exposid{Base}@>; - using value_type = tuple>; - - private: - using @\exposidnc{reference-type}@ = // \expos - tuple>; - iterator_t<@\exposidnc{Base}@> @\exposidnc{current_}@ = iterator_t<@\exposidnc{Base}@>(); // \expos - difference_type @\exposidnc{pos_}@ = 0; // \expos +return apply([](auto... sizes) { + using CT = @\exposid{make-unsigned-like-t}@>; + return ranges::min({CT(sizes)...}); +}, @\exposid{tuple-transform}@(ranges::size, @\exposid{views_}@)); +\end{codeblock} +\end{itemdescr} - constexpr explicit - @\exposidnc{iterator}@(iterator_t<@\exposidnc{Base}@> current, difference_type pos); // \expos +\rSec3[range.zip.iterator]{Class template \tcode{zip_view::\exposid{iterator}}} +\indexlibraryglobal{zip_view::\exposid{iterator}}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) + template + class zip_view::@\exposid{iterator}@ { + tuple>...> @\exposid{current_}@;@\itcorr[-1]@ // \expos + constexpr explicit @\exposidnc{iterator}@(tuple>...>); + // \expos public: - @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; - constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; - - constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; - constexpr iterator_t<@\exposid{Base}@> base() &&; - - constexpr difference_type index() const noexcept; + using iterator_category = input_iterator_tag; // not always present + using iterator_concept = @\seebelow@; + using value_type = tuple>...>; + using difference_type = common_type_t>...>; - constexpr auto operator*() const { - return @\exposid{reference-type}@(@\exposid{pos_}@, *@\exposid{current_}@); - } + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && (@\libconcept{convertible_to}@, iterator_t> && ...); + constexpr auto operator*() const; constexpr @\exposid{iterator}@& operator++(); constexpr void operator++(int); - constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator++(int) requires @\exposconcept{all-forward}@; - 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--() requires @\exposconcept{all-bidirectional}@; + constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{all-bidirectional}@; constexpr @\exposid{iterator}@& operator+=(difference_type x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + requires @\exposconcept{all-random-access}@; constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + requires @\exposconcept{all-random-access}@; constexpr auto operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@> - { return @\exposid{reference-type}@(@\exposid{pos_}@ + n, @\exposid{current_}@[n]); } + requires @\exposconcept{all-random-access}@; - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; - friend constexpr strong_ordering operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{equality_comparable}@>> && ...); - friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; - friend constexpr auto iter_move(const @\exposid{iterator}@& i) - noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)) && - is_nothrow_move_constructible_v>) { - return tuple>(i.@\exposid{pos_}@, ranges::iter_move(i.@\exposid{current_}@)); - } + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\exposconcept{all-random-access}@; + friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\exposconcept{all-random-access}@; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\exposconcept{all-random-access}@; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...); + + friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); + + friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires (@\libconcept{indirectly_swappable}@>> && ...); }; } \end{codeblock} \pnum -The member \grammarterm{typedef-name} -\tcode{\exposid{iterator}::iterator_concept} -is defined as follows: +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: \begin{itemize} \item -If \exposid{Base} models \libconcept{random_access_range}, +If \tcode{\exposconcept{all-random-access}} is modeled, then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. \item -Otherwise, if \exposid{Base} models \libconcept{bidirectional_range}, +Otherwise, +if \tcode{\exposconcept{all-bidirectional}} is modeled, then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. \item -Otherwise, if \exposid{Base} models \libconcept{forward_range}, -then \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. +Otherwise, +if \tcode{\exposconcept{all-forward}} is modeled, +then \tcode{iterator_concept} denotes \tcode{for\-ward_iterator_tag}. \item Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. \end{itemize} -\indexlibraryctor{enumerate_view::\exposid{iterator}}% -\begin{itemdecl} -constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, difference_type pos); -\end{itemdecl} - -\begin{itemdescr} \pnum -\effects -Initializes \exposid{current_} with \tcode{std::move(current)} and -\exposid{pos_} with \tcode{pos}. -\end{itemdescr} - -\indexlibraryctor{enumerate_view::\exposid{iterator}}% -\begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; -\end{itemdecl} +\tcode{\exposid{iterator}::iterator_category} is present +if and only if \tcode{\exposconcept{all-forward}} is modeled. -\begin{itemdescr} \pnum -\effects -Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})} and -\exposid{pos_} with \tcode{i.\exposid{pos_}}. -\end{itemdescr} +If the invocation of any non-const member function of \exposid{iterator} +exits via an exception, +the iterator acquires a singular value. -\indexlibrarymember{base}{enumerate_view::\exposid{iterator}}% +\indexlibraryctor{zip_view::\exposid{iterator}}% \begin{itemdecl} -constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; +constexpr explicit @\exposid{iterator}@(tuple>...> current); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{current_};} +Initializes \exposid{current_} with \tcode{std::move(current)}. \end{itemdescr} -\indexlibrarymember{base}{enumerate_view::\exposid{iterator}}% +\indexlibraryctor{zip_view::\exposid{iterator}}% \begin{itemdecl} -constexpr iterator_t<@\exposid{Base}@> base() &&; +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && (@\libconcept{convertible_to}@, iterator_t> && ...); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return std::move(\exposid{current_});} +Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}. \end{itemdescr} -\indexlibrarymember{index}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{operator*}{izip_view::\exposid{iterator}}% \begin{itemdecl} -constexpr difference_type index() const noexcept; +constexpr auto operator*() const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{pos_};} +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{operator++}{izip_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -9738,13 +11624,12 @@ \effects Equivalent to: \begin{codeblock} -++@\exposid{current_}@; -++@\exposid{pos_}@; +@\exposid{tuple-for-each}@([](auto& i) { ++i; }, @\exposid{current_}@); return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{operator++}{izip_view::\exposid{iterator}}% \begin{itemdecl} constexpr void operator++(int); \end{itemdecl} @@ -9755,9 +11640,9 @@ Equivalent to \tcode{++*this}. \end{itemdescr} -\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{operator++}{izip_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@ operator++(int) requires @\exposconcept{all-forward}@; \end{itemdecl} \begin{itemdescr} @@ -9765,15 +11650,15 @@ \effects Equivalent to: \begin{codeblock} -auto temp = *this; +auto tmp = *this; ++*this; -return temp; +return tmp; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{operator--}{izip_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@& operator--() requires @\exposconcept{all-bidirectional}@; \end{itemdecl} \begin{itemdescr} @@ -9781,15 +11666,14 @@ \effects Equivalent to: \begin{codeblock} ---@\exposid{current_}@; ---@\exposid{pos_}@; +@\exposid{tuple-for-each}@([](auto& i) { --i; }, @\exposid{current_}@); return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{operator--}{izip_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{all-bidirectional}@; \end{itemdecl} \begin{itemdescr} @@ -9797,16 +11681,16 @@ \effects Equivalent to: \begin{codeblock} -auto temp = *this; +auto tmp = *this; --*this; -return temp; +return tmp; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator+=}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{operator+=}{izip_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\exposconcept{all-random-access}@; \end{itemdecl} \begin{itemdescr} @@ -9814,16 +11698,15 @@ \effects Equivalent to: \begin{codeblock} -@\exposid{current_}@ += n; -@\exposid{pos_}@ += n; +@\exposid{tuple-for-each}@([&](I& i) { i += iter_difference_t(x); }, @\exposid{current_}@); return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-=}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{operator-=}{izip_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator-=(difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\exposconcept{all-random-access}@; \end{itemdecl} \begin{itemdescr} @@ -9831,38 +11714,73 @@ \effects Equivalent to: \begin{codeblock} -@\exposid{current_}@ -= n; -@\exposid{pos_}@ -= n; +@\exposid{tuple-for-each}@([&](I& i) { i -= iter_difference_t(x); }, @\exposid{current_}@); return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator==}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{operator[]}{izip_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; +constexpr auto operator[](difference_type n) const + requires @\exposconcept{all-random-access}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{pos_} == y.\exposid{pos_};} +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@([&](I& i) -> decltype(auto) { + return i[iter_difference_t(n)]; +}, @\exposid{current_}@); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator<=>}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{operator==}{izip_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr strong_ordering operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{equality_comparable}@>> && ...); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return x.\exposid{pos_} <=> y.\exposid{pos_};} +\returns +\begin{itemize} +\item +\tcode{x.\exposid{current_} == y.\exposid{current_}} +if \tcode{\exposconcept{all-bidirectional}} is \tcode{true}. +\item +Otherwise, \tcode{true} +if there exists an integer $0 \leq i < \tcode{sizeof...(Views)}$ +such that \tcode{bool(std::\brk{}get<$i$>(x.\exposid{current_}) == +std::get<$i$>(y.\exposid{current_}))} is \tcode{true}. +\begin{note} +This allows \tcode{zip_view} to model \libconcept{common_range} +when all constituent views model \libconcept{common_range}. +\end{note} +\item +Otherwise, \tcode{false}. +\end{itemize} \end{itemdescr} -\indexlibrarymember{operator+}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{operator<=>}{izip_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +\end{itemdescr} + +\indexlibrarymember{operator+}{izip_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\exposconcept{all-random-access}@; +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\exposconcept{all-random-access}@; \end{itemdecl} \begin{itemdescr} @@ -9870,28 +11788,49 @@ \effects Equivalent to: \begin{codeblock} -auto temp = x; -temp += y; -return temp; +auto r = i; +r += n; +return r; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator+}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{izip_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\exposconcept{all-random-access}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return y + x;} +Equivalent to: +\begin{codeblock} +auto r = i; +r -= n; +return r; +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{izip_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) - 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{maybe-const}@>> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{\exposid{DIST}($i$)} be \tcode{difference_type(std::get<$i$>(x.\exposid{current_}) - std::get<$i$>(y.\exposid{current_}))}. + +\pnum +\returns +The value with the smallest absolute value among \tcode{\exposid{DIST}($n$)} +for all integers $0 \leq n < \tcode{sizeof...(Views)}$. +\end{itemdescr} + +\indexlibrarymember{iter_move}{izip_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} @@ -9899,396 +11838,423 @@ \effects Equivalent to: \begin{codeblock} -auto temp = x; -temp -= y; -return temp; +return @\exposid{tuple-transform}@(ranges::iter_move, i.@\exposid{current_}@); +\end{codeblock} + +\pnum +\remarks +The exception specification is equivalent to: +\begin{codeblock} +(noexcept(ranges::iter_move(declval>&>())) && ...) && +(is_nothrow_move_constructible_v>> && ...) \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-}{enumerate_view::\exposid{iterator}}% +\indexlibrarymember{iter_swap}{izip_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; +friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires (@\libconcept{indirectly_swappable}@>> && ...); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{pos_} - y.\exposid{pos_};} +For every integer $0 \leq i < \tcode{sizeof...(Views)}$, +performs: +\begin{codeblock} +ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@)) +\end{codeblock} + +\pnum +\remarks +The exception specification is equivalent to +the logical \logop{and} of the following expressions: +\begin{codeblock} +noexcept(ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@))) +\end{codeblock} +for every integer $0 \leq i < \tcode{sizeof...(Views)}$. \end{itemdescr} -\rSec3[range.enumerate.sentinel]{Class template \tcode{enumerate_view::\exposid{sentinel}}} +\rSec3[range.zip.sentinel]{Class template \tcode{zip_view::\exposid{sentinel}}} -\indexlibraryglobal{enumerate_view::\exposid{sentinel}}% +\indexlibraryglobal{zip_view::\exposid{sentinel}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{view}@ V> - requires @\exposconcept{range-with-movable-references}@ + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) template - class enumerate_view::@\exposid{sentinel}@ { - using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos - sentinel_t<@\exposidnc{Base}@> @\exposidnc{end_}@ = sentinel_t<@\exposidnc{Base}@>(); // \expos - constexpr explicit @\exposidnc{sentinel}@(sentinel_t<@\exposidnc{Base}@> end); // \expos - + class zip_view::@\exposid{sentinel}@ { + tuple>...> @\exposid{end_}@;@\itcorr[-1]@ // \expos + constexpr explicit @\exposidnc{sentinel}@(tuple>...> end); + // \expos public: @\exposid{sentinel}@() = default; - constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) - requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; - - constexpr sentinel_t<@\exposid{Base}@> base() const; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && (@\libconcept{convertible_to}@, sentinel_t> && ...); template - requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + requires (@\libconcept{sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> - friend constexpr range_difference_t<@\exposid{maybe-const}@> + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) + friend constexpr common_type_t>...> operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) + friend constexpr common_type_t>...> + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); }; } \end{codeblock} -\indexlibraryctor{enumerate_view::\exposid{sentinel}}% -\begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \exposid{end_} with \tcode{std::move(end)}. -\end{itemdescr} - -\indexlibraryctor{enumerate_view::\exposid{sentinel}}% +\indexlibraryctor{zip_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) - requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +constexpr explicit @\exposid{sentinel}@(tuple>...> end); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{std::move(other.\exposid{end_})}. +Initializes \exposid{end_} with \tcode{end}. \end{itemdescr} -\indexlibrarymember{base}{enumerate_view::\exposid{sentinel}}% +\indexlibraryctor{zip_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr sentinel_t<@\exposid{Base}@> base() const; +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && (@\libconcept{convertible_to}@, sentinel_t> && ...); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{end_};} +Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}. \end{itemdescr} -\indexlibrarymember{operator==}{enumerate_view::\exposid{sentinel}}% +\indexlibrarymember{operator==}{zip_view::\exposid{sentinel}}% \begin{itemdecl} template - requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + requires (@\libconcept{sentinel_for}@>, + iterator_t>> && ...) friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{end_};} +\returns +\tcode{true} if there exists an integer $0 \leq i < \tcode{sizeof...(Views)}$ +such that \tcode{bool(std::get<$i$>(x.\brk{}\exposid{current_}) == +std::get<$i$>(y.\exposid{end_}))} is \tcode{true}. +Otherwise, \tcode{false}. \end{itemdescr} -\indexlibrarymember{operator-}{enumerate_view::\exposid{sentinel}}% +\indexlibrarymember{operator-}{zip_view::\exposid{sentinel}}% \begin{itemdecl} template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> -friend constexpr range_difference_t<@\exposid{maybe-const}@> + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) +friend constexpr common_type_t>...> operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{end_};} +Let \tcode{D} be the return type. +Let \tcode{\exposid{DIST}($i$)} be +\tcode{D(std::get<$i$>(x.\exposid{current_}) - std::get<$i$>(y.\exposid{end_}))}. + +\pnum +\returns +The value with the smallest absolute value among \tcode{\exposid{DIST}($n$)} +for all integers $0 \leq n < \tcode{sizeof...(Views)}$. \end{itemdescr} -\indexlibrarymember{operator-}{enumerate_view::\exposid{sentinel}}% +\indexlibrarymember{operator-}{zip_view::\exposid{sentinel}}% \begin{itemdecl} template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) +friend constexpr common_type_t>...> + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{end_} - y.\exposid{current_};} +Equivalent to: \tcode{return -(x - y);} \end{itemdescr} -\rSec2[range.zip]{Zip view} +\rSec2[range.zip.transform]{Zip transform view} -\rSec3[range.zip.overview]{Overview} +\rSec3[range.zip.transform.overview]{Overview} \pnum -\indexlibraryglobal{zip_view}% -\tcode{zip_view} takes any number of views and -produces a view of tuples of references -to the corresponding elements of the constituent views. +\indexlibraryglobal{zip_transform_view}% +\tcode{zip_transform_view} takes an invocable object and +any number of views and +produces a view +whose $M^\text{th}$ element is +the result of applying the invocable object +to the $M^\text{th}$ elements of all views. \pnum -\indexlibrarymember{zip}{views}% -The name \tcode{views::zip} denotes +\indexlibrarymember{zip_transform}{views}% +The name \tcode{views::zip_transform} denotes a customization point object\iref{customization.point.object}. -Given a pack of subexpressions \tcode{Es...}, -the expression \tcode{views::zip(Es...)} is expression-equivalent to +Let \tcode{F} be a subexpression, and +let \tcode{Es...} be a pack of subexpressions. \begin{itemize} \item -\tcode{auto(views::empty>)} -if \tcode{Es} is an empty pack, +If \tcode{Es} is an empty pack, +let \tcode{FD} be \tcode{decay_t}. +\begin{itemize} \item -otherwise, \tcode{zip_view...>(Es...)}. +If \tcode{\libconcept{move_constructible} \&\& +\libconcept{regular_invocable}} is \tcode{false}, or +if \tcode{decay_t>} is not an object type, +\tcode{views::zip_transform(F, Es...)} is ill-formed. +\item +Otherwise, the expression \tcode{views::zip_transform(F, Es...)} +is expression-equivalent to +\begin{codeblock} +((void)F, auto(views::empty>>)) +\end{codeblock} +\end{itemize} +\item +Otherwise, the expression \tcode{views::zip_transform(F, Es...)} +is expression-equivalent to \tcode{zip_trans\-form_view(F, Es...)}. \end{itemize} +\pnum \begin{example} \begin{codeblock} -vector v = {1, 2}; -list l = {'a', 'b', 'c'}; - -auto z = views::zip(v, l); -range_reference_t f = z.front(); // \tcode{f} is a \tcode{tuple} - // that refers to the first element of \tcode{v} and \tcode{l} +vector v1 = {1, 2}; +vector v2 = {4, 5, 6}; -for (auto&& [x, y] : z) { - cout << '(' << x << ", " << y << ") "; // prints \tcode{(1, a) (2, b)} +for (auto i : views::zip_transform(plus(), v1, v2)) { + cout << i << ' '; // prints \tcode{5 7} } \end{codeblock} \end{example} -\rSec3[range.zip.view]{Class template \tcode{zip_view}} +\rSec3[range.zip.transform.view]{Class template \tcode{zip_transform_view}} -\indexlibrarymember{begin}{zip_view}% -\indexlibrarymember{end}{zip_view}% -\indexlibrarymember{size}{zip_view}% +\indexlibraryglobal{zip_transform_view}% +\indexlibrarymember{begin}{zip_transform_view}% +\indexlibrarymember{end}{zip_transform_view}% +\indexlibrarymember{size}{zip_transform_view}% \begin{codeblock} namespace std::ranges { - template - concept @\defexposconcept{zip-is-common}@ = // \expos - (sizeof...(Rs) == 1 && (@\libconcept{common_range}@ && ...)) || - (!(@\libconcept{bidirectional_range}@ && ...) && (@\libconcept{common_range}@ && ...)) || - ((@\libconcept{random_access_range}@ && ...) && (@\libconcept{sized_range}@ && ...)); + template<@\libconcept{move_constructible}@ F, @\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && + @\libconcept{regular_invocable}@...> && + @\exposconcept{can-reference}@...>> + class zip_transform_view : public view_interface> { + @\exposidnc{movable-box}@ @\exposid{fun_}@; // \expos + zip_view @\exposid{zip_}@; // \expos - template<@\libconcept{input_range}@... Views> - requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) - class zip_view : public view_interface> { - tuple @\exposid{views_}@; // \expos + using @\exposidnc{InnerView}@ = zip_view; // \expos + template + using @\exposidnc{ziperator}@ = iterator_t<@\exposidnc{maybe-const}@>; // \expos + template + using @\exposidnc{zentinel}@ = sentinel_t<@\exposidnc{maybe-const}@>; // \expos - // \ref{range.zip.iterator}, class template \tcode{zip_view::\exposid{iterator}} - template class @\exposidnc{iterator}@; // \expos + // \ref{range.zip.transform.iterator}, class template \tcode{zip_transform_view::\exposid{iterator}} + template class @\exposidnc{iterator}@; // \expos - // \ref{range.zip.sentinel}, class template \tcode{zip_view::\exposid{sentinel}} - template class @\exposidnc{sentinel}@; // \expos + // \ref{range.zip.transform.sentinel}, class template \tcode{zip_transform_view::\exposid{sentinel}} + template class @\exposidnc{sentinel}@; // \expos public: - zip_view() = default; - constexpr explicit zip_view(Views... views); + zip_transform_view() = default; - constexpr auto begin() requires (!(@\exposconcept{simple-view}@ && ...)) { - return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@)); + constexpr explicit zip_transform_view(F fun, Views... views); + + constexpr auto begin() { return @\exposid{iterator}@(*this, @\exposid{zip_}@.begin()); } + + constexpr auto begin() const + requires @\libconcept{range}@ && + @\libconcept{regular_invocable}@...> { + return @\exposid{iterator}@(*this, @\exposid{zip_}@.begin()); } - constexpr auto begin() const requires (@\libconcept{range}@ && ...) { - return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@)); + + constexpr auto end() { + if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) { + return @\exposid{iterator}@(*this, @\exposid{zip_}@.end()); + } else { + return @\exposid{sentinel}@(@\exposid{zip_}@.end()); + } } - constexpr auto end() requires (!(@\exposconcept{simple-view}@ && ...)) { - if constexpr (!@\exposconcept{zip-is-common}@) { - return @\exposid{sentinel}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); - } else if constexpr ((@\libconcept{random_access_range}@ && ...)) { - return begin() + iter_difference_t<@\exposid{iterator}@>(size()); + constexpr auto end() const + requires @\libconcept{range}@ && + @\libconcept{regular_invocable}@...> { + if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(*this, @\exposid{zip_}@.end()); } else { - return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); + return @\exposid{sentinel}@(@\exposid{zip_}@.end()); } } - constexpr auto end() const requires (@\libconcept{range}@ && ...) { - if constexpr (!@\exposconcept{zip-is-common}@) { - return @\exposid{sentinel}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); - } else if constexpr ((@\libconcept{random_access_range}@ && ...)) { - return begin() + iter_difference_t<@\exposid{iterator}@>(size()); - } else { - return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); - } + constexpr auto size() requires @\libconcept{sized_range}@<@\exposid{InnerView}@> { + return @\exposid{zip_}@.size(); } - constexpr auto size() requires (@\libconcept{sized_range}@ && ...); - constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); + constexpr auto size() const requires @\libconcept{sized_range}@ { + return @\exposid{zip_}@.size(); + } }; - template - zip_view(Rs&&...) -> zip_view...>; + template + zip_transform_view(F, Rs&&...) -> zip_transform_view...>; } \end{codeblock} -\pnum -Two \tcode{zip_view} objects have the same underlying sequence if and only if -the corresponding elements of \exposid{views_} are equal\iref{concepts.equality} -and have the same underlying sequence. -\begin{note} -In particular, comparison of iterators obtained from \tcode{zip_view} objects -that do not have the same underlying sequence -is not required to produce meaningful results\iref{iterator.concept.forward}. -\end{note} - -\begin{itemdecl} -constexpr explicit zip_view(Views... views); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \exposid{views_} with \tcode{std::move(views)...}. -\end{itemdescr} - +\indexlibraryctor{zip_transform_view}% \begin{itemdecl} -constexpr auto size() requires (@\libconcept{sized_range}@ && ...); -constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); +constexpr explicit zip_transform_view(F fun, Views... views); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return apply([](auto... sizes) { - using CT = @\exposid{make-unsigned-like-t}@>; - return ranges::min({CT(sizes)...}); -}, @\exposid{tuple-transform}@(ranges::size, @\exposid{views_}@)); -\end{codeblock} +Initializes \exposid{fun_} with \tcode{std::move(fun)} and +\exposid{zip_} with \tcode{std::move(views)...}. \end{itemdescr} -\rSec3[range.zip.iterator]{Class template \tcode{zip_view::\exposid{iterator}}} +\rSec3[range.zip.transform.iterator]{Class template \tcode{zip_transform_view::\exposid{iterator}}} +\indexlibraryglobal{zip_transform_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { - template - concept @\defexposconceptnc{all-random-access}@ = // \expos - (@\libconcept{random_access_range}@<@\exposid{maybe-const}@> && ...); - template - concept @\defexposconceptnc{all-bidirectional}@ = // \expos - (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@> && ...); - template - concept @\defexposconceptnc{all-forward}@ = // \expos - (@\libconcept{forward_range}@<@\exposid{maybe-const}@> && ...); - - template<@\libconcept{input_range}@... Views> - requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) + template<@\libconcept{move_constructible}@ F, @\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && + @\libconcept{regular_invocable}@...> && + @\exposconcept{can-reference}@...>> template - class zip_view::@\exposid{iterator}@ { - tuple>...> @\exposid{current_}@;@\itcorr[-1]@ // \expos - constexpr explicit @\exposidnc{iterator}@(tuple>...>); - // \expos + class zip_transform_view::@\exposid{iterator}@ { + using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + @\exposid{ziperator}@ @\exposid{inner_}@;@\itcorr[-1]@ // \expos + + constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@ inner); // \expos + public: - using iterator_category = input_iterator_tag; // not always present - using iterator_concept = @\seebelow@; - using value_type = tuple>...>; - using difference_type = common_type_t>...>; + using iterator_category = @\seebelownc@; // not always present + using iterator_concept = typename @\exposid{ziperator}@::iterator_concept; + using value_type = + remove_cvref_t&, + range_reference_t<@\exposid{maybe-const}@>...>>; + using difference_type = range_difference_t<@\exposid{Base}@>; @\exposid{iterator}@() = default; constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && (@\libconcept{convertible_to}@, iterator_t> && ...); + requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; - constexpr auto operator*() const; + constexpr decltype(auto) operator*() const noexcept(@\seebelow@); constexpr @\exposid{iterator}@& operator++(); constexpr void operator++(int); - constexpr @\exposid{iterator}@ operator++(int) requires @\exposconcept{all-forward}@; + constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; - constexpr @\exposid{iterator}@& operator--() requires @\exposconcept{all-bidirectional}@; - constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{all-bidirectional}@; + 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 @\exposconcept{all-random-access}@; - constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\exposconcept{all-random-access}@; + 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 @\exposconcept{all-random-access}@; + constexpr decltype(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) - requires (@\libconcept{equality_comparable}@>> && ...); + requires @\libconcept{equality_comparable}@<@\exposid{ziperator}@>; friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposconcept{all-random-access}@; + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) - requires @\exposconcept{all-random-access}@; + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) - requires @\exposconcept{all-random-access}@; + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - requires @\exposconcept{all-random-access}@; + 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{maybe-const}@>> && ...); - - friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); - - friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) - requires (@\libconcept{indirectly_swappable}@>> && ...); + requires @\libconcept{sized_sentinel_for}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; }; } \end{codeblock} \pnum -\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +The member \grammarterm{typedef-name} +\tcode{\exposid{iterator}::iterator_category} +is defined if and only if \exposid{Base} models \libconcept{forward_range}. +In that case, +\tcode{\exposid{iterator}::iterator_category} is defined as follows: \begin{itemize} \item -If \tcode{\exposconcept{all-random-access}} is modeled, -then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. +If +\begin{codeblock} +invoke_result_t<@\exposid{maybe-const}@&, range_reference_t<@\exposid{maybe-const}@>...> +\end{codeblock} +is not a reference, +\tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\item +Otherwise, let \tcode{Cs} denote the pack of types +\tcode{iterator_traits>>::iterator_category...}. +\begin{itemize} +\item +If \tcode{(\libconcept{derived_from} \&\& ...)} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}. \item Otherwise, -if \tcode{\exposconcept{all-bidirectional}} is modeled, -then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +if \tcode{(\libconcept{derived_from} \&\& ...)} +is \tcode{true}, +\tcode{iterator\-_category} denotes \tcode{bidirectional_iterator_tag}. \item Otherwise, -if \tcode{\exposconcept{all-forward}} is modeled, -then \tcode{iterator_concept} denotes \tcode{for\-ward_iterator_tag}. +if \tcode{(\libconcept{derived_from} \&\& ...)} +is \tcode{true}, +\tcode{iterator_cate\-gory} denotes \tcode{forward_iterator_tag}. \item -Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. +Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\end{itemize} \end{itemize} -\pnum -\tcode{\exposid{iterator}::iterator_category} is present -if and only if \tcode{\exposconcept{all-forward}} is modeled. - -\pnum -If the invocation of any non-const member function of \exposid{iterator} -exits via an exception, -the iterator acquires a singular value. - +\indexlibraryctor{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit @\exposid{iterator}@(tuple>...> current); +constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@ inner); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{current_} with \tcode{std::move(current)}. +Initializes \exposid{parent_} with \tcode{addressof(parent)} and +\exposid{inner_} with \tcode{std::move(inner)}. \end{itemdescr} +\indexlibraryctor{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && (@\libconcept{convertible_to}@, iterator_t> && ...); + requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}. +Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and +\exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. \end{itemdescr} +\indexlibrarymember{operator*}{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} -constexpr auto operator*() const; +constexpr decltype(auto) operator*() const noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} @@ -10296,10 +12262,19 @@ \effects Equivalent to: \begin{codeblock} -return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); +return apply([&](const auto&... iters) -> decltype(auto) { + return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...); +}, @\exposid{inner_}@.@\exposid{current_}@); \end{codeblock} + +\pnum +\remarks +Let \tcode{Is} be the pack \tcode{0, 1, \ldots, \tcode{(sizeof...(Views) - 1)}}. +The exception specification is equivalent to: +\tcode{noexcept(invoke(*\exposid{parent_}->\exposid{fun_}, *std::get(\exposid{inner_}.\exposid{current_})...))}. \end{itemdescr} +\indexlibrarymember{operator++}{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} @@ -10309,11 +12284,12 @@ \effects Equivalent to: \begin{codeblock} -@\exposid{tuple-for-each}@([](auto& i) { ++i; }, @\exposid{current_}@); +++@\exposid{inner_}@; return *this; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr void operator++(int); \end{itemdecl} @@ -10321,11 +12297,12 @@ \begin{itemdescr} \pnum \effects -Equivalent to \tcode{++*this}. +Equivalent to: \tcode{++*this}. \end{itemdescr} +\indexlibrarymember{operator++}{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int) requires @\exposconcept{all-forward}@; +constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -10339,8 +12316,9 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\exposconcept{all-bidirectional}@; +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -10348,13 +12326,14 @@ \effects Equivalent to: \begin{codeblock} -@\exposid{tuple-for-each}@([](auto& i) { --i; }, @\exposid{current_}@); +--@\exposid{inner_}@; return *this; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{all-bidirectional}@; +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -10368,9 +12347,10 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator+=}{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator+=(difference_type x) - requires @\exposconcept{all-random-access}@; + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -10378,14 +12358,15 @@ \effects Equivalent to: \begin{codeblock} -@\exposid{tuple-for-each}@([&](I& i) { i += iter_difference_t(x); }, @\exposid{current_}@); +@\exposid{inner_}@ += x; return *this; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator+=}{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\exposconcept{all-random-access}@; + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -10393,548 +12374,676 @@ \effects Equivalent to: \begin{codeblock} -@\exposid{tuple-for-each}@([&](I& i) { i -= iter_difference_t(x); }, @\exposid{current_}@); +@\exposid{inner_}@ -= x; return *this; -\end{codeblock} -\end{itemdescr} - -\begin{itemdecl} -constexpr auto operator[](difference_type n) const - requires @\exposconcept{all-random-access}@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -return @\exposid{tuple-transform}@([&](I& i) -> decltype(auto) { - return i[iter_difference_t(n)]; -}, @\exposid{current_}@); -\end{codeblock} -\end{itemdescr} - -\begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires (@\libconcept{equality_comparable}@>> && ...); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\begin{itemize} -\item -\tcode{x.\exposid{current_} == y.\exposid{current_}} -if \tcode{\exposconcept{all-bidirectional}} is \tcode{true}. -\item -Otherwise, \tcode{true} -if there exists an integer $0 \leq i < \tcode{sizeof...(Views)}$ -such that \tcode{bool(std::\brk{}get<$i$>(x.\exposid{current_}) == -std::get<$i$>(y.\exposid{current_}))} is \tcode{true}. -\begin{note} -This allows \tcode{zip_view} to model \libconcept{common_range} -when all constituent views model \libconcept{common_range}. -\end{note} -\item -Otherwise, \tcode{false}. -\end{itemize} +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator[]}{zip_transform_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr decltype(auto) operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return apply([&](const Is&... iters) -> decltype(auto) { + return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, iters[iter_difference_t(n)]...); +}, @\exposid{inner_}@.@\exposid{current_}@); +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator==}{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{equality_comparable}@<@\exposid{ziperator}@>; friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposconcept{all-random-access}@; + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +Let \placeholder{op} be the operator. + +\pnum +\effects +Equivalent to: +\tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};} \end{itemdescr} +\indexlibrarymember{operator+}{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) - requires @\exposconcept{all-random-access}@; + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) - requires @\exposconcept{all-random-access}@; + 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} +\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);} \end{itemdescr} +\indexlibrarymember{operator-}{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - requires @\exposconcept{all-random-access}@; + 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} +\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);} \end{itemdescr} +\indexlibrarymember{operator-}{zip_transform_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires (@\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...); + requires @\libconcept{sized_sentinel_for}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{\exposid{DIST}($i$)} be \tcode{difference_type(std::get<$i$>(x.\exposid{current_}) - std::get<$i$>(y.\exposid{current_}))}. +\effects +Equivalent to: +\tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\end{itemdescr} + +\rSec3[range.zip.transform.sentinel]{Class template \tcode{zip_transform_view::\exposid{sentinel}}} + +\indexlibraryglobal{zip_transform_view::\exposid{sentinel}}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{move_constructible}@ F, @\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && + @\libconcept{regular_invocable}@...> && + @\exposconcept{can-reference}@...>> + template + class zip_transform_view::@\exposid{sentinel}@ { + @\exposidnc{zentinel}@ @\exposid{inner_}@; // \expos + constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{zentinel}@ inner); // \expos + + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; + + template + requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); + }; +} +\end{codeblock} + +\indexlibraryctor{zip_transform_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(@\exposid{zentinel}@ inner); +\end{itemdecl} +\begin{itemdescr} \pnum -\returns -The value with the smallest absolute value among \tcode{\exposid{DIST}($n$)} -for all integers $0 \leq n < \tcode{sizeof...(Views)}$. +\effects +Initializes \exposid{inner_} with \tcode{inner}. \end{itemdescr} +\indexlibraryctor{zip_transform_view::\exposid{sentinel}}% \begin{itemdecl} -friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return @\exposid{tuple-transform}@(ranges::iter_move, i.@\exposid{current_}@); -\end{codeblock} +Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +\end{itemdescr} + +\indexlibrarymember{operator==}{zip_transform_view::\exposid{sentinel}}% +\begin{itemdecl} +template + requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} +\begin{itemdescr} \pnum -\remarks -The exception specification is equivalent to: -\begin{codeblock} -(noexcept(ranges::iter_move(declval>&>())) && ...) && -(is_nothrow_move_constructible_v>> && ...) -\end{codeblock} +\effects +Equivalent to: \tcode{return x.\exposid{inner_} == y.\exposid{inner_};} \end{itemdescr} +\indexlibrarymember{operator-}{zip_transform_view::\exposid{sentinel}}% \begin{itemdecl} -friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) - requires (@\libconcept{indirectly_swappable}@>> && ...); +template + requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +template + requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); \end{itemdecl} \begin{itemdescr} \pnum \effects -For every integer $0 \leq i < \tcode{sizeof...(Views)}$, -performs: -\begin{codeblock} -ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@)) -\end{codeblock} +Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\end{itemdescr} + +\rSec2[range.adjacent]{Adjacent view} + +\rSec3[range.adjacent.overview]{Overview} \pnum -\remarks -The exception specification is equivalent to -the logical \logop{and} of the following expressions: +\tcode{adjacent_view} takes a view and +produces a view whose $M^\text{th}$ element is +a tuple of references to +the $M^\text{th}$ through $(M + N - 1)^\text{th}$ elements of +the original view. +If the original view has fewer than $N$ elements, the resulting view is empty. + +\pnum +\indexlibrarymember{adjacent}{views}% +The name \tcode{views::adjacent} denotes +a range adaptor object\iref{range.adaptor.object}. +Given a subexpression \tcode{E} and a constant expression \tcode{N}, +the expression \tcode{views::adjacent(E)} is expression-equivalent to +\begin{itemize} +\item +\tcode{((void)E, auto(views::empty>))} +if \tcode{N} is equal to \tcode{0} and +\tcode{decltype((E))} models \libconcept{forward_range}, +\item +otherwise, \tcode{adjacent_view, N>(E)}. +\end{itemize} + +\begin{example} \begin{codeblock} -noexcept(ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@))) +vector v = {1, 2, 3, 4}; + +for (auto i : v | views::adjacent<2>) { + cout << "(" << std::get<0>(i) << ", " << std::get<1>(i) << ") "; // prints \tcode{(1, 2) (2, 3) (3, 4)} +} \end{codeblock} -for every integer $0 \leq i < \tcode{sizeof...(Views)}$. -\end{itemdescr} +\end{example} -\rSec3[range.zip.sentinel]{Class template \tcode{zip_view::\exposid{sentinel}}} +\pnum +Define \tcode{\exposid{REPEAT}(T, N)} as a pack of \tcode{N} types, +each of which denotes the same type as \tcode{T}. +\rSec3[range.adjacent.view]{Class template \tcode{adjacent_view}} + +\indexlibraryglobal{adjacent_view}% +\indexlibrarymember{begin}{adjacent_view}% +\indexlibrarymember{end}{adjacent_view}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{input_range}@... Views> - requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) - template - class zip_view::@\exposid{sentinel}@ { - tuple>...> @\exposid{end_}@;@\itcorr[-1]@ // \expos - constexpr explicit @\exposidnc{sentinel}@(tuple>...> end); - // \expos + template<@\libconcept{forward_range}@ V, size_t N> + requires @\libconcept{view}@ && (N > 0) + class adjacent_view : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + + // \ref{range.adjacent.iterator}, class template \tcode{adjacent_view::\exposid{iterator}} + template class @\exposidnc{iterator}@; // \expos + + // \ref{range.adjacent.sentinel}, class template \tcode{adjacent_view::\exposid{sentinel}} + template class @\exposidnc{sentinel}@; // \expos + + struct @\exposidnc{as-sentinel}@{}; // \expos + public: - @\exposid{sentinel}@() = default; - constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && (@\libconcept{convertible_to}@, sentinel_t> && ...); + adjacent_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit adjacent_view(V base); - template - requires (@\libconcept{sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } - template - requires (@\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) - friend constexpr common_type_t>...> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + constexpr auto begin() requires (!@\exposconcept{simple-view}@) { + return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); + } - template - requires (@\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) - friend constexpr common_type_t>...> - operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); + constexpr auto begin() const requires @\libconcept{range}@ { + return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); + } + + constexpr auto end() requires (!@\exposconcept{simple-view}@) { + if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(@\exposid{as-sentinel}@{}, ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); + } else { + return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); + } + } + + constexpr auto end() const requires @\libconcept{range}@ { + if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(@\exposid{as-sentinel}@{}, ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); + } else { + return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); + } + } + + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; + + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; }; } \end{codeblock} +\indexlibraryctor{adjacent_view}% \begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(tuple>...> end); +constexpr explicit adjacent_view(V base); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{end}. +Initializes \exposid{base_} with \tcode{std::move(base)}. \end{itemdescr} +\indexlibrarymember{size}{adjacent_view}% \begin{itemdecl} -constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && (@\libconcept{convertible_to}@, sentinel_t> && ...); +constexpr auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}. +Equivalent to: +\begin{codeblock} +using ST = decltype(ranges::size(@\exposid{base_}@)); +using CT = common_type_t; +auto sz = static_cast(ranges::size(@\exposid{base_}@)); +sz -= std::min(sz, N - 1); +return static_cast(sz); +\end{codeblock} \end{itemdescr} +\indexlibrarymember{reserve_hint}{adjacent_view}% \begin{itemdecl} -template - requires (@\libconcept{sentinel_for}@>, - iterator_t>> && ...) -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; +constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{true} if there exists an integer $0 \leq i < \tcode{sizeof...(Views)}$ -such that \tcode{bool(std::get<$i$>(x.\brk{}\exposid{current_}) == -std::get<$i$>(y.\exposid{end_}))} is \tcode{true}. -Otherwise, \tcode{false}. +\effects +Equivalent to: +\begin{codeblock} +using DT = range_difference_t; +using CT = common_type_t; +auto sz = static_cast(ranges::reserve_hint(@\exposid{base_}@)); +sz -= std::min(sz, N - 1); +return @\exposid{to-unsigned-like}@(sz); +\end{codeblock} \end{itemdescr} -\begin{itemdecl} -template - requires (@\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) -friend constexpr common_type_t>...> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); -\end{itemdecl} +\rSec3[range.adjacent.iterator]{Class template \tcode{adjacent_view::\exposid{iterator}}} -\begin{itemdescr} -\pnum -Let \tcode{D} be the return type. -Let \tcode{\exposid{DIST}($i$)} be -\tcode{D(std::get<$i$>(x.\exposid{current_}) - std::get<$i$>(y.\exposid{end_}))}. +\indexlibraryglobal{adjacent_view::\exposid{iterator}}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, size_t N> + requires @\libconcept{view}@ && (N > 0) + template + class adjacent_view::@\exposid{iterator}@ { + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + array, N> @\exposid{current_}@ = array, N>(); // \expos + constexpr @\exposidnc{iterator}@(iterator_t<@\exposidnc{Base}@> first, sentinel_t<@\exposidnc{Base}@> last); // \expos + constexpr @\exposidnc{iterator}@(@\exposidnc{as-sentinel}@, iterator_t<@\exposidnc{Base}@> first, iterator_t<@\exposidnc{Base}@> last); + // \expos + public: + using iterator_category = input_iterator_tag; + using iterator_concept = @\seebelow@; + using value_type = tuple<@\exposid{REPEAT}@(range_value_t<@\exposid{Base}@>, N)...>; + using difference_type = range_difference_t<@\exposid{Base}@>; -\pnum -\returns -The value with the smallest absolute value among \tcode{\exposid{DIST}($n$)} -for all integers $0 \leq n < \tcode{sizeof...(Views)}$. -\end{itemdescr} + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; -\begin{itemdecl} -template - requires (@\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ...) -friend constexpr common_type_t>...> - operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); -\end{itemdecl} + constexpr auto operator*() const; + constexpr @\exposid{iterator}@& operator++(); + constexpr @\exposid{iterator}@ operator++(int); -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return -(x - y);} -\end{itemdescr} + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; -\rSec2[range.zip.transform]{Zip transform view} + 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}@>; -\rSec3[range.zip.transform.overview]{Overview} + constexpr auto operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\pnum -\indexlibraryglobal{zip_transform_view}% -\tcode{zip_transform_view} takes an invocable object and -any number of views and -produces a view -whose $M^\text{th}$ element is -the result of applying the invocable object -to the $M^\text{th}$ elements of all views. + 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}@>>; + + friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); + friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires @\libconcept{indirectly_swappable}@>; + }; +} +\end{codeblock} \pnum -\indexlibrarymember{zip_transform}{views}% -The name \tcode{views::zip_transform} denotes -a customization point object\iref{customization.point.object}. -Let \tcode{F} be a subexpression, and -let \tcode{Es...} be a pack of subexpressions. -\begin{itemize} -\item -If \tcode{Es} is an empty pack, -let \tcode{FD} be \tcode{decay_t}. +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: \begin{itemize} \item -If \tcode{\libconcept{move_constructible} \&\& -\libconcept{regular_invocable}} is \tcode{false}, or -if \tcode{decay_t>} is not an object type, -\tcode{views::zip_transform(F, Es...)} is ill-formed. +If \exposid{Base} models \libconcept{random_access_range}, +then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. \item -Otherwise, the expression \tcode{views::zip_transform(F, Es...)} -is expression-equivalent to -\begin{codeblock} -((void)F, auto(views::empty>>)) -\end{codeblock} -\end{itemize} +Otherwise, if \exposid{Base} models \libconcept{bidirectional_range}, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. \item -Otherwise, the expression \tcode{views::zip_transform(F, Es...)} -is expression-equivalent to \tcode{zip_trans\-form_view(F, Es...)}. +Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. \end{itemize} \pnum -\begin{example} -\begin{codeblock} -vector v1 = {1, 2}; -vector v2 = {4, 5, 6}; - -for (auto i : views::zip_transform(plus(), v1, v2)) { - cout << i << ' '; // prints \tcode{5 7} -} -\end{codeblock} -\end{example} - -\rSec3[range.zip.transform.view]{Class template \tcode{zip_transform_view}} +If the invocation of any non-const member function of \exposid{iterator} +exits via an exception, the \exposid{iterator} acquires a singular value. -\indexlibrarymember{begin}{zip_transform_view}% -\indexlibrarymember{end}{zip_transform_view}% -\indexlibrarymember{size}{zip_transform_view}% -\begin{codeblock} -namespace std::ranges { - template<@\libconcept{move_constructible}@ F, @\libconcept{input_range}@... Views> - requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && - @\libconcept{regular_invocable}@...> && - @\exposconcept{can-reference}@...>> - class zip_transform_view : public view_interface> { - @\exposidnc{movable-box}@ @\exposid{fun_}@; // \expos - zip_view @\exposid{zip_}@; // \expos +\indexlibraryctor{adjacent_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> first, sentinel_t<@\exposid{Base}@> last); +\end{itemdecl} - using @\exposidnc{InnerView}@ = zip_view; // \expos - template - using @\exposidnc{ziperator}@ = iterator_t<@\exposidnc{maybe-const}@>; // \expos - template - using @\exposidnc{zentinel}@ = sentinel_t<@\exposidnc{maybe-const}@>; // \expos +\begin{itemdescr} +\pnum +\ensures +\tcode{\exposid{current_}[0] == first} is \tcode{true}, and +for every integer $1 \leq i < \tcode{N}$, +\tcode{\exposid{current_}[$i$] == ranges::next(\exposid{current_}[$i$-1], 1, last)} +is \tcode{true}. +\end{itemdescr} - // \ref{range.zip.transform.iterator}, class template \tcode{zip_transform_view::\exposid{iterator}} - template class @\exposidnc{iterator}@; // \expos +\indexlibraryctor{adjacent_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{as-sentinel}@, iterator_t<@\exposid{Base}@> first, iterator_t<@\exposid{Base}@> last); +\end{itemdecl} - // \ref{range.zip.transform.sentinel}, class template \tcode{zip_transform_view::\exposid{sentinel}} - template class @\exposidnc{sentinel}@; // \expos +\begin{itemdescr} +\pnum +\ensures +If \exposid{Base} does not model \libconcept{bidirectional_range}, +each element of \exposid{current_} is equal to \exposid{last}. +Otherwise, \tcode{\exposid{current_}[N-1] == last} is \tcode{true}, and +for every integer $0 \leq i < (\tcode{N} - 1)$, +\tcode{\exposid{current_}[$i$] == ranges::prev(\exposid{current_}[$i$+1], 1, first)} +is \tcode{true}. +\end{itemdescr} - public: - zip_transform_view() = default; +\indexlibraryctor{adjacent_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} - constexpr explicit zip_transform_view(F fun, Views... views); +\begin{itemdescr} +\pnum +\effects +Initializes each element of \exposid{current_} +with the corresponding element of \tcode{i.\exposid{current_}} as an xvalue. +\end{itemdescr} - constexpr auto begin() { return @\exposid{iterator}@(*this, @\exposid{zip_}@.begin()); } +\indexlibrarymember{operator*}{adjacent_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr auto operator*() const; +\end{itemdecl} - constexpr auto begin() const - requires @\libconcept{range}@ && - @\libconcept{regular_invocable}@...> { - return @\exposid{iterator}@(*this, @\exposid{zip_}@.begin()); - } +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); +\end{codeblock} +\end{itemdescr} - constexpr auto end() { - if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) { - return @\exposid{iterator}@(*this, @\exposid{zip_}@.end()); - } else { - return @\exposid{sentinel}@(@\exposid{zip_}@.end()); - } - } +\indexlibrarymember{operator++}{adjacent_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} - constexpr auto end() const - requires @\libconcept{range}@ && - @\libconcept{regular_invocable}@...> { - if constexpr (@\libconcept{common_range}@) { - return @\exposid{iterator}@(*this, @\exposid{zip_}@.end()); - } else { - return @\exposid{sentinel}@(@\exposid{zip_}@.end()); - } - } +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_}.back()} is incrementable. - constexpr auto size() requires @\libconcept{sized_range}@<@\exposid{InnerView}@> { - return @\exposid{zip_}@.size(); - } +\pnum +\ensures +Each element of \exposid{current_} is equal to \tcode{ranges::next(i)}, +where \tcode{i} is the value of that element before the call. - constexpr auto size() const requires @\libconcept{sized_range}@ { - return @\exposid{zip_}@.size(); - } - }; +\pnum +\returns +\tcode{*this}. +\end{itemdescr} - template - zip_transform_view(F, Rs&&...) -> zip_transform_view...>; -} +\indexlibrarymember{operator++}{adjacent_view::\exposid{iterator}}% +\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} +\indexlibrarymember{operator--}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit zip_transform_view(F fun, Views... views); +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{fun_} with \tcode{std::move(fun)} and -\exposid{zip_} with \tcode{std::move(views)...}. +\expects +\tcode{\exposid{current_}.front()} is decrementable. + +\pnum +\ensures +Each element of \exposid{current_} is equal to \tcode{ranges::prev(i)}, +where \tcode{i} is the value of that element before the call. + +\pnum +\returns +\tcode{*this}. \end{itemdescr} -\rSec3[range.zip.transform.iterator]{Class template \tcode{zip_transform_view::\exposid{iterator}}} +\indexlibrarymember{operator--}{adjacent_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Equivalent to: \begin{codeblock} -namespace std::ranges { - template<@\libconcept{move_constructible}@ F, @\libconcept{input_range}@... Views> - requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && - @\libconcept{regular_invocable}@...> && - @\exposconcept{can-reference}@...>> - template - class zip_transform_view::@\exposid{iterator}@ { - using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos - using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos - @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos - @\exposid{ziperator}@ @\exposid{inner_}@;@\itcorr[-1]@ // \expos - - constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@ inner); // \expos +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} - public: - using iterator_category = @\seebelownc@; // not always present - using iterator_concept = typename @\exposid{ziperator}@::iterator_concept; - using value_type = - remove_cvref_t&, - range_reference_t<@\exposid{maybe-const}@>...>>; - using difference_type = range_difference_t<@\exposid{Base}@>; +\indexlibrarymember{operator+=}{adjacent_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} - @\exposid{iterator}@() = default; - constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_}.back() + x} has well-defined behavior. - constexpr decltype(auto) operator*() const noexcept(@\seebelow@); - constexpr @\exposid{iterator}@& operator++(); - constexpr void operator++(int); - constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; +\pnum +\ensures +Each element of \exposid{current_} is equal to \tcode{i + x}, +where \tcode{i} is the value of that element before the call. - constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; - constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\pnum +\returns +\tcode{*this}. +\end{itemdescr} - 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}@>; +\indexlibrarymember{operator-=}{adjacent_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} - constexpr decltype(auto) operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_}.front() - x} has well-defined behavior. - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@<@\exposid{ziperator}@>; +\pnum +\ensures +Each element of \exposid{current_} is equal to \tcode{i - x}, +where \tcode{i} is the value of that element before the call. - friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\pnum +\returns +\tcode{*this}. +\end{itemdescr} - 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}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; - }; -} -\end{codeblock} +\indexlibrarymember{operator[]}{adjacent_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr auto operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} +\begin{itemdescr} \pnum -The member \grammarterm{typedef-name} -\tcode{\exposid{iterator}::iterator_category} -is defined if and only if \exposid{Base} models \libconcept{forward_range}. -In that case, -\tcode{\exposid{iterator}::iterator_category} is defined as follows: -\begin{itemize} -\item -If +\effects +Equivalent to: \begin{codeblock} -invoke_result_t<@\exposid{maybe-const}@&, range_reference_t<@\exposid{maybe-const}@>...> +return @\exposid{tuple-transform}@([&](auto& i) -> decltype(auto) { return i[n]; }, @\exposid{current_}@); \end{codeblock} -is not a reference, -\tcode{iterator_category} denotes \tcode{input_iterator_tag}. -\item -Otherwise, let \tcode{Cs} denote the pack of types -\tcode{iterator_traits>>::iterator_category...}. -\begin{itemize} -\item -If \tcode{(\libconcept{derived_from} \&\& ...)} -is \tcode{true}, -\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}. -\item -Otherwise, -if \tcode{(\libconcept{derived_from} \&\& ...)} -is \tcode{true}, -\tcode{iterator\-_category} denotes \tcode{bidirectional_iterator_tag}. -\item -Otherwise, -if \tcode{(\libconcept{derived_from} \&\& ...)} -is \tcode{true}, -\tcode{iterator_cate\-gory} denotes \tcode{forward_iterator_tag}. -\item -Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. -\end{itemize} -\end{itemize} +\end{itemdescr} +\indexlibrarymember{operator==}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@ inner); +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_}.back() == y.\exposid{current_}.back()}. +\end{itemdescr} + +\indexlibrarymember{operator<}{adjacent_view::\exposid{iterator}}% +\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_}.back() < y.\exposid{current_}.back()}. +\end{itemdescr} + +\indexlibrarymember{operator>}{adjacent_view::\exposid{iterator}}% +\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 -Initializes \exposid{parent_} with \tcode{addressof(parent)} and -\exposid{inner_} with \tcode{std::move(inner)}. +Equivalent to: \tcode{return y < x;} \end{itemdescr} +\indexlibrarymember{operator<=}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; +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 -Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and -\exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +Equivalent to: \tcode{return !(y < x);} \end{itemdescr} +\indexlibrarymember{operator>=}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr decltype(auto) operator*() const noexcept(@\seebelow@); +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: -\begin{codeblock} -return apply([&](const auto&... iters) -> decltype(auto) { - return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...); -}, @\exposid{inner_}@.@\exposid{current_}@); -\end{codeblock} +Equivalent to: \tcode{return !(x < y);} +\end{itemdescr} + +\indexlibrarymember{operator<=>}{adjacent_view::\exposid{iterator}}% +\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 -\remarks -Let \tcode{Is} be the pack \tcode{0, 1, \ldots, \tcode{(sizeof...(Views)-1)}}. -The exception specification is equivalent to: -\tcode{noexcept(invoke(*\exposid{parent_}->\exposid{fun_}, *std::get(\exposid{inner_}.\exposid{current_})...))}. +\returns +\tcode{x.\exposid{current_}.back() <=> y.\exposid{current_}.back()}. \end{itemdescr} +\indexlibrarymember{operator+}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator++(); +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} @@ -10942,362 +13051,522 @@ \effects Equivalent to: \begin{codeblock} -++@\exposid{inner_}@; -return *this; +auto r = i; +r += n; +return r; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr void operator++(int); +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: \tcode{++*this}. +Equivalent to: +\begin{codeblock} +auto r = i; +r -= n; +return r; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_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{itemdecl} \begin{itemdescr} \pnum \effects Equivalent to: -\begin{codeblock} -auto tmp = *this; -++*this; -return tmp; -\end{codeblock} +\tcode{return x.\exposid{current_}.back() - y.\exposid{current_}.back();} \end{itemdescr} +\indexlibrarymember{iter_move}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum \effects Equivalent to: +\tcode{return \exposid{tuple-transform}(ranges::iter_move, i.\exposid{current_});} + +\pnum +\remarks +The exception specification is equivalent to: \begin{codeblock} ---@\exposid{inner_}@; -return *this; +noexcept(ranges::iter_move(declval&>())) && +is_nothrow_move_constructible_v> \end{codeblock} \end{itemdescr} +\indexlibrarymember{iter_swap}{adjacent_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires @\libconcept{indirectly_swappable}@>; \end{itemdecl} \begin{itemdescr} +\pnum +\expects +None of the iterators in \tcode{l.\exposid{current_}} is equal to +an iterator in \tcode{r.\exposid{current_}}. + \pnum \effects -Equivalent to: +For every integer $0 \leq i < \tcode{N}$, +performs +\tcode{ranges::iter_swap(l.\exposid{current_}[$i$], r.\exposid{current_}[$i$])}. + +\pnum +\remarks +The exception specification is equivalent to: \begin{codeblock} -auto tmp = *this; ---*this; -return tmp; +noexcept(ranges::iter_swap(declval>(), declval>())) \end{codeblock} \end{itemdescr} +\rSec3[range.adjacent.sentinel]{Class template \tcode{adjacent_view::\exposid{sentinel}}} + +\indexlibraryglobal{adjacent_view::\exposid{sentinel}}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, size_t N> + requires @\libconcept{view}@ && (N > 0) + template + class adjacent_view::@\exposid{sentinel}@ { + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos + constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); // \expos + + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + 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); + + template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); + }; +} +\end{codeblock} + +\indexlibraryctor{adjacent_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -@\exposid{inner_}@ += x; -return *this; -\end{codeblock} +Initializes \exposid{end_} with \tcode{end}. \end{itemdescr} +\indexlibraryctor{adjacent_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -@\exposid{inner_}@ -= x; -return *this; -\end{codeblock} +Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}. \end{itemdescr} +\indexlibrarymember{operator==}{adjacent_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr decltype(auto) operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\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{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return apply([&](const Is&... iters) -> decltype(auto) { - return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, iters[iter_difference_t(n)]...); -}, @\exposid{inner_}@.@\exposid{current_}@); -\end{codeblock} +Equivalent to: \tcode{return x.\exposid{current_}.back() == y.\exposid{end_};} \end{itemdescr} +\indexlibrarymember{operator-}{adjacent_view::\exposid{sentinel}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@<@\exposid{ziperator}@>; -friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} \begin{itemdescr} -\pnum -Let \placeholder{op} be the operator. - \pnum \effects -Equivalent to: -\tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};} +Equivalent to: \tcode{return x.\exposid{current_}.back() - y.\exposid{end_};} \end{itemdescr} +\indexlibrarymember{operator-}{adjacent_view::\exposid{sentinel}}% \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}@>; +template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);} +Equivalent to: \tcode{return y.\exposid{end_} - x.\exposid{current_}.back();} \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} +\rSec2[range.adjacent.transform]{Adjacent transform view} + +\rSec3[range.adjacent.transform.overview]{Overview} + +\pnum +\tcode{adjacent_transform_view} takes an invocable object and +a view and produces a view +whose $M^\text{th}$ element is the result of applying the invocable object +to the $M^\text{th}$ through $(M + N - 1)^\text{th}$ elements +of the original view. +If the original view has fewer than $N$ elements, the resulting view is empty. + +\pnum +\indexlibrarymember{adjacent_transform}{views}% +The name \tcode{views::adjacent_transform} denotes +a range adaptor object\iref{range.adaptor.object}. +Given subexpressions \tcode{E} and \tcode{F} and +a constant expression \tcode{N}: +\begin{itemize} +\item +If \tcode{N} is equal to \tcode{0} and +\tcode{decltype((E))} models \libconcept{forward_range}, +\tcode{views::adjacent_transform(E, F)} is expression-equivalent to +\tcode{((void)E, views::zip_transform(F))}, +except that the evaluations of \tcode{E} and \tcode{F} are +indeterminately sequenced. +\item +Otherwise, +the expression \tcode{views::adjacent_transform(E, F)} is +expression-equivalent to +\tcode{adja\-cent_transform_view, decay_t, N>(E, F)}. +\end{itemize} + +\pnum +\begin{example} +\begin{codeblock} +vector v = {1, 2, 3, 4}; + +for (auto i : v | views::adjacent_transform<2>(std::multiplies())) { + cout << i << ' '; // prints \tcode{2 6 12} +} +\end{codeblock} +\end{example} + +\rSec3[range.adjacent.transform.view]{Class template \tcode{adjacent_transform_view}} + +\indexlibraryglobal{adjacent_transform_view}% +\indexlibrarymember{base}{adjacent_transform_view}% +\indexlibrarymember{begin}{adjacent_transform_view}% +\indexlibrarymember{end}{adjacent_transform_view}% +\indexlibrarymember{size}{adjacent_transform_view}% +\indexlibrarymember{reserve_hint}{adjacent_transform_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, @\libconcept{move_constructible}@ F, size_t N> + requires @\libconcept{view}@ && (N > 0) && is_object_v && + @\libconcept{regular_invocable}@, N)...> && + @\exposconcept{can-reference}@, N)...>> + class adjacent_transform_view : public view_interface> { + @\exposidnc{movable-box}@ @\exposid{fun_}@; // \expos + adjacent_view @\exposid{inner_}@; // \expos + + using @\exposidnc{InnerView}@ = adjacent_view; // \expos + template + using @\exposid{inner-iterator}@ = iterator_t<@\exposid{maybe-const}@>; // \expos + template + using @\exposid{inner-sentinel}@ = sentinel_t<@\exposid{maybe-const}@>; // \expos + + // \ref{range.adjacent.transform.iterator}, class template \tcode{adjacent_transform_view::\exposid{iterator}} + template class @\exposidnc{iterator}@; // \expos + + // \ref{range.adjacent.transform.sentinel}, class template \tcode{adjacent_transform_view::\exposid{sentinel}} + template class @\exposidnc{sentinel}@; // \expos + + public: + adjacent_transform_view() = default; + constexpr explicit adjacent_transform_view(V base, F fun); + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{inner_}@.base(); } + constexpr V base() && { return std::move(@\exposid{inner_}@).base(); } + + constexpr auto begin() { + return @\exposid{iterator}@(*this, @\exposid{inner_}@.begin()); + } + + constexpr auto begin() const + requires @\libconcept{range}@ && + @\libconcept{regular_invocable}@, N)...> { + return @\exposid{iterator}@(*this, @\exposid{inner_}@.begin()); + } + + constexpr auto end() { + if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) { + return @\exposid{iterator}@(*this, @\exposid{inner_}@.end()); + } else { + return @\exposid{sentinel}@(@\exposid{inner_}@.end()); + } + } + + constexpr auto end() const + requires @\libconcept{range}@ && + @\libconcept{regular_invocable}@, N)...> { + if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(*this, @\exposid{inner_}@.end()); + } else { + return @\exposid{sentinel}@(@\exposid{inner_}@.end()); + } + } + + constexpr auto size() requires @\libconcept{sized_range}@<@\exposid{InnerView}@> { + return @\exposid{inner_}@.size(); + } + + constexpr auto size() const requires @\libconcept{sized_range}@ { + return @\exposid{inner_}@.size(); + } -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);} -\end{itemdescr} + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@<@\exposid{InnerView}@> { + return @\exposid{inner_}@.reserve_hint(); + } + + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@ { + return @\exposid{inner_}@.reserve_hint(); + } + }; +} +\end{codeblock} +\indexlibraryctor{adjacent_transform_view}% \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{sized_sentinel_for}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; +constexpr explicit adjacent_transform_view(V base, F fun); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +Initializes \exposid{fun_} with \tcode{std::move(fun)} and +\exposid{inner_} with \tcode{std::move(base)}. \end{itemdescr} -\rSec3[range.zip.transform.sentinel]{Class template \tcode{zip_transform_view::\exposid{sentinel}}} +\rSec3[range.adjacent.transform.iterator]{Class template \tcode{adjacent_transform_view::\exposid{iterator}}} +\indexlibraryglobal{adjacent_transform_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{move_constructible}@ F, @\libconcept{input_range}@... Views> - requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && - @\libconcept{regular_invocable}@...> && - @\exposconcept{can-reference}@...>> + template<@\libconcept{forward_range}@ V, @\libconcept{move_constructible}@ F, size_t N> + requires @\libconcept{view}@ && (N > 0) && is_object_v && + @\libconcept{regular_invocable}@, N)...> && + @\exposconcept{can-reference}@, N)...>> template - class zip_transform_view::@\exposid{sentinel}@ { - @\exposidnc{zentinel}@ @\exposid{inner_}@; // \expos - constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{zentinel}@ inner); // \expos + class adjacent_transform_view::@\exposid{iterator}@ { + using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + @\exposidnc{inner-iterator}@ @\exposid{inner_}@; // \expos + + constexpr @\exposidnc{iterator}@(@\exposidnc{Parent}@& parent, @\exposidnc{inner-iterator}@ inner); // \expos public: - @\exposid{sentinel}@() = default; - constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; + using iterator_category = @\seebelow@; + using iterator_concept = typename @\exposid{inner-iterator}@::iterator_concept; + using value_type = + remove_cvref_t&, + @\exposid{REPEAT}@(range_reference_t<@\exposid{Base}@>, N)...>>; + using difference_type = range_difference_t<@\exposid{Base}@>; - template - requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; - template - requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + constexpr decltype(auto) operator*() const noexcept(@\seebelow@); + 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}@>; - template - requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); + constexpr decltype(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}@<@\exposid{inner-iterator}@>; + + 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}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; }; } \end{codeblock} -\begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(@\exposid{zentinel}@ inner); -\end{itemdecl} - -\begin{itemdescr} \pnum -\effects -Initializes \exposid{inner_} with \tcode{inner}. -\end{itemdescr} +The member \grammarterm{typedef-name} \tcode{\exposid{iterator}::iterator_category} +is defined as follows: +\begin{itemize} +\item +If \tcode{invoke_result_t<\exposid{maybe-const}\&, +\exposid{REPEAT}(range_reference_t<\exposid{Base}>, N)...>} +is\linebreak not a reference, +\tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\item +Otherwise, let \tcode{C} denote the type +\tcode{iterator_traits>::iterator_category}. +\begin{itemize} +\item +If \tcode{\libconcept{derived_from}} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{ran\-dom_access_iterator_tag}. +\item +Otherwise, +if \tcode{\libconcept{derived_from}} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, +if \tcode{\libconcept{derived_from}} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{forward_iterator_tag}. +\item +Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\end{itemize} +\end{itemize} +\indexlibraryctor{adjacent_transform_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; +constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{inner-iterator}@ inner); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +Initializes \exposid{parent_} with \tcode{addressof(parent)} and +\exposid{inner_} with \tcode{std::move(inner)}. \end{itemdescr} +\indexlibraryctor{adjacent_transform_view::\exposid{iterator}}% \begin{itemdecl} -template - requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{inner_} == y.\exposid{inner_};} +Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and +\exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. \end{itemdescr} +\indexlibrarymember{operator*}{adjacent_transform_view::\exposid{iterator}}% \begin{itemdecl} -template - requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); -template - requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); +constexpr decltype(auto) operator*() const noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} -\end{itemdescr} - -\rSec2[range.adjacent]{Adjacent view} - -\rSec3[range.adjacent.overview]{Overview} - -\pnum -\indexlibraryglobal{adjacent_view}% -\tcode{adjacent_view} takes a view and -produces a view whose $M^\text{th}$ element is -a tuple of references to -the $M^\text{th}$ through $(M + N - 1)^\text{th}$ elements of -the original view. -If the original view has fewer than $N$ elements, the resulting view is empty. - -\pnum -\indexlibrarymember{adjacent}{views}% -The name \tcode{views::adjacent} denotes -a range adaptor object\iref{range.adaptor.object}. -Given a subexpression \tcode{E} and a constant expression \tcode{N}, -the expression \tcode{views::adjacent(E)} is expression-equivalent to -\begin{itemize} -\item -\tcode{((void)E, auto(views::empty>))} -if \tcode{N} is equal to \tcode{0}, -\item -otherwise, \tcode{adjacent_view, N>(E)}. -\end{itemize} - -\begin{example} +Equivalent to: \begin{codeblock} -vector v = {1, 2, 3, 4}; - -for (auto i : v | views::adjacent<2>) { - cout << "(" << std::get<0>(i) << ", " << std::get<1>(i) << ") "; // prints \tcode{(1, 2) (2, 3) (3, 4)} -} +return apply([&](const auto&... iters) -> decltype(auto) { + return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...); +}, @\exposid{inner_}@.@\exposid{current_}@); \end{codeblock} -\end{example} \pnum -Define \tcode{\exposid{REPEAT}(T, N)} as a pack of \tcode{N} types, -each of which denotes the same type as \tcode{T}. - -\rSec3[range.adjacent.view]{Class template \tcode{adjacent_view}} - -\indexlibrarymember{begin}{adjacent_view}% -\indexlibrarymember{end}{adjacent_view}% -\indexlibrarymember{size}{adjacent_view}% +\remarks +Let \tcode{Is} be the pack \tcode{0, 1, \ldots, (N - 1)}. +The exception specification is equivalent to: \begin{codeblock} -namespace std::ranges { - template<@\libconcept{forward_range}@ V, size_t N> - requires @\libconcept{view}@ && (N > 0) - class adjacent_view : public view_interface> { - V @\exposid{base_}@ = V(); // \expos - - // \ref{range.adjacent.iterator}, class template \tcode{adjacent_view::\exposid{iterator}} - template class @\exposidnc{iterator}@; // \expos - - // \ref{range.adjacent.sentinel}, class template \tcode{adjacent_view::\exposid{sentinel}} - template class @\exposidnc{sentinel}@; // \expos - - struct @\exposidnc{as-sentinel}@{}; // \expos - - public: - adjacent_view() requires @\libconcept{default_initializable}@ = default; - constexpr explicit adjacent_view(V 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}@) { - return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); - } +noexcept(invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *std::get(@\exposid{inner_}@.@\exposid{current_}@)...)) +\end{codeblock} +\end{itemdescr} - constexpr auto begin() const requires @\libconcept{range}@ { - return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); - } +\indexlibrarymember{operator++}{adjacent_transform_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} - constexpr auto end() requires (!@\exposconcept{simple-view}@) { - if constexpr (@\libconcept{common_range}@) { - return @\exposid{iterator}@(@\exposid{as-sentinel}@{}, ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); - } else { - return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); - } - } +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +++@\exposid{inner_}@; +return *this; +\end{codeblock} +\end{itemdescr} - constexpr auto end() const requires @\libconcept{range}@ { - if constexpr (@\libconcept{common_range}@) { - return @\exposid{iterator}@(@\exposid{as-sentinel}@{}, ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); - } else { - return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); - } - } +\indexlibrarymember{operator++}{adjacent_transform_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int); +\end{itemdecl} - constexpr auto size() requires @\libconcept{sized_range}@; - constexpr auto size() const requires @\libconcept{sized_range}@; - }; -} +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; \end{codeblock} +\end{itemdescr} +\indexlibrarymember{operator--}{adjacent_transform_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit adjacent_view(V base); +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{base_} with \tcode{std::move(base)}. +Equivalent to: +\begin{codeblock} +--@\exposid{inner_}@; +return *this; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{adjacent_transform_view::\exposid{iterator}}% \begin{itemdecl} -constexpr auto size() requires @\libconcept{sized_range}@; -constexpr auto size() const requires @\libconcept{sized_range}@; +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -11305,206 +13574,316 @@ \effects Equivalent to: \begin{codeblock} -using ST = decltype(ranges::size(@\exposid{base_}@)); -using CT = common_type_t; -auto sz = static_cast(ranges::size(@\exposid{base_}@)); -sz -= std::min(sz, N - 1); -return static_cast(sz); +auto tmp = *this; +--*this; +return tmp; \end{codeblock} \end{itemdescr} -\rSec3[range.adjacent.iterator]{Class template \tcode{adjacent_view::\exposid{iterator}}} +\indexlibrarymember{operator+=}{adjacent_transform_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Equivalent to: \begin{codeblock} -namespace std::ranges { - template<@\libconcept{forward_range}@ V, size_t N> - requires @\libconcept{view}@ && (N > 0) - template - class adjacent_view::@\exposid{iterator}@ { - using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos - array, N> @\exposid{current_}@ = array, N>(); // \expos - constexpr @\exposidnc{iterator}@(iterator_t<@\exposidnc{Base}@> first, sentinel_t<@\exposidnc{Base}@> last); // \expos - constexpr @\exposidnc{iterator}@(@\exposidnc{as-sentinel}@, iterator_t<@\exposidnc{Base}@> first, iterator_t<@\exposidnc{Base}@> last); - // \expos - public: - using iterator_category = input_iterator_tag; - using iterator_concept = @\seebelow@; - using value_type = tuple<@\exposid{REPEAT}@(range_value_t<@\exposid{Base}@>, N)...>; - using difference_type = range_difference_t<@\exposid{Base}@>; +@\exposid{inner_}@ += x; +return *this; +\end{codeblock} +\end{itemdescr} - @\exposid{iterator}@() = default; - constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; +\indexlibrarymember{operator-=}{adjacent_transform_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} - constexpr auto operator*() const; - constexpr @\exposid{iterator}@& operator++(); - constexpr @\exposid{iterator}@ operator++(int); +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{inner_}@ -= x; +return *this; +\end{codeblock} +\end{itemdescr} - constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; - constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\indexlibrarymember{operator[]}{adjacent_transform_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr decltype(auto) operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} - 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}@>; +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return apply([&](const auto&... iters) -> decltype(auto) { + return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, iters[n]...); +}, @\exposid{inner_}@.@\exposid{current_}@); +\end{codeblock} +\end{itemdescr} - constexpr auto operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\indexlibrarymember{operator==}{adjacent_transform_view::\exposid{iterator}}% +\begin{itemdecl} +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}@<@\exposid{inner-iterator}@>; +\end{itemdecl} - 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}@>; +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. - 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}@>>; +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};} +\end{itemdescr} - friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); - friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) - requires @\libconcept{indirectly_swappable}@>; - }; -} -\end{codeblock} +\indexlibrarymember{operator+}{adjacent_transform_view::\exposid{iterator}}% +\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 -\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} +\effects +Equivalent to: \tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);} +\end{itemdescr} + +\indexlibrarymember{operator-}{adjacent_transform_view::\exposid{iterator}}% +\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 -If the invocation of any non-const member function of \exposid{iterator} -exits via an exception, the \exposid{iterator} acquires a singular value. +\effects +Equivalent to: \tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);} +\end{itemdescr} +\indexlibrarymember{operator-}{adjacent_transform_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> first, sentinel_t<@\exposid{Base}@> last); +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{\exposid{current_}[0] == first} is \tcode{true}, and -for every integer $1 \leq i < \tcode{N}$, -\tcode{\exposid{current_}[$i$] == ranges::next(\exposid{current_}[$i$-1], 1, last)} -is \tcode{true}. +\effects +Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} \end{itemdescr} +\rSec3[range.adjacent.transform.sentinel]{Class template \tcode{adjacent_transform_view::\exposid{sentinel}}} + +\indexlibraryglobal{adjacent_transform_view::\exposid{sentinel}}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, @\libconcept{move_constructible}@ F, size_t N> + requires @\libconcept{view}@ && (N > 0) && is_object_v && + @\libconcept{regular_invocable}@, N)...> && + @\exposconcept{can-reference}@, N)...>> + template + class adjacent_transform_view::@\exposid{sentinel}@ { + @\exposidnc{inner-sentinel}@ @\exposid{inner_}@; // \expos + constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{inner-sentinel}@ inner); // \expos + + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@, @\exposid{inner-sentinel}@>; + + template + requires @\libconcept{sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); + }; +} +\end{codeblock} + +\indexlibraryctor{adjacent_transform_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{as-sentinel}@, iterator_t<@\exposid{Base}@> first, iterator_t<@\exposid{Base}@> last); +constexpr explicit @\exposid{sentinel}@(@\exposid{inner-sentinel}@ inner); \end{itemdecl} \begin{itemdescr} \pnum -\ensures -If \exposid{Base} does not model \libconcept{bidirectional_range}, -each element of \exposid{current_} is equal to \exposid{last}. -Otherwise, \tcode{\exposid{current_}[N-1] == last} is \tcode{true}, and -for every integer $0 \leq i < (\tcode{N} - 1)$, -\tcode{\exposid{current_}[$i$] == ranges::prev(\exposid{current_}[$i$+1], 1, first)} -is \tcode{true}. +\effects +Initializes \exposid{inner_} with \tcode{inner}. \end{itemdescr} +\indexlibraryctor{adjacent_transform_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@, @\exposid{inner-sentinel}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes each element of \exposid{current_} -with the corresponding element of \tcode{i.\exposid{current_}} as an xvalue. +Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. \end{itemdescr} +\indexlibrarymember{operator==}{adjacent_transform_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr auto operator*() const; +template + requires @\libconcept{sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); -\end{codeblock} +Equivalent to: \tcode{return x.\exposid{inner_} == y.\exposid{inner_};} \end{itemdescr} +\indexlibrarymember{operator-}{adjacent_transform_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator++(); +template + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + +template + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{\exposid{current_}.back()} is incrementable. +\effects +Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\end{itemdescr} + +\rSec2[range.chunk]{Chunk view} + +\rSec3[range.chunk.overview]{Overview} \pnum -\ensures -Each element of \exposid{current_} is equal to \tcode{ranges::next(i)}, -where \tcode{i} is the value of that element before the call. +\tcode{chunk_view} takes a view and a number $N$ and +produces a range of views +that are $N$-sized non-overlapping successive chunks of +the elements of the original view, in order. +The last view in the range can have fewer than $N$ elements. \pnum -\returns -\tcode{*this}. -\end{itemdescr} +\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{itemdecl} -constexpr @\exposid{iterator}@ operator++(int); -\end{itemdecl} +\begin{example} +\begin{codeblock} +vector v = {1, 2, 3, 4, 5}; -\begin{itemdescr} -\pnum -\effects -Equivalent to: +for (auto r : v | views::chunk(2)) { + cout << '['; + auto sep = ""; + for (auto i : r) { + cout << sep << i; + sep = ", "; + } + cout << "] "; +} +// The above prints \tcode{[1, 2] [3, 4] [5]} +\end{codeblock} +\end{example} + +\rSec3[range.chunk.view.input]{Class template \tcode{chunk_view} for input ranges} + +\indexlibraryglobal{chunk_view}% \begin{codeblock} -auto tmp = *this; -++*this; -return tmp; +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_}@; // \expos + range_difference_t @\exposid{n_}@; // \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: + 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() const noexcept; + + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; + + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; + }; + + template + chunk_view(R&&, range_difference_t) -> chunk_view>; +} \end{codeblock} -\end{itemdescr} +\indexlibraryctor{chunk_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +constexpr explicit chunk_view(V base, range_difference_t n); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{\exposid{current_}.front()} is decrementable. - -\pnum -\ensures -Each element of \exposid{current_} is equal to \tcode{ranges::prev(i)}, -where \tcode{i} is the value of that element before the call. +\tcode{n > 0} is \tcode{true}. \pnum -\returns -\tcode{*this}. +\effects +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{n_} with \tcode{n}. \end{itemdescr} +\indexlibrarymember{begin}{chunk_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +constexpr @\exposid{outer-iterator}@ begin(); \end{itemdecl} \begin{itemdescr} @@ -11512,55 +13891,42 @@ \effects Equivalent to: \begin{codeblock} -auto tmp = *this; ---*this; -return tmp; +@\exposid{current_}@ = ranges::begin(@\exposid{base_}@); +@\exposid{remainder_}@ = @\exposid{n_}@; +return @\exposid{outer-iterator}@(*this); \end{codeblock} \end{itemdescr} +\indexlibrarymember{end}{chunk_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr default_sentinel_t end() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{\exposid{current_}.back() + x} has well-defined behavior. - -\pnum -\ensures -Each element of \exposid{current_} is equal to \tcode{i + x}, -where \tcode{i} is the value of that element before the call. - \pnum \returns -\tcode{*this}. +\tcode{default_sentinel}. \end{itemdescr} +\indexlibrarymember{size}{chunk_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{\exposid{current_}.front() - x} has well-defined behavior. - -\pnum -\ensures -Each element of \exposid{current_} is equal to \tcode{i - x}, -where \tcode{i} is the value of that element before the call. - -\pnum -\returns -\tcode{*this}. +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{to-unsigned-like}@(@\exposidnc{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{n_}@)); +\end{codeblock} \end{itemdescr} +\indexlibrarymember{reserve_hint}{chunk_view}% \begin{itemdecl} -constexpr auto operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; +constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; \end{itemdecl} \begin{itemdescr} @@ -11568,81 +13934,107 @@ \effects Equivalent to: \begin{codeblock} -return @\exposid{tuple-transform}@([&](auto& i) -> decltype(auto) { return i[n]; }, @\exposid{current_}@); +auto s = static_cast>(ranges::reserve_hint(@\exposidnc{base_}@)); +return @\exposidnc{to-unsigned-like}@(@\exposidnc{div-ceil}@(s, @\exposidnc{n_}@)); \end{codeblock} \end{itemdescr} -\begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); -\end{itemdecl} +\rSec3[range.chunk.outer.iter]{Class \tcode{chunk_view::\exposid{outer-iterator}}} -\begin{itemdescr} -\pnum -\returns -\tcode{x.\exposid{current_}.back() == y.\exposid{current_}.back()}. -\end{itemdescr} +\indexlibraryglobal{chunk_view::\exposid{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 -\begin{itemdecl} -friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} + constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent); // \expos -\begin{itemdescr} -\pnum -\returns -\tcode{x.\exposid{current_}.back() < y.\exposid{current_}.back()}. -\end{itemdescr} + 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} + +\indexlibraryctor{chunk_view::\exposid{outer-iterator}}% \begin{itemdecl} -friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return y < x;} +Initializes \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} +\indexlibrarymember{operator*}{chunk_view::\exposid{outer-iterator}}% \begin{itemdecl} -friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr value_type operator*() const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return !(y < x);} +\expects +\tcode{*this == default_sentinel} is \tcode{false}. + +\pnum +\returns +\tcode{value_type(*\exposid{parent_})}. \end{itemdescr} +\indexlibrarymember{operator++}{chunk_view::\exposid{outer-iterator}}% \begin{itemdecl} -friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{outer-iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{*this == default_sentinel} is \tcode{false}. + \pnum \effects -Equivalent to: \tcode{return !(x < y);} +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} +\indexlibrarymember{operator++}{chunk_view::\exposid{outer-iterator}}% \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}@>; +constexpr void operator++(int); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_}.back() <=> y.\exposid{current_}.back()}. +\effects +Equivalent to \tcode{++*this}. \end{itemdescr} +\indexlibrarymember{operator==}{chunk_view::\exposid{outer-iterator}}% \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}@>; +friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t); \end{itemdecl} \begin{itemdescr} @@ -11650,15 +14042,14 @@ \effects Equivalent to: \begin{codeblock} -auto r = i; -r += n; -return r; +return *x.@\exposid{parent_}@->@\exposid{current_}@ == ranges::end(x.@\exposid{parent_}@->@\exposid{base_}@) && x.@\exposid{parent_}@->@\exposid{remainder_}@ != 0; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-}{chunk_view::\exposid{outer-iterator}}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +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} @@ -11666,330 +14057,451 @@ \effects Equivalent to: \begin{codeblock} -auto r = i; -r -= n; -return r; +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} +\indexlibrarymember{operator-}{chunk_view::\exposid{outer-iterator}}% \begin{itemdecl} -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-(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 x.\exposid{current_}.back() - y.\exposid{current_}.back();} +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::\exposid{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 { + private: + 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>; + + constexpr auto reserve_hint() const noexcept; + }; +} +\end{codeblock} + +\indexlibraryctor{chunk_view::\exposid{outer-iterator}::value_type}% \begin{itemdecl} -friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); +constexpr explicit value_type(chunk_view& parent); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return \exposid{tuple-transform}(ranges::iter_move, i.\exposid{current_});} +Initializes \exposid{parent_} with \tcode{addressof(parent)}. +\end{itemdescr} + +\indexlibrarymember{begin}{chunk_view::\exposid{outer-iterator}::value_type}% +\begin{itemdecl} +constexpr @\exposid{inner-iterator}@ begin() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\remarks -The exception specification is equivalent to: -\begin{codeblock} -noexcept(ranges::iter_move(declval&>())) && -is_nothrow_move_constructible_v> -\end{codeblock} +\returns +\tcode{\exposid{inner-iterator}(*\exposid{parent_})}. \end{itemdescr} +\indexlibrarymember{end}{chunk_view::\exposid{outer-iterator}::value_type}% \begin{itemdecl} -friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) - requires @\libconcept{indirectly_swappable}@>; +constexpr default_sentinel_t end() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -None of the iterators in \tcode{l.\exposid{current_}} is equal to -an iterator in \tcode{r.\exposid{current_}}. +\returns +\tcode{default_sentinel}. +\end{itemdescr} + +\indexlibrarymember{size}{chunk_view::\exposid{outer-iterator}::value_type}% +\begin{itemdecl} +constexpr auto size() const + requires @\libconcept{sized_sentinel_for}@, iterator_t>; +\end{itemdecl} +\begin{itemdescr} \pnum \effects -For every integer $0 \leq i < \tcode{N}$, -performs -\tcode{ranges::iter_swap(l.\exposid{current_}[$i$], r.\exposid{current_}[$i$])}. +Equivalent to: +\begin{codeblock} +return @\exposid{to-unsigned-like}@(ranges::min(@\exposid{parent_}@->@\exposid{remainder_}@, + ranges::end(@\exposid{parent_}@->@\exposid{base_}@) - *@\exposid{parent_}@->@\exposid{current_}@)); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{reserve_hint}{chunk_view::\exposid{outer-iterator}::value_type}% +\begin{itemdecl} +constexpr auto reserve_hint() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\remarks -The exception specification is equivalent to: +\effects +Equivalent to: \begin{codeblock} -noexcept(ranges::iter_swap(declval>(), declval>())) +return @\exposid{to-unsigned-like}@(@\exposid{parent_}@->@\exposid{remainder_}@); \end{codeblock} \end{itemdescr} -\rSec3[range.adjacent.sentinel]{Class template \tcode{adjacent_view::\exposid{sentinel}}} +\rSec3[range.chunk.inner.iter]{Class \tcode{chunk_view::\exposid{inner-iterator}}} +\indexlibraryglobal{chunk_view::\exposid{inner-iterator}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{forward_range}@ V, size_t N> - requires @\libconcept{view}@ && (N > 0) - template - class adjacent_view::@\exposid{sentinel}@ { - using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos - sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos - constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); // \expos + 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: - @\exposid{sentinel}@() = default; - constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; + using iterator_concept = input_iterator_tag; + using difference_type = range_difference_t; + using value_type = range_value_t; - template - requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + @\exposid{inner-iterator}@(@\exposid{inner-iterator}@&&) = default; + @\exposid{inner-iterator}@& operator=(@\exposid{inner-iterator}@&&) = default; - template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + constexpr const iterator_t& base() const &; - template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); + 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_for}@, iterator_t>; + + friend constexpr range_rvalue_reference_t iter_move(const @\exposid{inner-iterator}@& i) + noexcept(noexcept(ranges::iter_move(*i.@\exposid{parent_}@->@\exposid{current_}@))); + + friend constexpr void iter_swap(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y) + noexcept(noexcept(ranges::iter_swap(*x.@\exposid{parent_}@->@\exposid{current_}@, *y.@\exposid{parent_}@->@\exposid{current_}@))) + requires @\libconcept{indirectly_swappable}@>; }; } \end{codeblock} +\indexlibraryctor{chunk_view::\exposid{inner-iterator}}% \begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); +constexpr explicit @\exposid{inner-iterator}@(chunk_view& parent) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{end}. +Initializes \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} +\indexlibrarymember{base}{chunk_view::\exposid{inner-iterator}}% \begin{itemdecl} -constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +constexpr const iterator_t& base() const &; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}. +Equivalent to: \tcode{return *\exposid{parent_}->\exposid{current_};} \end{itemdescr} +\indexlibrarymember{operator*}{chunk_view::\exposid{inner-iterator}}% \begin{itemdecl} -template - requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +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 x.\exposid{current_}.back() == y.\exposid{end_};} +Equivalent to: \tcode{return **\exposid{parent_}->\exposid{current_};} \end{itemdescr} +\indexlibrarymember{operator++}{chunk_view::\exposid{inner-iterator}}% \begin{itemdecl} -template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +constexpr @\exposid{inner-iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{*this == default_sentinel} is \tcode{false}. + \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_}.back() - y.\exposid{end_};} +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} +\indexlibrarymember{operator++}{chunk_view::\exposid{inner-iterator}}% \begin{itemdecl} -template - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); +constexpr void operator++(int); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return y.\exposid{end_} - x.\exposid{current_}.back();} +Equivalent to \tcode{++*this}. \end{itemdescr} -\rSec2[range.adjacent.transform]{Adjacent transform view} - -\rSec3[range.adjacent.transform.overview]{Overview} +\indexlibrarymember{operator==}{chunk_view::\exposid{inner-iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t); +\end{itemdecl} +\begin{itemdescr} \pnum -\indexlibraryglobal{adjacent_transform_view}% -\tcode{adjacent_transform_view} takes an invocable object and -a view and produces a view -whose $M^\text{th}$ element is the result of applying the invocable object -to the $M^\text{th}$ through $(M + N - 1)^\text{th}$ elements -of the original view. -If the original view has fewer than $N$ elements, the resulting view is empty. +\returns +\tcode{x.\exposid{parent_}->\exposid{remainder_} == 0}. +\end{itemdescr} + +\indexlibrarymember{operator-}{chunk_view::\exposid{inner-iterator}}% +\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 -\indexlibrarymember{adjacent_transform}{views}% -The name \tcode{views::adjacent_transform} denotes -a range adaptor object\iref{range.adaptor.object}. -Given subexpressions \tcode{E} and \tcode{F} and -a constant expression \tcode{N}: -\begin{itemize} -\item -If \tcode{N} is equal to \tcode{0}, -\tcode{views::adjacent_transform(E, F)} is expression-equivalent to -\tcode{((void)E, views::zip_transform(F))}, -except that the evaluations of \tcode{E} and \tcode{F} are -indeterminately sequenced. -\item -Otherwise, -the expression \tcode{views::adjacent_transform(E, F)} is -expression-equivalent to -\tcode{adja\-cent_transform_view, decay_t, N>(E, F)}. -\end{itemize} +\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} + +\indexlibrarymember{operator-}{chunk_view::\exposid{inner-iterator}}% +\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 -\begin{example} -\begin{codeblock} -vector v = {1, 2, 3, 4}; +\effects +Equivalent to: \tcode{return -(y - x);} +\end{itemdescr} -for (auto i : v | views::adjacent_transform<2>(std::multiplies())) { - cout << i << ' '; // prints \tcode{2 6 12} -} -\end{codeblock} -\end{example} +\indexlibrarymember{iter_move}{chunk_view::\exposid{inner-iterator}}% +\begin{itemdecl} +friend constexpr range_rvalue_reference_t iter_move(const @\exposid{inner-iterator}@& i) + noexcept(noexcept(ranges::iter_move(*i.@\exposid{parent_}@->@\exposid{current_}@))); +\end{itemdecl} -\rSec3[range.adjacent.transform.view]{Class template \tcode{adjacent_transform_view}} +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return ranges::iter_move(*i.\exposid{parent_}->\exposid{current_});} +\end{itemdescr} -\indexlibrarymember{begin}{adjacent_transform_view}% -\indexlibrarymember{end}{adjacent_transform_view}% -\indexlibrarymember{size}{adjacent_transform_view}% -\begin{codeblock} -namespace std::ranges { - template<@\libconcept{forward_range}@ V, @\libconcept{move_constructible}@ F, size_t N> - requires @\libconcept{view}@ && (N > 0) && is_object_v && - @\libconcept{regular_invocable}@, N)...> && - @\exposconcept{can-reference}@, N)...>> - class adjacent_transform_view : public view_interface> { - @\exposidnc{movable-box}@ @\exposid{fun_}@; // \expos - adjacent_view @\exposid{inner_}@; // \expos +\indexlibrarymember{iter_swap}{chunk_view::\exposid{inner-iterator}}% +\begin{itemdecl} +friend constexpr void iter_swap(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y) + noexcept(noexcept(ranges::iter_swap(*x.@\exposid{parent_}@->@\exposid{current_}@, *y.@\exposid{parent_}@->@\exposid{current_}@))) + requires @\libconcept{indirectly_swappable}@>; +\end{itemdecl} - using @\exposidnc{InnerView}@ = adjacent_view; // \expos - template - using @\exposid{inner-iterator}@ = iterator_t<@\exposid{maybe-const}@>; // \expos - template - using @\exposid{inner-sentinel}@ = sentinel_t<@\exposid{maybe-const}@>; // \expos +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{ranges::iter_swap(*x.\exposid{parent_}->\exposid{current_}, *y.\exposid{parent_}->\exposid{current_});} +\end{itemdescr} - // \ref{range.adjacent.transform.iterator}, class template \tcode{adjacent_transform_view::\exposid{iterator}} - template class @\exposidnc{iterator}@; // \expos +\rSec3[range.chunk.view.fwd]{Class template \tcode{chunk_view} for forward ranges} - // \ref{range.adjacent.transform.sentinel}, class template \tcode{adjacent_transform_view::\exposid{sentinel}} - template class @\exposidnc{sentinel}@; // \expos +\indexlibraryglobal{chunk_view}% +\indexlibrarymember{begin}{chunk_view}% +\indexlibrarymember{end}{chunk_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\libconcept{forward_range}@ + class chunk_view : public view_interface> { + V @\exposid{base_}@; // \expos + range_difference_t @\exposid{n_}@; // \expos + + // \ref{range.chunk.fwd.iter}, class template \tcode{chunk_view::\exposid{iterator}} + template class @\exposid{iterator}@; // \expos public: - adjacent_transform_view() = default; - constexpr explicit adjacent_transform_view(V base, F fun); + constexpr explicit chunk_view(V base, range_difference_t n); - constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{inner_}@.base(); } - constexpr V base() && { return std::move(@\exposid{inner_}@).base(); } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } - constexpr auto begin() { - return @\exposid{iterator}@(*this, @\exposid{inner_}@.begin()); + constexpr auto begin() requires (!@\exposconcept{simple-view}@) { + return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); } - constexpr auto begin() const - requires @\libconcept{range}@ && - @\libconcept{regular_invocable}@, N)...> { - return @\exposid{iterator}@(*this, @\exposid{inner_}@.begin()); + constexpr auto begin() const requires @\libconcept{forward_range}@ { + return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); } - constexpr auto end() { - if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) { - return @\exposid{iterator}@(*this, @\exposid{inner_}@.end()); + 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 @\exposid{sentinel}@(@\exposid{inner_}@.end()); + return default_sentinel; } } - constexpr auto end() const - requires @\libconcept{range}@ && - @\libconcept{regular_invocable}@, N)...> { - if constexpr (@\libconcept{common_range}@) { - return @\exposid{iterator}@(*this, @\exposid{inner_}@.end()); + 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 @\exposid{sentinel}@(@\exposid{inner_}@.end()); + return default_sentinel; } } - constexpr auto size() requires @\libconcept{sized_range}@<@\exposid{InnerView}@> { - return @\exposid{inner_}@.size(); - } + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; - constexpr auto size() const requires @\libconcept{sized_range}@ { - return @\exposid{inner_}@.size(); - } + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; }; } \end{codeblock} +\indexlibraryctor{chunk_view}% \begin{itemdecl} -constexpr explicit adjacent_transform_view(V base, F fun); +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{fun_} with \tcode{std::move(fun)} and -\exposid{inner_} with \tcode{std::move(base)}. +Initializes \exposid{base_} with \tcode{std::move(base)} and +\exposid{n_} with \tcode{n}. \end{itemdescr} -\rSec3[range.adjacent.transform.iterator]{Class template \tcode{adjacent_transform_view::\exposid{iterator}}} +\indexlibrarymember{size}{chunk_view}% +\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} + +\indexlibrarymember{reserve_hint}{chunk_view}% +\begin{itemdecl} +constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; +constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto s = static_cast>(ranges::reserve_hint(@\exposid{base_}@)); +return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(s, @\exposid{n_}@)); +\end{codeblock} +\end{itemdescr} + +\rSec3[range.chunk.fwd.iter]{Class template \tcode{chunk_view::\exposid{iterator}} for forward ranges} +\indexlibraryglobal{chunk_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{forward_range}@ V, @\libconcept{move_constructible}@ F, size_t N> - requires @\libconcept{view}@ && (N > 0) && is_object_v && - @\libconcept{regular_invocable}@, N)...> && - @\exposconcept{can-reference}@, N)...>> + template<@\libconcept{view}@ V> + requires @\libconcept{forward_range}@ template - class adjacent_transform_view::@\exposid{iterator}@ { - using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos - using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos - @\exposidnc{Parent}@* @\exposid{parent_}@ = nullptr; // \expos - @\exposidnc{inner-iterator}@ @\exposid{inner_}@; // \expos + class chunk_view::@\exposid{iterator}@ { + using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos - constexpr @\exposidnc{iterator}@(@\exposidnc{Parent}@& parent, @\exposidnc{inner-iterator}@ inner); // \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 = @\seebelow@; - using iterator_concept = typename @\exposid{inner-iterator}@::iterator_concept; - using value_type = - remove_cvref_t&, - @\exposid{REPEAT}@(range_reference_t<@\exposid{Base}@>, N)...>>; + 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}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> + && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; - constexpr decltype(auto) operator*() const noexcept(@\seebelow@); + 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 decltype(auto) operator[](difference_type n) const + 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) @@ -11999,7 +14511,8 @@ 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}@<@\exposid{inner-iterator}@>; + 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}@>; @@ -12008,103 +14521,106 @@ 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}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; + 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 -The member \grammarterm{typedef-name} \tcode{\exposid{iterator}::iterator_category} -is defined as follows: -\begin{itemize} -\item -If \tcode{invoke_result_t<\exposid{maybe-const}\&, -\exposid{REPEAT}(range_reference_t<\exposid{Base}>, N)...>} -is\linebreak not a reference, -\tcode{iterator_category} denotes \tcode{input_iterator_tag}. -\item -Otherwise, let \tcode{C} denote the type -\tcode{iterator_traits>::iterator_category}. +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: \begin{itemize} \item -If \tcode{\libconcept{derived_from}} -is \tcode{true}, -\tcode{iterator_category} denotes \tcode{ran\-dom_access_iterator_tag}. -\item -Otherwise, -if \tcode{\libconcept{derived_from}} -is \tcode{true}, -\tcode{iterator_category} denotes \tcode{bidirectional_iterator_tag}. +If \exposid{Base} models \libconcept{random_access_range}, +then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. \item -Otherwise, -if \tcode{\libconcept{derived_from}} -is \tcode{true}, -\tcode{iterator_category} denotes \tcode{forward_iterator_tag}. +Otherwise, if \exposid{Base} models \libconcept{bidirectional_range}, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. \item -Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. -\end{itemize} +Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. \end{itemize} +\indexlibraryctor{chunk_view::\exposid{iterator}}% +\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} + +\indexlibraryctor{chunk_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{inner-iterator}@ inner); +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{parent_} with \tcode{addressof(parent)} and -\exposid{inner_} with \tcode{std::move(inner)}. +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} +\indexlibrarymember{base}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; +constexpr iterator_t<@\exposid{Base}@> base() const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and -\exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +\returns +\exposid{current_}. \end{itemdescr} +\indexlibrarymember{operator*}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -constexpr decltype(auto) operator*() const noexcept(@\seebelow@); +constexpr value_type operator*() const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return apply([&](const auto&... iters) -> decltype(auto) { - return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...); -}, @\exposid{inner_}@.@\exposid{current_}@); -\end{codeblock} +\expects +\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}. \pnum -\remarks -Let \tcode{Is} be the pack \tcode{0, 1, \ldots, (N-1)}. -The exception specification is equivalent to: -\begin{codeblock} -noexcept(invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *std::get(@\exposid{inner_}@.@\exposid{current_}@)...)) -\end{codeblock} +\returns +\tcode{views::take(subrange(\exposid{current_}, \exposid{end_}), \exposid{n_})}. \end{itemdescr} +\indexlibrarymember{operator++}{chunk_view::\exposid{iterator}}% \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{inner_}@; +@\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{n_}@, @\exposid{end_}@); return *this; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{chunk_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} @@ -12120,6 +14636,7 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{chunk_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} @@ -12129,11 +14646,13 @@ \effects Equivalent to: \begin{codeblock} ---@\exposid{inner_}@; +ranges::advance(@\exposid{current_}@, @\exposid{missing_}@ - @\exposid{n_}@); +@\exposid{missing_}@ = 0; return *this; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{chunk_view::\exposid{iterator}}% \begin{itemdecl} constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} @@ -12149,280 +14668,305 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator+=}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -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}@>; \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} -@\exposid{inner_}@ += x; +if (x > 0) { + ranges::advance(@\exposid{current_}@, @\exposid{n_}@ * (x - 1)); + @\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{n_}@, @\exposid{end_}@); +} else if (x < 0) { + ranges::advance(@\exposid{current_}@, @\exposid{n_}@ * x + @\exposid{missing_}@); + @\exposid{missing_}@ = 0; +} return *this; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-=}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -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}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -@\exposid{inner_}@ -= x; -return *this; -\end{codeblock} +Equivalent to: \tcode{return *this += -x;} \end{itemdescr} +\indexlibrarymember{operator[]}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -constexpr decltype(auto) operator[](difference_type n) const +constexpr value_type operator[](difference_type n) const requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return apply([&](const auto&... iters) -> decltype(auto) { - return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, iters[n]...); -}, @\exposid{inner_}@.@\exposid{current_}@); -\end{codeblock} +\returns +\tcode{*(*this + n)}. \end{itemdescr} +\indexlibrarymember{operator-=}{chunk_view::\exposid{iterator}}% \begin{itemdecl} 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}@<@\exposid{inner-iterator}@>; \end{itemdecl} \begin{itemdescr} \pnum -Let \placeholder{op} be the operator. +\returns +\tcode{x.\exposid{current_} == y.\exposid{current_}}. +\end{itemdescr} + +\indexlibrarymember{operator==}{chunk_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); +\end{itemdecl} +\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};} +\returns +\tcode{x.\exposid{current_} == x.\exposid{end_}}. \end{itemdescr} +\indexlibrarymember{operator<}{chunk_view::\exposid{iterator}}% \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) +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 \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);} +\returns +\tcode{x.\exposid{current_} < y.\exposid{current_}}. \end{itemdescr} +\indexlibrarymember{operator>}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) +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 \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);} +Equivalent to: \tcode{return y < x;} \end{itemdescr} +\indexlibrarymember{operator<=}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; +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.\exposid{inner_} - y.\exposid{inner_};} +Equivalent to: \tcode{return !(y < x);} \end{itemdescr} -\rSec3[range.adjacent.transform.sentinel]{Class template \tcode{adjacent_transform_view::\exposid{sentinel}}} +\indexlibrarymember{operator>=}{chunk_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} -\begin{codeblock} -namespace std::ranges { - template<@\libconcept{forward_range}@ V, @\libconcept{move_constructible}@ F, size_t N> - requires @\libconcept{view}@ && (N > 0) && is_object_v && - @\libconcept{regular_invocable}@, N)...> && - @\exposconcept{can-reference}@, N)...>> - template - class adjacent_transform_view::@\exposid{sentinel}@ { - @\exposidnc{inner-sentinel}@ @\exposid{inner_}@; // \expos - constexpr explicit @\exposidnc{sentinel}@(@\exposidnc{inner-sentinel}@ inner); // \expos +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(x < y);} +\end{itemdescr} - public: - @\exposid{sentinel}@() = default; - constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@, @\exposid{inner-sentinel}@>; +\indexlibrarymember{operator<=>}{chunk_view::\exposid{iterator}}% +\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} - template - requires @\libconcept{sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +\end{itemdescr} - template - requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\indexlibrarymember{operator+}{chunk_view::\exposid{iterator}}% +\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} - template - requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> - friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); - }; -} +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto r = i; +r += n; +return r; \end{codeblock} +\end{itemdescr} +\indexlibrarymember{operator-}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(@\exposid{inner-sentinel}@ inner); +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 -Initializes \exposid{inner_} with \tcode{inner}. +Equivalent to: +\begin{codeblock} +auto r = i; +r -= n; +return r; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) - requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@, @\exposid{inner-sentinel}@>; +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 -\effects -Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +\returns +\tcode{(x.\exposid{current_} - y.\exposid{current_} + x.\exposid{missing_} - y.\exposid{missing_}) / x.\exposid{n_}}. \end{itemdescr} +\indexlibrarymember{operator-}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -template - requires @\libconcept{sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +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 -\effects -Equivalent to: \tcode{return x.\exposid{inner_} == y.\exposid{inner_};} +\returns +\tcode{\exposid{div-ceil}(x.\exposid{end_} - x.\exposid{current_}, x.\exposid{n_})}. \end{itemdescr} +\indexlibrarymember{operator-}{chunk_view::\exposid{iterator}}% \begin{itemdecl} -template - requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); - -template - requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> -friend constexpr range_difference_t<@\exposid{maybe-const}@> - operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); +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 x.\exposid{inner_} - y.\exposid{inner_};} +Equivalent to: \tcode{return -(y - x);} \end{itemdescr} -\rSec2[range.chunk]{Chunk view} +\rSec2[range.slide]{Slide view} -\rSec3[range.chunk.overview]{Overview} +\rSec3[range.slide.overview]{Overview} \pnum -\tcode{chunk_view} takes a view and a number $N$ and -produces a range of views -that are $N$-sized non-overlapping successive chunks of -the elements of the original view, in order. -The last view in the range can have fewer than $N$ elements. +\tcode{slide_view} takes a view and a number $N$ and +produces a view +whose $M^\text{th}$ element is a view over +the $M^\text{th}$ through +$(M + N - 1)^\text{th}$ elements +of the original view. +If the original view has fewer than $N$ elements, +the resulting view is empty. \pnum -\indexlibrarymember{chunk}{views}% -The name \tcode{views::chunk} denotes +\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::chunk(E, N)} is expression-equivalent to -\tcode{chunk_view(E, 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, 5}; +vector v = {1, 2, 3, 4}; -for (auto r : v | views::chunk(2)) { - cout << '['; - auto sep = ""; - for (auto i : r) { - cout << sep << i; - sep = ", "; - } - cout << "] "; +for (auto i : v | views::slide(2)) { + cout << '[' << i[0] << ", " << i[1] << "] "; // prints \tcode{[1, 2] [2, 3] [3, 4]} } -// The above prints \tcode{[1, 2] [3, 4] [5]} \end{codeblock} \end{example} -\rSec3[range.chunk.view.input]{Class template \tcode{chunk_view} for input ranges} +\rSec3[range.slide.view]{Class template \tcode{slide_view}} -\indexlibrarymember{begin}{chunk_view}% -\indexlibrarymember{end}{chunk_view}% -\indexlibrarymember{size}{chunk_view}% +\indexlibraryglobal{slide_view}% +\indexlibraryctor{slide_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 + concept @\defexposconcept{slide-caches-nothing}@ = @\libconcept{random_access_range}@ && @\libconcept{sized_range}@; // \expos - template<@\libconcept{view}@ V> - requires @\libconcept{input_range}@ - class chunk_view : public view_interface> { - V @\exposid{base_}@; // \expos - range_difference_t @\exposid{n_}@; // \expos - range_difference_t @\exposid{remainder_}@ = 0; // \expos + template + concept @\defexposconcept{slide-caches-last}@ = // \expos + !@\exposconcept{slide-caches-nothing}@ && @\libconcept{bidirectional_range}@ && @\libconcept{common_range}@; - @\exposid{non-propagating-cache}@> @\exposid{current_}@; // \expos + template + concept @\defexposconcept{slide-caches-first}@ = // \expos + !@\exposconcept{slide-caches-nothing}@ && !@\exposconcept{slide-caches-last}@; - // \ref{range.chunk.outer.iter}, class \tcode{chunk_view::\exposid{outer-iterator}} - class @\exposid{outer-iterator}@; // \expos + template<@\libconcept{forward_range}@ V> + requires @\libconcept{view}@ + class slide_view : public view_interface> { + V @\exposid{base_}@; // \expos + range_difference_t @\exposid{n_}@; // \expos - // \ref{range.chunk.inner.iter}, class \tcode{chunk_view::\exposid{inner-iterator}} - class @\exposid{inner-iterator}@; // \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: - constexpr explicit chunk_view(V base, range_difference_t n); + constexpr explicit slide_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() const noexcept; + 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}@; + + constexpr auto reserve_hintsize() requires @\libconcept{approximately_sized_range}@; + constexpr auto reserve_hintsize() const requires @\libconcept{approximately_sized_range}@; }; template - chunk_view(R&&, range_difference_t) -> chunk_view>; + slide_view(R&&, range_difference_t) -> slide_view>; } \end{codeblock} +\indexlibraryctor{slide_view}% \begin{itemdecl} -constexpr explicit chunk_view(V base, range_difference_t n); +constexpr explicit slide_view(V base, range_difference_t n); \end{itemdecl} \begin{itemdescr} @@ -12436,31 +14980,96 @@ \exposid{n_} with \tcode{n}. \end{itemdescr} +\indexlibrarymember{begin}{slide_view}% \begin{itemdecl} -constexpr @\exposid{outer-iterator}@ begin(); +constexpr auto begin() + requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: +\returns +\begin{itemize} +\item +If \tcode{V} models \exposconcept{slide-caches-first}, \begin{codeblock} -@\exposid{current_}@ = ranges::begin(@\exposid{base_}@); -@\exposid{remainder_}@ = @\exposid{n_}@; -return @\exposid{outer-iterator}@(*this); +@\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} + +\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-first}. +\end{itemdescr} + +\indexlibrarymember{begin}{slide_view}% +\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} +\indexlibrarymember{end}{slide_view}% \begin{itemdecl} -constexpr default_sentinel_t end() const noexcept; +constexpr auto end() + requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{default_sentinel}. +\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} + +\indexlibrarymember{end}{slide_view}% +\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} +\indexlibrarymember{size}{slide_view}% \begin{itemdecl} constexpr auto size() requires @\libconcept{sized_range}@; constexpr auto size() const requires @\libconcept{sized_range}@; @@ -12471,115 +15080,201 @@ \effects Equivalent to: \begin{codeblock} -return @\exposid{to-unsigned-like}@(@\exposidnc{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{n_}@)); +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.chunk.outer.iter]{Class \tcode{chunk_view::\exposid{outer-iterator}}} +\indexlibrarymember{reserve_hint}{slide_view}% +\begin{itemdecl} +constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; +constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto sz = static_cast>(ranges::reserve_hint(@\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{chunk_view::outer-iterator}% +\indexlibraryglobal{slide_view::\exposid{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 + 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 \exposid{Base} models \tcode{\exposconcept{slide-caches-first}} + range_difference_t<@\exposid{Base}@> @\exposid{n_}@ = 0; // \expos - constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent); // \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_concept = input_iterator_tag; - using difference_type = range_difference_t; + 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}@>; - // \ref{range.chunk.outer.value}, class \tcode{chunk_view::\exposid{outer-iterator}::value_type} - struct value_type; + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; - @\exposid{outer-iterator}@(@\exposid{outer-iterator}@&&) = default; - @\exposid{outer-iterator}@& operator=(@\exposid{outer-iterator}@&&) = default; + constexpr auto operator*() const; + constexpr @\exposid{iterator}@& operator++(); + constexpr @\exposid{iterator}@ operator++(int); - constexpr value_type operator*() const; - constexpr @\exposid{outer-iterator}@& operator++(); - constexpr void operator++(int); + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; - friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t); + 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}@>; - 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>; + 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. + +\indexlibraryctor{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit @\exposid{outer-iterator}@(chunk_view& parent); +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{parent_} with \tcode{addressof(parent)}. +Initializes \exposid{current_} with \tcode{current} and +\exposid{n_} with \tcode{n}. \end{itemdescr} +\indexlibraryctor{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr value_type operator*() const; +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 -\expects -\tcode{*this == default_sentinel} is \tcode{false}. - -\pnum -\returns -\tcode{value_type(*\exposid{parent_})}. +\effects +Initializes \exposid{current_} with \tcode{current}, +\exposid{last_ele_} with \tcode{last_ele}, and +\exposid{n_} with \tcode{n}. \end{itemdescr} +\indexlibraryctor{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{outer-iterator}@& operator++(); +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; \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} +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} +\indexlibrarymember{operator*}{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr void operator++(int); +constexpr auto operator*() const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{++*this}. +\returns +\tcode{views::counted(\exposid{current_}, \exposid{n_})}. \end{itemdescr} +\indexlibrarymember{operator++}{slide_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{outer-iterator}@& x, default_sentinel_t); +constexpr @\exposid{iterator}@& operator++(); \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} +\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} +\indexlibrarymember{operator++}{slide_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{outer-iterator}@& x) - requires @\libconcept{sized_sentinel_for}@, iterator_t>; +constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} \begin{itemdescr} @@ -12587,215 +15282,187 @@ \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; +auto tmp = *this; +++*this; +return tmp; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{slide_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{outer-iterator}@& x, default_sentinel_t y) - requires @\libconcept{sized_sentinel_for}@, iterator_t>; +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \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 { - private: - chunk_view* @\exposid{parent_}@; // \expos - - constexpr explicit value_type(chunk_view& parent); // \expos +\expects +\exposid{current_} and \exposid{last_ele_} (if present) are decrementable. - public: - constexpr @\exposid{inner-iterator}@ begin() const noexcept; - constexpr default_sentinel_t end() const noexcept; +\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. - constexpr auto size() const - requires @\libconcept{sized_sentinel_for}@, iterator_t>; - }; -} -\end{codeblock} +\pnum +\returns +\tcode{*this}. +\end{itemdescr} +\indexlibrarymember{operator--}{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit value_type(chunk_view& parent); +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{parent_} with \tcode{addressof(parent)}. +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator+=}{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{inner-iterator}@ begin() const noexcept; +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. + +\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{\exposid{inner-iterator}(*\exposid{parent_})}. +\tcode{*this}. \end{itemdescr} +\indexlibrarymember{operator-=}{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr default_sentinel_t end() const noexcept; +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. + +\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{default_sentinel}. +\tcode{*this}. \end{itemdescr} +\indexlibrarymember{operator[]}{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr auto size() const - requires @\libconcept{sized_sentinel_for}@, iterator_t>; +constexpr auto operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return @\exposid{to-unsigned-like}@(ranges::min(@\exposid{parent_}@->@\exposid{remainder_}@, - ranges::end(@\exposid{parent_}@->@\exposid{base_}@) - *@\exposid{parent_}@->@\exposid{current_}@)); -\end{codeblock} +Equivalent to: \tcode{return views::counted(\exposid{current_} + n, \exposid{n_});} \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_for}@, iterator_t>; - - friend constexpr range_rvalue_reference_t iter_move(const @\exposid{inner-iterator}@& i) - noexcept(noexcept(ranges::iter_move(*i.@\exposid{parent_}@->@\exposid{current_}@))); - - friend constexpr void iter_swap(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y) - noexcept(noexcept(ranges::iter_swap(*x.@\exposid{parent_}@->@\exposid{current_}@, *y.@\exposid{parent_}@->@\exposid{current_}@))) - requires @\libconcept{indirectly_swappable}@>; - }; -} -\end{codeblock} - +\indexlibrarymember{operator==}{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit @\exposid{inner-iterator}@(chunk_view& parent) noexcept; +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Initializes \exposid{parent_} with \tcode{addressof(parent)}. +\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} +\indexlibrarymember{operator<}{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr const iterator_t& base() const &; +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 *\exposid{parent_}->\exposid{current_};} +\returns +\tcode{x.\exposid{current_} < y.\exposid{current_}}. \end{itemdescr} +\indexlibrarymember{operator>}{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr range_reference_t operator*() const; +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{*this == default_sentinel} is \tcode{false}. - \pnum \effects -Equivalent to: \tcode{return **\exposid{parent_}->\exposid{current_};} +Equivalent to: \tcode{return y < x;} \end{itemdescr} +\indexlibrarymember{operator<=}{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{inner-iterator}@& operator++(); +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \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} +Equivalent to: \tcode{return !(y < x);} \end{itemdescr} +\indexlibrarymember{operator>=}{slide_view::\exposid{iterator}}% \begin{itemdecl} -constexpr void operator++(int); +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{++*this}. +Equivalent to: \tcode{return !(x < y);} \end{itemdescr} +\indexlibrarymember{operator<=>}{slide_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{inner-iterator}@& x, default_sentinel_t); +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{parent_}->\exposid{remainder_} == 0}. +\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. \end{itemdescr} +\indexlibrarymember{operator+}{slide_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{inner-iterator}@& x) - requires @\libconcept{sized_sentinel_for}@, iterator_t>; +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} @@ -12803,297 +15470,242 @@ \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_}@); +auto r = i; +r += n; +return r; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-}{slide_view::\exposid{iterator}}% \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} - -\begin{itemdecl} -friend constexpr range_rvalue_reference_t iter_move(const @\exposid{inner-iterator}@& i) - noexcept(noexcept(ranges::iter_move(*i.@\exposid{parent_}@->@\exposid{current_}@))); +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: \tcode{return ranges::iter_move(*i.\exposid{parent_}->\exposid{current_});} +Equivalent to: +\begin{codeblock} +auto r = i; +r -= n; +return r; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-}{slide_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr void iter_swap(const @\exposid{inner-iterator}@& x, const @\exposid{inner-iterator}@& y) - noexcept(noexcept(ranges::iter_swap(*x.@\exposid{parent_}@->@\exposid{current_}@, *y.@\exposid{parent_}@->@\exposid{current_}@))) - requires @\libconcept{indirectly_swappable}@>; +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 -\effects -Equivalent to: \tcode{ranges::iter_swap(*x.\exposid{parent_}->\exposid{current_}, *y.\exposid{parent_}->\exposid{current_});} +\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.chunk.view.fwd]{Class template \tcode{chunk_view} for forward ranges} +\rSec3[range.slide.sentinel]{Class \tcode{slide_view::\exposid{sentinel}}} -\indexlibrarymember{begin}{chunk_view}% -\indexlibrarymember{end}{chunk_view}% -\indexlibrarymember{size}{chunk_view}% +\indexlibraryglobal{slide_view::\exposid{sentinel}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{view}@ V> - requires @\libconcept{forward_range}@ - class chunk_view : public view_interface> { - V @\exposid{base_}@; // \expos - range_difference_t @\exposid{n_}@; // \expos - - // \ref{range.chunk.fwd.iter}, class template \tcode{chunk_view::\exposid{iterator}} - template class @\exposid{iterator}@; // \expos + 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: - 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_}@)); - } + @\exposid{sentinel}@() = default; - 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; - } - } + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); - 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; - } - } + friend constexpr range_difference_t + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; - constexpr auto size() requires @\libconcept{sized_range}@; - constexpr auto size() const requires @\libconcept{sized_range}@; + 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} + +\indexlibraryctor{slide_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr explicit chunk_view(V base, range_difference_t n); +constexpr explicit @\exposid{sentinel}@(sentinel_t end); \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}. +Initializes \exposid{end_} with \tcode{end}. \end{itemdescr} +\indexlibrarymember{operator==}{slide_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr auto size() requires @\libconcept{sized_range}@; -constexpr auto size() const requires @\libconcept{sized_range}@; +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \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} +\returns +\tcode{x.\exposid{last_ele_} == y.\exposid{end_}}. \end{itemdescr} -\rSec3[range.chunk.fwd.iter]{Class template \tcode{chunk_view::\exposid{iterator}} for forward ranges} +\indexlibrarymember{operator-}{slide_view::\exposid{sentinel}}% +\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{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 +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{last_ele_} - y.\exposid{end_}}. +\end{itemdescr} - 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 +\indexlibrarymember{operator-}{slide_view::\exposid{sentinel}}% +\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} - constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current, // \expos - range_difference_t<@\exposid{Base}@> missing = 0); +\begin{itemdescr} +\pnum +\returns +\tcode{y.\exposid{end_} - x.\exposid{last_ele_}}. +\end{itemdescr} - 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}@>; +\rSec2[range.chunk.by]{Chunk by view} - @\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}@>>; +\rSec3[range.chunk.by.overview]{Overview} - constexpr iterator_t<@\exposid{Base}@> base() const; +\pnum +\tcode{chunk_by_view} takes a view and a predicate, and +splits the view into \tcode{subrange}s +between each pair of adjacent elements +for which the predicate returns \tcode{false}. - constexpr value_type operator*() const; - constexpr @\exposid{iterator}@& operator++(); - constexpr @\exposid{iterator}@ operator++(int); +\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}; - constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; - constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +for (auto r : v | views::chunk_by(ranges::less_equal{})) { + cout << '['; + auto sep = ""; + for (auto i : r) { + cout << sep << i; + sep = ", "; + } + cout << "] "; +} +// The above prints \tcode{[1, 2, 2, 3] [0, 4, 5] [2]} +\end{codeblock} +\end{example} - 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}@>; +\rSec3[range.chunk.by.view]{Class template \tcode{chunk_by_view}} - constexpr value_type operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\indexlibraryglobal{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 + @\exposidnc{movable-box}@ @\exposid{pred_}@; // \expos - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); - friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); + // \ref{range.chunk.by.iter}, class \tcode{chunk_by_view::\exposid{iterator}} + class @\exposidnc{iterator}@; // \expos - 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}@>; + public: + chunk_by_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; + constexpr explicit chunk_by_view(V base, Pred pred); - 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}@>>; + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\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}@>>; + constexpr const Pred& pred() const; + + constexpr @\exposid{iterator}@ begin(); + constexpr auto end(); + + constexpr iterator_t @\exposidnc{find-next}@(iterator_t); // \expos + constexpr iterator_t @\exposidnc{find-prev}@(iterator_t) // \expos + requires @\libconcept{bidirectional_range}@; }; + + template + chunk_by_view(R&&, Pred) -> chunk_by_view, Pred>; } \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} - +\indexlibraryctor{chunk_by_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current, - range_difference_t<@\exposid{Base}@> missing = 0); +constexpr explicit chunk_by_view(V base, Pred pred); \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}. +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 @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> - && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +constexpr const Pred& pred() const; \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_}. +Equivalent to: \tcode{return *\exposid{pred_};} \end{itemdescr} +\indexlibrarymember{begin}{chunk_by_view}% \begin{itemdecl} -constexpr value_type operator*() const; +constexpr @\exposid{iterator}@ begin(); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}. +\tcode{\exposid{pred_}.has_value()} 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}. +\tcode{\exposid{iterator}(*this, ranges::begin(\exposid{base_}), \exposid{find-next}(ranges::begin(\exposid{base_})))}. \pnum -\effects -Equivalent to: -\begin{codeblock} -@\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{n_}@, @\exposid{end_}@); -return *this; -\end{codeblock} +\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} +\indexlibrarymember{end}{chunk_by_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int); +constexpr auto end(); \end{itemdecl} \begin{itemdescr} @@ -13101,175 +15713,158 @@ \effects Equivalent to: \begin{codeblock} -auto tmp = *this; -++*this; -return tmp; +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} +\indexlibrarymember{\exposid{find-next}}{chunk_by_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +constexpr iterator_t @\exposid{find-next}@(iterator_t current); \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} +\expects +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. -\begin{itemdescr} \pnum -\effects -Equivalent to: +\returns \begin{codeblock} -auto tmp = *this; ---*this; -return tmp; +ranges::next(ranges::adjacent_find(current, ranges::end(@\exposid{base_}@), not_fn(ref(*@\exposid{pred_}@))), + 1, ranges::end(@\exposid{base_}@)) \end{codeblock} \end{itemdescr} +\indexlibrarymember{\exposid{find-prev}}{chunk_by_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr iterator_t @\exposid{find-prev}@(iterator_t current) requires @\libconcept{bidirectional_range}@; \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} +\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 -\effects -Equivalent to: -\begin{codeblock} -if (x > 0) { - ranges::advance(@\exposid{current_}@, @\exposid{n_}@ * (x - 1)); - @\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{n_}@, @\exposid{end_}@); -} else if (x < 0) { - ranges::advance(@\exposid{current_}@, @\exposid{n_}@ * x + @\exposid{missing_}@); - @\exposid{missing_}@ = 0; -} -return *this; -\end{codeblock} +\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} -\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} +\rSec3[range.chunk.by.iter]{Class \tcode{chunk_by_view::\exposid{iterator}}} -\begin{itemdecl} -constexpr value_type operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} +\indexlibraryglobal{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 -\begin{itemdescr} -\pnum -\returns -\tcode{*(*this + n)}. -\end{itemdescr} + constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t current, // \expos + iterator_t next); -\begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); -\end{itemdecl} + public: + using value_type = subrange>; + using difference_type = range_difference_t; + using iterator_category = input_iterator_tag; + using iterator_concept = @\seebelow@; -\begin{itemdescr} -\pnum -\returns -\tcode{x.\exposid{current_} == y.\exposid{current_}}. -\end{itemdescr} + @\exposid{iterator}@() = default; -\begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); -\end{itemdecl} + constexpr value_type operator*() const; + constexpr @\exposid{iterator}@& operator++(); + constexpr @\exposid{iterator}@ operator++(int); -\begin{itemdescr} -\pnum -\returns -\tcode{x.\exposid{current_} == x.\exposid{end_}}. -\end{itemdescr} + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; -\begin{itemdecl} -friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; -\end{itemdecl} + 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} -\begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_} < y.\exposid{current_}}. -\end{itemdescr} +\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} +\indexlibraryctor{chunk_by_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t current, iterator_t next); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return y < x;} +Initializes \exposid{parent_} with \tcode{addressof(parent)}, +\exposid{current_} with \tcode{current}, and +\exposid{next_} with \tcode{next}. \end{itemdescr} +\indexlibrarymember{operator*}{chunk_by_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr value_type operator*() const; \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} +\expects +\exposid{current_} is not equal to \exposid{next_}. -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return !(x < y);} +\returns +\tcode{subrange(\exposid{current_}, \exposid{next_})}. \end{itemdescr} +\indexlibrarymember{operator++}{chunk_by_view::\exposid{iterator}}% \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}@>; +constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +\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} +\indexlibrarymember{operator++}{chunk_by_view::\exposid{iterator}}% \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}@>; +constexpr @\exposid{iterator}@ operator++(int); \end{itemdecl} \begin{itemdescr} @@ -13277,15 +15872,15 @@ \effects Equivalent to: \begin{codeblock} -auto r = i; -r += n; -return r; +auto tmp = *this; +++*this; +return tmp; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{chunk_by_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; \end{itemdecl} \begin{itemdescr} @@ -13293,232 +15888,183 @@ \effects Equivalent to: \begin{codeblock} -auto r = i; -r -= n; -return r; +@\exposid{next_}@ = @\exposid{current_}@; +@\exposid{current_}@ = @\exposid{parent_}@->@\exposid{find-prev}@(@\exposid{next_}@); +return *this; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{chunk_by_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{(x.\exposid{current_} - y.\exposid{current_} + x.\exposid{missing_} - y.\exposid{missing_}) / x.\exposid{n_}}. +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator==}{chunk_by_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{iterator}@& x) - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{\exposid{div-ceil}(x.\exposid{end_} - x.\exposid{current_}, x.\exposid{n_})}. +\tcode{x.\exposid{current_} == y.\exposid{current_}}. \end{itemdescr} +\indexlibrarymember{operator==}{chunk_by_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t y) - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return -(y - x);} +\returns +\tcode{x.\exposid{current_} == x.\exposid{next_}}. \end{itemdescr} -\rSec2[range.slide]{Slide view} +\rSec2[range.stride]{Stride view} -\rSec3[range.slide.overview]{Overview} +\rSec3[range.stride.overview]{Overview} \pnum -\tcode{slide_view} takes a view and a number $N$ and -produces a view -whose $M^\text{th}$ element is a view over -the $M^\text{th}$ through -$(M + N - 1)^\text{th}$ elements -of the original view. -If the original view has fewer than $N$ elements, -the resulting view is empty. +\tcode{stride_view} presents a view of an underlying sequence, +advancing over $n$ elements at a time, +as opposed to the usual single-step succession. \pnum -\indexlibrarymember{slide}{views}% -The name \tcode{views::slide} denotes +The name \tcode{views::stride} 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)}. +the expression \tcode{views::stride(E, N)} +is expression-equivalent to \tcode{stride_view(E, N)}. + +\pnum \begin{example} \begin{codeblock} -vector v = {1, 2, 3, 4}; - -for (auto i : v | views::slide(2)) { - cout << '[' << i[0] << ", " << i[1] << "] "; // prints \tcode{[1, 2] [2, 3] [3, 4]} -} +auto input = views::iota(0, 12) | views::stride(3); +ranges::copy(input, ostream_iterator(cout, " ")); // prints \tcode{0 3 6 9} +ranges::copy(input | views::reverse, ostream_iterator(cout, " ")); // prints \tcode{9 6 3 0} \end{codeblock} \end{example} -\rSec3[range.slide.view]{Class template \tcode{slide_view}} +\rSec3[range.stride.view]{Class template \tcode{stride_view}} -\indexlibrarymember{begin}{slide_view}% -\indexlibrarymember{end}{slide_view}% -\indexlibrarymember{size}{slide_view}% +\indexlibraryglobal{stride_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> + template<@\libconcept{input_range}@ V> requires @\libconcept{view}@ - class slide_view : public view_interface> { - V @\exposid{base_}@; // \expos - range_difference_t @\exposid{n_}@; // \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 - + class stride_view : public view_interface> { + V @\exposid{base_}@; // \expos + range_difference_t @\exposid{stride_}@; // \expos + // \ref{range.stride.iterator}, class template \tcode{stride_view::\exposid{iterator}} + template class @\exposid{iterator}@; // \expos public: - constexpr explicit slide_view(V base, range_difference_t n); + constexpr explicit stride_view(V base, range_difference_t stride); 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}@ && @\exposconcept{slide-caches-nothing}@)); - constexpr auto begin() const requires @\exposconcept{slide-caches-nothing}@; + constexpr range_difference_t stride() const noexcept; - constexpr auto end() - requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); - constexpr auto end() const requires @\exposconcept{slide-caches-nothing}@; + constexpr auto begin() requires (!@\exposconcept{simple-view}@) { + return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); + } + + constexpr auto begin() const requires @\libconcept{range}@ { + return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); + } + + constexpr auto end() requires (!@\exposconcept{simple-view}@) { + if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@ && @\libconcept{forward_range}@) { + auto missing = (@\exposid{stride_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{stride_}@) % @\exposid{stride_}@; + 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{range}@ { + if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@ && @\libconcept{forward_range}@) { + auto missing = (@\exposid{stride_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{stride_}@) % @\exposid{stride_}@; + 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}@; + + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; }; template - slide_view(R&&, range_difference_t) -> slide_view>; + stride_view(R&&, range_difference_t) -> stride_view>; } \end{codeblock} +\indexlibraryctor{stride_view}% \begin{itemdecl} -constexpr explicit slide_view(V base, range_difference_t n); +constexpr stride_view(V base, range_difference_t stride); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{n > 0} is \tcode{true}. +\tcode{stride > 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 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} - -\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-first}. +\exposid{stride_} with \tcode{stride}. \end{itemdescr} +\indexlibrarymember{stride}{stride_view}% \begin{itemdecl} -constexpr auto begin() const requires @\exposconcept{slide-caches-nothing}@; +constexpr range_difference_t stride() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{\exposid{iterator}(ranges::begin(\exposid{base_}), \exposid{n_})}. +\exposid{stride_}. \end{itemdescr} +\indexlibrarymember{size}{stride_view}% \begin{itemdecl} -constexpr auto end() - requires (!(@\exposconcept{simple-view}@ && @\exposconcept{slide-caches-nothing}@)); +constexpr auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; \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}, +\effects +Equivalent to: \begin{codeblock} -@\exposid{iterator}@(ranges::end(@\exposid{base_}@), ranges::end(@\exposid{base_}@), @\exposid{n_}@) +return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{stride_}@)); \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} +\indexlibrarymember{reserve_hint}{stride_view}% \begin{itemdecl} -constexpr auto size() requires @\libconcept{sized_range}@; -constexpr auto size() const requires @\libconcept{sized_range}@; +constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; +constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; \end{itemdecl} \begin{itemdescr} @@ -13526,80 +16072,101 @@ \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); +auto s = static_cast>(ranges::reserve_hint(@\exposid{base_}@)); +return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(s, @\exposid{stride_}@)); \end{codeblock} \end{itemdescr} -\rSec3[range.slide.iterator]{Class template \tcode{slide_view::\exposid{iterator}}} +\rSec3[range.stride.iterator]{Class template \tcode{stride_view::\exposid{iterator}}} +\indexlibraryglobal{stride_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{forward_range}@ V> + template<@\libconcept{input_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 \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}@>); + class stride_view::@\exposid{iterator}@ { + using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos - 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}@>; + 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{stride_}@ = 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::counted(@\exposid{current_}@, @\exposid{n_}@)); using difference_type = range_difference_t<@\exposid{Base}@>; + using value_type = range_value_t<@\exposid{Base}@>; + using iterator_concept = @\seebelow@; + using iterator_category = @\seebelow@; // not always present - @\exposid{iterator}@() = default; - constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; + @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; + + constexpr @\exposid{iterator}@(@\exposid{iterator}@ other) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> + && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; + + constexpr iterator_t<@\exposid{Base}@> base() &&; + constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; + + constexpr decltype(auto) operator*() const { return *@\exposid{current_}@; } - constexpr auto operator*() const; constexpr @\exposid{iterator}@& operator++(); - constexpr @\exposid{iterator}@ operator++(int); + constexpr void operator++(int); + constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; 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 @\exposid{iterator}@& operator+=(difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator-=(difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - constexpr auto operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr decltype(auto) operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@> + { return *(*this + n); } - 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{equality_comparable}@>; 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}@>; + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@>; - friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, 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}@>>; + + friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i) + noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); + + friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@))) + requires @\libconcept{indirectly_swappable}@>; }; } \end{codeblock} @@ -13614,264 +16181,131 @@ 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}. +Otherwise, if \exposid{Base} models \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 -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. - -\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} - -\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. - -\pnum -\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 @\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. - -\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} +The member \grammarterm{typedef-name} \tcode{iterator_category} is defined +if and only if \exposid{Base} models \libconcept{forward_range}. +In that case, +\tcode{\exposid{iterator}::iterator_category} is defined as follows: +\begin{itemize} +\item +Let \tcode{C} denote +the type \tcode{iterator_traits>::iterator_category}. +\item +If \tcode{C} models +\tcode{\libconcept{derived_from}}, +then \tcode{iterator_category} denotes \tcode{ran\-dom_access_iterator_tag}. +\item +Otherwise, \tcode{iterator_category} denotes \tcode{C}. +\end{itemize} +\indexlibraryctor{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current, + range_difference_t<@\exposid{Base}@> missing = 0); \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. - -\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}. +\effects +Initializes \exposid{current_} with \tcode{std::move(current)}, +\exposid{end_} with \tcode{ranges::end(parent->\exposid{base_})}, +\exposid{stride_} with \tcode{parent->\exposid{stride_}}, and +\exposid{missing_} with \tcode{missing}. \end{itemdescr} +\indexlibraryctor{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr auto operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +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 -Equivalent to: \tcode{return views::counted(\exposid{current_} + n, \exposid{n_});} +Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}, +\exposid{end_} with \tcode{std::move(i.\exposid{end_})}, +\exposid{stride_} with \tcode{i.\exposid{stride_}}, and +\exposid{missing_} with \tcode{i.\exposid{missing_}}. \end{itemdescr} +\indexlibrarymember{base}{stride_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +constexpr iterator_t<@\exposid{Base}@> 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_}}. +\tcode{std::move(\exposid{current_})}. \end{itemdescr} +\indexlibrarymember{base}{stride_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{x.\exposid{current_} < y.\exposid{current_}}. +\exposid{current_}. \end{itemdescr} +\indexlibrarymember{operator++}{stride_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@& operator++(); \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} +\expects +\tcode{\exposid{current_} != \exposid{end_}} is \tcode{true}. -\begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !(y < x);} +Equivalent to: +\begin{codeblock} +@\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{stride_}@, @\exposid{end_}@); +return *this; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{stride_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr void operator++(int); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !(x < y);} +Equivalent to \tcode{++*this;} \end{itemdescr} +\indexlibrarymember{operator++}{stride_view::\exposid{iterator}}% \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}@>; +constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{stride_view::\exposid{iterator}}% \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}@>; +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -13879,15 +16313,15 @@ \effects Equivalent to: \begin{codeblock} -auto r = i; -r += n; -return r; +ranges::advance(@\exposid{current_}@, @\exposid{missing_}@ - @\exposid{stride_}@); +@\exposid{missing_}@ = 0; +return *this; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator--}{stride_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} @@ -13895,215 +16329,143 @@ \effects Equivalent to: \begin{codeblock} -auto r = i; -r -= n; -return r; +auto tmp = *this; +--*this; +return tmp; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator+=}{stride_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +constexpr @\exposid{iterator}@& operator+=(difference_type n) requires @\libconcept{random_access_range}@<@\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}}} - -\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 +\expects +If \tcode{n} is positive, +\tcode{ranges::distance(\exposid{current_}, \exposid{end_}) > \exposid{stride_} * (n - 1)} +is \tcode{true}. \begin{note} -\exposid{sentinel} is used -only when \tcode{\exposconcept{slide-caches-first}} is \tcode{true}. +If \tcode{n} is negative, the \Fundescx{Effects} paragraph implies a precondition. \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_}}. +Equivalent to: +\begin{codeblock} +if (n > 0) { + ranges::advance(@\exposid{current_}@, @\exposid{stride_}@ * (n - 1)); + @\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{stride_}@, @\exposid{end_}@); +} else if (n < 0) { + ranges::advance(@\exposid{current_}@, @\exposid{stride_}@ * n + @\exposid{missing_}@); + @\exposid{missing_}@ = 0; +} +return *this; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-=}{stride_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr range_difference_t - operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y) - requires @\libconcept{sized_sentinel_for}@, iterator_t>; +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{last_ele_} - y.\exposid{end_}}. +\effects +Equivalent to: \tcode{return *this += -x;} \end{itemdescr} +\indexlibrarymember{operator==}{stride_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr range_difference_t - operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x) - requires @\libconcept{sized_sentinel_for}@, iterator_t>; +friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); \end{itemdecl} \begin{itemdescr} \pnum \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 view and a predicate, and -splits the 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 << "] "; -} -// The above prints \tcode{[1, 2, 2, 3] [0, 4, 5] [2]} -\end{codeblock} -\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 - @\exposidnc{movable-box}@ @\exposid{pred_}@; // \expos - - // \ref{range.chunk.by.iter}, class \tcode{chunk_by_view::\exposid{iterator}} - class @\exposidnc{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_}@); } +\tcode{x.\exposid{current_} == x.\exposid{end_}}. +\end{itemdescr} - constexpr const Pred& pred() const; +\indexlibrarymember{operator==}{stride_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{equality_comparable}@>; +\end{itemdecl} - constexpr @\exposid{iterator}@ begin(); - constexpr auto end(); +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} == y.\exposid{current_}}. +\end{itemdescr} - constexpr iterator_t @\exposidnc{find-next}@(iterator_t); // \expos - constexpr iterator_t @\exposidnc{find-prev}@(iterator_t) // \expos - requires @\libconcept{bidirectional_range}@; - }; +\indexlibrarymember{operator<}{stride_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} - template - chunk_by_view(R&&, Pred) -> chunk_by_view, Pred>; -} -\end{codeblock} +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} < y.\exposid{current_}}. +\end{itemdescr} +\indexlibrarymember{operator>}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit chunk_by_view(V base, Pred pred); +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 -Initializes \exposid{base_} with \tcode{std::move(base)} and -\exposid{pred_} with \tcode{std::move(pred)}. +Equivalent to: \tcode{return y < x;} \end{itemdescr} -\indexlibrarymember{pred}{chunk_by_view}% +\indexlibrarymember{operator<=}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr const Pred& pred() const; +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 *\exposid{pred_};} +Equivalent to: \tcode{return !(y < x);} \end{itemdescr} +\indexlibrarymember{operator>=}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ begin(); +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{\exposid{pred_}.has_value()} is \tcode{true}. +\effects +Equivalent to: \tcode{return !(x < y);} +\end{itemdescr} -\pnum -\returns -\tcode{\exposid{iterator}(*this, ranges::begin(\exposid{base_}), \exposid{find-next}(ranges::begin(\exposid{base_})))}. +\indexlibrarymember{operator<=>}{stride_view::\exposid{iterator}}% +\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 -\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. +\returns +\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. \end{itemdescr} +\indexlibrarymember{operator+}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr auto end(); +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} @@ -14111,151 +16473,253 @@ \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; -} +auto r = i; +r += n; +return r; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr iterator_t @\exposid{find-next}@(iterator_t current); +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{\exposid{pred_}.has_value()} is \tcode{true}. - -\pnum -\returns +\effects +Equivalent to: \begin{codeblock} -ranges::next(ranges::adjacent_find(current, ranges::end(@\exposid{base_}@), not_fn(ref(*@\exposid{pred_}@))), - 1, ranges::end(@\exposid{base_}@)) +auto r = i; +r -= n; +return r; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}% \begin{itemdecl} -constexpr iterator_t @\exposid{find-prev}@(iterator_t current) requires @\libconcept{bidirectional_range}@; +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 -\expects +\returns +Let \tcode{N} be \tcode{(x.\exposid{current_} - y.\exposid{current_})}. \begin{itemize} \item -\tcode{current} is not equal to \tcode{ranges::begin(\exposid{base_})}. +If \exposid{Base} models \libconcept{forward_range}, +\tcode{(N + x.\exposid{missing_} - y.\exposid{missing_}) / x.\exposid{stride_}}. \item -\tcode{\exposid{pred_}.has_value()} is \tcode{true}. +Otherwise, if \tcode{N} is negative, \tcode{-\exposid{div-ceil}(-N, x.\exposid{stride_})}. +\item +Otherwise, \tcode{\exposid{div-ceil}(N, x.\exposid{stride_})}. \end{itemize} +\end{itemdescr} + +\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}% +\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 -An iterator \tcode{i} -in the range \range{ranges::begin(\exposid{base_})}{current} such that: +\tcode{\exposid{div-ceil}(x.\exposid{end_} - x.\exposid{current_}, x.\exposid{stride_})}. +\end{itemdescr} + +\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}% +\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} + +\indexlibrarymember{iter_move}{stride_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i) + noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});} +\end{itemdescr} + +\indexlibrarymember{iter_swap}{stride_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@))) + requires @\libconcept{indirectly_swappable}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_});} +\end{itemdescr} + +\rSec2[range.cartesian]{Cartesian product view} + +\rSec3[range.cartesian.overview]{Overview} + +\indexlibraryglobal{cartesian_product_view}% +\pnum +\tcode{cartesian_product_view} takes any non-zero number of ranges $n$ and +produces a view of tuples calculated by +the $n$-ary cartesian product of the provided ranges. + +\pnum +The name \tcode{views::cartesian_product} denotes a customization point object\iref{customization.point.object}. +Given a pack of subexpressions \tcode{Es}, +the expression \tcode{views::cartesian_product(Es...)} +is expression-equivalent to \begin{itemize} \item -\tcode{ranges::adjacent_find(i, current, not_fn(ref(*\exposid{pred_})))} is equal to \tcode{current}; and +\tcode{views::single(tuple())} +if \tcode{Es} is an empty pack, \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}. +otherwise, +\tcode{cartesian_product_view...>(Es...)}. \end{itemize} -\end{itemdescr} -\rSec3[range.chunk.by.iter]{Class \tcode{chunk_by_view::\exposid{iterator}}} +\pnum +\begin{example} +\begin{codeblock} +vector v { 0, 1, 2 }; +for (auto&& [a, b, c] : views::cartesian_product(v, v, v)) { + cout << a << ' ' << b << ' ' << c << '\n'; +} +// The above prints +// \tcode{0 0 0} +// \tcode{0 0 1} +// \tcode{0 0 2} +// \tcode{0 1 0} +// \tcode{0 1 1} +// ... +\end{codeblock} +\end{example} +\rSec3[range.cartesian.view]{Class template \tcode{cartesian_product_view}} + +\indexlibraryglobal{cartesian_product_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::@\exposid{iterator}@ { - chunk_by_view* @\exposid{parent_}@ = nullptr; // \expos - iterator_t @\exposid{current_}@ = iterator_t(); // \expos - iterator_t @\exposid{next_}@ = iterator_t(); // \expos + template + concept @\defexposconcept{cartesian-product-is-random-access}@ = // \expos + (@\libconcept{random_access_range}@<@\exposid{maybe-const}@> && ... && + (@\libconcept{random_access_range}@<@\exposid{maybe-const}@> + && @\libconcept{sized_range}@<@\exposid{maybe-const}@>)); + + template + concept @\defexposconcept{cartesian-product-common-arg}@ = // \expos + @\libconcept{common_range}@ || (@\libconcept{sized_range}@ && @\libconcept{random_access_range}@); + + template + concept @\defexposconcept{cartesian-product-is-bidirectional}@ = // \expos + (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@> && ... && + (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@> + && @\exposconcept{cartesian-product-common-arg}@<@\exposid{maybe-const}@>)); + + template + concept @\defexposconcept{cartesian-product-is-common}@ = // \expos + @\exposconcept{cartesian-product-common-arg}@; + + template + concept @\defexposconcept{cartesian-product-is-sized}@ = // \expos + (@\libconcept{sized_range}@ && ...); + + template class FirstSent, class First, class... Vs> + concept @\defexposconcept{cartesian-is-sized-sentinel}@ = // \expos + (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ... + && (@\libconcept{sized_range}@<@\exposid{maybe-const}@> + && @\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>>)); + + template<@\exposconcept{cartesian-product-common-arg}@ R> + constexpr auto @\exposid{cartesian-common-arg-end}@(R& r) { // \expos + if constexpr (@\libconcept{common_range}@) { + return ranges::end(r); + } else { + return ranges::begin(r) + ranges::distance(r); + } + } - constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t current, // \expos - iterator_t next); + template<@\libconcept{input_range}@ First, @\libconcept{forward_range}@... Vs> + requires (@\libconcept{view}@ && ... && @\libconcept{view}@) + class cartesian_product_view : public view_interface> { + private: + tuple @\exposid{bases_}@; // \expos + // \ref{range.cartesian.iterator}, class template \tcode{cartesian_product_view::\exposid{iterator}} + template class @\exposid{iterator}@; // \expos 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 cartesian_product_view() = default; + constexpr explicit cartesian_product_view(First first_base, Vs... bases); - constexpr value_type operator*() const; - constexpr @\exposid{iterator}@& operator++(); - constexpr @\exposid{iterator}@ operator++(int); + constexpr @\exposid{iterator}@ begin() + requires (!@\exposconcept{simple-view}@ || ... || !@\exposconcept{simple-view}@); + constexpr @\exposid{iterator}@ begin() const + requires (@\libconcept{range}@ && ... && @\libconcept{range}@); - constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; - constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; + constexpr @\exposid{iterator}@ end() + requires ((!@\exposconcept{simple-view}@ || ... || !@\exposconcept{simple-view}@) && + @\exposconcept{cartesian-product-is-common}@); + constexpr @\exposid{iterator}@ end() const + requires @\exposconcept{cartesian-product-is-common}@; + constexpr default_sentinel_t end() const noexcept; - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); - friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); + constexpr @\seebelow@ size() + requires @\exposconcept{cartesian-product-is-sized}@; + constexpr @\seebelow@ size() const + requires @\exposconcept{cartesian-product-is-sized}@; }; + + template + cartesian_product_view(Vs&&...) -> cartesian_product_view...>; } \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} - +\indexlibraryctor{cartesian_product_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@(chunk_by_view& parent, iterator_t current, iterator_t next); +constexpr explicit cartesian_product_view(First first_base, Vs... bases); \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_})}. +Initializes \exposid{bases_} +with \tcode{std::move(first_base), std::move(bases)...}. \end{itemdescr} +\indexlibrarymember{begin}{cartesian_product_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator++(); +constexpr @\exposid{iterator}@ begin() + requires (!@\exposconcept{simple-view}@ || ... || !@\exposconcept{simple-view}@); \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; +return @\exposid{iterator}@(*this, @\exposid{tuple-transform}@(ranges::begin, @\exposid{bases_}@)); \end{codeblock} \end{itemdescr} +\indexlibrarymember{begin}{cartesian_product_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int); +constexpr @\exposid{iterator}@ begin() const + requires (@\libconcept{range}@ && ... && @\libconcept{range}@); \end{itemdecl} \begin{itemdescr} @@ -14263,276 +16727,176 @@ \effects Equivalent to: \begin{codeblock} -auto tmp = *this; -++*this; -return tmp; +return @\exposid{iterator}@(*this, @\exposid{tuple-transform}@(ranges::begin, @\exposid{bases_}@)); \end{codeblock} \end{itemdescr} +\indexlibrarymember{end}{cartesian_product_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; +constexpr @\exposid{iterator}@ end() + requires ((!@\exposconcept{simple-view}@ || ... || !@\exposconcept{simple-view}@) + && @\exposconcept{cartesian-product-is-common}@); +constexpr @\exposid{iterator}@ end() const + requires @\exposconcept{cartesian-product-is-common}@; \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} +Let: +\begin{itemize} +\item +\exposid{is-const} be \tcode{true} for the const-qualified overload, and +\tcode{false} otherwise; +\item +\exposid{is-empty} be \tcode{true} +if the expression \tcode{ranges::empty(rng)} is \tcode{true} +for any \tcode{rng} among the underlying ranges except the first one and +\tcode{false} otherwise; and +\item +\tcode{\exposid{begin-or-first-end}(rng)} be expression-equivalent to +\tcode{\exposid{is-empty} ? ranges::begin(rng) : \brk{}\exposid{cartesian-common-arg-end}(rng)} +if \tcode{rng} is the first underlying range and +\tcode{ranges::begin(rng)} otherwise. +\end{itemize} -\begin{itemdescr} \pnum \effects Equivalent to: \begin{codeblock} -auto tmp = *this; ---*this; -return tmp; +@\exposid{iterator}@<@\exposid{is-const}@> it(*this, @\exposid{tuple-transform}@( + [](auto& rng){ return @\exposid{begin-or-first-end}@(rng); }, @\exposid{bases_}@)); +return it; \end{codeblock} \end{itemdescr} +\indexlibrarymember{end}{cartesian_product_view}% \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); +constexpr default_sentinel_t end() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{x.\exposid{current_} == x.\exposid{next_}}. +\tcode{default_sentinel}. \end{itemdescr} -\rSec2[range.stride]{Stride view} - -\rSec3[range.stride.overview]{Overview} - -\pnum -\tcode{stride_view} presents a view of an underlying sequence, -advancing over $n$ elements at a time, -as opposed to the usual single-step succession. - -\pnum -The name \tcode{views::stride} denotes -a range adaptor object\iref{range.adaptor.object}. -Given subexpressions \tcode{E} and \tcode{N}, -the expression \tcode{views::stride(E, N)} -is expression-equivalent to \tcode{stride_view(E, N)}. - -\pnum -\begin{example} -\begin{codeblock} -auto input = views::iota(0, 12) | views::stride(3); -ranges::copy(input, ostream_iterator(cout, " ")); // prints \tcode{0 3 6 9} -ranges::copy(input | views::reverse, ostream_iterator(cout, " ")); // prints \tcode{9 6 3 0} -\end{codeblock} -\end{example} - -\rSec3[range.stride.view]{Class template \tcode{stride_view}} - -\begin{codeblock} -namespace std::ranges { - template<@\libconcept{input_range}@ V> - requires @\libconcept{view}@ - class stride_view : public view_interface> { - V @\exposid{base_}@; // \expos - range_difference_t @\exposid{stride_}@; // \expos - // \ref{range.stride.iterator}, class template \tcode{stride_view::\exposid{iterator}} - template class @\exposid{iterator}@; // \expos - public: - constexpr explicit stride_view(V base, range_difference_t stride); - - constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } - constexpr V base() && { return std::move(@\exposid{base_}@); } - - constexpr range_difference_t stride() const noexcept; - - constexpr auto begin() requires (!@\exposconcept{simple-view}@) { - return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); - } - - constexpr auto begin() const requires @\libconcept{range}@ { - return @\exposid{iterator}@(this, ranges::begin(@\exposid{base_}@)); - } - - constexpr auto end() requires (!@\exposconcept{simple-view}@) { - if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@ && @\libconcept{forward_range}@) { - auto missing = (@\exposid{stride_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{stride_}@) % @\exposid{stride_}@; - 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{range}@ { - if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@ && @\libconcept{forward_range}@) { - auto missing = (@\exposid{stride_}@ - ranges::distance(@\exposid{base_}@) % @\exposid{stride_}@) % @\exposid{stride_}@; - 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}@; - }; - - template - stride_view(R&&, range_difference_t) -> stride_view>; -} -\end{codeblock} - -\indexlibraryctor{stride_view}% +\indexlibrarymember{size}{cartesian_product_view}% \begin{itemdecl} -constexpr stride_view(V base, range_difference_t stride); +constexpr @\seebelow@ size() + requires @\exposconcept{cartesian-product-is-sized}@; +constexpr @\seebelow@ size() const + requires @\exposconcept{cartesian-product-is-sized}@; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{stride > 0} is \tcode{true}. +The return type is an \impldef{return type of \tcode{cartesian_product_view::size}} unsigned-integer-like type. \pnum -\effects -Initializes \exposid{base_} with \tcode{std::move(base)} and -\exposid{stride_} with \tcode{stride}. -\end{itemdescr} - -\indexlibrarymember{stride}{stride_view}% -\begin{itemdecl} -constexpr range_difference_t stride() const noexcept; -\end{itemdecl} +\recommended +The return type should be the smallest unsigned-integer-like type +that is sufficiently wide to store the product of the maximum sizes of +all the underlying ranges, if such a type exists. -\begin{itemdescr} \pnum -\returns -\exposid{stride_}. -\end{itemdescr} +Let $p$ be the product of the sizes of all the ranges in \exposid{bases_}. -\indexlibrarymember{size}{stride_view}% -\begin{itemdecl} -constexpr auto size() requires @\libconcept{sized_range}@; -constexpr auto size() const requires @\libconcept{sized_range}@; -\end{itemdecl} +\pnum +\expects +$p$ can be represented by the return type. -\begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return @\exposid{to-unsigned-like}@(@\exposid{div-ceil}@(ranges::distance(@\exposid{base_}@), @\exposid{stride_}@)); -\end{codeblock} +\returns +$p$. \end{itemdescr} -\rSec3[range.stride.iterator]{Class template \tcode{stride_view::\exposid{iterator}}} +\rSec3[range.cartesian.iterator]{Class template \tcode{cartesian_product_view::\exposid{iterator}}} +\indexlibraryglobal{cartesian_product_view::\exposid{iterator}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{input_range}@ V> - requires @\libconcept{view}@ + template<@\libconcept{input_range}@ First, @\libconcept{forward_range}@... Vs> + requires (@\libconcept{view}@ && ... && @\libconcept{view}@) template - class stride_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{stride_}@ = 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); + class cartesian_product_view::@\exposid{iterator}@ { public: - using difference_type = range_difference_t<@\exposid{Base}@>; - using value_type = range_value_t<@\exposid{Base}@>; - using iterator_concept = @\seebelow@; - using iterator_category = @\seebelow@; // not always present - - @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; - - constexpr @\exposid{iterator}@(@\exposid{iterator}@ other) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> - && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; + using iterator_category = input_iterator_tag; + using iterator_concept = @\seebelow@; + using value_type = tuple>, + range_value_t<@\exposid{maybe-const}@>...>; + using reference = tuple>, + range_reference_t<@\exposid{maybe-const}@>...>; + using difference_type = @\seebelow@; - constexpr iterator_t<@\exposid{Base}@> base() &&; - constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; + @\exposid{iterator}@() = default; - constexpr decltype(auto) operator*() const { return *@\exposid{current_}@; } + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) requires Const && + (@\libconcept{convertible_to}@, iterator_t> && + ... && @\libconcept{convertible_to}@, iterator_t>); + constexpr auto operator*() const; constexpr @\exposid{iterator}@& operator++(); constexpr void operator++(int); - constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{maybe-const}@>; - 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--() + requires @\exposconcept{cartesian-product-is-bidirectional}@; + constexpr @\exposid{iterator}@ operator--(int) + requires @\exposconcept{cartesian-product-is-bidirectional}@; - constexpr @\exposid{iterator}@& operator+=(difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - constexpr @\exposid{iterator}@& operator-=(difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\exposconcept{cartesian-product-is-random-access}@; + constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\exposconcept{cartesian-product-is-random-access}@; - constexpr decltype(auto) operator[](difference_type n) const - requires @\libconcept{random_access_range}@<@\exposid{Base}@> - { return *(*this + n); } + constexpr reference operator[](difference_type n) const + requires @\exposconcept{cartesian-product-is-random-access}@; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{equality_comparable}@>>; 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{equality_comparable}@>; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; - friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) + requires @\exposconcept{cartesian-product-is-random-access}@; + friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) + requires @\exposconcept{cartesian-product-is-random-access}@; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) + requires @\exposconcept{cartesian-product-is-random-access}@; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{cartesian-is-sized-sentinel}@; - friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& i, default_sentinel_t) + requires @\exposconcept{cartesian-is-sized-sentinel}@; + friend constexpr difference_type operator-(default_sentinel_t, const @\exposid{iterator}@& i) + requires @\exposconcept{cartesian-is-sized-sentinel}@; - friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); - friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires (@\libconcept{indirectly_swappable}@>> && ... && + @\libconcept{indirectly_swappable}@>>); - friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@>; + private: + using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos + @\exposidnc{Parent}@* @\exposidnc{parent_}@ = nullptr; // \expos + tuple>, + iterator_t<@\exposidnc{maybe-const}@>...> @\exposidnc{current_}@; // \expos - friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; - friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, 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}@>>; + template + constexpr void @\exposidnc{next}@(); // \expos - 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}@>>; + template + constexpr void @\exposidnc{prev}@(); // \expos - friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i) - noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); + template + constexpr difference_type @\exposidnc{distance-from}@(const Tuple& t) const; // \expos - friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@))) - requires @\libconcept{indirectly_swappable}@>; + constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, tuple>, + iterator_t<@\exposidnc{maybe-const}@>...> current); // \expos }; } \end{codeblock} @@ -14541,108 +16905,170 @@ \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}. +If \tcode{\exposconcept{cartesian-product-is-random-access}} +is modeled, +then \tcode{iterator_con\-cept} denotes \tcode{random_access_iterator_tag}. \item -Otherwise, if \exposid{Base} models \libconcept{bidirectional_range}, -then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +Otherwise, +if \tcode{\exposconcept{cartesian-product-is-bidirectional}} +is modeled, +then \tcode{it\-erator_concept} denotes \tcode{bidirectional_iterator_tag}. \item -Otherwise, if \exposid{Base} models \libconcept{forward_range}, +Otherwise, +if \tcode{\exposid{maybe-const}} models \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{Base} models \libconcept{forward_range}. -In that case, -\tcode{\exposid{iterator}::iterator_category} is defined as follows: +\tcode{\exposid{iterator}::difference_type} is +an \impldef{type of \tcode{ranges::cartesian_product_view::\exposid{iterator}::difference_type}} +signed-integer-like type. + +\pnum +\recommended +\tcode{\exposid{iterator}::difference_type} should be +the smallest signed-integer-like type +that is sufficiently wide to store +the product of the maximum sizes of all underlying ranges +if such a type exists. + +\indexlibrarymember{\exposid{next}}{cartesian_product_view}% +\begin{itemdecl} +template + constexpr void @\exposid{next}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto& it = std::get(@\exposid{current_}@); +++it; +if constexpr (N > 0) { + if (it == ranges::end(std::get(@\exposid{parent_}@->@\exposid{bases_}@))) { + it = ranges::begin(std::get(@\exposid{parent_}@->@\exposid{bases_}@)); + @\exposid{next}@(); + } +} +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{\exposid{prev}}{cartesian_product_view}% +\begin{itemdecl} +template + constexpr void @\exposid{prev}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto& it = std::get(@\exposid{current_}@); +if constexpr (N > 0) { + if (it == ranges::begin(std::get(@\exposid{parent_}@->@\exposid{bases_}@))) { + it = @\exposid{cartesian-common-arg-end}@(std::get(@\exposid{parent_}@->@\exposid{bases_}@)); + @\exposid{prev}@(); + } +} +--it; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{\exposid{distance-from}}{cartesian_product_view}% +\begin{itemdecl} +template + constexpr difference_type @\exposid{distance-from}@(const Tuple& t) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let: \begin{itemize} \item -Let \tcode{C} denote -the type \tcode{iterator_traits>::iterator_category}. +$\exposid{scaled-size}(N)$ be the product of +\tcode{static_cast(ranges::size(std::get<\brk{}$N$>(\exposid{parent_}->\exposid{bases_})))} and +$\exposid{scaled-size}(N+1)$ +if $N \le \tcode{sizeof...(Vs)}$, otherwise \tcode{static_cast(1)}; \item -If \tcode{C} models -\tcode{\libconcept{derived_from}}, -then \tcode{iterator_category} denotes \tcode{ran\-dom_access_iterator_tag}. +$\exposid{scaled-distance}(N)$ be the product of +\tcode{static_cast(std::get<$N$>(\exposid{cur\-rent_}) - std::get<$N$>(t))} and $\exposid{scaled-size}(N+1)$; and \item -Otherwise, \tcode{iterator_category} denotes \tcode{C}. +\exposid{scaled-sum} be the sum of $\exposid{scaled-distance}(N)$ +for every integer $0 \le N \le \tcode{sizeof...(Vs)}$. \end{itemize} -\indexlibraryctor{stride_view::\exposid{iterator}}% -\begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{Parent}@* parent, iterator_t<@\exposid{Base}@> current, - range_difference_t<@\exposid{Base}@> missing = 0); -\end{itemdecl} +\pnum +\expects +\exposid{scaled-sum} can be represented by \tcode{difference_type}. -\begin{itemdescr} \pnum -\effects -Initializes \exposid{current_} with \tcode{std::move(current)}, -\exposid{end_} with \tcode{ranges::end(parent->\exposid{base_})}, -\exposid{stride_} with \tcode{parent->\exposid{stride_}}, and -\exposid{missing_} with \tcode{missing}. +\returns +\exposid{scaled-sum}. \end{itemdescr} -\indexlibraryctor{stride_view::\exposid{iterator}}% +\indexlibraryctor{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) - requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> - && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, tuple>, + iterator_t<@\exposid{maybe-const}@>...> current); \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{stride_} with \tcode{i.\exposid{stride_}}, and -\exposid{missing_} with \tcode{i.\exposid{missing_}}. +Initializes +\exposid{parent_} with \tcode{addressof(parent)} and +\exposid{current_} with \tcode{std::move(current)}. \end{itemdescr} -\indexlibrarymember{base}{stride_view::\exposid{iterator}}% +\indexlibraryctor{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -constexpr iterator_t<@\exposid{Base}@> base() &&; +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) requires Const && + (@\libconcept{convertible_to}@, iterator_t> && + ... && @\libconcept{convertible_to}@, iterator_t>); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{std::move(\exposid{current_})}. +\effects +Initializes +\exposid{parent_} with \tcode{i.\exposid{parent_}} and +\exposid{current_} with \tcode{std::move(i.\exposid{current_})}. \end{itemdescr} -\indexlibrarymember{base}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator*}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; +constexpr auto operator*() const; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\exposid{current_}. +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator++}{cartesian_product_view::\exposid{iterator}}% \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{stride_}@, @\exposid{end_}@); +@\exposid{next}@(); return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator++}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator++}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} constexpr void operator++(int); \end{itemdecl} @@ -14650,12 +17076,12 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{++*this;} +Equivalent to \tcode{++*this}. \end{itemdescr} -\indexlibrarymember{operator++}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator++}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{maybe-const}@>; \end{itemdecl} \begin{itemdescr} @@ -14669,9 +17095,10 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator--}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@& operator--() + requires @\exposconcept{cartesian-product-is-bidirectional}@; \end{itemdecl} \begin{itemdescr} @@ -14679,15 +17106,15 @@ \effects Equivalent to: \begin{codeblock} -ranges::advance(@\exposid{current_}@, @\exposid{missing_}@ - @\exposid{stride_}@); -@\exposid{missing_}@ = 0; +@\exposid{prev}@(); return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator--}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator--}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@ operator--(int) + requires @\exposconcept{cartesian-product-is-bidirectional}@; \end{itemdecl} \begin{itemdescr} @@ -14701,49 +17128,88 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator+=}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator+=}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type n) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\exposconcept{cartesian-product-is-random-access}@; \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{orig} be the value of \tcode{*this} before the call. + +Let \tcode{ret} be: +\begin{itemize} +\item +If \tcode{x > 0}, +the value of \tcode{*this} had \exposid{next} been called \tcode{x} times. +\item +Otherwise, if \tcode{x < 0}, +the value of \tcode{*this} had \exposid{prev} been called \tcode{-x} times. +\item +Otherwise, \tcode{orig}. +\end{itemize} + \pnum \expects -If \tcode{n} is positive, -\tcode{ranges::distance(\exposid{current_}, \exposid{end_}) > \exposid{stride_} * (n - 1)} -is \tcode{true}. -\begin{note} -If \tcode{n} is negative, the \Fundescx{Effects} paragraph implies a precondition. -\end{note} +\tcode{x} is in the range +$[\tcode{ranges::distance(*this, ranges::begin(*\exposid{parent_}))},$\newline +$\tcode{ranges::distance(*this, ranges::end(*\exposid{parent_}))}]$. + +\pnum +\effects +Sets the value of \tcode{*this} to \tcode{ret}. + +\pnum +\returns +\tcode{*this}. + +\pnum +\complexity +Constant. +\end{itemdescr} + +\indexlibrarymember{operator-=}{cartesian_product_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\exposconcept{cartesian-product-is-random-access}@; +\end{itemdecl} +\begin{itemdescr} \pnum \effects Equivalent to: \begin{codeblock} -if (n > 0) { - ranges::advance(@\exposid{current_}@, @\exposid{stride_}@ * (n - 1)); - @\exposid{missing_}@ = ranges::advance(@\exposid{current_}@, @\exposid{stride_}@, @\exposid{end_}@); -} else if (n < 0) { - ranges::advance(@\exposid{current_}@, @\exposid{stride_}@ * n + @\exposid{missing_}@); - @\exposid{missing_}@ = 0; -} +*this += -x; return *this; \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator-=}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator[]}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +constexpr reference operator[](difference_type n) const + requires @\exposconcept{cartesian-product-is-random-access}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return *this += -x;} +Equivalent to: \tcode{return *((*this) + n);} \end{itemdescr} -\indexlibrarymember{operator==}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator==}{cartesian_product_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{equality_comparable}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};} +\end{itemdescr} + +\indexlibrarymember{operator==}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); \end{itemdecl} @@ -14751,337 +17217,352 @@ \begin{itemdescr} \pnum \returns -\tcode{x.\exposid{current_} == x.\exposid{end_}}. +\tcode{true} if \tcode{std::get<$i$>(x.\exposid{current_}) == ranges::end(std::get<$i$>(x.\exposid{parent_}->\exposid{bases_}))} +is \tcode{true} +for any integer $0 \le i \le \tcode{sizeof...(Vs)}$; +otherwise, \tcode{false}. \end{itemdescr} -\indexlibrarymember{operator==}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator<=>}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@>; +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_} == y.\exposid{current_}}. +\effects +Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};} \end{itemdescr} -\indexlibrarymember{operator<}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator+}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) + requires @\exposconcept{cartesian-product-is-random-access}@; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_} < y.\exposid{current_}}. +\effects +Equivalent to: \tcode{return \exposid{iterator}(x) += y;} \end{itemdescr} -\indexlibrarymember{operator>}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator+}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) + requires @\exposconcept{cartesian-product-is-random-access}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return y < x;} +Equivalent to: \tcode{return y + x;} \end{itemdescr} -\indexlibrarymember{operator<=}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) + requires @\exposconcept{cartesian-product-is-random-access}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !(y < x);} +Equivalent to: \tcode{return \exposid{iterator}(x) -= y;} \end{itemdescr} -\indexlibrarymember{operator>=}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{cartesian-is-sized-sentinel}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return !(x < y);} +Equivalent to: \tcode{return x.\exposid{distance-from}(y.\exposid{current_});} \end{itemdescr} -\indexlibrarymember{operator<=>}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{cartesian_product_view::\exposid{iterator}}% \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}@>; +friend constexpr difference_type operator-(const @\exposid{iterator}@& i, default_sentinel_t) + requires @\exposconcept{cartesian-is-sized-sentinel}@; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +Let \exposid{end-tuple} be an object of a type +that is a specialization of \tcode{tuple}, such that: +\begin{itemize} +\item +\tcode{std::get<0>(\exposid{end-tuple})} has the same value as +\tcode{ranges::end(std::get<0>(i.\exposid{parent_}->\exposid{ba\-ses_}))}; +\item +\tcode{std::get<$N$>(\exposid{end-tuple})} has the same value as +\tcode{ranges::begin(std::get<$N$>(i.\exposid{parent_}->\exposid{bases_}))} +for every integer $1 \le N \le \tcode{sizeof...(Vs)}$. +\end{itemize} + +\pnum +\effects +Equivalent to: \tcode{return i.\exposid{distance-from}(\exposid{end-tuple});} \end{itemdescr} -\indexlibrarymember{operator+}{stride_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{cartesian_product_view::\exposid{iterator}}% \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}@>; +friend constexpr difference_type operator-(default_sentinel_t s, const @\exposid{iterator}@& i) + requires @\exposconcept{cartesian-is-sized-sentinel}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -auto r = i; -r += n; -return r; -\end{codeblock} +Equivalent to: \tcode{return -(i - s);} \end{itemdescr} -\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}% +\indexlibrarymember{iter_move}{cartesian_product_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) - requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{tuple-transform}(ranges::iter_move, i.\exposid{current_});} + +\pnum +\remarks +The exception specification is equivalent to +the logical \logop{and} of the following expressions: +\begin{itemize} +\item +\tcode{noexcept(ranges::iter_move(std::get<$N$>(i.\exposid{current_})))} +for every integer\newline $0 \le N \le \tcode{sizeof...(Vs)}$, +\item +\tcode{is_nothrow_move_constructible_v>>}\newline +for every type \tcode{T} in \tcode{First, Vs...}. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{iter_swap}{cartesian_product_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires (@\libconcept{indirectly_swappable}@>> && ... && + @\libconcept{indirectly_swappable}@>>); \end{itemdecl} -\begin{itemdescr} +\begin{itemdescr} +\pnum +\effects +For every integer $0 \le i \le \tcode{sizeof...(Vs)}$, performs: +\begin{codeblock} +ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@)) +\end{codeblock} + +\pnum +\remarks +The exception specification is equivalent to the logical \logop{and} of the following expressions: +\begin{itemize} +\item +\tcode{noexcept(ranges::iter_swap(std::get<$i$>(l.\exposid{current_}), std::get<$i$>(r.\exposid{current_})))} +for\newline every integer $0 \le i \le \tcode{sizeof...(Vs)}$. +\end{itemize} +\end{itemdescr} + +\rSec2[range.cache.latest]{Cache latest view} + +\rSec3[range.cache.latest.overview]{Overview} + \pnum -\effects -Equivalent to: +\tcode{cache_latest_view} caches the last-accessed element of +its underlying sequence +so that the element does not have to be recomputed on repeated access. +\begin{note} +This is useful if computation of the element to produce is expensive. +\end{note} + +\pnum +The name \tcode{views::cache_latest} denotes +a range adaptor object\iref{range.adaptor.object}. +Let \tcode{E} be an expression. +The expression \tcode{views::cache_latest(E)} is expression-equivalent to +\tcode{cache_latest_view(E)}. + +\rSec3[range.cache.latest.view]{Class template \tcode{cache_latest_view}} + \begin{codeblock} -auto r = i; -r -= n; -return r; +namespace std::ranges { + template<@\libconcept{input_range}@ V> + requires @\libconcept{view}@ + class @\libglobal{cache_latest_view}@ : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + using @\exposid{cache-t}@ = conditional_t>, // \expos + add_pointer_t>, + range_reference_t>; + + @\exposid{non-propagating-cache}@<@\exposid{cache-t}@> @\exposid{cache_}@; // \expos + + // \ref{range.cache.latest.iterator}, class \tcode{cache_latest_view::\exposid{iterator}} + class @\exposid{iterator}@; // \expos + // \ref{range.cache.latest.sentinel}, class \tcode{cache_latest_view::\exposid{sentinel}} + class @\exposid{sentinel}@; // \expos + + public: + cache_latest_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit cache_latest_view(V base); + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + + constexpr auto begin(); + constexpr auto end(); + + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; + + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; + }; + + template + cache_latest_view(R&&) -> cache_latest_view>; +} \end{codeblock} -\end{itemdescr} -\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}% +\indexlibraryctor{cache_latest_view}% \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +constexpr explicit cache_latest_view(V base); \end{itemdecl} \begin{itemdescr} \pnum -\returns -Let \tcode{N} be \tcode{(x.\exposid{current_} - y.\exposid{current_})}. -\begin{itemize} -\item -If \exposid{Base} models \libconcept{forward_range}, -\tcode{(N + x.\exposid{missing_} - y.\exposid{missing_}) / x.\exposid{stride_}}. -\item -Otherwise, if \tcode{N} is negative, \tcode{-\exposid{div-ceil}(-N, x.\exposid{stride_})}. -\item -Otherwise, \tcode{\exposid{div-ceil}(N, x.\exposid{stride_})}. -\end{itemize} +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}. \end{itemdescr} -\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}% +\indexlibrarymember{begin}{cache_latest_view}% \begin{itemdecl} -friend constexpr difference_type operator-(default_sentinel_t y, const @\exposid{iterator}@& x) - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +constexpr auto begin(); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{\exposid{div-ceil}(x.\exposid{end_} - x.\exposid{current_}, x.\exposid{stride_})}. +\effects +Equivalent to: \tcode{return \exposid{iterator}(*this);} \end{itemdescr} -\indexlibrarymember{operator-}{stride_view::\exposid{iterator}}% +\indexlibrarymember{end}{cache_latest_view}% \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, default_sentinel_t y) - requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +constexpr auto end(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return -(y - x);} +Equivalent to: \tcode{return \exposid{sentinel}(*this);} \end{itemdescr} -\indexlibrarymember{iter_move}{stride_view::\exposid{iterator}}% +\indexlibrarymember{size}{cache_latest_view}% \begin{itemdecl} -friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i) - noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); +constexpr auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});} +Equivalent to: \tcode{return ranges::size(\exposid{base_});} \end{itemdescr} -\indexlibrarymember{iter_swap}{stride_view::\exposid{iterator}}% +\indexlibrarymember{reserve_hint}{cache_latest_view}% \begin{itemdecl} -friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@))) - requires @\libconcept{indirectly_swappable}@>; +constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; +constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_});} +Equivalent to: \tcode{return ranges::reserve_hint(\exposid{base_});} \end{itemdescr} -\rSec2[range.cartesian]{Cartesian product view} - -\rSec3[range.cartesian.overview]{Overview} - -\indexlibraryglobal{cartesian_product_view}% -\pnum -\tcode{cartesian_product_view} takes any non-zero number of ranges $n$ and -produces a view of tuples calculated by -the $n$-ary cartesian product of the provided ranges. - -\pnum -The name \tcode{views::cartesian_product} denotes a customization point object\iref{customization.point.object}. -Given a pack of subexpressions \tcode{Es}, -the expression \tcode{views::cartesian_product(Es...)} -is expression-equivalent to -\begin{itemize} -\item -\tcode{views::single(tuple())} -if \tcode{Es} is an empty pack, -\item -otherwise, -\tcode{cartesian_product_view...>(Es...)}. -\end{itemize} - -\pnum -\begin{example} -\begin{codeblock} -vector v { 0, 1, 2 }; -for (auto&& [a, b, c] : views::cartesian_product(v, v, v)) { - cout << a << ' ' << b << ' ' << c << '\n'; -} -// The above prints -// \tcode{0 0 0} -// \tcode{0 0 1} -// \tcode{0 0 2} -// \tcode{0 1 0} -// \tcode{0 1 1} -// ... -\end{codeblock} -\end{example} - -\rSec3[range.cartesian.view]{Class template \tcode{cartesian_product_view}} +\rSec3[range.cache.latest.iterator]{Class \tcode{cache_latest_view::\exposid{iterator}}} +\indexlibraryglobal{cache_latest_view::\exposid{iiterator}}% \begin{codeblock} namespace std::ranges { - template - concept @\defexposconcept{cartesian-product-is-random-access}@ = // \expos - (@\libconcept{random_access_range}@<@\exposid{maybe-const}@> && ... && - (@\libconcept{random_access_range}@<@\exposid{maybe-const}@> - && @\libconcept{sized_range}@<@\exposid{maybe-const}@>)); - - template - concept @\defexposconcept{cartesian-product-common-arg}@ = // \expos - @\libconcept{common_range}@ || (@\libconcept{sized_range}@ && @\libconcept{random_access_range}@); - - template - concept @\defexposconcept{cartesian-product-is-bidirectional}@ = // \expos - (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@> && ... && - (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@> - && @\exposconcept{cartesian-product-common-arg}@<@\exposid{maybe-const}@>)); - - template - concept @\defexposconcept{cartesian-product-is-common}@ = // \expos - @\exposconcept{cartesian-product-common-arg}@; + template<@\libconcept{input_range}@ V> + requires @\libconcept{view}@ + class cache_latest_view::@\exposid{iterator}@ { + cache_latest_view* @\exposid{parent_}@; // \expos + iterator_t @\exposid{current_}@; // \expos - template - concept @\defexposconcept{cartesian-product-is-sized}@ = // \expos - (@\libconcept{sized_range}@ && ...); + constexpr explicit @\exposid{iterator}@(cache_latest_view& parent); // \expos - template class FirstSent, class First, class... Vs> - concept @\defexposconcept{cartesian-is-sized-sentinel}@ = // \expos - (@\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>> && ... - && (@\libconcept{sized_range}@<@\exposid{maybe-const}@> - && @\libconcept{sized_sentinel_for}@>, - iterator_t<@\exposid{maybe-const}@>>)); + public: + using difference_type = range_difference_t; + using value_type = range_value_t; + using iterator_concept = input_iterator_tag; - template<@\exposconcept{cartesian-product-common-arg}@ R> - constexpr auto @\exposid{cartesian-common-arg-end}@(R& r) { // \expos - if constexpr (@\libconcept{common_range}@) { - return ranges::end(r); - } else { - return ranges::begin(r) + ranges::distance(r); - } - } + @\exposid{iterator}@(@\exposid{iterator}@&&) = default; + @\exposid{iterator}@& operator=(@\exposid{iterator}@&&) = default; - template<@\libconcept{input_range}@ First, @\libconcept{forward_range}@... Vs> - requires (@\libconcept{view}@ && ... && @\libconcept{view}@) - class cartesian_product_view : public view_interface> { - private: - tuple @\exposid{bases_}@; // \expos - // \ref{range.cartesian.iterator}, class template \tcode{cartesian_product_view::\exposid{iterator}} - template class @\exposid{iterator}@; // \expos + constexpr iterator_t base() &&; + constexpr const iterator_t& base() const & noexcept; - public: - constexpr cartesian_product_view() = default; - constexpr explicit cartesian_product_view(First first_base, Vs... bases); + constexpr range_reference_t& operator*() const; - constexpr @\exposid{iterator}@ begin() - requires (!@\exposconcept{simple-view}@ || ... || !@\exposconcept{simple-view}@); - constexpr @\exposid{iterator}@ begin() const - requires (@\libconcept{range}@ && ... && @\libconcept{range}@); + constexpr @\exposid{iterator}@& operator++(); + constexpr void operator++(int); - constexpr @\exposid{iterator}@ end() - requires ((!@\exposconcept{simple-view}@ || ... || !@\exposconcept{simple-view}@) && - @\exposconcept{cartesian-product-is-common}@); - constexpr @\exposid{iterator}@ end() const - requires @\exposconcept{cartesian-product-is-common}@; - constexpr default_sentinel_t end() const noexcept; + friend constexpr range_rvalue_reference_t iter_move(const @\exposid{iterator}@& i) + noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); - constexpr @\seebelow@ size() - requires @\exposconcept{cartesian-product-is-sized}@; - constexpr @\seebelow@ size() const - requires @\exposconcept{cartesian-product-is-sized}@; + friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@))) + requires @\libconcept{indirectly_swappable}@>; }; - - template - cartesian_product_view(Vs&&...) -> cartesian_product_view...>; } \end{codeblock} +\indexlibraryctor{cache_latest_view::\exposid{iterator}}% \begin{itemdecl} -constexpr explicit cartesian_product_view(First first_base, Vs... bases); +constexpr explicit @\exposid{iterator}@(cache_latest_view& parent); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes \exposid{bases_} -with \tcode{std::move(first_base), std::move(bases)...}. +Initializes \exposid{current_} with +\tcode{ranges::begin(parent.\exposid{base_})} +and \exposid{parent_} with \tcode{addressof(par\-ent)}. \end{itemdescr} +\indexlibrarymember{base}{cache_latest_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ begin() - requires (!@\exposconcept{simple-view}@ || ... || !@\exposconcept{simple-view}@); +constexpr iterator_t base() &&; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return @\exposid{iterator}@(*this, @\exposid{tuple-transform}@(ranges::begin, @\exposid{bases_}@)); -\end{codeblock} +\returns +\tcode{std::move(\exposid{current_})}. \end{itemdescr} +\indexlibrarymember{base}{cache_latest_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ begin() const - requires (@\libconcept{range}@ && ... && @\libconcept{range}@); +constexpr const iterator_t& base() const & noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{current_}. +\end{itemdescr} + +\indexlibrarymember{operator++}{cache_latest_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} @@ -15089,618 +17570,481 @@ \effects Equivalent to: \begin{codeblock} -return @\exposid{iterator}@(*this, @\exposid{tuple-transform}@(ranges::begin, @\exposid{bases_}@)); +@\exposid{parent_}@->@\exposid{cache_}@.reset(); +++@\exposid{current_}@; +return *this; \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{cache_latest_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ end() - requires ((!@\exposconcept{simple-view}@ || ... || !@\exposconcept{simple-view}@) - && @\exposconcept{cartesian-product-is-common}@); -constexpr @\exposid{iterator}@ end() const - requires @\exposconcept{cartesian-product-is-common}@; +constexpr void operator++(int); \end{itemdecl} \begin{itemdescr} \pnum -Let: -\begin{itemize} -\item -\exposid{is-const} be \tcode{true} for the const-qualified overload, and -\tcode{false} otherwise; -\item -\exposid{is-empty} be \tcode{true} -if the expression \tcode{ranges::empty(rng)} is \tcode{true} -for any \tcode{rng} among the underlying ranges except the first one and -\tcode{false} otherwise; and -\item -\tcode{\exposid{begin-or-first-end}(rng)} be expression-equivalent to -\tcode{\exposid{is-empty} ? ranges::begin(rng) : \brk{}\exposid{cartesian-common-arg-end}(rng)} -if \tcode{rng} is the first underlying range and -\tcode{ranges::begin(rng)} otherwise. -\end{itemize} +\effects +Equivalent to: \tcode{++*this}. +\end{itemdescr} +\indexlibrarymember{operator*}{cache_latest_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr range_reference_t& operator*() const; +\end{itemdecl} + +\begin{itemdescr} \pnum \effects Equivalent to: \begin{codeblock} -@\exposid{iterator}@<@\exposid{is-const}@> it(*this, @\exposid{tuple-transform}@( - [](auto& rng){ return @\exposid{begin-or-first-end}@(rng); }, @\exposid{bases_}@)); -return it; +if constexpr (is_reference_v>) { + if (!@\exposid{parent_}@->@\exposid{cache_}@) { + @\exposid{parent_}@->@\exposid{cache_}@ = addressof(@\exposid{as-lvalue}@(*@\exposid{current_}@)); + } + return **@\exposid{parent_}@->@\exposid{cache_}@; +} else { + if (!@\exposid{parent_}@->c@\exposid{ache_}@) { + @\exposid{parent_}@->@\exposid{cache_}@.@\exposid{emplace-deref}@(@\exposid{current_}@); + } + return *@\exposid{parent_}@->@\exposid{cache_}@; +} \end{codeblock} +\begin{note} +Evaluations of \tcode{operator*} on the same iterator object +can conflict\iref{intro.races}. +\end{note} \end{itemdescr} +\indexlibrarymember{iter_move}{cache_latest_view::\exposid{iterator}}% \begin{itemdecl} -constexpr default_sentinel_t end() const noexcept; +friend constexpr range_rvalue_reference_t iter_move(const @\exposid{iterator}@& i) + noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{default_sentinel}. +\effects +Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});} \end{itemdescr} +\indexlibrarymember{iter_swap}{cache_latest_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\seebelow@ size() - requires @\exposconcept{cartesian-product-is-sized}@; -constexpr @\seebelow@ size() const - requires @\exposconcept{cartesian-product-is-sized}@; +friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@))) + requires @\libconcept{indirectly_swappable}@>; \end{itemdecl} \begin{itemdescr} \pnum -The return type is an \impldef{return type of \tcode{cartesian_product_view::size}} unsigned-integer-like type. - -\pnum -\recommended -The return type should be the smallest unsigned-integer-like type -that is sufficiently wide to store the product of the maximum sizes of -all the underlying ranges, if such a type exists. - -\pnum -Let $p$ be the product of the sizes of all the ranges in \exposid{bases_}. - -\pnum -\expects -$p$ can be represented by the return type. - -\pnum -\returns -$p$. +\effects +Equivalent to +\tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_})}. \end{itemdescr} -\rSec3[range.cartesian.iterator]{Class template \tcode{cartesian_product_view::\exposid{iterator}}} +\rSec3[range.cache.latest.sentinel]{Class \tcode{cache_latest_view::\exposid{sentinel}}} +\indexlibraryglobal{cache_latest_view::\exposid{sentinel}}% \begin{codeblock} namespace std::ranges { - template<@\libconcept{input_range}@ First, @\libconcept{forward_range}@... Vs> - requires (@\libconcept{view}@ && ... && @\libconcept{view}@) - template - class cartesian_product_view::@\exposid{iterator}@ { - public: - using iterator_category = input_iterator_tag; - using iterator_concept = @\seebelow@; - using value_type = tuple>, - range_value_t<@\exposid{maybe-const}@>...>; - using reference = tuple>, - range_reference_t<@\exposid{maybe-const}@>...>; - using difference_type = @\seebelow@; - - @\exposid{iterator}@() = default; - - constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) requires Const && - (@\libconcept{convertible_to}@, iterator_t> && - ... && @\libconcept{convertible_to}@, iterator_t>); - - constexpr auto operator*() const; - constexpr @\exposid{iterator}@& operator++(); - constexpr void operator++(int); - constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{maybe-const}@>; - - constexpr @\exposid{iterator}@& operator--() - requires @\exposconcept{cartesian-product-is-bidirectional}@; - constexpr @\exposid{iterator}@ operator--(int) - requires @\exposconcept{cartesian-product-is-bidirectional}@; - - constexpr @\exposid{iterator}@& operator+=(difference_type x) - requires @\exposconcept{cartesian-product-is-random-access}@; - constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\exposconcept{cartesian-product-is-random-access}@; - - constexpr reference operator[](difference_type n) const - requires @\exposconcept{cartesian-product-is-random-access}@; - - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@>>; - - friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); - - friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposconcept{all-random-access}@; - - friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) - requires @\exposconcept{cartesian-product-is-random-access}@; - friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) - requires @\exposconcept{cartesian-product-is-random-access}@; - friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) - requires @\exposconcept{cartesian-product-is-random-access}@; - friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposconcept{cartesian-is-sized-sentinel}@; - - friend constexpr difference_type operator-(const @\exposid{iterator}@& i, default_sentinel_t) - requires @\exposconcept{cartesian-is-sized-sentinel}@; - friend constexpr difference_type operator-(default_sentinel_t, const @\exposid{iterator}@& i) - requires @\exposconcept{cartesian-is-sized-sentinel}@; - - friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); - - friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) - requires (@\libconcept{indirectly_swappable}@>> && ... && - @\libconcept{indirectly_swappable}@>>); + template<@\libconcept{input_range}@ V> + requires @\libconcept{view}@ + class cache_latest_view::@\exposid{sentinel}@ { + sentinel_t @\exposid{end_}@ = sentinel_t(); // \expos - private: - using @\exposidnc{Parent}@ = @\exposidnc{maybe-const}@; // \expos - @\exposidnc{Parent}@* @\exposidnc{parent_}@ = nullptr; // \expos - tuple>, - iterator_t<@\exposidnc{maybe-const}@>...> @\exposidnc{current_}@; // \expos + constexpr explicit @\exposid{sentinel}@(cache_latest_view& parent); // \expos - template - constexpr void @\exposidnc{next}@(); // \expos + public: + @\exposid{sentinel}@() = default; - template - constexpr void @\exposidnc{prev}@(); // \expos + constexpr sentinel_t base() const; - template - constexpr difference_type @\exposidnc{distance-from}@(const Tuple& t) const; // \expos + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); - constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, tuple>, - iterator_t<@\exposidnc{maybe-const}@>...> current); // \expos + 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}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; }; } \end{codeblock} -\pnum -\tcode{\exposid{iterator}::iterator_concept} is defined as follows: -\begin{itemize} -\item -If \tcode{\exposconcept{cartesian-product-is-random-access}} -is modeled, -then \tcode{iterator_con\-cept} denotes \tcode{random_access_iterator_tag}. -\item -Otherwise, -if \tcode{\exposconcept{cartesian-product-is-bidirectional}} -is modeled, -then \tcode{it\-erator_concept} denotes \tcode{bidirectional_iterator_tag}. -\item -Otherwise, -if \tcode{\exposid{maybe-const}} models \libconcept{forward_range}, -then \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. -\item -Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. -\end{itemize} +\indexlibraryctor{cache_latest_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(cache_latest_view& parent); +\end{itemdecl} +\begin{itemdescr} \pnum -\tcode{\exposid{iterator}::difference_type} is -an \impldef{type of \tcode{ranges::cartesian_product_view::\exposid{iterator}::difference_type}} -signed-integer-like type. +\effects +Initializes \exposid{end_} with \tcode{ranges::end(parent.\exposid{base_})}. +\end{itemdescr} -\pnum -\recommended -\tcode{\exposid{iterator}::difference_type} should be -the smallest signed-integer-like type -that is sufficiently wide to store -the product of the maximum sizes of all underlying ranges -if such a type exists. +\indexlibrarymember{base}{cache_latest_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr sentinel_t base() const; +\end{itemdecl} +\begin{itemdescr} \pnum +\returns +\exposid{end_}. +\end{itemdescr} + +\indexlibrarymember{operator==}{cache_latest_view::\exposid{iterator}}% +\indexlibrarymember{operator==}{cache_latest_view::\exposid{sentinel}}% \begin{itemdecl} -template - constexpr void @\exposid{next}@(); +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -auto& it = std::get(@\exposid{current_}@); -++it; -if constexpr (N > 0) { - if (it == ranges::end(std::get(@\exposid{parent_}@->@\exposid{bases_}@))) { - it = ranges::begin(std::get(@\exposid{parent_}@->@\exposid{bases_}@)); - @\exposid{next}@(); - } -} -\end{codeblock} +\returns +\tcode{x.\exposid{current_} == y.\exposid{end_}}. \end{itemdescr} +\indexlibrarymember{operator-}{cache_latest_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{cache_latest_view::\exposid{sentinel}}% \begin{itemdecl} -template - constexpr void @\exposid{prev}@(); +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 -\effects -Equivalent to: -\begin{codeblock} -auto& it = std::get(@\exposid{current_}@); -if constexpr (N > 0) { - if (it == ranges::begin(std::get(@\exposid{parent_}@->@\exposid{bases_}@))) { - it = @\exposid{cartesian-common-arg-end}@(std::get(@\exposid{parent_}@->@\exposid{bases_}@)); - @\exposid{prev}@(); - } -} ---it; -\end{codeblock} +\returns +\tcode{x.\exposid{current_} - y.\exposid{end_}}. \end{itemdescr} +\indexlibrarymember{operator-}{cache_latest_view::\exposid{iterator}}% +\indexlibrarymember{operator-}{cache_latest_view::\exposid{sentinel}}% \begin{itemdecl} -template - constexpr difference_type @\exposid{distance-from}@(const Tuple& t) const; +friend constexpr range_difference_t operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t>; \end{itemdecl} \begin{itemdescr} \pnum -Let: +\returns +\tcode{x.\exposid{end_} - y.\exposid{current_}}. +\end{itemdescr} + +\rSec2[range.to.input]{To input view} + +\rSec3[range.to.input.overview]{Overview} + +\pnum +\tcode{to_input_view} presents a view of an underlying sequence +as an input-only non-common range. +\begin{note} +This is useful to avoid overhead +that can be necessary to provide support for the operations +needed for greater iterator strength. +\end{note} + +\pnum +The name \tcode{views::to_input} denotes +a range adaptor object\iref{range.adaptor.object}. +Let \tcode{E} be an expression and let \tcode{T} be \tcode{decltype((E))}. +The expression \tcode{views::to_input(E)} is expression-equivalent to: \begin{itemize} \item -$\exposid{scaled-size}(N)$ be the product of -\tcode{static_cast(ranges::size(std::get<\brk{}$N$>(\exposid{parent_}->\exposid{bases_})))} and -$\exposid{scaled-size}(N+1)$ -if $N \le \tcode{sizeof...(Vs)}$, otherwise \tcode{static_cast(1)}; -\item -$\exposid{scaled-distance}(N)$ be the product of -\tcode{static_cast(std::get<$N$>(\exposid{cur\-rent_}) - std::get<$N$>(t))} and $\exposid{scaled-size}(N+1)$; and +\tcode{views::all(E)} +if \tcode{T} models \libconcept{input_range}, +does not satisfy \libconcept{common_range}, and +does not satisfy \libconcept{forward_range}. \item -\exposid{scaled-sum} be the sum of $\exposid{scaled-distance}(N)$ -for every integer $0 \le N \le \tcode{sizeof...(Vs)}$. +Otherwise, \tcode{to_input_view(E)}. \end{itemize} -\pnum -\expects -\exposid{scaled-sum} can be represented by \tcode{difference_type}. +\rSec3[range.to.input.view]{Class template \tcode{to_input_view}} -\pnum -\returns -\exposid{scaled-sum}. -\end{itemdescr} +\indexlibraryglobal{to_input_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@ V> + requires @\libconcept{view}@ + class to_input_view : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + + // \ref{range.to.input.iterator}, class template \tcode{to_input_view::\exposid{iterator}} + template class @\exposid{iterator}@; // \expos + + public: + to_input_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit to_input_view(V 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}@); + constexpr auto begin() const requires @\libconcept{range}@; + + constexpr auto end() requires (!@\exposconcept{simple-view}@); + constexpr auto end() const requires @\libconcept{range}@; + + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; + + constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; + constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; + }; + + template + to_input_view(R&&) -> to_input_view>; +} +\end{codeblock} +\indexlibraryctor{to_input_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, tuple>, - iterator_t<@\exposid{maybe-const}@>...> current); +constexpr explicit to_input_view(V base); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes -\exposid{parent_} with \tcode{addressof(parent)} and -\exposid{current_} with \tcode{std::move(current)}. +Initializes \exposid{base_} with \tcode{std::move(base)}. \end{itemdescr} +\indexlibrarymember{begin}{to_input_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) requires Const && - (@\libconcept{convertible_to}@, iterator_t> && - ... && @\libconcept{convertible_to}@, iterator_t>); +constexpr auto begin() requires (!@\exposconcept{simple-view}@); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes -\exposid{parent_} with \tcode{i.\exposid{parent_}} and -\exposid{current_} with \tcode{std::move(i.\exposid{current_})}. +Equivalent to: \tcode{return \exposid{iterator}(ranges::begin(\exposid{base_}));} \end{itemdescr} +\indexlibrarymember{begin}{to_input_view}% \begin{itemdecl} -constexpr auto operator*() const; +constexpr auto begin() const requires @\libconcept{range}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); -\end{codeblock} +Equivalent to: \tcode{return \exposid{iterator}(ranges::begin(\exposid{base_}));} \end{itemdescr} +\indexlibrarymember{end}{to_input_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator++(); +constexpr auto end() requires (!@\exposconcept{simple-view}@); +constexpr auto end() const requires @\libconcept{range}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -@\exposid{next}@(); -return *this; -\end{codeblock} +Equivalent to: \tcode{return ranges::end(\exposid{base_});} \end{itemdescr} +\indexlibrarymember{size}{to_input_view}% \begin{itemdecl} -constexpr void operator++(int); +constexpr auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to \tcode{++*this}. +Equivalent to: \tcode{return ranges::size(\exposid{base_});} \end{itemdescr} +\indexlibrarymember{reserve_hint}{to_input_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{maybe-const}@>; +constexpr auto reserve_hint() requires @\libconcept{approximately_sized_range}@; +constexpr auto reserve_hint() const requires @\libconcept{approximately_sized_range}@; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -auto tmp = *this; -++*this; -return tmp; -\end{codeblock} +Equivalent to: \tcode{return ranges::reserve_hint(\exposid{base_});} \end{itemdescr} -\begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() - requires @\exposconcept{cartesian-product-is-bidirectional}@; -\end{itemdecl} +\rSec3[range.to.input.iterator]{Class template \tcode{to_input_view::\exposid{iterator}}} -\begin{itemdescr} -\pnum -\effects -Equivalent to: +\indexlibraryglobal{to_input_view::\exposid{iterator}}% \begin{codeblock} -@\exposid{prev}@(); -return *this; -\end{codeblock} -\end{itemdescr} +namespace std::ranges { + template<@\libconcept{input_range}@ V> + requires @\libconcept{view}@ + template + class to_input_view::@\exposid{iterator}@ { + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos -\begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) - requires @\exposconcept{cartesian-product-is-bidirectional}@; -\end{itemdecl} + iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -auto tmp = *this; ---*this; -return tmp; -\end{codeblock} -\end{itemdescr} + constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); // \expos -\begin{itemdecl} -constexpr @\exposid{iterator}@& operator+=(difference_type x) - requires @\exposconcept{cartesian-product-is-random-access}@; -\end{itemdecl} + public: + using difference_type = range_difference_t<@\exposid{Base}@>; + using value_type = range_value_t<@\exposid{Base}@>; + using iterator_concept = input_iterator_tag; -\begin{itemdescr} -\pnum -Let \tcode{orig} be the value of \tcode{*this} before the call. + @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; -Let \tcode{ret} be: -\begin{itemize} -\item -If \tcode{x > 0}, -the value of \tcode{*this} had \exposid{next} been called \tcode{x} times. -\item -Otherwise, if \tcode{x < 0}, -the value of \tcode{*this} had \exposid{prev} been called \tcode{-x} times. -\item -Otherwise, \tcode{orig}. -\end{itemize} + @\exposid{iterator}@(@\exposid{iterator}@&&) = default; + @\exposid{iterator}@& operator=(@\exposid{iterator}@&&) = default; -\pnum -\expects -\tcode{x} is in the range -$[\tcode{ranges::distance(*this, ranges::begin(*\exposid{parent_}))},$\newline -$\tcode{ranges::distance(*this, ranges::end(*\exposid{parent_}))}]$. + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; -\pnum -\effects -Sets the value of \tcode{*this} to \tcode{ret}. + constexpr iterator_t<@\exposid{Base}@> base() &&; + constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; -\pnum -\returns -\tcode{*this}. + constexpr decltype(auto) operator*() const { return *@\exposid{current_}@; } -\pnum -\complexity -Constant. -\end{itemdescr} + constexpr @\exposid{iterator}@& operator++(); + constexpr void operator++(int); -\begin{itemdecl} -constexpr @\exposid{iterator}@& operator-=(difference_type x) - requires @\exposconcept{cartesian-product-is-random-access}@; -\end{itemdecl} + friend constexpr bool operator==(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y); -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -*this += -x; -return *this; + friend constexpr difference_type operator-(const sentinel_t<@\exposid{Base}@>& y, const @\exposid{iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; + + friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i) + noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); + + friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@))) + requires @\libconcept{indirectly_swappable}@>; + }; +} \end{codeblock} -\end{itemdescr} +\indexlibraryctor{to_input_view::\exposid{iterator}}% \begin{itemdecl} -constexpr reference operator[](difference_type n) const - requires @\exposconcept{cartesian-product-is-random-access}@; +constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return *((*this) + n);} +Initializes \exposid{current_} with \tcode{std::move(current)}. \end{itemdescr} +\indexlibraryctor{to_input_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@>>; +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{current_};} +Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}. \end{itemdescr} +\indexlibrarymember{base}{to_input_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, default_sentinel_t); +constexpr iterator_t<@\exposid{Base}@> base() &&; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{true} if \tcode{std::get<$i$>(x.\exposid{current_}) == ranges::end(std::get<$i$>(x.\exposid{parent_}->\exposid{bases_}))} -is \tcode{true} -for any integer $0 \le i \le \tcode{sizeof...(Vs)}$; -otherwise, \tcode{false}. -\end{itemdescr} - -\begin{itemdecl} -friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposconcept{all-random-access}@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return x.\exposid{current_} <=> y.\exposid{current_};} +\tcode{std::move(\exposid{current_)}}. \end{itemdescr} +\indexlibrarymember{base}{to_input_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) - requires @\exposconcept{cartesian-product-is-random-access}@; +constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \exposid{iterator}(x) += y;} +\returns +\exposid{current_}. \end{itemdescr} +\indexlibrarymember{operator++}{to_input_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) - requires @\exposconcept{cartesian-product-is-random-access}@; +constexpr @\exposid{iterator}@& operator++(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return y + x;} +Equivalent to: +\begin{codeblock} +++@\exposid{current_}@; +return *this; +\end{codeblock} \end{itemdescr} +\indexlibrarymember{operator++}{to_input_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) - requires @\exposconcept{cartesian-product-is-random-access}@; +constexpr void operator++(int); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{iterator}(x) -= y;} +Equivalent to: \tcode{++*this;} \end{itemdescr} +\indexlibrarymember{operator==}{to_input_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\exposconcept{cartesian-is-sized-sentinel}@; +friend constexpr bool operator==(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return x.\exposid{distance-from}(y.\exposid{current_});} +\returns +\tcode{x.\exposid{current_} == y}. \end{itemdescr} +\indexlibrarymember{operator-}{to_input_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr difference_type operator-(const @\exposid{iterator}@& i, default_sentinel_t) - requires @\exposconcept{cartesian-is-sized-sentinel}@; +friend constexpr difference_type operator-(const sentinel_t<@\exposid{Base}@>& y, const @\exposid{iterator}@& x) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum -Let \exposid{end-tuple} be an object of a type -that is a specialization of \tcode{tuple}, such that: -\begin{itemize} -\item -\tcode{std::get<0>(\exposid{end-tuple})} has the same value as -\tcode{ranges::end(std::get<0>(i.\exposid{parent_}->\exposid{ba\-ses_}))}; -\item -\tcode{std::get<$N$>(\exposid{end-tuple})} has the same value as -\tcode{ranges::begin(std::get<$N$>(i.\exposid{parent_}->\exposid{bases_}))} -for every integer $1 \le N \le \tcode{sizeof...(Vs)}$. -\end{itemize} - -\pnum -\effects -Equivalent to: \tcode{return i.\exposid{distance-from}(\exposid{end-tuple});} +\returns +\tcode{y - x.\exposid{current_}}. \end{itemdescr} +\indexlibrarymember{operator-}{to_input_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr difference_type operator-(default_sentinel_t s, const @\exposid{iterator}@& i) - requires @\exposconcept{cartesian-is-sized-sentinel}@; +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return -(i - s);} +\returns +\tcode{x.\exposid{current_} - y}. \end{itemdescr} +\indexlibrarymember{iter_move}{to_input_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); +friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i) + noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return \exposid{tuple-transform}(ranges::iter_move, i.\exposid{current_});} - -\pnum -\remarks -The exception specification is equivalent to -the logical \logop{and} of the following expressions: -\begin{itemize} -\item -\tcode{noexcept(ranges::iter_move(std::get<$N$>(i.\exposid{current_})))} -for every integer\newline $0 \le N \le \tcode{sizeof...(Vs)}$, -\item -\tcode{is_nothrow_move_constructible_v>>}\newline -for every type \tcode{T} in \tcode{First, Vs...}. -\end{itemize} +Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});} \end{itemdescr} +\indexlibrarymember{iter_swap}{to_input_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) - requires (@\libconcept{indirectly_swappable}@>> && ... && - @\libconcept{indirectly_swappable}@>>); +friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_)}@)) + requires @\libconcept{indirectly_swappable}@>; \end{itemdecl} \begin{itemdescr} \pnum \effects -For every integer $0 \le i \le \tcode{sizeof...(Vs)}$, performs: -\begin{codeblock} -ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@)) -\end{codeblock} - -\pnum -\remarks -The exception specification is equivalent to the logical \logop{and} of the following expressions: -\begin{itemize} -\item -\tcode{noexcept(ranges::iter_swap(std::get<$i$>(l.\exposid{current_}), std::get<$i$>(r.\exposid{current_})))} -for\newline every integer $0 \le i \le \tcode{sizeof...(Vs)}$. -\end{itemize} +Equivalent to: \tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_});} \end{itemdescr} \rSec1[coro.generator]{Range generators} @@ -15740,12 +18084,12 @@ \begin{codeblock} namespace std { // \ref{coro.generator.class}, class template \tcode{generator} - template + template class generator; namespace pmr { - template - using generator = std::generator>; + template + using generator = std::generator>; } } \end{codeblock} @@ -15754,11 +18098,11 @@ \begin{codeblock} namespace std { - template - class @\libglobal{generator}@ : public ranges::view_interface> { + template + class @\libglobal{generator}@ : public ranges::view_interface> { private: - using @\exposid{value}@ = conditional_t, remove_cvref_t, V>; // \expos - using @\exposid{reference}@ = conditional_t, Ref&&, Ref>; // \expos + using @\exposid{value}@ = conditional_t, remove_cvref_t, Val>; // \expos + using @\exposid{reference}@ = conditional_t, Ref&&, Ref>; // \expos // \ref{coro.generator.iterator}, class \tcode{generator::\exposid{iterator}} class @\exposidnc{iterator}@; // \expos @@ -15840,7 +18184,7 @@ Initializes \exposid{coroutine_} with \tcode{exchange(other.\exposid{coroutine_}, \{\})} and \exposid{active_} with -\tcode{exchange(\brk{}other.active_, nullptr)}. +\tcode{exchange(\brk{}other.\exposid{active_}, nullptr)}. \pnum \begin{note} @@ -15944,8 +18288,8 @@ \begin{codeblock} namespace std { - template - class generator::promise_type { + template + class generator::promise_type { public: generator get_return_object() noexcept; @@ -15961,6 +18305,9 @@ template requires @\libconcept{same_as}@::yielded, yielded> auto yield_value(ranges::elements_of&&, Unused> g) noexcept; + template + requires @\libconcept{same_as}@::yielded, yielded> + auto yield_value(ranges::elements_of&, Unused> g) noexcept; template requires @\libconcept{convertible_to}@, yielded> @@ -15975,13 +18322,11 @@ requires @\libconcept{same_as}@ || @\libconcept{default_initializable}@; template - requires @\libconcept{same_as}@ || @\libconcept{convertible_to}@ - void* operator new(size_t size, allocator_arg_t, const Alloc& alloc, const Args&...); + void* operator new(size_t size, allocator_arg_t, const Alloc& alloc, const Args&...); template - requires @\libconcept{same_as}@ || @\libconcept{convertible_to}@ - void* operator new(size_t size, const This&, allocator_arg_t, const Alloc& alloc, - const Args&...); + void* operator new(size_t size, const This&, allocator_arg_t, const Alloc& alloc, + const Args&...); void operator delete(void* pointer, size_t size) noexcept; @@ -16088,6 +18433,9 @@ template requires @\libconcept{same_as}@::yielded, yielded> auto yield_value(ranges::elements_of&&, Unused> g) noexcept; +template + requires @\libconcept{same_as}@::yielded, yielded> + auto yield_value(ranges::elements_of&, Unused> g) noexcept; \end{itemdecl} \begin{itemdescr} @@ -16120,7 +18468,7 @@ \pnum \remarks -A \grammarterm{yield-expression} that calls this function +A \grammarterm{yield-expression} that calls one of these functions has type \tcode{void}\iref{expr.yield}. \end{itemdescr} @@ -16137,7 +18485,7 @@ Equivalent to: \begin{codeblock} auto nested = [](allocator_arg_t, Alloc, ranges::iterator_t i, ranges::sentinel_t s) - -> generator, Alloc> { + -> generator { for (; i != s; ++i) { co_yield static_cast(*i); } @@ -16180,11 +18528,9 @@ requires @\libconcept{same_as}@ || @\libconcept{default_initializable}@; template - requires @\libconcept{same_as}@ || @\libconcept{convertible_to}@ void* operator new(size_t size, allocator_arg_t, const Alloc& alloc, const Args&...); template - requires @\libconcept{same_as}@ || @\libconcept{convertible_to}@ void* operator new(size_t size, const This&, allocator_arg_t, const Alloc& alloc, const Args&...); \end{itemdecl} @@ -16207,6 +18553,9 @@ \pnum \mandates \tcode{allocator_traits::pointer} is a pointer type. +For the overloads with a template parameter \tcode{Alloc}, +\tcode{\libconcept{same_as} || \libconcept{convertible_to}} +is modeled. \pnum \effects @@ -16247,8 +18596,8 @@ \begin{codeblock} namespace std { - template - class generator::@\exposid{iterator}@ { + template + class generator::@\exposid{iterator}@ { public: using value_type = @\exposid{value}@; using difference_type = ptrdiff_t; diff --git a/source/regex.tex b/source/regex.tex deleted file mode 100644 index bbec2e9f78..0000000000 --- a/source/regex.tex +++ /dev/null @@ -1,4001 +0,0 @@ -%!TEX root = std.tex -\rSec0[re]{Regular expressions library} -\indextext{regular expression|(} - -\rSec1[re.general]{General} - - -\pnum -This Clause describes components that \Cpp{} programs may use to -perform operations involving regular expression matching and -searching. - -\pnum -The following subclauses describe a basic regular expression class template and its -traits that can handle char-like\iref{strings.general} template arguments, -two specializations of this class template that handle sequences of \tcode{char} and \keyword{wchar_t}, -a class template that holds the -result of a regular expression match, a series of algorithms that allow a character -sequence to be operated upon by a regular expression, -and two iterator types for -enumerating regular expression matches, as summarized in \tref{re.summary}. - -\begin{libsumtab}{Regular expressions library summary}{re.summary} -\ref{re.req} & Requirements & \\ \rowsep -\ref{re.const} & Constants & \tcode{} \\ -\ref{re.badexp} & Exception type & \\ -\ref{re.traits} & Traits & \\ -\ref{re.regex} & Regular expression template & \\ -\ref{re.submatch} & Submatches & \\ -\ref{re.results} & Match results & \\ -\ref{re.alg} & Algorithms & \\ -\ref{re.iter} & Iterators & \\ \rowsep -\ref{re.grammar} & Grammar & \\ -\end{libsumtab} - -\pnum -The ECMAScript Language Specification described in Standard Ecma-262 -is called \defn{ECMA-262} in this Clause. - -\rSec1[re.req]{Requirements} - -\pnum -This subclause defines requirements on classes representing regular -expression traits. -\begin{note} -The class template -\tcode{regex_traits}, defined in \ref{re.traits}, -meets these requirements. -\end{note} - -\pnum -The class template \tcode{basic_regex}, defined in -\ref{re.regex}, needs a set of related types and -functions to complete the definition of its semantics. These types -and functions are provided as a set of member \grammarterm{typedef-name}{s} and functions -in the template parameter \tcode{traits} used by the \tcode{basic_regex} class -template. This subclause defines the semantics of these -members. - -\pnum -To specialize class template \tcode{basic_regex} for a character -container \tcode{CharT} and its related regular -expression traits class \tcode{Traits}, use \tcode{basic_regex}. - -\pnum -\indextext{regular expression traits!requirements}% -\indextext{requirements!regular expression traits}% -\indextext{regular expression!requirements}% -\indextext{locale}% -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}; -\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} - -\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} - -\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} - -\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} -Class template \tcode{regex_traits} meets the requirements for a -regular expression traits class when it is specialized for -\tcode{char} or \keyword{wchar_t}. This class template is described in -the header \libheader{regex}, and is described in \ref{re.traits}. -\end{note} - -\rSec1[re.syn]{Header \tcode{} synopsis} - -\indexheader{regex}% -\indexlibraryglobal{basic_regex}% -\indexlibraryglobal{regex}% -\indexlibraryglobal{wregex}% -\begin{codeblock} -#include // see \ref{compare.syn} -#include // see \ref{initializer.list.syn} - -namespace std { - // \ref{re.const}, regex constants - namespace regex_constants { - using syntax_option_type = @\placeholder{T1}@; - using match_flag_type = @\placeholder{T2}@; - using error_type = @\placeholder{T3}@; - } - - // \ref{re.badexp}, class \tcode{regex_error} - class regex_error; - - // \ref{re.traits}, class template \tcode{regex_traits} - template struct regex_traits; - - // \ref{re.regex}, class template \tcode{basic_regex} - template> class basic_regex; - - using regex = basic_regex; - using wregex = basic_regex; - - // \ref{re.regex.swap}, \tcode{basic_regex} swap - template - void swap(basic_regex& e1, basic_regex& e2); - - // \ref{re.submatch}, class template \tcode{sub_match} - template - class sub_match; - - using csub_match = sub_match; - using wcsub_match = sub_match; - using ssub_match = sub_match; - using wssub_match = sub_match; - - // \ref{re.submatch.op}, \tcode{sub_match} non-member operators - template - bool operator==(const sub_match& lhs, const sub_match& rhs); - template - auto operator<=>(const sub_match& lhs, const sub_match& rhs); - - template - bool operator==( - const sub_match& lhs, - const basic_string::value_type, ST, SA>& rhs); - template - auto operator<=>( - const sub_match& lhs, - const basic_string::value_type, ST, SA>& rhs); - - template - bool operator==(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); - template - auto operator<=>(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); - - template - bool operator==(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); - template - auto operator<=>(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); - - template - basic_ostream& - operator<<(basic_ostream& os, const sub_match& m); - - // \ref{re.results}, class template \tcode{match_results} - template>> - class match_results; - - using cmatch = match_results; - using wcmatch = match_results; - using smatch = match_results; - using wsmatch = match_results; - - // \tcode{match_results} comparisons - template - bool operator==(const match_results& m1, - const match_results& m2); - - // \ref{re.results.swap}, \tcode{match_results} swap - template - void swap(match_results& m1, - match_results& m2); - - // \ref{re.alg.match}, function template \tcode{regex_match} - template - bool regex_match(BidirectionalIterator first, BidirectionalIterator last, - match_results& m, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - bool regex_match(BidirectionalIterator first, BidirectionalIterator last, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - bool regex_match(const charT* str, match_results& m, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - bool regex_match(const basic_string& s, - match_results::const_iterator, - Allocator>& m, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - bool regex_match(const basic_string&&, - match_results::const_iterator, - Allocator>&, - const basic_regex&, - regex_constants::match_flag_type = regex_constants::match_default) = delete; - template - bool regex_match(const charT* str, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - bool regex_match(const basic_string& s, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); - - // \ref{re.alg.search}, function template \tcode{regex_search} - template - bool regex_search(BidirectionalIterator first, BidirectionalIterator last, - match_results& m, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - bool regex_search(BidirectionalIterator first, BidirectionalIterator last, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - bool regex_search(const charT* str, - match_results& m, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - bool regex_search(const charT* str, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - bool regex_search(const basic_string& s, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - bool regex_search(const basic_string& s, - match_results::const_iterator, - Allocator>& m, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - bool regex_search(const basic_string&&, - match_results::const_iterator, - Allocator>&, - const basic_regex&, - regex_constants::match_flag_type - = regex_constants::match_default) = delete; - - // \ref{re.alg.replace}, function template \tcode{regex_replace} - template - OutputIterator - regex_replace(OutputIterator out, - BidirectionalIterator first, BidirectionalIterator last, - const basic_regex& e, - const basic_string& fmt, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - OutputIterator - regex_replace(OutputIterator out, - BidirectionalIterator first, BidirectionalIterator last, - const basic_regex& e, - const charT* fmt, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - basic_string - regex_replace(const basic_string& s, - const basic_regex& e, - const basic_string& fmt, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - basic_string - regex_replace(const basic_string& s, - const basic_regex& e, - const charT* fmt, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - basic_string - regex_replace(const charT* s, - const basic_regex& e, - const basic_string& fmt, - regex_constants::match_flag_type flags = regex_constants::match_default); - template - basic_string - regex_replace(const charT* s, - const basic_regex& e, - const charT* fmt, - regex_constants::match_flag_type flags = regex_constants::match_default); - - // \ref{re.regiter}, class template \tcode{regex_iterator} - template::value_type, - class traits = regex_traits> - class regex_iterator; - - using cregex_iterator = regex_iterator; - using wcregex_iterator = regex_iterator; - using sregex_iterator = regex_iterator; - using wsregex_iterator = regex_iterator; - - // \ref{re.tokiter}, class template \tcode{regex_token_iterator} - template::value_type, - class traits = regex_traits> - class regex_token_iterator; - - using cregex_token_iterator = regex_token_iterator; - using wcregex_token_iterator = regex_token_iterator; - using sregex_token_iterator = regex_token_iterator; - using wsregex_token_iterator = regex_token_iterator; - - namespace pmr { - template - using match_results = - std::match_results>>; - - using cmatch = match_results; - using wcmatch = match_results; - using smatch = match_results; - using wsmatch = match_results; - } -} -\end{codeblock} - -\rSec1[re.const]{Namespace \tcode{std::regex_constants}} - -\rSec2[re.const.general]{General} - -\pnum -\indexlibraryglobal{regex_constants}% -The namespace \tcode{std::regex_constants} holds -symbolic constants used by the regular expression library. This -namespace provides three types, \tcode{syntax_option_type}, -\tcode{match_flag_type}, and \tcode{error_type}, along with several -constants of these types. - -\rSec2[re.synopt]{Bitmask type \tcode{syntax_option_type}} -\indexlibraryglobal{syntax_option_type}% -\indexlibrarymember{regex_constants}{syntax_option_type}% -\begin{codeblock} -namespace std::regex_constants { - using syntax_option_type = @\textit{T1}@; - inline constexpr syntax_option_type icase = @\unspec@; - inline constexpr syntax_option_type nosubs = @\unspec@; - inline constexpr syntax_option_type optimize = @\unspec@; - inline constexpr syntax_option_type collate = @\unspec@; - inline constexpr syntax_option_type ECMAScript = @\unspec@; - inline constexpr syntax_option_type basic = @\unspec@; - inline constexpr syntax_option_type extended = @\unspec@; - inline constexpr syntax_option_type awk = @\unspec@; - inline constexpr syntax_option_type grep = @\unspec@; - inline constexpr syntax_option_type egrep = @\unspec@; - inline constexpr syntax_option_type multiline = @\unspec@; -} -\end{codeblock} - -\pnum -\indexlibraryglobal{syntax_option_type}% -\indexlibrarymember{syntax_option_type}{icase}% -\indexlibrarymember{syntax_option_type}{nosubs}% -\indexlibrarymember{syntax_option_type}{optimize}% -\indexlibrarymember{syntax_option_type}{collate}% -\indexlibrarymember{syntax_option_type}{ECMAScript}% -\indexlibrarymember{syntax_option_type}{basic}% -\indexlibrarymember{syntax_option_type}{extended}% -\indexlibrarymember{syntax_option_type}{awk}% -\indexlibrarymember{syntax_option_type}{grep}% -\indexlibrarymember{syntax_option_type}{egrep}% -The type \tcode{syntax_option_type} is an \impldef{type of \tcode{syntax_option_type}} bitmask -type\iref{bitmask.types}. Setting its elements has the effects listed in -\tref{re.synopt}. A valid value of type -\tcode{syntax_option_type} shall have at most one of the grammar elements -\tcode{ECMAScript}, \tcode{basic}, \tcode{extended}, \tcode{awk}, \tcode{grep}, \tcode{egrep}, set. -If no grammar element is set, the default grammar is \tcode{ECMAScript}. - -\begin{libefftab} - {\tcode{syntax_option_type} effects} - {re.synopt} -% -\tcode{icase} & -Specifies that matching of regular expressions against a character -container sequence shall be performed without regard to case. -\indexlibrarymember{syntax_option_type}{icase}% -\\ \rowsep -% -\tcode{nosubs} & -Specifies that no sub-expressions shall be considered to be marked, so that -when a regular expression is matched against a -character container sequence, no sub-expression matches shall be -stored in the supplied \tcode{match_results} object. -\indexlibrarymember{syntax_option_type}{nosubs}% -\\ \rowsep -% -\tcode{optimize} & -Specifies that the regular expression engine should pay more attention -to the speed with which regular expressions are matched, and less to -the speed with which regular expression objects are -constructed. Otherwise it has no detectable effect on the program -output. -\indexlibrarymember{syntax_option_type}{optimize}% -\\ \rowsep -% -\tcode{collate} & -Specifies that character ranges of the form \tcode{"[a-b]"} shall be locale -sensitive.% -\indexlibrarymember{syntax_option_type}{collate}% -\indextext{locale}% -\\ \rowsep -% -\tcode{ECMAScript} & -Specifies that the grammar recognized by the regular expression engine -shall be that used by ECMAScript in ECMA-262, as modified in~\ref{re.grammar}. -\newline \xref ECMA-262 15.10 -\indextext{ECMAScript}% -\indexlibrarymember{syntax_option_type}{ECMAScript}% -\\ \rowsep -% -\tcode{basic} & -Specifies that the grammar recognized by the regular expression engine -shall be that used by basic regular expressions in POSIX. -\newline \xref POSIX, Base Definitions and Headers, Section 9.3 -\indextext{POSIX!regular expressions}% -\indexlibrarymember{syntax_option_type}{basic}% -\\ \rowsep -% -\tcode{extended} & -Specifies that the grammar recognized by the regular expression engine -shall be that used by extended regular expressions in POSIX. -\newline \xref POSIX, Base Definitions and Headers, Section 9.4 -\indextext{POSIX!extended regular expressions}% -\indexlibrarymember{syntax_option_type}{extended}% -\\ \rowsep -% -\tcode{awk} & -Specifies that the grammar recognized by the regular expression engine -shall be that used by the utility awk in POSIX. -\indexlibrarymember{syntax_option_type}{awk}% -\\ \rowsep -% -\tcode{grep} & -Specifies that the grammar recognized by the regular expression engine -shall be that used by the utility grep in POSIX. -\indexlibrarymember{syntax_option_type}{grep}% -\\ \rowsep -% -\tcode{egrep} & -Specifies that the grammar recognized by the regular expression engine -shall be that used by the utility grep when given the -E -option in POSIX. -\indexlibrarymember{syntax_option_type}{egrep}% -\\ \rowsep -% -\tcode{multiline} & -Specifies that \tcode{\caret} shall match the beginning of a line and -\tcode{\$} shall match the end of a line, -if the \tcode{ECMAScript} engine is selected. -\indexlibrarymember{syntax_option_type}{multiline}% -\\ -% -\end{libefftab} - -\rSec2[re.matchflag]{Bitmask type \tcode{match_flag_type}} - -\indexlibraryglobal{match_flag_type}% -\indexlibrarymember{regex_constants}{match_flag_type}% -\indexlibraryglobal{match_default}% -\indexlibraryglobal{match_not_bol}% -\indexlibraryglobal{match_not_eol}% -\indexlibraryglobal{match_not_bow}% -\indexlibraryglobal{match_not_eow}% -\indexlibraryglobal{match_any}% -\indexlibraryglobal{match_not_null}% -\indexlibraryglobal{match_continuous}% -\indexlibraryglobal{match_prev_avail}% -\indexlibraryglobal{format_default}% -\indexlibraryglobal{format_sed}% -\indexlibraryglobal{format_no_copy}% -\indexlibraryglobal{format_first_only}% -\begin{codeblock} -namespace std::regex_constants { - using match_flag_type = @\textit{T2}@; - inline constexpr match_flag_type match_default = {}; - inline constexpr match_flag_type match_not_bol = @\unspec@; - inline constexpr match_flag_type match_not_eol = @\unspec@; - inline constexpr match_flag_type match_not_bow = @\unspec@; - inline constexpr match_flag_type match_not_eow = @\unspec@; - inline constexpr match_flag_type match_any = @\unspec@; - inline constexpr match_flag_type match_not_null = @\unspec@; - inline constexpr match_flag_type match_continuous = @\unspec@; - inline constexpr match_flag_type match_prev_avail = @\unspec@; - inline constexpr match_flag_type format_default = {}; - inline constexpr match_flag_type format_sed = @\unspec@; - inline constexpr match_flag_type format_no_copy = @\unspec@; - inline constexpr match_flag_type format_first_only = @\unspec@; -} -\end{codeblock} - -\pnum -\indexlibraryglobal{match_flag_type}% -The type \tcode{match_flag_type} is an -\impldef{type of \tcode{regex_constants::match_flag_type}} bitmask type\iref{bitmask.types}. -The constants of that type, except for \tcode{match_default} and -\tcode{format_default}, are bitmask elements. The \tcode{match_default} and -\tcode{format_default} constants are empty bitmasks. -Matching a regular expression against a sequence of characters -\range{first}{last} proceeds according to the rules of the grammar specified for the regular -expression object, modified according to the effects listed in \tref{re.matchflag} for -any bitmask elements set. - -\begin{longlibefftab} - {\tcode{regex_constants::match_flag_type} effects when obtaining a match against a - character container sequence \range{first}{last}.} - {re.matchflag} -% -\indexlibraryglobal{match_not_bol}% -\tcode{match_not_bol} & -The first character in the sequence \range{first}{last} shall be treated -as though it is not at the beginning of a line, so the character -\verb|^| in the regular expression shall not match \range{first}{first}. -\\ \rowsep -% -\indexlibraryglobal{match_not_eol}% -\tcode{match_not_eol} & -The last character in the sequence \range{first}{last} shall be treated -as though it is not at the end of a line, so the character -\verb|"$"| in the regular expression shall not match \range{last}{last}. -\\ \rowsep -% -\indexlibraryglobal{match_not_bow}% -\tcode{match_not_bow} & -The expression \verb|"\\b"| shall not match the -sub-sequence \range{first}{first}. -\\ \rowsep -% -\indexlibraryglobal{match_not_eow}% -\tcode{match_not_eow} & -The expression \verb|"\\b"| shall not match the -sub-sequence \range{last}{last}. -\\ \rowsep -% -\indexlibraryglobal{match_any}% -\tcode{match_any} & -If more than one match is possible then any match is an -acceptable result. -\\ \rowsep -% -\indexlibraryglobal{match_not_null}% -\tcode{match_not_null} & -The expression shall not match an empty -sequence. -\\ \rowsep -% -\indexlibraryglobal{match_continuous}% -\tcode{match_continuous} & -The expression shall only match a sub-sequence that begins at -\tcode{first}. -\\ \rowsep -% -\indexlibraryglobal{match_prev_avail}% -\tcode{match_prev_avail} & -\verb!--first! is a valid iterator position. When this flag is -set the flags \tcode{match_not_bol} and \tcode{match_not_bow} shall be ignored by the -regular expression algorithms\iref{re.alg} and iterators\iref{re.iter}. -\\ \rowsep -% -\indexlibraryglobal{format_default}% -\tcode{format_default} & -When a regular expression match is to be replaced by a -new string, the new string shall be constructed using the rules used by -the ECMAScript replace function in ECMA-262, -part 15.5.4.11 String.prototype.replace. In -addition, during search and replace operations all non-overlapping -occurrences of the regular expression shall be located and replaced, and -sections of the input that did not match the expression shall be copied -unchanged to the output string. -\\ \rowsep -% -\indexlibraryglobal{format_sed}% -\tcode{format_sed} & -When a regular expression match is to be replaced by a -new string, the new string shall be constructed using the rules used by -the sed utility in POSIX. -\\ \rowsep -% -\indexlibraryglobal{format_no_copy}% -\tcode{format_no_copy} & -During a search and replace operation, sections of -the character container sequence being searched that do not match the -regular expression shall not be copied to the output string. \\ \rowsep -% -\indexlibraryglobal{format_first_only}% -\tcode{format_first_only} & -When specified during a search and replace operation, only the -first occurrence of the regular expression shall be replaced. -\\ -\end{longlibefftab} - -\rSec2[re.err]{Implementation-defined \tcode{error_type}} -\indexlibraryglobal{error_type}% -\indexlibrarymember{regex_constants}{error_type}% -\begin{codeblock} -namespace std::regex_constants { - using error_type = @\textit{T3}@; - inline constexpr error_type error_collate = @\unspec@; - inline constexpr error_type error_ctype = @\unspec@; - inline constexpr error_type error_escape = @\unspec@; - inline constexpr error_type error_backref = @\unspec@; - inline constexpr error_type error_brack = @\unspec@; - inline constexpr error_type error_paren = @\unspec@; - inline constexpr error_type error_brace = @\unspec@; - inline constexpr error_type error_badbrace = @\unspec@; - inline constexpr error_type error_range = @\unspec@; - inline constexpr error_type error_space = @\unspec@; - inline constexpr error_type error_badrepeat = @\unspec@; - inline constexpr error_type error_complexity = @\unspec@; - inline constexpr error_type error_stack = @\unspec@; -} -\end{codeblock} - -\pnum -\indexlibraryglobal{error_type}% -\indexlibrarymember{regex_constants}{error_type}% -The type \tcode{error_type} is an \impldef{type of -\tcode{regex_constants::error_type}} enumerated type\iref{enumerated.types}. -Values of type \tcode{error_type} represent the error -conditions described in \tref{re.err}: - -\begin{longliberrtab} - {\tcode{error_type} values in the C locale} - {re.err} -\tcode{error_collate} -& -The expression contains an invalid collating element name. \\ \rowsep -% -\tcode{error_ctype} -& -The expression contains an invalid character class name. \\ \rowsep -% -\tcode{error_escape} -& -The expression contains an invalid escaped character, or a trailing -escape. \\ \rowsep -% -\tcode{error_backref} -& -The expression contains an invalid back reference. \\ \rowsep -% -\tcode{error_brack} -& -The expression contains mismatched \verb|[| and \verb|]|. \\ \rowsep -% -\tcode{error_paren} -& -The expression contains mismatched \verb|(| and \verb|)|. \\ \rowsep -% -\tcode{error_brace} -& -The expression contains mismatched \verb|{| and \verb|}| \\ \rowsep -% -\tcode{error_badbrace} -& -The expression contains an invalid range in a \verb|{}| expression. \\ -\rowsep -% -\tcode{error_range} -& -The expression contains an invalid character range, such as -\verb|[b-a]| in most encodings. \\ \rowsep -% -\tcode{error_space} -& -There is insufficient memory to convert the expression into a finite -state machine. \\ \rowsep -% -\tcode{error_badrepeat} -& -One of \verb|*?+{| is not preceded by a valid regular expression. \\ \rowsep -% -\tcode{error_complexity} -& -The complexity of an attempted match against a regular expression -exceeds a pre-set level. \\ \rowsep -% -\tcode{error_stack} -& -There is insufficient memory to determine whether the regular -expression matches the specified character sequence. \\ -% -\end{longliberrtab} - -\rSec1[re.badexp]{Class \tcode{regex_error}} -\indexlibraryglobal{regex_error}% -\begin{codeblock} -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 -The class \tcode{regex_error} defines the type of objects thrown as -exceptions to report errors from the regular expression library. - -\indexlibraryctor{regex_error}% -\begin{itemdecl} -regex_error(regex_constants::error_type ecode); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{ecode == code()}. -\end{itemdescr} - -\indexlibraryglobal{error_type}% -\indexlibrarymember{regex_constants}{error_type}% -\begin{itemdecl} -regex_constants::error_type code() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The error code that was passed to the constructor. -\end{itemdescr} - -\rSec1[re.traits]{Class template \tcode{regex_traits}} -\indexlibraryglobal{regex_traits}% -\begin{codeblock} -namespace std { - template - struct regex_traits { - using char_type = charT; - using string_type = basic_string; - using locale_type = locale; - using char_class_type = @\placeholdernc{bitmask_type}@; - - regex_traits(); - static size_t length(const char_type* p); - charT translate(charT c) const; - charT translate_nocase(charT c) const; - template - string_type transform(ForwardIterator first, ForwardIterator last) const; - template - string_type transform_primary( - ForwardIterator first, ForwardIterator last) const; - template - string_type lookup_collatename( - ForwardIterator first, ForwardIterator last) const; - template - char_class_type lookup_classname( - ForwardIterator first, ForwardIterator last, bool icase = false) const; - bool isctype(charT c, char_class_type f) const; - int value(charT ch, int radix) const; - locale_type imbue(locale_type l); - locale_type getloc() const; - }; -} -\end{codeblock} - -\pnum -\indextext{regular expression traits!requirements}% -\indextext{requirements!regular expression traits}% -The specializations \tcode{regex_traits} and -\tcode{regex_traits} meet the -requirements for a regular expression traits class\iref{re.req}. - -\indexlibrarymember{regex_traits}{char_class_type}% -\begin{itemdecl} -using char_class_type = @\textit{bitmask_type}@; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The type \tcode{char_class_type} is used to represent a character -classification and is capable of holding an implementation specific -set returned by \tcode{lookup_classname}. -\end{itemdescr} - -\indexlibrarymember{length}{regex_traits}% -\begin{itemdecl} -static size_t length(const char_type* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{char_traits::length(p)}. -\end{itemdescr} - -\indexlibrarymember{regex_traits}{translate}% -\begin{itemdecl} -charT translate(charT c) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{c}. -\end{itemdescr} - -\indexlibrarymember{regex_traits}{translate_nocase}% -\begin{itemdecl} -charT translate_nocase(charT c) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{use_facet>(getloc()).tolower(c)}. -\end{itemdescr} - -\indexlibrarymember{regex_traits}{transform}% -\begin{itemdecl} -template - string_type transform(ForwardIterator first, ForwardIterator last) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by: -\begin{codeblock} -string_type str(first, last); -return use_facet>( - getloc()).transform(str.data(), str.data() + str.length()); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{regex_traits}{transform_primary}% -\begin{itemdecl} -template - string_type transform_primary(ForwardIterator first, ForwardIterator last) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If -\begin{codeblock} -typeid(use_facet>) == typeid(collate_byname) -\end{codeblock} -and the form of the sort key returned -by \tcode{collate_byname::transform(first, last)} is known and -can be converted into a primary sort key then returns that key, -otherwise returns an empty string. -\end{itemdescr} - -\indexlibrarymember{regex_traits}{lookup_collatename}% -\begin{itemdecl} -template - string_type lookup_collatename(ForwardIterator first, ForwardIterator last) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A sequence of one or more characters that -represents the collating element consisting of the character -sequence designated by the iterator range \range{first}{last}. -Returns an empty string if the character sequence is not a -valid collating element. -\end{itemdescr} - -\indexlibrarymember{regex_traits}{lookup_classname}% -\begin{itemdecl} -template - char_class_type lookup_classname( - ForwardIterator first, ForwardIterator last, bool icase = false) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -An unspecified value that represents -the character classification named by the character sequence -designated by the iterator range \range{first}{last}. -If the parameter \tcode{icase} is \tcode{true} then the returned mask identifies the -character classification without regard to the case of the characters being -matched, otherwise it does honor the case of the characters being -matched. -\begin{footnote} -For example, if the parameter \tcode{icase} is \tcode{true} then -\tcode{[[:lower:]]} is the same as \tcode{[[:alpha:]]}. -\end{footnote} -The value -returned shall be independent of the case of the characters in -the character sequence. If the name -is not recognized then returns \tcode{char_class_type()}. - -\pnum -\remarks -For \tcode{regex_traits}, at least the narrow character names -in \tref{re.traits.classnames} shall be recognized. -For \tcode{regex_traits}, at least the wide character names -in \tref{re.traits.classnames} shall be recognized. -\end{itemdescr} - -\indexlibrarymember{regex_traits}{isctype}% -\begin{itemdecl} -bool isctype(charT c, char_class_type f) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Determines if the character \tcode{c} is a member of the character -classification represented by \tcode{f}. - -\pnum -\returns -Given the following function declaration: -\begin{codeblock} -// for exposition only -template - ctype_base::mask convert(typename regex_traits::char_class_type f); -\end{codeblock} -that returns a value in which each \tcode{ctype_base::mask} value corresponding to -a value in \tcode{f} named in \tref{re.traits.classnames} is set, then the -result is determined as if by: -\begin{codeblock} -ctype_base::mask m = convert(f); -const ctype& ct = use_facet>(getloc()); -if (ct.is(m, c)) { - return true; -} else if (c == ct.widen('_')) { - charT w[1] = { ct.widen('w') }; - char_class_type x = lookup_classname(w, w+1); - return (f&x) == x; -} else { - return false; -} -\end{codeblock} -\begin{example} -\begin{codeblock} -regex_traits t; -string d("d"); -string u("upper"); -regex_traits::char_class_type f; -f = t.lookup_classname(d.begin(), d.end()); -f |= t.lookup_classname(u.begin(), u.end()); -ctype_base::mask m = convert(f); // \tcode{m == ctype_base::digit|ctype_base::upper} -\end{codeblock} -\end{example} -\begin{example} -\begin{codeblock} -regex_traits t; -string w("w"); -regex_traits::char_class_type f; -f = t.lookup_classname(w.begin(), w.end()); -t.isctype('A', f); // returns \tcode{true} -t.isctype('_', f); // returns \tcode{true} -t.isctype(' ', f); // returns \tcode{false} -\end{codeblock} -\end{example} -\end{itemdescr} - -\indexlibrarymember{value}{regex_traits}% -\begin{itemdecl} -int value(charT ch, int radix) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -The value of \tcode{radix} is 8, 10, or 16. - -\pnum -\returns -The value represented by the digit \tcode{ch} in base -\tcode{radix} if the character \tcode{ch} is a valid digit in base -\tcode{radix}; otherwise returns \tcode{-1}. -\end{itemdescr} - -\indexlibraryglobal{locale}% -\indexlibraryglobal{imbue}% -\begin{itemdecl} -locale_type imbue(locale_type loc); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Imbues \tcode{*this} with a copy of the -locale \tcode{loc}. -\begin{note} -Calling \tcode{imbue} with a -different locale than the one currently in use invalidates all cached -data held by \tcode{*this}. -\end{note} - -\pnum -\ensures -\tcode{getloc() == loc}. - -\pnum -\returns -If no locale has been previously imbued then a copy of the -global locale in effect at the time of construction of \tcode{*this}, -otherwise a copy of the last argument passed to \tcode{imbue}. -\end{itemdescr} - -\indexlibraryglobal{locale}% -\indexlibraryglobal{getloc}% -\begin{itemdecl} -locale_type getloc() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -If no locale has been imbued then a copy of the global locale -in effect at the time of construction of \tcode{*this}, otherwise a copy of -the last argument passed to \tcode{imbue}. -\end{itemdescr} - -\begin{floattable}{Character class names and corresponding \tcode{ctype} masks}{re.traits.classnames}{lll} -\topline -\lhdr{Narrow character name} & \chdr{Wide character name} & \rhdr{Corresponding \tcode{ctype_base::mask} value} \\\capsep -\tcode{"alnum"} & \tcode{L"alnum"} & \tcode{ctype_base::alnum} \\ \rowsep -\tcode{"alpha"} & \tcode{L"alpha"} & \tcode{ctype_base::alpha} \\ \rowsep -\tcode{"blank"} & \tcode{L"blank"} & \tcode{ctype_base::blank} \\ \rowsep -\tcode{"cntrl"} & \tcode{L"cntrl"} & \tcode{ctype_base::cntrl} \\ \rowsep -\tcode{"digit"} & \tcode{L"digit"} & \tcode{ctype_base::digit} \\ \rowsep -\tcode{"d"} & \tcode{L"d"} & \tcode{ctype_base::digit} \\ \rowsep -\tcode{"graph"} & \tcode{L"graph"} & \tcode{ctype_base::graph} \\ \rowsep -\tcode{"lower"} & \tcode{L"lower"} & \tcode{ctype_base::lower} \\ \rowsep -\tcode{"print"} & \tcode{L"print"} & \tcode{ctype_base::print} \\ \rowsep -\tcode{"punct"} & \tcode{L"punct"} & \tcode{ctype_base::punct} \\ \rowsep -\tcode{"space"} & \tcode{L"space"} & \tcode{ctype_base::space} \\ \rowsep -\tcode{"s"} & \tcode{L"s"} & \tcode{ctype_base::space} \\ \rowsep -\tcode{"upper"} & \tcode{L"upper"} & \tcode{ctype_base::upper} \\ \rowsep -\tcode{"w"} & \tcode{L"w"} & \tcode{ctype_base::alnum} \\ \rowsep -\tcode{"xdigit"} & \tcode{L"xdigit"} & \tcode{ctype_base::xdigit} \\ -\end{floattable} - -\rSec1[re.regex]{Class template \tcode{basic_regex}} - -\rSec2[re.regex.general]{General} -\indexlibraryglobal{basic_regex}% - -\pnum -For a char-like type \tcode{charT}, specializations of class -template \tcode{basic_regex} represent regular expressions constructed -from character sequences of \tcode{charT} characters. In the rest -of~\ref{re.regex}, \tcode{charT} denotes a given char-like -type. Storage for a regular expression is allocated and freed as -necessary by the member functions of class \tcode{basic_regex}. - -\pnum -Objects of type specialization of \tcode{basic_regex} are responsible for -converting the sequence of \tcode{charT} objects to an internal -representation. It is not specified what form this representation -takes, nor how it is accessed by algorithms that operate on regular -expressions. -\begin{note} -Implementations will typically declare -some function templates as friends of \tcode{basic_regex} to achieve -this. -\end{note} - -\pnum -\indexlibraryglobal{regex_error}% -The functions described in \ref{re.regex} report errors by throwing -exceptions of type \tcode{regex_error}. - -\indexlibraryglobal{basic_regex}% -\begin{codeblock} -namespace std { - template> - class basic_regex { - public: - // types - using value_type = charT; - using traits_type = traits; - using string_type = typename traits::string_type; - using flag_type = regex_constants::syntax_option_type; - using locale_type = typename traits::locale_type; - - // \ref{re.synopt}, constants - static constexpr flag_type icase = regex_constants::icase; - static constexpr flag_type nosubs = regex_constants::nosubs; - static constexpr flag_type optimize = regex_constants::optimize; - static constexpr flag_type collate = regex_constants::collate; - static constexpr flag_type ECMAScript = regex_constants::ECMAScript; - static constexpr flag_type basic = regex_constants::basic; - static constexpr flag_type extended = regex_constants::extended; - static constexpr flag_type awk = regex_constants::awk; - static constexpr flag_type grep = regex_constants::grep; - static constexpr flag_type egrep = regex_constants::egrep; - static constexpr flag_type multiline = regex_constants::multiline; - - // \ref{re.regex.construct}, construct/copy/destroy - basic_regex(); - explicit basic_regex(const charT* p, flag_type f = regex_constants::ECMAScript); - basic_regex(const charT* p, size_t len, flag_type f = regex_constants::ECMAScript); - basic_regex(const basic_regex&); - basic_regex(basic_regex&&) noexcept; - template - explicit basic_regex(const basic_string& s, - flag_type f = regex_constants::ECMAScript); - template - basic_regex(ForwardIterator first, ForwardIterator last, - flag_type f = regex_constants::ECMAScript); - basic_regex(initializer_list il, flag_type f = regex_constants::ECMAScript); - - ~basic_regex(); - - // \ref{re.regex.assign}, assign - basic_regex& operator=(const basic_regex& e); - basic_regex& operator=(basic_regex&& e) noexcept; - basic_regex& operator=(const charT* p); - basic_regex& operator=(initializer_list il); - template - basic_regex& operator=(const basic_string& s); - - basic_regex& assign(const basic_regex& e); - basic_regex& assign(basic_regex&& e) noexcept; - basic_regex& assign(const charT* p, flag_type f = regex_constants::ECMAScript); - basic_regex& assign(const charT* p, size_t len, flag_type f = regex_constants::ECMAScript); - template - basic_regex& assign(const basic_string& s, - flag_type f = regex_constants::ECMAScript); - template - basic_regex& assign(InputIterator first, InputIterator last, - flag_type f = regex_constants::ECMAScript); - basic_regex& assign(initializer_list, - flag_type f = regex_constants::ECMAScript); - - // \ref{re.regex.operations}, const operations - unsigned mark_count() const; - flag_type flags() const; - - // \ref{re.regex.locale}, locale - locale_type imbue(locale_type loc); - locale_type getloc() const; - - // \ref{re.regex.swap}, swap - void swap(basic_regex&); - }; - - template - basic_regex(ForwardIterator, ForwardIterator, - regex_constants::syntax_option_type = regex_constants::ECMAScript) - -> basic_regex::value_type>; -} -\end{codeblock} - -\rSec2[re.regex.construct]{Constructors} - -\indexlibraryctor{basic_regex}% -\begin{itemdecl} -basic_regex(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{*this} does not match any character sequence. -\end{itemdescr} - -\indexlibraryctor{basic_regex}% -\begin{itemdecl} -explicit basic_regex(const charT* p, flag_type f = regex_constants::ECMAScript); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\range{p}{p + char_traits::length(p)} is a valid range. - -\pnum -\effects -The object's internal finite state machine -is constructed from the regular expression contained in -the sequence of characters -\range{p}{p + char_traits::\brk{}length(p)}, and -interpreted according to the flags \tcode{f}. - -\pnum -\ensures -\tcode{flags()} returns \tcode{f}. -\tcode{mark_count()} returns the number of marked sub-expressions -within the expression. - -\pnum -\throws -\tcode{regex_error} if -\range{p}{p + char_traits::length(p)} is not a valid regular expression. -\end{itemdescr} - -\indexlibraryctor{basic_regex}% -\begin{itemdecl} -basic_regex(const charT* p, size_t len, flag_type f = regex_constants::ECMAScript); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\range{p}{p + len} is a valid range. - -\pnum -\effects -The object's internal finite state machine -is constructed from the regular expression contained in -the sequence of characters \range{p}{p + len}, and -interpreted according the flags specified in \tcode{f}. - -\pnum -\ensures -\tcode{flags()} returns \tcode{f}. -\tcode{mark_count()} returns the number of marked sub-expressions -within the expression. - -\pnum -\throws -\tcode{regex_error} if \range{p}{p + len} is not a valid regular expression. -\end{itemdescr} - -\indexlibraryctor{basic_regex}% -\begin{itemdecl} -basic_regex(const basic_regex& e); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{flags()} and \tcode{mark_count()} return -\tcode{e.flags()} and \tcode{e.mark_count()}, respectively. -\end{itemdescr} - -\indexlibraryctor{basic_regex}% -\begin{itemdecl} -basic_regex(basic_regex&& e) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{flags()} and \tcode{mark_count()} return the values that -\tcode{e.flags()} and \tcode{e.mark_count()}, respectively, had before construction. -\end{itemdescr} - -\indexlibraryctor{basic_regex}% -\begin{itemdecl} -template - explicit basic_regex(const basic_string& s, - flag_type f = regex_constants::ECMAScript); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -The object's internal finite state machine -is constructed from the regular expression contained in -the string \tcode{s}, and -interpreted according to the flags specified in \tcode{f}. - -\pnum -\ensures -\tcode{flags()} returns \tcode{f}. -\tcode{mark_count()} returns the number of marked sub-expressions -within the expression. - -\pnum -\throws -\tcode{regex_error} if \tcode{s} is not a valid regular expression. -\end{itemdescr} - -\indexlibraryctor{basic_regex}% -\begin{itemdecl} -template - basic_regex(ForwardIterator first, ForwardIterator last, - flag_type f = regex_constants::ECMAScript); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -The object's internal finite state machine -is constructed from the regular expression contained in -the sequence of characters \range{first}{last}, and -interpreted according to the flags specified in \tcode{f}. - -\pnum -\ensures -\tcode{flags()} returns \tcode{f}. -\tcode{mark_count()} returns the number of marked sub-expressions -within the expression. - -\pnum -\throws -\tcode{regex_error} if the sequence \range{first}{last} is not a -valid regular expression. -\end{itemdescr} - -\indexlibraryctor{basic_regex}% -\begin{itemdecl} -basic_regex(initializer_list il, flag_type f = regex_constants::ECMAScript); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Same as \tcode{basic_regex(il.begin(), il.end(), f)}. -\end{itemdescr} - -\rSec2[re.regex.assign]{Assignment} - -\indexlibrarymember{basic_regex}{operator=}% -\begin{itemdecl} -basic_regex& operator=(const basic_regex& e); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{flags()} and \tcode{mark_count()} return -\tcode{e.flags()} and \tcode{e.mark_count()}, respectively. -\end{itemdescr} - -\indexlibrarymember{basic_regex}{operator=}% -\begin{itemdecl} -basic_regex& operator=(basic_regex&& e) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{flags()} and \tcode{mark_count()} return the values that -\tcode{e.flags()} and \tcode{e.mark_count()}, respectively, had before assignment. -\tcode{e} is in a valid state with unspecified value. -\end{itemdescr} - -\indexlibrarymember{basic_regex}{operator=}% -\begin{itemdecl} -basic_regex& operator=(const charT* p); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return assign(p);} -\end{itemdescr} - -\indexlibrarymember{basic_regex}{operator=}% -\begin{itemdecl} -basic_regex& operator=(initializer_list il); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return assign(il.begin(), il.end());} -\end{itemdescr} - -\indexlibrarymember{basic_regex}{operator=}% -\begin{itemdecl} -template - basic_regex& operator=(const basic_string& s); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return assign(s);} -\end{itemdescr} - -\indexlibrarymember{basic_regex}{assign}% -\begin{itemdecl} -basic_regex& assign(const basic_regex& e); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return *this = e;} -\end{itemdescr} - -\indexlibrarymember{basic_regex}{assign}% -\begin{itemdecl} -basic_regex& assign(basic_regex&& e) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return *this = std::move(e);} -\end{itemdescr} - -\indexlibrarymember{basic_regex}{assign}% -\begin{itemdecl} -basic_regex& assign(const charT* p, flag_type f = regex_constants::ECMAScript); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return assign(string_type(p), f);} -\end{itemdescr} - -\indexlibrarymember{basic_regex}{assign}% -\begin{itemdecl} -basic_regex& assign(const charT* p, size_t len, flag_type f = regex_constants::ECMAScript); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return assign(string_type(p, len), f);} -\end{itemdescr} - -\indexlibrarymember{basic_regex}{assign}% -\begin{itemdecl} -template - basic_regex& assign(const basic_string& s, - flag_type f = regex_constants::ECMAScript); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Assigns the regular expression contained in the string -\tcode{s}, interpreted according the flags specified in \tcode{f}. -If an exception is thrown, \tcode{*this} is unchanged. - -\pnum -\ensures -If no exception is thrown, -\tcode{flags()} returns \tcode{f} and \tcode{mark_count()} -returns the number of marked sub-expressions within the expression. - -\pnum -\returns -\tcode{*this}. - -\pnum -\throws -\tcode{regex_error} if \tcode{s} is not a valid regular expression. -\end{itemdescr} - -\indexlibrarymember{basic_regex}{assign}% -\begin{itemdecl} -template - basic_regex& assign(InputIterator first, InputIterator last, - flag_type f = regex_constants::ECMAScript); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return assign(string_type(first, last), f);} -\end{itemdescr} - -\indexlibrarymember{assign}{basic_regex}% -\begin{itemdecl} -basic_regex& assign(initializer_list il, - flag_type f = regex_constants::ECMAScript); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return assign(il.begin(), il.end(), f);} -\end{itemdescr} - - -\rSec2[re.regex.operations]{Constant operations} - -\indexlibrarymember{mark_count}{basic_regex}% -\begin{itemdecl} -unsigned mark_count() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Returns the number of marked sub-expressions within the -regular expression. -\end{itemdescr} - -\indexlibrarymember{flag_type}{basic_regex}% -\begin{itemdecl} -flag_type flags() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Returns a copy of the regular expression syntax flags that -were passed to the object's constructor or to the last call -to \tcode{assign}. -\end{itemdescr} - -\rSec2[re.regex.locale]{Locale}% -\indexlibraryglobal{locale} - -\indexlibrarymember{imbue}{basic_regex}% -\begin{itemdecl} -locale_type imbue(locale_type loc); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Returns the result of \tcode{traits_inst.imbue(loc)} where -\tcode{traits_inst} is a (default-initialized) instance of the template -type argument \tcode{traits} stored within the object. After a call -to \tcode{imbue} the \tcode{basic_regex} object does not match any -character sequence. -\end{itemdescr} - -\indexlibrarymember{getloc}{basic_regex}% -\begin{itemdecl} -locale_type getloc() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Returns the result of \tcode{traits_inst.getloc()} where -\tcode{traits_inst} is a (default-initialized) instance of the template -parameter \tcode{traits} stored within the object. -\end{itemdescr} - -\rSec2[re.regex.swap]{Swap} -\indexlibrarymember{basic_regex}{swap}% - -\indexlibrarymember{swap}{basic_regex}% -\begin{itemdecl} -void swap(basic_regex& e); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Swaps the contents of the two regular expressions. - -\pnum -\ensures -\tcode{*this} contains the regular expression -that was in \tcode{e}, \tcode{e} contains the regular expression that -was in \tcode{*this}. - -\pnum -\complexity -Constant time. -\end{itemdescr} - -\rSec2[re.regex.nonmemb]{Non-member functions} - -\indexlibrarymember{basic_regex}{swap}% -\begin{itemdecl} -template - void swap(basic_regex& lhs, basic_regex& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Calls \tcode{lhs.swap(rhs)}. -\end{itemdescr} - -\rSec1[re.submatch]{Class template \tcode{sub_match}} - -\rSec2[re.submatch.general]{General} -\pnum -\indexlibraryglobal{sub_match}% -Class template \tcode{sub_match} denotes the sequence of characters matched -by a particular marked sub-expression. - -\begin{codeblock} -namespace std { - template - class sub_match : public pair { - public: - using value_type = - typename iterator_traits::value_type; - using difference_type = - typename iterator_traits::difference_type; - using iterator = BidirectionalIterator; - using string_type = basic_string; - - bool matched; - - constexpr sub_match(); - - difference_type length() const; - operator string_type() const; - string_type str() const; - - int compare(const sub_match& s) const; - int compare(const string_type& s) const; - int compare(const value_type* s) const; - - void swap(sub_match& s) noexcept(@\seebelow@); - }; -} -\end{codeblock} - - -\rSec2[re.submatch.members]{Members} - -\indexlibraryctor{sub_match}% -\begin{itemdecl} -constexpr sub_match(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Value-initializes the \tcode{pair} base class subobject and the member -\tcode{matched}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{length}% -\begin{itemdecl} -difference_type length() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{matched ?\ distance(first, second) :\ 0}. -\end{itemdescr} - -\indexlibrarymember{operator basic_string}{sub_match}% -\begin{itemdecl} -operator string_type() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{matched ?\ string_type(first, second) :\ string_type()}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{str}% -\begin{itemdecl} -string_type str() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{matched ?\ string_type(first, second) :\ string_type()}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{compare}% -\begin{itemdecl} -int compare(const sub_match& s) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{str().compare(s.str())}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{compare}% -\begin{itemdecl} -int compare(const string_type& s) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{str().compare(s)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{compare}% -\begin{itemdecl} -int compare(const value_type* s) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{str().compare(s)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{swap}% -\begin{itemdecl} -void swap(sub_match& s) noexcept(@\seebelow@); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{BidirectionalIterator} meets -the \oldconcept{Swappable} requirements\iref{swappable.requirements}. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -this->pair::swap(s); -std::swap(matched, s.matched); -\end{codeblock} - -\pnum -\remarks -The exception specification is equivalent to -\tcode{is_nothrow_swappable_v}. -\end{itemdescr} - -\rSec2[re.submatch.op]{Non-member operators} - -\pnum -Let \tcode{\placeholdernc{SM-CAT}(I)} be -\begin{codeblock} -compare_three_way_result_t::value_type>> -\end{codeblock} - -\indexlibrarymember{sub_match}{operator==}% -\begin{itemdecl} -template - bool operator==(const sub_match& lhs, const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{lhs.compare(rhs) == 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<=>}% -\begin{itemdecl} -template - auto operator<=>(const sub_match& lhs, const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{static_cast<\placeholdernc{SM-CAT}(BiIter)>(lhs.compare(rhs) <=> 0)}. -\end{itemdescr} - -\indexlibrarymember{operator==}{sub_match}% -\begin{itemdecl} -template - bool operator==( - const sub_match& lhs, - const basic_string::value_type, ST, SA>& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\begin{codeblock} -lhs.compare(typename sub_match::string_type(rhs.data(), rhs.size())) == 0 -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{operator<=>}{sub_match}% -\begin{itemdecl} -template - auto operator<=>( - const sub_match& lhs, - const basic_string::value_type, ST, SA>& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\begin{codeblock} -static_cast<@\placeholdernc{SM-CAT}@(BiIter)>(lhs.compare( - typename sub_match::string_type(rhs.data(), rhs.size())) - <=> 0 - ) -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator==}% -\begin{itemdecl} -template - bool operator==(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{lhs.compare(rhs) == 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<=>}% -\begin{itemdecl} -template - auto operator<=>(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{static_cast<\placeholdernc{SM-CAT}(BiIter)>(lhs.compare(rhs) <=> 0)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator==}% -\begin{itemdecl} -template - bool operator==(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{lhs.compare(typename sub_match::string_type(1, rhs)) == 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<=>}% -\begin{itemdecl} -template - auto operator<=>(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\begin{codeblock} -static_cast<@\placeholdernc{SM-CAT}@(BiIter)>(lhs.compare( - typename sub_match::string_type(1, rhs)) - <=> 0 - ) -\end{codeblock} -\end{itemdescr} - -\indexlibraryglobal{basic_ostream}% -\indexlibrarymember{sub_match}{operator<<}% -\begin{itemdecl} -template - basic_ostream& - operator<<(basic_ostream& os, const sub_match& m); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{os << m.str()}. -\end{itemdescr} - -\rSec1[re.results]{Class template \tcode{match_results}} - -\rSec2[re.results.general]{General} -\pnum -\indexlibraryglobal{match_results}% -Class template \tcode{match_results} denotes a collection of character -sequences representing the result of a regular expression -match. Storage for the collection is allocated and freed as necessary -by the member functions of class template \tcode{match_results}. - -\pnum -\indextext{requirements!container}% -\indextext{requirements!sequence}% -The class template \tcode{match_results} meets the requirements of an -allocator-aware container\iref{container.alloc.reqmts} and of -a sequence container\iref{container.requirements.general,sequence.reqmts} -except that only -copy assignment, -move assignment, and -operations defined for const-qualified sequence containers -are supported and -that the semantics of the comparison operator functions are different from those -required for a container. - -\pnum -A default-constructed \tcode{match_results} object has no fully established result state. A -match result is \defn{ready} when, as a consequence of a completed regular expression match -modifying such an object, its result state becomes fully established. The effects of calling -most member functions from a \tcode{match_results} object that is not ready are undefined. - -\pnum -\indexlibrarymember{match_results}{matched}% -The \tcode{sub_match} object stored at index 0 represents sub-expression 0, -i.e., the whole match. In this case the \tcode{sub_match} member -\tcode{matched} is always \tcode{true}. The \tcode{sub_match} -object stored at index \tcode{n} denotes what matched the marked -sub-expression \tcode{n} within the matched expression. If the -sub-expression \tcode{n} participated in a regular expression -match then the \tcode{sub_match} member \tcode{matched} evaluates to \tcode{true}, and -members \tcode{first} and \tcode{second} denote the range of characters -\range{first}{second} which formed that -match. Otherwise \tcode{matched} is \tcode{false}, and members \tcode{first} -and \tcode{second} point to the end of the sequence -that was searched. -\begin{note} -The \tcode{sub_match} objects representing -different sub-expressions that did not participate in a regular expression -match need not be distinct. -\end{note} - -\begin{codeblock} -namespace std { - template>> - class match_results { - public: - using value_type = sub_match; - using const_reference = const value_type&; - using reference = value_type&; - using const_iterator = @\impdefx{type of \tcode{match_results::const_iterator}}@; - using iterator = const_iterator; - using difference_type = - typename iterator_traits::difference_type; - using size_type = typename allocator_traits::size_type; - using allocator_type = Allocator; - using char_type = - typename iterator_traits::value_type; - using string_type = basic_string; - - // \ref{re.results.const}, construct/copy/destroy - match_results() : match_results(Allocator()) {} - explicit match_results(const Allocator& a); - match_results(const match_results& m); - match_results(const match_results& m, const Allocator& a); - match_results(match_results&& m) noexcept; - match_results(match_results&& m, const Allocator& a); - match_results& operator=(const match_results& m); - match_results& operator=(match_results&& m); - ~match_results(); - - // \ref{re.results.state}, state - bool ready() const; - - // \ref{re.results.size}, size - size_type size() const; - size_type max_size() const; - [[nodiscard]] bool empty() const; - - // \ref{re.results.acc}, element access - difference_type length(size_type sub = 0) const; - difference_type position(size_type sub = 0) const; - string_type str(size_type sub = 0) const; - const_reference operator[](size_type n) const; - - const_reference prefix() const; - const_reference suffix() const; - const_iterator begin() const; - const_iterator end() const; - const_iterator cbegin() const; - const_iterator cend() const; - - // \ref{re.results.form}, format - template - OutputIter - format(OutputIter out, - const char_type* fmt_first, const char_type* fmt_last, - regex_constants::match_flag_type flags = regex_constants::format_default) const; - template - OutputIter - format(OutputIter out, - const basic_string& fmt, - regex_constants::match_flag_type flags = regex_constants::format_default) const; - template - basic_string - format(const basic_string& fmt, - regex_constants::match_flag_type flags = regex_constants::format_default) const; - string_type - format(const char_type* fmt, - regex_constants::match_flag_type flags = regex_constants::format_default) const; - - // \ref{re.results.all}, allocator - allocator_type get_allocator() const; - - // \ref{re.results.swap}, swap - void swap(match_results& that); - }; -} -\end{codeblock} - -\rSec2[re.results.const]{Constructors} - -\pnum -\tref{re.results.const} lists the postconditions of -\tcode{match_results} copy/move constructors and copy/move assignment operators. -For move operations, -the results of the expressions depending on the parameter \tcode{m} denote -the values they had before the respective function calls. - -\indexlibraryctor{match_results}% -\begin{itemdecl} -explicit match_results(const Allocator& a); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -The stored \tcode{Allocator} value is constructed from \tcode{a}. - -\pnum -\ensures -\tcode{ready()} returns \tcode{false}. -\tcode{size()} returns \tcode{0}. -\end{itemdescr} - -\indexlibraryctor{match_results}% -\begin{itemdecl} -match_results(const match_results& m); -match_results(const match_results& m, const Allocator& a); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -For the first form, -the stored \tcode{Allocator} value is obtained -as specified in \ref{container.reqmts}. -For the second form, -the stored \tcode{Allocator} value is constructed from \tcode{a}. - -\pnum -\ensures -As specified in \tref{re.results.const}. -\end{itemdescr} - -\indexlibraryctor{match_results}% -\begin{itemdecl} -match_results(match_results&& m) noexcept; -match_results(match_results&& m, const Allocator& a); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -For the first form, -the stored \tcode{Allocator} value is move constructed from \tcode{m.get_allocator()}. -For the second form, -the stored \tcode{Allocator} value is constructed from \tcode{a}. - -\pnum -\ensures -As specified in \tref{re.results.const}. - -\pnum -\throws -The second form throws nothing if -\tcode{a == m.get_allocator()} is \tcode{true}. -\end{itemdescr} - -\indexlibrarymember{match_results}{operator=}% -\begin{itemdecl} -match_results& operator=(const match_results& m); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -As specified in \tref{re.results.const}. -\end{itemdescr} - -\indexlibrarymember{match_results}{operator=}% -\begin{itemdecl} -match_results& operator=(match_results&& m); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -As specified in \tref{re.results.const}. -\end{itemdescr} - -\begin{libefftabvalue} - {\tcode{match_results} copy/move operation postconditions} - {re.results.const} -\tcode{ready()} & \tcode{m.ready()} \\ \rowsep -\tcode{size()} & \tcode{m.size()} \\ \rowsep -\tcode{str(n)} & \tcode{m.str(n)} for all non-negative integers \tcode{n < m.size()} \\ \rowsep -\tcode{prefix()} & \tcode{m.prefix()} \\ \rowsep -\tcode{suffix()} & \tcode{m.suffix()} \\ \rowsep -\tcode{(*this)[n]} & \tcode{m[n]} for all non-negative integers \tcode{n < m.size()} \\ \rowsep -\tcode{length(n)} & \tcode{m.length(n)} for all non-negative integers \tcode{n < m.size()} \\ \rowsep -\tcode{position(n)} & \tcode{m.position(n)} for all non-negative integers \tcode{n < m.size()} \\ -\end{libefftabvalue} - -\rSec2[re.results.state]{State} - -\indexlibrarymember{match_results}{ready}% -\begin{itemdecl} -bool ready() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if \tcode{*this} has a fully established result state, otherwise -\tcode{false}. -\end{itemdescr} - -\rSec2[re.results.size]{Size} - -\indexlibrarymember{match_results}{size}% -\begin{itemdecl} -size_type size() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -One plus the number of marked sub-expressions in the -regular expression that was matched if \tcode{*this} represents the -result of a successful match. Otherwise returns \tcode{0}. -\begin{note} -The state of a \tcode{match_results} object can be modified -only by passing that object to \tcode{regex_match} or \tcode{regex_search}. -Subclauses~\ref{re.alg.match} and~\ref{re.alg.search} specify the -effects of those algorithms on their \tcode{match_results} arguments. -\end{note} -\end{itemdescr} - -\indexlibrarymember{match_results}{max_size}% -\begin{itemdecl} -size_type max_size() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The maximum number of \tcode{sub_match} elements that can be -stored in \tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{match_results}{empty}% -\begin{itemdecl} -[[nodiscard]] bool empty() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{size() == 0}. -\end{itemdescr} - -\rSec2[re.results.acc]{Element access} - -\indexlibrarymember{length}{match_results}% -\begin{itemdecl} -difference_type length(size_type sub = 0) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{ready() == true}. - -\pnum -\returns -\tcode{(*this)[sub].length()}. -\end{itemdescr} - -\indexlibrarymember{position}{match_results}% -\begin{itemdecl} -difference_type position(size_type sub = 0) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{ready() == true}. - -\pnum -\returns -The distance from the start of the target sequence -to \tcode{(*this)[sub].first}. -\end{itemdescr} - -\indexlibrarymember{match_results}{str}% -\begin{itemdecl} -string_type str(size_type sub = 0) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{ready() == true}. - -\pnum -\returns -\tcode{string_type((*this)[sub])}. -\end{itemdescr} - -\indexlibrarymember{match_results}{operator[]}% -\begin{itemdecl} -const_reference operator[](size_type n) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{ready() == true}. - -\pnum -\returns -A reference to the \tcode{sub_match} object representing the -character sequence that matched marked sub-expression \tcode{n}. If \tcode{n == 0} -then returns a reference to a \tcode{sub_match} object representing the -character sequence that matched the whole regular expression. If -\tcode{n >= size()} then returns a \tcode{sub_match} object representing an -unmatched sub-expression. -\end{itemdescr} - -\indexlibrarymember{match_results}{prefix}% -\begin{itemdecl} -const_reference prefix() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{ready() == true}. - -\pnum -\returns -A reference to the \tcode{sub_match} object representing the -character sequence from the start of the string being -matched/searched to the start of the match found. -\end{itemdescr} - -\indexlibrarymember{match_results}{suffix}% -\begin{itemdecl} -const_reference suffix() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{ready() == true}. - -\pnum -\returns -A reference to the \tcode{sub_match} object representing the -character sequence from the end of the match found to the end of the -string being matched/searched. -\end{itemdescr} - -\indexlibrarymember{match_results}{begin}% -\begin{itemdecl} -const_iterator begin() const; -const_iterator cbegin() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A starting iterator that enumerates over all the -sub-expressions stored in \tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{match_results}{end}% -\begin{itemdecl} -const_iterator end() const; -const_iterator cend() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A terminating iterator that enumerates over all the -sub-expressions stored in \tcode{*this}. -\end{itemdescr} - -\rSec2[re.results.form]{Formatting} - -\indexlibrarymember{match_results}{format}% -\begin{itemdecl} -template - OutputIter format( - OutputIter out, - const char_type* fmt_first, const char_type* fmt_last, - regex_constants::match_flag_type flags = regex_constants::format_default) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{ready() == true} and \tcode{OutputIter} meets the requirements for a -\oldconcept{OutputIterator}\iref{output.iterators}. - -\pnum -\effects -Copies the character sequence \range{fmt_first}{fmt_last} to -OutputIter \tcode{out}. Replaces each format specifier or escape -sequence in the copied range with either the character(s) it represents or -the sequence of characters within \tcode{*this} to which it refers. -The bitmasks specified in \tcode{flags} determine which format -specifiers and escape sequences are recognized. - -\pnum -\returns -\tcode{out}. -\end{itemdescr} - -\indexlibrarymember{match_results}{format}% -\begin{itemdecl} -template - OutputIter format( - OutputIter out, - const basic_string& fmt, - regex_constants::match_flag_type flags = regex_constants::format_default) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -return format(out, fmt.data(), fmt.data() + fmt.size(), flags); -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{match_results}{format}% -\begin{itemdecl} -template - basic_string format( - const basic_string& fmt, - regex_constants::match_flag_type flags = regex_constants::format_default) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{ready() == true}. - -\pnum -\effects -Constructs an empty string \tcode{result} of type \tcode{basic_string} and -calls: -\begin{codeblock} -format(back_inserter(result), fmt, flags); -\end{codeblock} - -\pnum -\returns -\tcode{result}. -\end{itemdescr} - -\indexlibrarymember{match_results}{format}% -\begin{itemdecl} -string_type format( - const char_type* fmt, - regex_constants::match_flag_type flags = regex_constants::format_default) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{ready() == true}. - -\pnum -\effects -Constructs an empty string \tcode{result} of type \tcode{string_type} and -calls: -\begin{codeblock} -format(back_inserter(result), fmt, fmt + char_traits::length(fmt), flags); -\end{codeblock} - -\pnum -\returns -\tcode{result}. -\end{itemdescr} - -\rSec2[re.results.all]{Allocator}% - -\indexlibrarymember{get_allocator}{match_results}% -\begin{itemdecl} -allocator_type get_allocator() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -A copy of the Allocator that was passed to the object's constructor or, if that -allocator has been replaced, a copy of the most recent replacement. -\end{itemdescr} - -\rSec2[re.results.swap]{Swap} - -\indexlibrarymember{match_results}{swap}% -\begin{itemdecl} -void swap(match_results& that); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Swaps the contents of the two sequences. - -\pnum -\ensures -\tcode{*this} contains the sequence of matched -sub-expressions that were in \tcode{that}, \tcode{that} contains the -sequence of matched sub-expressions that were in \tcode{*this}. - -\pnum -\complexity -Constant time. -\end{itemdescr} - -\indexlibrarymember{match_results}{swap}% -\begin{itemdecl} -template - void swap(match_results& m1, - match_results& m2); -\end{itemdecl} - -\pnum -\effects -As if by \tcode{m1.swap(m2)}. - -\rSec2[re.results.nonmember]{Non-member functions} - -\indexlibrarymember{operator==}{match_results}% -\begin{itemdecl} -template -bool operator==(const match_results& m1, - const match_results& m2); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if neither match result is ready, \tcode{false} if one match result is ready and the -other is not. If both match results are ready, returns \tcode{true} only if: -\begin{itemize} -\item -\tcode{m1.empty() \&\& m2.empty()}, or - -\item -\tcode{!m1.empty() \&\& !m2.empty()}, and the following conditions are satisfied: -\begin{itemize} -\item -\tcode{m1.prefix() == m2.prefix()}, - -\item -\tcode{m1.size() == m2.size() \&\& equal(m1.begin(), m1.end(), m2.begin())}, and - -\item -\tcode{m1.suffix() == m2.suffix()}. -\end{itemize} -\end{itemize} -\begin{note} -The algorithm \tcode{equal} is defined in \ref{algorithms}. -\end{note} -\end{itemdescr} - -\rSec1[re.alg]{Regular expression algorithms} - -\rSec2[re.except]{Exceptions} -\pnum -The algorithms described in subclause~\ref{re.alg} may throw an exception -of type \tcode{regex_error}. If such an exception \tcode{e} is thrown, -\tcode{e.code()} shall return either \tcode{regex_constants::error_complexity} -or \tcode{regex_constants::error_stack}. - -\rSec2[re.alg.match]{\tcode{regex_match}} -\indexlibraryglobal{regex_match}% -\begin{itemdecl} -template - bool regex_match(BidirectionalIterator first, BidirectionalIterator last, - match_results& m, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{BidirectionalIterator} models -\libconcept{bidirectional_iterator}\iref{iterator.concept.bidir}. - -\pnum -\effects -Determines whether there is a match between the -regular expression \tcode{e}, and all of the character -sequence \range{first}{last}. The parameter \tcode{flags} is -used to control how the expression is matched against the character -sequence. When determining if there is a match, only potential matches -that match the entire character sequence are considered. -Returns \tcode{true} if such a match exists, \tcode{false} -otherwise. -\begin{example} -\begin{codeblock} -std::regex re("Get|GetValue"); -std::cmatch m; -regex_search("GetValue", m, re); // returns \tcode{true}, and \tcode{m[0]} contains \tcode{"Get"} -regex_match ("GetValue", m, re); // returns \tcode{true}, and \tcode{m[0]} contains \tcode{"GetValue"} -regex_search("GetValues", m, re); // returns \tcode{true}, and \tcode{m[0]} contains \tcode{"Get"} -regex_match ("GetValues", m, re); // returns \tcode{false} -\end{codeblock} -\end{example} - -\pnum -\ensures -\tcode{m.ready() == true} in all cases. -If the function returns \tcode{false}, then the effect -on parameter \tcode{m} is unspecified except that \tcode{m.size()} -returns \tcode{0} and \tcode{m.empty()} returns \tcode{true}. -Otherwise the effects on parameter \tcode{m} are given in -\tref{re.alg.match}. -\end{itemdescr} - -\begin{longlibefftabvalue} - {Effects of \tcode{regex_match} algorithm} - {re.alg.match} -\tcode{m.size()} -& -\tcode{1 + e.mark_count()} -\\ \rowsep -\tcode{m.empty()} -& -\tcode{false} -\\ \rowsep -\tcode{m.prefix().first} -& -\tcode{first} -\\ \rowsep -\tcode{m.prefix().second} -& -\tcode{first} -\\ \rowsep -\tcode{m.prefix().matched} -& -\tcode{false} -\\ \rowsep -\tcode{m.suffix().first} -& -\tcode{last} -\\ \rowsep -\tcode{m.suffix().second} -& -\tcode{last} -\\ \rowsep -\tcode{m.suffix().matched} -& -\tcode{false} -\\ \rowsep -\tcode{m[0].first} -& -\tcode{first} -\\ \rowsep -\tcode{m[0].second} -& -\tcode{last} -\\ \rowsep -\tcode{m[0].matched} -& -\tcode{true} -\\ \rowsep -\tcode{m[n].first} -& -For all integers \tcode{0 < n < m.size()}, the start of the sequence that matched -sub-expression \tcode{n}. Alternatively, if sub-expression \tcode{n} did not participate -in the match, then \tcode{last}. -\\ \rowsep -\tcode{m[n].second} -& -For all integers \tcode{0 < n < m.size()}, the end of the sequence that matched -sub-expression \tcode{n}. Alternatively, if sub-expression \tcode{n} did not participate -in the match, then \tcode{last}. -\\ \rowsep -\tcode{m[n].matched} -& -For all integers \tcode{0 < n < m.size()}, \tcode{true} if sub-expression \tcode{n} participated in -the match, \tcode{false} otherwise. -\\ -\end{longlibefftabvalue} - -\indexlibraryglobal{regex_match}% -\begin{itemdecl} -template - bool regex_match(BidirectionalIterator first, BidirectionalIterator last, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Behaves ``as if'' by constructing an instance of -\tcode{match_results what}, and then -returning the result of -\tcode{regex_match(first, last, what, e, flags)}. -\end{itemdescr} - -\indexlibraryglobal{regex_match}% -\begin{itemdecl} -template - bool regex_match(const charT* str, - match_results& m, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{regex_match(str, str + char_traits::length(str), m, e, flags)}. -\end{itemdescr} - -\indexlibraryglobal{regex_match}% -\begin{itemdecl} -template - bool regex_match(const basic_string& s, - match_results::const_iterator, - Allocator>& m, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{regex_match(s.begin(), s.end(), m, e, flags)}. -\end{itemdescr} - -\indexlibraryglobal{regex_match}% -\begin{itemdecl} -template - bool regex_match(const charT* str, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{regex_match(str, str + char_traits::length(str), e, flags)} -\end{itemdescr} - -\indexlibraryglobal{regex_match}% -\begin{itemdecl} -template - bool regex_match(const basic_string& s, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{regex_match(s.begin(), s.end(), e, flags)}. -\end{itemdescr} - -\rSec2[re.alg.search]{\tcode{regex_search}} - -\indexlibraryglobal{regex_search}% -\begin{itemdecl} -template - bool regex_search(BidirectionalIterator first, BidirectionalIterator last, - match_results& m, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{BidirectionalIterator} models -\libconcept{bidirectional_iterator}\iref{iterator.concept.bidir}. - -\pnum -\effects -Determines whether there is some sub-sequence within \range{first}{last} that matches -the regular expression \tcode{e}. The parameter \tcode{flags} is used to control how the -expression is matched against the character sequence. Returns \tcode{true} if such a sequence -exists, \tcode{false} otherwise. - -\pnum -\ensures -\tcode{m.ready() == true} in all cases. -If the function returns \tcode{false}, then the effect -on parameter \tcode{m} is unspecified except that \tcode{m.size()} -returns \tcode{0} and \tcode{m.empty()} returns \tcode{true}. Otherwise -the effects on parameter \tcode{m} are given in \tref{re.alg.search}. -\end{itemdescr} - -\begin{longlibefftabvalue} - {Effects of \tcode{regex_search} algorithm} - {re.alg.search} -\tcode{m.size()} -& -\tcode{1 + e.mark_count()} -\\ \rowsep -\tcode{m.empty()} -& -\tcode{false} -\\ \rowsep -\tcode{m.prefix().first} -& -\tcode{first} -\\ \rowsep -\tcode{m.prefix().second} -& -\tcode{m[0].first} -\\ \rowsep -\tcode{m.prefix().matched} -& -\tcode{m.prefix().first != m.prefix().second} -\\ \rowsep -\tcode{m.suffix().first} -& -\tcode{m[0].second} -\\ \rowsep -\tcode{m.suffix().second} -& -\tcode{last} -\\ \rowsep -\tcode{m.suffix().matched} -& -\tcode{m.suffix().first != m.suffix().second} -\\ \rowsep -\tcode{m[0].first} -& -The start of the sequence of characters that matched the regular expression -\\ \rowsep -\tcode{m[0].second} -& -The end of the sequence of characters that matched the regular expression -\\ \rowsep -\tcode{m[0].matched} -& -\tcode{true} -\\ \rowsep -\tcode{m[n].first} -& -For all integers \tcode{0 < n < m.size()}, the start of the sequence that -matched sub-expression \tcode{n}. Alternatively, if sub-expression \tcode{n} -did not participate in the match, then \tcode{last}. -\\ \rowsep -\tcode{m[n].second} -& -For all integers \tcode{0 < n < m.size()}, the end of the sequence that matched -sub-expression \tcode{n}. Alternatively, if sub-expression \tcode{n} did not -participate in the match, then \tcode{last}. -\\ \rowsep -\tcode{m[n].matched} -& -For all integers \tcode{0 < n < m.size()}, \tcode{true} if sub-expression \tcode{n} -participated in the match, \tcode{false} otherwise. -\\ -\end{longlibefftabvalue} - -\indexlibraryglobal{regex_search}% -\begin{itemdecl} -template - bool regex_search(const charT* str, match_results& m, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{regex_search(str, str + char_traits::length(str), m, e, flags)}. -\end{itemdescr} - -\indexlibraryglobal{regex_search}% -\begin{itemdecl} -template - bool regex_search(const basic_string& s, - match_results::const_iterator, - Allocator>& m, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{regex_search(s.begin(), s.end(), m, e, flags)}. -\end{itemdescr} - -\indexlibraryglobal{regex_search}% -\begin{itemdecl} -template - bool regex_search(BidirectionalIterator first, BidirectionalIterator last, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Behaves ``as if'' by constructing an object \tcode{what} -of type \tcode{match_results} and returning -\tcode{regex_search(first, last, what, e, flags)}. -\end{itemdescr} - -\indexlibraryglobal{regex_search}% -\begin{itemdecl} -template - bool regex_search(const charT* str, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{regex_search(str, str + char_traits::length(str), e, flags)}. -\end{itemdescr} - -\indexlibraryglobal{regex_search}% -\begin{itemdecl} -template - bool regex_search(const basic_string& s, - const basic_regex& e, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{regex_search(s.begin(), s.end(), e, flags)}. -\end{itemdescr} - -\rSec2[re.alg.replace]{\tcode{regex_replace}} - -\indexlibraryglobal{regex_replace}% -\begin{itemdecl} -template - OutputIterator - regex_replace(OutputIterator out, - BidirectionalIterator first, BidirectionalIterator last, - const basic_regex& e, - const basic_string& fmt, - regex_constants::match_flag_type flags = regex_constants::match_default); -template - OutputIterator - regex_replace(OutputIterator out, - BidirectionalIterator first, BidirectionalIterator last, - const basic_regex& e, - const charT* fmt, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\indexlibraryglobal{format_no_copy}% -\indexlibraryglobal{format_first_only}% -\effects -Constructs a \tcode{regex_iterator} object \tcode{i} -as if by -\begin{codeblock} -regex_iterator i(first, last, e, flags) -\end{codeblock} -and uses \tcode{i} to enumerate through all -of the matches \tcode{m} of type \tcode{match_results} -that occur within the sequence \range{first}{last}. -If no such -matches are found and -\tcode{!(flags \& regex_constants::format_no_copy)}, then calls -\begin{codeblock} -out = copy(first, last, out) -\end{codeblock} -If any matches are found then, for each such match: -\begin{itemize} -\item -If \tcode{!(flags \& regex_constants::format_no_copy)}, calls -\begin{codeblock} -out = copy(m.prefix().first, m.prefix().second, out) -\end{codeblock} -\item -Then calls -\begin{codeblock} -out = m.format(out, fmt, flags) -\end{codeblock} -for the first form of the function and -\begin{codeblock} -out = m.format(out, fmt, fmt + char_traits::length(fmt), flags) -\end{codeblock} -for the second. -\end{itemize} -Finally, if such a match -is found and \tcode{!(flags \& regex_constants::format_no_copy)}, -calls -\begin{codeblock} -out = copy(last_m.suffix().first, last_m.suffix().second, out) -\end{codeblock} -where \tcode{last_m} is a copy of the last match -found. If \tcode{flags \& regex_constants::format_first_only} -is nonzero, then only the first match found is replaced. - -\pnum -\returns -\tcode{out}. -\end{itemdescr} - -\indexlibraryglobal{regex_replace}% -\begin{itemdecl} -template - basic_string - regex_replace(const basic_string& s, - const basic_regex& e, - const basic_string& fmt, - regex_constants::match_flag_type flags = regex_constants::match_default); -template - basic_string - regex_replace(const basic_string& s, - const basic_regex& e, - const charT* fmt, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs an empty string \tcode{result} of -type \tcode{basic_string} and calls: -\begin{codeblock} -regex_replace(back_inserter(result), s.begin(), s.end(), e, fmt, flags); -\end{codeblock} - -\pnum -\returns -\tcode{result}. -\end{itemdescr} - -\indexlibraryglobal{regex_replace}% -\begin{itemdecl} -template - basic_string - regex_replace(const charT* s, - const basic_regex& e, - const basic_string& fmt, - regex_constants::match_flag_type flags = regex_constants::match_default); -template - basic_string - regex_replace(const charT* s, - const basic_regex& e, - const charT* fmt, - regex_constants::match_flag_type flags = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs an empty string \tcode{result} of -type \tcode{basic_string} and calls: -\begin{codeblock} -regex_replace(back_inserter(result), s, s + char_traits::length(s), e, fmt, flags); -\end{codeblock} - -\pnum -\returns -\tcode{result}. -\end{itemdescr} - -\rSec1[re.iter]{Regular expression iterators} - -\rSec2[re.regiter]{Class template \tcode{regex_iterator}} - -\rSec3[re.regiter.general]{General} -\pnum -\indexlibraryglobal{regex_iterator}% -\indexlibraryglobal{match_results}% -The class template \tcode{regex_iterator} is an iterator adaptor. -It represents a new view of an existing iterator sequence, by -enumerating all the occurrences of a regular expression within that -sequence. A \tcode{regex_iterator} uses \tcode{regex_search} to find successive -regular expression matches within the sequence from which it was -constructed. After the iterator is constructed, and every time \tcode{operator++} is -used, the iterator finds and stores a value of -\tcode{match_results}. If the end of the sequence is -reached (\tcode{regex_search} returns \tcode{false}), the iterator becomes equal to -the end-of-sequence iterator value. The default constructor -constructs an end-of-sequence iterator object, -which is the only legitimate iterator to be used for the end -condition. The result of \tcode{operator*} on an end-of-sequence iterator is not -defined. For any other iterator value a const -\tcode{match_results\&} is returned. The result of -\tcode{operator->} on an end-of-sequence iterator is not defined. For any other -iterator value a \tcode{const match_results*} is -returned. It is impossible to store things into \tcode{regex_iterator}s. Two -end-of-sequence iterators are always equal. An end-of-sequence -iterator is not equal to a non-end-of-sequence iterator. Two -non-end-of-sequence iterators are equal when they are constructed from -the same arguments. - -\begin{codeblock} -namespace std { - template::value_type, - class traits = regex_traits> - class regex_iterator { - public: - using regex_type = basic_regex; - using iterator_category = forward_iterator_tag; - using iterator_concept = input_iterator_tag; - using value_type = match_results; - using difference_type = ptrdiff_t; - using pointer = const value_type*; - using reference = const value_type&; - - regex_iterator(); - regex_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type& re, - regex_constants::match_flag_type m = regex_constants::match_default); - regex_iterator(BidirectionalIterator, BidirectionalIterator, - const regex_type&&, - regex_constants::match_flag_type = regex_constants::match_default) = delete; - regex_iterator(const regex_iterator&); - regex_iterator& operator=(const regex_iterator&); - bool operator==(const regex_iterator&) const; - bool operator==(default_sentinel_t) const { return *this == regex_iterator(); } - const value_type& operator*() const; - const value_type* operator->() const; - regex_iterator& operator++(); - regex_iterator operator++(int); - - private: - BidirectionalIterator begin; // \expos - BidirectionalIterator end; // \expos - const regex_type* pregex; // \expos - regex_constants::match_flag_type flags; // \expos - match_results match; // \expos - }; -} -\end{codeblock} - -\pnum -An object of type \tcode{regex_iterator} that is not an end-of-sequence iterator -holds a \textit{zero-length match} if \tcode{match[0].matched == true} and -\tcode{match[0].first == match[0].second}. -\begin{note} -For -example, this can occur when the part of the regular expression that -matched consists only of an assertion (such as \verb|'^'|, \verb|'$'|, -\tcode{'$\backslash$b'}, \tcode{'$\backslash$B'}). -\end{note} - -\rSec3[re.regiter.cnstr]{Constructors} - -\indexlibraryctor{regex_iterator}% -\begin{itemdecl} -regex_iterator(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs an end-of-sequence iterator. -\end{itemdescr} - -\indexlibraryctor{regex_iterator}% -\begin{itemdecl} -regex_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type& re, - regex_constants::match_flag_type m = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Initializes \tcode{begin} and \tcode{end} to -\tcode{a} and \tcode{b}, respectively, sets -\tcode{pregex} to \tcode{addressof(re)}, sets \tcode{flags} to -\tcode{m}, then calls \tcode{regex_search(begin, end, match, *pregex, flags)}. If this -call returns \tcode{false} the constructor sets \tcode{*this} to the end-of-sequence -iterator. -\end{itemdescr} - -\rSec3[re.regiter.comp]{Comparisons} - -\indexlibrarymember{regex_iterator}{operator==}% -\begin{itemdecl} -bool operator==(const regex_iterator& right) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if \tcode{*this} and \tcode{right} are both end-of-sequence -iterators or if the following conditions all hold: -\begin{itemize} -\item \tcode{begin == right.begin}, -\item \tcode{end == right.end}, -\item \tcode{pregex == right.pregex}, -\item \tcode{flags == right.flags}, and -\item \tcode{match[0] == right.match[0]}; -\end{itemize} -otherwise \tcode{false}. -\end{itemdescr} - -\rSec3[re.regiter.deref]{Indirection} - -\indexlibrarymember{regex_iterator}{operator*}% -\begin{itemdecl} -const value_type& operator*() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{match}. -\end{itemdescr} - -\indexlibrarymember{operator->}{regex_iterator}% -\begin{itemdecl} -const value_type* operator->() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{addressof(match)}. -\end{itemdescr} - -\rSec3[re.regiter.incr]{Increment} - -\indexlibrarymember{regex_iterator}{operator++}% -\indexlibrary{\idxcode{regex_iterator}!increment}% -\begin{itemdecl} -regex_iterator& operator++(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs a local variable \tcode{start} of type \tcode{BidirectionalIterator} and -initializes it with the value of \tcode{match[0].second}. - -\pnum -If the iterator holds a zero-length match and \tcode{start == end} the operator -sets \tcode{*this} to the end-of-sequence iterator and returns \tcode{*this}. - -\pnum -\indexlibraryglobal{match_not_null}% -\indexlibraryglobal{match_continuous}% -Otherwise, if the iterator holds a zero-length match, the operator calls: -\begin{codeblock} -regex_search(start, end, match, *pregex, - flags | regex_constants::match_not_null | regex_constants::match_continuous) -\end{codeblock} -If the call returns \tcode{true} the operator -returns \tcode{*this}. Otherwise the operator increments \tcode{start} and continues as if -the most recent match was not a zero-length match. - -\pnum -\indexlibraryglobal{match_prev_avail}% -If the most recent match was not a zero-length match, the operator sets -\tcode{flags} to \tcode{flags | regex_constants::match_prev_avail} and -calls \tcode{regex_search(start, end, match, *pregex, flags)}. If the call returns -\tcode{false} the iterator sets \tcode{*this} to the end-of-sequence iterator. The -iterator then returns \tcode{*this}. - -\pnum -In all cases in which the call to \tcode{regex_search} returns \tcode{true}, -\tcode{match.prefix().first} shall be equal to the previous value of -\tcode{match[0].second}, and for each index \tcode{i} in the half-open range -\tcode{[0, match.size())} for which \tcode{match[i].matched} is \tcode{true}, -\tcode{match.position(i)} -shall return \tcode{distance(begin, match[i].\brk{}first)}. - -\pnum -\begin{note} -This means that \tcode{match.position(i)} gives the -offset from the beginning of the target sequence, which is often not -the same as the offset from the sequence passed in the call -to \tcode{regex_search}. -\end{note} - -\pnum -It is unspecified how the implementation makes these adjustments. - -\pnum -\begin{note} -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. -\end{note} -\end{itemdescr} - -\indexlibrarymember{regex_iterator}{operator++}% -\begin{itemdecl} -regex_iterator operator++(int); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by: -\begin{codeblock} -regex_iterator tmp = *this; -++(*this); -return tmp; -\end{codeblock} -\end{itemdescr} - -\rSec2[re.tokiter]{Class template \tcode{regex_token_iterator}} - -\rSec3[re.tokiter.general]{General} - -\pnum -\indexlibraryglobal{regex_token_iterator}% -The class template \tcode{regex_token_iterator} is an iterator adaptor; that -is to say it represents a new view of an existing iterator sequence, -by enumerating all the occurrences of a regular expression within that -sequence, and presenting one or more sub-expressions for each match -found. Each position enumerated by the iterator is a \tcode{sub_match} class -template instance that represents what matched a particular sub-expression -within the regular expression. - -\pnum -When class \tcode{regex_token_iterator} is used to enumerate a -single sub-expression with index $-1$ the iterator performs field -splitting: that is to say it enumerates one sub-expression for each section of -the character container sequence that does not match the regular -expression specified. - -\pnum -\indexlibraryglobal{match_results}% -After it is constructed, the iterator finds and stores a value -\tcode{regex_iterator position} -and sets the internal count \tcode{N} to zero. It also maintains a sequence -\tcode{subs} which contains a list of the sub-expressions which will be -enumerated. Every time \tcode{operator++} is used -the count \tcode{N} is incremented; if \tcode{N} exceeds or equals \tcode{subs.size()}, -then the iterator increments member \tcode{position} -and sets count \tcode{N} to zero. - -\pnum -If the end of sequence is reached (\tcode{position} is equal to the end of -sequence iterator), the iterator becomes equal to the end-of-sequence -iterator value, unless the sub-expression being enumerated has index $-1$, -in which case the iterator enumerates one last sub-expression that contains -all the characters from the end of the last regular expression match to the -end of the input sequence being enumerated, provided that this would not be an -empty sub-expression. - -\pnum -\indexlibrary{\idxcode{regex_token_iterator}!end-of-sequence}% -The default constructor constructs -an end-of-sequence iterator object, which is the only legitimate -iterator to be used for the end condition. The result of \tcode{operator*} on -an end-of-sequence iterator is not defined. For any other iterator value a -\tcode{const sub_match\&} is returned. -The result of \tcode{operator->} on an end-of-sequence iterator -is not defined. For any other iterator value a \tcode{const -sub_match*} is returned. - -\pnum -\indexlibrarymember{regex_token_iterator}{operator==}% -It is impossible to store things -into \tcode{regex_token_iterator}s. Two end-of-sequence iterators are always -equal. An end-of-sequence iterator is not equal to a -non-end-of-sequence iterator. Two non-end-of-sequence iterators are -equal when they are constructed from the same arguments. - -\begin{codeblock} -namespace std { - template::value_type, - class traits = regex_traits> - class regex_token_iterator { - public: - using regex_type = basic_regex; - using iterator_category = forward_iterator_tag; - using iterator_concept = input_iterator_tag; - using value_type = sub_match; - using difference_type = ptrdiff_t; - using pointer = const value_type*; - using reference = const value_type&; - - regex_token_iterator(); - regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type& re, - int submatch = 0, - regex_constants::match_flag_type m = - regex_constants::match_default); - regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type& re, - const vector& submatches, - regex_constants::match_flag_type m = - regex_constants::match_default); - regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type& re, - initializer_list submatches, - regex_constants::match_flag_type m = - regex_constants::match_default); - template - regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type& re, - const int (&submatches)[N], - regex_constants::match_flag_type m = - regex_constants::match_default); - regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type&& re, - int submatch = 0, - regex_constants::match_flag_type m = - regex_constants::match_default) = delete; - regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type&& re, - const vector& submatches, - regex_constants::match_flag_type m = - regex_constants::match_default) = delete; - regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type&& re, - initializer_list submatches, - regex_constants::match_flag_type m = - regex_constants::match_default) = delete; - template - regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type&& re, - const int (&submatches)[N], - regex_constants::match_flag_type m = - regex_constants::match_default) = delete; - regex_token_iterator(const regex_token_iterator&); - regex_token_iterator& operator=(const regex_token_iterator&); - bool operator==(const regex_token_iterator&) const; - bool operator==(default_sentinel_t) const { return *this == regex_token_iterator(); } - const value_type& operator*() const; - const value_type* operator->() const; - regex_token_iterator& operator++(); - regex_token_iterator operator++(int); - - private: - using position_iterator = - regex_iterator; // \expos - position_iterator position; // \expos - const value_type* result; // \expos - value_type suffix; // \expos - size_t N; // \expos - vector subs; // \expos - }; -} -\end{codeblock} - -\pnum -A \textit{suffix iterator} is a \tcode{regex_token_iterator} object -that points to a final sequence of characters at -the end of the target sequence. In a suffix iterator the -member \tcode{result} holds a pointer to the data -member \tcode{suffix}, the value of the member \tcode{suffix.match} -is \tcode{true}, \tcode{suffix.first} points to the beginning of the -final sequence, and \tcode{suffix.second} points to the end of the -final sequence. - -\pnum -\begin{note} -For a suffix iterator, data -member \tcode{suffix.first} is the same as the end of the last match -found, and \tcode{suffix\brk.second} is the same as the end of the target -sequence. -\end{note} - -\pnum -The \textit{current match} is \tcode{(*position).prefix()} if \tcode{subs[N] == -1}, or -\tcode{(*position)[subs[N]]} for any other value of \tcode{subs[N]}. - -\rSec3[re.tokiter.cnstr]{Constructors} - -\indexlibraryctor{regex_token_iterator}% -\begin{itemdecl} -regex_token_iterator(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs the end-of-sequence iterator. -\end{itemdescr} - -\indexlibraryctor{regex_token_iterator}% -\begin{itemdecl} -regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type& re, - int submatch = 0, - regex_constants::match_flag_type m = regex_constants::match_default); - -regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type& re, - const vector& submatches, - regex_constants::match_flag_type m = regex_constants::match_default); - -regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type& re, - initializer_list submatches, - regex_constants::match_flag_type m = regex_constants::match_default); - -template - regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, - const regex_type& re, - const int (&submatches)[N], - regex_constants::match_flag_type m = regex_constants::match_default); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -Each of the initialization values of \tcode{submatches} is \tcode{>= -1}. - -\pnum -\effects -The first constructor initializes the member \tcode{subs} to hold the single -value \tcode{submatch}. -The second, third, and fourth constructors -initialize the member \tcode{subs} to hold a copy of the sequence of integer values -pointed to by the iterator range -\range{begin(submatches)}{end(submatches)}. - -\pnum -Each constructor then sets \tcode{N} to 0, and \tcode{position} to -\tcode{position_iterator(a, b, re, m)}. If \tcode{position} is not an -end-of-sequence iterator the constructor sets \tcode{result} to the -address of the current match. Otherwise if any of the values stored -in \tcode{subs} is equal to $-1$ the constructor sets \tcode{*this} to a suffix -iterator that points to the range \range{a}{b}, otherwise the constructor -sets \tcode{*this} to an end-of-sequence iterator. -\end{itemdescr} - -\rSec3[re.tokiter.comp]{Comparisons} - -\indexlibrarymember{regex_token_iterator}{operator==}% -\begin{itemdecl} -bool operator==(const regex_token_iterator& right) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if \tcode{*this} and \tcode{right} are both end-of-sequence iterators, -or if \tcode{*this} and \tcode{right} are both suffix iterators and \tcode{suffix == right.suffix}; -otherwise returns \tcode{false} if \tcode{*this} or \tcode{right} is an end-of-sequence -iterator or a suffix iterator. Otherwise returns \tcode{true} if \tcode{position == right.position}, -\tcode{N == right.N}, and \tcode{subs == right.subs}. Otherwise returns \tcode{false}. -\end{itemdescr} - -\rSec3[re.tokiter.deref]{Indirection} - -\indexlibrarymember{regex_token_iterator}{operator*}% -\begin{itemdecl} -const value_type& operator*() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{*result}. -\end{itemdescr} - -\indexlibrarymember{operator->}{regex_token_iterator}% -\begin{itemdecl} -const value_type* operator->() const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{result}. -\end{itemdescr} - - -\rSec3[re.tokiter.incr]{Increment} - -\indexlibrarymember{regex_token_iterator}{operator++}% -\begin{itemdecl} -regex_token_iterator& operator++(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs a local variable \tcode{prev} of -type \tcode{position_iterator}, initialized with the value -of \tcode{position}. - -\pnum -If \tcode{*this} is a suffix iterator, sets \tcode{*this} to an -end-of-sequence iterator. - -\pnum -Otherwise, if \tcode{N + 1 < subs.size()}, increments \tcode{N} and -sets \tcode{result} to the address of the current match. - -\pnum -Otherwise, sets \tcode{N} to 0 and -increments \tcode{position}. If \tcode{position} is not an -end-of-sequence iterator the operator sets \tcode{result} to the -address of the current match. - -\pnum -Otherwise, if any of the values stored in \tcode{subs} is equal to $-1$ and -\tcode{prev->suffix().length()} is not 0 the operator sets \tcode{*this} to a -suffix iterator that points to the range \range{prev->suffix().first}{prev->suffix().second}. - -\pnum -Otherwise, sets \tcode{*this} to an end-of-sequence iterator. - -\pnum -\returns -\tcode{*this} -\end{itemdescr} - -\indexlibrarymember{regex_token_iterator}{operator++}% -\begin{itemdecl} -regex_token_iterator& operator++(int); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Constructs a copy \tcode{tmp} of \tcode{*this}, then calls \tcode{++(*this)}. - -\pnum -\returns -\tcode{tmp}. -\end{itemdescr} - -\rSec1[re.grammar]{Modified ECMAScript regular expression grammar} -\indextext{regular expression!grammar}% -\indextext{grammar!regular expression}% - -\pnum -\indexlibraryglobal{basic_regex}% -\indextext{ECMAScript}% -The regular expression grammar recognized by -\tcode{basic_regex} objects constructed with the ECMAScript -flag is that specified by ECMA-262, except as specified below. - -\pnum -\indexlibraryglobal{locale}% -\indextext{regular expression traits}% -Objects of type specialization of \tcode{basic_regex} store within themselves a -default-constructed instance of their \tcode{traits} template parameter, henceforth -referred to as \tcode{traits_inst}. This \tcode{traits_inst} object is used to support localization -of the regular expression; \tcode{basic_regex} member functions shall not call -any locale dependent C or \Cpp{} API, including the formatted string input functions. -Instead they shall call the appropriate traits member function to achieve the required effect. - -\pnum -The following productions within the ECMAScript grammar are modified as follows: - -\begin{ncrebnf} -\renontermdef{ClassAtom}\br - \terminal{-}\br - ClassAtomNoDash\br - ClassAtomExClass\br - ClassAtomCollatingElement\br - ClassAtomEquivalence -\end{ncrebnf} - -\begin{ncrebnf} -\renontermdef{IdentityEscape}\br - SourceCharacter \textnormal{\textbf{but not}} \terminal{c} -\end{ncrebnf} - -\pnum -The following new productions are then added: - -\begin{ncrebnf} -\renontermdef{ClassAtomExClass}\br - \terminal{[:} ClassName \terminal{:]} -\end{ncrebnf} - -\begin{ncrebnf} -\renontermdef{ClassAtomCollatingElement}\br - \terminal{[.} ClassName \terminal{.]} -\end{ncrebnf} - -\begin{ncrebnf} -\renontermdef{ClassAtomEquivalence}\br - \terminal{[=} ClassName \terminal{=]} -\end{ncrebnf} - -\begin{ncrebnf} -\renontermdef{ClassName}\br - ClassNameCharacter\br - ClassNameCharacter ClassName -\end{ncrebnf} - -\begin{ncrebnf} -\renontermdef{ClassNameCharacter}\br - SourceCharacter \textnormal{\textbf{but not one of}} \terminal{.} \textnormal{\textbf{or}} \terminal{=} \textnormal{\textbf{or}} \terminal{:} -\end{ncrebnf} - -\pnum -The productions \regrammarterm{ClassAtomExClass}, \regrammarterm{ClassAtomCollatingElement} -and \regrammarterm{ClassAtomEquivalence} provide functionality -equivalent to that of the same features in regular expressions in POSIX. - -\pnum -The regular expression grammar may be modified by -any \tcode{regex_constants::syntax_option_type} flags specified when -constructing an object of type specialization of \tcode{basic_regex} -according to the rules in \tref{re.synopt}. - -\pnum -A \regrammarterm{ClassName} production, when used in \regrammarterm{ClassAtomExClass}, -is not valid if \tcode{traits_inst.lookup_classname} returns zero for -that name. The names recognized as valid \regrammarterm{ClassName}s are -determined by the type of the traits class, but at least the following -names shall be recognized: -\tcode{alnum}, \tcode{alpha}, \tcode{blank}, \tcode{cntrl}, \tcode{digit}, -\tcode{graph}, \tcode{lower}, \tcode{print}, \tcode{punct}, \tcode{space}, -\tcode{upper}, \tcode{xdigit}, \tcode{d}, \tcode{s}, \tcode{w}. -In addition the following expressions shall be equivalent: - -\begin{codeblock} -\d @\textnormal{and}@ [[:digit:]] - -\D @\textnormal{and}@ [^[:digit:]] - -\s @\textnormal{and}@ [[:space:]] - -\S @\textnormal{and}@ [^[:space:]] - -\w @\textnormal{and}@ [_[:alnum:]] - -\W @\textnormal{and}@ [^_[:alnum:]] -\end{codeblock} - -\pnum -\indexlibrary{regular expression traits!\idxcode{lookup_collatename}}% -\indexlibrary{\idxcode{lookup_collatename}!regular expression traits}% -A \regrammarterm{ClassName} production when used in -a \regrammarterm{ClassAtomCollatingElement} production is not valid -if the value returned by \tcode{traits_inst.lookup_collatename} for -that name is an empty string. - -\pnum -\indexlibrary{regular expression traits!\idxcode{isctype}}% -\indexlibrary{\idxcode{isctype}!regular expression traits}% -\indexlibrary{regular expression traits!\idxcode{lookup_classname}}% -\indexlibrary{\idxcode{lookup_classname}!regular expression traits}% -The results from multiple calls -to \tcode{traits_inst.lookup_classname} can be bitwise \logop{or}'ed -together and subsequently passed to \tcode{traits_inst.isctype}. - -\pnum -A \regrammarterm{ClassName} production when used in -a \regrammarterm{ClassAtomEquivalence} production is not valid if the value -returned by \tcode{traits_inst.lookup_collatename} for that name is an -empty string or if the value returned by \tcode{traits_inst\brk.transform_primary} -for the result of the call to \tcode{traits_inst.lookup_collatename} -is an empty string. - -\pnum -\indexlibraryglobal{regex_error}% -When the sequence of characters being transformed to a finite state -machine contains an invalid class name the translator shall throw an -exception object of type \tcode{regex_error}. - -\pnum -\indexlibraryglobal{regex_error}% -If the \textit{CV} of a \textit{UnicodeEscapeSequence} is greater than the largest -value that can be held in an object of type \tcode{charT} the translator shall -throw an exception object of type \tcode{regex_error}. -\begin{note} -This means that values of the form \tcode{"uxxxx"} that do not fit in -a character are invalid. -\end{note} - -\pnum -Where the regular expression grammar requires the conversion of a sequence of characters -to an integral value, this is accomplished by calling \tcode{traits_inst.value}. - -\pnum -\indexlibraryglobal{match_flag_type}% -The behavior of the internal finite state machine representation when used to match a -sequence of characters is as described in ECMA-262. -The behavior is modified according -to any \tcode{match_flag_type} flags\iref{re.matchflag} specified when using the regular expression -object in one of the regular expression algorithms\iref{re.alg}. The behavior is also -localized by interaction with the traits class template parameter as follows: -\begin{itemize} -\item During matching of a regular expression finite state machine -against a sequence of characters, two characters \tcode{c} -and \tcode{d} are compared using the following rules: -\begin{itemize} -\item if \tcode{(flags() \& regex_constants::icase)} the two characters are equal -if \tcode{traits_inst.trans\-late_nocase(c) == traits_inst.translate_nocase(d)}; -\item otherwise, if \tcode{flags() \& regex_constants::collate} the -two characters are equal if -\tcode{traits_inst\brk.translate(c) == traits_inst\brk.translate(d)}; -\indexlibrarymember{syntax_option_type}{collate}% -\item otherwise, the two characters are equal if \tcode{c == d}. -\end{itemize} - -\item During matching of a regular expression finite state machine -against a sequence of characters, comparison of a collating element -range \tcode{c1-c2} against a character \tcode{c} is -conducted as follows: if \tcode{flags() \& regex_constants::collate} -is \tcode{false} then the character \tcode{c} is matched if \tcode{c1 -<= c \&\& c <= c2}, otherwise \tcode{c} is matched in -accordance with the following algorithm: - -\begin{codeblock} -string_type str1 = string_type(1, - flags() & icase ? - traits_inst.translate_nocase(c1) : traits_inst.translate(c1)); -string_type str2 = string_type(1, - flags() & icase ? - traits_inst.translate_nocase(c2) : traits_inst.translate(c2)); -string_type str = string_type(1, - flags() & icase ? - traits_inst.translate_nocase(c) : traits_inst.translate(c)); -return traits_inst.transform(str1.begin(), str1.end()) - <= traits_inst.transform(str.begin(), str.end()) - && traits_inst.transform(str.begin(), str.end()) - <= traits_inst.transform(str2.begin(), str2.end()); -\end{codeblock} - -\item During matching of a regular expression finite state machine against a sequence of -characters, testing whether a collating element is a member of a primary equivalence -class is conducted by first converting the collating element and the equivalence -class to sort keys using \tcode{traits::transform_primary}, and then comparing the sort -keys for equality. -\indextext{regular expression traits!\idxcode{transform_primary}}% -\indextext{transform_primary@\tcode{transform_primary}!regular expression traits}% - -\item During matching of a regular expression finite state machine against a sequence -of characters, a character \tcode{c} is a member of a character class designated by an -iterator range \range{first}{last} if -\tcode{traits_inst.isctype(c, traits_inst.lookup_classname(first, last, flags() \& icase))} is \tcode{true}. -\end{itemize} -\xref ECMA-262 15.10 -\indextext{regular expression|)} diff --git a/source/statements.tex b/source/statements.tex index 4ebc6e7309..34018bd618 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -1,5 +1,5 @@ %!TEX root = std.tex -\rSec0[stmt.stmt]{Statements}% +\rSec0[stmt]{Statements}% \indextext{statement|(} \gramSec[gram.stmt]{Statements} @@ -9,7 +9,7 @@ \rSec1[stmt.pre]{Preamble} \pnum -Except as indicated, statements are executed in sequence. +Except as indicated, statements are executed in sequence\iref{intro.execution}. \begin{bnf} \nontermdef{statement}\br @@ -18,7 +18,9 @@ \opt{attribute-specifier-seq} compound-statement\br \opt{attribute-specifier-seq} selection-statement\br \opt{attribute-specifier-seq} iteration-statement\br + \opt{attribute-specifier-seq} expansion-statement\br \opt{attribute-specifier-seq} jump-statement\br + \opt{attribute-specifier-seq} assertion-statement\br declaration-statement\br \opt{attribute-specifier-seq} try-block \end{bnf} @@ -33,10 +35,24 @@ \begin{bnf} \nontermdef{condition}\br expression\br - \opt{attribute-specifier-seq} decl-specifier-seq declarator brace-or-equal-initializer + \opt{attribute-specifier-seq} decl-specifier-seq declarator brace-or-equal-initializer\br + structured-binding-declaration initializer +\end{bnf} + +\begin{bnf} +\nontermdef{for-range-declaration}\br + \opt{attribute-specifier-seq} decl-specifier-seq declarator\br + structured-binding-declaration +\end{bnf} + +\begin{bnf} +\nontermdef{for-range-initializer}\br + expr-or-braced-init-list \end{bnf} The optional \grammarterm{attribute-specifier-seq} appertains to the respective statement. +See~\ref{dcl.meaning} for the optional \grammarterm{attribute-specifier-seq} in a +\grammarterm{for-range-declaration}. \pnum A \defn{substatement} of a \grammarterm{statement} is one of the following: @@ -46,9 +62,12 @@ \item for a \grammarterm{compound-statement}, any \grammarterm{statement} of its \grammarterm{statement-seq}, \item - for a \grammarterm{selection-statement}, any of its \grammarterm{statement}{s} or \grammarterm{compound-statement}{s} (but not its \grammarterm{init-statement}), or + for a \grammarterm{selection-statement}, any of its \grammarterm{statement}{s} or \grammarterm{compound-statement}{s} (but not its \grammarterm{init-statement}), +\item + for an \grammarterm{iteration-statement}, its \grammarterm{statement} (but not an \grammarterm{init-statement}), or \item - for an \grammarterm{iteration-statement}, its \grammarterm{statement} (but not an \grammarterm{init-statement}). + for an \grammarterm{expansion-statement}, its \grammarterm{compound-statement} + (but not an \grammarterm{init-statement}). \end{itemize} \begin{note} The \grammarterm{compound-statement} of a \grammarterm{lambda-expression} @@ -64,9 +83,10 @@ \item \tcode{S2} is a substatement of \tcode{S1}, \item - \tcode{S1} is a \grammarterm{selection-statement} or - \grammarterm{iteration-statement} and - \tcode{S2} is the \grammarterm{init-statement} of \tcode{S1}, + \tcode{S1} is a \grammarterm{selection-statement}, + \grammarterm{iteration-statement}, or + \grammarterm{expansion-statement}, + and \tcode{S2} is the \grammarterm{init-statement} of \tcode{S1}, \item \tcode{S1} is a \grammarterm{try-block} and \tcode{S2} is its \grammarterm{compound-statement} or @@ -86,8 +106,12 @@ The rules for \grammarterm{condition}{s} apply both to \grammarterm{selection-statement}{s}\iref{stmt.select} and to the \keyword{for} and \keyword{while} statements\iref{stmt.iter}. -A \grammarterm{condition} that is not an \grammarterm{expression} is a -declaration\iref{dcl.dcl}. +If a \grammarterm{structured-binding-declaration} +appears in a \grammarterm{condition}, +the \grammarterm{condition} is a structured binding declaration\iref{dcl.pre}. +A \grammarterm{condition} that is +neither an \grammarterm{expression} nor a structured binding declaration +is a declaration\iref{dcl}. The \grammarterm{declarator} shall not specify a function or an array. The \grammarterm{decl-specifier-seq} shall not define a class or enumeration. If the \keyword{auto} \grammarterm{type-specifier} appears in @@ -95,9 +119,16 @@ the type of the identifier being declared is deduced from the initializer as described in~\ref{dcl.spec.auto}. \pnum -The value of a \grammarterm{condition} that is an initialized declaration +The \defnadj{decision}{variable} of a \grammarterm{condition} +that is neither an \grammarterm{expression} nor a structured binding declaration +is the declared variable. +The decision variable of a \grammarterm{condition} +that is a structured binding declaration is specified in \ref{dcl.struct.bind}. + +\pnum +The value of a \grammarterm{condition} that is not an \grammarterm{expression} in a statement other than a \keyword{switch} statement is the value of the -declared variable +decision variable contextually converted to \tcode{bool}\iref{conv}. If that conversion is ill-formed, the program is ill-formed. @@ -116,9 +147,15 @@ it is interpreted as the latter. \pnum -In the \grammarterm{decl-specifier-seq} of a \grammarterm{condition}, each +In the \grammarterm{decl-specifier-seq} of a \grammarterm{condition} +or of a \grammarterm{for-range-declaration}, +including that of any \grammarterm{structured-binding-declaration} of +the \grammarterm{condition}, +each \grammarterm{decl-specifier} shall be either a \grammarterm{type-specifier} or \keyword{constexpr}. +The \grammarterm{decl-specifier-seq} of a \grammarterm{for-range-declaration} +shall not define a class or enumeration. \rSec1[stmt.label]{Label}% \indextext{statement!labeled} @@ -170,6 +207,9 @@ statement\iref{stmt.goto} in \tcode{S}. \end{itemize} +\pnum +An identifier label shall not be enclosed +by an \grammarterm{expansion-statement}\iref{stmt.expand}. \rSec1[stmt.expr]{Expression statement}% \indextext{statement!expression} @@ -211,14 +251,12 @@ \begin{bnf} \nontermdef{statement-seq}\br - statement\br - statement-seq statement + statement \opt{statement-seq} \end{bnf} \begin{bnf} \nontermdef{label-seq}\br - label\br - label-seq label + label \opt{label-seq} \end{bnf} A label at the end of a \grammarterm{compound-statement} @@ -231,9 +269,9 @@ \end{note} \rSec1[stmt.select]{Selection statements}% +\indextext{statement!selection|(} \rSec2[stmt.select.general]{General}% -\indextext{statement!selection|(} \pnum Selection statements choose one of several flows of control. @@ -267,7 +305,7 @@ \indextext{statement!\idxcode{if}} \pnum -If the condition\iref{stmt.pre} yields \tcode{true} the first +If the condition\iref{stmt.pre} yields \tcode{true}, the first substatement is executed. If the \keyword{else} part of the selection statement is present and the condition yields \tcode{false}, the second substatement is executed. If the first substatement is reached via a @@ -408,10 +446,9 @@ several statements depending on the value of a condition. \pnum -The value of a \grammarterm{condition} -that is an initialized declaration -is the value of the declared variable, -or the value of the \grammarterm{expression} otherwise. +If the \grammarterm{condition} is an \grammarterm{expression}, +the value of the condition is the value of the \grammarterm{expression}; +otherwise, it is the value of the decision variable. The value of the condition shall be of integral type, enumeration type, or class type. If of class type, the condition is contextually implicitly converted\iref{conv} to @@ -487,9 +524,9 @@ \indextext{statement!selection|)} \rSec1[stmt.iter]{Iteration statements}% +\indextext{statement!iteration|(} \rSec2[stmt.iter.general]{General}% -\indextext{statement!iteration|(} \pnum Iteration statements specify looping. @@ -506,19 +543,6 @@ \keyword{for} \terminal{(} \opt{init-statement} for-range-declaration \terminal{:} for-range-initializer \terminal{)} statement \end{bnf} -\begin{bnf} -\nontermdef{for-range-declaration}\br - \opt{attribute-specifier-seq} decl-specifier-seq declarator\br - \opt{attribute-specifier-seq} decl-specifier-seq \opt{ref-qualifier} \terminal{[} identifier-list \terminal{]} -\end{bnf} - -\begin{bnf} -\nontermdef{for-range-initializer}\br - expr-or-braced-init-list -\end{bnf} - -See~\ref{dcl.meaning} for the optional \grammarterm{attribute-specifier-seq} in a -\grammarterm{for-range-declaration}. \begin{note} An \grammarterm{init-statement} ends with a semicolon. \end{note} @@ -546,6 +570,37 @@ Thus after the \keyword{while} statement, \tcode{i} is no longer in scope. \end{example} +\pnum +A \defnadj{trivially empty}{iteration statement} is +an iteration statement matching one of the following forms: +\begin{itemize} +\item \tcode{while (} \grammarterm{expression} \tcode{) ;} +\item \tcode{while (} \grammarterm{expression} \tcode{) \{ \}} +\item \tcode{do ; while (} \grammarterm{expression} \tcode{) ;} +\item \tcode{do \{ \} while (} \grammarterm{expression} \tcode{) ;} +\item \tcode{for (} \grammarterm{init-statement} \opt{\grammarterm{expression}} \tcode{; ) ;} +\item \tcode{for (} \grammarterm{init-statement} \opt{\grammarterm{expression}} \tcode{; ) \{ \}} +\end{itemize} +The \defnadj{controlling}{expression} of a trivially empty iteration statement +is the \grammarterm{expression} of +a \tcode{while}, \tcode{do}, or \tcode{for} statement +(or \tcode{true}, if the \tcode{for} statement has no \grammarterm{expression}). +A \defnadj{trivial infinite}{loop} is a trivially empty iteration statement +for which the converted controlling expression is a constant expression, +when interpreted as a \grammarterm{constant-expression}\iref{expr.const}, and +evaluates to \tcode{true}. +The \grammarterm{statement} of a trivial infinite loop is replaced with +a call to the function \tcode{std::this_thread::yield}\iref{thread.thread.this}; +it is \impldef{whether freestanding implementations replace the \grammarterm{statement} +of a trivial infinite loop with a call to the function \tcode{std::this_thread::yield}} +whether this replacement occurs on freestanding implementations. +\begin{note} +In a freestanding environment, +concurrent forward progress is not guaranteed; +such systems therefore require explicit cooperation. +A call to yield can add implicit cooperation where none is otherwise intended. +\end{note} + \rSec2[stmt.while]{The \keyword{while} statement}% \indextext{statement!\idxcode{while}} @@ -640,7 +695,7 @@ and the \grammarterm{expression} can be omitted. A missing \grammarterm{condition} makes the implied \keyword{while} clause -equivalent to \tcode{while(true)}. +equivalent to \tcode{while (true)}. \rSec2[stmt.ranged]{The range-based \keyword{for} statement}% \indextext{statement!range based for@range based \tcode{for}} @@ -677,15 +732,15 @@ \exposid{begin-expr} and \exposid{end-expr} are determined as follows: \begin{itemize} -\item if the \grammarterm{for-range-initializer} is an expression of +\item if the type of \exposid{range} is a reference to an array type \tcode{R}, \exposid{begin-expr} and \exposid{end-expr} are \exposid{range} and \exposid{range} \tcode{+} \tcode{N}, respectively, where \tcode{N} is the array bound. If \tcode{R} is an array of unknown bound or an array of incomplete type, the program is ill-formed; -\item if the \grammarterm{for-range-initializer} is -an expression of class type \tcode{C}, and +\item if the type of \exposid{range} is a reference to a +class type \tcode{C}, and searches in the scope of \tcode{C}\iref{class.member.lookup} for the names \tcode{begin} and \tcode{end} each find at least one declaration, @@ -728,13 +783,204 @@ \end{codeblock} \end{example} -\pnum -In the \grammarterm{decl-specifier-seq} of a \grammarterm{for-range-declaration}, -each \grammarterm{decl-specifier} shall be either a \grammarterm{type-specifier} -or \keyword{constexpr}. The \grammarterm{decl-specifier-seq} shall not define a -class or enumeration.% \indextext{statement!iteration|)} +\rSec1[stmt.expand]{Expansion statements} +\indextext{statement!expansion|(} + +\pnum +Expansion statements specify repeated instantiations\iref{temp.decls.general} +of their substatement. + +\begin{bnf} +\nontermdef{expansion-statement}\br + \keyword{template} \keyword{for} \terminal{(} + \opt{init-statement} for-range-declaration \terminal{:} + expansion-initializer \terminal{)} compound-statement +\end{bnf} + +\begin{bnf} +\nontermdef{expansion-initializer}\br + expression\br + expansion-init-list +\end{bnf} + +\begin{bnf} +\nontermdef{expansion-init-list}\br + \terminal{\{} \opt{expression-list} \terminal{\}} +\end{bnf} + +\pnum +The \grammarterm{compound-statement} of an \grammarterm{expansion-statement} +is a control-flow-limited statement\iref{stmt.label}. + +\pnum +For an expression \tcode{E}, let the expressions +\exposid{begin-expr} and \exposid{end-expr} be determined as specified in~\ref{stmt.ranged}. +An expression is \defn{expansion-iterable} if it does not have array type and either +\begin{itemize} +\item +\exposid{begin-expr} and \exposid{end-expr} are of the form +\tcode{E.begin()} and \tcode{E.end()}, or +\item +argument-dependent lookups for \tcode{begin(E)} and for \tcode{end(E)} +each find at least one function or function template. +\end{itemize} + +\pnum +An expansion statement is +\begin{itemize} +\item +an \defnadj{enumerating}{expansion statement} if its \grammarterm{expansion-initializer} +is of the form \grammarterm{expansion-init-list}; +\item +otherwise, an \defnadj{iterating}{expansion statement} if its \grammarterm{expansion-initializer} +is an expansion-iterable expression; +\item +otherwise, a \defnadj{destructuring}{expansion statement}. +\end{itemize} + +\pnum +An expansion statement $S$ is equivalent to a \grammarterm{compound-statement} +containing instantiations of the \grammarterm{for-range-declaration} +(including its implied initialization), +together with the compound-statement of $S$, as follows: +\begin{itemize} +\item +If $S$ is an enumerating expansion statement, $S$ is equivalent to: +\begin{codeblock} +{ + @\grammarterm{init-statement}@ + @$S_{0}$@ + @\vdots@ + @$S_{N-1}$@ +} +\end{codeblock} +where $N$ is the number of elements in the \grammarterm{expression-list}, +$S_{i}$ is +\begin{codeblock} +{ + @\grammarterm{for-range-declaration}@ = @$E_{i}$@; + @\grammarterm{compound-statement}@ +} +\end{codeblock} +and $E_{i}$ is the $i^{\text{th}}$ element of the \grammarterm{expression-list}. + +\item +Otherwise, if $S$ is an iterating expansion statement, $S$ is equivalent to: +\begin{codeblock} +{ + @\grammarterm{init-statement}@ + static constexpr auto&& @\exposidnc{range}@ = @\grammarterm{expansion-initializer}@; + static constexpr auto @\exposidnc{begin}@ = @\exposidnc{begin-expr}@; // see \ref{stmt.ranged} + static constexpr auto @\exposidnc{end}@ = @\exposidnc{end-expr}@; // see \ref{stmt.ranged} + + @$S_{0}$@ + @\vdots@ + @$S_{N-1}$@ +} +\end{codeblock} +where $N$ is the result of evaluating the expression +\begin{codeblock} +[] consteval { + std::ptrdiff_t result = 0; + for (auto i = @\exposid{begin}@; i != @\exposid{end}@; ++i, ++result); + return result; // distance from \exposid{begin} to \exposid{end} +}() +\end{codeblock} +and $S_{i}$ is +\begin{codeblock} +{ + static constexpr auto @\exposid{iter}@ = @\exposid{begin}@ + i; + @\grammarterm{for-range-declaration}@ = *@\exposid{iter}@; + @\grammarterm{compound-statement}@ +} +\end{codeblock} +The variables \exposid{range}, \exposid{begin}, \exposid{end}, and \exposid{iter} +are defined for exposition only. +\begin{note} +The instantiation is ill-formed if \exposid{range} +is not a constant expression\iref{expr.const}. +\end{note} + +\item +Otherwise, $S$ is a destructuring expansion statement and $S$ is equivalent to: +\begin{codeblock} +{ + @\grammarterm{init-statement}@ + @\opt{\keyword{constexpr}}@ auto&& [@$u_{0}$@, @$u_{1}$@, @$\dotsc$@, @$u_{N-1}$@] = @\grammarterm{expansion-initializer}@; + @$S_{0}$@ + @\vdots@ + @$S_{N-1}$@ +} +\end{codeblock} +where $N$ is the structured binding size of the type +of the \grammarterm{expansion-initializer} and $S_{i}$ is +\begin{codeblock} +{ + @\grammarterm{for-range-declaration}@ = @$u_{i}$@; + @\grammarterm{compound-statement}@ +} +\end{codeblock} +The keyword \keyword{constexpr} is present in the declaration +of $u_{0}, u_{1}, \dotsc, u_{N-1}$ if and only if +\keyword{constexpr} is one of the \grammarterm{decl-specifier}s +of the \grammarterm{decl-specifier-seq} +of the \grammarterm{for-range-declaration}. +\end{itemize} + +\pnum +\begin{example} +\begin{codeblock} +consteval int f(auto const&... Containers) { + int result = 0; + template for (auto const& c : {Containers...}) { // OK, enumerating expansion statement + result += c[0]; + } + return result; +} +constexpr int c1[] = {1, 2, 3}; +constexpr int c2[] = {4, 3, 2, 1}; +static_assert(f(c1, c2) == 5); +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblock} +consteval int f() { + constexpr std::array arr {1, 2, 3}; + int result = 0; + template for (constexpr int s : arr) { // OK, iterating expansion statement + result += sizeof(char[s]); + } + return result; +} +static_assert(f() == 6); +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblock} +struct S { + int i; + short s; +}; + +consteval long f(S s) { + long result = 0; + template for (auto x : s) { // OK, destructuring expansion statement + result += sizeof(x); + } + return result; +} +static_assert(f(S{}) == sizeof(int) + sizeof(short)); +\end{codeblock} +\end{example} + +\indextext{statement!expansion|)} + \rSec1[stmt.jump]{Jump statements}% \rSec2[stmt.jump.general]{General}% @@ -787,10 +1033,11 @@ A \keyword{break} statement shall be enclosed by\iref{stmt.pre} \indextext{\idxgram{iteration-statement}}% \indextext{statement!\idxcode{switch}}% -an \grammarterm{iteration-statement}\iref{stmt.iter} or +an \grammarterm{iteration-statement}\iref{stmt.iter}, +an \grammarterm{expansion-statement}\iref{stmt.expand}, or a \keyword{switch} statement\iref{stmt.switch}. The \keyword{break} statement causes -termination of the smallest such enclosing statement; +termination of the innermost such enclosing statement; control passes to the statement following the terminated statement, if any. @@ -799,47 +1046,16 @@ \pnum A \keyword{continue} -statement shall be enclosed by\iref{stmt.pre} an +statement shall be enclosed by\iref{stmt.pre} \indextext{\idxgram{iteration-statement}}% -\grammarterm{iteration-statement}\iref{stmt.iter}. -The \keyword{continue} statement -causes control to pass to the loop-continuation portion of the -smallest such enclosing statement, that is, to the end -of the loop. More precisely, in each of the statements - -\begin{minipage}{.30\hsize} -\begin{codeblock} -while (foo) { - { - // ... - } -@\exposid{contin}@: ; -} -\end{codeblock} -\end{minipage} -\begin{minipage}{.30\hsize} -\begin{codeblock} -do { - { - // ... - } -@\exposid{contin}@: ; -} while (foo); -\end{codeblock} -\end{minipage} -\begin{minipage}{.30\hsize} -\begin{codeblock} -for (;;) { - { - // ... - } -@\exposid{contin}@: ; -} -\end{codeblock} -\end{minipage} - -a \keyword{continue} not contained in an enclosed iteration statement is -equivalent to \tcode{goto} \exposid{contin}. +an \grammarterm{iteration-statement} or an \grammarterm{expansion-statement}. +If the innermost enclosing such statement $X$ +is an \grammarterm{iteration-statement}\iref{stmt.iter}, +the \keyword{continue} statement +causes control to pass to the end of the \grammarterm{statement} +or \grammarterm{compound-statement} of $X$. +Otherwise, control passes to the end of the \grammarterm{compound-statement} +of the current $S_{i}$\iref{stmt.expand}. \rSec2[stmt.return]{The \keyword{return} statement}% \indextext{\idxcode{return}}% @@ -904,6 +1120,39 @@ by the operand of the \tcode{return} statement, which, in turn, is sequenced before the destruction of local variables\iref{stmt.jump} of the block enclosing the \tcode{return} statement. +\begin{note} +These operations +are sequenced before the destruction of local variables +in each remaining enclosing block of the function\iref{stmt.dcl}, +which, in turn, +is sequenced before the evaluation of +postcondition assertions of the function\iref{dcl.contract.func}, +which, in turn, +is sequenced before the destruction of function parameters\iref{expr.call}. +\end{note} + +\pnum +In a function whose return type is a reference, +other than an invented function for \tcode{std::is_convertible}\iref{meta.rel}, +a \tcode{return} statement that binds the returned reference to +a temporary expression\iref{class.temporary} is ill-formed. +\begin{example} +\begin{codeblock} +auto&& f1() { + return 42; // ill-formed +} +const double& f2() { + static int x = 42; + return x; // ill-formed +} +auto&& id(auto&& r) { + return static_cast(r); +} +auto&& f3() { + return id(42); // OK, but probably a bug +} +\end{codeblock} +\end{example} \rSec2[stmt.return.coroutine]{The \keyword{co_return} statement}% \indextext{\idxcode{co_return}}% @@ -911,7 +1160,7 @@ \begin{bnf} \nontermdef{coroutine-return-statement}\br - \terminal{co_return} \opt{expr-or-braced-init-list} \terminal{;} + \keyword{co_return} \opt{expr-or-braced-init-list} \terminal{;} \end{bnf} \pnum @@ -931,7 +1180,7 @@ promise object\iref{dcl.fct.def.coroutine}. A \keyword{co_return} statement is equivalent to: \begin{ncsimplebnf} -\terminal{\{} S\terminal{;} \terminal{goto} \exposid{final-suspend}\terminal{;} \terminal{\}} +\terminal{\{} S\terminal{;} \keyword{goto} \exposid{final-suspend}\terminal{;} \terminal{\}} \end{ncsimplebnf} where \exposid{final-suspend} is the exposition-only label defined in \ref{dcl.fct.def.coroutine} @@ -966,6 +1215,48 @@ \indextext{label}% label\iref{stmt.label} located in the current function. +\rSec1[stmt.contract.assert]{Assertion statement} + +\begin{bnf} +\nontermdef{assertion-statement}\br + \terminal{contract_assert} \opt{attribute-specifier-seq} \terminal{(} conditional-expression \terminal{)} \terminal{;} +\end{bnf} + +\pnum +\indexdefn{contract assertion!statement|see{assertion, statement}} +\indextext{assertion!statement} +An \grammarterm{assertion-statement} +introduces a contract assertion\iref{basic.contract}. +The optional \grammarterm{attribute-specifier-seq} +appertains to the introduced contract assertion. + +\pnum +The predicate\iref{basic.contract.general} +of an \grammarterm{assertion-statement} +is its \grammarterm{conditional-expression} +contextually converted to \tcode{bool}. + +\pnum +The evaluation of consecutive \grammarterm{assertion-statement}s +is an evaluation in sequence\iref{basic.contract.eval} of +the contract assertions introduced +by those \grammarterm{assertion-statement}s. +\begin{note} +A sequence of \grammarterm{assertion-statement}s +can thus be repeatedly evaluated as a group. +\begin{example} +\begin{codeblock} +int f(int i) +{ + contract_assert(i == 0); // \#1 + contract_assert(i >= 0); // \#2 + return 0; +} +int g = f(0); // can evaluate \#1, \#2, \#1, \#2 +\end{codeblock} +\end{example} +\end{note} + \rSec1[stmt.dcl]{Declaration statement}% \indextext{statement!declaration} @@ -991,16 +1282,16 @@ \indextext{block (statement)!initialization in}% \indextext{initialization!automatic}% \indextext{active|see{variable, active}}% -A variable with automatic storage duration\iref{basic.stc.auto} +A block variable with automatic storage duration\iref{basic.stc.auto} is \defnx{active}{variable!active} everywhere in the scope to which it belongs after its \grammarterm{init-declarator}. \indextext{initialization!jump past}% \indextext{\idxcode{goto}!initialization and}% Upon each transfer of control (including sequential execution of statements) within a function from point $P$ to point $Q$, -all variables with automatic storage duration +all block variables with automatic storage duration that are active at $P$ and not at $Q$ are destroyed in the reverse order of their construction. -Then, all variables with automatic storage duration +Then, all block variables with automatic storage duration that are active at $Q$ but not at $P$ are initialized in declaration order; unless all such variables have vacuous initialization\iref{basic.life}, the transfer of control shall not be a jump. @@ -1094,7 +1385,7 @@ of many examples. \begin{example} Assuming \tcode{T} is a -\grammarterm{simple-type-specifier}\iref{dcl.type}, +\grammarterm{simple-type-specifier}\iref{dcl.type.simple}, \begin{codeblock} T(a)->m = 7; // expression-statement diff --git a/source/std.tex b/source/std.tex index c97d4302bd..0170e31451 100644 --- a/source/std.tex +++ b/source/std.tex @@ -24,6 +24,7 @@ \usepackage{color} % define colors for strikeouts and underlines \usepackage{amsmath} % additional math symbols \usepackage{mathrsfs} % mathscr font +\usepackage{bm} \usepackage[final]{microtype} \usepackage[splitindex,original]{imakeidx} \usepackage{multicol} @@ -41,9 +42,11 @@ linktocpage=true, colorlinks=true, linkcolor=blue, + citecolor=blue, + urlcolor=blue, % ISO/IEC Directives, Part 2, section 6.5 plainpages=false} \usepackage{memhfixc} % fix interactions between hyperref and memoir -\usepackage[active,header=false,handles=false,copydocumentclass=false,generate=std-gram.ext,extract-cmdline={gramSec},extract-env={bnf,simplebnf}]{extract} % Grammar extraction +\usepackage{environ} \usepackage{expl3} \usepackage{xparse} \usepackage{xstring} @@ -54,6 +57,10 @@ \renewcommand\RSsmallest{5.5pt} % smallest font size for relsize +% Begin grammar extraction... +\newwrite\gramout +\immediate\openout\gramout=std-gram.ext + \input{layout} \input{styles} \input{macros} @@ -85,6 +92,10 @@ %% turn off all ligatures inside \texttt \DisableLigatures{encoding = T1, family = tt*} +%%-------------------------------------------------- +%% select regular text font for \url +\urlstyle{same} + \begin{document} \chapterstyle{cppstd} \pagestyle{cpppage} @@ -122,21 +133,22 @@ \include{memory} \include{meta} \include{utilities} -\include{strings} \include{containers} \include{iterators} \include{ranges} \include{algorithms} +\include{strings} +\include{text} \include{numerics} \include{time} -\include{locales} \include{iostreams} -\include{regex} \include{threads} +\include{exec} %%-------------------------------------------------- %% appendices \appendix +\chapterstyle{cppannex} % \include and \addtocontents don't mix; see % https://tex.stackexchange.com/questions/13914/toc-numbering-problem @@ -146,6 +158,9 @@ \numberwithin{table}{chapter} +% ... end grammar extraction. +\immediate\closeout\gramout + \include{grammar} \include{limits} \include{compatibility} diff --git a/source/strings.tex b/source/strings.tex index 91b17d4d3b..5a93b51d1a 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -5,7 +5,8 @@ \pnum This Clause describes components for manipulating sequences of -any non-array trivial standard-layout\iref{term.standard.layout.type} type. +any non-array trivially copyable standard-layout\iref{term.standard.layout.type} type \tcode{T} +where \tcode{is_trivially_default_constructible_v} is \tcode{true}. Such types are called \defnx{char-like types}{char-like type}, and objects of char-like types are called \defnx{char-like objects}{char-like object} or @@ -21,9 +22,7 @@ \ref{char.traits} & Character traits & \tcode{} \\ \ref{string.view} & String view classes & \tcode{} \\ \rowsep \ref{string.classes} & String classes & \tcode{} \\ \rowsep -\ref{c.strings} & Null-terminated sequence utilities & - \tcode{}, \tcode{}, \tcode{}, - \tcode{}, \tcode{}, \tcode{} \\ +\ref{c.strings} & Null-terminated sequence utilities & \tcode{} \\ \end{libsumtab} \rSec1[char.traits]{Character traits} @@ -108,7 +107,7 @@ denotes an lvalue of type \tcode{C}. No expression which is part of the character traits requirements -specified in this subclause \ref{char.traits.require} +specified in \ref{char.traits.require} shall exit via an exception. \begin{libreqtab4d} @@ -124,15 +123,15 @@ & & \chdr{pre-/post-condition} & \\ \capsep \endhead \tcode{X::char_type} & \tcode{C} & - & compile-time \\ \rowsep + & \\ \rowsep \tcode{X::int_type} & & -(described in~\ref{char.traits.typedefs}) & compile-time \\ \rowsep +(described in~\ref{char.traits.typedefs}) & \\ \rowsep \tcode{X::off_type} & & -(described in~\ref{iostreams.limits.pos} and \ref{iostream.forward}) & compile-time \\ \rowsep +(described in~\ref{iostreams.limits.pos} and \ref{iostream.forward}) & \\ \rowsep \tcode{X::pos_type} & & -(described in~\ref{iostreams.limits.pos} and \ref{iostream.forward}) & compile-time \\ \rowsep +(described in~\ref{iostreams.limits.pos} and \ref{iostream.forward}) & \\ \rowsep \tcode{X::state_type} & & -(described in~\ref{char.traits.typedefs}) & compile-time \\ \rowsep +(described in~\ref{char.traits.typedefs}) & \\ \rowsep \tcode{X::eq(c,d)} & \tcode{bool} & \returns whether \tcode{c} is to be treated as equal to \tcode{d}. & constant \\ \rowsep @@ -141,31 +140,31 @@ whether \tcode{c} is to be treated as less than \tcode{d}. & constant \\ \rowsep \tcode{X::compare(p,q,n)} & \tcode{int} & \returns -\tcode{0} if for each \tcode{i} in \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{0} if for each \tcode{i} in \range{0}{n}, \tcode{X::eq(p[i],q[i])} +is \tcode{true}; else, a negative value if, for some \tcode{j} in \range{0}{n}, +\tcode{X::lt(p[j],q[j])} is \tcode{true} and for each \tcode{i} in \range{0}{j} \tcode{X::eq(p[i],q[i])} is \tcode{true}; else a positive value. & linear \\ \rowsep \tcode{X::length(p)} & \tcode{size_t} & \returns the smallest \tcode{i} such that \tcode{X::eq(p[i],charT())} is \tcode{true}. & linear \\ \rowsep \tcode{X::find(p,n,c)} & \tcode{const X::char_type*} & \returns -the smallest \tcode{q} in \tcode{[p,p+n)} such that +the smallest \tcode{q} in \range{p}{p+n} such that \tcode{X::eq(*q,c)} is \tcode{true}, \tcode{nullptr} otherwise. & linear \\ \rowsep \tcode{X::move(s,p,n)} & \tcode{X::char_type*} & -for each \tcode{i} in \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 +for each \tcode{i} in \range{0}{n}, performs \tcode{X::assign(s[i],p[i])}. +Copies correctly even where the ranges \range{p}{p+n} and \range{s}{s+n} overlap.\br \returns \tcode{s}. & linear \\ \rowsep \tcode{X::copy(s,p,n)} & \tcode{X::char_type*} & \expects The ranges \range{p}{p+n} and \range{s}{s+n} do not overlap.\par \returns \tcode{s}.\br for each \tcode{i} in -\tcode{[0,n)}, performs \tcode{X::assign(s[i],p[i])}. & linear \\ \rowsep +\range{0}{n}, performs \tcode{X::assign(s[i],p[i])}. & linear \\ \rowsep \tcode{X::assign(r,d)} & (not used) & assigns \tcode{r=d}. & constant \\ \rowsep \tcode{X::assign\-(s,n,c)} & \tcode{X::char_type*} & -for each \tcode{i} in \tcode{[0,n)}, performs +for each \tcode{i} in \range{0}{n}, performs \tcode{X::assign(s[i],c)}.\br \returns \tcode{s}. & linear \\ \rowsep @@ -201,7 +200,7 @@ \begin{codeblock} template struct char_traits; \end{codeblock} -is provided in the header \libheader{string} +is provided in the header \libheaderref{string} as a basis for explicit specializations. \rSec2[char.traits.typedefs]{Traits typedefs} @@ -307,7 +306,7 @@ \end{codeblock} \pnum -The type \tcode{mbstate_t} is defined in \libheader{cwchar} +The type \tcode{mbstate_t} is defined in \libheaderref{cwchar} and can represent any of the conversion states that can occur in an \impldef{supported multibyte character encoding rules} set of supported multibyte character encoding rules. @@ -549,12 +548,11 @@ // \ref{string.view.comparison}, non-member comparison functions template constexpr bool operator==(basic_string_view x, - basic_string_view y) noexcept; + type_identity_t> 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 + @\itcorr@ type_identity_t> y) noexcept; // \ref{string.view.io}, inserters and extractors template @@ -660,7 +658,7 @@ 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; + constexpr bool empty() const noexcept; // \ref{string.view.access}, element access constexpr const_reference operator[](size_type pos) const; @@ -680,6 +678,8 @@ constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; // freestanding-deleted + constexpr basic_string_view subview(size_type pos = 0, + size_type n = npos) const; // freestanding-deleted constexpr int compare(basic_string_view s) const noexcept; constexpr int compare(size_type pos1, size_type n1, @@ -734,8 +734,8 @@ constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const; private: - const_pointer data_; // \expos - size_type size_; // \expos + const_pointer @\exposid{data_}@; // \expos + size_type @\exposid{size_}@; // \expos }; // \ref{string.view.deduct}, deduction guides @@ -780,7 +780,7 @@ \begin{itemdescr} \pnum \ensures -\tcode{size_ == 0} and \tcode{data_ == nullptr}. +\tcode{\exposid{size_} == 0} and \tcode{\exposid{data_} == nullptr}. \end{itemdescr} \indexlibraryctor{basic_string_view}% @@ -795,8 +795,8 @@ \pnum \effects -Constructs a \tcode{basic_string_view}, initializing \tcode{data_} with \tcode{str} -and initializing \tcode{size_} with \tcode{traits::length(str)}. +Constructs a \tcode{basic_string_view}, initializing \exposid{data_} with \tcode{str} +and initializing \exposid{size_} with \tcode{traits::length(str)}. \pnum \complexity @@ -815,8 +815,8 @@ \pnum \effects -Constructs a \tcode{basic_string_view}, initializing \tcode{data_} with \tcode{str} -and initializing \tcode{size_} with \tcode{len}. +Constructs a \tcode{basic_string_view}, initializing \exposid{data_} with \tcode{str} +and initializing \exposid{size_} with \tcode{len}. \end{itemdescr} \indexlibraryctor{basic_string_view}% @@ -845,8 +845,8 @@ \pnum \effects -Initializes \tcode{data_} with \tcode{to_address(begin)} and -initializes \tcode{size_} with \tcode{end - begin}. +Initializes \exposid{data_} with \tcode{to_address(begin)} and +initializes \exposid{size_} with \tcode{end - begin}. \pnum \throws @@ -882,8 +882,8 @@ \pnum \effects -Initializes \tcode{data_} with \tcode{ranges::data(r)} and -\tcode{size_} with \tcode{ranges::size(r)}. +Initializes \exposid{data_} with \tcode{ranges::data(r)} and +\exposid{size_} with \tcode{ranges::size(r)}. \pnum \throws @@ -949,7 +949,7 @@ \returns An iterator such that \begin{itemize} -\item if \tcode{!empty()}, \tcode{addressof(*begin()) == data_}, +\item if \tcode{!empty()}, \tcode{addressof(*begin()) == \exposid{data_}}, \item otherwise, an unspecified value such that \range{begin()}{end()} is a valid range. \end{itemize} \end{itemdescr} @@ -1005,7 +1005,7 @@ \begin{itemdescr} \pnum \returns -\tcode{size_}. +\exposid{size_}. \end{itemdescr} @@ -1022,13 +1022,13 @@ \indexlibrarymember{empty}{basic_string_view}% \begin{itemdecl} -[[nodiscard]] constexpr bool empty() const noexcept; +constexpr bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{size_ == 0}. +\tcode{\exposid{size_} == 0}. \end{itemdescr} \rSec3[string.view.access]{Element access} @@ -1040,22 +1040,19 @@ \begin{itemdescr} \pnum -\expects -\tcode{pos < size()}. +\hardexpects +\tcode{pos < size()} is \tcode{true}. +\begin{note} +This precondition is stronger than the one on \tcode{basic_string::operator[]}. +\end{note} \pnum \returns -\tcode{data_[pos]}. +\tcode{\exposid{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{at}{basic_string_view}% @@ -1066,7 +1063,7 @@ \begin{itemdescr} \pnum \returns -\tcode{data_[pos]}. +\tcode{\exposid{data_}[pos]}. \pnum \throws @@ -1080,12 +1077,12 @@ \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum \returns -\tcode{data_[0]}. +\tcode{\exposid{data_}[0]}. \pnum \throws @@ -1099,12 +1096,12 @@ \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum \returns -\tcode{data_[size() - 1]}. +\tcode{\exposid{data_}[size() - 1]}. \pnum \throws @@ -1119,7 +1116,7 @@ \begin{itemdescr} \pnum \returns -\tcode{data_}. +\exposid{data_}. \pnum \begin{note} @@ -1138,12 +1135,12 @@ \begin{itemdescr} \pnum -\expects -\tcode{n <= size()}. +\hardexpects +\tcode{n <= size()} is \tcode{true}. \pnum \effects -Equivalent to: \tcode{data_ += n; size_ -= n;} +Equivalent to: \tcode{\exposid{data_} += n; \exposid{size_} -= n;} \end{itemdescr} \indexlibrarymember{remove_suffix}{basic_string_view}% @@ -1153,12 +1150,12 @@ \begin{itemdescr} \pnum -\expects -\tcode{n <= size()}. +\hardexpects +\tcode{n <= size()} is \tcode{true}. \pnum \effects -Equivalent to: \tcode{size_ -= n;} +Equivalent to: \tcode{\exposid{size_} -= n;} \end{itemdescr} \indexlibrarymember{swap}{basic_string_view}% @@ -1205,8 +1202,10 @@ \end{itemdescr} \indexlibrarymember{substr}{basic_string_view}% +\indexlibrarymember{subview}{basic_string_view}% \begin{itemdecl} constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; +constexpr basic_string_view subview(size_type pos = 0, size_type n = npos) const; \end{itemdecl} \begin{itemdescr} @@ -1451,7 +1450,7 @@ \item \tcode{xpos + str.size() <= size()} \item -\tcode{traits::eq(data_[xpos + I], str[I])} for all elements \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(\exposid{data_}[xpos + I], str[I])} for all elements \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1478,7 +1477,7 @@ \item \tcode{xpos + str.size() <= size()} \item -\tcode{traits::eq(data_[xpos + I], str[I])} for all elements \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(\exposid{data_}[xpos + I], str[I])} for all elements \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1505,7 +1504,7 @@ \item \tcode{xpos < size()} \item -\tcode{traits::eq(data_[xpos], str[I])} for some element \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(\exposid{data_}[xpos], str[I])} for some element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1532,7 +1531,7 @@ \item \tcode{xpos < size()} \item -\tcode{traits::eq(data_[xpos], str[I])} for some element \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(\exposid{data_}[xpos], str[I])} for some element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1559,7 +1558,7 @@ \item \tcode{xpos < size()} \item -\tcode{traits::eq(data_[xpos], str[I])} for no element \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(\exposid{data_}[xpos], str[I])} for no element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1585,7 +1584,7 @@ \item \tcode{xpos < size()} \item -\tcode{traits::eq(data_[xpos], str[I])} for no element \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(\exposid{data_}[xpos], str[I])} for no element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1600,47 +1599,11 @@ \rSec2[string.view.comparison]{Non-member comparison functions} -\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; + type_identity_t> rhs) noexcept; \end{itemdecl} \begin{itemdescr} @@ -1653,7 +1616,7 @@ \begin{itemdecl} template constexpr @\seebelow@ operator<=>(basic_string_view lhs, - @\itcorr@ basic_string_view rhs) noexcept; + @\itcorr@ type_identity_t> rhs) noexcept; \end{itemdecl} \begin{itemdescr} @@ -1669,6 +1632,15 @@ \pnum \returns \tcode{static_cast(lhs.compare(rhs) <=> 0)}. + +\pnum +\begin{note} +The usage of \tcode{type_identity_t} as parameter +ensures that an object of type \tcode{basic_string_view} +can always be compared with an object of a type \tcode{T} with +an implicit conversion to \tcode{basic_string_view}, and +vice versa, as per \ref{over.match.oper}. +\end{note} \end{itemdescr} \rSec2[string.view.io]{Inserters and extractors} @@ -1695,7 +1667,7 @@ \pnum \returns -\tcode{os} +\tcode{os}. \end{itemdescr} \rSec2[string.view.hash]{Hash support} @@ -1864,6 +1836,22 @@ constexpr basic_string operator+(basic_string&& lhs, charT rhs); + template + constexpr basic_string + operator+(const basic_string& lhs, + type_identity_t> rhs); + template + constexpr basic_string + operator+(basic_string&& lhs, + type_identity_t> rhs); + template + constexpr basic_string + operator+(type_identity_t> lhs, + const basic_string& rhs); + template + constexpr basic_string + operator+(type_identity_t> lhs, + basic_string&& rhs); template constexpr bool @@ -1916,7 +1904,7 @@ basic_string& str); // \ref{string.erasure}, erasure - template + template constexpr typename basic_string::size_type erase(basic_string& c, const U& value); template @@ -2135,7 +2123,7 @@ constexpr void reserve(size_type res_arg); constexpr void shrink_to_fit(); constexpr void clear() noexcept; - [[nodiscard]] constexpr bool empty() const noexcept; + constexpr bool empty() const noexcept; // \ref{string.access}, element access constexpr const_reference operator[](size_type pos) const; @@ -2301,6 +2289,8 @@ constexpr basic_string substr(size_type pos = 0, size_type n = npos) const &; constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&; + constexpr basic_string_view subview(size_type pos = 0, + size_type n = npos) const; template constexpr int compare(const T& t) const noexcept(@\seebelow@); @@ -3086,7 +3076,7 @@ \indexlibrarymember{empty}{basic_string}% \begin{itemdecl} -[[nodiscard]] constexpr bool empty() const noexcept; +constexpr bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3106,8 +3096,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{pos <= size()}. +\hardexpects +\tcode{pos <= size()} is \tcode{true}. \pnum \returns @@ -3151,8 +3141,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum \effects @@ -3167,8 +3157,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum \effects @@ -3750,7 +3740,7 @@ \pnum \returns -\tcode{*this} +\tcode{*this}. \pnum \throws @@ -3930,7 +3920,7 @@ \pnum \effects Removes the characters in the range -\tcode{[first, last)}. +\range{first}{last}. \pnum \returns @@ -3952,8 +3942,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{!empty()}. +\hardexpects +\tcode{empty()} is \tcode{false}. \pnum \effects @@ -4115,7 +4105,7 @@ \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 +would exceed \tcode{max_size()}, or \item any exceptions thrown by \tcode{allocator_traits::allocate.} \end{itemize} \end{itemdescr} @@ -4486,6 +4476,17 @@ Equivalent to: \tcode{return basic_string(std::move(*this), pos, n);} \end{itemdescr} +\indexlibrarymember{subview}{basic_string}% +\begin{itemdecl} +constexpr basic_string_view subview(size_type pos = 0, size_type n = npos) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return basic_string_view(*this).subview(pos, n);} +\end{itemdescr} + \rSec4[string.compare]{\tcode{basic_string::compare}} \indexlibrarymember{compare}{basic_string}% @@ -4879,6 +4880,85 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator+}{basic_string}% +\begin{itemdecl} +template + constexpr basic_string + operator+(const basic_string& lhs, + type_identity_t> rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Equivalent to: +\begin{codeblock} +basic_string r = lhs; +r.append(rhs); +return r; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+}{basic_string}% +\begin{itemdecl} +template + constexpr basic_string + operator+(basic_string&& lhs, + type_identity_t> rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Equivalent to: +\begin{codeblock} +lhs.append(rhs); +return std::move(lhs); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+}{basic_string}% +\begin{itemdecl} +template + constexpr basic_string + operator+(type_identity_t> lhs, + const basic_string& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Equivalent to: +\begin{codeblock} +basic_string r = rhs; +r.insert(0, lhs); +return r; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+}{basic_string}% +\begin{itemdecl} +template + constexpr basic_string + operator+(type_identity_t> lhs, + basic_string&& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Equivalent to: +\begin{codeblock} +rhs.insert(0, lhs); +return std::move(rhs); +\end{codeblock} +\end{itemdescr} + +\pnum +\begin{note} +Using a specialization of \tcode{type_identity_t} as a parameter type ensures +that an object of type \tcode{basic_string} +can be concatenated with an object of a type \tcode{T} +having an implicit conversion to +\tcode{basic_string_view}\iref{over.match.oper}. +\end{note} + \rSec3[string.cmp]{Non-member comparison operator functions} \begin{itemdecl} template @@ -5079,7 +5159,7 @@ \indexlibrarymember{erase}{basic_string}% \begin{itemdecl} -template +template constexpr typename basic_string::size_type erase(basic_string& c, const U& value); \end{itemdecl} @@ -5376,106 +5456,6 @@ \rSec1[c.strings]{Null-terminated sequence utilities} -\rSec2[cctype.syn]{Header \tcode{} synopsis} - -\indexlibraryglobal{isalnum}% -\indexlibraryglobal{isalpha}% -\indexlibraryglobal{isblank}% -\indexlibraryglobal{iscntrl}% -\indexlibraryglobal{isdigit}% -\indexlibraryglobal{isgraph}% -\indexlibraryglobal{islower}% -\indexlibraryglobal{isprint}% -\indexlibraryglobal{ispunct}% -\indexlibraryglobal{isspace}% -\indexlibraryglobal{isupper}% -\indexlibraryglobal{isxdigit}% -\indexlibraryglobal{tolower}% -\indexlibraryglobal{toupper}% -\begin{codeblock} -namespace std { - int isalnum(int c); - int isalpha(int c); - int isblank(int c); - int iscntrl(int c); - int isdigit(int c); - int isgraph(int c); - int islower(int c); - int isprint(int c); - int ispunct(int c); - int isspace(int c); - int isupper(int c); - int isxdigit(int c); - int tolower(int c); - int toupper(int c); -} -\end{codeblock} - -\pnum -The contents and meaning of the header \libheaderdef{cctype} -are the same as the C standard library header \libheader{ctype.h}. - -\xrefc{7.4} - -\rSec2[cwctype.syn]{Header \tcode{} synopsis} - -\indexlibraryglobal{wint_t}% -\indexlibraryglobal{wctrans_t}% -\indexlibraryglobal{wctype_t}% -\indexlibraryglobal{iswalnum}% -\indexlibraryglobal{iswalpha}% -\indexlibraryglobal{iswblank}% -\indexlibraryglobal{iswcntrl}% -\indexlibraryglobal{iswdigit}% -\indexlibraryglobal{iswgraph}% -\indexlibraryglobal{iswlower}% -\indexlibraryglobal{iswprint}% -\indexlibraryglobal{iswpunct}% -\indexlibraryglobal{iswspace}% -\indexlibraryglobal{iswupper}% -\indexlibraryglobal{iswxdigit}% -\indexlibraryglobal{iswctype}% -\indexlibraryglobal{wctype}% -\indexlibraryglobal{towlower}% -\indexlibraryglobal{towupper}% -\indexlibraryglobal{towctrans}% -\indexlibraryglobal{wctrans}% -\indexlibraryglobal{WEOF}% -\begin{codeblock} -namespace std { - using wint_t = @\seebelow@; - using wctrans_t = @\seebelow@; - using wctype_t = @\seebelow@; - - int iswalnum(wint_t wc); - int iswalpha(wint_t wc); - int iswblank(wint_t wc); - int iswcntrl(wint_t wc); - int iswdigit(wint_t wc); - int iswgraph(wint_t wc); - int iswlower(wint_t wc); - int iswprint(wint_t wc); - int iswpunct(wint_t wc); - int iswspace(wint_t wc); - int iswupper(wint_t wc); - int iswxdigit(wint_t wc); - int iswctype(wint_t wc, wctype_t desc); - wctype_t wctype(const char* property); - wint_t towlower(wint_t wc); - wint_t towupper(wint_t wc); - wint_t towctrans(wint_t wc, wctrans_t desc); - wctrans_t wctrans(const char* property); -} - -#define WEOF @\seebelow@ -\end{codeblock} - -\pnum -The contents and meaning of the header \libheaderdef{cwctype} -are the same as the C standard library header \libheader{wctype.h}. - -\xrefc{7.30} - \rSec2[cstring.syn]{Header \tcode{} synopsis} \indexlibraryglobal{memchr}% @@ -5502,13 +5482,18 @@ \indexlibraryglobal{strtok}% \indexlibraryglobal{strxfrm}% \begin{codeblock} +#define __STDC_VERSION_STRING_H__ 202311L + namespace std { using size_t = @\textit{see \ref{support.types.layout}}@; // freestanding void* memcpy(void* s1, const void* s2, size_t n); // freestanding + void* memccpy(void* s1, const void* s2, int c, size_t n); // freestanding void* memmove(void* s1, const void* s2, size_t n); // freestanding char* strcpy(char* s1, const char* s2); // freestanding char* strncpy(char* s1, const char* s2, size_t n); // freestanding + char* strdup(const char* s); + char* strndup(const char* s, size_t size); char* strcat(char* s1, const char* s2); // freestanding char* strncat(char* s1, const char* s2, size_t n); // freestanding int memcmp(const void* s1, const void* s2, size_t n); // freestanding @@ -5530,6 +5515,7 @@ char* strstr(char* s1, const char* s2); // freestanding; see \ref{library.c} char* strtok(char* s1, const char* s2); void* memset(void* s, int c, size_t n); // freestanding + void* memset_explicit(void* s, int c, size_t n); // freestanding char* strerror(int errnum); size_t strlen(const char* s); // freestanding } @@ -5549,9 +5535,11 @@ \indextext{signal-safe!\idxcode{memcpy}}% \indextext{signal-safe!\idxcode{memmove}}% The functions \tcode{memcpy} and \tcode{memmove} are signal-safe\iref{support.signal}. -Both functions implicitly create objects\iref{intro.object} +Each of these functions implicitly creates objects\iref{intro.object} in the destination region of storage immediately prior to copying the sequence of characters to the destination. +Each of these functions returns a pointer to a suitable created object, if any, +otherwise the value of the first parameter. \pnum \begin{note} @@ -5561,374 +5549,4 @@ but they have the same behavior as in the C standard library\iref{library.c}. \end{note} -\xrefc{7.24} - -\rSec2[cwchar.syn]{Header \tcode{} synopsis} - -\indexheader{cwchar}% -\indexlibraryglobal{NULL}% -\indexlibraryglobal{WCHAR_MAX}% -\indexlibraryglobal{WCHAR_MIN}% -\indexlibraryglobal{WEOF}% -\indexlibraryglobal{btowc}% -\indexlibraryglobal{fgetwc}% -\indexlibraryglobal{fgetws}% -\indexlibraryglobal{fputwc}% -\indexlibraryglobal{fputws}% -\indexlibraryglobal{fwide}% -\indexlibraryglobal{fwprintf}% -\indexlibraryglobal{fwscanf}% -\indexlibraryglobal{getwchar}% -\indexlibraryglobal{getwc}% -\indexlibraryglobal{mbrlen}% -\indexlibraryglobal{mbrtowc}% -\indexlibraryglobal{mbsinit}% -\indexlibraryglobal{mbsrtowcs}% -\indexlibraryglobal{mbstate_t}% -\indexlibraryglobal{putwchar}% -\indexlibraryglobal{putwc}% -\indexlibraryglobal{size_t}% -\indexlibraryglobal{swprintf}% -\indexlibraryglobal{swscanf}% -\indexlibraryglobal{tm}% -\indexlibraryglobal{ungetwc}% -\indexlibraryglobal{vfwprintf}% -\indexlibraryglobal{vfwscanf}% -\indexlibraryglobal{vswprintf}% -\indexlibraryglobal{vswscanf}% -\indexlibraryglobal{vwprintf}% -\indexlibraryglobal{vwscanf}% -\indexlibraryglobal{wcrtomb}% -\indexlibraryglobal{wcscat}% -\indexlibraryglobal{wcschr}% -\indexlibraryglobal{wcscmp}% -\indexlibraryglobal{wcscoll}% -\indexlibraryglobal{wcscpy}% -\indexlibraryglobal{wcscspn}% -\indexlibraryglobal{wcsftime}% -\indexlibraryglobal{wcslen}% -\indexlibraryglobal{wcsncat}% -\indexlibraryglobal{wcsncmp}% -\indexlibraryglobal{wcsncpy}% -\indexlibraryglobal{wcspbrk}% -\indexlibraryglobal{wcsrchr}% -\indexlibraryglobal{wcsrtombs}% -\indexlibraryglobal{wcsspn}% -\indexlibraryglobal{wcsstr}% -\indexlibraryglobal{wcstod}% -\indexlibraryglobal{wcstof}% -\indexlibraryglobal{wcstok}% -\indexlibraryglobal{wcstold}% -\indexlibraryglobal{wcstoll}% -\indexlibraryglobal{wcstol}% -\indexlibraryglobal{wcstoull}% -\indexlibraryglobal{wcstoul}% -\indexlibraryglobal{wcsxfrm}% -\indexlibraryglobal{wctob}% -\indexlibraryglobal{wint_t}% -\indexlibraryglobal{wmemchr}% -\indexlibraryglobal{wmemcmp}% -\indexlibraryglobal{wmemcpy}% -\indexlibraryglobal{wmemmove}% -\indexlibraryglobal{wmemset}% -\indexlibraryglobal{wprintf}% -\indexlibraryglobal{wscanf}% -\begin{codeblock} -namespace std { - using size_t = @\textit{see \ref{support.types.layout}}@; // freestanding - using mbstate_t = @\seebelow@; // freestanding - using wint_t = @\seebelow@; // freestanding - - struct tm; - - int fwprintf(FILE* stream, const wchar_t* format, ...); - int fwscanf(FILE* stream, const wchar_t* format, ...); - int swprintf(wchar_t* s, size_t n, const wchar_t* format, ...); - int swscanf(const wchar_t* s, const wchar_t* format, ...); - int vfwprintf(FILE* stream, const wchar_t* format, va_list arg); - int vfwscanf(FILE* stream, const wchar_t* format, va_list arg); - int vswprintf(wchar_t* s, size_t n, const wchar_t* format, va_list arg); - int vswscanf(const wchar_t* s, const wchar_t* format, va_list arg); - int vwprintf(const wchar_t* format, va_list arg); - int vwscanf(const wchar_t* format, va_list arg); - int wprintf(const wchar_t* format, ...); - int wscanf(const wchar_t* format, ...); - wint_t fgetwc(FILE* stream); - wchar_t* fgetws(wchar_t* s, int n, FILE* stream); - wint_t fputwc(wchar_t c, FILE* stream); - int fputws(const wchar_t* s, FILE* stream); - int fwide(FILE* stream, int mode); - wint_t getwc(FILE* stream); - wint_t getwchar(); - wint_t putwc(wchar_t c, FILE* stream); - wint_t putwchar(wchar_t c); - wint_t ungetwc(wint_t c, FILE* stream); - double wcstod(const wchar_t* nptr, wchar_t** endptr); - float wcstof(const wchar_t* nptr, wchar_t** endptr); - long double wcstold(const wchar_t* nptr, wchar_t** endptr); - long int wcstol(const wchar_t* nptr, wchar_t** endptr, int base); - long long int wcstoll(const wchar_t* nptr, wchar_t** endptr, int base); - unsigned long int wcstoul(const wchar_t* nptr, wchar_t** endptr, int base); - unsigned long long int wcstoull(const wchar_t* nptr, wchar_t** endptr, int base); - wchar_t* wcscpy(wchar_t* s1, const wchar_t* s2); // freestanding - wchar_t* wcsncpy(wchar_t* s1, const wchar_t* s2, size_t n); // freestanding - wchar_t* wmemcpy(wchar_t* s1, const wchar_t* s2, size_t n); // freestanding - wchar_t* wmemmove(wchar_t* s1, const wchar_t* s2, size_t n); // freestanding - wchar_t* wcscat(wchar_t* s1, const wchar_t* s2); // freestanding - wchar_t* wcsncat(wchar_t* s1, const wchar_t* s2, size_t n); // freestanding - int wcscmp(const wchar_t* s1, const wchar_t* s2); // freestanding - int wcscoll(const wchar_t* s1, const wchar_t* s2); - int wcsncmp(const wchar_t* s1, const wchar_t* s2, size_t n); // freestanding - size_t wcsxfrm(wchar_t* s1, const wchar_t* s2, size_t n); - int wmemcmp(const wchar_t* s1, const wchar_t* s2, size_t n); // freestanding - const wchar_t* wcschr(const wchar_t* s, wchar_t c); // freestanding; see \ref{library.c} - wchar_t* wcschr(wchar_t* s, wchar_t c); // freestanding; see \ref{library.c} - size_t wcscspn(const wchar_t* s1, const wchar_t* s2); // freestanding - const wchar_t* wcspbrk(const wchar_t* s1, const wchar_t* s2); // freestanding; see \ref{library.c} - wchar_t* wcspbrk(wchar_t* s1, const wchar_t* s2); // freestanding; see \ref{library.c} - const wchar_t* wcsrchr(const wchar_t* s, wchar_t c); // freestanding; see \ref{library.c} - wchar_t* wcsrchr(wchar_t* s, wchar_t c); // freestanding; see \ref{library.c} - size_t wcsspn(const wchar_t* s1, const wchar_t* s2); // freestanding - const wchar_t* wcsstr(const wchar_t* s1, const wchar_t* s2); // freestanding; see \ref{library.c} - wchar_t* wcsstr(wchar_t* s1, const wchar_t* s2); // freestanding; see \ref{library.c} - wchar_t* wcstok(wchar_t* s1, const wchar_t* s2, wchar_t** ptr); // freestanding - const wchar_t* wmemchr(const wchar_t* s, wchar_t c, size_t n); // freestanding; see \ref{library.c} - wchar_t* wmemchr(wchar_t* s, wchar_t c, size_t n); // freestanding; see \ref{library.c} - size_t wcslen(const wchar_t* s); // freestanding - wchar_t* wmemset(wchar_t* s, wchar_t c, size_t n); // freestanding - size_t wcsftime(wchar_t* s, size_t maxsize, const wchar_t* format, const tm* timeptr); - wint_t btowc(int c); - int wctob(wint_t c); - - // \ref{c.mb.wcs}, multibyte / wide string and character conversion functions - int mbsinit(const mbstate_t* ps); - size_t mbrlen(const char* s, size_t n, mbstate_t* ps); - size_t mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* ps); - size_t wcrtomb(char* s, wchar_t wc, mbstate_t* ps); - size_t mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* ps); - size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* ps); -} - -#define NULL @\textit{see \ref{support.types.nullptr}}@ // freestanding -#define WCHAR_MAX @\seebelow@ // freestanding -#define WCHAR_MIN @\seebelow@ // freestanding -#define WEOF @\seebelow@ // freestanding -\end{codeblock} - -\pnum -The contents and meaning of the header \libheader{cwchar} -are the same as the C standard library header -\libheader{wchar.h}, except that it does not declare a type \keyword{wchar_t}. - -\pnum -\begin{note} -The functions -\tcode{wcschr}, \tcode{wcspbrk}, \tcode{wcsrchr}, \tcode{wcsstr}, and \tcode{wmemchr} -have different signatures in this document, -but they have the same behavior as in the C standard library\iref{library.c}. -\end{note} - -\xrefc{7.29} - -\rSec2[cuchar.syn]{Header \tcode{} synopsis} - -\indexlibraryglobal{mbstate_t}% -\indexlibraryglobal{size_t}% -\indexlibraryglobal{mbrtoc8}% -\indexlibraryglobal{c8rtomb}% -\indexlibraryglobal{mbrtoc16}% -\indexlibraryglobal{c16rtomb}% -\indexlibraryglobal{mbrtoc32}% -\indexlibraryglobal{c32rtomb}% -\begin{codeblock} -namespace std { - using mbstate_t = @\seebelow@; - using size_t = @\textit{see \ref{support.types.layout}}@; - - size_t mbrtoc8(char8_t* pc8, const char* s, size_t n, mbstate_t* ps); - size_t c8rtomb(char* s, char8_t c8, mbstate_t* ps); - size_t mbrtoc16(char16_t* pc16, const char* s, size_t n, mbstate_t* ps); - size_t c16rtomb(char* s, char16_t c16, mbstate_t* ps); - size_t mbrtoc32(char32_t* pc32, const char* s, size_t n, mbstate_t* ps); - size_t c32rtomb(char* s, char32_t c32, mbstate_t* ps); -} -\end{codeblock} - -\pnum -The contents and meaning of the header \libheaderdef{cuchar} -are the same as the C standard library header -\libheader{uchar.h}, except that it -declares the additional \tcode{mbrtoc8} and \tcode{c8rtomb} functions -and does not declare types \keyword{char16_t} nor \keyword{char32_t}. - -\xrefc{7.28} - -\rSec2[c.mb.wcs]{Multibyte / wide string and character conversion functions} - -\pnum -\begin{note} -The headers \libheaderref{cstdlib}, -\libheaderref{cuchar}, -and \libheaderref{cwchar} -declare the functions described in this subclause. -\end{note} - -\indexlibraryglobal{mbsinit}% -\indexlibraryglobal{mblen}% -\indexlibraryglobal{mbstowcs}% -\indexlibraryglobal{wcstombs}% -\begin{itemdecl} -int mbsinit(const mbstate_t* ps); -int mblen(const char* s, size_t n); -size_t mbstowcs(wchar_t* pwcs, const char* s, size_t n); -size_t wcstombs(char* s, const wchar_t* pwcs, size_t n); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -These functions have the semantics specified in the C standard library. -\end{itemdescr} - -\xrefc{7.22.7.1, 7.22.8, 7.29.6.2.1} - -\indexlibraryglobal{mbtowc}% -\indexlibraryglobal{wctomb}% -\begin{itemdecl} -int mbtowc(wchar_t* pwc, const char* s, size_t n); -int wctomb(char* s, wchar_t wchar); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -These functions have the semantics specified in the C standard library. - -\pnum -\remarks -Calls to these functions -may introduce a data race\iref{res.on.data.races} -with other calls to the same function. -\end{itemdescr} - -\xrefc{7.22.7} - -\indexlibraryglobal{mbrlen}% -\indexlibraryglobal{mbrstowcs}% -\indexlibraryglobal{wcrstombs}% -\indexlibraryglobal{mbrtowc}% -\indexlibraryglobal{wcrtomb}% -\begin{itemdecl} -size_t mbrlen(const char* s, size_t n, mbstate_t* ps); -size_t mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* ps); -size_t wcrtomb(char* s, wchar_t wc, mbstate_t* ps); -size_t mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* ps); -size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* ps); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -These functions have the semantics specified in the C standard library. - -\pnum -\remarks -Calling these functions -with an \tcode{mbstate_t*} argument that is a null pointer value -may introduce a data race\iref{res.on.data.races} -with other calls to the same function -with an \tcode{mbstate_t*} argument that is a null pointer value. -\end{itemdescr} - -\xrefc{7.29.6.3} - -\indexlibraryglobal{mbrtoc8}% -\begin{itemdecl} -size_t mbrtoc8(char8_t* pc8, const char* s, size_t n, mbstate_t* ps); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If \tcode{s} is a null pointer, -equivalent to \tcode{mbrtoc8(nullptr, "", 1, ps)}. -Otherwise, the function inspects at most \tcode{n} bytes -beginning with the byte pointed to by \tcode{s} -to determine the number of bytes needed to complete -the next multibyte character (including any shift sequences). -If the function determines -that the next multibyte character is complete and valid, -\indextext{UTF-8}% -it determines the values of the corresponding UTF-8 code units and then, -if \tcode{pc8} is not a null pointer, -stores the value of the first (or only) such code unit -in the object pointed to by \tcode{pc8}. -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 \unicode{0000}{null}, -the resulting state described is the initial conversion state. - -\pnum -\returns -The first of the following that applies (given the current conversion state): -\begin{itemize} -\item \tcode{0}, if the next \tcode{n} or fewer bytes complete -the multibyte 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 -(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 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 -contribute to an incomplete (but potentially valid) multibyte character, and -all \tcode{n} bytes have been processed (no value is stored). -\item \tcode{(size_t)(-1)}, if an encoding error occurs, -in which case the next \tcode{n} or fewer bytes do not contribute to -a complete and valid multibyte character (no value is stored); -the value of the macro \tcode{EILSEQ} is stored in \tcode{errno}, and -the conversion state is unspecified. -\end{itemize} -\end{itemdescr} - -\indexlibraryglobal{c8rtomb}% -\begin{itemdecl} -size_t c8rtomb(char* s, char8_t c8, mbstate_t* ps); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If \tcode{s} is a null pointer, equivalent to -\tcode{c8rtomb(buf, u8'$\backslash$0', ps)} -where \tcode{buf} is an internal buffer. -\indextext{UTF-8}% -Otherwise, if \tcode{c8} completes a sequence of valid UTF-8 code units, -determines the number of bytes needed -to represent the multibyte character (including any shift sequences), -and stores the multibyte character representation in the array -whose first element is pointed to by \tcode{s}. -At most \tcode{MB_CUR_MAX} bytes are stored. -If the multibyte character is a null character, a null byte is stored, -preceded by any shift sequence needed to restore the initial shift state; -the resulting state described is the initial conversion state. - -\pnum -\returns -The number of bytes stored in the array object (including any shift sequences). -If \tcode{c8} does not contribute to a sequence of \keyword{char8_t} -corresponding to a valid multibyte character, -the value of the macro \tcode{EILSEQ} is stored in \tcode{errno}, -\tcode{(size_t) (-1)} is returned, and the conversion state is unspecified. - -\pnum -\remarks -Calls to \tcode{c8rtomb} with a null pointer argument for \tcode{s} -may introduce a data race\iref{res.on.data.races} -with other calls to \tcode{c8rtomb} -with a null pointer argument for \tcode{s}. -\end{itemdescr} +\xrefc{7.26} diff --git a/source/styles.tex b/source/styles.tex index 8d771e10db..224c99d1e1 100644 --- a/source/styles.tex +++ b/source/styles.tex @@ -5,11 +5,11 @@ % footnotes %%-------------------------------------------------- -%% create chapter style +%% create chapter styles \makechapterstyle{cppstd}{% - \renewcommand{\beforechapskip}{\onelineskip} - \renewcommand{\afterchapskip}{\onelineskip} + \setlength{\beforechapskip}{\onelineskip} + \setlength{\afterchapskip}{\onelineskip} \renewcommand{\chapternamenum}{} \renewcommand{\chapnamefont}{\chaptitlefont} \renewcommand{\chapnumfont}{\chaptitlefont} @@ -17,14 +17,24 @@ \renewcommand{\afterchapternum}{} } +\makechapterstyle{cppannex}{% + \setlength{\beforechapskip}{\onelineskip} + \setlength{\afterchapskip}{\onelineskip} + \renewcommand{\chapternamenum}{} + \renewcommand{\chapnamefont}{\chaptitlefont} + \renewcommand{\chapnumfont}{\chaptitlefont} + \renewcommand{\printchapternum}{\chapnumfont\centering\thechapter\protect\\} + \renewcommand{\afterchapternum}{} +} + %%-------------------------------------------------- %% create page styles \makepagestyle{cpppage} -\makeevenhead{cpppage}{\copyright\,\textsc{ISO/IEC}}{}{\textbf{\docno}} -\makeoddhead{cpppage}{\copyright\,\textsc{ISO/IEC}}{}{\textbf{\docno}} -\makeevenfoot{cpppage}{\leftmark}{}{\thepage} -\makeoddfoot{cpppage}{\leftmark}{}{\thepage} +\makeevenhead{cpppage}{}{\textbf{\docno}}{} + \makeoddhead{cpppage}{}{\textbf{\docno}}{} +\makeevenfoot{cpppage}{\leftmark\\\mbox{}}{}{\copyright\,\textsc{ISO/IEC}\\\thepage} + \makeoddfoot{cpppage}{\leftmark\\\mbox{}}{}{\copyright\,\textsc{ISO/IEC}\\\thepage} \makeatletter \makepsmarks{cpppage}{% @@ -86,7 +96,7 @@ %%-------------------------------------------------- % set heading style for annexes -\newcommand{\Annex}[3]{\chapter[#2]{(#3)\protect\\#2\hfill[#1]}\relax\annexlabel{#1}} +\newcommand{\Annex}[3]{\chapter[#2]{\textnormal{(#3)}\protect\\[3ex]#2\hfill[#1]}\relax\annexlabel{#1}} \newcommand{\infannex}[2]{\addxref{#1}\Annex{#1}{#2}{informative}} \newcommand{\normannex}[2]{\addxref{#1}\Annex{#1}{#2}{normative}} @@ -111,10 +121,10 @@ leftmargin=\bnfindentrest, listparindent=-\bnfindentinc, itemindent=\listparindent} %%-------------------------------------------------- -%% set caption style -\captionstyle{\centering} +%% set caption styles \DeclareCaptionLabelSeparator{emdash}{ --- } -\captionsetup{labelsep=emdash,font+=bf} +\captionsetup{justification=centering,labelsep=emdash,font+=bf} +\captionsetup[lstlisting]{justification=raggedright,singlelinecheck=false,font=normal} %%-------------------------------------------------- %% set global styles that get reset by \mainmatter @@ -165,15 +175,17 @@ \else \lst@ifdisplaystyle \lst@EveryDisplay - % make penalty configurable - \par\lst@beginpenalty + \par\lst@beginpenalty % penalty is now configurable \vspace\lst@aboveskip \fi \fi \normalbaselines \abovecaptionskip\lst@abovecaption\relax \belowcaptionskip\lst@belowcaption\relax - \lst@MakeCaption t% + \let\savedallowbreak\allowbreak + \let\allowbreak\relax + \lst@MakeCaption t% % neuter \allowbreak before non-existing top caption + \let\allowbreak\savedallowbreak \lsthk@PreInit \lsthk@Init \lst@ifdisplaystyle \global\let\lst@ltxlabel\@empty diff --git a/source/support.tex b/source/support.tex index 8ddffc6635..19e19d6f11 100644 --- a/source/support.tex +++ b/source/support.tex @@ -17,6 +17,7 @@ functions supporting start and termination of a \Cpp{} program, support for dynamic memory management, support for dynamic type identification, +support for contract-violation handling, support for exception processing, support for initializer lists, and other runtime support, as summarized in \tref{support.summary}. @@ -29,10 +30,11 @@ \ref{support.arith.types} & Arithmetic types & \tcode{}, \tcode{} \\ \rowsep \ref{support.start.term} & Start and termination & \tcode{} \\ \rowsep \ref{support.dynamic} & Dynamic memory management & \tcode{} \\ \rowsep -\ref{support.rtti} & Type identification & \tcode{} \\ \rowsep +\ref{support.rtti} & Type identification & \tcode{}, \tcode{} \\ \rowsep \ref{support.srcloc} & Source location & \tcode{} \\ \rowsep \ref{support.exception} & Exception handling & \tcode{} \\ \rowsep -\ref{support.initlist} & Initializer lists & \tcode{} \\ \rowsep +\ref{support.contract} & Contract-violation handling & \tcode{} \\ \rowsep +\ref{support.initlist} & Initializer lists & \tcode{} \\ \rowsep \ref{cmp} & Comparisons & \tcode{} \\ \rowsep \ref{support.coroutine} & Coroutines & \tcode{} \\ \rowsep \ref{support.runtime} & Other runtime support & @@ -88,13 +90,14 @@ The contents and meaning of the header \libheaderdef{cstddef} are the same as the C standard library header \libheader{stddef.h}, except that it does not declare the type \keyword{wchar_t}, +that it does not define the macro \tcode{unreachable}, that it also declares the type \tcode{byte} and its associated operations\iref{support.types.byteops}, and as noted in \ref{support.types.nullptr} and \ref{support.types.layout}. -\xrefc{7.19} +\xrefc{7.22} \rSec2[cstdlib.syn]{Header \tcode{} synopsis} @@ -185,14 +188,20 @@ void* aligned_alloc(size_t alignment, size_t size); void* calloc(size_t nmemb, size_t size); void free(void* ptr); + void free_sized(void* ptr, size_t size); + void free_aligned_sized(void* ptr, size_t alignment, size_t size); void* malloc(size_t size); void* realloc(void* ptr, size_t size); + size_t memalignment(const void* p); // freestanding double atof(const char* nptr); int atoi(const char* nptr); long int atol(const char* nptr); long long int atoll(const char* nptr); double strtod(const char* nptr, char** endptr); + int strfromd(char* s, size_t n, const char* format, double fp); + int strfromf(char* s, size_t n, const char* format, float fp); + int strfroml(char* s, size_t n, const char* format, long double fp); float strtof(const char* nptr, char** endptr); long double strtold(const char* nptr, char** endptr); long int strtol(const char* nptr, char** endptr, int base); @@ -208,10 +217,14 @@ size_t wcstombs(char* s, const wchar_t* pwcs, size_t n); // \ref{alg.c.library}, C standard library algorithms - void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, // freestanding + void* bsearch(const void* key, void* base, size_t nmemb, size_t size, // freestanding @\placeholder{c-compare-pred}@*@\itcorr[-1]@ compar); - void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, // freestanding + void* bsearch(const void* key, void* base, size_t nmemb, size_t size, // freestanding @\placeholder{compare-pred}@*@\itcorr[-1]@ compar); + const void* bsearch(const void* key, const void* base, size_t nmemb, // freestanding + size_t size, @\placeholder{c-compare-pred}@*@\itcorr[-1]@ compar); + const void* bsearch(const void* key, const void* base, size_t nmemb, // freestanding + size_t size, @\placeholder{compare-pred}@*@\itcorr[-1]@ compar); void qsort(void* base, size_t nmemb, size_t size, @\placeholder{c-compare-pred}@*@\itcorr[-1]@ compar); // freestanding void qsort(void* base, size_t nmemb, size_t size, @\placeholder{compare-pred}@*@\itcorr[-1]@ compar); // freestanding @@ -239,7 +252,8 @@ \pnum The contents and meaning of the header \libheader{cstdlib} are the same as the C standard library header \libheader{stdlib.h}, -except that it does not declare the type \keyword{wchar_t}, +except that it does not declare the types \keyword{wchar_t} or \tcode{once_flag}, +and does not declare the function \tcode{call_once}, and except as noted in \ref{support.types.nullptr}, \ref{support.types.layout}, @@ -254,7 +268,7 @@ but they have the same behavior as in the C standard library\iref{library.c}. \end{note} -\xrefc{7.22} +\xrefc{7.24} \rSec2[support.types.nullptr]{Null pointers} @@ -283,7 +297,7 @@ \tcode{(void*)0}. \end{footnote} -\xrefc{7.19} +\xrefc{7.22} \rSec2[support.types.layout]{Sizes, alignments, and offsets} @@ -333,11 +347,12 @@ \pnum The type \indexlibraryglobal{max_align_t}% -\tcode{max_align_t} is a trivial standard-layout type whose alignment requirement +\tcode{max_align_t} is a trivially copyable standard-layout type whose alignment requirement is at least as great as that of every scalar type, and whose alignment requirement is supported in every context\iref{basic.align}. +\tcode{std::is_trivially_default_constructible_v} is \tcode{true}. -\xrefc{7.19} +\xrefc{7.22} \rSec2[support.types.byteops]{\tcode{byte} type operations} @@ -546,21 +561,24 @@ after inclusion of any member of the set of library headers indicated in the corresponding comment in this synopsis. \begin{note} -Future revisions of \Cpp{} might replace +Future revisions of this document might replace the values of these macros with greater values. \end{note} \begin{codeblock} #define @\defnlibxname{cpp_lib_adaptor_iterator_pair_constructor}@ 202106L // also in \libheader{stack}, \libheader{queue} #define @\defnlibxname{cpp_lib_addressof_constexpr}@ 201603L // freestanding, also in \libheader{memory} +#define @\defnlibxname{cpp_lib_algorithm_default_value_type}@ 202403L + // also in \libheader{algorithm}, \libheader{ranges}, \libheader{string}, \libheader{deque}, \libheader{list}, \libheader{forward_list}, \libheader{vector} #define @\defnlibxname{cpp_lib_algorithm_iterator_requirements}@ 202207L // also in \libheader{algorithm}, \libheader{numeric}, \libheader{memory} +#define @\defnlibxname{cpp_lib_aligned_accessor}@ 202411L // also in \libheader{mdspan} #define @\defnlibxname{cpp_lib_allocate_at_least}@ 202302L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_allocator_traits_is_always_equal}@ 201411L // freestanding, also in \libheader{memory}, \libheader{scoped_allocator}, \libheader{string}, \libheader{deque}, \libheader{forward_list}, \libheader{list}, // \libheader{vector}, \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set} #define @\defnlibxname{cpp_lib_any}@ 201606L // also in \libheader{any} -#define @\defnlibxname{cpp_lib_apply}@ 201603L // freestanding, also in \libheader{tuple} +#define @\defnlibxname{cpp_lib_apply}@ 202506L // freestanding, also in \libheader{tuple}, \libheader{type_traits} #define @\defnlibxname{cpp_lib_array_constexpr}@ 201811L // also in \libheader{iterator}, \libheader{array} #define @\defnlibxname{cpp_lib_as_const}@ 201510L // freestanding, also in \libheader{utility} #define @\defnlibxname{cpp_lib_associative_heterogeneous_erasure}@ 202110L @@ -572,7 +590,9 @@ #define @\defnlibxname{cpp_lib_atomic_float}@ 201711L // freestanding, also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_is_always_lock_free}@ 201603L // freestanding, also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_lock_free_type_aliases}@ 201907L // also in \libheader{atomic} -#define @\defnlibxname{cpp_lib_atomic_ref}@ 201806L // freestanding, also in \libheader{atomic} +#define @\defnlibxname{cpp_lib_atomic_min_max}@ 202506L // freestanding, also in \libheader{atomic} +#define @\defnlibxname{cpp_lib_atomic_reductions}@ 202506L // freestanding, also in \libheader{atomic} +#define @\defnlibxname{cpp_lib_atomic_ref}@ 202411L // freestanding, also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_shared_ptr}@ 201711L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_atomic_value_initialization}@ 201911L // freestanding, also in \libheader{atomic}, \libheader{memory} #define @\defnlibxname{cpp_lib_atomic_wait}@ 201907L // freestanding, also in \libheader{atomic} @@ -593,39 +613,62 @@ #define @\defnlibxname{cpp_lib_chrono}@ 202306L // also in \libheader{chrono} #define @\defnlibxname{cpp_lib_chrono_udls}@ 201304L // also in \libheader{chrono} #define @\defnlibxname{cpp_lib_clamp}@ 201603L // also in \libheader{algorithm} -#define @\defnlibxname{cpp_lib_common_reference}@ 202302L // also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_common_reference_wrapper}@ 202302L // also in \libheader{functional} +#define @\defnlibxname{cpp_lib_common_reference}@ 202302L // freestanding, also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_common_reference_wrapper}@ 202302L // freestanding, also in \libheader{functional} #define @\defnlibxname{cpp_lib_complex_udls}@ 201309L // also in \libheader{complex} #define @\defnlibxname{cpp_lib_concepts}@ 202207L // freestanding, also in \libheader{concepts}, \libheader{compare} +#define @\defnlibxname{cpp_lib_constant_wrapper}@ 202506L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_constexpr_algorithms}@ 202306L // also in \libheader{algorithm}, \libheader{utility} +#define @\defnlibxname{cpp_lib_constexpr_atomic}@ 202411L // also in \libheader{atomic} #define @\defnlibxname{cpp_lib_constexpr_bitset}@ 202207L // also in \libheader{bitset} -#define @\defnlibxname{cpp_lib_constexpr_charconv}@ 202207L // also in \libheader{charconv} +#define @\defnlibxname{cpp_lib_constexpr_charconv}@ 202207L // freestanding, also in \libheader{charconv} #define @\defnlibxname{cpp_lib_constexpr_cmath}@ 202306L // also in \libheader{cmath}, \libheader{cstdlib} #define @\defnlibxname{cpp_lib_constexpr_complex}@ 202306L // also in \libheader{complex} +#define @\defnlibxname{cpp_lib_constexpr_deque}@ 202502L // also in \libheader{deque} #define @\defnlibxname{cpp_lib_constexpr_dynamic_alloc}@ 201907L // also in \libheader{memory} +#define @\defnlibxname{cpp_lib_constexpr_exceptions}@ 202502L + // also in \libheader{exception}, \libheader{stdexcept}, \libheader{expected}, \libheader{optional}, \libheader{variant}, and \libheader{format} +#define @\defnlibxname{cpp_lib_constexpr_flat_map}@ 202502L // also in \libheader{flat_map} +#define @\defnlibxname{cpp_lib_constexpr_flat_set}@ 202502L // also in \libheader{flat_set} +#define @\defnlibxname{cpp_lib_constexpr_forward_list}@ 202502L // also in \libheader{forward_list} #define @\defnlibxname{cpp_lib_constexpr_functional}@ 201907L // freestanding, also in \libheader{functional} +#define @\defnlibxname{cpp_lib_constexpr_inplace_vector}@ 202502L // also in \libheader{inplace_vector} #define @\defnlibxname{cpp_lib_constexpr_iterator}@ 201811L // freestanding, also in \libheader{iterator} -#define @\defnlibxname{cpp_lib_constexpr_memory}@ 202202L // freestanding, also in \libheader{memory} +#define @\defnlibxname{cpp_lib_constexpr_list}@ 202502L // also in \libheader{list} +#define @\defnlibxname{cpp_lib_constexpr_map}@ 202502L // also in \libheader{map} +#define @\defnlibxname{cpp_lib_constexpr_memory}@ 202506L // freestanding, also in \libheader{memory} +#define @\defnlibxname{cpp_lib_constexpr_new}@ 202406L // freestanding, also in \libheader{new} #define @\defnlibxname{cpp_lib_constexpr_numeric}@ 201911L // also in \libheader{numeric} +#define @\defnlibxname{cpp_lib_constexpr_queue}@ 202502L // also in \libheader{queue} +#define @\defnlibxname{cpp_lib_constexpr_set}@ 202502L // also in \libheader{set} +#define @\defnlibxname{cpp_lib_constexpr_stack}@ 202502L // also in \libheader{stack} #define @\defnlibxname{cpp_lib_constexpr_string}@ 201907L // also in \libheader{string} #define @\defnlibxname{cpp_lib_constexpr_string_view}@ 201811L // also in \libheader{string_view} #define @\defnlibxname{cpp_lib_constexpr_tuple}@ 201811L // freestanding, also in \libheader{tuple} #define @\defnlibxname{cpp_lib_constexpr_typeinfo}@ 202106L // freestanding, also in \libheader{typeinfo} +#define @\defnlibxname{cpp_lib_constexpr_unordered_map}@ 202502L // also in \libheader{unordered_map} +#define @\defnlibxname{cpp_lib_constexpr_unordered_set}@ 202502L // also in \libheader{unordered_set} #define @\defnlibxname{cpp_lib_constexpr_utility}@ 201811L // freestanding, also in \libheader{utility} #define @\defnlibxname{cpp_lib_constexpr_vector}@ 201907L // also in \libheader{vector} +#define @\defnlibxname{cpp_lib_constrained_equality}@ 202411L // freestanding, + // also in \libheader{utility}, \libheader{tuple}, \libheader{optional}, \libheader{variant}, \libheader{expected} #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{stack}, \libheader{string} +#define @\defnlibxname{cpp_lib_contracts}@ 202502L // freestanding, also in \libheader{contracts} #define @\defnlibxname{cpp_lib_copyable_function}@ 202306L // also in \libheader{functional} -#define @\defnlibxname{cpp_lib_coroutine}@ 201902L // also in \libheader{coroutine} -#define @\defnlibxname{cpp_lib_debugging}@ 202311L // freestanding, also in \libheader{debugging} +#define @\defnlibxname{cpp_lib_coroutine}@ 201902L // freestanding, also in \libheader{coroutine} +#define @\defnlibxname{cpp_lib_counting_scope}@ 202506L // also in \libheader{execution} +#define @\defnlibxname{cpp_lib_debugging}@ 202403L // freestanding, also in \libheader{debugging} +#define @\defnlibxname{cpp_lib_define_static}@ 202506L // freestanding, also in \libheader{meta} #define @\defnlibxname{cpp_lib_destroying_delete}@ 201806L // freestanding, also in \libheader{new} #define @\defnlibxname{cpp_lib_enable_shared_from_this}@ 201603L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_endian}@ 201907L // freestanding, also in \libheader{bit} #define @\defnlibxname{cpp_lib_erase_if}@ 202002L // also in \libheader{string}, \libheader{deque}, \libheader{forward_list}, \libheader{list}, \libheader{vector}, \libheader{map}, \libheader{set}, \libheader{unordered_map}, // \libheader{unordered_set} +#define @\defnlibxname{cpp_lib_exception_ptr_cast}@ 202506L // also in \libheader{exception} #define @\defnlibxname{cpp_lib_exchange_function}@ 201304L // freestanding, also in \libheader{utility} #define @\defnlibxname{cpp_lib_execution}@ 201902L // also in \libheader{execution} #define @\defnlibxname{cpp_lib_expected}@ 202211L // also in \libheader{expected} @@ -634,10 +677,11 @@ #define @\defnlibxname{cpp_lib_flat_set}@ 202207L // also in \libheader{flat_set} #define @\defnlibxname{cpp_lib_format}@ 202311L // also in \libheader{format} #define @\defnlibxname{cpp_lib_format_ranges}@ 202207L // also in \libheader{format} +#define @\defnlibxname{cpp_lib_format_path}@ 202506L // also in \libheader{filesystem} #define @\defnlibxname{cpp_lib_format_uchar}@ 202311L // also in \libheader{format} #define @\defnlibxname{cpp_lib_formatters}@ 202302L // also in \libheader{stacktrace}, \libheader{thread} #define @\defnlibxname{cpp_lib_forward_like}@ 202207L // freestanding, also in \libheader{utility} -#define @\defnlibxname{cpp_lib_freestanding_algorithm}@ 202311L // freestanding, also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_freestanding_algorithm}@ 202502L // freestanding, also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_freestanding_array}@ 202311L // freestanding, also in \libheader{array} #define @\defnlibxname{cpp_lib_freestanding_char_traits}@ 202306L // freestanding, also in \libheader{string} #define @\defnlibxname{cpp_lib_freestanding_charconv}@ 202306L // freestanding, also in \libheader{charconv} @@ -646,15 +690,17 @@ #define @\defnlibxname{cpp_lib_freestanding_cwchar}@ 202306L // freestanding, also in \libheader{cwchar} #define @\defnlibxname{cpp_lib_freestanding_errc}@ 202306L // freestanding, also in \libheader{cerrno}, \libheader{system_error} +#define @\defnlibxname{cpp_lib_freestanding_execution}@ 202502L // freestanding, also in \libheader{execution} #define @\defnlibxname{cpp_lib_freestanding_expected}@ 202311L // freestanding, also in \libheader{expected} #define @\defnlibxname{cpp_lib_freestanding_feature_test_macros}@ 202306L // freestanding #define @\defnlibxname{cpp_lib_freestanding_functional}@ 202306L // freestanding, also in \libheader{functional} #define @\defnlibxname{cpp_lib_freestanding_iterator}@ 202306L // freestanding, also in \libheader{iterator} #define @\defnlibxname{cpp_lib_freestanding_mdspan}@ 202311L // freestanding, also in \libheader{mdspan} -#define @\defnlibxname{cpp_lib_freestanding_memory}@ 202306L // freestanding, also in \libheader{memory} -#define @\defnlibxname{cpp_lib_freestanding_numeric}@ 202311L // freestanding, also in \libheader{numeric} +#define @\defnlibxname{cpp_lib_freestanding_memory}@ 202502L // freestanding, also in \libheader{memory} +#define @\defnlibxname{cpp_lib_freestanding_numeric}@ 202502L // freestanding, also in \libheader{numeric} #define @\defnlibxname{cpp_lib_freestanding_operator_new}@ @\seebelow@ // freestanding, also in \libheader{new} -#define @\defnlibxname{cpp_lib_freestanding_optional}@ 202311L // freestanding, also in \libheader{optional} +#define @\defnlibxname{cpp_lib_freestanding_optional}@ 202506L // freestanding, also in \libheader{optional} +#define @\defnlibxname{cpp_lib_freestanding_random}@ 202502L // freestanding, also in \libheader{random} #define @\defnlibxname{cpp_lib_freestanding_ranges}@ 202306L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_freestanding_ratio}@ 202306L // freestanding, also in \libheader{ratio} #define @\defnlibxname{cpp_lib_freestanding_string_view}@ 202311L // freestanding, also in \libheader{string_view} @@ -671,9 +717,12 @@ #define @\defnlibxname{cpp_lib_hardware_interference_size}@ 201703L // freestanding, also in \libheader{new} #define @\defnlibxname{cpp_lib_has_unique_object_representations}@ 201606L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_hazard_pointer}@ 202306L // also in \libheader{hazard_pointer} +#define @\defnlibxname{cpp_lib_hive}@ 202502L // also in \libheader{hive} #define @\defnlibxname{cpp_lib_hypot}@ 201603L // also in \libheader{cmath} #define @\defnlibxname{cpp_lib_incomplete_container_elements}@ 201505L // also in \libheader{forward_list}, \libheader{list}, \libheader{vector} +#define @\defnlibxname{cpp_lib_indirect}@ 202502L // also in \libheader{memory} +#define @\defnlibxname{cpp_lib_inplace_vector}@ 202406L // also in \libheader{inplace_vector} #define @\defnlibxname{cpp_lib_int_pow2}@ 202002L // freestanding, also in \libheader{bit} #define @\defnlibxname{cpp_lib_integer_comparison_functions}@ 202002L // also in \libheader{utility} #define @\defnlibxname{cpp_lib_integer_sequence}@ 201304L // freestanding, also in \libheader{utility} @@ -685,19 +734,21 @@ #define @\defnlibxname{cpp_lib_is_aggregate}@ 201703L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_constant_evaluated}@ 201811L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_final}@ 201402L // freestanding, also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_implicit_lifetime}@ 202302L // also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_is_implicit_lifetime}@ 202302L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_invocable}@ 201703L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_layout_compatible}@ 201907L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_nothrow_convertible}@ 201806L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_null_pointer}@ 201309L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_pointer_interconvertible}@ 201907L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_is_scoped_enum}@ 202011L // freestanding, also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_is_sufficiently_aligned}@ 202411L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_is_swappable}@ 201603L // freestanding, also in \libheader{type_traits} -#define @\defnlibxname{cpp_lib_is_within_lifetime}@ 202306L // also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_is_virtual_base_of}@ 202406L // freestanding, also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_is_within_lifetime}@ 202306L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_jthread}@ 201911L // also in \libheader{stop_token}, \libheader{thread} #define @\defnlibxname{cpp_lib_latch}@ 201907L // also in \libheader{latch} #define @\defnlibxname{cpp_lib_launder}@ 201606L // freestanding, also in \libheader{new} -#define @\defnlibxname{cpp_lib_linalg}@ 202311L // also in \libheader{linalg} +#define @\defnlibxname{cpp_lib_linalg}@ 202412L // also in \libheader{linalg} #define @\defnlibxname{cpp_lib_list_remove_return_type}@ 201806L // also in \libheader{forward_list}, \libheader{list} #define @\defnlibxname{cpp_lib_logical_traits}@ 201510L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_make_from_tuple}@ 201606L // freestanding, also in \libheader{tuple} @@ -706,7 +757,7 @@ #define @\defnlibxname{cpp_lib_map_try_emplace}@ 201411L // also in \libheader{map} #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_mdspan}@ 202207L // also in \libheader{mdspan} +#define @\defnlibxname{cpp_lib_mdspan}@ 202406L // freestanding, also in \libheader{mdspan} #define @\defnlibxname{cpp_lib_memory_resource}@ 201603L // also in \libheader{memory_resource} #define @\defnlibxname{cpp_lib_modules}@ 202207L // freestanding #define @\defnlibxname{cpp_lib_move_iterator_concept}@ 202207L // freestanding, also in \libheader{iterator} @@ -718,36 +769,50 @@ // \libheader{string}, \libheader{unordered_map}, \libheader{unordered_set}, \libheader{vector} #define @\defnlibxname{cpp_lib_not_fn}@ 202306L // freestanding, also in \libheader{functional} #define @\defnlibxname{cpp_lib_null_iterators}@ 201304L // freestanding, also in \libheader{iterator} -#define @\defnlibxname{cpp_lib_optional}@ 202110L // also in \libheader{optional} +#define @\defnlibxname{cpp_lib_observable_checkpoint}@ 202506L // freestanding, also in \libheader{utility} +#define @\defnlibxname{cpp_lib_optional}@ 202506L // also in \libheader{optional} +#define @\defnlibxname{cpp_lib_optional_range_support}@ 202406L // freestanding, also in \libheader{optional} #define @\defnlibxname{cpp_lib_out_ptr}@ 202311L // freestanding, also in \libheader{memory} -#define @\defnlibxname{cpp_lib_parallel_algorithm}@ 201603L // also in \libheader{algorithm}, \libheader{numeric} +#define @\defnlibxname{cpp_lib_parallel_algorithm}@ 202506L + // also in \libheader{algorithm}, \libheader{numeric}, \libheader{memory} +#define @\defnlibxname{cpp_lib_parallel_scheduler}@ 202506L // also in \libheader{execution} +#define @\defnlibxname{cpp_lib_philox_engine}@ 202406L // also in \libheader{random} +#define @\defnlibxname{cpp_lib_polymorphic}@ 202502L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_polymorphic_allocator}@ 201902L // also in \libheader{memory_resource} -#define @\defnlibxname{cpp_lib_print}@ 202207L // also in \libheader{print}, \libheader{ostream} +#define @\defnlibxname{cpp_lib_print}@ 202406L // also in \libheader{print}, \libheader{ostream} #define @\defnlibxname{cpp_lib_quoted_string_io}@ 201304L // also in \libheader{iomanip} -#define @\defnlibxname{cpp_lib_ranges}@ 202302L +#define @\defnlibxname{cpp_lib_ranges}@ 202406L // also in \libheader{algorithm}, \libheader{functional}, \libheader{iterator}, \libheader{memory}, \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_as_const}@ 202311L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_as_rvalue}@ 202207L // freestanding, also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_cache_latest}@ 202411L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_cartesian_product}@ 202207L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_chunk}@ 202202L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_chunk_by}@ 202202L // freestanding, also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_concat}@ 202403L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_contains}@ 202207L // also in \libheader{algorithm} -#define @\defnlibxname{cpp_lib_ranges_enumerate}@ 202302L // also in \libheader{ranges}, \libheader{version} +#define @\defnlibxname{cpp_lib_ranges_enumerate}@ 202302L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_find_last}@ 202207L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_fold}@ 202207L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_ranges_generate_random}@ 202403L // also in \libheader{random} +#define @\defnlibxname{cpp_lib_ranges_indices}@ 202506L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_iota}@ 202202L // also in \libheader{numeric} #define @\defnlibxname{cpp_lib_ranges_join_with}@ 202202L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_repeat}@ 202207L // freestanding, also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_reserve_hint}@ 202502L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_slide}@ 202202L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_starts_ends_with}@ 202106L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_stride}@ 202207L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_to_container}@ 202202L // freestanding, also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_to_input}@ 202502L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_zip}@ 202110L // freestanding, also in \libheader{ranges}, \libheader{tuple}, \libheader{utility} -#define @\defnlibxname{cpp_lib_ratio}@ 202306L // also in \libheader{ratio} -#define @\defnlibxname{cpp_lib_raw_memory_algorithms}@ 201606L // also in \libheader{memory} +#define @\defnlibxname{cpp_lib_ratio}@ 202306L // freestanding, also in \libheader{ratio} +#define @\defnlibxname{cpp_lib_raw_memory_algorithms}@ 202411L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_rcu}@ 202306L // also in \libheader{rcu} #define @\defnlibxname{cpp_lib_reference_from_temporary}@ 202202L // freestanding, also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_reference_wrapper}@ 202403L // freestanding, also in \libheader{functional} +#define @\defnlibxname{cpp_lib_reflection}@ 202506L // also in \libheader{meta} #define @\defnlibxname{cpp_lib_remove_cvref}@ 201711L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_result_of_sfinae}@ 201210L // freestanding, also in \libheader{functional}, \libheader{type_traits} @@ -756,16 +821,20 @@ #define @\defnlibxname{cpp_lib_saturation_arithmetic}@ 202311L // also in \libheader{numeric} #define @\defnlibxname{cpp_lib_scoped_lock}@ 201703L // also in \libheader{mutex} #define @\defnlibxname{cpp_lib_semaphore}@ 201907L // also in \libheader{semaphore} +#define @\defnlibxname{cpp_lib_senders}@ 202506L // also in \libheader{execution} #define @\defnlibxname{cpp_lib_shared_mutex}@ 201505L // also in \libheader{shared_mutex} #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}@ 202202L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_simd}@ 202506L // also in \libheader{simd} +#define @\defnlibxname{cpp_lib_simd_complex}@ 202502L // also in \libheader{simd} +#define @\defnlibxname{cpp_lib_simd_permutations}@ 202506L // also in \libheader{simd} #define @\defnlibxname{cpp_lib_smart_ptr_for_overwrite}@ 202002L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_smart_ptr_owner_equality}@ 202306L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_source_location}@ 201907L // freestanding, also in \libheader{source_location} #define @\defnlibxname{cpp_lib_span}@ 202311L // freestanding, also in \libheader{span} -#define @\defnlibxname{cpp_lib_span_initializer_list}@ 202311L // also in \libheader{span} +#define @\defnlibxname{cpp_lib_span_initializer_list}@ 202311L // freestanding, also in \libheader{span} #define @\defnlibxname{cpp_lib_spanstream}@ 202106L // also in \libheader{spanstream} #define @\defnlibxname{cpp_lib_ssize}@ 201902L // freestanding, also in \libheader{iterator} #define @\defnlibxname{cpp_lib_sstream_from_string_view}@ 202306L // also in \libheader{sstream} @@ -775,25 +844,30 @@ #define @\defnlibxname{cpp_lib_stdatomic_h}@ 202011L // also in \libheader{stdatomic.h} #define @\defnlibxname{cpp_lib_string_contains}@ 202011L // also in \libheader{string}, \libheader{string_view} #define @\defnlibxname{cpp_lib_string_resize_and_overwrite}@ 202110L // also in \libheader{string} +#define @\defnlibxname{cpp_lib_string_subview}@ 202506L // also in \libheader{string}, \libheader{string_view} #define @\defnlibxname{cpp_lib_string_udls}@ 201304L // also in \libheader{string} -#define @\defnlibxname{cpp_lib_string_view}@ 201803L // also in \libheader{string}, \libheader{string_view} -#define @\defnlibxname{cpp_lib_submdspan}@ 202306L // also in \libheader{mdspan} +#define @\defnlibxname{cpp_lib_string_view}@ 202403L // also in \libheader{string}, \libheader{string_view} +#define @\defnlibxname{cpp_lib_submdspan}@ 202411L // freestanding, also in \libheader{mdspan} #define @\defnlibxname{cpp_lib_syncbuf}@ 201803L // also in \libheader{syncstream} +#define @\defnlibxname{cpp_lib_task}@ 202506L // also in \libheader{execution} #define @\defnlibxname{cpp_lib_text_encoding}@ 202306L // also in \libheader{text_encoding} #define @\defnlibxname{cpp_lib_three_way_comparison}@ 201907L // freestanding, also in \libheader{compare} #define @\defnlibxname{cpp_lib_to_address}@ 201711L // freestanding, also in \libheader{memory} -#define @\defnlibxname{cpp_lib_to_array}@ 201907L // also in \libheader{array} +#define @\defnlibxname{cpp_lib_to_array}@ 201907L // freestanding, also in \libheader{array} #define @\defnlibxname{cpp_lib_to_chars}@ 202306L // also in \libheader{charconv} #define @\defnlibxname{cpp_lib_to_string}@ 202306L // also in \libheader{string} #define @\defnlibxname{cpp_lib_to_underlying}@ 202102L // freestanding, also in \libheader{utility} #define @\defnlibxname{cpp_lib_transformation_trait_aliases}@ 201304L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_transparent_operators}@ 201510L // freestanding, also in \libheader{memory}, \libheader{functional} +#define @\defnlibxname{cpp_lib_trivially_relocatable}@ 202502L + // freestanding, also in \libheader{memory}, \libheader{type_traits} #define @\defnlibxname{cpp_lib_tuple_element_t}@ 201402L // freestanding, also in \libheader{tuple} #define @\defnlibxname{cpp_lib_tuple_like}@ 202311L // also in \libheader{utility}, \libheader{tuple}, \libheader{map}, \libheader{unordered_map} #define @\defnlibxname{cpp_lib_tuples_by_type}@ 201304L // freestanding, also in \libheader{utility}, \libheader{tuple} #define @\defnlibxname{cpp_lib_type_identity}@ 201806L // freestanding, also in \libheader{type_traits} +#define @\defnlibxname{cpp_lib_type_order}@ 202506L // also in \libheader{compare} #define @\defnlibxname{cpp_lib_type_trait_variable_templates}@ 201510L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_uncaught_exceptions}@ 201411L // freestanding, also in \libheader{exception} #define @\defnlibxname{cpp_lib_unordered_map_try_emplace}@ 201411L // also in \libheader{unordered_map} @@ -803,6 +877,30 @@ #define @\defnlibxname{cpp_lib_void_t}@ 201411L // freestanding, also in \libheader{type_traits} \end{codeblock} +\pnum +Additionally, each of the following macros is defined in a hardened implementation: +\begin{codeblock} +#define @\defnlibxname{cpp_lib_hardened_array}@ 202502L // also in \libheader{array} +#define @\defnlibxname{cpp_lib_hardened_basic_stacktrace}@ 202506L // also in \libheader{stacktrace} +#define @\defnlibxname{cpp_lib_hardened_basic_string}@ 202502L // also in \libheader{string} +#define @\defnlibxname{cpp_lib_hardened_basic_string_view}@ 202502L // also in \libheader{string_view} +#define @\defnlibxname{cpp_lib_hardened_bitset}@ 202502L // also in \libheader{bitset} +#define @\defnlibxname{cpp_lib_hardened_common_iterator}@ 202506L // also in \libheader{iterator} +#define @\defnlibxname{cpp_lib_hardened_counted_iterator}@ 202506L // also in \libheader{iterator} +#define @\defnlibxname{cpp_lib_hardened_deque}@ 202502L // also in \libheader{deque} +#define @\defnlibxname{cpp_lib_hardened_expected}@ 202502L // also in \libheader{expected} +#define @\defnlibxname{cpp_lib_hardened_forward_list}@ 202502L // also in \libheader{forward_list} +#define @\defnlibxname{cpp_lib_hardened_inplace_vector}@ 202502L // also in \libheader{inplace_vector} +#define @\defnlibxname{cpp_lib_hardened_list}@ 202502L // also in \libheader{list} +#define @\defnlibxname{cpp_lib_hardened_mdspan}@ 202502L // also in \libheader{mdspan} +#define @\defnlibxname{cpp_lib_hardened_optional}@ 202502L // also in \libheader{optional} +#define @\defnlibxname{cpp_lib_hardened_shared_ptr_array}@ 202506L // also in \libheader{memory} +#define @\defnlibxname{cpp_lib_hardened_span}@ 202502L // also in \libheader{span} +#define @\defnlibxname{cpp_lib_hardened_valarray}@ 202502L // also in \libheader{valarray} +#define @\defnlibxname{cpp_lib_hardened_vector}@ 202502L // also in \libheader{vector} +#define @\defnlibxname{cpp_lib_hardened_view_interface}@ 202506L // also in \libheader{ranges} +\end{codeblock} + \pnum The macro \xname{cpp_lib_freestanding_operator_new} is defined to the integer literal \tcode{202306L} @@ -815,6 +913,11 @@ Freestanding implementations should only define a macro from \libheader{version} if the implementation provides the corresponding facility in its entirety. +\pnum +\recommended +A non-hardened implementation should not define macros from \libheader{version} +required for hardened implementations. + \rSec2[limits.syn]{Header \tcode{} synopsis} \indexheader{limits}% @@ -1003,6 +1106,11 @@ \pnum \indextext{signal-safe!\idxcode{numeric_limits} members}% Each member function defined in this subclause is signal-safe\iref{support.signal}. +\begin{note} +\indextext{LIA-1}% +The arithmetic specification described in ISO/IEC 10967-1:2012 is +commonly termed LIA-1. +\end{note} \indexlibrarymember{min}{numeric_limits}% \begin{itemdecl} @@ -1213,16 +1321,14 @@ \pnum Measure of the maximum rounding error. \begin{footnote} -Rounding error is described in -LIA-1 -Section 5.2.4 and +Rounding error is described in ISO/IEC 10967-1:2012 Section 5.2.4 and Annex C Rationale Section C.5.2.4 --- Rounding and rounding constants. \end{footnote} \end{itemdescr} \indexlibrarymember{min_exponent}{numeric_limits}% \begin{itemdecl} -static constexpr int min_exponent; +static constexpr int min_exponent; \end{itemdecl} \begin{itemdescr} @@ -1242,7 +1348,7 @@ \indexlibrarymember{min_exponent10}{numeric_limits}% \begin{itemdecl} -static constexpr int min_exponent10; +static constexpr int min_exponent10; \end{itemdecl} \begin{itemdescr} @@ -1260,7 +1366,7 @@ \indexlibrarymember{max_exponent}{numeric_limits}% \begin{itemdecl} -static constexpr int max_exponent; +static constexpr int max_exponent; \end{itemdecl} \begin{itemdescr} @@ -1280,7 +1386,7 @@ \indexlibrarymember{max_exponent10}{numeric_limits}% \begin{itemdecl} -static constexpr int max_exponent10; +static constexpr int max_exponent10; \end{itemdecl} \begin{itemdescr} @@ -1325,7 +1431,7 @@ \tcode{true} if the type has a representation for a quiet (non-signaling) ``Not a Number''. \begin{footnote} -Required by LIA-1. +Required by ISO/IEC 10967-1:2012. \end{footnote} \pnum @@ -1347,7 +1453,7 @@ \pnum \tcode{true} if the type has a representation for a signaling ``Not a Number''. \begin{footnote} -Required by LIA-1. +Required by ISO/IEC 10967-1:2012. \end{footnote} \pnum @@ -1369,7 +1475,7 @@ \pnum Representation of positive infinity, if available. \begin{footnote} -Required by LIA-1. +Required by ISO/IEC 10967-1:2012. \end{footnote} \pnum @@ -1388,7 +1494,7 @@ \pnum Representation of a quiet ``Not a Number'', if available. \begin{footnote} -Required by LIA-1. +Required by ISO/IEC 10967-1:2012. \end{footnote} \pnum @@ -1407,7 +1513,7 @@ \pnum Representation of a signaling ``Not a Number'', if available. \begin{footnote} -Required by LIA-1. +Required by ISO/IEC 10967-1:2012. \end{footnote} \pnum @@ -1427,7 +1533,7 @@ \pnum Minimum positive subnormal value, if available. \begin{footnote} -Required by LIA-1. +Required by ISO/IEC 10967-1:2012. \end{footnote} Otherwise, minimum positive normalized value. @@ -1442,9 +1548,9 @@ \begin{itemdescr} \pnum -\tcode{true} if and only if the type adheres to ISO/IEC/IEEE 60559. +\tcode{true} if and only if the type adheres to \IsoFloatUndated{}. \begin{footnote} -ISO/IEC/IEEE 60559:2020 is the same as IEEE 754-2019. +\IsoFloatUndated{}:2020 is the same as IEEE 754-2019. \end{footnote} \begin{note} The value is \tcode{true} for any of the types @@ -1465,7 +1571,7 @@ \pnum \tcode{true} if the set of values representable by the type is finite. \begin{footnote} -Required by LIA-1. +Required by ISO/IEC 10967-1:2012. \end{footnote} \begin{note} All fundamental types\iref{basic.fundamental} are bounded. This member would be \tcode{false} for arbitrary @@ -1485,7 +1591,7 @@ \pnum \tcode{true} if the type is modulo. \begin{footnote} -Required by LIA-1. +Required by ISO/IEC 10967-1:2012. \end{footnote} A type is modulo if, for any operation involving \tcode{+}, \tcode{-}, or \tcode{*} on values of that type whose result would fall outside the range @@ -1514,7 +1620,7 @@ if, at the start of the program, there exists a value of the type that would cause an arithmetic operation using that value to trap. \begin{footnote} -Required by LIA-1. +Required by ISO/IEC 10967-1:2012. \end{footnote} \pnum @@ -1532,8 +1638,8 @@ if tinyness is detected before rounding. \begin{footnote} Refer to -ISO/IEC/IEEE 60559. -Required by LIA-1. +\IsoFloatUndated{}. +Required by ISO/IEC 10967-1:2012. \end{footnote} \pnum @@ -1550,7 +1656,7 @@ The rounding style for the type. \begin{footnote} Equivalent to \tcode{FLT_ROUNDS}. -Required by LIA-1. +Required by ISO/IEC 10967-1:2012. \end{footnote} \pnum @@ -1603,9 +1709,9 @@ static constexpr int max_exponent = +128; static constexpr int max_exponent10 = + 38; - static constexpr bool has_infinity = true; - static constexpr bool has_quiet_NaN = true; - static constexpr bool has_signaling_NaN = true; + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = true; static constexpr float infinity() noexcept { return @\textit{value}@; } static constexpr float quiet_NaN() noexcept { return @\textit{value}@; } @@ -1676,53 +1782,48 @@ \rSec2[climits.syn]{Header \tcode{} synopsis} \indexheader{climits}% -\indexlibraryglobal{CHAR_BIT}% -\indexlibraryglobal{SCHAR_MIN}% -\indexlibraryglobal{SCHAR_MAX}% -\indexlibraryglobal{UCHAR_MAX}% -\indexlibraryglobal{CHAR_MIN}% -\indexlibraryglobal{CHAR_MAX}% -\indexlibraryglobal{MB_LEN_MAX}% -\indexlibraryglobal{SHRT_MIN}% -\indexlibraryglobal{SHRT_MAX}% -\indexlibraryglobal{USHRT_MAX}% -\indexlibraryglobal{INT_MIN}% -\indexlibraryglobal{INT_MAX}% -\indexlibraryglobal{UINT_MAX}% -\indexlibraryglobal{LONG_MIN}% -\indexlibraryglobal{LONG_MAX}% -\indexlibraryglobal{ULONG_MAX}% -\indexlibraryglobal{LLONG_MIN}% -\indexlibraryglobal{LLONG_MAX}% -\indexlibraryglobal{ULLONG_MAX}% \begin{codeblock} // all freestanding -#define CHAR_BIT @\seebelow@ -#define SCHAR_MIN @\seebelow@ -#define SCHAR_MAX @\seebelow@ -#define UCHAR_MAX @\seebelow@ -#define CHAR_MIN @\seebelow@ -#define CHAR_MAX @\seebelow@ -#define MB_LEN_MAX @\seebelow@ -#define SHRT_MIN @\seebelow@ -#define SHRT_MAX @\seebelow@ -#define USHRT_MAX @\seebelow@ -#define INT_MIN @\seebelow@ -#define INT_MAX @\seebelow@ -#define UINT_MAX @\seebelow@ -#define LONG_MIN @\seebelow@ -#define LONG_MAX @\seebelow@ -#define ULONG_MAX @\seebelow@ -#define LLONG_MIN @\seebelow@ -#define LLONG_MAX @\seebelow@ -#define ULLONG_MAX @\seebelow@ +#define @\libmacro{BOOL_WIDTH}@ @\seebelow@ +#define @\libmacro{CHAR_BIT}@ @\seebelow@ +#define @\libmacro{CHAR_WIDTH}@ @\seebelow@ +#define @\libmacro{SCHAR_WIDTH}@ @\seebelow@ +#define @\libmacro{UCHAR_WIDTH}@ @\seebelow@ +#define @\libmacro{USHRT_WIDTH}@ @\seebelow@ +#define @\libmacro{SHRT_WIDTH}@ @\seebelow@ +#define @\libmacro{UINT_WIDTH}@ @\seebelow@ +#define @\libmacro{INT_WIDTH}@ @\seebelow@ +#define @\libmacro{ULONG_WIDTH}@ @\seebelow@ +#define @\libmacro{LONG_WIDTH}@ @\seebelow@ +#define @\libmacro{ULLONG_WIDTH}@ @\seebelow@ +#define @\libmacro{LLONG_WIDTH}@ @\seebelow@ +#define @\libmacro{SCHAR_MIN}@ @\seebelow@ +#define @\libmacro{SCHAR_MAX}@ @\seebelow@ +#define @\libmacro{UCHAR_MAX}@ @\seebelow@ +#define @\libmacro{CHAR_MIN}@ @\seebelow@ +#define @\libmacro{CHAR_MAX}@ @\seebelow@ +#define @\libmacro{MB_LEN_MAX}@ @\seebelow@ +#define @\libmacro{SHRT_MIN}@ @\seebelow@ +#define @\libmacro{SHRT_MAX}@ @\seebelow@ +#define @\libmacro{USHRT_MAX}@ @\seebelow@ +#define @\libmacro{INT_MIN}@ @\seebelow@ +#define @\libmacro{INT_MAX}@ @\seebelow@ +#define @\libmacro{UINT_MAX}@ @\seebelow@ +#define @\libmacro{LONG_MIN}@ @\seebelow@ +#define @\libmacro{LONG_MAX}@ @\seebelow@ +#define @\libmacro{ULONG_MAX}@ @\seebelow@ +#define @\libmacro{LLONG_MIN}@ @\seebelow@ +#define @\libmacro{LLONG_MAX}@ @\seebelow@ +#define @\libmacro{ULLONG_MAX}@ @\seebelow@ \end{codeblock} \pnum The header \libheader{climits} defines all macros the same as -the C standard library header \libheader{limits.h}. +the C standard library header \libheader{limits.h}, +except that it does not define the macro \tcode{BITINT_MAXWIDTH}. \begin{note} -Except for \tcode{CHAR_BIT} and \tcode{MB_LEN_MAX}, a macro referring to +Except for the \tcode{WIDTH} macros, \tcode{CHAR_BIT}, and \tcode{MB_LEN_MAX}, +a macro referring to an integer type \tcode{T} defines a constant whose type is the promoted type of \tcode{T}\iref{conv.prom}. \end{note} @@ -1732,88 +1833,51 @@ \rSec2[cfloat.syn]{Header \tcode{} synopsis} \indexheader{cfloat}% -\indexlibraryglobal{DBL_DECIMAL_DIG}% -\indexlibraryglobal{DBL_DIG}% -\indexlibraryglobal{DBL_EPSILON}% -\indexlibraryglobal{DBL_HAS_SUBNORM}% -\indexlibraryglobal{DBL_MANT_DIG}% -\indexlibraryglobal{DBL_MAX}% -\indexlibraryglobal{DBL_MAX_10_EXP}% -\indexlibraryglobal{DBL_MAX_EXP}% -\indexlibraryglobal{DBL_MIN}% -\indexlibraryglobal{DBL_MIN_10_EXP}% -\indexlibraryglobal{DBL_MIN_EXP}% -\indexlibraryglobal{DBL_TRUE_MIN}% -\indexlibraryglobal{DECIMAL_DIG}% -\indexlibraryglobal{FLT_DECIMAL_DIG}% -\indexlibraryglobal{FLT_DIG}% -\indexlibraryglobal{FLT_EPSILON}% -\indexlibraryglobal{FLT_EVAL_METHOD}% -\indexlibraryglobal{FLT_HAS_SUBNORM}% -\indexlibraryglobal{FLT_MANT_DIG}% -\indexlibraryglobal{FLT_MAX}% -\indexlibraryglobal{FLT_MAX_10_EXP}% -\indexlibraryglobal{FLT_MAX_EXP}% -\indexlibraryglobal{FLT_MIN}% -\indexlibraryglobal{FLT_MIN_10_EXP}% -\indexlibraryglobal{FLT_MIN_EXP}% -\indexlibraryglobal{FLT_RADIX}% -\indexlibraryglobal{FLT_ROUNDS}% -\indexlibraryglobal{FLT_TRUE_MIN}% -\indexlibraryglobal{LDBL_DECIMAL_DIG}% -\indexlibraryglobal{LDBL_DIG}% -\indexlibraryglobal{LDBL_EPSILON}% -\indexlibraryglobal{LDBL_HAS_SUBNORM}% -\indexlibraryglobal{LDBL_MANT_DIG}% -\indexlibraryglobal{LDBL_MAX}% -\indexlibraryglobal{LDBL_MAX_10_EXP}% -\indexlibraryglobal{LDBL_MAX_EXP}% -\indexlibraryglobal{LDBL_MIN}% -\indexlibraryglobal{LDBL_MIN_10_EXP}% -\indexlibraryglobal{LDBL_MIN_EXP}% -\indexlibraryglobal{LDBL_TRUE_MIN}% \begin{codeblock} // all freestanding -#define FLT_ROUNDS @\seebelow@ -#define FLT_EVAL_METHOD @\seebelow@ -#define FLT_HAS_SUBNORM @\seebelow@ -#define DBL_HAS_SUBNORM @\seebelow@ -#define LDBL_HAS_SUBNORM @\seebelow@ -#define FLT_RADIX @\seebelow@ -#define FLT_MANT_DIG @\seebelow@ -#define DBL_MANT_DIG @\seebelow@ -#define LDBL_MANT_DIG @\seebelow@ -#define FLT_DECIMAL_DIG @\seebelow@ -#define DBL_DECIMAL_DIG @\seebelow@ -#define LDBL_DECIMAL_DIG @\seebelow@ -#define DECIMAL_DIG @\seebelow@ -#define FLT_DIG @\seebelow@ -#define DBL_DIG @\seebelow@ -#define LDBL_DIG @\seebelow@ -#define FLT_MIN_EXP @\seebelow@ -#define DBL_MIN_EXP @\seebelow@ -#define LDBL_MIN_EXP @\seebelow@ -#define FLT_MIN_10_EXP @\seebelow@ -#define DBL_MIN_10_EXP @\seebelow@ -#define LDBL_MIN_10_EXP @\seebelow@ -#define FLT_MAX_EXP @\seebelow@ -#define DBL_MAX_EXP @\seebelow@ -#define LDBL_MAX_EXP @\seebelow@ -#define FLT_MAX_10_EXP @\seebelow@ -#define DBL_MAX_10_EXP @\seebelow@ -#define LDBL_MAX_10_EXP @\seebelow@ -#define FLT_MAX @\seebelow@ -#define DBL_MAX @\seebelow@ -#define LDBL_MAX @\seebelow@ -#define FLT_EPSILON @\seebelow@ -#define DBL_EPSILON @\seebelow@ -#define LDBL_EPSILON @\seebelow@ -#define FLT_MIN @\seebelow@ -#define DBL_MIN @\seebelow@ -#define LDBL_MIN @\seebelow@ -#define FLT_TRUE_MIN @\seebelow@ -#define DBL_TRUE_MIN @\seebelow@ -#define LDBL_TRUE_MIN @\seebelow@ +#define __STDC_VERSION_FLOAT_H__ 202311L + +#define @\libmacro{FLT_ROUNDS}@ @\seebelow@ +#define @\libmacro{FLT_EVAL_METHOD}@ @\seebelow@ +#define @\libmacro{FLT_RADIX}@ @\seebelow@ +#define @\libmacro{INFINITY}@ @\seebelow@ +#define @\libmacro{NAN}@ @\seebelow@ +#define @\libmacro{FLT_SNAN}@ @\seebelow@ +#define @\libmacro{DBL_SNAN}@ @\seebelow@ +#define @\libmacro{LDBL_SNAN}@ @\seebelow@ +#define @\libmacro{FLT_MANT_DIG}@ @\seebelow@ +#define @\libmacro{DBL_MANT_DIG}@ @\seebelow@ +#define @\libmacro{LDBL_MANT_DIG}@ @\seebelow@ +#define @\libmacro{FLT_DECIMAL_DIG}@ @\seebelow@ +#define @\libmacro{DBL_DECIMAL_DIG}@ @\seebelow@ +#define @\libmacro{LDBL_DECIMAL_DIG}@ @\seebelow@ +#define @\libmacro{FLT_DIG}@ @\seebelow@ +#define @\libmacro{DBL_DIG}@ @\seebelow@ +#define @\libmacro{LDBL_DIG}@ @\seebelow@ +#define @\libmacro{FLT_MIN_EXP}@ @\seebelow@ +#define @\libmacro{DBL_MIN_EXP}@ @\seebelow@ +#define @\libmacro{LDBL_MIN_EXP}@ @\seebelow@ +#define @\libmacro{FLT_MIN_10_EXP}@ @\seebelow@ +#define @\libmacro{DBL_MIN_10_EXP}@ @\seebelow@ +#define @\libmacro{LDBL_MIN_10_EXP}@ @\seebelow@ +#define @\libmacro{FLT_MAX_EXP}@ @\seebelow@ +#define @\libmacro{DBL_MAX_EXP}@ @\seebelow@ +#define @\libmacro{LDBL_MAX_EXP}@ @\seebelow@ +#define @\libmacro{FLT_MAX_10_EXP}@ @\seebelow@ +#define @\libmacro{DBL_MAX_10_EXP}@ @\seebelow@ +#define @\libmacro{LDBL_MAX_10_EXP}@ @\seebelow@ +#define @\libmacro{FLT_MAX}@ @\seebelow@ +#define @\libmacro{DBL_MAX}@ @\seebelow@ +#define @\libmacro{LDBL_MAX}@ @\seebelow@ +#define @\libmacro{FLT_EPSILON}@ @\seebelow@ +#define @\libmacro{DBL_EPSILON}@ @\seebelow@ +#define @\libmacro{LDBL_EPSILON}@ @\seebelow@ +#define @\libmacro{FLT_MIN}@ @\seebelow@ +#define @\libmacro{DBL_MIN}@ @\seebelow@ +#define @\libmacro{LDBL_MIN}@ @\seebelow@ +#define @\libmacro{FLT_TRUE_MIN}@ @\seebelow@ +#define @\libmacro{DBL_TRUE_MIN}@ @\seebelow@ +#define @\libmacro{LDBL_TRUE_MIN}@ @\seebelow@ \end{codeblock} \pnum @@ -1860,8 +1924,38 @@ \indexlibraryglobal{uint_least64_t}% \indexlibraryglobal{uintmax_t}% \indexlibraryglobal{uintptr_t}% +\indexlibraryglobal{INTN_MIN}% +\indexlibraryglobal{INTN_MAX}% +\indexlibraryglobal{UINTN_MAX}% +\indexlibraryglobal{INT_FASTN_MIN}% +\indexlibraryglobal{INT_FASTN_MAX}% +\indexlibraryglobal{UINT_FASTN_MAX}% +\indexlibraryglobal{INT_LEASTN_MIN}% +\indexlibraryglobal{INT_LEASTN_MAX}% +\indexlibraryglobal{UINT_LEASTN_MAX}% +\indexlibraryglobal{INTMAX_MIN}% +\indexlibraryglobal{INTMAX_MAX}% +\indexlibraryglobal{UINTMAX_MAX}% +\indexlibraryglobal{INTPTR_MIN}% +\indexlibraryglobal{INTPTR_MAX}% +\indexlibraryglobal{UINTPTR_MAX}% +\indexlibraryglobal{PTRDIFF_MIN}% +\indexlibraryglobal{PTRDIFF_MAX}% +\indexlibraryglobal{SIZE_MAX}% +\indexlibraryglobal{SIG_ATOMIC_MIN}% +\indexlibraryglobal{SIG_ATOMIC_MAX}% +\indexlibraryglobal{WCHAR_MAX}% +\indexlibraryglobal{WCHAR_MIN}% +\indexlibraryglobal{WINT_MIN}% +\indexlibraryglobal{WINT_MAX}% +\indexlibraryglobal{INTN_C}% +\indexlibraryglobal{UINTN_C}% +\indexlibraryglobal{INTMAX_C}% +\indexlibraryglobal{UINTMAX_C}% \begin{codeblock} // all freestanding +#define __STDC_VERSION_STDINT_H__ 202311L + namespace std { using int8_t = @\textit{signed integer type}@; // optional using int16_t = @\textit{signed integer type}@; // optional @@ -1906,50 +2000,68 @@ using uintptr_t = @\textit{unsigned integer type}@; // optional } -#define INT@\placeholdernc{N}@_MIN @\seebelow@ -#define INT@\placeholdernc{N}@_MAX @\seebelow@ -#define UINT@\placeholdernc{N}@_MAX @\seebelow@ - -#define INT_FAST@\placeholdernc{N}@_MIN @\seebelow@ -#define INT_FAST@\placeholdernc{N}@_MAX @\seebelow@ -#define UINT_FAST@\placeholdernc{N}@_MAX @\seebelow@ - -#define INT_LEAST@\placeholdernc{N}@_MIN @\seebelow@ -#define INT_LEAST@\placeholdernc{N}@_MAX @\seebelow@ -#define UINT_LEAST@\placeholdernc{N}@_MAX @\seebelow@ - -#define INTMAX_MIN @\seebelow@ -#define INTMAX_MAX @\seebelow@ -#define UINTMAX_MAX @\seebelow@ - -#define INTPTR_MIN @\seebelow@ // optional -#define INTPTR_MAX @\seebelow@ // optional -#define UINTPTR_MAX @\seebelow@ // optional - -#define PTRDIFF_MIN @\seebelow@ -#define PTRDIFF_MAX @\seebelow@ -#define SIZE_MAX @\seebelow@ - -#define SIG_ATOMIC_MIN @\seebelow@ -#define SIG_ATOMIC_MAX @\seebelow@ - -#define WCHAR_MIN @\seebelow@ -#define WCHAR_MAX @\seebelow@ - -#define WINT_MIN @\seebelow@ -#define WINT_MAX @\seebelow@ - -#define INT@\placeholdernc{N}@_C(value) @\seebelow@ -#define UINT@\placeholdernc{N}@_C(value) @\seebelow@ -#define INTMAX_C(value) @\seebelow@ -#define UINTMAX_C(value) @\seebelow@ +#define INT@\placeholdernc{N}@_MIN @\seebelow@ +#define INT@\placeholdernc{N}@_MAX @\seebelow@ +#define UINT@\placeholdernc{N}@_MAX @\seebelow@ +#define INT@\placeholdernc{N}@_WIDTH @\seebelow@ +#define UINT@\placeholdernc{N}@_WIDTH @\seebelow@ + +#define INT_FAST@\placeholdernc{N}@_MIN @\seebelow@ +#define INT_FAST@\placeholdernc{N}@_MAX @\seebelow@ +#define UINT_FAST@\placeholdernc{N}@_MAX @\seebelow@ +#define INT_FAST@\placeholdernc{N}@_WIDTH @\seebelow@ +#define UINT_FAST@\placeholdernc{N}@_WIDTH @\seebelow@ + +#define INT_LEAST@\placeholdernc{N}@_MIN @\seebelow@ +#define INT_LEAST@\placeholdernc{N}@_MAX @\seebelow@ +#define UINT_LEAST@\placeholdernc{N}@_MAX @\seebelow@ +#define INT_LEAST@\placeholdernc{N}@_WIDTH @\seebelow@ +#define UINT_LEAST@\placeholdernc{N}@_WIDTH @\seebelow@ + +#define INTMAX_MIN @\seebelow@ +#define INTMAX_MAX @\seebelow@ +#define UINTMAX_MAX @\seebelow@ +#define INTMAX_WIDTH @\seebelow@ +#define UINTMAX_WIDTH @\seebelow@ + +#define INTPTR_MIN @\seebelow@ // optional +#define INTPTR_MAX @\seebelow@ // optional +#define UINTPTR_MAX @\seebelow@ // optional +#define INTPTR_WIDTH @\seebelow@ // optional +#define UINTPTR_WIDTH @\seebelow@ // optional + +#define PTRDIFF_MIN @\seebelow@ +#define PTRDIFF_MAX @\seebelow@ +#define PTRDIFF_WIDTH @\seebelow@ +#define SIZE_MAX @\seebelow@ +#define SIZE_WIDTH @\seebelow@ + +#define SIG_ATOMIC_MIN @\seebelow@ +#define SIG_ATOMIC_MAX @\seebelow@ +#define SIG_ATOMIC_WIDTH @\seebelow@ + +#define WCHAR_MIN @\seebelow@ +#define WCHAR_MAX @\seebelow@ +#define WCHAR_WIDTH @\seebelow@ + +#define WINT_MIN @\seebelow@ +#define WINT_MAX @\seebelow@ +#define WINT_WIDTH @\seebelow@ + +#define INT@\placeholdernc{N}@_C(value) @\seebelow@ +#define UINT@\placeholdernc{N}@_C(value) @\seebelow@ +#define INTMAX_C(value) @\seebelow@ +#define UINTMAX_C(value) @\seebelow@ \end{codeblock} \pnum The header defines all types and macros the same as the C standard library header \libheader{stdint.h}. +The types denoted by \tcode{intmax_t} and \tcode{uintmax_t} +are not required to be able to represent all values of extended integer types +wider than \tcode{long long} and \tcode{unsigned long long}, respectively. -\xrefc{7.20} +\xrefc{7.22} \pnum All types that use the placeholder \placeholder{N} @@ -2025,7 +2137,7 @@ \pnum \remarks -The program is terminated without executing destructors for objects of automatic, +The program is terminated without executing destructors for objects with automatic, thread, or static storage duration and without calling functions passed to \tcode{atexit()}\iref{basic.start.term}. \indextext{signal-safe!\idxcode{_Exit}}% @@ -2216,7 +2328,7 @@ when the functions registered with \tcode{at_quick_exit} are. \end{itemdescr} -\xrefc{7.22.4} +\xrefc{7.24.4} \rSec1[support.dynamic]{Dynamic memory management} @@ -2256,7 +2368,7 @@ new_handler set_new_handler(new_handler new_p) noexcept; // \ref{ptr.launder}, pointer optimization barrier - template [[nodiscard]] constexpr T* launder(T* p) noexcept; + template constexpr T* launder(T* p) noexcept; // \ref{hardware.interference}, hardware interference size inline constexpr size_t hardware_destructive_interference_size = @\impdef{}@; @@ -2264,11 +2376,10 @@ } // \ref{new.delete}, storage allocation and deallocation -[[nodiscard]] void* operator new(std::size_t size); -[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment); -[[nodiscard]] void* operator new(std::size_t size, const std::nothrow_t&) noexcept; -[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment, - const std::nothrow_t&) noexcept; +void* operator new(std::size_t size); +void* operator new(std::size_t size, std::align_val_t alignment); +void* operator new(std::size_t size, const std::nothrow_t&) noexcept; +void* operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept; void operator delete(void* ptr) noexcept; void operator delete(void* ptr, std::size_t size) noexcept; @@ -2277,11 +2388,11 @@ void operator delete(void* ptr, const std::nothrow_t&) noexcept; void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept; -[[nodiscard]] void* operator new[](std::size_t size); -[[nodiscard]] void* operator new[](std::size_t size, std::align_val_t alignment); -[[nodiscard]] void* operator new[](std::size_t size, const std::nothrow_t&) noexcept; -[[nodiscard]] void* operator new[](std::size_t size, std::align_val_t alignment, - const std::nothrow_t&) noexcept; +void* operator new[](std::size_t size); +void* operator new[](std::size_t size, std::align_val_t alignment); +void* operator new[](std::size_t size, const std::nothrow_t&) noexcept; +void* operator new[](std::size_t size, std::align_val_t alignment, + const std::nothrow_t&) noexcept; void operator delete[](void* ptr) noexcept; void operator delete[](void* ptr, std::size_t size) noexcept; @@ -2290,8 +2401,8 @@ void operator delete[](void* ptr, const std::nothrow_t&) noexcept; void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept; -[[nodiscard]] void* operator new (std::size_t size, void* ptr) noexcept; -[[nodiscard]] void* operator new[](std::size_t size, void* ptr) noexcept; +constexpr void* operator new (std::size_t size, void* ptr) noexcept; +constexpr void* operator new[](std::size_t size, void* ptr) noexcept; void operator delete (void* ptr, void*) noexcept; void operator delete[](void* ptr, void*) noexcept; \end{codeblock} @@ -2328,18 +2439,12 @@ If any of the default versions of the replaceable global allocation functions meet the requirements of a hosted implementation, they all should. -\newcommand{\replaceabledesc}[1]{% -A \Cpp{} program may define functions with #1 of these function signatures, -and thereby displace the default versions defined by the -\Cpp{} standard library.% -} - \rSec3[new.delete.single]{Single-object forms} \indexlibrarymember{new}{operator}% \begin{itemdecl} -[[nodiscard]] void* operator new(std::size_t size); -[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment); +void* operator new(std::size_t size); +void* operator new(std::size_t size, std::align_val_t alignment); \end{itemdecl} \begin{itemdescr} @@ -2354,10 +2459,6 @@ The second form is called for a type with new-extended alignment, and the first form is called otherwise. -\pnum -\replaceable -\replaceabledesc{either} - \pnum \required Return a non-null pointer to suitably aligned storage\iref{basic.stc.dynamic}, @@ -2394,13 +2495,16 @@ \tcode{new_handler} function does not return. \end{itemize} + +\pnum +\remarks +This function is replaceable\iref{dcl.fct.def.replace}. \end{itemdescr} \indexlibrarymember{new}{operator}% \begin{itemdecl} -[[nodiscard]] void* operator new(std::size_t size, const std::nothrow_t&) noexcept; -[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment, - const std::nothrow_t&) noexcept; +void* operator new(std::size_t size, const std::nothrow_t&) noexcept; +void* operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept; \end{itemdecl} \begin{itemdescr} @@ -2413,10 +2517,6 @@ \tcode{bad_alloc} exception. -\pnum -\replaceable -\replaceabledesc{either} - \pnum \required Return a non-null pointer to suitably aligned storage\iref{basic.stc.dynamic}, @@ -2444,6 +2544,10 @@ T* p2 = new(nothrow) T; // returns \keyword{nullptr} if it fails \end{codeblock} \end{example} + +\pnum +\remarks +This function is replaceable\iref{dcl.fct.def.replace}. \end{itemdescr} \indexlibrarymember{delete}{operator}% @@ -2486,20 +2590,6 @@ \grammarterm{delete-expression}\iref{expr.delete} to render the value of \tcode{ptr} invalid. -\pnum -\replaceable -\replaceabledesc{any} -If a function without a \tcode{size} parameter is defined, -the program should also define -the corresponding function with a \tcode{size} parameter. -If a function with a \tcode{size} parameter is defined, -the program shall also define -the corresponding version without the \tcode{size} parameter. -\begin{note} -The default behavior below might change in the future, which will require -replacing both deallocation functions when replacing the allocation function. -\end{note} - \pnum \required A call to an \tcode{operator delete} @@ -2520,7 +2610,7 @@ forward their other parameters to the corresponding function without a \tcode{size} parameter. \begin{note} -See the note in the above \replaceable paragraph. +See the note in the below \remarks paragraph. \end{note} \pnum @@ -2542,6 +2632,22 @@ or \tcode{realloc}, declared in \libheaderref{cstdlib}. +This function is replaceable\iref{dcl.fct.def.replace}. +If a replacement function +without a \tcode{size} parameter +is defined by the program, +the program should also define the corresponding +function with a \tcode{size} parameter. +If a replacement function +with a \tcode{size} parameter +is defined by the program, +the program shall also define the corresponding +version without the \tcode{size} parameter. +\begin{note} +The default behavior above might change in the future, +which will require replacing both deallocation functions +when replacing the allocation function. +\end{note} \end{itemdescr} \indexlibrarymember{delete}{operator}% @@ -2580,23 +2686,23 @@ when the constructor invoked from a nothrow placement version of the \grammarterm{new-expression} throws an exception. -\pnum -\replaceable -\replaceabledesc{either} - \pnum \default Calls \tcode{operator delete(ptr)}, or \tcode{operator delete(ptr, alignment)}, respectively. + +\pnum +\remarks +This function is replaceable\iref{dcl.fct.def.replace}. \end{itemdescr} \rSec3[new.delete.array]{Array forms} \indexlibrarymember{new}{operator}% \begin{itemdecl} -[[nodiscard]] void* operator new[](std::size_t size); -[[nodiscard]] void* operator new[](std::size_t size, std::align_val_t alignment); +void* operator new[](std::size_t size); +void* operator new[](std::size_t size, std::align_val_t alignment); \end{itemdecl} \begin{itemdescr} @@ -2628,10 +2734,6 @@ to obtain space to store supplemental information. \end{footnote} -\pnum -\replaceable -\replaceabledesc{either} - \pnum \required Same as for @@ -2645,13 +2747,16 @@ or \tcode{operator new(size, alignment)}, respectively. + +\pnum +\remarks +This function is replaceable\iref{dcl.fct.def.replace}. \end{itemdescr} \indexlibrarymember{new}{operator}% \begin{itemdecl} -[[nodiscard]] void* operator new[](std::size_t size, const std::nothrow_t&) noexcept; -[[nodiscard]] void* operator new[](std::size_t size, std::align_val_t alignment, - const std::nothrow_t&) noexcept; +void* operator new[](std::size_t size, const std::nothrow_t&) noexcept; +void* operator new[](std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept; \end{itemdecl} \begin{itemdescr} @@ -2664,10 +2769,6 @@ \tcode{bad_alloc} exception. -\pnum -\replaceable -\replaceabledesc{either} - \pnum \required Return a non-null pointer to suitably aligned storage\iref{basic.stc.dynamic}, @@ -2687,6 +2788,10 @@ If the call returns normally, returns the result of that call. Otherwise, returns a null pointer. + +\pnum +\remarks +This function is replaceable\iref{dcl.fct.def.replace}. \end{itemdescr} \indexlibrarymember{delete}{operator}% @@ -2729,20 +2834,6 @@ \grammarterm{delete-expression} to render the value of \tcode{ptr} invalid. -\pnum -\replaceable -\replaceabledesc{any} -If a function without a \tcode{size} parameter is defined, -the program should also define -the corresponding function with a \tcode{size} parameter. -If a function with a \tcode{size} parameter is defined, -the program shall also define -the corresponding version without the \tcode{size} parameter. -\begin{note} -The default behavior below might change in the future, which will require -replacing both deallocation functions when replacing the allocation function. -\end{note} - \pnum \required A call to an \tcode{operator delete[]} @@ -2765,6 +2856,25 @@ The functions that do not have a \tcode{size} parameter forward their parameters to the corresponding \tcode{operator delete} (single-object) function. + +\pnum +\remarks +This function is replaceable\iref{dcl.fct.def.replace}. +If a replacement function +without a \tcode{size} parameter +is defined by the program, +the program should also define the corresponding +function with a \tcode{size} parameter. +If a replacement function +with a \tcode{size} parameter +is defined by the program, +the program shall also define the corresponding +version without the \tcode{size} parameter. +\begin{note} +The default behavior above might change in the future, +which will require replacing both deallocation functions +when replacing the allocation function. +\end{note} \end{itemdescr} \indexlibrarymember{delete}{operator}% @@ -2803,15 +2913,15 @@ when the constructor invoked from a nothrow placement version of the array \grammarterm{new-expression} throws an exception. -\pnum -\replaceable -\replaceabledesc{either} - \pnum \default Calls \tcode{operator delete[](ptr)}, or \tcode{operator delete[](ptr, alignment)}, respectively. + +\pnum +\remarks +This function is replaceable\iref{dcl.fct.def.replace}. \end{itemdescr} \rSec3[new.delete.placement]{Non-allocating forms} @@ -2824,7 +2934,7 @@ \indexlibrarymember{new}{operator}% \begin{itemdecl} -[[nodiscard]] void* operator new(std::size_t size, void* ptr) noexcept; +constexpr void* operator new(std::size_t size, void* ptr) noexcept; \end{itemdecl} \begin{itemdescr} @@ -2849,7 +2959,7 @@ \indexlibrarymember{new}{operator}% \begin{itemdecl} -[[nodiscard]] void* operator new[](std::size_t size, void* ptr) noexcept; +constexpr void* operator new[](std::size_t size, void* ptr) noexcept; \end{itemdecl} \begin{itemdescr} @@ -2926,7 +3036,7 @@ class bad_alloc : public exception { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -2939,7 +3049,7 @@ \indexlibrarymember{what}{bad_alloc}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -2957,7 +3067,7 @@ class bad_array_new_length : public bad_alloc { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -2970,7 +3080,7 @@ \indexlibrarymember{what}{bad_array_new_length}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3056,7 +3166,7 @@ \indexlibraryglobal{launder}% \begin{itemdecl} -template [[nodiscard]] constexpr T* launder(T* p) noexcept; +template constexpr T* launder(T* p) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3165,12 +3275,16 @@ \rSec2[support.rtti.general]{General} \pnum -The header \libheaderdef{typeinfo} defines a +The header \libheaderref{typeinfo} defines a type associated with type information generated by the implementation. It also defines two types for reporting dynamic type identification errors. +The header \libheaderrefx{typeindex}{type.index.synopsis} defines +a wrapper type for use as an index type in associative containers\iref{associative} +and in unordered associative containers\iref{unord}. \rSec2[typeinfo.syn]{Header \tcode{} synopsis} +\indexheader{typeinfo}% \indexlibraryglobal{type_info}% \indexlibraryglobal{bad_cast}% \indexlibraryglobal{bad_typeid}% @@ -3196,8 +3310,8 @@ size_t hash_code() const noexcept; const char* name() const noexcept; - type_info(const type_info&) = delete; // cannot be copied - type_info& operator=(const type_info&) = delete; // cannot be copied + type_info(const type_info&) = delete; + type_info& operator=(const type_info&) = delete; }; } \end{codeblock} @@ -3291,7 +3405,7 @@ class bad_cast : public exception { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -3307,7 +3421,7 @@ \indexlibrarymember{what}{bad_cast}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3325,7 +3439,7 @@ class bad_typeid : public exception { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -3341,7 +3455,7 @@ \indexlibrarymember{what}{bad_typeid}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3350,6 +3464,166 @@ An \impldef{return value of \tcode{bad_typeid::what}} \ntbs{}. \end{itemdescr} +\rSec2[type.index.synopsis]{Header \tcode{} synopsis} + +\indexheader{typeindex}% +\begin{codeblock} +#include // see \ref{compare.syn} + +namespace std { + class type_index; + template struct hash; + template<> struct hash; +} +\end{codeblock} + +\rSec2[type.index]{Class \tcode{type_index}} + +\indexlibraryglobal{type_index}% +\begin{codeblock} +namespace std { + class type_index { + public: + type_index(const type_info& rhs) noexcept; + bool operator==(const type_index& rhs) const noexcept; + bool operator< (const type_index& rhs) const noexcept; + bool operator> (const type_index& rhs) const noexcept; + bool operator<=(const type_index& rhs) const noexcept; + bool operator>=(const type_index& rhs) const noexcept; + strong_ordering operator<=>(const type_index& rhs) const noexcept; + size_t hash_code() const noexcept; + const char* name() const noexcept; + + private: + const type_info* target; // \expos + // Note that the use of a pointer here, rather than a reference, + // means that the default copy/move constructor and assignment + // operators will be provided and work as expected. + }; +} +\end{codeblock} + +\pnum +The class \tcode{type_index} provides a simple wrapper for +\tcode{type_info} which can be used as an index type in associative +containers\iref{associative} and in unordered associative +containers\iref{unord}. + +\indexlibraryctor{type_index}% +\begin{itemdecl} +type_index(const type_info& rhs) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{type_index} object, the equivalent of \tcode{target = \&rhs}. +\end{itemdescr} + +\indexlibrarymember{operator==}{type_index}% +\begin{itemdecl} +bool operator==(const type_index& rhs) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{*target == *rhs.target}. +\end{itemdescr} + +\indexlibrarymember{operator<}{type_index}% +\begin{itemdecl} +bool operator<(const type_index& rhs) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{target->before(*rhs.target)}. +\end{itemdescr} + +\indexlibrarymember{operator>}{type_index}% +\begin{itemdecl} +bool operator>(const type_index& rhs) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{rhs.target->before(*target)}. +\end{itemdescr} + +\indexlibrarymember{operator<=}{type_index}% +\begin{itemdecl} +bool operator<=(const type_index& rhs) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!rhs.target->before(*target)}. +\end{itemdescr} + +\indexlibrarymember{operator>=}{type_index}% +\begin{itemdecl} +bool operator>=(const type_index& rhs) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!target->before(*rhs.target)}. +\end{itemdescr} + +\indexlibrarymember{operator<=>}{type_index}% +\begin{itemdecl} +strong_ordering operator<=>(const type_index& rhs) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (*target == *rhs.target) return strong_ordering::equal; +if (target->before(*rhs.target)) return strong_ordering::less; +return strong_ordering::greater; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{hash_code}{type_index}% +\begin{itemdecl} +size_t hash_code() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{target->hash_code()}. +\end{itemdescr} + +\indexlibrarymember{name}{type_index}% +\begin{itemdecl} +const char* name() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{target->name()}. +\end{itemdescr} + +\indexlibrarymember{hash}{type_index}% +\begin{itemdecl} +template<> struct hash; +\end{itemdecl} + +\begin{itemdescr} +\pnum +For an object \tcode{index} of type \tcode{type_index}, +\tcode{hash()(index)} shall evaluate to the same result as \tcode{index.hash_code()}. +\end{itemdescr} + \rSec1[support.srcloc]{Source location} \rSec2[source.location.syn]{Header \tcode{} synopsis} @@ -3486,7 +3760,7 @@ \pnum \remarks Any call to \tcode{current} that appears -as a default member initializer\iref{class.mem}, or +as a default member initializer\iref{class.mem.general}, or as a subexpression thereof, should correspond to the location of the constructor definition or aggregate initialization @@ -3596,16 +3870,18 @@ terminate_handler set_terminate(terminate_handler f) noexcept; [[noreturn]] void terminate() noexcept; - int uncaught_exceptions() noexcept; + constexpr int uncaught_exceptions() noexcept; using exception_ptr = @\unspec@; - exception_ptr current_exception() noexcept; - [[noreturn]] void rethrow_exception(exception_ptr p); - template exception_ptr make_exception_ptr(E e) noexcept; + constexpr exception_ptr current_exception() noexcept; + [[noreturn]] constexpr void rethrow_exception(exception_ptr p); + template constexpr exception_ptr make_exception_ptr(E e) noexcept; + template constexpr const E* exception_ptr_cast(const exception_ptr& p) noexcept; + template void exception_ptr_cast(const exception_ptr&&) = delete; - template [[noreturn]] void throw_with_nested(T&& t); - template void rethrow_if_nested(const E& e); + template [[noreturn]] constexpr void throw_with_nested(T&& t); + template constexpr void rethrow_if_nested(const E& e); } \end{codeblock} @@ -3617,11 +3893,11 @@ namespace std { class exception { public: - exception() noexcept; - exception(const exception&) noexcept; - exception& operator=(const exception&) noexcept; - virtual ~exception(); - virtual const char* what() const noexcept; + constexpr exception() noexcept; + constexpr exception(const exception&) noexcept; + constexpr exception& operator=(const exception&) noexcept; + constexpr virtual ~exception(); + constexpr virtual const char* what() const noexcept; }; } \end{codeblock} @@ -3654,8 +3930,8 @@ \indexlibraryctor{exception}% \indexlibrarymember{operator=}{exception}% \begin{itemdecl} -exception(const exception& rhs) noexcept; -exception& operator=(const exception& rhs) noexcept; +constexpr exception(const exception& rhs) noexcept; +constexpr exception& operator=(const exception& rhs) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3667,7 +3943,7 @@ \indexlibrarydtor{exception}% \begin{itemdecl} -virtual ~exception(); +constexpr virtual ~exception(); \end{itemdecl} \begin{itemdescr} @@ -3679,13 +3955,15 @@ \indexlibrarymember{what}{exception}% \begin{itemdecl} -virtual const char* what() const noexcept; +constexpr virtual const char* what() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -An \impldef{return value of \tcode{exception::what}} \ntbs{}. +An \impldef{return value of \tcode{exception::what}} \ntbs{}, +which during constant evaluation is encoded with +the ordinary literal encoding\iref{lex.ccon}. \pnum \remarks @@ -3706,7 +3984,7 @@ class bad_exception : public exception { public: // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; + constexpr const char* what() const noexcept override; }; } \end{codeblock} @@ -3721,7 +3999,7 @@ \indexlibrarymember{what}{bad_exception}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} @@ -3828,13 +4106,13 @@ \indexlibraryglobal{uncaught_exceptions}% \begin{itemdecl} -int uncaught_exceptions() noexcept; +constexpr int uncaught_exceptions() noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -The number of uncaught exceptions\iref{except.uncaught}. +The number of uncaught exceptions\iref{except.throw} in the current thread. \pnum \remarks @@ -3880,7 +4158,8 @@ For purposes of determining the presence of a data race, operations on \tcode{exception_ptr} objects shall access and modify only the \tcode{exception_ptr} objects themselves and not the exceptions they refer to. -Use of \tcode{rethrow_exception} on \tcode{exception_ptr} objects that refer to +Use of \tcode{rethrow_exception} or \tcode{exception_ptr_cast} +on \tcode{exception_ptr} objects that refer to the same exception object shall not introduce a data race. \begin{note} If @@ -3889,11 +4168,14 @@ Changes in the number of \tcode{exception_ptr} objects that refer to a particular exception do not introduce a data race. \end{note} + +\pnum +All member functions are marked \tcode{constexpr}. \end{itemdescr} \indexlibraryglobal{current_exception}% \begin{itemdecl} -exception_ptr current_exception() noexcept; +constexpr exception_ptr current_exception() noexcept; \end{itemdecl} \begin{itemdescr} @@ -3924,7 +4206,7 @@ \indexlibraryglobal{rethrow_exception}% \begin{itemdecl} -[[noreturn]] void rethrow_exception(exception_ptr p); +[[noreturn]] constexpr void rethrow_exception(exception_ptr p); \end{itemdecl} \begin{itemdescr} @@ -3952,7 +4234,7 @@ \indexlibraryglobal{make_exception_ptr}% \begin{itemdecl} -template exception_ptr make_exception_ptr(E e) noexcept; +template constexpr exception_ptr make_exception_ptr(E e) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3974,6 +4256,32 @@ \end{note} \end{itemdescr} +\indexlibraryglobal{exception_ptr_cast}% +\begin{itemdecl} +template constexpr const E* exception_ptr_cast(const exception_ptr& p) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{E} is a cv-unqualified complete object type. +\tcode{E} is not an array type. +\tcode{E} is not a pointer or pointer-to-member type. +\begin{note} +When \tcode{E} is a pointer or pointer-to-member type, +a handler of type \tcode{const E\&} can match +without binding to the exception object itself. +\end{note} + +\pnum +\returns +A pointer to the exception object referred to by \tcode{p}, +if \tcode{p} is not null and +a handler of type \tcode{const E\&} +would be a match\iref{except.handle} for that exception object. +Otherwise, \tcode{nullptr}. +\end{itemdescr} + \rSec2[except.nested]{\tcode{nested_exception}} \indexlibraryglobal{nested_exception}% @@ -3981,18 +4289,18 @@ namespace std { class nested_exception { public: - nested_exception() noexcept; - nested_exception(const nested_exception&) noexcept = default; - nested_exception& operator=(const nested_exception&) noexcept = default; - virtual ~nested_exception() = default; + constexpr nested_exception() noexcept; + constexpr nested_exception(const nested_exception&) noexcept = default; + constexpr nested_exception& operator=(const nested_exception&) noexcept = default; + constexpr virtual ~nested_exception() = default; // access functions - [[noreturn]] void rethrow_nested() const; - exception_ptr nested_ptr() const noexcept; + [[noreturn]] constexpr void rethrow_nested() const; + constexpr exception_ptr nested_ptr() const noexcept; }; - template [[noreturn]] void throw_with_nested(T&& t); - template void rethrow_if_nested(const E& e); + template [[noreturn]] constexpr void throw_with_nested(T&& t); + template constexpr void rethrow_if_nested(const E& e); } \end{codeblock} @@ -4009,7 +4317,7 @@ \indexlibraryctor{nested_exception}% \begin{itemdecl} -nested_exception() noexcept; +constexpr nested_exception() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4020,7 +4328,7 @@ \indexlibrarymember{rethrow_nested}{nested_exception}% \begin{itemdecl} -[[noreturn]] void rethrow_nested() const; +[[noreturn]] constexpr void rethrow_nested() const; \end{itemdecl} \begin{itemdescr} @@ -4032,7 +4340,7 @@ \indexlibrarymember{nested_ptr}{nested_exception}% \begin{itemdecl} -exception_ptr nested_ptr() const noexcept; +constexpr exception_ptr nested_ptr() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4043,7 +4351,7 @@ \indexlibrarymember{throw_with_nested}{nested_exception}% \begin{itemdecl} -template [[noreturn]] void throw_with_nested(T&& t); +template [[noreturn]] constexpr void throw_with_nested(T&& t); \end{itemdecl} \begin{itemdescr} @@ -4066,7 +4374,7 @@ \indexlibrarymember{rethrow_if_nested}{nested_exception}% \begin{itemdecl} -template void rethrow_if_nested(const E& e); +template constexpr void rethrow_if_nested(const E& e); \end{itemdecl} \begin{itemdescr} @@ -4082,6 +4390,268 @@ \end{codeblock} \end{itemdescr} +\rSec1[support.contract]{Contract-violation handling} + +\rSec2[contracts.syn]{Header \tcode{} synopsis} + +\pnum +The header \libheader{contracts} defines types +for reporting information about contract violations\iref{basic.contract.eval}. + +\indexheader{contracts} +\indexlibraryglobal{contract_violation}% +\begin{codeblock} +// all freestanding +namespace std::contracts { + + enum class assertion_kind : @\unspec@ { + pre = 1, + post = 2, + assert = 3 + }; + + enum class evaluation_semantic : @\unspec@ { + ignore = 1, + observe = 2, + enforce = 3, + quick_enforce = 4 + }; + + enum class detection_mode : @\unspec@ { + predicate_false = 1, + evaluation_exception = 2 + }; + + class contract_violation { + // no user-accessible constructor + public: + contract_violation(const contract_violation&) = delete; + contract_violation& operator=(const contract_violation&) = delete; + + @\seebelow@ ~contract_violation(); + + const char* comment() const noexcept; + contracts::detection_mode detection_mode() const noexcept; + exception_ptr evaluation_exception() const noexcept; + bool is_terminating() const noexcept; + assertion_kind kind() const noexcept; + source_location location() const noexcept; + evaluation_semantic semantic() const noexcept; + }; + + void invoke_default_contract_violation_handler(const contract_violation&); +} +\end{codeblock} + +\rSec2[support.contract.enum]{Enumerations} + +\pnum +\recommended +For all enumerations in \ref{support.contract.enum}, +if implementation-defined enumerators are provided, +they should have a minimum value of $1000$. + +\pnum +The enumerators of \tcode{assertion_kind} +correspond to +the syntactic forms of a contract assertion\iref{basic.contract.general}, +with meanings listed in Table~\ref{tab:support.contract.enum.kind}. + +\begin{floattable}{Enum \tcode{assertion_kind}}{support.contract.enum.kind} +{ll} +\topline +\lhdr{Name} & \rhdr{Meaning} \\ \capsep +\tcode{pre} & A precondition assertion \\ \rowsep +\tcode{post} & A postcondition assertion \\ \rowsep +\tcode{assert} & An \grammarterm{assertion-statement} \\ \rowsep +\end{floattable} + +\pnum +The enumerators of \tcode{evaluation_semantic} +correspond to +the evaluation semantics with which +a contract assertion may be evaluated\iref{basic.contract.eval}, +with meanings listed in Table~\ref{tab:support.contract.enum.semantic}. + +\begin{floattable}{Enum \tcode{evaluation_semantic}}{support.contract.enum.semantic} +{ll} +\topline +\lhdr{Name} & \rhdr{Meaning} \\ \capsep +\tcode{ignore} & Ignore evaluation semantic \\ \rowsep +\tcode{observe} & Observe evaluation semantic \\ \rowsep +\tcode{enforce} & Enforce evaluation semantic \\ \rowsep +\tcode{quick_enforce} & Quick-enforce evaluation semantic \\ \rowsep +\end{floattable} + +\pnum +The enumerators of \tcode{detection_mode} correspond to the manners in which a +contract violation can be identified\iref{basic.contract.eval}, with +meanings listed in \mbox{Table~\ref{tab:support.contract.enum.detection}}. + +\begin{floattable}{Enum \tcode{detection_mode}}{support.contract.enum.detection} +{lp{.6\hsize}} +\topline +\lhdr{Name} & \rhdr{Meaning} \\ \capsep +\tcode{predicate_false} & The predicate of the contract assertion evaluated to \keyword{false} or would have evaluated to \keyword{false}. \\ \rowsep +\tcode{evaluation_exception} & An uncaught exception occurred during evaluation of the contract assertion. \\ \rowsep +\end{floattable} + +\rSec2[support.contract.violation]{Class \tcode{contract_violation}} + +\pnum +\indexlibraryglobal{contract_violation}% +The class \tcode{contract_violation} +defines the type of objects used to represent +a contract violation that has been detected +during the evaluation of a contract assertion +with a particular evaluation semantic\iref{basic.contract.eval}. +Objects of this type can +be created only by the implementation. +It is +\impldef{whether \tcode{contract_violation} has a virtual destructor} +whether the destructor is virtual. + +\begin{itemdecl} +const char* comment() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An +\impldef{the contents provided in the \tcode{comment} field of \tcode{contract_violation}} +\ntmbs{} in +the ordinary literal encoding\iref{lex.charset}. + +\pnum +\recommended +The string returned +should contain a textual representation +of the predicate of the violated contract assertion +or an empty string if +storing a textual representation is undesired. +\begin{note} +The string can represent a +truncated, reformatted, or summarized rendering of the +predicate, before or after preprocessing. +\end{note} + +\end{itemdescr} + +\begin{itemdecl} +contracts::detection_mode detection_mode() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The enumerator value +corresponding to +the manner in which the contract violation was identified. + +\end{itemdescr} + +\begin{itemdecl} +exception_ptr evaluation_exception() const noexcept; +\end{itemdecl} + +\begin{itemdescr} + +\pnum +\returns +If the contract violation occurred +because the evaluation of the predicate exited via an exception, +an \tcode{exception_ptr} object that refers to +that exception or a copy of that exception; +otherwise, a null \tcode{exception_ptr} object. + +\end{itemdescr} + +\begin{itemdecl} +bool is_terminating() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\indextext{contract evaluation semantics!terminating}% +\pnum +\returns +\keyword{true} if the evaluation semantic is +a terminating semantic\iref{basic.contract.eval}; +otherwise, \tcode{false}. + +\end{itemdescr} + +\begin{itemdecl} +assertion_kind kind() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The enumerator value +corresponding to +the syntactic form of the violated contract assertion. + +\end{itemdescr} + +\begin{itemdecl} +source_location location() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{source_location} object +with +\impldef{the contents provided in the \tcode{location} field of \tcode{contract_violation}} +value. + +\pnum +\recommended +The value returned should be +a default constructed \tcode{source_location} object +or a value identifying the violated contract assertion: +\begin{itemize} +\item +When possible, +if the violated contract assertion was a precondition, +the source location of the function invocation should be returned. +\item +Otherwise, +the source location of the contract assertion should be returned. +\end{itemize} + +\end{itemdescr} + +\begin{itemdecl} +evaluation_semantic semantic() const noexcept; +\end{itemdecl} + +\begin{itemdescr} + +\pnum +\returns +The enumerator value +corresponding to +the evaluation semantic with which +the violated contract assertion was evaluated. + +\end{itemdescr} + +\rSec2[support.contract.invoke]{Invoke default handler} + +\begin{itemdecl} +void invoke_default_contract_violation_handler(const contract_violation& v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Invokes the default contract-violation handler\iref{basic.contract.handler} +with the argument \tcode{v}. + +\end{itemdescr} + \rSec1[support.initlist]{Initializer lists} \rSec2[support.initlist.general]{General} @@ -4130,7 +4700,7 @@ A pair of pointers or a pointer plus a length would be obvious representations for \tcode{initializer_list}. \tcode{initializer_list} is used to implement initializer lists as specified -in~\ref{dcl.init.list}. Copying an initializer list does not copy the underlying +in~\ref{dcl.init.list}. Copying an \tcode{initializer_list} does not copy the underlying elements. \end{note} @@ -4233,6 +4803,7 @@ \indexlibraryglobal{is_geq}% \indexlibraryglobal{is_gteq}% \indexlibraryglobal{common_comparison_category_t}% +\indexlibraryglobal{type_order_v}% \begin{codeblock} // all freestanding namespace std { @@ -4281,6 +4852,13 @@ inline constexpr @\unspec@ compare_weak_order_fallback = @\unspec@; inline constexpr @\unspec@ compare_partial_order_fallback = @\unspec@; } + + // \ref{compare.type}, type ordering + template + struct type_order; + + template + constexpr strong_ordering type_order_v = type_order::value; } \end{codeblock} @@ -4323,7 +4901,7 @@ an argument other than a literal \tcode{0} is undefined. \pnum -For the purposes of subclause \ref{cmp.categories}, +For the purposes of \ref{cmp.categories}, \defn{substitutability} is the property that \tcode{f(a) == f(b)} is \tcode{true} whenever \tcode{a == b} is \tcode{true}, where \tcode{f} denotes a function that reads only comparison-salient state @@ -4350,14 +4928,14 @@ \begin{codeblock} namespace std { class partial_ordering { - int value; // \expos - bool is_ordered; // \expos + int @\exposid{value}@; // \expos + bool @\exposid{is-ordered}@; // \expos // exposition-only constructors constexpr explicit - partial_ordering(@\placeholder{ord}@ v) noexcept : value(int(v)), is_ordered(true) {} // \expos + partial_ordering(@\placeholder{ord}@ v) noexcept : @\exposid{value}@(int(v)), @\exposid{is-ordered}@(true) {} // \expos constexpr explicit - partial_ordering(@\placeholder{ncmp}@ v) noexcept : value(int(v)), is_ordered(false) {} // \expos + partial_ordering(@\placeholder{ncmp}@ v) noexcept : @\exposid{value}@(int(v)), @\exposid{is-ordered}@(false) {} // \expos public: // valid values @@ -4405,7 +4983,7 @@ \begin{itemdescr} \pnum \returns -For \tcode{operator@}, \tcode{v.is_ordered \&\& v.value @ 0}. +For \tcode{operator@}, \tcode{v.\exposid{is-ordered} \&\& v.\exposid{value} @ 0}. \end{itemdescr} \indexlibrarymember{operator<}{partial_ordering}% @@ -4422,7 +5000,7 @@ \begin{itemdescr} \pnum \returns -For \tcode{operator@}, \tcode{v.is_ordered \&\& 0 @ v.value}. +For \tcode{operator@}, \tcode{v.\exposid{is-ordered} \&\& 0 @ v.\exposid{value}}. \end{itemdescr} \indexlibrarymember{operator<=>}{partial_ordering}% @@ -4463,10 +5041,10 @@ \begin{codeblock} namespace std { class weak_ordering { - int value; // \expos + int @\exposid{value}@; // \expos // exposition-only constructors - constexpr explicit weak_ordering(@\placeholder{ord}@ v) noexcept : value(int(v)) {} // \expos + constexpr explicit weak_ordering(@\placeholder{ord}@ v) noexcept : @\exposid{value}@(int(v)) {} // \expos public: // valid values @@ -4508,8 +5086,8 @@ \pnum \returns \begin{codeblock} -value == 0 ? partial_ordering::equivalent : -value < 0 ? partial_ordering::less : +@\exposid{value}@ == 0 ? partial_ordering::equivalent : +@\exposid{value}@ < 0 ? partial_ordering::less : partial_ordering::greater \end{codeblock} \end{itemdescr} @@ -4530,7 +5108,7 @@ \begin{itemdescr} \pnum \returns -\tcode{v.value @ 0} for \tcode{operator@}. +\tcode{v.\exposid{value} @ 0} for \tcode{operator@}. \end{itemdescr} \indexlibrarymember{operator<}{weak_ordering}% @@ -4547,7 +5125,7 @@ \begin{itemdescr} \pnum \returns -\tcode{0 @ v.value} for \tcode{operator@}. +\tcode{0 @ v.\exposid{value}} for \tcode{operator@}. \end{itemdescr} \indexlibrarymember{operator<=>}{weak_ordering}% @@ -4589,10 +5167,10 @@ \begin{codeblock} namespace std { class strong_ordering { - int value; // \expos + int @\exposid{value}@; // \expos // exposition-only constructors - constexpr explicit strong_ordering(@\placeholder{ord}@ v) noexcept : value(int(v)) {} // \expos + constexpr explicit strong_ordering(@\placeholder{ord}@ v) noexcept : @\exposid{value}@(int(v)) {} // \expos public: // valid values @@ -4637,8 +5215,8 @@ \pnum \returns \begin{codeblock} -value == 0 ? partial_ordering::equivalent : -value < 0 ? partial_ordering::less : +@\exposid{value}@ == 0 ? partial_ordering::equivalent : +@\exposid{value}@ < 0 ? partial_ordering::less : partial_ordering::greater \end{codeblock} \end{itemdescr} @@ -4652,8 +5230,8 @@ \pnum \returns \begin{codeblock} -value == 0 ? weak_ordering::equivalent : -value < 0 ? weak_ordering::less : +@\exposid{value}@ == 0 ? weak_ordering::equivalent : +@\exposid{value}@ < 0 ? weak_ordering::less : weak_ordering::greater \end{codeblock} \end{itemdescr} @@ -4674,7 +5252,7 @@ \begin{itemdescr} \pnum \returns -\tcode{v.value @ 0} for \tcode{operator@}. +\tcode{v.\exposid{value} @ 0} for \tcode{operator@}. \end{itemdescr} \indexlibrarymember{operator<}{strong_ordering}% @@ -4691,7 +5269,7 @@ \begin{itemdescr} \pnum \returns -\tcode{0 @ v.value} for \tcode{operator@}. +\tcode{0 @ v.\exposid{value}} for \tcode{operator@}. \end{itemdescr} \indexlibrarymember{operator<=>}{strong_ordering}% @@ -4775,7 +5353,7 @@ lvalues of types \tcode{const remove_reference_t} and \tcode{const remove_reference_t}, respectively. \tcode{T} and \tcode{U} model -\tcode{\exposconcept{partially-ordered-with}} only if: +\tcode{\exposconcept{partially-ordered-with}} only if \begin{itemize} \item \tcode{t < u}, @@ -4786,7 +5364,7 @@ \tcode{u <= t}, \tcode{u > t}, and \tcode{u >= t} - have the same domain. + have the same domain, \item \tcode{bool(t < u) == bool(u > t)} is \tcode{true}, \item @@ -4811,7 +5389,7 @@ Let \tcode{a} and \tcode{b} be lvalues of type \tcode{const remove_reference_t}. \tcode{T} and \tcode{Cat} -model \tcode{\libconcept{three_way_comparable}} only if: +model \tcode{\libconcept{three_way_comparable}} only if \begin{itemize} \item \tcode{(a <=> b == 0) == bool(a == b)} is \tcode{true}, @@ -4861,7 +5439,7 @@ Let \tcode{\exposid{CONVERT_TO_LVALUE}(E)} be defined as in \ref{concepts.compare.general}. \tcode{T}, \tcode{U}, and \tcode{Cat} -model \tcode{\libconcept{three_way_comparable_with}} only if: +model \tcode{\libconcept{three_way_comparable_with}} only if \begin{itemize} \item \tcode{t <=> u} and \tcode{u <=> t} have the same domain, @@ -4933,7 +5511,7 @@ observed by \tcode{T}'s comparison operators, and if \tcode{numeric_limits::is_iec559} is \tcode{true}, is additionally consistent with the \tcode{totalOrder} operation - as specified in ISO/IEC/IEEE 60559. + as specified in \IsoFloatUndated{}. \item Otherwise, \tcode{strong_ordering(compare_three_way()(E, F))} if it is a well-formed expression. @@ -5116,7 +5694,8 @@ Otherwise, if the expressions \tcode{E == F}, \tcode{E < F}, and \tcode{F < E} are all well-formed and - each of \tcode{decltype(E == F)} and \tcode{decltype(E < F)} models + each of \tcode{decltype(E == F)}, \tcode{decltype(E < F)}, and + \tcode{decltype(F < E)} models \exposconcept{boolean-testable}, \begin{codeblock} E == F ? partial_ordering::equivalent : @@ -5135,6 +5714,45 @@ of a template instantiation. \end{note} +\rSec2[compare.type]{Type Ordering} + +\pnum +There is an \impldef{total ordering of all types} total ordering of all types. +For any (possibly incomplete) types \tcode{X} and \tcode{Y}, +the expression \tcode{\exposid{TYPE-ORDER}(X, Y)} is a constant expression\iref{expr.const} +of type \tcode{strong_ordering}\iref{cmp.strongord}. +Its value is \tcode{strong_ordering::less} if \tcode{X} precedes \tcode{Y} +in this implementation-defined total order, +\tcode{strong_ordering::greater} if \tcode{Y} precedes \tcode{X}, and +\tcode{strong_ordering::equal} if they are the same type. +\begin{note} +\tcode{int}, \tcode{const int} and \tcode{int\&} are different types. +\end{note} +\begin{note} +This ordering need not be consistent with the one induced by \tcode{type_info::before}. +\end{note} +\begin{note} +The ordering of TU-local types from different translation units is not observable, +because the necessary specialization of \tcode{type_order} is impossible to name. +\end{note} + +\indexlibraryglobal{type_order}% +\begin{itemdecl} +template + struct type_order; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The name \tcode{type_order} denotes a \oldconcept{BinaryTypeTrait}\iref{meta.rqmts} +with a base characteristic of +\tcode{inte\-gral_constant}. + +\pnum +\recommended +The order should be lexicographical on parameter-type-lists and template argument lists. +\end{itemdescr} + \rSec1[support.coroutine]{Coroutines} \rSec2[support.coroutine.general]{General} @@ -5557,6 +6175,8 @@ \rSec3[coroutine.handle.noop]{Class \tcode{coroutine_handle}} +\rSec4[coroutine.handle.noop.general]{General} + \indexlibraryglobal{coroutine_handle}% \begin{codeblock} namespace std { @@ -5771,21 +6391,18 @@ \rSec2[cstdarg.syn]{Header \tcode{} synopsis} \indexheader{cstdarg}% -\indexlibraryglobal{va_list}% -\indexlibraryglobal{va_start}% -\indexlibraryglobal{va_copy}% -\indexlibraryglobal{va_end}% -\indexlibraryglobal{va_arg}% \begin{codeblock} // all freestanding +#define __STDC_VERSION_STDARG_H__ 202311L + namespace std { - using va_list = @\seebelow@; + using @\libglobal{va_list}@ = @\seebelow@; } -#define va_arg(V, P) @\seebelow@ -#define va_copy(VDST, VSRC) @\seebelow@ -#define va_end(V) @\seebelow@ -#define va_start(V, P) @\seebelow@ +#define @\libmacro{va_arg}@(V, P) @\seebelow@ +#define @\libmacro{va_copy}@(VDST, VSRC) @\seebelow@ +#define @\libmacro{va_end}@(V) @\seebelow@ +#define @\libmacro{va_start}@(V, ...) @\seebelow@ \end{codeblock} \pnum @@ -5793,37 +6410,19 @@ standard library header \libheader{stdarg.h}, with the following changes: \begin{itemize} \item -In lieu of the default argument promotions specified in ISO C 6.5.2.2, +In lieu of the default argument promotions specified in \IsoC{} 6.5.2.2, the definition in~\ref{expr.call} applies. \item -The restrictions that ISO C places on the second parameter to the -\indexlibraryglobal{va_start}% -\tcode{va_start} macro in header \libheader{stdarg.h} -are different in this document. -The parameter -\tcode{parmN} -is the rightmost parameter in the variable parameter list -of the function definition (the one just before the -\tcode{...}). -\begin{footnote} -Note that -\tcode{va_start} -is required to work as specified even if unary -\tcode{operator\&} -is overloaded for the type of -\tcode{parmN}. -\end{footnote} -If the parameter \tcode{parmN} is a pack expansion\iref{temp.variadic} or -an entity resulting from a lambda capture\iref{expr.prim.lambda}, -the program is ill-formed, no diagnostic required. -If the parameter -\tcode{parmN} -is of a reference type, or of a type that is not compatible with the -type that results when passing an argument for which there is no -parameter, the behavior is undefined. +The preprocessing tokens +comprising the second and subsequent arguments to \tcode{va_start} (if any) +are discarded. +\begin{note} +\tcode{va_start} accepts a second argument +for compatibility with prior revisions of \Cpp{}. +\end{note} \end{itemize} -\xrefc{7.16.1.1} +\xrefc{7.16} \rSec2[csetjmp.syn]{Header \tcode{} synopsis} @@ -5831,6 +6430,8 @@ \indexlibraryglobal{longjmp}% \indexlibraryglobal{setjmp}% \begin{codeblock} +#define __STDC_VERSION_SETJMP_H__ 202311L + namespace std { using jmp_buf = @\seebelow@; [[noreturn]] void longjmp(jmp_buf env, int val); @@ -5990,8 +6591,8 @@ the \defnx{C headers}{headers!C library} shown in \tref{c.headers}. The intended use of these headers is for interoperability only. It is possible that \Cpp{} source files need to include -one of these headers in order to be valid ISO C. -Source files that are not intended to also be valid ISO C +one of these headers in order to be valid C. +Source files that are not intended to also be valid C should not use any of the C headers. \begin{note} @@ -6002,17 +6603,17 @@ assuredly defines them in namespace \tcode{std}. \end{note} \begin{example} -The following source file is both valid \Cpp{} and valid ISO C. +The following source file is both valid \Cpp{} and valid C. Viewed as \Cpp{}, it declares a function with C language linkage; viewed as C it simply declares a function (and provides a prototype). \begin{codeblock} -#include // for \tcode{bool} in C, no effect in \Cpp{} +#include // for \tcode{char8_t} in C, not necessary in \Cpp{} #include // for \tcode{size_t} #ifdef __cplusplus // see \ref{cpp.predefined} extern "C" // see \ref{dcl.link} #endif -void f(bool b[], size_t n); +void f(char8_t s[], size_t n); \end{codeblock} \end{example} @@ -6036,16 +6637,18 @@ \libheader{stdalign.h} \\ \libheaderdef{stdarg.h} \\ \libheader{stdatomic.h} \\ +\libheader{stdbit.h} \\ \libheader{stdbool.h} \\ -\libheaderdef{stddef.h} \\ \columnbreak +\libheader{stdckdint.h} \\ +\libheaderdef{stddef.h} \\ \libheaderdef{stdint.h} \\ \libheaderdef{stdio.h} \\ \libheaderdef{stdlib.h} \\ \libheaderdef{string.h} \\ +\columnbreak \libheader{tgmath.h} \\ \libheaderdef{time.h} \\ -\columnbreak \libheaderdef{uchar.h} \\ \libheaderdef{wchar.h} \\ \libheaderdef{wctype.h} \\ @@ -6094,23 +6697,18 @@ \indexheader{stdalign.h}% \pnum The contents of the \Cpp{} header \libheader{stdalign.h} are the same as the C -standard library header \libheader{stdalign.h}, with the following changes: -The header \libheader{stdalign.h} does not -define a macro named \tcode{alignas}. +standard library header \libheader{stdalign.h}. \xrefc{7.15} \rSec2[stdbool.h.syn]{Header \tcode{} synopsis} \indexheader{stdbool.h}% -\indexhdr{stdbool.h}% \pnum The contents of the \Cpp{} header \libheader{stdbool.h} are the same as the C -standard library header \libheader{stdbool.h}, with the following changes: -The header \libheader{stdbool.h} does not -define macros named \tcode{bool}, \tcode{true}, or \tcode{false}. +standard library header \libheader{stdbool.h}. -\xrefc{7.18} +\xrefc{7.19} \rSec2[tgmath.h.syn]{Header \tcode{} synopsis} @@ -6149,7 +6747,9 @@ \libheaderref{iso646.h}, \libheaderref{stdalign.h},\newline \libheaderref{stdatomic.h}, -\libheaderref{stdbool.h}, and +\libheaderref{stdbit.h}, +\libheaderref{stdbool.h}, +\libheaderref{stdckdint.h}, and\newline \libheaderref{tgmath.h}, each of which has a name of the form diff --git a/source/tables.tex b/source/tables.tex index c1f20586f0..ea2f26a2c9 100644 --- a/source/tables.tex +++ b/source/tables.tex @@ -48,6 +48,7 @@ % floattablebase without TableBase, used for lib2dtab2base \newenvironment{floattablebasex}[4] { + \protect\hypertarget{tab:#2}{} \begin{table}[#4] \caption{\label{tab:#2}#1 \quad [tab:#2]} \begin{center} @@ -196,6 +197,7 @@ \newenvironment{LongTable}[3] { \newcommand{\continuedcaption}{\caption[]{#1 (continued)}} + \protect\hypertarget{tab:#2}{} \begin{TableBase} \begin{longtable}{|#3|} \caption{#1 \quad [tab:#2]}\label{tab:#2} @@ -241,6 +243,16 @@ \end{LongTable} } +\newenvironment{libreqtab2b}[2] +{ + \begin{LongTable} + {#1}{#2} + {x{.35\hsize}x{.59\hsize}} +} +{ + \end{LongTable} +} + \newenvironment{libreqtab3}[2] { \begin{LongTable} @@ -490,7 +502,7 @@ \newcommand{\bottomline}{\rowsep} \newcommand{\hdstyle}[1]{\textbf{##1}} \newcommand{\rowhdr}[1]{\hdstyle{##1}&} - \newcommand{\colhdr}[1]{\multicolumn{1}{|>{\centering}m{#6}|}{\hdstyle{##1}}} + \newcommand{\colhdr}[1]{\multicolumn{1}{>{\centering}m{#6}|}{\hdstyle{##1}}} \begin{floattablebasex} {#1}{#2} {>{\centering}m{#5}|@{}p{0.2\normalbaselineskip}@{}|m{#6}|m{#7} } diff --git a/source/templates.tex b/source/templates.tex index 44235f9d48..9ef3133aef 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -59,11 +59,7 @@ \end{note} \pnum -The -\grammarterm{declaration} -in a -\grammarterm{template-declaration} -(if any) +The \grammarterm{declaration} in a \grammarterm{template-declaration} (if any) shall \begin{itemize} \item declare or define a function, a class, or a variable, or @@ -73,6 +69,8 @@ \item define a member template of a class or class template, or +\item be a \grammarterm{friend-type-declaration}, or + \item be a \grammarterm{deduction-guide}, or \item be an \grammarterm{alias-declaration}. @@ -145,12 +143,26 @@ \begin{note} A template cannot have the same name as any other name bound in the same scope\iref{basic.scope.scope}, except -that a function template can share a name with non-template -functions\iref{dcl.fct} and/or function templates\iref{temp.over}. +that a function template can share a name with \grammarterm{using-declarator}s, +a type, non-template functions\iref{dcl.fct} and/or function templates\iref{temp.over}. Specializations, including partial specializations\iref{temp.spec.partial}, do not reintroduce or bind names. Their target scope is the target scope of the primary template, so all specializations of a template belong to the same scope as it does. +\begin{example} +\begin{codeblock} +void f() {} +class f {}; // OK +namespace N { + void f(int) {} +} +using N::f; // OK +template void f(long) {} // \#1, OK +template void f(long) {} // error: redefinition of \#1 +template void f(long long) {} // OK +template<> void f(long long) {} // OK, doesn't bind a name +\end{codeblock} +\end{example} \end{note} \pnum @@ -160,7 +172,9 @@ \begin{itemize} \item a template, \item an entity defined\iref{basic.def} or created\iref{class.temporary} - in a templated entity, + within the \grammarterm{compound-statement} + of an expansion statement\iref{stmt.expand}, +\item an entity defined or created in a templated entity, \item a member of a templated entity, \item an enumerator for an enumeration that is a templated entity, or \item the closure type of a \grammarterm{lambda-expression}\iref{expr.prim.lambda.closure} @@ -225,7 +239,10 @@ \begin{bnf} \nontermdef{template-parameter}\br type-parameter\br - parameter-declaration + parameter-declaration\br + type-tt-parameter\br + variable-tt-parameter\br + concept-tt-parameter \end{bnf} \begin{bnf} @@ -233,9 +250,7 @@ type-parameter-key \opt{\terminal{...}} \opt{identifier}\br type-parameter-key \opt{identifier} \terminal{=} type-id\br type-constraint \opt{\terminal{...}} \opt{identifier}\br - type-constraint \opt{identifier} \terminal{=} type-id\br - template-head type-parameter-key \opt{\terminal{...}} \opt{identifier}\br - template-head type-parameter-key \opt{identifier} \terminal{=} id-expression + type-constraint \opt{identifier} \terminal{=} type-id \end{bnf} \begin{bnf} @@ -250,6 +265,30 @@ \opt{nested-name-specifier} concept-name \terminal{<} \opt{template-argument-list} \terminal{>} \end{bnf} +\begin{bnf} +\nontermdef{type-tt-parameter}\br + template-head type-parameter-key \opt{\terminal{...}} \opt{identifier}\br + template-head type-parameter-key \opt{identifier} type-tt-parameter-default +\end{bnf} + +\begin{bnf} +\nontermdef{type-tt-parameter-default}\br + \terminal{=} \opt{nested-name-specifier} template-name\br + \terminal{=} nested-name-specifier \terminal{template} template-name +\end{bnf} + +\begin{bnf} +\nontermdef{variable-tt-parameter}\br + template-head \terminal{auto} \opt{\terminal{...}} \opt{identifier}\br + template-head \terminal{auto} \opt{identifier} \terminal{=} \opt{nested-name-specifier} template-name +\end{bnf} + +\begin{bnf} +\nontermdef{concept-tt-parameter}\br + \terminal{template} \terminal{<} template-parameter-list \terminal{>} \terminal{concept} \opt{\terminal{...}} \opt{identifier}\br + \terminal{template} \terminal{<} template-parameter-list \terminal{>} \terminal{concept} \opt{identifier} \terminal{=} \opt{nested-name-specifier} template-name +\end{bnf} + \indextext{component name}% The component names of a \grammarterm{type-constraint} are its \grammarterm{concept-name} and @@ -257,12 +296,85 @@ \begin{note} The \tcode{>} token following the \grammarterm{template-parameter-list} of a -\grammarterm{type-parameter} +\grammarterm{type-tt-parameter}, +\grammarterm{variable-tt-parameter}, or +\grammarterm{concept-tt-parameter} can be the product of replacing a \tcode{>>} token by two consecutive \tcode{>} tokens\iref{temp.names}. \end{note} +\pnum +%FIXME: "is" or "shall be"? i.e., what if it's not? +%FIXME: Note: we don't appear to ever define what a "template parameter" is; +%FIXME: is this supposed to be the definition for template parameter? +A template parameter is of one of the following kinds: +\begin{itemize} +\item +A \defnadj{type}{template parameter} is +a template parameter introduced by a \grammarterm{type-parameter}. +\item +A \defnadj{constant}{template parameter} is +a template parameter introduced by a \grammarterm{parameter-declaration}. +\item +A \defnadj{type template}{template parameter} is +a template parameter introduced by a \grammarterm{type-tt-parameter}. +\item +A \defnadj{variable template}{template parameter} is +a template parameter introduced by a \grammarterm{variable-tt-parameter}. +\item +A \defnadj{concept}{template parameter} is +a template parameter introduced by a \grammarterm{concept-tt-parameter}. +\end{itemize} + +\pnum +Type template template parameters, +variable template template parameters, and +concept template parameters +are collectively referred to as \defnadj{template}{template parameters}. + +\pnum +The \grammarterm{nested-name-specifier} of a \grammarterm{type-constraint}, +if any, shall not be dependent. + +\pnum +A concept template parameter shall not have +associated constraints\iref{temp.constr.decl}. + +\pnum +If a \grammarterm{template-parameter} is +a \grammarterm{parameter-declaration} that declares a pack\iref{dcl.fct}, or +otherwise has an ellipsis prior to its optional \grammarterm{identifier}, +then the \grammarterm{template-parameter} +declares a template parameter pack\iref{temp.variadic}. +A template parameter pack that is a \grammarterm{parameter-declaration} whose type +contains one or more unexpanded packs is a pack expansion. Similarly, +a template parameter pack that is a template template parameter with a +\grammarterm{template-parameter-list} containing one or more unexpanded +packs is a pack expansion. +A type parameter pack with a \grammarterm{type-constraint} that +contains an unexpanded parameter pack is a pack expansion. +A template parameter pack that is a pack +expansion shall not expand a template parameter pack declared in the same +\grammarterm{template-parameter-list}. +\begin{example} +\begin{codeblock} +template // \tcode{Types} is a template type parameter pack + class Tuple; // but not a pack expansion + +template // \tcode{Dims} is a constant template parameter pack + struct multi_array; // but not a pack expansion + +template + struct value_holder { + template struct apply { }; // \tcode{Values} is a constant template parameter pack + }; // and a pack expansion + +template // error: \tcode{Values} expands template type parameter + struct static_array; // pack \tcode{T} within the same template parameter list +\end{codeblock} +\end{example} + \pnum There is no semantic difference between \keyword{class} @@ -277,18 +389,7 @@ \keyword{typename} followed by a \grammarterm{qualified-id} -denotes the type in a non-type -\begin{footnote} -Since template -\grammarterm{template-parameter}{s} -and template -\grammarterm{template-argument}{s} -are treated as types for descriptive purposes, the terms -\term{non-type parameter} -and -\term{non-type argument} -are used to refer to non-type, non-template parameters and arguments. -\end{footnote} +denotes the type in a \grammarterm{parameter-declaration}. A \grammarterm{template-parameter} of the form \keyword{class} \grammarterm{identifier} is a \grammarterm{type-parameter}. @@ -298,56 +399,44 @@ int i; template void f(T t) { - T t1 = i; // template-parameters \tcode{T} and \tcode{i} + T t1 = i; // template parameters \tcode{T} and \tcode{i} ::T t2 = ::i; // global namespace members \tcode{T} and \tcode{i} } \end{codeblock} -Here, the template \tcode{f} has a \grammarterm{type-parameter} -called \tcode{T}, rather than an unnamed non-type -\grammarterm{template-parameter} of class \tcode{T}. +Here, the template \tcode{f} has a type template parameter +called \tcode{T}, rather than an unnamed constant +template parameter of class \tcode{T}. \end{example} -A \grammarterm{template-parameter} declaration shall not -have a \grammarterm{storage-class-specifier}. -Types shall not be defined in a \grammarterm{template-parameter} +The \grammarterm{parameter-declaration} of a \grammarterm{template-parameter} +shall not have a \grammarterm{storage-class-specifier}. +Types shall not be defined in a template parameter declaration. \pnum -The \grammarterm{identifier} in a \grammarterm{type-parameter} is not looked up. -A \grammarterm{type-parameter} -whose \grammarterm{identifier} does not follow an ellipsis -defines its -\grammarterm{identifier} -to be a -\grammarterm{typedef-name} -(if declared without -\keyword{template}) -or -\grammarterm{template-name} -(if declared with -\keyword{template}) +The \grammarterm{identifier} in +a \grammarterm{template-parameter} denoting a type or template +is not looked up. +An \grammarterm{identifier} that does not follow an ellipsis +is defined to be +\begin{itemize} +\item +a \grammarterm{typedef-name} for a \grammarterm{type-parameter}, +\item +a \grammarterm{template-name} for a \grammarterm{variable-tt-parameter}, +\item +a \grammarterm{template-name} for a \grammarterm{type-tt-parameter}, or +\item +a \grammarterm{concept-name} for a \grammarterm{concept-tt-parameter}, +\end{itemize} in the scope of the template declaration. -\begin{note} -A template argument can be a class template or alias template. -For example, - -\begin{codeblock} -template class myarray { @\commentellip@ }; - -template class C = myarray> -class Map { - C key; - C value; -}; -\end{codeblock} -\end{note} \pnum A \grammarterm{type-constraint} \tcode{Q} that designates a concept \tcode{C} can be used to constrain a contextually-determined type or template type parameter pack \tcode{T} with a \grammarterm{constraint-expression} \tcode{E} defined as follows. -If \tcode{Q} is of the form \tcode{C}, -then let \tcode{E$'$} be \tcode{C}. +If \tcode{Q} is of the form \tcode{C}, +then let \tcode{E$'$} be \tcode{C}. Otherwise, let \tcode{E$'$} be \tcode{C}. If \tcode{T} is not a pack, then \tcode{E} is \tcode{E$'$}, @@ -377,7 +466,7 @@ \end{example} \pnum -A non-type \grammarterm{template-parameter} +A constant template parameter shall have one of the following (possibly cv-qualified) types: \begin{itemize} \item a structural type (see below), @@ -401,24 +490,24 @@ \item all base classes and non-static data members are public and non-mutable and \item -the types of all bases classes and non-static data members are -structural types or (possibly multidimensional) array thereof. +the types of all base classes and non-static data members are +structural types or (possibly multidimensional) arrays thereof. \end{itemize} \end{itemize} \pnum An \grammarterm{id-expression} naming -a non-type \grammarterm{template-parameter} of class type \tcode{T} +a constant template parameter of class type \tcode{T} denotes a static storage duration object of type \tcode{const T}, known as a \defn{template parameter object}, which is template-argument-equivalent\iref{temp.type} to the corresponding template argument after it has been converted -to the type of the \grammarterm{template-parameter}\iref{temp.arg.nontype}. +to the type of the template parameter\iref{temp.arg.nontype}. No two template parameter objects are template-argument-equivalent. \begin{note} If an \grammarterm{id-expression} names -a non-type non-reference \grammarterm{template-parameter}, +a non-reference constant template parameter, then it is a prvalue if it has non-class type. Otherwise, if it is of class type \tcode{T}, it is an lvalue and has type \tcode{const T}\iref{expr.prim.id.unqual}. @@ -428,10 +517,10 @@ using X = int; struct A {}; template void f() { - i++; // error: change of \grammarterm{template-parameter} value + i++; // error: change of template parameter value &x; // OK - &i; // error: address of non-reference template-parameter + &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 @@ -442,8 +531,7 @@ \pnum \begin{note} -A non-type -\grammarterm{template-parameter} +A constant template parameter cannot be declared to have type \cv{} \keyword{void}. \begin{example} \begin{codeblock} @@ -454,8 +542,7 @@ \end{note} \pnum -A non-type -\grammarterm{template-parameter} +A constant template parameter \indextext{array!template parameter of type}% of type ``array of \tcode{T}'' or \indextext{function!template parameter of type}% @@ -475,7 +562,7 @@ \end{example} \pnum -A non-type template parameter declared with a type that +A constant template parameter declared with a type that contains a placeholder type with a \grammarterm{type-constraint} introduces the immediately-declared constraint of the \grammarterm{type-constraint} @@ -483,10 +570,10 @@ \pnum A \defnadj{default}{template argument} is -a template argument \iref{temp.arg} specified after \tcode{=} +a template argument\iref{temp.arg} specified after \tcode{=} in a \grammarterm{template-parameter}. A default template argument may be specified for -any kind of \grammarterm{template-parameter} (type, non-type, template) +any kind of template parameter that is not a template parameter pack\iref{temp.variadic}. A default template argument may be specified in a template declaration. A default template argument shall not be specified in @@ -523,14 +610,15 @@ a default template argument, each subsequent \grammarterm{template-parameter} shall either have a default template argument supplied or -be a template parameter pack. +declare a template parameter pack. If a \grammarterm{template-parameter} of a primary class template, primary variable template, or alias template -is a template parameter pack, +declares a template parameter pack, it shall be the last \grammarterm{template-parameter}. -A template parameter pack of a function template -shall not be followed by another template parameter -unless that template parameter can be deduced from the +If a \grammarterm{template-parameter} of a function template +declares a template parameter pack, it +shall not be followed by another \grammarterm{template-parameter} +unless that template parameter is deducible from the parameter-type-list\iref{dcl.fct} of the function template or has a default argument\iref{temp.deduct}. A template parameter of a deduction guide template\iref{temp.deduct.guide} @@ -549,7 +637,7 @@ \indextext{\idxcode{<}!template and}% \pnum When parsing a default template argument -for a non-type \grammarterm{template-parameter}, +for a constant template parameter, the first non-nested \tcode{>} is taken as the end of the \grammarterm{template-parameter-list} rather than a greater-than operator. @@ -584,39 +672,15 @@ } \end{codeblock} \end{example} - -\pnum -If a \grammarterm{template-parameter} is a -\grammarterm{type-parameter} with an ellipsis prior to its -optional \grammarterm{identifier} or is a -\grammarterm{parameter-declaration} that declares a -pack\iref{dcl.fct}, then the \grammarterm{template-parameter} -is a template parameter pack\iref{temp.variadic}. -A template parameter pack that is a \grammarterm{parameter-declaration} whose type -contains one or more unexpanded packs is a pack expansion. Similarly, -a template parameter pack that is a \grammarterm{type-parameter} with a -\grammarterm{template-parameter-list} containing one or more unexpanded -packs is a pack expansion. -A type parameter pack with a \grammarterm{type-constraint} that -contains an unexpanded parameter pack is a pack expansion. -A template parameter pack that is a pack -expansion shall not expand a template parameter pack declared in the same -\grammarterm{template-parameter-list}. +The associated constraints of a template template parameter +shall not contain a concept-dependent constraint\iref{temp.constr.concept}. \begin{example} \begin{codeblock} -template // \tcode{Types} is a template type parameter pack - class Tuple; // but not a pack expansion - -template // \tcode{Dims} is a non-type template parameter pack - struct multi_array; // but not a pack expansion - -template - struct value_holder { - template struct apply { }; // \tcode{Values} is a non-type template parameter pack - }; // and a pack expansion - -template // error: \tcode{Values} expands template type parameter - struct static_array; // pack \tcode{T} within the same template parameter list +template< + template concept C, + template class TT // error: \tcode{C} forms a concept-dependent constraint +> +struct A {}; \end{codeblock} \end{example} @@ -653,8 +717,8 @@ \nontermdef{template-argument}\br constant-expression\br type-id\br - id-expression\br - braced-init-list + \opt{nested-name-specifier} template-name\br + nested-name-specifier \terminal{template} template-name \end{bnf} \pnum @@ -668,7 +732,16 @@ \pnum A \tcode{<} is interpreted as the delimiter of a \grammarterm{template-argument-list} -if it follows a name that is not a \grammarterm{conversion-function-id} and +if either +\begin{itemize} +\item +it follows a \grammarterm{splice-specifier} that either +\begin{itemize} +\item appears in a type-only context or +\item is preceded by \keyword{template} or \keyword{typename}, or +\end{itemize} +\item +it follows a name that is not a \grammarterm{conversion-function-id} and \begin{itemize} \item that follows the keyword \keyword{template} or a \tcode{\~} @@ -687,6 +760,7 @@ in a type-only context other than a \grammarterm{nested-name-specifier}\iref{temp.res}. \end{itemize} +\end{itemize} \begin{note} If the name is an \grammarterm{identifier}, it is then interpreted as a \grammarterm{template-name}. @@ -705,7 +779,11 @@ 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 -} + + static constexpr std::meta::info r = ^^T::adjust; + T* p3 = [:r:]<200>(); // error: \tcode{<} means less than + T* p4 = template [:r:]<200>(); // OK, \tcode{<} starts template argument list +}} \end{codeblock} \end{example} @@ -718,20 +796,21 @@ A \tcode{>} that encloses the \grammarterm{type-id} of a \keyword{dynamic_cast}, \keyword{static_cast}, \keyword{reinterpret_cast} or \keyword{const_cast}, or which encloses the \grammarterm{template-argument}{s} -of a subsequent \grammarterm{template-id}, is considered nested for the purpose -of this description. +of a subsequent \grammarterm{template-id} or +\grammarterm{splice-specialization-specifier}, +is considered nested for the purpose of this description. \end{footnote} is taken as the ending delimiter rather than a greater-than operator. Similarly, the first non-nested \tcode{>>} is treated as two consecutive but distinct \tcode{>} tokens, the first of which is taken as the end of the \grammarterm{template-argument-list} and completes -the \grammarterm{template-id}. +the \grammarterm{template-id} or \grammarterm{splice-specialization-specifier}. \begin{note} The second \tcode{>} token produced by this replacement rule can terminate an enclosing -\grammarterm{template-id} construct or it can be part of a different -construct (e.g., a cast). +\grammarterm{template-id} or \grammarterm{splice-specialization-specifier} +construct or it can be part of a different construct (e.g., a cast). \end{note} \begin{example} \begin{codeblock} @@ -751,6 +830,20 @@ The keyword \keyword{template} shall not appear immediately after a declarative \grammarterm{nested-name-specifier}\iref{expr.prim.id.qual}. +\pnum +The \grammarterm{constant-expression} of a \grammarterm{template-argument} +shall not be an unparenthesized \grammarterm{splice-expression}. +\begin{example} +\begin{codeblock} +template struct S { }; +constexpr int k = 5; +constexpr std::meta::info r = ^^k; +S<[:r:]> s1; // error: unparenthesized \grammarterm{splice-expression} used as template argument +S<([:r:])> s2; // OK +S<[:r:] + 1> s3; // OK +\end{codeblock} +\end{example} + \pnum A name prefixed by the keyword \keyword{template} @@ -796,7 +889,8 @@ \end{example} \pnum -A \grammarterm{template-id} is \defnx{valid}{\idxgram{template-id}!valid} if +A \grammarterm{template-id} or \grammarterm{splice-specialization-specifier} +is \defnx{valid}{\idxgram{template-id}!valid} if \begin{itemize} \item there are at most as many arguments as there are parameters @@ -808,18 +902,22 @@ \item each \grammarterm{template-argument} matches the corresponding - \grammarterm{template-parameter}\iref{temp.arg}, + template parameter\iref{temp.arg}, \item substitution of each template argument into the following template parameters (if any) succeeds, and \item - if the \grammarterm{template-id} is non-dependent, + if the \grammarterm{template-id} or + \grammarterm{splice-specialization-specifier} is non-dependent, the associated constraints are satisfied as specified in the next paragraph. \end{itemize} -A \grammarterm{simple-template-id} shall be valid unless it names a -function template specialization\iref{temp.deduct}. +A \grammarterm{simple-template-id} or +\grammarterm{splice-specialization-specifier} +shall be valid unless its respective +\grammarterm{template-name} or \grammarterm{splice-specifier} +names or designates a function template\iref{temp.deduct}. \begin{example} \begin{codeblock} template class X; @@ -836,13 +934,16 @@ \pnum When the \grammarterm{template-name} -of a \grammarterm{simple-template-id} -names a constrained non-function template +of a \grammarterm{simple-template-id} or +the \grammarterm{splice-specifier} +of a \grammarterm{splice-specialization-specifier} +designates a constrained non-function template or -a constrained template \grammarterm{template-parameter}, +a constrained template template parameter, and all \grammarterm{template-argument}{s} -in the \grammarterm{simple-template-id} +in the \grammarterm{simple-template-id} or +\grammarterm{splice-specialization-specifier} are non-dependent\iref{temp.dep.temp}, the associated constraints\iref{temp.constr.decl} of the constrained template @@ -908,15 +1009,9 @@ \pnum \indextext{argument!template}% -There are three forms of -\grammarterm{template-argument}, -corresponding to the three forms of -\grammarterm{template-parameter}: -type, non-type and template. -The type and form of each -\grammarterm{template-argument} -specified in a -\grammarterm{template-id} +The type and form of each \grammarterm{template-argument} specified +in a \grammarterm{template-id} or +in a \grammarterm{splice-specialization-specifier} shall match the type and form specified for the corresponding parameter declared by the template in its \grammarterm{template-parameter-list}. @@ -988,8 +1083,8 @@ \begin{note} Names used in a \grammarterm{template-argument} are subject to access control where they appear. -Because a \grammarterm{template-parameter} is not a class member, -no access control applies. +Because a template parameter is not a class member, +no access control applies where the template parameter is used. \end{note} \begin{example} \begin{codeblock} @@ -1082,7 +1177,9 @@ \end{note} \pnum -When a \grammarterm{simple-template-id} does not name a function, +When a \grammarterm{simple-template-id} or +\grammarterm{splice-specialization-specifier} +does not designate a function, a default \grammarterm{template-argument} is implicitly instantiated\iref{temp.inst} when the value of that default argument is needed. @@ -1098,14 +1195,12 @@ A \grammarterm{template-argument} followed by an ellipsis is a pack expansion\iref{temp.variadic}. -\rSec2[temp.arg.type]{Template type arguments} +\rSec2[temp.arg.type]{Type template arguments} \pnum A \grammarterm{template-argument} -for a -\grammarterm{template-parameter} -which is a type +for a type template parameter shall be a \grammarterm{type-id}. @@ -1134,28 +1229,30 @@ A template type argument can be an incomplete type\iref{term.incomplete.type}. \end{note} -\rSec2[temp.arg.nontype]{Template non-type arguments} +\rSec2[temp.arg.nontype]{Constant template arguments} \pnum -If the type \tcode{T} of a \grammarterm{template-parameter}\iref{temp.param} -contains a placeholder type\iref{dcl.spec.auto} -or a placeholder for a deduced class type\iref{dcl.type.class.deduct}, -the type of the parameter is the type deduced -for the variable \tcode{x} in the invented declaration +A template argument $E$ for +a constant template parameter with declared type \tcode{T} +shall be such that the invented declaration \begin{codeblock} T x = @$E$@ ; \end{codeblock} -where $E$ is the template argument provided for the parameter. +satisfies the semantic constraints for the definition of +a \tcode{constexpr} variable with static storage duration\iref{dcl.constexpr}. +If \tcode{T} contains a placeholder type\iref{dcl.spec.auto} +or a placeholder for a deduced class type\iref{dcl.type.class.deduct}, +the type of the parameter is deduced from the above declaration. \begin{note} $E$ is a \grammarterm{template-argument} or (for a default template argument) an \grammarterm{initializer-clause}. \end{note} -If a deduced parameter type is not permitted -for a \grammarterm{template-parameter} declaration\iref{temp.param}, +If the parameter type thus deduced is not permitted +for a constant template parameter\iref{temp.param}, the program is ill-formed. \pnum -The value of a non-type \grammarterm{template-parameter} $P$ +The value of a constant template parameter $P$ of (possibly deduced) type \tcode{T} is determined from its template argument $A$ as follows. If \tcode{T} is not a class type and @@ -1199,11 +1296,11 @@ Otherwise, the value of $P$ is that of v. \pnum -For a non-type \grammarterm{template-parameter} of reference or pointer type, +For a constant template parameter of reference or pointer type, or for each non-static data member of reference or pointer type -in a non-type \grammarterm{template-parameter} of class type or subobject thereof, -the reference or pointer value shall not refer to -or be the address of (respectively): +in a constant template parameter of class type or subobject thereof, +the reference or pointer value shall not refer +or point to (respectively): \begin{itemize} \item a temporary object\iref{class.temporary}, \item a string literal object\iref{lex.string}, @@ -1212,6 +1309,19 @@ \item a subobject\iref{intro.object} of one of the above. \end{itemize} +\pnum +\begin{example} +\begin{codeblock} +template class A{}; +extern int x; +A a; // OK +void f(int p) { + constexpr int& r = p; // OK + A a; // error: a static constexpr \tcode{int\&} variable cannot be initialized to refer to \tcode{p} here +} +\end{codeblock} +\end{example} + \pnum \begin{example} \begin{codeblock} @@ -1262,7 +1372,7 @@ \begin{note} A \grammarterm{string-literal}\iref{lex.string} is not an acceptable \grammarterm{template-argument} -for a \grammarterm{template-parameter} of non-class type. +for a constant template parameter of non-class type. \begin{example} \begin{codeblock} template class X { @@ -1290,7 +1400,7 @@ is not an acceptable \grammarterm{template-argument} when the corresponding -\grammarterm{template-parameter} +template parameter has reference type. \begin{example} \begin{codeblock} @@ -1316,9 +1426,14 @@ A \grammarterm{template-argument} for a template -\grammarterm{template-parameter} -shall be the name of a class template or an alias template, expressed as -\grammarterm{id-expression}. +template parameter +shall be the name of a template. +For a \grammarterm{type-tt-parameter}, +the name shall denote a class template or alias template. +For a \grammarterm{variable-tt-parameter}, +the name shall denote a variable template. +For a \grammarterm{concept-tt-parameter}, +the name shall denote a concept. Only primary templates are considered when matching the template template argument with the corresponding parameter; partial specializations are not considered even if their parameter lists match that of the template template @@ -1327,9 +1442,7 @@ \pnum Any partial specializations\iref{temp.spec.partial} associated with the primary template are considered when a -specialization based on the template -\grammarterm{template-parameter} -is instantiated. +specialization based on the template template parameter is instantiated. If a specialization is not reachable from the point of instantiation, and it would have been selected had it been reachable, the program is ill-formed, no diagnostic required. @@ -1351,23 +1464,41 @@ \end{example} \pnum -A \grammarterm{template-argument} matches a template -\grammarterm{template-parameter} \tcode{P} when -\tcode{P} is at least as specialized as the \grammarterm{template-argument} \tcode{A}. -In this comparison, if \tcode{P} is unconstrained, -the constraints on \tcode{A} are not considered. +A template template parameter \tcode{P} and +a \grammarterm{template-argument} \tcode{A} are +\defnx{compatible}{compatible!template template parameter and template argument} +if +\begin{itemize} +\item +\tcode{A} denotes a class template or an alias template and +\tcode{P} is a type template parameter, +\item +\tcode{A} denotes a variable template and +\tcode{P} is a variable template parameter, or +\item +\tcode{A} denotes a concept and +\tcode{P} is a concept template parameter. +\end{itemize} + +\pnum +A template \grammarterm{template-argument} \tcode{A} matches a template +template parameter \tcode{P} when +\tcode{A} and \tcode{P} are compatible and +\tcode{P} is at least as specialized as \tcode{A}, ignoring constraints +on \tcode{A} if \tcode{P} is unconstrained. If \tcode{P} contains a template parameter pack, then \tcode{A} also matches \tcode{P} if each of \tcode{A}'s template parameters -matches the corresponding template parameter in the +matches the corresponding template parameter declared in the \grammarterm{template-head} of \tcode{P}. -Two template parameters match if they are of the same kind (type, non-type, template), -for non-type \grammarterm{template-parameter}{s}, their types are -equivalent\iref{temp.over.link}, and for template \grammarterm{template-parameter}{s}, -each of their corresponding \grammarterm{template-parameter}{s} matches, recursively. -When \tcode{P}'s \grammarterm{template-head} contains a template parameter +Two template parameters match if they are of the same kind, +for constant template parameters, their types are +equivalent\iref{temp.over.link}, and for template template parameters, +each of their corresponding template parameters matches, recursively. +When \tcode{P}'s \grammarterm{template-head} contains a \grammarterm{template-parameter} +that declares a template parameter pack\iref{temp.variadic}, the template parameter pack will match zero or more template -parameters or template parameter packs in the \grammarterm{template-head} of -\tcode{A} with the same type and form as the template parameter pack in \tcode{P} +parameters or template parameter packs declared in the \grammarterm{template-head} of +\tcode{A} with the same type and form as the template parameter pack declared in \tcode{P} (ignoring whether those template parameters are template parameter packs). \begin{example} @@ -1427,7 +1558,7 @@ \end{example} \pnum -A template \grammarterm{template-parameter} \tcode{P} is +A template template parameter \tcode{P} is at least as specialized as a template \grammarterm{template-argument} \tcode{A} if, given the following rewrite to two function templates, the function template corresponding to \tcode{P} @@ -1449,12 +1580,12 @@ whose type is a specialization of \tcode{X} with template arguments corresponding to the template parameters from the respective function template where, -for each template parameter \tcode{PP} +for each \grammarterm{template-parameter} \tcode{PP} in the \grammarterm{template-head} of the function template, -a corresponding template argument \tcode{AA} is formed. +a corresponding \grammarterm{template-argument} \tcode{AA} is formed. If \tcode{PP} declares a template parameter pack, then \tcode{AA} is the pack expansion \tcode{PP...}\iref{temp.variadic}; -otherwise, \tcode{AA} is the \grammarterm{id-expression} \tcode{PP}. +otherwise, \tcode{AA} is an \grammarterm{id-expression} denoting \tcode{PP}. \end{itemize} If the rewrite produces an invalid type, then \tcode{P} is not at least as specialized as \tcode{A}. @@ -1482,11 +1613,13 @@ A \defn{constraint} is a sequence of logical operations and operands that specifies requirements on template arguments. The operands of a logical operation are constraints. -There are three different kinds of constraints: +There are five different kinds of constraints: \begin{itemize} \item conjunctions\iref{temp.constr.op}, -\item disjunctions\iref{temp.constr.op}, and -\item atomic constraints\iref{temp.constr.atomic}. +\item disjunctions\iref{temp.constr.op}, +\item atomic constraints\iref{temp.constr.atomic}, +\item concept-dependent constraints\iref{temp.constr.concept}, and +\item fold expanded constraints\iref{temp.constr.fold}. \end{itemize} \pnum @@ -1721,6 +1854,110 @@ \end{codeblock} \end{example} +\rSec3[temp.constr.concept]{Concept-dependent constraints} + +\pnum +A \defnadj{concept-dependent}{constraint} \tcode{CD} is +an atomic constraint whose expression is a concept-id \tcode{CI} whose +\grammarterm{concept-name} names a dependent concept named \tcode{C}. + +\pnum +To determine if \tcode{CD} is +\defnx{satisfied}{constraint!satisfaction!concept-dependent}, +the parameter mapping and template arguments are first +substituted into \tcode{C}. +If substitution results in an invalid concept-id in +the immediate context of the constraint\iref{temp.deduct.general}, +the constraint is not satisfied. +Otherwise, let \tcode{CI$'$} be +the normal form\iref{temp.constr.normal} of the concept-id +after substitution of \tcode{C}. +\begin{note} +Normalization of \tcode{CI} might be ill-formed; no diagnostics is required. +\end{note} + +\pnum +To form \tcode{CI$''$}, +each appearance of \tcode{C}{'s} template parameters in +the parameter mappings of the atomic constraints +(including concept-dependent constraints) +in \tcode{CI$'$} +is substituted with their respective arguments from +the parameter mapping of \tcode{CD} and the arguments of \tcode{CI}. + +\pnum +\tcode{CD} is satisfied if \tcode{CI$''$} is satisfied. +\begin{note} +Checking whether \tcode{CI$''$} is satisfied +can lead to further normalization of concept-dependent constraints. +\end{note} +\begin{example} +\begin{codeblock} +template +concept C = true; + +template concept CC> +concept D = CC; + +template concept CT, + template concept> concept CU> +int f() requires CU; +int i = f(); +\end{codeblock} +In this example, the associated constraints of \tcode{f} +consist of a concept-dependent constraint +whose expression is the concept-id \tcode{CU} with the mapping +$\tcode{U} \mapsto \tcode{U}, \tcode{CT} \mapsto \tcode{CT}, \tcode{CU} \mapsto \tcode{CU}$. +The result of substituting \tcode{D} into this expression is \tcode{D}. +We consider the normal form of the resulting concept-id, +which is \tcode{CC} with the mapping +$\tcode{T} \mapsto \tcode{U}, \tcode{CC} \mapsto \tcode{CT}$. +By recursion, \tcode{C} is substituted into \tcode{CC}, and the result +is normalized to the atomic constraint \tcode{true}, which is satisfied. +\end{example} + +\rSec3[temp.constr.fold]{Fold expanded constraint} + +\pnum +A \defnadj{fold expanded}{constraint} is formed from a constraint $C$ and +a \grammarterm{fold-operator} +which can either be \tcode{\&\&} or \tcode{||}. +A fold expanded constraint is a pack expansion\iref{temp.variadic}. +Let $N$ be the number of elements +in the pack expansion parameters\iref{temp.variadic}. + +\pnum +A fold expanded constraint whose \grammarterm{fold-operator} is \tcode{\&\&} +is satisfied if it is a valid pack expansion and +if $N = 0$ or if for each $i$ where $0 \le i < N$ in increasing order, +$C$ is satisfied +when replacing each pack expansion parameter +with the corresponding $i^\text{th}$ element. +No substitution takes place for any $i$ greater than +the smallest $i$ for which the constraint is not satisfied. + +\pnum +A fold expanded constraint whose \grammarterm{fold-operator} is \tcode{||} +is satisfied if it is a valid pack expansion, +$N > 0$, and if for $i$ where $0 \le i < N$ in increasing order, +there is a smallest $i$ for which $C$ is satisfied +when replacing each pack expansion parameter +with the corresponding $i^\text{th}$ element. +No substitution takes place for any $i$ greater than +the smallest $i$ for which the constraint is satisfied. + +\pnum +\begin{note} +If the pack expansion expands packs of different size, +then it is invalid and the fold expanded constraint is not satisfied. +\end{note} + +\pnum +Two fold expanded constraints are \defnadj{compatible for}{subsumption} +if their respective constraints both contain +an equivalent unexpanded pack\iref{temp.over.link}. + \rSec2[temp.constr.decl]{Constrained declarations} \pnum @@ -1870,13 +2107,30 @@ the normal forms of \tcode{E1} and \tcode{E2}. \item -The normal form of a concept-id \tcode{C} -is the normal form of the \grammarterm{constraint-expression} of \tcode{C}, -after substituting \tcode{A$_1$, A$_2$, ..., A$_n$} for -\tcode{C}{'s} respective template parameters in the -parameter mappings in each atomic constraint. +For a concept-id \tcode{C} termed \tcode{CI}: +\begin{itemize} +\item +If \tcode{C} names a dependent concept, +the normal form of \tcode{CI} is a concept-dependent constraint +whose concept-id is \tcode{CI} and +whose parameter mapping is the identity mapping. +\item +Otherwise, to form \tcode{CE}, +%FIXME: We're saying any Ai can be used to form CE. Do we have to try all +%FIXME: the Ais to check for ill-formedness or just the random one we picked? +%FIXME: Don't we want to form a CEi for each Ai? +any non-dependent concept template argument \tcode{A$_i$} +is substituted into the \grammarterm{constraint-expression} of \tcode{C}. +If any such substitution results in an invalid concept-id, +the program is ill-formed; no diagnostic is required. +The normal form of \tcode{CI} is the result of substituting, +in the normal form \tcode{N} of \tcode{CE}, +appearances of \tcode{C}{'s} template parameters +in the parameter mappings of the atomic constraints in \tcode{N} +with their respective arguments from \tcode{C}. If any such substitution results in an invalid type or expression, the program is ill-formed; no diagnostic is required. +\end{itemize} \begin{example} \begin{codeblock} template concept A = T::value || true; @@ -1896,6 +2150,52 @@ in the parameter mapping. \end{example} +\item +For a \grammarterm{fold-operator} \tcode{Op}\iref{expr.prim.fold} +that is either \tcode{\&\&} or \tcode{||}: + \begin{itemize} + \item + The normal form of an expression \tcode{( ... Op E )} + is the normal form of \tcode{( E Op ... )}. + \item + The normal form of an expression \tcode{( E1 Op ... Op E2 )} + is the normal form of + \begin{itemize} + \item + \tcode{( E1 Op ... ) Op E2} if \tcode{E1} contains an unexpanded pack, or + \item + \tcode{E1 Op ( E2 Op ... )} otherwise. + \end{itemize} + \item + The normal form of an expression \tcode{F} of the form \tcode{( E Op ... )} + is as follows:\\ + If \tcode{E} contains an unexpanded concept template parameter pack, + it shall not contain an unexpanded template parameter pack of another kind. + Let \tcode{E$'$} be the normal form of \tcode{E}. + \begin{itemize} + \item + If \tcode{E} contains + an unexpanded concept template parameter pack \tcode{P$_k$} that + has corresponding template arguments in + the parameter mapping of any atomic constraint + (including concept-dependent constraints) of \tcode{E$'$}, + the number of arguments specified for all such \tcode{P$_k$} + shall be the same number $N$. + The normal form of \tcode{F} is the normal form of + \tcode{E$_0$ Op $\dotsb$ Op E$_{N-1}$} + after substituting in \tcode{E$_i$} + the respective $i^\text{th}$ concept argument of each \tcode{P$_k$}. + If any such substitution results in an invalid type or expression, + the program is ill-formed; no diagnostic is required. + \item + Otherwise, + the normal form of \tcode{F} is + a fold expanded constraint\iref{temp.constr.fold} whose + constraint is \tcode{E$'$} and whose + \grammarterm{fold-operator} is \tcode{Op}. + \end{itemize} + \end{itemize} + \item The normal form of any other expression \tcode{E} is the atomic constraint @@ -1937,6 +2237,65 @@ The associated constraints of \#3 are \tcode{requires (T x) \{ ++x; \}} (with mapping $\tcode{T} \mapsto \tcode{U}$). \end{example} + +\begin{example} +\begin{codeblock} +template +concept C = true; +template concept CT> +concept CC = CT; + +template concept> concept CT> + void f() requires CT; +template + void g() requires CC; +\end{codeblock} +The normal form of the associated constraints of \tcode{f} is +the concept-dependent constraint \tcode{CT}.\\ +The normal form of the associated constraints of \tcode{g} is +the atomic constraint \tcode{true}. +\end{example} + +\begin{example} +\begin{codeblock} +template +concept A = true; +template +concept B = A && true; // \tcode{B} subsumes \tcode{A} +template +concept C = true; +template +concept D = C && true; // \tcode{D} subsumes \tcode{C} + +template concept... CTs> +concept all_of = (CTs && ...); + +template requires all_of + constexpr int f(T) { return 1; } // \#1 +template requires all_of + constexpr int f(T) { return 2; } // \#2 + +static_assert(f(1) == 2); // ok +\end{codeblock} +The normal form of \tcode{all_of} is +the conjunction of the normal forms of \tcode{A} and \tcode{C}.\\ +Similarly, the normal form of \tcode{all_of} is +the conjunction of the normal forms of \tcode{B} and \tcode{D}.\\ +\#2 therefore is more constrained than \#1. +\end{example} + +\begin{example} +\begin{codeblock} +template concept> +struct wrapper {}; + +template concept... CTs> + int f(wrapper...) requires (CTs && ...); // error: fold expression contains + // different kinds of template parameters +\end{codeblock} +\end{example} + \indextext{constraint!normalization|)} \rSec2[temp.constr.order]{Partial ordering by constraints} @@ -1949,7 +2308,7 @@ in the disjunctive normal form \begin{footnote} A constraint is in disjunctive normal form when it is a disjunction of -clauses where each clause is a conjunction of atomic constraints. +clauses where each clause is a conjunction of fold expanded or atomic constraints. For atomic constraints $A$, $B$, and $C$, the disjunctive normal form of the constraint $A \land (B \lor C)$ @@ -1962,7 +2321,7 @@ in the conjunctive normal form \begin{footnote} A constraint is in conjunctive normal form when it is a conjunction -of clauses where each clause is a disjunction of atomic constraints. +of clauses where each clause is a disjunction of fold expanded or atomic constraints. For atomic constraints $A$, $B$, and $C$, the constraint $A \land (B \lor C)$ is in conjunctive normal form. % @@ -1973,11 +2332,17 @@ \item a disjunctive clause $P_i$ subsumes a conjunctive clause $Q_j$ if and only if there exists an atomic constraint $P_{ia}$ in $P_i$ for which there exists -an atomic constraint $Q_{jb}$ in $Q_j$ such that $P_{ia}$ subsumes $Q_{jb}$, and +an atomic constraint $Q_{jb}$ in $Q_j$ such that $P_{ia}$ subsumes $Q_{jb}$, \item an atomic constraint $A$ subsumes another atomic constraint $B$ if and only if $A$ and $B$ are identical using the -rules described in \ref{temp.constr.atomic}. +rules described in \ref{temp.constr.atomic}, and + +\item a fold expanded constraint $A$ subsumes +another fold expanded constraint $B$ +if they are compatible for subsumption, +have the same \grammarterm{fold-operator}, and +the constraint of $A$ subsumes that of $B$. \end{itemize} % \begin{example} @@ -2003,6 +2368,14 @@ \end{itemize} \end{note} +\pnum +The associated constraints \tcode{C} of a declaration \tcode{D} +\indextext{subsumption!eligible for}% +are \defnx{eligible for subsumption}{eligible!for subsumption} +%%% FIXME: This "definiton" needs work. Do we mean: +%%% "if C can be subsumed and C does not contain a concept-dependent constraint"? +unless \tcode{C} contains a concept-dependent constraint. + %%% FIXME: We need to substitute the deductions from partial ordering %%% into the constraints before comparing them, otherwise they will be %%% referring to unrelated template parameters. @@ -2012,7 +2385,8 @@ a declaration \tcode{D2} if \begin{itemize} \item \tcode{D1} and \tcode{D2} are both constrained declarations and -\tcode{D1}'s associated constraints subsume those of \tcode{D2}; or +\tcode{D1}'s associated constraints +are eligible for subsumption and subsume those of \tcode{D2}; or \item \tcode{D2} has no associated constraints. \end{itemize} @@ -2038,6 +2412,37 @@ g(0); // selects \#4 \end{codeblock} \end{example} +\begin{example} +\begin{codeblock} +template concept CT, typename T> +struct S {}; +template +concept A = true; + +template concept X, typename T> +int f(S) requires A { return 42; } // \#1 +template concept X, typename T> +int f(S) requires X { return 43; } // \#2 + +f(S{}); // ok, select \#1 because \#2 is not eligible for subsumption +\end{codeblock} +\end{example} + +\pnum +A non-template function \tcode{F1} is \defn{more partial-ordering-constrained} +than a non-template function \tcode{F2} if +\begin{itemize} +\item +they have the same non-object-parameter-type-lists\iref{dcl.fct}, and +\item +if they are member functions, both are direct members of the same class, and +\item +if both are non-static member functions, +they have the same types for their object parameters, and +\item +the declaration of \tcode{F1} is more constrained than +the declaration of \tcode{F2}. +\end{itemize} \rSec1[temp.type]{Type equivalence} @@ -2057,7 +2462,7 @@ \item the template parameter values determined by -their corresponding non-type template arguments\iref{temp.arg.nontype} +their corresponding constant template arguments\iref{temp.arg.nontype} are template-argument-equivalent (see below), and \item @@ -2080,6 +2485,10 @@ \item they are of type \tcode{std::nullptr_t}, or +\item +they are of type \tcode{std::meta::info} and +their values compare equal\iref{expr.eq}, or + \item they are of enumeration type and their values are the same, \begin{footnote} @@ -2109,6 +2518,9 @@ they both have no active member or they have the same active member and their active members are template-argument-equivalent, or +\item +they are of a closure type\iref{expr.prim.lambda.closure}, or + \item they are of class type and their corresponding direct subobjects and reference members are template-argument-equivalent. @@ -2226,6 +2638,9 @@ \grammarterm{noexcept-specifier}{s}. For the purpose of instantiation, the substatements of a constexpr if statement\iref{stmt.if} are considered definitions. +For the purpose of name lookup and instantiation, +the \grammarterm{compound-statement} of an \grammarterm{expansion-statement} +is considered a template definition. \pnum Because an \grammarterm{alias-declaration} cannot declare a @@ -2412,8 +2827,8 @@ \pnum Deduction guides are used -when a \grammarterm{template-name} appears -as a type specifier +when a \grammarterm{template-name} or \grammarterm{splice-type-specifier} +appears as a type specifier for a deduced class type\iref{dcl.type.class.deduct}. Deduction guides are not found by name lookup. Instead, when performing class template argument deduction\iref{over.match.class.deduct}, @@ -2421,7 +2836,7 @@ \begin{bnf} \nontermdef{deduction-guide}\br - \opt{explicit-specifier} template-name \terminal{(} parameter-declaration-clause \terminal{)} \terminal{->} simple-template-id \terminal{;} + \opt{explicit-specifier} template-name \terminal{(} parameter-declaration-clause \terminal{)} \terminal{->} simple-template-id \opt{requires-clause} \terminal{;} \end{bnf} \pnum @@ -2531,7 +2946,6 @@ template struct A { enum E : T; }; -A a; template enum A::E : T { e1, e2 }; A::E e = A::e1; \end{codeblock} @@ -2641,7 +3055,7 @@ \begin{note} A specialization of a conversion function template -is referenced in +is named in the same way as a non-template conversion function that converts to the same type\iref{class.conv.fct}. \begin{example} @@ -2660,9 +3074,12 @@ } \end{codeblock} \end{example} -There is no syntax to form a \grammarterm{template-id}\iref{temp.names} -by providing an explicit template argument list\iref{temp.arg.explicit} -for a conversion function template. +An expression designating +a particular specialization of a conversion function template +can only be formed with a \grammarterm{splice-expression}. +There is no analogous syntax to form a \grammarterm{template-id}\iref{temp.names} +for such a function +by providing an explicit template argument list\iref{temp.arg.explicit}. \end{note} \rSec2[temp.variadic]{Variadic templates} @@ -2712,11 +3129,27 @@ \end{codeblock} \end{example} +\pnum +A \defn{structured binding pack} is an \grammarterm{sb-identifier} +that introduces zero or more structured bindings\iref{dcl.struct.bind}. +\begin{example} +\begin{codeblock} +auto foo() -> int(&)[2]; + +template +void g() { + auto [...a] = foo(); // \tcode{a} is a structured binding pack containing two elements + auto [b, c, ...d] = foo(); // \tcode{d} is a structured binding pack containing zero elements +} +\end{codeblock} +\end{example} + \pnum A \defn{pack} is a template parameter pack, a function parameter pack, -or an \grammarterm{init-capture} pack. +an \grammarterm{init-capture} pack, or +a structured binding pack. The number of elements of a template parameter pack or a function parameter pack is the number of arguments provided for the parameter pack. @@ -2739,6 +3172,9 @@ \item In a \grammarterm{using-declaration}\iref{namespace.udecl}; the pattern is a \grammarterm{using-declarator}. +\item In a \grammarterm{friend-type-declaration}\iref{class.mem.general}; +the pattern is a \grammarterm{friend-type-specifier}. + \item In a template parameter pack that is a pack expansion\iref{temp.param}: \begin{itemize} \item @@ -2748,6 +3184,14 @@ \item if the template parameter pack is a \grammarterm{type-parameter}; the pattern is the corresponding \grammarterm{type-parameter} +without the ellipsis; + +\item +if the template parameter pack is a template template parameter; +the pattern is the corresponding +\grammarterm{type-tt-parameter}, +\grammarterm{variable-tt-parameter}, or +\grammarterm{concept-tt-parameter} without the ellipsis. \end{itemize} @@ -2764,8 +3208,10 @@ \item In a \grammarterm{template-argument-list}\iref{temp.arg}; the pattern is a \grammarterm{template-argument}. -\item In an \grammarterm{attribute-list}\iref{dcl.attr.grammar}; the pattern is -an \grammarterm{attribute}. +\item In an \grammarterm{attribute-list}\iref{dcl.attr.grammar}; +the pattern is an \grammarterm{attribute}. +In an \grammarterm{annotation-list}; +the pattern is an \grammarterm{annotation}. \item In an \grammarterm{alignment-specifier}\iref{dcl.align}; the pattern is the \grammarterm{alignment-specifier} without the ellipsis. @@ -2785,6 +3231,9 @@ \item In a \grammarterm{fold-expression}\iref{expr.prim.fold}; the pattern is the \grammarterm{cast-expression} that contains an unexpanded pack. + +\item In a fold expanded constraint\iref{temp.constr.fold}; +the pattern is the constraint of that fold expanded constraint. \end{itemize} \begin{example} @@ -2848,16 +3297,20 @@ replacing each pack expansion parameter with its $i^\text{th}$ element. Such an element, in the context of the instantiation, is interpreted as follows: + \begin{itemize} \item if the pack is a template parameter pack, the element is -an \grammarterm{id-expression} -(for a non-type template parameter pack), -a \grammarterm{typedef-name} -(for a type template parameter pack declared without \tcode{template}), or -a \grammarterm{template-name} -(for a type template parameter pack declared with \tcode{template}), -designating the $i^\text{th}$ corresponding type or value template argument; +\begin{itemize} +\item +a \grammarterm{typedef-name} for a type template parameter pack, +\item +an \grammarterm{id-expression} for a constant template parameter pack, or +\item +a \grammarterm{template-name} for a template template parameter pack +\end{itemize} +designating the $i^\text{th}$ corresponding +type, constant, or template template argument; \item if the pack is a function parameter pack, the element is an @@ -2865,7 +3318,6 @@ designating the $i^\text{th}$ function parameter that resulted from instantiation of the function parameter pack declaration; -otherwise \item if the pack is an \grammarterm{init-capture} pack, @@ -2873,7 +3325,14 @@ designating the variable introduced by the $i^\text{th}$ \grammarterm{init-capture} that resulted from instantiation of -the \grammarterm{init-capture} pack declaration. +the \grammarterm{init-capture} pack declaration; +otherwise + +\item +if the pack is a structured binding pack, +the element is an \grammarterm{id-expression} +designating the $i^\textrm{th}$ structured binding in the pack +that resulted from the structured binding declaration. \end{itemize} When $N$ is zero, the instantiation of a pack expansion does not alter the syntactic interpretation of the enclosing construct, @@ -2972,6 +3431,9 @@ \tcode{,} & \tcode{void()} \\ \end{floattable} +\pnum +A fold expanded constraint is not instantiated\iref{temp.constr.fold}. + \pnum The instantiation of any other pack expansion produces a list of elements $\tcode{E}_1, \tcode{E}_2, \dotsc, \tcode{E}_N$. @@ -3299,9 +3761,9 @@ \end{example} \pnum -A non-type argument is non-specialized if it is the name of a non-type -parameter. -All other non-type arguments are specialized. +A constant template argument is non-specialized if it is the name of a constant +template parameter. +All other constant template arguments are specialized. \pnum Within the argument list of a partial specialization, @@ -3309,8 +3771,8 @@ \begin{itemize} \item -The type of a template parameter corresponding to a specialized non-type argument -shall not be dependent on a parameter of the partial specialization. +The type of a template parameter corresponding to a specialized constant template +argument shall not be dependent on a parameter of the partial specialization. \begin{example} \begin{codeblock} template struct C {}; @@ -3697,7 +4159,7 @@ \end{codeblock} \end{example} \begin{note} -Most expressions that use template parameters use non-type template +Most expressions that use template parameters use constant template parameters, but it is possible for an expression to reference a type parameter. For example, a template type parameter can be used in the @@ -3797,11 +4259,11 @@ \begin{itemize} \item they declare template parameters of the same kind, \item if either declares a template parameter pack, they both do, -\item if they declare non-type template parameters, +\item if they declare constant template parameters, they have equivalent types ignoring the use of \grammarterm{type-constraint}{s} for placeholder types, and -\item if they declare template template parameters, their template -parameters are equivalent. +\item if they declare template template parameters, +their \grammarterm{template-head}{s} are equivalent. \end{itemize} When determining whether types or \grammarterm{type-constraint}{s} are equivalent, the rules above are used to compare expressions @@ -3816,15 +4278,19 @@ whether two constructs are equivalent, and they are functionally equivalent but not equivalent, the program is ill-formed, no diagnostic required. -% FIXME: What does it mean for two function templates to correspond? -Furthermore, if two function templates that do not correspond +Furthermore, if two declarations $A$ and $B$ of function templates \begin{itemize} -\item have the same name, -\item have corresponding signatures\iref{basic.scope.scope}, -\item would declare the same entity\iref{basic.link} considering them to correspond, and -% FIXME: What does it mean for a set of template argument lists to satisfy a function template? -\item accept and are satisfied by the same set of template argument lists, +\item +introduce the same name, +\item +have corresponding signatures\iref{basic.scope.scope}, +\item +would declare the same entity, +when considering $A$ and $B$ to correspond in that determination\iref{basic.link}, and +\item +accept and are satisfied by the same set of template argument lists, \end{itemize} +but do not correspond, the program is ill-formed, no diagnostic required. \pnum @@ -3893,16 +4359,30 @@ the more constrained template (if one exists) as determined below. \pnum -To produce the transformed template, for each type, non-type, or template +To produce the transformed template, for each +%FIXME: Don't we want to append "template parameter" to each of these? +%FIXME: As is, it reads as if it only applies to "conecpt". +%FIXME: E.g., we mean "type template parameter", not "type". +type, constant, +type template, variable template, or concept template parameter (including template parameter packs\iref{temp.variadic} -thereof) synthesize a unique type, value, or class template -respectively and substitute it for each occurrence of that parameter +thereof) synthesize a unique type, value, class template, +variable template, or concept, +respectively, and substitute it for each occurrence of that parameter in the function type of the template. \begin{note} The type replacing the placeholder -in the type of the value synthesized for a non-type template parameter +in the type of the value synthesized for a constant template parameter is also a unique synthesized type. \end{note} + +\pnum +%FIXME: What's a "synthesized template"? Do we mean the synthesized +%FIXME: template described above? If so, say so. +A synthesized template has the same \grammarterm{template-head} as +its corresponding template template parameter. + +\pnum Each function template $M$ that is a member function is considered to have a new first parameter of type $X(M)$, described below, @@ -4128,11 +4608,22 @@ types. The name of the alias template is a \grammarterm{template-name}. \pnum -When a \grammarterm{template-id} refers to the specialization of -an alias template, it is equivalent to the associated type obtained by +A +\begin{itemize} +\item +\grammarterm{template-id} +that is not the operand of a \grammarterm{reflect-expression} or +\item +\grammarterm{splice-specialization-specifier} +\end{itemize} +that designates the specialization of +an alias template is equivalent to the associated type obtained by substitution of its \grammarterm{template-argument}{s} for the \grammarterm{template-parameter}{s} in the \grammarterm{defining-type-id} of the alias template. +Any other \grammarterm{template-id} +that names a specialization of an alias template is +a \grammarterm{typedef-name} for a type alias. \begin{note} An alias template name is never deduced. \end{note} @@ -4266,7 +4757,7 @@ \indextext{type concept|see{concept, type}}% A \defnx{type concept}{concept!type} is a concept whose prototype parameter -is a type \grammarterm{template-parameter}. +is a type template parameter. \rSec1[temp.res]{Name resolution} @@ -4357,7 +4848,7 @@ \begin{bnf} \nontermdef{typename-specifier}\br \keyword{typename} nested-name-specifier identifier\br - \keyword{typename} nested-name-specifier \terminal{\opt{template}} simple-template-id + \keyword{typename} nested-name-specifier \opt{\keyword{template}} simple-template-id \end{bnf} \pnum @@ -4397,16 +4888,20 @@ \pnum \indextext{type-only!context|see{context, type-only}}% +A \defnx{type-only context}{context!type-only} is defined as follows: A qualified or unqualified name is said to be in -a \defnx{type-only context}{context!type-only} -if it is the terminal name of +a type-only context if it is the terminal name of \begin{itemize} \item a \grammarterm{typename-specifier}, \grammarterm{type-requirement}, \grammarterm{nested-name-specifier}, \grammarterm{elaborated-type-specifier}, -\grammarterm{class-or-decltype}, or +\grammarterm{class-or-decltype}, +\grammarterm{using-enum-declarator}, +or +\item +a \grammarterm{simple-type-specifier} of a \grammarterm{friend-type-specifier}, or \item a \grammarterm{type-specifier} of a \begin{itemize} @@ -4438,20 +4933,30 @@ \item \grammarterm{parameter-declaration} in a \grammarterm{lambda-declarator} or \grammarterm{requirement-parameter-list}, unless that \grammarterm{parameter-declaration} appears in a default argument, or -\item \grammarterm{parameter-declaration} of a (non-type) \grammarterm{template-parameter}. +\item \grammarterm{parameter-declaration} of a \grammarterm{template-parameter} +(which necessarily declares a constant template parameter). \end{itemize} \end{itemize} +A \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier}\iref{basic.splice} +is said to be in a type-only context +if a hypothetical qualified name appearing in the same position +would be in a type-only context. \begin{example} \begin{codeblock} template T::R f(); // OK, return type of a function declaration at global scope template void f(T::R); // ill-formed, no diagnostic required: attempt to declare // a \keyword{void} variable template +enum class Enum { A, B, C }; template struct S { using Ptr = PtrTraits::Ptr; // OK, in a \grammarterm{defining-type-id} + using Alias = [:^^int:]; // OK, in a \grammarterm{defining-type-id} T::R f(T::P p) { // OK, class scope return static_cast(p); // OK, \grammarterm{type-id} of a \keyword{static_cast} } auto g() -> S::Ptr; // OK, \grammarterm{trailing-return-type} + auto h() -> [:^^S:]; // OK, \grammarterm{trailing-return-type} + using enum [:^^Enum:]; // OK, \grammarterm{using-enum-declarator} }; template void f() { void (*pf)(T::X); // variable \tcode{pf} of type \tcode{\keyword{void}*} initialized with \tcode{T::X} @@ -4498,7 +5003,7 @@ Knowing which names are type names allows the syntax of every template to be checked in this way. \end{note} -The program is ill-formed, no diagnostic required, if: +The program is ill-formed, no diagnostic required, if \begin{itemize} \item no valid specialization, @@ -4508,6 +5013,16 @@ within a templated entity and the innermost enclosing template is not instantiated, or \item +no valid specialization, +ignoring \grammarterm{static_assert-declaration}s that fail, +can be generated for the \grammarterm{compound-statement} +of an expansion statement and there is no instantiation of it, or +\item +no valid specialization, +ignoring \grammarterm{static_assert-declaration}{s} that fail, +can be generated for a default \grammarterm{template-argument} and +the default \grammarterm{template-argument} is not used in any instantiation, or +\item no specialization of an alias template\iref{temp.alias} is valid and no specialization of the alias template is named in the program, or \item @@ -4565,8 +5080,6 @@ \end{itemize} \end{note} -Otherwise, no diagnostic shall be issued for a template -for which a valid specialization can be generated. \begin{note} If a template is instantiated, errors will be diagnosed according to the other rules in this document. @@ -4614,7 +5127,7 @@ as a \grammarterm{template-name} or a \grammarterm{type-name}. When it is used with a \grammarterm{template-argument-list}, -as a \grammarterm{template-argument} for a template \grammarterm{template-parameter}, +as a \grammarterm{template-argument} for a type template template parameter, or as the final identifier in the \grammarterm{elaborated-type-specifier} of a friend class template declaration, it is a \grammarterm{template-name} that refers to the @@ -4708,21 +5221,21 @@ \end{example} \pnum -The name of a \grammarterm{template-parameter} +The name of a template parameter shall not be bound to any following declaration whose locus is contained by the scope -to which the template-parameter belongs. +to which the template parameter belongs. \begin{example} \begin{codeblock} template class Y { - int T; // error: \grammarterm{template-parameter} hidden + int T; // error: template parameter hidden void f() { - char T; // error: \grammarterm{template-parameter} hidden + char T; // error: template parameter hidden } friend void T(); // OK, no name bound }; -template class X; // error: hidden by \grammarterm{template-parameter} +template class X; // error: hidden by template parameter \end{codeblock} \end{example} @@ -4872,24 +5385,25 @@ \item in the definition of a nested class of a class template, the name of the nested class referenced as a member of the -current instantiation, or +current instantiation, \item in the definition of a class template partial specialization or a member of a class template partial specialization, the name of the class template followed by a template argument list equivalent to that of the partial specialization\iref{temp.spec.partial} -enclosed in \tcode{<>} (or an equivalent template alias specialization). +enclosed in \tcode{<>} (or an equivalent template alias specialization), or +\item +in the definition of a templated function, +the name of a local class\iref{class.local}. \end{itemize} \pnum A template argument that is equivalent to a template parameter can be used in place of that template parameter in a reference to the current instantiation. -For a template \grammarterm{type-parameter}, -a template argument is equivalent to a template parameter +A template argument is equivalent to a type template parameter if it denotes the same type. -For a non-type template parameter, -a template argument is equivalent to a template parameter +A template argument is equivalent to a constant template parameter if it is an \grammarterm{identifier} that names a variable that is equivalent to the template parameter. A variable is equivalent to a template parameter if @@ -5062,7 +5576,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{expr.prim.id.general} \end{codeblock} \end{example} @@ -5133,15 +5647,18 @@ \item denoted by a \grammarterm{simple-template-id} in which either the template name is a template parameter or any of the -template arguments is a dependent type or an expression that is type-dependent -or value-dependent or is a pack expansion, +template arguments is dependent\iref{temp.dep.temp}, \begin{footnote} This includes an injected-class-name\iref{class.pre} of a class template used without a \grammarterm{template-argument-list}. \end{footnote} -\item a \grammarterm{pack-index-specifier}, or +\item a \grammarterm{pack-index-specifier}, \item denoted by \tcode{decltype(}\grammarterm{expression}{}\tcode{)}, -where \grammarterm{expression} is type-dependent\iref{temp.dep.expr}. +where \grammarterm{expression} is type-dependent\iref{temp.dep.expr}, or +\item denoted by a \grammarterm{splice-type-specifier} in which either +the \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} +is dependent\iref{temp.dep.splice}. \end{itemize} \pnum @@ -5173,7 +5690,7 @@ declared with a dependent type, \item associated by name lookup with -a non-type \grammarterm{template-parameter} +a constant template parameter declared with a type that contains a placeholder type\iref{dcl.spec.auto}, \item @@ -5189,6 +5706,28 @@ a structured binding declaration\iref{dcl.struct.bind} whose \grammarterm{brace-or-equal-initializer} is type-dependent, \item +associated by name lookup with a pack, +\begin{example} +\begin{codeblock} +struct C { }; + +void g(...); // \#1 + +template +void f() { + C arr[1]; + auto [...e] = arr; + g(e...); // calls \#2 +} + +void g(C); // \#2 + +int main() { + f(); +} +\end{codeblock} +\end{example} +\item associated by name lookup with an entity captured by copy\iref{expr.prim.lambda.capture} in a \grammarterm{lambda-expression} @@ -5199,7 +5738,19 @@ \mname{func}\iref{dcl.fct.def.general}, where any enclosing function is a template, a member of a class template, or a generic lambda, \item -a \grammarterm{conversion-function-id} that specifies a dependent type, or +associated by name lookup +with a result binding\iref{dcl.contract.res} of a function +whose return type is dependent, +\item +a \grammarterm{conversion-function-id} that specifies a dependent type, +\item +a name $N$ introduced by the \grammarterm{for-range-declaration} +of an expansion statement $S$ +if the type specified for $N$ contains a placeholder type and either +\begin{itemize} +\item the \grammarterm{expansion-initializer} of $S$ is type-dependent or +\item $S$ is not an iterating expansion statement, or +\end{itemize} \item dependent \end{itemize} @@ -5245,7 +5796,8 @@ \opt{\terminal{::}} \keyword{delete} \terminal{[} \terminal{]} cast-expression\br \keyword{throw} \opt{assignment-expression}\br \keyword{noexcept} \terminal{(} expression \terminal{)}\br -requires-expression +requires-expression\br +reflect-expression \end{ncsimplebnf} \begin{note} @@ -5291,6 +5843,12 @@ A \grammarterm{pack-index-expression} is type-dependent if its \grammarterm{id-expression} is type-dependent. +\pnum +A \grammarterm{splice-expression} is type-dependent +if its \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} +is dependent\iref{temp.dep.splice}. + \rSec3[temp.dep.constexpr]{Value-dependent expressions} \pnum @@ -5301,14 +5859,19 @@ \pnum An \grammarterm{id-expression} -is value-dependent if: +is value-dependent if \begin{itemize} \item -it is a concept-id and any of its arguments are dependent, +it is a concept-id and +its \grammarterm{concept-name} is dependent or +any of its arguments are dependent\iref{temp.dep.temp}, \item it is type-dependent, \item -it is the name of a non-type template parameter, +it is the name of a constant template parameter, +\item +it is a name introduced by the \grammarterm{for-range-declaration} +of an expansion statement\iref{stmt.expand}, \item it names a static data member that is a dependent member of the current instantiation and is not initialized in a \grammarterm{member-declarator}, @@ -5331,8 +5894,7 @@ \keyword{sizeof} \terminal{(} type-id \terminal{)}\br \keyword{typeid} \terminal{(} expression \terminal{)}\br \keyword{typeid} \terminal{(} type-id \terminal{)}\br -\keyword{alignof} \terminal{(} type-id \terminal{)}\br -\keyword{noexcept} \terminal{(} expression \terminal{)} +\keyword{alignof} \terminal{(} type-id \terminal{)} \end{ncsimplebnf} \begin{note} @@ -5342,20 +5904,28 @@ \pnum Expressions of the following form are value-dependent if either the -\grammarterm{type-id} -or -\grammarterm{simple-type-specifier} +\grammarterm{type-id}, +\grammarterm{simple-type-specifier}, or +\grammarterm{typename-specifier} is dependent or the \grammarterm{expression} or \grammarterm{cast-expression} +is value-dependent or +any \grammarterm{expression} in the \grammarterm{expression-list} +is value-dependent or +any \grammarterm{assignment-expression} in the \grammarterm{braced-init-list} is value-dependent: \begin{ncsimplebnf} simple-type-specifier \terminal{(} \opt{expression-list} \terminal{)}\br +typename-specifier \terminal{(} \opt{expression-list} \terminal{)}\br +simple-type-specifier braced-init-list\br +typename-specifier braced-init-list\br \keyword{static_cast} \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br \keyword{const_cast} \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br \keyword{reinterpret_cast} \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br +\keyword{dynamic_cast} \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br \terminal{(} type-id \terminal{)} cast-expression \end{ncsimplebnf} @@ -5366,6 +5936,13 @@ \keyword{sizeof} \terminal{...} \terminal{(} identifier \terminal{)}\br fold-expression \end{ncsimplebnf} +unless the \grammarterm{identifier} is a structured binding pack +whose initializer is not dependent. + +\pnum +A \grammarterm{noexcept-expression}\iref{expr.unary.noexcept} +is value-dependent if +its \grammarterm{expression} involves a template parameter. \pnum An expression of the form \tcode{\&}\grammarterm{qualified-id} where the @@ -5377,6 +5954,107 @@ the result of the evaluation refers to a templated entity that is an object with static or thread storage duration or a member function. +\pnum +A \grammarterm{reflect-expression} is value-dependent if +\begin{itemize} +\item +it is of the form \tcode{\caret\caret \grammarterm{reflection-name}} and +the \grammarterm{reflection-name} +\begin{itemize} +\item is a dependent qualified name, +\item is a dependent \grammarterm{namespace-name}, +\item is the name of a template parameter, or +\item names a dependent member of the current instantiation\iref{temp.dep.type}, +\end{itemize} +\item +it is of the form \tcode{\caret\caret \grammarterm{type-id}} and +the \grammarterm{type-id} denotes a dependent type, or +\item +it is of the form \tcode{\caret\caret \grammarterm{id-expression}} and +the \grammarterm{id-expression} is value-dependent. +\end{itemize} + +\pnum +A \grammarterm{splice-expression} is value-dependent +if its \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} +is dependent\iref{temp.dep.splice}. + +\rSec3[temp.dep.splice]{Dependent splice specifiers} + +\pnum +A \grammarterm{splice-specifier} is dependent +if its converted \grammarterm{constant-expression} is value-dependent. +A \grammarterm{splice-specialization-specifier} is dependent +if its \grammarterm{splice-specifier} is dependent or +if any of its template arguments are dependent. +A \grammarterm{splice-scope-specifier} is dependent +if its \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} is dependent. + +\pnum +\begin{example} +\begin{codeblock} +template +void fn() { + using a = [:T:]<1>; // \tcode{[:T:]<1>} is dependent because \tcode{[:T:]} is dependent + static_assert([:NS:]::template TCls<1>::v == a::v); // \tcode{[:NS:]} is dependent +} + +namespace N { + template struct TCls { static constexpr int v = V; }; +} + +int main() { + fn<^^N::TCls, ^^N>(); +} +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblock} +template class X> +struct S { + [:^^X:] m; +}; + +template struct V1 {}; +template struct V2 {}; + +S s1; // error: \tcode{V1} has too many template arguments +S s2; // OK +\end{codeblock} +\end{example} + +\rSec3[temp.dep.namespace]{Dependent namespaces} + +\pnum +A namespace alias is dependent +if it is introduced by a \grammarterm{namespace-alias-definition} +whose \grammarterm{qualified-namespace-specifier} (if any) is +a dependent qualified name or +whose \grammarterm{splice-specifier} (if any) is dependent. +A \grammarterm{namespace-name} is dependent +if it names a dependent namespace alias. + +\pnum +\begin{example} +\begin{codeblock} +template +int fn() { + namespace Alias = [:R:]; // \tcode{[:R:]} is dependent + return typename Alias::T{}; // \tcode{Alias} is dependent +} + +namespace NS { + using T = int; +} + +int a = fn<^^NS>(); +\end{codeblock} +\end{example} + \rSec3[temp.dep.temp]{Dependent template arguments} \pnum @@ -5385,22 +6063,26 @@ is dependent if the type it specifies is dependent. \pnum -A non-type +A constant \grammarterm{template-argument} is dependent if its type is dependent or the constant expression it specifies is value-dependent. \pnum -Furthermore, a non-type +Furthermore, a constant \grammarterm{template-argument} -is dependent if the corresponding non-type \grammarterm{template-parameter} +is dependent if the corresponding constant template parameter is of reference or pointer type and the \grammarterm{template-argument} designates or points to a member of the current instantiation or a member of a dependent type. \pnum -A template \grammarterm{template-parameter} is dependent if -it names a \grammarterm{template-parameter} or +%FIXME: "also" adds nothing here and reads like a note; remove it? +A template argument is also dependent if it is a pack expansion. + +\pnum +A template template parameter is dependent if +it names a template parameter or its terminal name is dependent. \rSec2[temp.dep.res]{Dependent name resolution} @@ -5439,8 +6121,6 @@ scope declaration or definition that requires the \grammarterm{noexcept-specifier}. - - \pnum For a class template specialization, a class member template specialization, or a specialization for a class member of a class template, @@ -5496,6 +6176,14 @@ different meanings according to the one-definition rule\iref{basic.def.odr}, the program is ill-formed, no diagnostic required. +\pnum +For the \grammarterm{compound-statement} +of an expansion statement\iref{stmt.expand}, +the point of instantiation is the point of instantiation +of its enclosing templated entity, if any. +Otherwise, it immediately follows the namespace-scope declaration +or definition that contains the expansion statement. + \rSec3[temp.dep.candidate]{Candidate functions} \pnum @@ -6148,13 +6836,15 @@ \end{example} \pnum -The \grammarterm{noexcept-specifier} of a function template specialization -is not instantiated along with the function declaration; it is instantiated -when needed\iref{except.spec}. If such an -\grammarterm{noexcept-specifier} is needed but has not yet been +The \grammarterm{noexcept-specifier} and \grammarterm{function-contract-specifier}s +of a function template specialization +are not instantiated along with the function declaration; +they are instantiated +when needed\iref{except.spec,dcl.contract.func}. If such a +specifier is needed but has not yet been instantiated, the dependent names are looked up, the semantics constraints are checked, and the instantiation of any template used in the -\grammarterm{noexcept-specifier} is done as if it were being done as part +specifier is done as if it were being done as part of instantiating the declaration of the specialization at that point. \pnum @@ -6286,7 +6976,7 @@ template void Array::mf(); template void sort(Array& v) { @\commentellip@ } -template void sort(Array&); // argument is deduced here +template void sort(Array&); // argument is deduced here\iref{temp.arg.explicit} namespace N { template void f(T&) { } @@ -6347,24 +7037,6 @@ data member of a class template shall be present in every translation unit in which it is explicitly instantiated. -\pnum -A trailing -\grammarterm{template-argument} -can be left unspecified in an explicit instantiation of a function template -specialization or of a member function template specialization provided -it can be deduced\iref{temp.deduct.decl}. -If all template arguments can be deduced, -the empty template argument list \tcode{<>} may be omitted. -\begin{example} -\begin{codeblock} -template class Array { @\commentellip@ }; -template void sort(Array& v) { @\commentellip@ } - -// instantiate \tcode{sort(Array\&)} -- template-argument deduced -template void sort<>(Array&); -\end{codeblock} -\end{example} - \pnum \begin{note} An explicit instantiation of a constrained template needs @@ -6474,28 +7146,29 @@ \begin{codeblock} template class stream; -template<> class stream { @\commentellip@ }; +template<> class stream { @\commentellip@ }; // \#1 template class Array { @\commentellip@ }; template void sort(Array& v) { @\commentellip@ } -template<> void sort(Array&); +template<> void sort(Array&); // \#2 +template<> void sort(Array&); // \#3 template argument is deduced\iref{temp.arg.explicit} \end{codeblock} Given these declarations, -\tcode{stream} -will be used as the definition of streams of +\#1 will be used as the definition of streams of \tcode{char}s; other streams will be handled by class template specializations instantiated from the class template. Similarly, -\tcode{sort} -will be used as the sort function for arguments +\#2 will be used as the sort function for arguments of +type \tcode{Array} and +\#3 will be used for arguments of type \tcode{Array}; other \tcode{Array} -types will be sorted by functions generated from the template. +types will be sorted by functions generated from the function template. \end{example} \pnum @@ -6672,11 +7345,10 @@ or to make it compile will be such a trial as to kindle its self-immolation. \pnum -A -\grammarterm{simple-template-id} -that names a class template explicit specialization that has been declared but -not defined can be used exactly like the names of other incompletely-defined -classes\iref{basic.types}. +\begin{note} +A class template explicit specialization that has been declared but +not defined can be used exactly like other +incompletely-defined classes\iref{basic.types}. \begin{example} \begin{codeblock} template class X; // \tcode{X} is a class template @@ -6686,24 +7358,7 @@ X x; // error: object of incomplete class \tcode{X} \end{codeblock} \end{example} - -\pnum -A trailing -\grammarterm{template-argument} -can be left unspecified in the -\grammarterm{template-id} -naming an explicit function template specialization -provided it can be deduced\iref{temp.deduct.decl}. -\begin{example} -\begin{codeblock} -template class Array { @\commentellip@ }; -template void sort(Array& v); - -// explicit specialization for \tcode{sort(Array\&)} -// with deduced template-argument of type \tcode{int} -template<> void sort(Array&); -\end{codeblock} -\end{example} +\end{note} \pnum \begin{note} @@ -6727,7 +7382,8 @@ is determined by the explicit specialization and is independent of those properties of the template. Similarly, -attributes appearing in the declaration of a template +attributes and \grammarterm{function-contract-specifier}s +appearing in the declaration of a template have no effect on an explicit specialization of that template. \begin{example} \begin{codeblock} @@ -7024,13 +7680,12 @@ \pnum Template arguments that are present shall be specified in the declaration -order of their corresponding -\grammarterm{template-parameter}{s}. +order of their corresponding template parameters. The template argument list shall not specify more \grammarterm{template-argument}{s} than there are corresponding \grammarterm{template-parameter}{s} -unless one of the \grammarterm{template-parameter}{s} is a template +unless one of the \grammarterm{template-parameter}{s} declares a template parameter pack. \begin{example} \begin{codeblock} @@ -7049,8 +7704,7 @@ \pnum Implicit conversions\iref{conv} will be performed on a function argument to convert it to the type of the corresponding function parameter if -the parameter type contains no -\grammarterm{template-parameter}{s} +the parameter type contains no template parameters that participate in template argument deduction. \begin{note} Template parameters do not participate in template argument deduction if @@ -7124,7 +7778,8 @@ \pnum When an explicit template argument list is specified, if the -given \grammarterm{template-id} is not valid\iref{temp.names}, +given \grammarterm{template-id} or +\grammarterm{splice-specialization-specifier} is not valid\iref{temp.names}, type deduction fails. Otherwise, the specified template argument values are substituted for the corresponding template parameters as specified below. @@ -7275,8 +7930,13 @@ cause template instantiations to occur in a different order or not at all, the program is ill-formed; no diagnostic required. \begin{note} -The equivalent substitution in exception specifications is -done only when the \grammarterm{noexcept-specifier} is instantiated, +The equivalent substitution in +exception specifications\iref{except.spec} +and function contract assertions\iref{dcl.contract.func} +is done only when +the \grammarterm{noexcept-specifier} +or \grammarterm{function-contract-specifier}, respectively, +is instantiated, at which point a program is ill-formed if the substitution results in an invalid type or expression. \end{note} @@ -7403,7 +8063,8 @@ \item the specified member is not a template where a template is required, or \item -the specified member is not a non-type where a non-type is required. +the specified member is not a non-type, non-template where a non-type, +non-template is required. \end{itemize} \begin{example} \begin{codeblock} @@ -7425,7 +8086,7 @@ // Deduction fails in each of these cases: f(0); // \tcode{A} does not contain a member \tcode{Y} f(0); // The \tcode{Y} member of \tcode{B} is not a type - g(0); // The \tcode{N} member of \tcode{C} is not a non-type + g(0); // The \tcode{N} member of \tcode{C} is not a non-type, non-template name h(0); // The \tcode{TT} member of \tcode{D} is not a template } \end{codeblock} @@ -7444,7 +8105,7 @@ \end{codeblock} \end{example} \item -Attempting to give an invalid type to a non-type template parameter. +Attempting to give an invalid type to a constant template parameter. \begin{example} \begin{codeblock} template struct S {}; @@ -7452,7 +8113,7 @@ class X { int m; }; -int i0 = f(0); // \#1 uses a value of non-structural type \tcode{X} as a non-type template argument +int i0 = f(0); // \#1 uses a value of non-structural type \tcode{X} as a constant template argument \end{codeblock} \end{example} @@ -7471,6 +8132,13 @@ Attempting to create a function type in which a parameter has a type of \keyword{void}, or in which the return type is a function type or array type. + +\item +%FIXME: What's it mean to "give" a type "to" a parameter? +%FIXME: See also "Attempting to give an invalid type to ..." above. +Attempting to give to +an explicit object parameter of a lambda's function call operator +a type not permitted for such\iref{expr.prim.lambda.closure}. \end{itemize} \end{note} @@ -7500,12 +8168,12 @@ Template argument deduction is done by comparing each function template parameter type (call it \tcode{P}) -that contains \grammarterm{template-parameter}{s} that participate in template argument deduction +that contains template parameters that participate in template argument deduction with the type of the corresponding argument of the call (call it \tcode{A}) as described below. If removing references and cv-qualifiers from \tcode{P} gives -\tcode{std::initializer_list} +$\tcode{std::initializer_list}$ or $\tcode{P}'\tcode{[N]}$ for some $\tcode{P}'$ and \tcode{N} and the argument is a non-empty initializer list\iref{dcl.init.list}, then deduction is @@ -7513,7 +8181,7 @@ taking $\tcode{P}'$ as separate function template parameter types $\tcode{P}'_i$ and the $i^\text{th}$ initializer element as the corresponding argument. -In the $\tcode{P}'\tcode{[N]}$ case, if \tcode{N} is a non-type template parameter, +In the $\tcode{P}'\tcode{[N]}$ case, if \tcode{N} is a constant template parameter, \tcode{N} is deduced from the length of the initializer list. Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context\iref{temp.deduct.type}. @@ -7702,7 +8370,8 @@ is a class and \tcode{P} has the form -\grammarterm{simple-template-id}, +\grammarterm{simple-template-id} or +\opt{\keyword{typename}} \grammarterm{splice-specialization-specifier}, then the transformed \tcode{A} can be a derived class \tcode{D} of the @@ -7711,10 +8380,11 @@ Likewise, if \tcode{P} is a pointer to a class of the form -\grammarterm{simple-template-id}, +\grammarterm{simple-template-id} or +\opt{\keyword{typename}} \grammarterm{splice-specialization-specifier}, the transformed \tcode{A} can be a pointer to a -derived class \tcode{D} pointed to by the deduced +derived class \tcode{D} of the class pointed to by the deduced \tcode{A}. However, if there is a class \tcode{C} that is a (direct or indirect) base class of \tcode{D} and @@ -7747,8 +8417,7 @@ \tcode{A}, the type deduction fails. \begin{note} -If a -\grammarterm{template-parameter} +If a template parameter is not used in any of the function parameters of a function template, or is used only in a non-deduced context, its corresponding \grammarterm{template-argument} @@ -7767,10 +8436,11 @@ the parameter is treated as a non-deduced context. \item If the argument is an overload set (not containing function templates), trial -argument deduction is attempted using each of the members of the set. If -deduction succeeds for only one of the overload set members, that member is -used as the argument value for the deduction. If deduction succeeds for more than -one member of the overload set the parameter is treated as a non-deduced context. +argument deduction is attempted using each of the members of the set +whose associated constraints\iref{temp.constr.constr} are satisfied. +If all successful deductions yield the same deduced \tcode{A}, +that deduced \tcode{A} is the result of deduction; +otherwise, the parameter is treated as a non-deduced context. \end{itemize} \pnum @@ -7806,6 +8476,21 @@ \end{codeblock} \end{example} +\pnum +\begin{example} +\begin{codeblock} +// All arguments for placeholder type deduction\iref{dcl.type.auto.deduct} yield the same deduced type. +template struct X { + static void f(short) requires B; // \#1 + static void f(short); // \#2 +}; +void test() { + auto x = &X::f; // OK, deduces \tcode{void(*)(short)}, selects \#1 + auto y = &X::f; // OK, deduces \tcode{void(*)(short)}, selects \#2 +} +\end{codeblock} +\end{example} + \rSec3[temp.deduct.funcaddr]{Deducing template arguments taking the address of a function template} \pnum @@ -8138,8 +8823,8 @@ is compared with an actual type (call it \tcode{A}), and an attempt is made to find template argument values (a type for a type -parameter, a value for a non-type parameter, or a template for a -template parameter) that will make +parameter, a value for a constant template parameter, or a template for a +template template parameter) that will make \tcode{P}, after substitution of the deduced values (call it the deduced \tcode{A}), @@ -8175,7 +8860,7 @@ A given type \tcode{P} can be composed from a number of other -types, templates, and non-type values: +types, templates, and constant template argument values: \begin{itemize} \item @@ -8187,7 +8872,7 @@ \item A type that is a specialization of a class template (e.g., \tcode{A}) -includes the types, templates, and non-type values referenced by the +includes the types, templates, and constant template argument values referenced by the template argument list of the specialization. \item An array type includes the array element type and the value of the @@ -8195,7 +8880,7 @@ \end{itemize} \pnum -In most cases, the types, templates, and non-type values that are used +In most cases, the types, templates, and constant template argument values that are used to compose \tcode{P} participate in template argument deduction. @@ -8211,7 +8896,7 @@ explicitly specified, template argument deduction fails. \begin{note} Under \ref{temp.deduct.call}, -if \tcode{P} contains no \grammarterm{template-parameter}{s} that appear +if \tcode{P} contains no template parameters that appear in deduced contexts, no deduction is done, so \tcode{P} and \tcode{A} need not have the same form. \end{note} @@ -8229,9 +8914,13 @@ \item A \grammarterm{pack-index-specifier} or a \grammarterm{pack-index-expression}. \item +A \grammarterm{type-constraint}. +\item The \grammarterm{expression} of a \grammarterm{decltype-specifier}. \item -A non-type template argument or an array bound in which a subexpression +The \grammarterm{constant-expression} of a \grammarterm{splice-specifier}. +\item +A constant template argument or an array bound in which a subexpression references a template parameter. \item A template parameter used in the parameter type of a function parameter that @@ -8239,16 +8928,22 @@ deduction is being done. \item A function parameter for which the associated argument is an -overload set\iref{over.over}, and one or more of the following apply: +overload set such that one or more of the following apply: \begin{itemize} \item -more than one function matches the function parameter type (resulting in -an ambiguous deduction), or +functions whose associated constraints are satisfied and +that do not all have the same function type +match the function parameter type (resulting in an ambiguous deduction), or \item -no function matches the function parameter type, or +no function whose associated constraints are satisfied +matches the function parameter type, or \item the overload set supplied as an argument contains one or more function templates. \end{itemize} +\begin{tailnote} +A particular function from the overload set is selected\iref{over.over} +after template argument deduction has succeeded\iref{temp.over}. +\end{tailnote} \item A function parameter for which the associated argument is an initializer list\iref{dcl.init.list} but the parameter does not have a type for which deduction from an initializer list is specified\iref{temp.deduct.call}. @@ -8383,12 +9078,12 @@ \end{example} \pnum -A template type argument -\tcode{T}, -a template template argument -\tcode{TT}, -or a template non-type argument -\tcode{i} +A type template argument \tcode{T}, +a constant template argument \tcode{i}, +a template template argument \tcode{TT} +denoting a class template or an alias template, or +a template template argument \tcode{VV} +denoting a variable template or a concept can be deduced if \tcode{P} and @@ -8405,6 +9100,7 @@ @\opt{TT}@ @\opt{TT}@ @\opt{TT}@ +@\opt{TT}@ @\opt{TT}@<> \end{codeblock} where @@ -8415,15 +9111,15 @@ is a non-deduced context in \tcode{P} or \tcode{A}, or is the same non-dependent type in \tcode{P} and \tcode{A}, -\item -\tcode{\opt{TT}} represents either a class template or -a template template parameter, - \item \tcode{\opt{i}} represents an expression that either is an \tcode{i}, is value-dependent in \tcode{P} or \tcode{A}, or -has the same constant value in \tcode{P} and \tcode{A}, and +has the same constant value in \tcode{P} and \tcode{A}, + +\item +\tcode{\opt{TT}} represents either a class template or +a template template parameter, and \item \tcode{\keyword{noexcept}(\opt{i})} represents an @@ -8439,22 +9135,18 @@ \end{note} Similarly, -\tcode{} -represents template argument lists where at least one argument contains a -\tcode{T}, -\tcode{} -represents template argument lists where at least one argument contains an -\tcode{i} +\tcode{<$X$>} represents template argument lists where +at least one argument contains an $X$, where +$X$ is one of \tcode{T}, \tcode{i}, \tcode{TT}, or \tcode{VV}; and \tcode{<>} represents template argument lists where no argument contains a -\tcode{T} -or an -\tcode{i}. +\tcode{T}, an \tcode{i}, a \tcode{TT}, or a \tcode{VV}. \pnum -If \tcode{P} has a form that contains \tcode{} -or \tcode{}, then each argument $\mathtt{P}_i$ of the +If \tcode{P} has a form that contains +\tcode{}, \tcode{}, \tcode{}, or \tcode{}, +then each argument $\mathtt{P}_i$ of the respective template argument list of \tcode{P} is compared with the corresponding argument $\mathtt{A}_i$ of the corresponding template argument list of \tcode{A}. If the template argument list @@ -8575,7 +9267,7 @@ \pnum When the value of the argument -corresponding to a non-type template parameter \tcode{P} +corresponding to a constant template parameter \tcode{P} that is declared with a dependent type is deduced from an expression, the template parameters in the type of \tcode{P} @@ -8657,8 +9349,8 @@ \pnum \begin{note} -If, in the declaration of a function template with a non-type -template parameter, the non-type template parameter +If, in the declaration of a function template with a constant +template parameter, the constant template parameter is used in a subexpression in the function parameter list, the expression is a non-deduced context as specified above. \begin{example} @@ -8701,16 +9393,14 @@ If \tcode{P} has a form that contains \tcode{}, and if the type of \tcode{i} differs from the type of the corresponding template parameter -of the template named by the enclosing \grammarterm{simple-template-id}, -deduction fails. +of the template named by the enclosing \grammarterm{simple-template-id} or +\grammarterm{splice-specialization-specifier}, deduction fails. If \tcode{P} has a form that contains \tcode{[i]}, and if the type of \tcode{i} is not an integral type, deduction fails. \begin{footnote} Although the \grammarterm{template-argument} -corresponding to a -\grammarterm{template-parameter} -of type +corresponding to a template parameter of type \tcode{bool} can be deduced from an array bound, the resulting value will always be \tcode{true} @@ -8778,8 +9468,7 @@ \pnum The \grammarterm{template-argument} -corresponding to a template -\grammarterm{template-parameter} +corresponding to a template template parameter is deduced from the type of the \grammarterm{template-argument} of a class template specialization used in the argument list of a function call. @@ -8916,8 +9605,7 @@ \pnum \begin{example} Here is an example involving conversions on a function argument involved in -\grammarterm{template-argument} -deduction: +template argument deduction: \begin{codeblock} template struct B { @\commentellip@ }; template struct D : public B { @\commentellip@ }; @@ -8933,8 +9621,7 @@ \pnum \begin{example} Here is an example involving conversions on a function argument not involved in -\grammarterm{template-parameter} -deduction: +template argument deduction: \begin{codeblock} template void f(T*,int); // \#1 template void f(T,char); // \#2 diff --git a/source/text.tex b/source/text.tex new file mode 100644 index 0000000000..df1715da2b --- /dev/null +++ b/source/text.tex @@ -0,0 +1,13371 @@ +%!TEX root = std.tex + +\rSec0[text]{Text processing library} + +\rSec1[text.general]{General} + +This Clause describes components for dealing with text. +These components are summarized in \tref{text.summary}. + +\begin{libsumtab}{Text library summary}{text.summary} +\ref{charconv} & Primitive numeric conversions & \tcode{} \\ \rowsep +\ref{localization} & Localization library & \tcode{}, \tcode{} \\ \rowsep +\ref{format} & Formatting & \tcode{} \\ \rowsep +\ref{text.encoding} & Text encodings identification & \tcode{} \\ \rowsep +\ref{re} & Regular expressions library & \tcode{} \\ \rowsep +\ref{text.c.strings} & Null-terminated sequence utilities & + \tcode{}, \tcode{}, \tcode{}, \tcode{}, \tcode{} \\ +\end{libsumtab} + +\rSec1[charconv]{Primitive numeric conversions} + +\rSec2[charconv.syn]{Header \tcode{} synopsis} + +\pnum +When a function is specified +with a type placeholder of \tcode{\placeholder{integer-type}}, +the implementation provides overloads +for \tcode{char} and all cv-unqualified signed and unsigned integer types +in lieu of \tcode{\placeholder{integer-type}}. +When a function is specified +with a type placeholder of \tcode{\placeholder{floating-point-type}}, +the implementation provides overloads +for all cv-unqualified floating-point types\iref{basic.fundamental} +in lieu of \tcode{\placeholder{floating-point-type}}. + +\indexheader{charconv}% +\begin{codeblock} +namespace std { + // floating-point format for primitive numerical conversion + enum class @\libglobal{chars_format}@ { + @\libmember{scientific}{chars_format}@ = @\unspec@, + @\libmember{fixed}{chars_format}@ = @\unspec@, + @\libmember{hex}{chars_format}@ = @\unspec@, + @\libmember{general}{chars_format}@ = fixed | scientific + }; + + // \ref{charconv.to.chars}, primitive numerical output conversion + struct @\libglobal{to_chars_result}@ { // freestanding + char* @\libmember{ptr}{to_chars_result}@; + errc @\libmember{ec}{to_chars_result}@; + friend bool operator==(const to_chars_result&, const to_chars_result&) = default; + constexpr explicit operator bool() const noexcept { return ec == errc{}; } + }; + + constexpr to_chars_result to_chars(char* first, char* last, // freestanding + @\placeholder{integer-type}@ value, int base = 10); + to_chars_result to_chars(char* first, char* last, // freestanding + bool value, int base = 10) = delete; + + to_chars_result to_chars(char* first, char* last, // freestanding-deleted + @\placeholder{floating-point-type}@ value); + to_chars_result to_chars(char* first, char* last, // freestanding-deleted + @\placeholder{floating-point-type}@ value, chars_format fmt); + to_chars_result to_chars(char* first, char* last, // freestanding-deleted + @\placeholder{floating-point-type}@ value, chars_format fmt, int precision); + + // \ref{charconv.from.chars}, primitive numerical input conversion + struct @\libglobal{from_chars_result}@ { // freestanding + const char* @\libmember{ptr}{from_chars_result}@; + errc @\libmember{ec}{from_chars_result}@; + friend bool operator==(const from_chars_result&, const from_chars_result&) = default; + constexpr explicit operator bool() const noexcept { return ec == errc{}; } + }; + + constexpr from_chars_result from_chars(const char* first, const char* last, // freestanding + @\placeholder{integer-type}@& value, int base = 10); + + from_chars_result from_chars(const char* first, const char* last, // freestanding-deleted + @\placeholder{floating-point-type}@& value, + chars_format fmt = chars_format::general); +} +\end{codeblock} + +\pnum +The type \tcode{chars_format} is a bitmask type\iref{bitmask.types} +with elements \tcode{scientific}, \tcode{fixed}, and \tcode{hex}. + +\pnum +The types \tcode{to_chars_result} and \tcode{from_chars_result} +have the data members and special members specified above. +They have no base classes or members other than those specified. + +\rSec2[charconv.to.chars]{Primitive numeric output conversion} + +\pnum +All functions named \tcode{to_chars} +convert \tcode{value} into a character string +by successively filling the range +\range{first}{last}, +where \range{first}{last} is required to be a valid range. +If the member \tcode{ec} +of the return value +is such that the value +is equal to the value of a value-initialized \tcode{errc}, +the conversion was successful +and the member \tcode{ptr} +is the one-past-the-end pointer of the characters written. +Otherwise, +the member \tcode{ec} has the value \tcode{errc::value_too_large}, +the member \tcode{ptr} has the value \tcode{last}, +and the contents of the range \range{first}{last} are unspecified. + +\pnum +The functions that take a floating-point \tcode{value} +but not a \tcode{precision} parameter +ensure that the string representation +consists of the smallest number of characters +such that +there is at least one digit before the radix point (if present) and +parsing the representation using the corresponding \tcode{from_chars} function +recovers \tcode{value} exactly. +\begin{note} +This guarantee applies only if +\tcode{to_chars} and \tcode{from_chars} +are executed on the same implementation. +\end{note} +If there are several such representations, +the representation with the smallest difference from +the floating-point argument value is chosen, +resolving any remaining ties using rounding according to +\tcode{round_to_nearest}\iref{round.style}. + +\pnum +The functions taking a \tcode{chars_format} parameter +determine the conversion specifier for \tcode{printf} as follows: +The conversion specifier is +\tcode{f} if \tcode{fmt} is \tcode{chars_format::fixed}, +\tcode{e} if \tcode{fmt} is \tcode{chars_format::scientific}, +\tcode{a} (without leading \tcode{"0x"} in the result) +if \tcode{fmt} is \tcode{chars_format::hex}, +and +\tcode{g} if \tcode{fmt} is \tcode{chars_format::general}. + +\indexlibraryglobal{to_chars}% +\begin{itemdecl} +constexpr to_chars_result to_chars(char* first, char* last, @\placeholder{integer-type}@ value, int base = 10); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{base} has a value between 2 and 36 (inclusive). + +\pnum +\effects +The value of \tcode{value} is converted +to a string of digits in the given base +(with no redundant leading zeroes). +Digits in the range 10..35 (inclusive) +are represented as lowercase characters \tcode{a}..\tcode{z}. +If \tcode{value} is less than zero, +the representation starts with \tcode{'-'}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibraryglobal{to_chars}% +\begin{itemdecl} +to_chars_result to_chars(char* first, char* last, @\placeholder{floating-point-type}@ value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\tcode{value} is converted to a string +in the style of \tcode{printf} +in the \tcode{"C"} locale. +The conversion specifier is \tcode{f} or \tcode{e}, +chosen according to the requirement for a shortest representation +(see above); +a tie is resolved in favor of \tcode{f}. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibraryglobal{to_chars}% +\begin{itemdecl} +to_chars_result to_chars(char* first, char* last, @\placeholder{floating-point-type}@ value, chars_format fmt); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{fmt} has the value of +one of the enumerators of \tcode{chars_format}. + +\pnum +\effects +\tcode{value} is converted to a string +in the style of \tcode{printf} +in the \tcode{"C"} locale. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibraryglobal{to_chars}% +\begin{itemdecl} +to_chars_result to_chars(char* first, char* last, @\placeholder{floating-point-type}@ value, + chars_format fmt, int precision); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{fmt} has the value of +one of the enumerators of \tcode{chars_format}. + +\pnum +\effects +\tcode{value} is converted to a string +in the style of \tcode{printf} +in the \tcode{"C"} locale +with the given precision. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\xrefc{7.21.6.1} + +\rSec2[charconv.from.chars]{Primitive numeric input conversion} + +\pnum +All functions named \tcode{from_chars} +analyze the string \range{first}{last} +for a pattern, +where \range{first}{last} is required to be a valid range. +If no characters match the pattern, +\tcode{value} is unmodified, +the member \tcode{ptr} of the return value is \tcode{first} and +the member \tcode{ec} is equal to \tcode{errc::invalid_argument}. +\begin{note} +If the pattern allows for an optional sign, +but the string has no digit characters following the sign, +no characters match the pattern. +\end{note} +Otherwise, +the characters matching the pattern +are interpreted as a representation +of a value of the type of \tcode{value}. +The member \tcode{ptr} +of the return value +points to the first character +not matching the pattern, +or has the value \tcode{last} +if all characters match. +If the parsed value +is not in the range +representable by the type of \tcode{value}, +\tcode{value} is unmodified and +the member \tcode{ec} of the return value +is equal to \tcode{errc::result_out_of_range}. +Otherwise, +\tcode{value} is set to the parsed value, +after rounding according to \tcode{round_to_nearest}\iref{round.style}, and +the member \tcode{ec} is value-initialized. + +\indexlibraryglobal{from_chars}% +\begin{itemdecl} +constexpr from_chars_result from_chars(const char* first, const char* last, + @\placeholder{integer-type}@&@\itcorr[-1]@ value, int base = 10); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{base} has a value between 2 and 36 (inclusive). + +\pnum +\effects +The pattern is the expected form of the subject sequence +in the \tcode{"C"} locale +for the given nonzero base, +as described for \tcode{strtol}, +except that no \tcode{"0x"} or \tcode{"0X"} prefix shall appear +if the value of \tcode{base} is 16, +and except that \tcode{'-'} +is the only sign that may appear, +and only if \tcode{value} has a signed type. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\indexlibraryglobal{from_chars}% +\begin{itemdecl} +from_chars_result from_chars(const char* first, const char* last, @\placeholder{floating-point-type}@& value, + chars_format fmt = chars_format::general); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{fmt} has the value of +one of the enumerators of \tcode{chars_format}. + +\pnum +\effects +The pattern is the expected form of the subject sequence +in the \tcode{"C"} locale, +as described for \tcode{strtod}, +except that +\begin{itemize} +\item +the sign \tcode{'+'} may only appear in the exponent part; +\item +if \tcode{fmt} has \tcode{chars_format::scientific} set +but not \tcode{chars_format::fixed}, +the otherwise optional exponent part shall appear; +\item +if \tcode{fmt} has \tcode{chars_format::fixed} set +but not \tcode{chars_format::scientific}, +the optional exponent part shall not appear; and +\item +if \tcode{fmt} is \tcode{chars_format::hex}, +the prefix \tcode{"0x"} or \tcode{"0X"} is assumed. +\begin{example} +The string \tcode{0x123} +is parsed to have the value +\tcode{0} +with remaining characters \tcode{x123}. +\end{example} +\end{itemize} +In any case, the resulting \tcode{value} is one of +at most two floating-point values +closest to the value of the string matching the pattern. + +\pnum +\throws +Nothing. +\end{itemdescr} + +\xrefc{7.22.1.3, 7.22.1.4} + +\rSec1[localization]{Localization library} + +\rSec2[localization.general]{General} + +\pnum +Subclause \ref{localization} describes components that \Cpp{} programs may use to +encapsulate (and therefore be more portable when confronting) +cultural differences. +The locale facility includes +internationalization support for character classification and string collation, +numeric, monetary, and date/time formatting and parsing, and +message retrieval. + +\pnum +The following subclauses describe components for +locales themselves, +the standard facets, and +facilities from the C library, +as summarized in \tref{localization.summary}. + +\begin{libsumtab}{Localization library summary}{localization.summary} +\ref{locales} & Locales & \tcode{} \\ +\ref{locale.categories} & Standard \tcode{locale} categories & \\ \rowsep +\ref{c.locales} & C library locales & \tcode{} \\ \rowsep +\end{libsumtab} + +\rSec2[locale.syn]{Header \tcode{} synopsis} + +\indexheader{locale}% +\begin{codeblock} +namespace std { + // \ref{locale}, locale + class locale; + template const Facet& use_facet(const locale&); + template bool has_facet(const locale&) noexcept; + + // \ref{locale.convenience}, convenience interfaces + template bool isspace (charT c, const locale& loc); + template bool isprint (charT c, const locale& loc); + template bool iscntrl (charT c, const locale& loc); + template bool isupper (charT c, const locale& loc); + template bool islower (charT c, const locale& loc); + template bool isalpha (charT c, const locale& loc); + template bool isdigit (charT c, const locale& loc); + template bool ispunct (charT c, const locale& loc); + template bool isxdigit(charT c, const locale& loc); + template bool isalnum (charT c, const locale& loc); + template bool isgraph (charT c, const locale& loc); + template bool isblank (charT c, const locale& loc); + template charT toupper(charT c, const locale& loc); + template charT tolower(charT c, const locale& loc); + + // \ref{category.ctype}, ctype + class ctype_base; + template class ctype; + template<> class ctype; // specialization + template class ctype_byname; + class codecvt_base; + template class codecvt; + template class codecvt_byname; + + // \ref{category.numeric}, numeric + template> + class num_get; + template> + class num_put; + template + class numpunct; + template + class numpunct_byname; + + // \ref{category.collate}, collation + template class collate; + template class collate_byname; + + // \ref{category.time}, date and time + class time_base; + template> + class time_get; + template> + class time_get_byname; + template> + class time_put; + template> + class time_put_byname; + + // \ref{category.monetary}, money + class money_base; + template> + class money_get; + template> + class money_put; + template + class moneypunct; + template + class moneypunct_byname; + + // \ref{category.messages}, message retrieval + class messages_base; + template class messages; + template class messages_byname; +} +\end{codeblock} + +\pnum +The header \libheader{locale} +defines classes and declares functions +that encapsulate and manipulate the information peculiar to a locale. +\begin{footnote} +In this subclause, the type name \tcode{tm} +is an incomplete type that is defined in \libheaderref{ctime}. +\end{footnote} + +\rSec2[locales]{Locales} + +\rSec3[locale]{Class \tcode{locale}} + +\rSec4[locale.general]{General} + +\begin{codeblock} +namespace std { + class locale { + public: + // \ref{locale.types}, types + // \ref{locale.facet}, class \tcode{locale::facet} + class facet; + // \ref{locale.id}, class \tcode{locale::id} + class id; + // \ref{locale.category}, type \tcode{locale::category} + using category = int; + static const category // values assigned here are for exposition only + none = 0, + collate = 0x010, ctype = 0x020, + monetary = 0x040, numeric = 0x080, + time = 0x100, messages = 0x200, + all = collate | ctype | monetary | numeric | time | messages; + + // \ref{locale.cons}, construct/copy/destroy + locale() noexcept; + locale(const locale& other) noexcept; + explicit locale(const char* std_name); + explicit locale(const string& std_name); + locale(const locale& other, const char* std_name, category); + locale(const locale& other, const string& std_name, category); + template locale(const locale& other, Facet* f); + locale(const locale& other, const locale& one, category); + ~locale(); // not virtual + const locale& operator=(const locale& other) noexcept; + + // \ref{locale.members}, locale operations + template locale combine(const locale& other) const; + string name() const; + text_encoding encoding() const; + + bool operator==(const locale& other) const; + + template + bool operator()(const basic_string& s1, + const basic_string& s2) const; + + // \ref{locale.statics}, global locale objects + static locale global(const locale&); + static const locale& classic(); + }; +} +\end{codeblock} + +\pnum +Class \tcode{locale} implements a type-safe polymorphic set of facets, +indexed by facet \textit{type}. +In other words, a facet has a dual role: +in one sense, it's just a class interface; +at the same time, it's an index into a locale's set of facets. + +\pnum +Access to the facets of a \tcode{locale} is via two function templates, +\tcode{use_facet<>} and \tcode{has_facet<>}. + +\pnum +\begin{example} +An iostream \tcode{operator<<} can be implemented as: +\begin{footnote} +Note that in the call to \tcode{put}, +the stream is implicitly converted +to an \tcode{ostreambuf_iterator}. +\end{footnote} + +\begin{codeblock} +template +basic_ostream& +operator<< (basic_ostream& s, Date d) { + typename basic_ostream::sentry cerberos(s); + if (cerberos) { + tm tmbuf; d.extract(tmbuf); + bool failed = + use_facet>>( + s.getloc()).put(s, s, s.fill(), &tmbuf, 'x').failed(); + if (failed) + s.setstate(s.badbit); // can throw + } + return s; +} +\end{codeblock} +\end{example} + +\pnum +In the call to \tcode{use_facet(loc)}, +the type argument chooses a facet, +making available all members of the named type. +If \tcode{Facet} is not present in a locale, +it throws the standard exception \tcode{bad_cast}. +A \Cpp{} program can check if a locale implements a particular facet +with the function template \tcode{has_facet()}. +User-defined facets may be installed in a locale, and +used identically as may standard facets. + +\pnum +\begin{note} +All locale semantics are accessed via +\tcode{use_facet<>} and \tcode{has_facet<>}, +except that: + +\begin{itemize} +\item +A member operator template +\begin{codeblock} +operator()(const basic_string&, const basic_string&) +\end{codeblock} +is provided so that a locale can be used as a predicate argument to +the standard collections, to collate strings. +\item +Convenient global interfaces are provided for +traditional \tcode{ctype} functions such as +\tcode{isdigit()} and \tcode{isspace()}, +so that given a locale object \tcode{loc} +a \Cpp{} program can call \tcode{isspace(c, loc)}. +(This eases upgrading existing extractors\iref{istream.formatted}.) +\end{itemize} +\end{note} + +\pnum +Once a facet reference is obtained from a locale object +by calling \tcode{use_facet<>}, +that reference remains usable, +and the results from member functions of it may be cached and re-used, +as long as some locale object refers to that facet. + +\pnum +In successive calls to a locale facet member function +on a facet object installed in the same locale, +the returned result shall be identical. + +\pnum +A \tcode{locale} constructed +from a name string (such as \tcode{"POSIX"}), or +from parts of two named locales, has a name; +all others do not. +Named locales may be compared for equality; +an unnamed locale is equal only to (copies of) itself. +For an unnamed locale, \tcode{locale::name()} returns the string \tcode{"*"}. + +\pnum +Whether there is +one global locale object for the entire program or +one global locale object per thread +is \impldef{whether locale object is global or per-thread}. +Implementations should provide one global locale object per thread. +If there is a single global locale object for the entire program, +implementations are not required to +avoid data races on it\iref{res.on.data.races}. + +\rSec4[locale.types]{Types} + +\rSec5[locale.category]{Type \tcode{locale::category}} + +\indexlibrarymember{locale}{category}% +\begin{itemdecl} +using category = int; +\end{itemdecl} + +\pnum +\textit{Valid} \tcode{category} values +include the \tcode{locale} member bitmask elements +\tcode{collate}, +\tcode{ctype}, +\tcode{monetary}, +\tcode{numeric}, +\tcode{time}, +and +\tcode{messages}, +each of which represents a single locale category. +In addition, \tcode{locale} member bitmask constant \tcode{none} +is defined as zero and represents no category. +And \tcode{locale} member bitmask constant \tcode{all} +is defined such that the expression +\begin{codeblock} +(collate | ctype | monetary | numeric | time | messages | all) == all +\end{codeblock} +is \tcode{true}, +and represents the union of all categories. +Further, the expression \tcode{(X | Y)}, +where \tcode{X} and \tcode{Y} each represent a single category, +represents the union of the two categories. + +\pnum +\tcode{locale} member functions +expecting a \tcode{category} argument +require one of the \tcode{category} values defined above, or +the union of two or more such values. +Such a \tcode{category} value identifies a set of locale categories. +Each locale category, in turn, identifies a set of locale facets, +including at least those shown in \tref{locale.category.facets}. + +\begin{floattable}{Locale category facets}{locale.category.facets} +{ll} +\topline +\lhdr{Category} & \rhdr{Includes facets} \\ \capsep +collate & \tcode{collate}, \tcode{collate} \\ \rowsep +ctype & \tcode{ctype}, \tcode{ctype} \\ + & \tcode{codecvt} \\ + & \tcode{codecvt} \\ \rowsep +monetary & \tcode{moneypunct}, \tcode{moneypunct} \\ + & \tcode{moneypunct}, \tcode{moneypunct} \\ + & \tcode{money_get}, \tcode{money_get} \\ + & \tcode{money_put}, \tcode{money_put} \\ \rowsep +numeric & \tcode{numpunct}, \tcode{numpunct} \\ + & \tcode{num_get}, \tcode{num_get} \\ + & \tcode{num_put}, \tcode{num_put} \\ \rowsep +time & \tcode{time_get}, \tcode{time_get} \\ + & \tcode{time_put}, \tcode{time_put} \\ \rowsep +messages & \tcode{messages}, \tcode{messages} \\ +\end{floattable} + +\pnum +For any locale \tcode{loc} +either constructed, or returned by \tcode{locale::classic()}, +and any facet \tcode{Facet} shown in \tref{locale.category.facets}, +\tcode{has_facet(loc)} is \tcode{true}. +Each \tcode{locale} member function +which takes a \tcode{locale::category} argument +operates on the corresponding set of facets. + +\pnum +An implementation is required to provide those specializations +for facet templates identified as members of a category, and +for those shown in \tref{locale.spec}. + +\begin{floattable}{Required specializations}{locale.spec} +{ll} +\topline +\lhdr{Category} & \rhdr{Includes facets} \\ \capsep +collate & \tcode{collate_byname}, \tcode{collate_byname} \\ \rowsep +ctype & \tcode{ctype_byname}, \tcode{ctype_byname} \\ + & \tcode{codecvt_byname} \\ + & \tcode{codecvt_byname} \\ \rowsep +monetary & \tcode{moneypunct_byname} \\ + & \tcode{moneypunct_byname} \\ + & \tcode{money_get} \\ + & \tcode{money_put} \\ \rowsep +numeric & \tcode{numpunct_byname}, \tcode{numpunct_byname} \\ + & \tcode{num_get}, \tcode{num_put} \\ \rowsep +time & \tcode{time_get} \\ + & \tcode{time_get_byname} \\ + & \tcode{time_get} \\ + & \tcode{time_get_byname} \\ + & \tcode{time_put} \\ + & \tcode{time_put_byname} \\ + & \tcode{time_put} \\ + & \tcode{time_put_byname} \\ \rowsep +messages & \tcode{messages_byname}, \tcode{messages_byname} \\ +\end{floattable} + + +\pnum +The provided implementation of members of +facets \tcode{num_get} and \tcode{num_put} +calls \tcode{use_fac\-et(l)} only for facet \tcode{F} of +types \tcode{numpunct} and \tcode{ctype}, +and for locale \tcode{l} the value obtained by calling member \tcode{getloc()} +on the \tcode{ios_base\&} argument to these functions. + +\pnum +In declarations of facets, +a template parameter with name \tcode{InputIterator} or \tcode{OutputIterator} +indicates the set of all possible specializations on parameters that meet the +\oldconcept{InputIterator} requirements or +\oldconcept{OutputIterator} requirements, +respectively\iref{iterator.requirements}. +A template parameter with name \tcode{C} represents +the set of types containing \keyword{char}, \keyword{wchar_t}, and any other +\impldef{set of character container types +that iostreams templates can be instantiated for} +character container types\iref{defns.character.container} +that meet the requirements for a character +on which any of the iostream components can be instantiated. +A template parameter with name \tcode{International} +represents the set of all possible specializations on a bool parameter. + +\rSec5[locale.facet]{Class \tcode{locale::facet}} + +\indexlibrarymember{locale}{facet}% +\begin{codeblock} +namespace std { + class locale::facet { + protected: + explicit facet(size_t refs = 0); + virtual ~facet(); + facet(const facet&) = delete; + void operator=(const facet&) = delete; + }; +} +\end{codeblock} + +\pnum +Class \tcode{facet} is the base class for locale feature sets. +A class is a \defn{facet} +if it is publicly derived from another facet, or +if it is a class derived from \tcode{locale::facet} and +contains a publicly accessible declaration as follows: +\begin{footnote} +This is a complete list of requirements; there are no other requirements. +Thus, a facet class need not have a public +copy constructor, assignment, default constructor, destructor, etc. +\end{footnote} +\begin{codeblock} +static ::std::locale::id id; +\end{codeblock} + +\pnum +Template parameters in this Clause +which are required to be facets +are those named \tcode{Facet} in declarations. +A program that passes +a type that is \textit{not} a facet, or +a type that refers to a volatile-qualified facet, +as an (explicit or deduced) template parameter to +a locale function expecting a facet, +is ill-formed. +A const-qualified facet is a valid template argument to +any locale function that expects a \tcode{Facet} template parameter. + +\pnum +The \tcode{refs} argument to the constructor is used for lifetime management. +For \tcode{refs == 0}, +the implementation performs \tcode{delete static_cast(f)} +(where \tcode{f} is a point\-er to the facet) +when the last \tcode{locale} object containing the facet is destroyed; +for \tcode{refs == 1}, the implementation never destroys the facet. + +\pnum +Constructors of all facets defined in this Clause +take such an argument and pass it along to +their \tcode{facet} base class constructor. +All one-argument constructors defined in this Clause are explicit, +preventing their participation in implicit conversions. + +\pnum +For some standard facets a standard ``$\ldots$\tcode{_byname}'' class, +derived from it, implements the virtual function semantics +equivalent to that facet of the locale +constructed by \tcode{locale(const char*)} with the same name. +Each such facet provides a constructor that takes +a \tcode{const char*} argument, which names the locale, and +a \tcode{refs} argument, which is passed to the base class constructor. +Each such facet also provides a constructor that takes +a \tcode{string} argument \tcode{str} and +a \tcode{refs} argument, +which has the same effect as calling the first constructor +with the two arguments \tcode{str.c_str()} and \tcode{refs}. +If there is no ``$\ldots$\tcode{_byname}'' version of a facet, +the base class implements named locale semantics itself +by reference to other facets. + +\rSec5[locale.id]{Class \tcode{locale::id}} + +\indexlibrarymember{locale}{id}% +\begin{codeblock} +namespace std { + class locale::id { + public: + id(); + void operator=(const id&) = delete; + id(const id&) = delete; + }; +} +\end{codeblock} + +\pnum +The class \tcode{locale::id} provides +identification of a locale facet interface, +used as an index for lookup and to encapsulate initialization. + +\pnum +\begin{note} +Because facets are used by iostreams, +potentially while static constructors are running, +their initialization cannot depend on programmed static initialization. +One initialization strategy is for \tcode{locale} +to initialize each facet's \tcode{id} member +the first time an instance of the facet is installed into a locale. +This depends only on static storage being zero +before constructors run\iref{basic.start.static}. +\end{note} + +\rSec4[locale.cons]{Constructors and destructor} + +\indexlibraryctor{locale}% +\begin{itemdecl} +locale() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a copy of the argument last passed to +\tcode{locale::global(locale\&)}, +if it has been called; +else, the resulting facets have virtual function semantics identical to +those of \tcode{locale::classic()}. +\begin{note} +This constructor yields a copy of the current global locale. +It is commonly used as a default argument for +function parameters of type \tcode{const locale\&}. +\end{note} +\end{itemdescr} + +\indexlibraryctor{locale}% +\begin{itemdecl} +explicit locale(const char* std_name); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a locale using standard C locale names, e.g., \tcode{"POSIX"}. +The resulting locale implements semantics defined to be associated +with that name. + +\pnum +\throws +\tcode{runtime_error} if the argument is not valid, or is null. + +\pnum +\remarks +The set of valid string argument values is +\tcode{"C"}, \tcode{""}, and any \impldef{locale names} values. +\end{itemdescr} + +\indexlibraryctor{locale}% +\begin{itemdecl} +explicit locale(const string& std_name); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{locale(std_name.c_str())}. +\end{itemdescr} + +\indexlibraryctor{locale}% +\begin{itemdecl} +locale(const locale& other, const char* std_name, category cats); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{cats} is a valid \tcode{category} value\iref{locale.category}. + +\pnum +\effects +Constructs a locale as a copy of \tcode{other} +except for the facets identified by the \tcode{category} argument, +which instead implement the same semantics as \tcode{locale(std_name)}. + +\pnum +\throws +\tcode{runtime_error} if the second argument is not valid, or is null. + +\pnum +\remarks +The locale has a name if and only if \tcode{other} has a name. +\end{itemdescr} + +\indexlibraryctor{locale}% +\begin{itemdecl} +locale(const locale& other, const string& std_name, category cats); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{locale(other, std_name.c_str(), cats)}. +\end{itemdescr} + +\indexlibraryctor{locale}% +\begin{itemdecl} +template locale(const locale& other, Facet* f); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a locale incorporating all facets from the first argument +except that of type \tcode{Facet}, +and installs the second argument as the remaining facet. +If \tcode{f} is null, the resulting object is a copy of \tcode{other}. + +\pnum +\remarks +If \tcode{f} is null, +the resulting locale has the same name as \tcode{other}. +Otherwise, the resulting locale has no name. +\end{itemdescr} + +\indexlibraryctor{locale}% +\begin{itemdecl} +locale(const locale& other, const locale& one, category cats); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{cats} is a valid \tcode{category} value. + +\pnum +\effects +Constructs a locale incorporating all facets from the first argument +except those that implement \tcode{cats}, +which are instead incorporated from the second argument. + +\pnum +\remarks +If \tcode{cats} is equal to \tcode{locale::none}, +the resulting locale has a name if and only if the first argument has a name. +Otherwise, the resulting locale has a name if and only if +the first two arguments both have names. +\end{itemdescr} + +\indexlibrarymember{operator=}{locale}% +\begin{itemdecl} +const locale& operator=(const locale& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Creates a copy of \tcode{other}, replacing the current value. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\rSec4[locale.members]{Members} + +\indexlibrarymember{locale}{combine}% +\begin{itemdecl} +template locale combine(const locale& other) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a locale incorporating all facets from \tcode{*this} +except for that one facet of \tcode{other} that is identified by \tcode{Facet}. + +\pnum +\returns +The newly created locale. + +\pnum +\throws +\tcode{runtime_error} if \tcode{has_facet(other)} is \tcode{false}. + +\pnum +\remarks +The resulting locale has no name. +\end{itemdescr} + +\indexlibrarymember{locale}{name}% +\begin{itemdecl} +string name() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The name of \tcode{*this}, if it has one; +otherwise, the string \tcode{"*"}. +\end{itemdescr} + +\indexlibrarymember{locale}{encoding}% +\begin{itemdecl} +text_encoding encoding() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{CHAR_BIT == 8} is \tcode{true}. + +\pnum +\returns +A \tcode{text_encoding} object representing +the implementation-defined encoding scheme +associated with the locale \tcode{*this}. +\end{itemdescr} + +\rSec4[locale.operators]{Operators} + +\indexlibrarymember{locale}{operator==}% +\begin{itemdecl} +bool operator==(const locale& other) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if +both arguments are the same locale, or +one is a copy of the other, or +each has a name and the names are identical; +\tcode{false} otherwise. +\end{itemdescr} + +\indexlibrarymember{locale}{operator()}% +\begin{itemdecl} +template + bool operator()(const basic_string& s1, + const basic_string& s2) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Compares two strings according to the \tcode{std::collate} facet. + +\pnum +\returns +\begin{codeblock} +use_facet>(*this).compare(s1.data(), s1.data() + s1.size(), + s2.data(), s2.data() + s2.size()) < 0 +\end{codeblock} + +\pnum +\remarks +This member operator template (and therefore \tcode{locale} itself) +meets the requirements for +a comparator predicate template argument\iref{algorithms} applied to strings. + +\pnum +\begin{example} +A vector of strings \tcode{v} +can be collated according to collation rules in locale \tcode{loc} +simply by\iref{alg.sort,vector}: + +\begin{codeblock} +std::sort(v.begin(), v.end(), loc); +\end{codeblock} +\end{example} +\end{itemdescr} + +\rSec4[locale.statics]{Static members} + +\indexlibrarymember{locale}{global}% +\begin{itemdecl} +static locale global(const locale& loc); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Sets the global locale to its argument. +Causes future calls to the constructor \tcode{locale()} +to return a copy of the argument. +If the argument has a name, does +\begin{codeblock} +setlocale(LC_ALL, loc.name().c_str()); +\end{codeblock} +otherwise, the effect on the C locale, if any, is +\impldef{effect on C locale of calling \tcode{locale::global}}. + +\pnum +\returns +The previous value of \tcode{locale()}. + +\pnum +\remarks +No library function other than \tcode{locale::global()} +affects the value returned by \tcode{locale()}. +\begin{note} +See~\ref{c.locales} for data race considerations +when \tcode{setlocale} is invoked. +\end{note} +\end{itemdescr} + +\indexlibrarymember{locale}{classic}% +\begin{itemdecl} +static const locale& classic(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +The \tcode{"C"} locale. + +\pnum +\returns +A locale that implements the classic \tcode{"C"} locale semantics, +equivalent to the value \tcode{locale("C")}. + +\pnum +\remarks +This locale, its facets, and their member functions, do not change with time. +\end{itemdescr} + +\rSec3[locale.global.templates]{\tcode{locale} globals} + +\indexlibrarymember{locale}{use_facet}% +\begin{itemdecl} +template const Facet& use_facet(const locale& loc); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{Facet} is a facet class +whose definition contains the public static member \tcode{id} +as defined in~\ref{locale.facet}. + +\pnum +\returns +A reference to the corresponding facet of \tcode{loc}, if present. + +\pnum +\throws +\tcode{bad_cast} if \tcode{has_facet(loc)} is \tcode{false}. + +\pnum +\remarks +The reference returned remains valid +at least as long as any copy of \tcode{loc} exists. +\end{itemdescr} + +\indexlibrarymember{locale}{has_facet}% +\begin{itemdecl} +template bool has_facet(const locale& loc) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if the facet requested is present in \tcode{loc}; +otherwise \tcode{false}. +\end{itemdescr} + +\rSec3[locale.convenience]{Convenience interfaces} + +\rSec4[classification]{Character classification} + +\indexlibraryglobal{isspace}% +\indexlibraryglobal{isprint}% +\indexlibraryglobal{iscntrl}% +\indexlibraryglobal{isupper}% +\indexlibraryglobal{islower}% +\indexlibraryglobal{isalpha}% +\indexlibraryglobal{isdigit}% +\indexlibraryglobal{ispunct}% +\indexlibraryglobal{isxdigit}% +\indexlibraryglobal{isalnum}% +\indexlibraryglobal{isgraph}% +\indexlibraryglobal{isblank}% +\begin{itemdecl} +template bool isspace (charT c, const locale& loc); +template bool isprint (charT c, const locale& loc); +template bool iscntrl (charT c, const locale& loc); +template bool isupper (charT c, const locale& loc); +template bool islower (charT c, const locale& loc); +template bool isalpha (charT c, const locale& loc); +template bool isdigit (charT c, const locale& loc); +template bool ispunct (charT c, const locale& loc); +template bool isxdigit(charT c, const locale& loc); +template bool isalnum (charT c, const locale& loc); +template bool isgraph (charT c, const locale& loc); +template bool isblank (charT c, const locale& loc); +\end{itemdecl} + +\pnum +Each of these functions \tcode{is\placeholder{F}} +returns the result of the expression: +\begin{codeblock} +use_facet>(loc).is(ctype_base::@\placeholder{F}@, c) +\end{codeblock} +where \tcode{\placeholder{F}} is the \tcode{ctype_base::mask} value +corresponding to that function\iref{category.ctype}. +\begin{footnote} +When used in a loop, +it is faster to cache the \tcode{ctype<>} facet and use it directly, or +use the vector form of \tcode{ctype<>::is}. +\end{footnote} + +\rSec4[conversions.character]{Character conversions} + +\indexlibraryglobal{toupper}% +\begin{itemdecl} +template charT toupper(charT c, const locale& loc); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{use_facet>(loc).toupper(c)}. +\end{itemdescr} + +\indexlibraryglobal{tolower}% +\begin{itemdecl} +template charT tolower(charT c, const locale& loc); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{use_facet>(loc).tolower(c)}. +\end{itemdescr} + +\rSec2[locale.categories]{Standard \tcode{locale} categories} + +\rSec3[locale.categories.general]{General} + +\pnum +Each of the standard categories includes a family of facets. +Some of these implement formatting or parsing of a datum, +for use by standard or users' iostream operators \tcode{<<} and \tcode{>>}, +as members \tcode{put()} and \tcode{get()}, respectively. +Each such member function takes an +\indexlibrarymember{flags}{ios_base}% +\tcode{ios_base\&} argument whose members +\indexlibrarymember{flags}{ios_base}% +\tcode{flags()}, +\indexlibrarymember{precision}{ios_base}% +\tcode{precision()}, +and +\indexlibrarymember{width}{ios_base}% +\tcode{width()}, +specify the format of the corresponding datum\iref{ios.base}. +Those functions which need to use other facets call its member \tcode{getloc()} +to retrieve the locale imbued there. +Formatting facets use the character argument \tcode{fill} +to fill out the specified width where necessary. + +\pnum +The \tcode{put()} members make no provision for error reporting. +(Any failures of the OutputIterator argument can be extracted from +the returned iterator.) +The \tcode{get()} members take an \tcode{ios_base::iostate\&} argument +whose value they ignore, +but set to \tcode{ios_base::failbit} in case of a parse error. + +\pnum +Within \ref{locale.categories} it is unspecified whether +one virtual function calls another virtual function. + +\rSec3[category.ctype]{The \tcode{ctype} category} + +\rSec4[category.ctype.general]{General} + +\indexlibraryglobal{ctype_base}% +\begin{codeblock} +namespace std { + class ctype_base { + public: + using mask = @\seebelow@; + + // numeric values are for exposition only. + static constexpr mask space = 1 << 0; + static constexpr mask print = 1 << 1; + static constexpr mask cntrl = 1 << 2; + static constexpr mask upper = 1 << 3; + static constexpr mask lower = 1 << 4; + static constexpr mask alpha = 1 << 5; + static constexpr mask digit = 1 << 6; + static constexpr mask punct = 1 << 7; + static constexpr mask xdigit = 1 << 8; + static constexpr mask blank = 1 << 9; + static constexpr mask alnum = alpha | digit; + static constexpr mask graph = alnum | punct; + }; +} +\end{codeblock} + +\pnum +The type \tcode{mask} is a bitmask type\iref{bitmask.types}. + +\rSec4[locale.ctype]{Class template \tcode{ctype}} + +\rSec5[locale.ctype.general]{General} + +\indexlibraryglobal{ctype}% +\begin{codeblock} +namespace std { + template + class ctype : public locale::facet, public ctype_base { + public: + using char_type = charT; + + explicit ctype(size_t refs = 0); + + bool is(mask m, charT c) const; + const charT* is(const charT* low, const charT* high, mask* vec) const; + const charT* scan_is(mask m, const charT* low, const charT* high) const; + const charT* scan_not(mask m, const charT* low, const charT* high) const; + charT toupper(charT c) const; + const charT* toupper(charT* low, const charT* high) const; + charT tolower(charT c) const; + const charT* tolower(charT* low, const charT* high) const; + + charT widen(char c) const; + const char* widen(const char* low, const char* high, charT* to) const; + char narrow(charT c, char dfault) const; + const charT* narrow(const charT* low, const charT* high, char dfault, char* to) const; + + static locale::id id; + + protected: + ~ctype(); + virtual bool do_is(mask m, charT c) const; + virtual const charT* do_is(const charT* low, const charT* high, mask* vec) const; + virtual const charT* do_scan_is(mask m, const charT* low, const charT* high) const; + virtual const charT* do_scan_not(mask m, const charT* low, const charT* high) const; + virtual charT do_toupper(charT) const; + virtual const charT* do_toupper(charT* low, const charT* high) const; + virtual charT do_tolower(charT) const; + virtual const charT* do_tolower(charT* low, const charT* high) const; + virtual charT do_widen(char) const; + virtual const char* do_widen(const char* low, const char* high, charT* dest) const; + virtual char do_narrow(charT, char dfault) const; + virtual const charT* do_narrow(const charT* low, const charT* high, + char dfault, char* dest) const; + }; +} +\end{codeblock} + +\pnum +Class \tcode{ctype} encapsulates the C library \libheaderref{cctype} features. +\tcode{istream} members are required to use \tcode{ctype<>} +for character classing during input parsing. + +\pnum +The specializations +required in \tref{locale.category.facets}\iref{locale.category}, +namely \tcode{ctype} and \tcode{ctype}, +implement character classing appropriate +to the implementation's native character set. + +\rSec5[locale.ctype.members]{\tcode{ctype} members} + +\indexlibrarymember{ctype}{is}% +\begin{itemdecl} +bool is(mask m, charT c) const; +const charT* is(const charT* low, const charT* high, mask* vec) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_is(m, c)} or \tcode{do_is(low, high, vec)}. +\end{itemdescr} + +\indexlibrarymember{ctype}{scan_is}% +\begin{itemdecl} +const charT* scan_is(mask m, const charT* low, const charT* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_scan_is(m, low, high)}. +\end{itemdescr} + +\indexlibrarymember{ctype}{scan_not}% +\begin{itemdecl} +const charT* scan_not(mask m, const charT* low, const charT* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_scan_not(m, low, high)}. +\end{itemdescr} + +\indexlibrarymember{ctype}{toupper}% +\begin{itemdecl} +charT toupper(charT c) const; +const charT* toupper(charT* low, const charT* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_toupper(c)} or \tcode{do_toupper(low, high)}. +\end{itemdescr} + +\indexlibrarymember{ctype}{tolower}% +\begin{itemdecl} +charT tolower(charT c) const; +const charT* tolower(charT* low, const charT* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_tolower(c)} or \tcode{do_tolower(low, high)}. +\end{itemdescr} + +\indexlibrarymember{ctype}{widen}% +\begin{itemdecl} +charT widen(char c) const; +const char* widen(const char* low, const char* high, charT* to) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_widen(c)} or \tcode{do_widen(low, high, to)}. +\end{itemdescr} + +\indexlibrarymember{ctype}{narrow}% +\begin{itemdecl} +char narrow(charT c, char dfault) const; +const charT* narrow(const charT* low, const charT* high, char dfault, char* to) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_narrow(c, dfault)} or \tcode{do_narrow(low, high, dfault, to)}. +\end{itemdescr} + +\rSec5[locale.ctype.virtuals]{\tcode{ctype} virtual functions} + +\indexlibrarymember{ctype}{do_is}% +\begin{itemdecl} +bool do_is(mask m, charT c) const; +const charT* do_is(const charT* low, const charT* high, mask* vec) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Classifies a character or sequence of characters. +For each argument character, +identifies a value \tcode{M} of type \tcode{ctype_base::mask}. +The second form identifies a value \tcode{M} of type \tcode{ctype_base::mask} +for each \tcode{*p} where \tcode{(low <= p \&\& p < high)}, +and places it into \tcode{vec[p - low]}. + +\pnum +\returns +The first form returns the result of the expression \tcode{(M \& m) != 0}; +i.e., \tcode{true} if the character has the characteristics specified. +The second form returns \tcode{high}. +\end{itemdescr} + +\indexlibrarymember{ctype_base}{do_scan_is}% +\begin{itemdecl} +const charT* do_scan_is(mask m, const charT* low, const charT* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Locates a character in a buffer that conforms to a classification \tcode{m}. + +\pnum +\returns +The smallest pointer \tcode{p} in the range \range{low}{high} +such that \tcode{is(m, *p)} would return \tcode{true}; +otherwise, returns \tcode{high}. +\end{itemdescr} + +\indexlibrarymember{ctype}{do_scan_not}% +\begin{itemdecl} +const charT* do_scan_not(mask m, const charT* low, const charT* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Locates a character in a buffer that fails to conform to a classification +\tcode{m}. + +\pnum +\returns +The smallest pointer \tcode{p}, if any, in the range \range{low}{high} +such that \tcode{is(m, *p)} would return \tcode{false}; +otherwise, returns \tcode{high}. +\end{itemdescr} + +\indexlibrarymember{ctype}{do_toupper}% +\begin{itemdecl} +charT do_toupper(charT c) const; +const charT* do_toupper(charT* low, const charT* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Converts a character or characters to upper case. +The second form replaces +each character \tcode{*p} in the range \range{low}{high} +for which a corresponding upper-case character exists, +with that character. + +\pnum +\returns +The first form returns +the corresponding upper-case character if it is known to exist, or +its argument if not. +The second form returns \tcode{high}. +\end{itemdescr} + +\indexlibrarymember{ctype}{do_tolower}% +\begin{itemdecl} +charT do_tolower(charT c) const; +const charT* do_tolower(charT* low, const charT* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Converts a character or characters to lower case. +The second form replaces +each character \tcode{*p} in the range \range{low}{high} +and for which a corresponding lower-case character exists, +with that character. + +\pnum +\returns +The first form returns +the corresponding lower-case character if it is known to exist, or +its argument if not. +The second form returns \tcode{high}. +\end{itemdescr} + +\indexlibrarymember{ctype}{do_widen}% +\begin{itemdecl} +charT do_widen(char c) const; +const char* do_widen(const char* low, const char* high, charT* dest) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Applies the simplest reasonable transformation +from a \tcode{char} value or sequence of \tcode{char} values +to the corresponding \tcode{charT} value or values. +\begin{footnote} +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} +The only characters for which unique transformations are required +are those in the basic character set\iref{lex.charset}. + +For any named \tcode{ctype} category with +a \tcode{ctype} facet \tcode{ctc} and +valid \tcode{ctype_base::mask} value \tcode{M}, +\tcode{(ctc.\brk{}is(M, c) || !is(M, do_widen(c)) )} is \tcode{true}. +\begin{footnote} +In other words, the transformed character is not +a member of any character classification +that \tcode{c} is not also a member of. +\end{footnote} + +The second form transforms +each character \tcode{*p} in the range \range{low}{high}, +placing the result in \tcode{dest[p - low]}. + +\pnum +\returns +The first form returns the transformed value. +The second form returns \tcode{high}. +\end{itemdescr} + +\indexlibrarymember{ctype}{do_narrow}% +\begin{itemdecl} +char do_narrow(charT c, char dfault) const; +const charT* do_narrow(const charT* low, const charT* high, char dfault, char* dest) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Applies the simplest reasonable transformation +from a \tcode{charT} value or sequence of \tcode{charT} values +to the corresponding \tcode{char} value or values. + +For any character \tcode{c} in the basic character set\iref{lex.charset} +the transformation is such that +\begin{codeblock} +do_widen(do_narrow(c, 0)) == c +\end{codeblock} + +For any named \tcode{ctype} category with +a \tcode{ctype} facet \tcode{ctc} however, and +\tcode{ctype_base::mask} value \tcode{M}, +\begin{codeblock} +(is(M, c) || !ctc.is(M, do_narrow(c, dfault)) ) +\end{codeblock} +is \tcode{true} (unless \tcode{do_narrow} returns \tcode{dfault}). +In addition, for any digit character \tcode{c}, +the expression \tcode{(do_narrow(c, dfault) - '0')} +evaluates to the digit value of the character. +The second form transforms +each character \tcode{*p} in the range \range{low}{high}, +placing the result +(or \tcode{dfault} if no simple transformation is readily available) +in \tcode{dest[p - low]}. + +\pnum +\returns +The first form returns the transformed value; +or \tcode{dfault} if no mapping is readily available. +The second form returns \tcode{high}. +\end{itemdescr} + +\rSec4[locale.ctype.byname]{Class template \tcode{ctype_byname}} + +\indexlibraryglobal{ctype_byname}% +\begin{codeblock} +namespace std { + template + class ctype_byname : public ctype { + public: + using mask = typename ctype::mask; + explicit ctype_byname(const char*, size_t refs = 0); + explicit ctype_byname(const string&, size_t refs = 0); + + protected: + ~ctype_byname(); + }; +} +\end{codeblock} + +\rSec4[facet.ctype.special]{\tcode{ctype} specialization} + +\rSec5[facet.ctype.special.general]{General} + +\indexlibraryglobal{ctype}% +\begin{codeblock} +namespace std { + template<> + class ctype : public locale::facet, public ctype_base { + public: + using char_type = char; + + explicit ctype(const mask* tab = nullptr, bool del = false, size_t refs = 0); + + bool is(mask m, char c) const; + const char* is(const char* low, const char* high, mask* vec) const; + const char* scan_is (mask m, const char* low, const char* high) const; + const char* scan_not(mask m, const char* low, const char* high) const; + + char toupper(char c) const; + const char* toupper(char* low, const char* high) const; + char tolower(char c) const; + const char* tolower(char* low, const char* high) const; + + char widen(char c) const; + const char* widen(const char* low, const char* high, char* to) const; + char narrow(char c, char dfault) const; + const char* narrow(const char* low, const char* high, char dfault, char* to) const; + + static locale::id id; + static const size_t table_size = @\impdef@; + + const mask* table() const noexcept; + static const mask* classic_table() noexcept; + + protected: + ~ctype(); + virtual char do_toupper(char c) const; + virtual const char* do_toupper(char* low, const char* high) const; + virtual char do_tolower(char c) const; + virtual const char* do_tolower(char* low, const char* high) const; + + virtual char do_widen(char c) const; + virtual const char* do_widen(const char* low, const char* high, char* to) const; + virtual char do_narrow(char c, char dfault) const; + virtual const char* do_narrow(const char* low, const char* high, + char dfault, char* to) const; + }; +} +\end{codeblock} + +\pnum +A specialization \tcode{ctype} is provided +so that the member functions on type \tcode{char} can be implemented inline. +\begin{footnote} +Only the \tcode{char} (not \tcode{unsigned char} and \tcode{signed char}) +form is provided. +The specialization is specified in the standard, +and not left as an implementation detail, +because it affects the derivation interface for \tcode{ctype}. +\end{footnote} +The \impldef{value of \tcode{ctype::table_size}} value of +member \tcode{table_size} is at least 256. + +\rSec5[facet.ctype.char.dtor]{Destructor} + +\indexlibrarydtor{ctype}% +\begin{itemdecl} +~ctype(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If the constructor's first argument was nonzero, and +its second argument was \tcode{true}, +does \tcode{delete [] table()}. +\end{itemdescr} + +\rSec5[facet.ctype.char.members]{Members} + +\pnum +\indexlibrarymember{ctype}{ctype}% +In the following member descriptions, +for \tcode{unsigned char} values \tcode{v} where \tcode{v >= table_size}, +\tcode{table()[v]} is assumed to have an implementation-specific value +(possibly different for each such value \tcode{v}) +without performing the array lookup. + +\indexlibraryctor{ctype}% +\begin{itemdecl} +explicit ctype(const mask* tbl = nullptr, bool del = false, size_t refs = 0); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +Either \tcode{tbl == nullptr} is \tcode{true} or +\range{tbl}{tbl + table_size} is a valid range. + +\pnum +\effects +Passes its \tcode{refs} argument to its base class constructor. +\end{itemdescr} + +\indexlibrarymember{ctype}{is}% +\begin{itemdecl} +bool is(mask m, char c) const; +const char* is(const char* low, const char* high, mask* vec) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +The second form, for all \tcode{*p} in the range \range{low}{high}, +assigns into \tcode{vec[p - low]} the value \tcode{table()[(unsigned char)*p]}. + +\pnum +\returns +The first form returns \tcode{table()[(unsigned char)c] \& m}; +the second form returns \tcode{high}. +\end{itemdescr} + +\indexlibrarymember{ctype}{scan_is}% +\begin{itemdecl} +const char* scan_is(mask m, const char* low, const char* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The smallest \tcode{p} in the range \range{low}{high} such that +\begin{codeblock} +table()[(unsigned char) *p] & m +\end{codeblock} +is \tcode{true}. +\end{itemdescr} + +\indexlibrarymember{ctype}{scan_not}% +\begin{itemdecl} +const char* scan_not(mask m, const char* low, const char* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The smallest \tcode{p} in the range \range{low}{high} such that +\begin{codeblock} +table()[(unsigned char) *p] & m +\end{codeblock} +is \tcode{false}. +\end{itemdescr} + +\indexlibrarymember{ctype}{toupper}% +\begin{itemdecl} +char toupper(char c) const; +const char* toupper(char* low, const char* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_toupper(c)} or \tcode{do_toupper(low, high)}, respectively. +\end{itemdescr} + +\indexlibrarymember{ctype}{tolower}% +\begin{itemdecl} +char tolower(char c) const; +const char* tolower(char* low, const char* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_tolower(c)} or \tcode{do_tolower(low, high)}, respectively. +\end{itemdescr} + +\indexlibrarymember{ctype}{widen}% +\begin{itemdecl} +char widen(char c) const; +const char* widen(const char* low, const char* high, char* to) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_widen(c)} or +\indexlibraryglobal{do_widen}% +\tcode{do_widen(low, high, to)}, respectively. +\end{itemdescr} + +\indexlibrarymember{ctype}{narrow}% +\begin{itemdecl} +char narrow(char c, char dfault) const; +const char* narrow(const char* low, const char* high, char dfault, char* to) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\indexlibraryglobal{do_narrow}% +\tcode{do_narrow(c, dfault)} or +\indexlibraryglobal{do_narrow}% +\tcode{do_narrow(low, high, dfault, to)}, +respectively. +\end{itemdescr} + +\indexlibrarymember{ctype}{table}% +\begin{itemdecl} +const mask* table() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The first constructor argument, if it was nonzero, +otherwise \tcode{classic_table()}. +\end{itemdescr} + +\rSec5[facet.ctype.char.statics]{Static members} + +\indexlibrarymember{ctype}{classic_table}% +\begin{itemdecl} +static const mask* classic_table() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A pointer to the initial element of an array of size \tcode{table_size} +which represents the classifications of characters in the \tcode{"C"} locale. +\end{itemdescr} + +\rSec5[facet.ctype.char.virtuals]{Virtual functions} + +\indexlibrarymember{ctype}{do_toupper}% +\indexlibrarymember{ctype}{do_tolower}% +\indexlibrarymember{ctype}{do_widen}% +\indexlibrarymember{ctype}{do_narrow}% +\begin{codeblock} +char do_toupper(char) const; +const char* do_toupper(char* low, const char* high) const; +char do_tolower(char) const; +const char* do_tolower(char* low, const char* high) const; + +virtual char do_widen(char c) const; +virtual const char* do_widen(const char* low, const char* high, char* to) const; +virtual char do_narrow(char c, char dfault) const; +virtual const char* do_narrow(const char* low, const char* high, + char dfault, char* to) const; +\end{codeblock} + +\pnum +These functions are described identically as those members of the same name +in the \tcode{ctype} class template\iref{locale.ctype.members}. + +\rSec4[locale.codecvt]{Class template \tcode{codecvt}} + +\rSec5[locale.codecvt.general]{General} + +\indexlibraryglobal{codecvt}% +\begin{codeblock} +namespace std { + class codecvt_base { + public: + enum result { ok, partial, error, noconv }; + }; + + template + class codecvt : public locale::facet, public codecvt_base { + public: + using intern_type = internT; + using extern_type = externT; + using state_type = stateT; + + explicit codecvt(size_t refs = 0); + + result out( + stateT& state, + const internT* from, const internT* from_end, const internT*& from_next, + externT* to, externT* to_end, externT*& to_next) const; + + result unshift( + stateT& state, + externT* to, externT* to_end, externT*& to_next) const; + + result in( + stateT& state, + const externT* from, const externT* from_end, const externT*& from_next, + internT* to, internT* to_end, internT*& to_next) const; + + int encoding() const noexcept; + bool always_noconv() const noexcept; + int length(stateT&, const externT* from, const externT* end, size_t max) const; + int max_length() const noexcept; + + static locale::id id; + + protected: + ~codecvt(); + virtual result do_out( + stateT& state, + const internT* from, const internT* from_end, const internT*& from_next, + externT* to, externT* to_end, externT*& to_next) const; + virtual result do_in( + stateT& state, + const externT* from, const externT* from_end, const externT*& from_next, + internT* to, internT* to_end, internT*& to_next) const; + virtual result do_unshift( + stateT& state, + externT* to, externT* to_end, externT*& to_next) const; + + virtual int do_encoding() const noexcept; + virtual bool do_always_noconv() const noexcept; + virtual int do_length(stateT&, const externT* from, const externT* end, size_t max) const; + virtual int do_max_length() const noexcept; + }; +} +\end{codeblock} + +\pnum +The class \tcode{codecvt} is for use +when converting from one character encoding to another, +such as from wide characters to multibyte characters or +between wide character encodings such as UTF-32 and EUC. + +\pnum +The \tcode{stateT} argument selects +the pair of character encodings being mapped between. + +\pnum +The specializations required +in \tref{locale.category.facets}\iref{locale.category} +convert the implementation-defined native character set. +\tcode{codecvt} implements a degenerate conversion; +it does not convert at all. +\tcode{codecvt} +converts between the native character sets for ordinary and wide characters. +Specializations on \tcode{mbstate_t} +perform conversion between encodings known to the library implementer. +Other encodings can be converted by specializing on +a program-defined \tcode{stateT} type. +Objects of type \tcode{stateT} can contain any state +that is useful to communicate to or from +the specialized \tcode{do_in} or \tcode{do_out} members. + +\rSec5[locale.codecvt.members]{Members} + +\indexlibrarymember{codecvt}{out}% +\begin{itemdecl} +result out( + stateT& state, + const internT* from, const internT* from_end, const internT*& from_next, + externT* to, externT* to_end, externT*& to_next) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_out(state, from, from_end, from_next, to, to_end, to_next)}. +\end{itemdescr} + +\indexlibrarymember{codecvt}{unshift}% +\begin{itemdecl} +result unshift(stateT& state, externT* to, externT* to_end, externT*& to_next) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_unshift(state, to, to_end, to_next)}. +\end{itemdescr} + +\indexlibrarymember{codecvt}{in}% +\begin{itemdecl} +result in( + stateT& state, + const externT* from, const externT* from_end, const externT*& from_next, + internT* to, internT* to_end, internT*& to_next) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_in(state, from, from_end, from_next, to, to_end, to_next)}. +\end{itemdescr} + +\indexlibrarymember{codecvt}{encoding}% +\begin{itemdecl} +int encoding() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_encoding()}. +\end{itemdescr} + +\indexlibrarymember{codecvt}{always_noconv}% +\begin{itemdecl} +bool always_noconv() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_always_noconv()}. +\end{itemdescr} + +\indexlibrarymember{codecvt}{length}% +\begin{itemdecl} +int length(stateT& state, const externT* from, const externT* from_end, size_t max) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_length(state, from, from_end, max)}. +\end{itemdescr} + +\indexlibrarymember{codecvt}{max_length}% +\begin{itemdecl} +int max_length() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_max_length()}. +\end{itemdescr} + +\rSec5[locale.codecvt.virtuals]{Virtual functions} + +\indexlibrarymember{codecvt}{do_out}% +\indexlibrarymember{codecvt}{do_in}% +\begin{itemdecl} +result do_out( + stateT& state, + const internT* from, const internT* from_end, const internT*& from_next, + externT* to, externT* to_end, externT*& to_next) const; + +result do_in( + stateT& state, + const externT* from, const externT* from_end, const externT*& from_next, + internT* to, internT* to_end, internT*& to_next) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{(from <= from_end \&\& to <= to_end)} is well-defined and \tcode{true}; +\tcode{state} is initialized, if at the beginning of a sequence, +or else is equal to the result of converting +the preceding characters in the sequence. + +\pnum +\effects +Translates characters in the source range \range{from}{from_end}, +placing the results in sequential positions starting at destination \tcode{to}. +Converts no more than \tcode{(from_end - from)} source elements, and +stores no more than \tcode{(to_end - to)} destination elements. + +\pnum +Stops if it encounters a character it cannot convert. +It always leaves the \tcode{from_next} and \tcode{to_next} pointers +pointing one beyond the last element successfully converted. +If it returns \tcode{noconv}, +\tcode{internT} and \tcode{externT} are the same type, and +the converted sequence is identical to +the input sequence \range{from}{from\textunderscore\nobreak next}, +\tcode{to_next} is set equal to \tcode{to}, +the value of \tcode{state} is unchanged, and +there are no changes to the values in \range{to}{to_end}. + +\pnum +A \tcode{codecvt} facet +that is used by \tcode{basic_filebuf}\iref{file.streams} +shall have the property that if +\begin{codeblock} +do_out(state, from, from_end, from_next, to, to_end, to_next) +\end{codeblock} +would return \tcode{ok}, +where \tcode{from != from_end}, +then +\begin{codeblock} +do_out(state, from, from + 1, from_next, to, to_end, to_next) +\end{codeblock} +shall also return \tcode{ok}, +and that if +\begin{codeblock} +do_in(state, from, from_end, from_next, to, to_end, to_next) +\end{codeblock} +would return \tcode{ok}, +where \tcode{to != to_end}, +then +\begin{codeblock} +do_in(state, from, from_end, from_next, to, to + 1, to_next) +\end{codeblock} +shall also return \tcode{ok}. +\begin{footnote} +Informally, this means that \tcode{basic_filebuf} +assumes that the mappings from internal to external characters is 1 to N: +that a \tcode{codecvt} facet that is used by \tcode{basic_filebuf} +can translate characters one internal character at a time. +\end{footnote} +\begin{note} +As a result of operations on \tcode{state}, +it can return \tcode{ok} or \tcode{partial} and +set \tcode{from_next == from} and \tcode{to_next != to}. +\end{note} + +\pnum +\returns +An enumeration value, as summarized in \tref{locale.codecvt.inout}. + +\begin{floattable}{\tcode{do_in/do_out} result values}{locale.codecvt.inout} +{lp{3in}} +\topline +\lhdr{Value} & \rhdr{Meaning} \\ \capsep +\tcode{ok} & completed the conversion \\ +\tcode{partial} & not all source characters converted \\ +\tcode{error} & +encountered a character in \range{from}{from_end} +that cannot be converted \\ +\tcode{noconv} & +\tcode{internT} and \tcode{externT} are the same type, and input +sequence is identical to converted sequence \\ +\end{floattable} + +A return value of \tcode{partial}, +if \tcode{(from_next == from_end)}, +indicates +that either the destination sequence has not absorbed +all the available destination elements, or +that additional source elements are needed +before another destination element can be produced. + +\pnum +\remarks +Its operations on \tcode{state} are unspecified. +\begin{note} +This argument can be used, for example, +to maintain shift state, +to specify conversion options (such as count only), or +to identify a cache of seek offsets. +\end{note} +\end{itemdescr} + +\indexlibrarymember{codecvt}{do_unshift}% +\begin{itemdecl} +result do_unshift(stateT& state, externT* to, externT* to_end, externT*& to_next) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{(to <= to_end)} is well-defined and \tcode{true}; +\tcode{state} is initialized, if at the beginning of a sequence, +or else is equal to the result of converting +the preceding characters in the sequence. + +\pnum +\effects +Places characters starting at \tcode{to} +that should be appended to terminate a sequence +when the current \tcode{stateT} is given by \tcode{state}. +\begin{footnote} +Typically these will be characters to return the state to \tcode{stateT()}. +\end{footnote} +Stores no more than \tcode{(to_end - to)} destination elements, and +leaves the \tcode{to_next} pointer +pointing one beyond the last element successfully stored. + +\pnum +\returns +An enumeration value, as summarized in \tref{locale.codecvt.unshift}. + +\begin{floattable}{\tcode{do_unshift} result values}{locale.codecvt.unshift} +{lp{.50\hsize}} +\topline +\lhdr{Value} & \rhdr{Meaning} \\ \capsep +\tcode{ok} & completed the sequence \\ +\tcode{partial} & +space for more than \tcode{to_end - to} destination elements was needed +to terminate a sequence given the value of \tcode{state}\\ +\tcode{error} & an unspecified error has occurred \\ +\tcode{noconv} & no termination is needed for this \tcode{state_type} \\ +\end{floattable} +\end{itemdescr} + +\indexlibrarymember{codecvt}{do_encoding}% +\begin{itemdecl} +int do_encoding() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{-1} if the encoding of the \tcode{externT} sequence is state-dependent; +else the constant number of \tcode{externT} characters +needed to produce an internal character; +or \tcode{0} if this number is not a constant. +\begin{footnote} +If \tcode{encoding()} yields \tcode{-1}, +then more than \tcode{max_length()} \tcode{externT} elements +can be consumed when producing a single \tcode{internT} character, and +additional \tcode{externT} elements can appear at the end of a sequence +after those that yield the final \tcode{internT} character. +\end{footnote} +\end{itemdescr} + +\indexlibrarymember{codecvt}{do_always_noconv}% +\begin{itemdecl} +bool do_always_noconv() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{do_in()} and \tcode{do_out()} return \tcode{noconv} +for all valid argument values. +\tcode{codecvt} returns \tcode{true}. +\end{itemdescr} + +\indexlibrarymember{codecvt}{do_length}% +\begin{itemdecl} +int do_length(stateT& state, const externT* from, const externT* from_end, size_t max) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{(from <= from_end)} is well-defined and \tcode{true}; +\tcode{state} is initialized, if at the beginning of a sequence, +or else is equal to the result of converting +the preceding characters in the sequence. + +\pnum +\effects +The effect on the \tcode{state} argument is as if +it called \tcode{do_in(state, from, from_end, from, to, to + max, to)} +for \tcode{to} pointing to a buffer of at least \tcode{max} elements. + +\pnum +\returns +\tcode{(from_next - from)} where +\tcode{from_next} is the largest value in the range \crange{from}{from_end} +such that the sequence of values in the range \range{from}{from_next} +represents +\tcode{max} or fewer valid complete characters of type \tcode{internT}. +The specialization \tcode{codecvt}, +returns the lesser of \tcode{max} and \tcode{(from_end - from)}. +\end{itemdescr} + +\indexlibrarymember{codecvt}{do_max_length}% +\begin{itemdecl} +int do_max_length() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The maximum value that \tcode{do_length(state, from, from_end, 1)} can return +for any valid range \range{from}{from_end} +and \tcode{stateT} value \tcode{state}. +The specialization \tcode{codecvt::do_max_length()} +returns 1. +\end{itemdescr} + +\rSec4[locale.codecvt.byname]{Class template \tcode{codecvt_byname}} + +\indexlibraryglobal{codecvt_byname}% +\begin{codeblock} +namespace std { + template + class codecvt_byname : public codecvt { + public: + explicit codecvt_byname(const char*, size_t refs = 0); + explicit codecvt_byname(const string&, size_t refs = 0); + + protected: + ~codecvt_byname(); + }; +} +\end{codeblock} + +\rSec3[category.numeric]{The numeric category} + +\rSec4[category.numeric.general]{General} + +\pnum +The classes \tcode{num_get<>} and \tcode{num_put<>} +handle numeric formatting and parsing. +Virtual functions are provided for several numeric types. +Implementations may (but are not required to) delegate +extraction of smaller types to extractors for larger types. +\begin{footnote} +Parsing \tcode{"-1"} correctly into, e.g., an \tcode{unsigned short} +requires that the corresponding member \tcode{get()} +at least extract the sign before delegating. +\end{footnote} + +\pnum +All specifications of member functions for \tcode{num_put} and \tcode{num_get} +in the subclauses of~\ref{category.numeric} only apply to +the specializations required in Tables~\ref{tab:locale.category.facets} +and~\ref{tab:locale.spec}\iref{locale.category}, namely +\tcode{num_get}, +\tcode{num_get}, +\tcode{num_get}, +\tcode{num_put}, +\tcode{num_put}, and +\tcode{num_put}. +These specializations refer to the \tcode{ios_base\&} argument for +formatting specifications\iref{locale.categories}, +and to its imbued locale for the \tcode{numpunct<>} facet to +identify all numeric punctuation preferences, +and also for the \tcode{ctype<>} facet to perform character classification. + +\pnum +Extractor and inserter members of the standard iostreams use +\tcode{num_get<>} and \tcode{num_put<>} member functions for +formatting and parsing +numeric values\iref{istream.formatted.reqmts,ostream.formatted.reqmts}. + +\rSec4[locale.num.get]{Class template \tcode{num_get}} + +\rSec5[locale.num.get.general]{General} + +\indexlibraryglobal{num_get}% +\begin{codeblock} +namespace std { + template> + class num_get : public locale::facet { + public: + using char_type = charT; + using iter_type = InputIterator; + + explicit num_get(size_t refs = 0); + + iter_type get(iter_type in, iter_type end, ios_base&, + ios_base::iostate& err, bool& v) const; + iter_type get(iter_type in, iter_type end, ios_base&, + ios_base::iostate& err, long& v) const; + iter_type get(iter_type in, iter_type end, ios_base&, + ios_base::iostate& err, long long& v) const; + iter_type get(iter_type in, iter_type end, ios_base&, + ios_base::iostate& err, unsigned short& v) const; + iter_type get(iter_type in, iter_type end, ios_base&, + ios_base::iostate& err, unsigned int& v) const; + iter_type get(iter_type in, iter_type end, ios_base&, + ios_base::iostate& err, unsigned long& v) const; + iter_type get(iter_type in, iter_type end, ios_base&, + ios_base::iostate& err, unsigned long long& v) const; + iter_type get(iter_type in, iter_type end, ios_base&, + ios_base::iostate& err, float& v) const; + iter_type get(iter_type in, iter_type end, ios_base&, + ios_base::iostate& err, double& v) const; + iter_type get(iter_type in, iter_type end, ios_base&, + ios_base::iostate& err, long double& v) const; + iter_type get(iter_type in, iter_type end, ios_base&, + ios_base::iostate& err, void*& v) const; + + static locale::id id; + + protected: + ~num_get(); + virtual iter_type do_get(iter_type, iter_type, ios_base&, + ios_base::iostate& err, bool& v) const; + virtual iter_type do_get(iter_type, iter_type, ios_base&, + ios_base::iostate& err, long& v) const; + virtual iter_type do_get(iter_type, iter_type, ios_base&, + ios_base::iostate& err, long long& v) const; + virtual iter_type do_get(iter_type, iter_type, ios_base&, + ios_base::iostate& err, unsigned short& v) const; + virtual iter_type do_get(iter_type, iter_type, ios_base&, + ios_base::iostate& err, unsigned int& v) const; + virtual iter_type do_get(iter_type, iter_type, ios_base&, + ios_base::iostate& err, unsigned long& v) const; + virtual iter_type do_get(iter_type, iter_type, ios_base&, + ios_base::iostate& err, unsigned long long& v) const; + virtual iter_type do_get(iter_type, iter_type, ios_base&, + ios_base::iostate& err, float& v) const; + virtual iter_type do_get(iter_type, iter_type, ios_base&, + ios_base::iostate& err, double& v) const; + virtual iter_type do_get(iter_type, iter_type, ios_base&, + ios_base::iostate& err, long double& v) const; + virtual iter_type do_get(iter_type, iter_type, ios_base&, + ios_base::iostate& err, void*& v) const; + }; +} +\end{codeblock} + +\pnum +The facet \tcode{num_get} is used to parse numeric values +from an input sequence such as an istream. + +\rSec5[facet.num.get.members]{Members} + +\indexlibrarymember{num_get}{get}% +\begin{itemdecl} +iter_type get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, bool& val) const; +iter_type get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, long& val) const; +iter_type get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, long long& val) const; +iter_type get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, unsigned short& val) const; +iter_type get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, unsigned int& val) const; +iter_type get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, unsigned long& val) const; +iter_type get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, unsigned long long& val) const; +iter_type get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, float& val) const; +iter_type get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, double& val) const; +iter_type get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, long double& val) const; +iter_type get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, void*& val) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_get(in, end, str, err, val)}. +\end{itemdescr} + +\rSec5[facet.num.get.virtuals]{Virtual functions} + +\indexlibrarymember{num_get}{do_get}% +\begin{itemdecl} +iter_type do_get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, long& val) const; +iter_type do_get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, long long& val) const; +iter_type do_get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, unsigned short& val) const; +iter_type do_get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, unsigned int& val) const; +iter_type do_get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, unsigned long& val) const; +iter_type do_get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, unsigned long long& val) const; +iter_type do_get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, float& val) const; +iter_type do_get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, double& val) const; +iter_type do_get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, long double& val) const; +iter_type do_get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, void*& val) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Reads characters from \tcode{in}, +interpreting them according to +\tcode{str.flags()}, +\tcode{use_facet>(loc)}, and +\tcode{use_facet>(loc)}, +where \tcode{loc} is \tcode{str.getloc()}. + +\pnum +The details of this operation occur in three stages: + +\begin{itemize} +\item +Stage 1: +Determine a conversion specifier. +\item +Stage 2: +Extract characters from \tcode{in} and +determine a corresponding \tcode{char} value for +the format expected by the conversion specification determined in stage 1. +\item +Stage 3: +Store results. +\end{itemize} + +\pnum +The details of the stages are presented below. + +\begin{description} +\stage{1} +The function initializes local variables via +\begin{codeblock} +fmtflags flags = str.flags(); +fmtflags basefield = (flags & ios_base::basefield); +fmtflags uppercase = (flags & ios_base::uppercase); +fmtflags boolalpha = (flags & ios_base::boolalpha); +\end{codeblock} + +For conversion to an integral type, +the function determines the integral conversion specifier +as indicated in \tref{facet.num.get.int}. +The table is ordered. +That is, the first line whose condition is true applies. + +\begin{floattable}{Integer conversions}{facet.num.get.int} +{lc} +\topline +\lhdr{State} & \rhdr{\tcode{stdio} equivalent} \\ \capsep +\tcode{basefield == oct} & \tcode{\%o} \\ \rowsep +\tcode{basefield == hex} & \tcode{\%X} \\ \rowsep +\tcode{basefield == 0} & \tcode{\%i} \\ \capsep +\tcode{signed} integral type & \tcode{\%d} \\ \rowsep +\tcode{unsigned} integral type & \tcode{\%u} \\ +\end{floattable} + +For conversions to a floating-point type the specifier is \tcode{\%g}. + +For conversions to \tcode{void*} the specifier is \tcode{\%p}. + +A length modifier is added to the conversion specification, if needed, +as indicated in \tref{facet.num.get.length}. + +\begin{floattable}{Length modifier}{facet.num.get.length} +{lc} +\topline +\lhdr{Type} & \rhdr{Length modifier} \\ \capsep +\tcode{short} & \tcode{h} \\ \rowsep +\tcode{unsigned short} & \tcode{h} \\ \rowsep +\tcode{long} & \tcode{l} \\ \rowsep +\tcode{unsigned long} & \tcode{l} \\ \rowsep +\tcode{long long} & \tcode{ll} \\ \rowsep +\tcode{unsigned long long} & \tcode{ll} \\ \rowsep +\tcode{double} & \tcode{l} \\ \rowsep +\tcode{long double} & \tcode{L} \\ +\end{floattable} + +\stage{2} +If \tcode{in == end} then stage 2 terminates. +Otherwise a \tcode{charT} is taken from \tcode{in} and +local variables are initialized as if by +\begin{codeblock} +char_type ct = *in; +char c = src[find(atoms, atoms + sizeof(src) - 1, ct) - atoms]; +if (ct == use_facet>(loc).decimal_point()) + c = '.'; +bool discard = + ct == use_facet>(loc).thousands_sep() + && use_facet>(loc).grouping().length() != 0; +\end{codeblock} +where the values \tcode{src} and \tcode{atoms} are defined as if by: +\begin{codeblock} +static const char src[] = "0123456789abcdefpxABCDEFPX+-"; +char_type atoms[sizeof(src)]; +use_facet>(loc).widen(src, src + sizeof(src), atoms); +\end{codeblock} +for this value of \tcode{loc}. + +If \tcode{discard} is \tcode{true}, +then if \tcode{'.'} has not yet been accumulated, +then the position of the character is remembered, +but the character is otherwise ignored. +Otherwise, if \tcode{'.'} has already been accumulated, +the character is discarded and Stage 2 terminates. +If it is not discarded, +then a check is made to determine +if \tcode{c} is allowed as the next character of +an input field of the conversion specifier returned by Stage 1. +If so, it is accumulated. + +If the character is either discarded or accumulated +then \tcode{in} is advanced by \tcode{++in} +and processing returns to the beginning of stage 2. + +\begin{example} +Given an input sequence of \tcode{"0x1a.bp+07p"}, +\begin{itemize} +\item +if the conversion specifier returned by Stage 1 is \tcode{\%d}, +\tcode{"0"} is accumulated; +\item +if the conversion specifier returned by Stage 1 is \tcode{\%i}, +\tcode{"0x1a"} are accumulated; +\item +if the conversion specifier returned by Stage 1 is \tcode{\%g}, +\tcode{"0x1a.bp+07"} are accumulated. +\end{itemize} +In all cases, the remainder is left in the input. +\end{example} + +\stage{3} +The sequence of \tcode{char}{s} accumulated in stage 2 (the field) +is converted to a numeric value by the rules of one of the functions +declared in the header \libheaderref{cstdlib}: + +\begin{itemize} +\item +For a signed integer value, the function \tcode{strtoll}. +\item +For an unsigned integer value, the function \tcode{strtoull}. +\item +For a \tcode{float} value, the function \tcode{strtof}. +\item +For a \tcode{double} value, the function \tcode{strtod}. +\item +For a \tcode{long double} value, the function \tcode{strtold}. +\end{itemize} + +The numeric value to be stored can be one of: +\begin{itemize} +\item +zero, if the conversion function does not convert the entire field. +\item +the most positive (or negative) representable value, +if the field to be converted to a signed integer type represents a value +too large positive (or negative) to be represented in \tcode{val}. +\item +the most positive representable value, +if the field to be converted to an unsigned integer type represents a value +that cannot be represented in \tcode{val}. +\item +the converted value, otherwise. +\end{itemize} + +The resultant numeric value is stored in \tcode{val}. +If the conversion function does not convert the entire field, or +if the field represents a value outside the range of representable values, +\tcode{ios_base::failbit} is assigned to \tcode{err}. + +\end{description} + +\pnum +Digit grouping is checked. +That is, the positions of discarded +separators are examined for consistency with +\tcode{use_facet>(loc).grouping()}. +If they are not consistent +then \tcode{ios_base::failbit} is assigned to \tcode{err}. + +\pnum +In any case, +if stage 2 processing was terminated by the test for \tcode{in == end} +then \tcode{err |= ios_base::eofbit} is performed. +\end{itemdescr} + +\indexlibrarymember{do_get}{num_get}% +\begin{itemdecl} +iter_type do_get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, bool& val) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{(str.flags() \& ios_base::boolalpha) == 0} +then input proceeds as it would for a \tcode{long} +except that if a value is being stored into \tcode{val}, +the value is determined according to the following: +If the value to be stored is 0 then \tcode{false} is stored. +If the value is \tcode{1} then \tcode{true} is stored. +Otherwise \tcode{true} is stored and +\tcode{ios_base::failbit} is assigned to \tcode{err}. + +\pnum +Otherwise target sequences are determined ``as if'' by +calling the members \tcode{falsename()} and \tcode{truename()} of +the facet obtained by \tcode{use_facet>(str.getloc())}. +Successive characters in the range \range{in}{end} (see~\ref{sequence.reqmts}) +are obtained and matched against +corresponding positions in the target sequences +only as necessary to identify a unique match. +The input iterator \tcode{in} is compared to \tcode{end} +only when necessary to obtain a character. +If a target sequence is uniquely matched, +\tcode{val} is set to the corresponding value. +Otherwise \tcode{false} is stored and +\tcode{ios_base::failbit} is assigned to \tcode{err}. + +\pnum +The \tcode{in} iterator is always left pointing one position beyond +the last character successfully matched. +If \tcode{val} is set, then \tcode{err} is set to \tcode{str.goodbit}; +or to \tcode{str.eofbit} if, +when seeking another character to match, +it is found that \tcode{(in == end)}. +If \tcode{val} is not set, then \tcode{err} is set to \tcode{str.failbit}; +or to \tcode{(str.failbit | str.eofbit)} +if the reason for the failure was that \tcode{(in == end)}. +\begin{example} +For targets \tcode{true}: \tcode{"a"} and \tcode{false}: \tcode{"abb"}, +the input sequence \tcode{"a"} yields +\tcode{val == true} and \tcode{err == str.eofbit}; +the input sequence \tcode{"abc"} yields +\tcode{err = str.failbit}, with \tcode{in} ending at the \tcode{'c'} element. +For targets \tcode{true}: \tcode{"1"} and \tcode{false}: \tcode{"0"}, +the input sequence \tcode{"1"} yields +\tcode{val == true} and \tcode{err == str.goodbit}. +For empty targets \tcode{("")}, +any input sequence yields \tcode{err == str.failbit}. +\end{example} + +\pnum +\returns +\tcode{in}. +\end{itemdescr} + +\rSec4[locale.nm.put]{Class template \tcode{num_put}} + +\rSec5[locale.nm.put.general]{General} + +\indexlibraryglobal{num_put}% +\begin{codeblock} +namespace std { + template> + class num_put : public locale::facet { + public: + using char_type = charT; + using iter_type = OutputIterator; + + explicit num_put(size_t refs = 0); + + iter_type put(iter_type s, ios_base& f, char_type fill, bool v) const; + iter_type put(iter_type s, ios_base& f, char_type fill, long v) const; + iter_type put(iter_type s, ios_base& f, char_type fill, long long v) const; + iter_type put(iter_type s, ios_base& f, char_type fill, unsigned long v) const; + iter_type put(iter_type s, ios_base& f, char_type fill, unsigned long long v) const; + iter_type put(iter_type s, ios_base& f, char_type fill, double v) const; + iter_type put(iter_type s, ios_base& f, char_type fill, long double v) const; + iter_type put(iter_type s, ios_base& f, char_type fill, const void* v) const; + + static locale::id id; + + protected: + ~num_put(); + virtual iter_type do_put(iter_type, ios_base&, char_type fill, bool v) const; + virtual iter_type do_put(iter_type, ios_base&, char_type fill, long v) const; + virtual iter_type do_put(iter_type, ios_base&, char_type fill, long long v) const; + virtual iter_type do_put(iter_type, ios_base&, char_type fill, unsigned long) const; + virtual iter_type do_put(iter_type, ios_base&, char_type fill, unsigned long long) const; + virtual iter_type do_put(iter_type, ios_base&, char_type fill, double v) const; + virtual iter_type do_put(iter_type, ios_base&, char_type fill, long double v) const; + virtual iter_type do_put(iter_type, ios_base&, char_type fill, const void* v) const; + }; +} +\end{codeblock} + +\pnum +The facet +\tcode{num_put} +is used to format numeric values to a character sequence such as an ostream. + +\rSec5[facet.num.put.members]{Members} + +\indexlibrarymember{num_put}{put}% +\begin{itemdecl} +iter_type put(iter_type out, ios_base& str, char_type fill, bool val) const; +iter_type put(iter_type out, ios_base& str, char_type fill, long val) const; +iter_type put(iter_type out, ios_base& str, char_type fill, long long val) const; +iter_type put(iter_type out, ios_base& str, char_type fill, unsigned long val) const; +iter_type put(iter_type out, ios_base& str, char_type fill, unsigned long long val) const; +iter_type put(iter_type out, ios_base& str, char_type fill, double val) const; +iter_type put(iter_type out, ios_base& str, char_type fill, long double val) const; +iter_type put(iter_type out, ios_base& str, char_type fill, const void* val) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_put(out, str, fill, val)}. +\end{itemdescr} + +\rSec5[facet.num.put.virtuals]{Virtual functions} + +\indexlibrarymember{num_put}{do_put}% +\begin{itemdecl} +iter_type do_put(iter_type out, ios_base& str, char_type fill, long val) const; +iter_type do_put(iter_type out, ios_base& str, char_type fill, long long val) const; +iter_type do_put(iter_type out, ios_base& str, char_type fill, unsigned long val) const; +iter_type do_put(iter_type out, ios_base& str, char_type fill, unsigned long long val) const; +iter_type do_put(iter_type out, ios_base& str, char_type fill, double val) const; +iter_type do_put(iter_type out, ios_base& str, char_type fill, long double val) const; +iter_type do_put(iter_type out, ios_base& str, char_type fill, const void* val) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Writes characters to the sequence \tcode{out}, +formatting \tcode{val} as desired. +In the following description, \tcode{loc} names a local variable initialized as +\begin{codeblock} +locale loc = str.getloc(); +\end{codeblock} + +\pnum +The details of this operation occur in several stages: + +\begin{itemize} +\item +Stage 1: +Determine a printf conversion specifier \tcode{spec} and +determine the characters +that would be printed by \tcode{printf}\iref{c.files} +given this conversion specifier for +\begin{codeblock} +printf(spec, val) +\end{codeblock} +assuming that the current locale is the \tcode{"C"} locale. +\item +Stage 2: +Adjust the representation by converting +each \tcode{char} determined by stage 1 to a \tcode{charT} +using a conversion and +values returned by members of \tcode{use_facet>(loc)}. +\item +Stage 3: +Determine where padding is required. +\item +Stage 4: +Insert the sequence into the \tcode{out}. +\end{itemize} + +\pnum +Detailed descriptions of each stage follow. + +\pnum +\returns +\tcode{out}. + +\pnum +\begin{description} +\stage{1} +The first action of stage 1 is to determine a conversion specifier. +The tables that describe this determination use the following local variables + +\begin{codeblock} +fmtflags flags = str.flags(); +fmtflags basefield = (flags & (ios_base::basefield)); +fmtflags uppercase = (flags & (ios_base::uppercase)); +fmtflags floatfield = (flags & (ios_base::floatfield)); +fmtflags showpos = (flags & (ios_base::showpos)); +fmtflags showbase = (flags & (ios_base::showbase)); +fmtflags showpoint = (flags & (ios_base::showpoint)); +\end{codeblock} + +All tables used in describing stage 1 are ordered. +That is, the first line whose condition is true applies. +A line without a condition is the default behavior +when none of the earlier lines apply. + +For conversion from an integral type other than a character type, +the function determines the integral conversion specifier +as indicated in \tref{facet.num.put.int}. + +\begin{floattable}{Integer conversions}{facet.num.put.int} +{lc} +\topline +\lhdr{State} & \rhdr{\tcode{stdio} equivalent} \\ \capsep +\tcode{basefield == ios_base::oct} & \tcode{\%o} \\ \rowsep +\tcode{(basefield == ios_base::hex) \&\& !uppercase} & \tcode{\%x} \\ \rowsep +\tcode{(basefield == ios_base::hex)} & \tcode{\%X} \\ \rowsep +for a \tcode{signed} integral type & \tcode{\%d} \\ \rowsep +for an \tcode{unsigned} integral type & \tcode{\%u} \\ +\end{floattable} + +For conversion from a floating-point type, +the function determines the floating-point conversion specifier +as indicated in \tref{facet.num.put.fp}. + +\begin{floattable}{Floating-point conversions}{facet.num.put.fp} +{lc} +\topline +\lhdr{State} & \rhdr{\tcode{stdio} equivalent} \\ \capsep +\tcode{floatfield == ios_base::fixed \&\& !uppercase} & \tcode{\%f} \\ \rowsep +\tcode{floatfield == ios_base::fixed} & \tcode{\%F} \\ \rowsep +\tcode{floatfield == ios_base::scientific \&\& !uppercase} & \tcode{\%e} \\ \rowsep +\tcode{floatfield == ios_base::scientific} & \tcode{\%E} \\ \rowsep +\tcode{floatfield == (ios_base::fixed | ios_base::scientific) \&\& !uppercase} & \tcode{\%a} \\ \rowsep +\tcode{floatfield == (ios_base::fixed | ios_base::scientific)} & \tcode{\%A} \\ \rowsep +\tcode{!uppercase} & \tcode{\%g} \\ \rowsep +\textit{otherwise} & \tcode{\%G} \\ +\end{floattable} + +For conversions from an integral or floating-point type +a length modifier is added to the conversion specifier +as indicated in \tref{facet.num.put.length}. + +\begin{floattable}{Length modifier}{facet.num.put.length} +{lc} +\topline +\lhdr{Type} & \rhdr{Length modifier} \\ \capsep +\tcode{long} & \tcode{l} \\ \rowsep +\tcode{long long} & \tcode{ll} \\ \rowsep +\tcode{unsigned long} & \tcode{l} \\ \rowsep +\tcode{unsigned long long} & \tcode{ll} \\ \rowsep +\tcode{long double} & \tcode{L} \\ \rowsep +\textit{otherwise} & \textit{none} \\ +\end{floattable} + +The conversion specifier has the following optional additional qualifiers +prepended as indicated in \tref{facet.num.put.conv}. + +\begin{floattable}{Numeric conversions}{facet.num.put.conv} +{llc} +\topline +\lhdr{Type(s)} & \chdr{State} & \rhdr{\tcode{stdio} equivalent} \\ \capsep +an integral type & \tcode{showpos} & \tcode{+} \\ + & \tcode{showbase} & \tcode{\#} \\ \rowsep +a floating-point type & \tcode{showpos} & \tcode{+} \\ + & \tcode{showpoint} & \tcode{\#} \\ +\end{floattable} + +For conversion from a floating-point type, +if \tcode{floatfield != (ios_base::fixed | ios_base::\brk{}scientific)}, +\tcode{str.precision()} is specified as precision +in the conversion specification. +Otherwise, no precision is specified. + +For conversion from \tcode{void*} the specifier is \tcode{\%p}. + +The representations at the end of stage 1 consists of the \tcode{char}'s +that would be printed by a call of \tcode{printf(s, val)} +where \tcode{s} is the conversion specifier determined above. + +\stage{2} +Any character \tcode{c} other than a decimal point(.) is converted to +a \tcode{charT} via +\begin{codeblock} +use_facet>(loc).widen(c) +\end{codeblock} + +A local variable \tcode{punct} is initialized via +\begin{codeblock} +const numpunct& punct = use_facet>(loc); +\end{codeblock} + +For arithmetic types, +\tcode{punct.thousands_sep()} characters are inserted into +the sequence as determined by the value returned by \tcode{punct.do_grouping()} +using the method described in~\ref{facet.numpunct.virtuals}. + +Decimal point characters(.) are replaced by \tcode{punct.decimal_point()}. + +\stage{3} +A local variable is initialized as +\begin{codeblock} +fmtflags adjustfield = (flags & (ios_base::adjustfield)); +\end{codeblock} + +The location of any padding +\begin{footnote} +The conversion specification \tcode{\#o} generates a leading \tcode{0} +which is \textit{not} a padding character. +\end{footnote} +is determined according to \tref{facet.num.put.fill}. + +\begin{floattable}{Fill padding}{facet.num.put.fill} +{p{3in}l} +\topline +\lhdr{State} & \rhdr{Location} \\ \capsep +\tcode{adjustfield == ios_base::left} & pad after \\ \rowsep +\tcode{adjustfield == ios_base::right} & pad before \\ \rowsep +\tcode{adjustfield == internal} and a sign occurs in the representation + & pad after the sign \\ \rowsep +\tcode{adjustfield == internal} and representation after stage 1 +began with 0x or 0X & pad after x or X \\ \rowsep +\textit{otherwise} & pad before \\ +\end{floattable} + +If \tcode{str.width()} is nonzero and the number of \tcode{charT}'s +in the sequence after stage 2 is less than \tcode{str.\brk{}width()}, +then enough \tcode{fill} characters are added to the sequence +at the position indicated for padding +to bring the length of the sequence to \tcode{str.width()}. + +\tcode{str.width(0)} is called. + +\stage{4} +The sequence of \tcode{charT}'s at the end of stage 3 are output via +\begin{codeblock} +*out++ = c +\end{codeblock} +\end{description} +\end{itemdescr} + +\indexlibrarymember{do_put}{num_put}% +\begin{itemdecl} +iter_type do_put(iter_type out, ios_base& str, char_type fill, bool val) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \tcode{(str.flags() \& ios_base::boolalpha) == 0} +returns \tcode{do_put(out, str, fill,\\(int)val)}, +otherwise obtains a string \tcode{s} as if by +\begin{codeblock} +string_type s = + val ? use_facet>(loc).truename() + : use_facet>(loc).falsename(); +\end{codeblock} +and then inserts each character \tcode{c} of \tcode{s} into \tcode{out} +via \tcode{*out++ = c} +and returns \tcode{out}. +\end{itemdescr} + +\rSec3[facet.numpunct]{The numeric punctuation facet} + +\rSec4[locale.numpunct]{Class template \tcode{numpunct}} + +\rSec5[locale.numpunct.general]{General} + +\indexlibraryglobal{numpunct}% +\begin{codeblock} +namespace std { + template + class numpunct : public locale::facet { + public: + using char_type = charT; + using string_type = basic_string; + + explicit numpunct(size_t refs = 0); + + char_type decimal_point() const; + char_type thousands_sep() const; + string grouping() const; + string_type truename() const; + string_type falsename() const; + + static locale::id id; + + protected: + ~numpunct(); // virtual + virtual char_type do_decimal_point() const; + virtual char_type do_thousands_sep() const; + virtual string do_grouping() const; + virtual string_type do_truename() const; // for \tcode{bool} + virtual string_type do_falsename() const; // for \tcode{bool} + }; +} +\end{codeblock} + +\pnum +\tcode{numpunct<>} specifies numeric punctuation. +The specializations +required in \tref{locale.category.facets}\iref{locale.category}, +namely \tcode{numpunct<\brk{}wchar_t>} and \tcode{numpunct}, +provide classic \tcode{"C"} numeric formats, +i.e., they contain information +equivalent to that contained in the \tcode{"C"} locale or +their wide character counterparts as if obtained by a call to \tcode{widen}. + +% FIXME: For now, keep the locale grammar productions out of the index; +% they are conceptually unrelated to the main C++ grammar. +% Consider renaming these en masse (to locale-* ?) to avoid this problem. +\newcommand{\locnontermdef}[1]{{\BnfNontermshape#1\itcorr}\textnormal{:}} +\newcommand{\locgrammarterm}[1]{\gterm{#1}} + +\pnum +The syntax for number formats is as follows, +where \locgrammarterm{digit} represents the radix set +specified by the \tcode{fmtflags} argument value, and +\locgrammarterm{thousands-sep} and \locgrammarterm{decimal-point} +are the results of corresponding \tcode{numpunct} members. +Integer values have the format: +\begin{ncbnf} +\locnontermdef{intval}\br + \opt{sign} units +\end{ncbnf} +\begin{ncbnf} +\locnontermdef{sign}\br + \terminal{+}\br + \terminal{-} +\end{ncbnf} +\begin{ncbnf} +\locnontermdef{units}\br + digits\br + digits thousands-sep units +\end{ncbnf} +\begin{ncbnf} +\locnontermdef{digits}\br + digit \opt{digits} +\end{ncbnf} +and floating-point values have: +\begin{ncbnf} +\locnontermdef{floatval}\br + \opt{sign} units \opt{fractional} \opt{exponent}\br + \opt{sign} decimal-point digits \opt{exponent} +\end{ncbnf} +\begin{ncbnf} +\locnontermdef{fractional}\br + decimal-point \opt{digits} +\end{ncbnf} +\begin{ncbnf} +\locnontermdef{exponent}\br + e \opt{sign} digits +\end{ncbnf} +\begin{ncbnf} +\locnontermdef{e}\br + \terminal{e}\br + \terminal{E} +\end{ncbnf} +where the number of digits between \locgrammarterm{thousands-sep}{s} +is as specified by \tcode{do_grouping()}. +For parsing, +if the \locgrammarterm{digits} portion contains no thousands-separators, +no grouping constraint is applied. + +\rSec5[facet.numpunct.members]{Members} + +\indexlibrarymember{numpunct}{decimal_point}% +\begin{itemdecl} +char_type decimal_point() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_decimal_point()}. +\end{itemdescr} + +\indexlibrarymember{numpunct}{thousands_sep}% +\begin{itemdecl} +char_type thousands_sep() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_thousands_sep()}. +\end{itemdescr} + +\indexlibrarymember{numpunct}{grouping}% +\begin{itemdecl} +string grouping() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_grouping()}. +\end{itemdescr} + +\indexlibrarymember{numpunct}{truename}% +\indexlibrarymember{numpunct}{falsename}% +\begin{itemdecl} +string_type truename() const; +string_type falsename() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_truename()} +or +\tcode{do_falsename()}, +respectively. +\end{itemdescr} + +\rSec5[facet.numpunct.virtuals]{Virtual functions} + +\indexlibrarymember{numpunct}{do_decimal_point}% +\begin{itemdecl} +char_type do_decimal_point() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A character for use as the decimal radix separator. +The required specializations return \tcode{'.'} or \tcode{L'.'}. +\end{itemdescr} + +\indexlibrarymember{numpunct}{do_thousands_sep}% +\begin{itemdecl} +char_type do_thousands_sep() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A character for use as the digit group separator. +The required specializations return \tcode{','} or \tcode{L','}. +\end{itemdescr} + +\indexlibrarymember{numpunct}{do_grouping}% +\begin{itemdecl} +string do_grouping() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{string} \tcode{vec} used as a vector of integer values, +in which each element \tcode{vec[i]} represents the number of digits +\begin{footnote} +Thus, +the string \tcode{"\textbackslash003"} specifies groups of 3 digits each, and +\tcode{"3"} probably indicates groups of 51 (!) digits each, +because 51 is the ASCII value of \tcode{"3"}. +\end{footnote} +in the group at position \tcode{i}, +starting with position 0 as the rightmost group. +If \tcode{vec.size() <= i}, +the number is the same as group \tcode{(i - 1)}; +if \tcode{(i < 0 || vec[i] <= 0 || vec[i] == CHAR_MAX)}, +the size of the digit group is unlimited. + +\pnum +The required specializations return the empty string, indicating no grouping. +\end{itemdescr} + +\indexlibrarymember{numpunct}{do_truename}% +\indexlibrarymember{numpunct}{do_falsename}% +\begin{itemdecl} +string_type do_truename() const; +string_type do_falsename() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A string representing the name of +the boolean value \tcode{true} or \tcode{false}, respectively. + +\pnum +In the base class implementation +these names are \tcode{"true"} and \tcode{"false"}, +or \tcode{L"true"} and \tcode{L"false"}. +\end{itemdescr} + +\rSec4[locale.numpunct.byname]{Class template \tcode{numpunct_byname}} + +\indexlibraryglobal{numpunct_byname}% +\begin{codeblock} +namespace std { + template + class numpunct_byname : public numpunct { + // this class is specialized for \tcode{char} and \keyword{wchar_t}. + public: + using char_type = charT; + using string_type = basic_string; + + explicit numpunct_byname(const char*, size_t refs = 0); + explicit numpunct_byname(const string&, size_t refs = 0); + + protected: + ~numpunct_byname(); + }; +} +\end{codeblock} + +\rSec3[category.collate]{The collate category} + +\rSec4[locale.collate]{Class template \tcode{collate}} + +\rSec5[locale.collate.general]{General} + +\indexlibraryglobal{collate}% +\begin{codeblock} +namespace std { + template + class collate : public locale::facet { + public: + using char_type = charT; + using string_type = basic_string; + + explicit collate(size_t refs = 0); + + int compare(const charT* low1, const charT* high1, + const charT* low2, const charT* high2) const; + string_type transform(const charT* low, const charT* high) const; + long hash(const charT* low, const charT* high) const; + + static locale::id id; + + protected: + ~collate(); + virtual int do_compare(const charT* low1, const charT* high1, + const charT* low2, const charT* high2) const; + virtual string_type do_transform(const charT* low, const charT* high) const; + virtual long do_hash (const charT* low, const charT* high) const; + }; +} +\end{codeblock} + +\pnum +The class \tcode{collate} provides features +for use in the collation (comparison) and hashing of strings. +A locale member function template, \tcode{operator()}, +uses the collate facet to allow a locale to act directly as +the predicate argument for standard algorithms\iref{algorithms} and +containers operating on strings. +The specializations +required in \tref{locale.category.facets}\iref{locale.category}, +namely \tcode{collate} and \tcode{collate}, +apply lexicographical ordering\iref{alg.lex.comparison}. + +\pnum +Each function compares a string of characters \tcode{*p} +in the range \range{low}{high}. + +\rSec5[locale.collate.members]{Members} + +\indexlibrarymember{collate}{compare}% +\begin{itemdecl} +int compare(const charT* low1, const charT* high1, + const charT* low2, const charT* high2) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_compare(low1, high1, low2, high2)}. +\end{itemdescr} + +\indexlibrarymember{collate}{transform}% +\begin{itemdecl} +string_type transform(const charT* low, const charT* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_transform(low, high)}. +\end{itemdescr} + +\indexlibrarymember{collate}{hash}% +\begin{itemdecl} +long hash(const charT* low, const charT* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_hash(low, high)}. +\end{itemdescr} + +\rSec5[locale.collate.virtuals]{Virtual functions} + +\indexlibrarymember{collate}{do_compare}% +\begin{itemdecl} +int do_compare(const charT* low1, const charT* high1, + const charT* low2, const charT* high2) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{1} if the first string is greater than the second, +\tcode{-1} if less, +zero otherwise. +The specializations +required in \tref{locale.category.facets}\iref{locale.category}, +namely \tcode{collate} and \tcode{collate}, +implement a lexicographical comparison\iref{alg.lex.comparison}. +\end{itemdescr} + +\indexlibrarymember{collate}{do_transform}% +\begin{itemdecl} +string_type do_transform(const charT* low, const charT* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A \tcode{basic_string} value that, +compared lexicographically with +the result of calling \tcode{transform()} on another string, +yields the same result as calling \tcode{do_compare()} on the same two strings. +\begin{footnote} +This function is useful when one string is being compared to many other strings. +\end{footnote} +\end{itemdescr} + +\indexlibrarymember{collate}{do_hash}% +\begin{itemdecl} +long do_hash(const charT* low, const charT* high) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An integer value equal to the result of calling \tcode{hash()} +on any other string for which \tcode{do_compare()} returns 0 (equal) +when passed the two strings. + +\pnum +\recommended +The probability that the result equals that for another string +which does not compare equal should be very small, +approaching \tcode{(1.0/numeric_limits::max())}. +\end{itemdescr} + +\rSec4[locale.collate.byname]{Class template \tcode{collate_byname}} + +\indexlibraryglobal{collate_byname}% +\begin{codeblock} +namespace std { + template + class collate_byname : public collate { + public: + using string_type = basic_string; + + explicit collate_byname(const char*, size_t refs = 0); + explicit collate_byname(const string&, size_t refs = 0); + + protected: + ~collate_byname(); + }; +} +\end{codeblock} + +\rSec3[category.time]{The time category} + +\rSec4[category.time.general]{General} + +\pnum +Templates +\tcode{time_get} and +\tcode{time_put} +provide date and time formatting and parsing. +All specifications of member functions for \tcode{time_put} and \tcode{time_get} +in the subclauses of~\ref{category.time} only apply to the +specializations required in Tables~\ref{tab:locale.category.facets} +and~\ref{tab:locale.spec}\iref{locale.category}. +Their members use their +\tcode{ios_base\&}, \tcode{ios_base::iostate\&}, and \tcode{fill} arguments +as described in~\ref{locale.categories}, +and the \tcode{ctype<>} facet, +to determine formatting details. + +\rSec4[locale.time.get]{Class template \tcode{time_get}} + +\rSec5[locale.time.get.general]{General} + +\indexlibraryglobal{time_get}% +\begin{codeblock} +namespace std { + class time_base { + public: + enum dateorder { no_order, dmy, mdy, ymd, ydm }; + }; + + template> + class time_get : public locale::facet, public time_base { + public: + using char_type = charT; + using iter_type = InputIterator; + + explicit time_get(size_t refs = 0); + + dateorder date_order() const { return do_date_order(); } + iter_type get_time(iter_type s, iter_type end, ios_base& f, + ios_base::iostate& err, tm* t) const; + iter_type get_date(iter_type s, iter_type end, ios_base& f, + ios_base::iostate& err, tm* t) const; + iter_type get_weekday(iter_type s, iter_type end, ios_base& f, + ios_base::iostate& err, tm* t) const; + iter_type get_monthname(iter_type s, iter_type end, ios_base& f, + ios_base::iostate& err, tm* t) const; + iter_type get_year(iter_type s, iter_type end, ios_base& f, + ios_base::iostate& err, tm* t) const; + iter_type get(iter_type s, iter_type end, ios_base& f, + ios_base::iostate& err, tm* t, char format, char modifier = 0) const; + iter_type get(iter_type s, iter_type end, ios_base& f, + ios_base::iostate& err, tm* t, const char_type* fmt, + const char_type* fmtend) const; + + static locale::id id; + + protected: + ~time_get(); + virtual dateorder do_date_order() const; + virtual iter_type do_get_time(iter_type s, iter_type end, ios_base&, + ios_base::iostate& err, tm* t) const; + virtual iter_type do_get_date(iter_type s, iter_type end, ios_base&, + ios_base::iostate& err, tm* t) const; + virtual iter_type do_get_weekday(iter_type s, iter_type end, ios_base&, + ios_base::iostate& err, tm* t) const; + virtual iter_type do_get_monthname(iter_type s, iter_type end, ios_base&, + ios_base::iostate& err, tm* t) const; + virtual iter_type do_get_year(iter_type s, iter_type end, ios_base&, + ios_base::iostate& err, tm* t) const; + virtual iter_type do_get(iter_type s, iter_type end, ios_base& f, + ios_base::iostate& err, tm* t, char format, char modifier) const; + }; +} +\end{codeblock} + +\pnum +\tcode{time_get} is used to parse a character sequence, +extracting components of a time or date into a \tcode{tm} object. +Each \tcode{get} member parses a format as produced by a corresponding format specifier to +\tcode{time_put<>::put}. +If the sequence being parsed matches the correct format, the corresponding +members of the +\tcode{tm} +argument are set to the values used to produce the sequence; otherwise +either an error is reported or unspecified values are assigned. +\begin{footnote} +In +other words, user confirmation is required for reliable parsing of +user-entered dates and times, but machine-generated formats can be +parsed reliably. +This allows parsers to be aggressive about +interpreting user variations on standard formats. +\end{footnote} + +\pnum +If the end iterator is reached during parsing by any of the +\tcode{get()} +member functions, the member sets +\tcode{ios_base::eof\-bit} +in \tcode{err}. + +\rSec5[locale.time.get.members]{Members} + +\indexlibrarymember{time_get}{date_order}% +\begin{itemdecl} +dateorder date_order() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_date_order()}. +\end{itemdescr} + +\indexlibrarymember{time_get}{get_time}% +\begin{itemdecl} +iter_type get_time(iter_type s, iter_type end, ios_base& str, + ios_base::iostate& err, tm* t) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_get_time(s, end, str, err, t)}. +\end{itemdescr} + +\indexlibrarymember{time_get}{get_date}% +\begin{itemdecl} +iter_type get_date(iter_type s, iter_type end, ios_base& str, + ios_base::iostate& err, tm* t) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_get_date(s, end, str, err, t)}. +\end{itemdescr} + +\indexlibrarymember{time_get}{get_weekday}% +\indexlibrarymember{time_get}{get_monthname}% +\begin{itemdecl} +iter_type get_weekday(iter_type s, iter_type end, ios_base& str, + ios_base::iostate& err, tm* t) const; +iter_type get_monthname(iter_type s, iter_type end, ios_base& str, + ios_base::iostate& err, tm* t) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_get_weekday(s, end, str, err, t)} +or +\tcode{do_get_monthname(s, end, str, err, t)}. +\end{itemdescr} + +\indexlibrarymember{time_get}{get_year}% +\begin{itemdecl} +iter_type get_year(iter_type s, iter_type end, ios_base& str, + ios_base::iostate& err, tm* t) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_get_year(s, end, str, err, t)}. +\end{itemdescr} + +\indexlibrarymember{get}{time_get}% +\begin{itemdecl} +iter_type get(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, + tm* t, char format, char modifier = 0) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_get(s, end, f, err, t, format, modifier)}. +\end{itemdescr} + +\indexlibrarymember{get}{time_get}% +\begin{itemdecl} +iter_type get(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, + tm* t, const char_type* fmt, const char_type* fmtend) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\range{fmt}{fmtend} is a valid range. + +\pnum +\effects +The function starts by evaluating \tcode{err = ios_base::goodbit}. +It then enters a loop, +reading zero or more characters from \tcode{s} at each iteration. +Unless otherwise specified below, +the loop terminates when the first of the following conditions holds: + +\begin{itemize} +\item +The expression \tcode{fmt == fmtend} evaluates to \tcode{true}. +\item +The expression \tcode{err == ios_base::goodbit} evaluates to \tcode{false}. +\item +The expression \tcode{s == end} evaluates to \tcode{true}, +in which case +the function evaluates \tcode{err = ios_base::eofbit | ios_base::failbit}. +\item +The next element of \tcode{fmt} is equal to \tcode{'\%'}, +optionally followed by a modifier character, +followed by a conversion specifier character, \tcode{format}, +together forming a conversion specification +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, +the function evaluates \tcode{err = ios_base::failbit}. +Otherwise, +the function evaluates \tcode{s = do_get(s, end, f, err, t, format, modifier)}, +where the value of \tcode{modifier} is \tcode{'\textbackslash0'} +when the optional modifier is absent from the conversion specification. +If \tcode{err == ios_base::goodbit} holds +after the evaluation of the expression, +the function increments \tcode{fmt} +to point just past the end of the conversion specification and +continues looping. + +\item +The expression \tcode{isspace(*fmt, f.getloc())} evaluates to \tcode{true}, +in which case the function first increments \tcode{fmt} until +\tcode{fmt == fmtend || !isspace(*fmt, f.getloc())} evaluates to \tcode{true}, +then advances \tcode{s} +until \tcode{s == end || !isspace(*s, f.getloc())} is \tcode{true}, and +finally resumes looping. + +\item +The next character read from \tcode{s} +matches the element pointed to by \tcode{fmt} in a case-insensitive comparison, +in which case the function evaluates \tcode{++fmt, ++s} and continues looping. +Otherwise, the function evaluates \tcode{err = ios_base::failbit}. +\end{itemize} + +\pnum +\begin{note} +The function uses the \tcode{ctype} facet +installed in \tcode{f}'s locale +to determine valid whitespace characters. +It is unspecified +by what means the function performs case-insensitive comparison or +whether multi-character sequences are considered while doing so. +\end{note} + +\pnum +\returns +\tcode{s}. +\end{itemdescr} + +\rSec5[locale.time.get.virtuals]{Virtual functions} + +\indexlibrarymember{time_get}{do_date_order}% +\begin{itemdecl} +dateorder do_date_order() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An enumeration value indicating the preferred order of components +for those date formats that are composed of day, month, and year. +\begin{footnote} +This function is intended as a convenience only, for common formats, and +can return \tcode{no_order} in valid locales. +\end{footnote} +Returns \tcode{no_order} if the date format specified by \tcode{'x'} +contains other variable components (e.g., Julian day, week number, week day). +\end{itemdescr} + +\indexlibrarymember{time_get}{do_get_time}% +\begin{itemdecl} +iter_type do_get_time(iter_type s, iter_type end, ios_base& str, + ios_base::iostate& err, tm* t) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Reads characters starting at \tcode{s} +until it has extracted those \tcode{tm} members, and +remaining format characters, +used by \tcode{time_put<>::put} +to produce the format specified by \tcode{"\%H:\%M:\%S"}, +or until it encounters an error or end of sequence. + +\pnum +\returns +An iterator pointing immediately beyond +the last character recognized as possibly part of a valid time. +\end{itemdescr} + +\indexlibrarymember{time_get}{do_get_date}% +\begin{itemdecl} +iter_type do_get_date(iter_type s, iter_type end, ios_base& str, + ios_base::iostate& err, tm* t) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Reads characters starting at \tcode{s} +until it has extracted those \tcode{tm} members and +remaining format characters +used by \tcode{time_put<>::put} +to produce one of the following formats, +or until it encounters an error. +The format depends on the value returned by \tcode{date_order()} +as shown in \tref{locale.time.get.dogetdate}. + +\begin{libtab2}{\tcode{do_get_date} effects}{locale.time.get.dogetdate} +{ll}{\tcode{date_order()}}{Format} +\tcode{no_order} & \tcode{"\%m\%d\%y"} \\ +\tcode{dmy} & \tcode{"\%d\%m\%y"} \\ +\tcode{mdy} & \tcode{"\%m\%d\%y"} \\ +\tcode{ymd} & \tcode{"\%y\%m\%d"} \\ +\tcode{ydm} & \tcode{"\%y\%d\%m"} \\ +\end{libtab2} + +\pnum +An implementation may also accept additional +\impldef{additional formats for \tcode{time_get::do_get_date}} formats. + +\pnum +\returns +An iterator pointing immediately beyond +the last character recognized as possibly part of a valid date. +\end{itemdescr} + +\indexlibrarymember{time_get}{do_get_weekday}% +\indexlibrarymember{time_get}{do_get_monthname}% +\begin{itemdecl} +iter_type do_get_weekday(iter_type s, iter_type end, ios_base& str, + ios_base::iostate& err, tm* t) const; +iter_type do_get_monthname(iter_type s, iter_type end, ios_base& str, + ios_base::iostate& err, tm* t) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Reads characters starting at \tcode{s} +until it has extracted the (perhaps abbreviated) name of a weekday or month. +If it finds an abbreviation +that is followed by characters that can match a full name, +it continues reading until it matches the full name or fails. +It sets the appropriate \tcode{tm} member accordingly. + +\pnum +\returns +An iterator pointing immediately beyond the last character recognized +as part of a valid name. +\end{itemdescr} + +\indexlibrarymember{time_get}{do_get_year}% +\begin{itemdecl} +iter_type do_get_year(iter_type s, iter_type end, ios_base& str, + ios_base::iostate& err, tm* t) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Reads characters starting at \tcode{s} +until it has extracted an unambiguous year identifier. +It is +\impldef{whether \tcode{time_get::do_get_year} accepts two-digit year numbers} +whether two-digit year numbers are accepted, +and (if so) what century they are assumed to lie in. +Sets the \tcode{t->tm_year} member accordingly. + +\pnum +\returns +An iterator pointing immediately beyond +the last character recognized as part of a valid year identifier. +\end{itemdescr} + +\indexlibrarymember{do_get}{time_get}% +\begin{itemdecl} +iter_type do_get(iter_type s, iter_type end, ios_base& f, + ios_base::iostate& err, tm* t, char format, char modifier) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{t} points to an object. + +\pnum +\effects +The function starts by evaluating \tcode{err = ios_base::goodbit}. +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 specification appropriate for +the POSIX function \tcode{strptime}, +formed by concatenating \tcode{'\%'}, +the \tcode{modifier} character, when non-NUL, and +the \tcode{format} character. +When the concatenation fails to yield a complete valid directive +the function leaves the object pointed to by \tcode{t} unchanged and +evaluates \tcode{err |= ios_base::failbit}. +When \tcode{s == end} evaluates to \tcode{true} after reading a character +the function evaluates \tcode{err |= ios_base::eofbit}. + +\pnum +For complex conversion specifications +such as \tcode{\%c}, \tcode{\%x}, or \tcode{\%X}, or +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}. +In such cases the values of those \tcode{tm} members are unspecified +and may be outside their valid range. + +\pnum +\returns +An iterator pointing immediately beyond +the last character recognized as possibly part of +a valid input sequence for the given \tcode{format} and \tcode{modifier}. + +\pnum +\remarks +It is unspecified whether multiple calls to \tcode{do_get()} +with the address of the same \tcode{tm} object +will update the current contents of the object or simply overwrite its members. +Portable programs should zero out the object before invoking the function. +\end{itemdescr} + +\rSec4[locale.time.get.byname]{Class template \tcode{time_get_byname}} + +\indexlibraryglobal{time_get_byname}% +\begin{codeblock} +namespace std { + template> + class time_get_byname : public time_get { + public: + using dateorder = time_base::dateorder; + using iter_type = InputIterator; + + explicit time_get_byname(const char*, size_t refs = 0); + explicit time_get_byname(const string&, size_t refs = 0); + + protected: + ~time_get_byname(); + }; +} +\end{codeblock} + +\rSec4[locale.time.put]{Class template \tcode{time_put}} + +\rSec5[locale.time.put.general]{General} + +\indexlibraryglobal{time_put}% +\begin{codeblock} +namespace std { + template> + class time_put : public locale::facet { + public: + using char_type = charT; + using iter_type = OutputIterator; + + explicit time_put(size_t refs = 0); + + // the following is implemented in terms of other member functions. + iter_type put(iter_type s, ios_base& f, char_type fill, const tm* tmb, + const charT* pattern, const charT* pat_end) const; + iter_type put(iter_type s, ios_base& f, char_type fill, + const tm* tmb, char format, char modifier = 0) const; + + static locale::id id; + + protected: + ~time_put(); + virtual iter_type do_put(iter_type s, ios_base&, char_type, const tm* t, + char format, char modifier) const; + }; +} +\end{codeblock} + +\rSec5[locale.time.put.members]{Members} + +\indexlibrarymember{time_put}{put}% +\begin{itemdecl} +iter_type put(iter_type s, ios_base& str, char_type fill, const tm* t, + const charT* pattern, const charT* pat_end) const; +iter_type put(iter_type s, ios_base& str, char_type fill, const tm* t, + char format, char modifier = 0) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +The first form steps through the sequence +from \tcode{pattern} to \tcode{pat_end}, +identifying characters that are part of a format sequence. +Each character that is not part of a format sequence +is written to \tcode{s} immediately, and +each format sequence, as it is identified, results in a call to \tcode{do_put}; +thus, format elements and other characters are interleaved in the output +in the order in which they appear in the pattern. +Format sequences are identified by converting each character \tcode{c} to +a \tcode{char} value as if by \tcode{ct.narrow(c, 0)}, +where \tcode{ct} is a reference to \tcode{ctype} +obtained from \tcode{str.getloc()}. +The first character of each sequence is equal to \tcode{'\%'}, +followed by an optional modifier character \tcode{mod} +and a format specifier character \tcode{spec} +as defined for the function \tcode{strftime}. +If no modifier character is present, \tcode{mod} is zero. +For each valid format sequence identified, +calls \tcode{do_put(s, str, fill, t, spec, mod)}. + +\pnum +The second form calls \tcode{do_put(s, str, fill, t, format, modifier)}. + +\pnum +\begin{note} +The \tcode{fill} argument can be used +in the implementation-defined formats or by derivations. +A space character is a reasonable default for this argument. +\end{note} + +\pnum +\returns +An iterator pointing immediately after the last character produced. +\end{itemdescr} + +\rSec5[locale.time.put.virtuals]{Virtual functions} + +\indexlibrarymember{time_put}{do_put}% +\begin{itemdecl} +iter_type do_put(iter_type s, ios_base&, char_type fill, const tm* t, + char format, char modifier) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Formats the contents of the parameter \tcode{t} +into characters placed on the output sequence \tcode{s}. +Formatting is controlled by the parameters \tcode{format} and \tcode{modifier}, +interpreted identically as the format specifiers +in the string argument to the standard library function +\indexlibraryglobal{strftime}% +\tcode{strftime()}, +except that the sequence of characters produced for those specifiers +that are described as depending on the C locale +are instead +\impldef{formatted character sequence generated by \tcode{time_put::do_put} +in C locale}. +\begin{note} +Interpretation of the \tcode{modifier} argument is implementation-defined. +\end{note} + +\pnum +\returns +An iterator pointing immediately after the last character produced. +\begin{note} +The \tcode{fill} argument can be used +in the implementation-defined formats or by derivations. +A space character is a reasonable default for this argument. +\end{note} + +\pnum +\recommended +Interpretation of the \tcode{modifier} should follow POSIX conventions. +Implementations should refer to other standards such as POSIX +for a specification of the character sequences produced for +those specifiers described as depending on the C locale. +\end{itemdescr} + +\rSec4[locale.time.put.byname]{Class template \tcode{time_put_byname}} + +\indexlibraryglobal{time_put_byname}% +\begin{codeblock} +namespace std { + template> + class time_put_byname : public time_put { + public: + using char_type = charT; + using iter_type = OutputIterator; + + explicit time_put_byname(const char*, size_t refs = 0); + explicit time_put_byname(const string&, size_t refs = 0); + + protected: + ~time_put_byname(); + }; +} +\end{codeblock} + +\rSec3[category.monetary]{The monetary category} + +\rSec4[category.monetary.general]{General} + +\pnum +These templates handle monetary formats. +A template parameter indicates +whether local or international monetary formats are to be used. + +\pnum +All specifications of member functions +for \tcode{money_put} and \tcode{money_get} +in the subclauses of~\ref{category.monetary} only apply to +the specializations required in Tables~\ref{tab:locale.category.facets} +and~\ref{tab:locale.spec}\iref{locale.category}. +Their members use their \tcode{ios_base\&}, \tcode{ios_base::io\-state\&}, +and \tcode{fill} arguments as described in~\ref{locale.categories}, and +the \tcode{moneypunct<>} and \tcode{ctype<>} facets, +to determine formatting details. + +\rSec4[locale.money.get]{Class template \tcode{money_get}} + +\rSec5[locale.money.get.general]{General} + +\indexlibraryglobal{money_get}% +\begin{codeblock} +namespace std { + template> + class money_get : public locale::facet { + public: + using char_type = charT; + using iter_type = InputIterator; + using string_type = basic_string; + + explicit money_get(size_t refs = 0); + + iter_type get(iter_type s, iter_type end, bool intl, + ios_base& f, ios_base::iostate& err, + long double& units) const; + iter_type get(iter_type s, iter_type end, bool intl, + ios_base& f, ios_base::iostate& err, + string_type& digits) const; + + static locale::id id; + + protected: + ~money_get(); + virtual iter_type do_get(iter_type, iter_type, bool, ios_base&, + ios_base::iostate& err, long double& units) const; + virtual iter_type do_get(iter_type, iter_type, bool, ios_base&, + ios_base::iostate& err, string_type& digits) const; + }; +} +\end{codeblock} + +\rSec5[locale.money.get.members]{Members} + +\indexlibrarymember{money_get}{get}% +\begin{itemdecl} +iter_type get(iter_type s, iter_type end, bool intl, ios_base& f, + ios_base::iostate& err, long double& quant) const; +iter_type get(iter_type s, iter_type end, bool intl, ios_base& f, + ios_base::iostate& err, string_type& quant) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_get(s, end, intl, f, err, quant)}. +\end{itemdescr} + +\rSec5[locale.money.get.virtuals]{Virtual functions} + +\indexlibrarymember{money_get}{do_get}% +\begin{itemdecl} +iter_type do_get(iter_type s, iter_type end, bool intl, ios_base& str, + ios_base::iostate& err, long double& units) const; +iter_type do_get(iter_type s, iter_type end, bool intl, ios_base& str, + ios_base::iostate& err, string_type& digits) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Reads characters from \tcode{s} to parse and construct a monetary value +according to the format specified by +a \tcode{moneypunct} facet reference \tcode{mp} +and the character mapping specified by +a \tcode{ctype} facet reference \tcode{ct} +obtained from the locale returned by \tcode{str.getloc()}, and +\tcode{str.flags()}. +If a valid sequence is recognized, does not change \tcode{err}; +otherwise, sets \tcode{err} to \tcode{(err | str.failbit)}, or +\tcode{(err | str.failbit | str.eof\-bit)} if no more characters are available, +and does not change \tcode{units} or \tcode{digits}. +Uses the pattern returned by \tcode{mp.neg_format()} to parse all values. +The result is returned as an integral value stored in \tcode{units} +or as a sequence of digits possibly preceded by a minus sign +(as produced by \tcode{ct.widen(c)} +where \tcode{c} is \tcode{'-'} or +in the range from \tcode{'0'} through \tcode{'9'} (inclusive)) +stored in \tcode{digits}. +\begin{example} +The sequence \tcode{\$1,056.23} in a common United States locale would yield, +for \tcode{units}, \tcode{105623}, or, +for \tcode{digits}, \tcode{"105623"}. +\end{example} +If \tcode{mp.grouping()} indicates that no thousands separators are permitted, +any such characters are not read, and +parsing is terminated at the point where they first appear. +Otherwise, thousands separators are optional; +if present, they are checked for correct placement only after +all format components have been read. + +\pnum +Where \tcode{money_base::space} or \tcode{money_base::none} +appears as the last element in the format pattern, +no whitespace is consumed. +Otherwise, where \tcode{money_base::space} appears in any of +the initial elements of the format pattern, +at least one whitespace character is required. +Where \tcode{money_base::none} appears +in any of the initial elements of the format pattern, +whitespace is allowed but not required. +If \tcode{(str.flags() \& str.showbase)} is \tcode{false}, +the currency symbol is optional and +is consumed only if other characters are needed to complete the format; +otherwise, the currency symbol is required. + +\pnum +If the first character (if any) in +the string \tcode{pos} returned by \tcode{mp.positive_sign()} or +the string \tcode{neg} returned by \tcode{mp.negative_sign()} +is recognized in the position indicated by \tcode{sign} in the format pattern, +it is consumed and +any remaining characters in the string are required +after all the other format components. +\begin{example} +If \tcode{showbase} is off, +then for a \tcode{neg} value of \tcode{"()"} and +a currency symbol of \tcode{"L"}, +in \tcode{"(100 L)"} the \tcode{"L"} is consumed; +but if \tcode{neg} is \tcode{"-"}, +the \tcode{"L"} in \tcode{"-100 L"} is not consumed. +\end{example} +If \tcode{pos} or \tcode{neg} is empty, +the sign component is optional, and +if no sign is detected, +the result is given the sign that corresponds to the source of the empty string. +Otherwise, +the character in the indicated position must match +the first character of \tcode{pos} or \tcode{neg}, +and the result is given the corresponding sign. +If the first character of \tcode{pos} is equal to +the first character of \tcode{neg}, +or if both strings are empty, +the result is given a positive sign. + +\pnum +Digits in the numeric monetary component are extracted and +placed in \tcode{digits}, or into a character buffer \tcode{buf1} +for conversion to produce a value for \tcode{units}, +in the order in which they appear, +preceded by a minus sign if and only if the result is negative. +The value \tcode{units} is produced as if by +\begin{footnote} +The semantics here are different from \tcode{ct.narrow}. +\end{footnote} +\begin{codeblock} +for (int i = 0; i < n; ++i) + buf2[i] = src[find(atoms, atoms + sizeof(src), buf1[i]) - atoms]; +buf2[n] = 0; +sscanf(buf2, "%Lf", &units); +\end{codeblock} +where \tcode{n} is the number of characters placed in \tcode{buf1}, +\tcode{buf2} is a character buffer, and +the values \tcode{src} and \tcode{atoms} are defined as if by +\begin{codeblock} +static const char src[] = "0123456789-"; +charT atoms[sizeof(src)]; +ct.widen(src, src + sizeof(src) - 1, atoms); +\end{codeblock} + +\pnum +\returns +An iterator pointing immediately beyond +the last character recognized as part of a valid monetary quantity. +\end{itemdescr} + +\rSec4[locale.money.put]{Class template \tcode{money_put}} + +\rSec5[locale.money.put.general]{General} + +\indexlibraryglobal{money_put}% +\begin{codeblock} +namespace std { + template> + class money_put : public locale::facet { + public: + using char_type = charT; + using iter_type = OutputIterator; + using string_type = basic_string; + + explicit money_put(size_t refs = 0); + + iter_type put(iter_type s, bool intl, ios_base& f, + char_type fill, long double units) const; + iter_type put(iter_type s, bool intl, ios_base& f, + char_type fill, const string_type& digits) const; + + static locale::id id; + + protected: + ~money_put(); + virtual iter_type do_put(iter_type, bool, ios_base&, char_type fill, + long double units) const; + virtual iter_type do_put(iter_type, bool, ios_base&, char_type fill, + const string_type& digits) const; + }; +} +\end{codeblock} + +\rSec5[locale.money.put.members]{Members} + +\indexlibrarymember{money_put}{put}% +\begin{itemdecl} +iter_type put(iter_type s, bool intl, ios_base& f, char_type fill, long double quant) const; +iter_type put(iter_type s, bool intl, ios_base& f, char_type fill, const string_type& quant) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_put(s, intl, f, fill, quant)}. +\end{itemdescr} + +\rSec5[locale.money.put.virtuals]{Virtual functions} + +\indexlibrarymember{money_put}{do_put}% +\begin{itemdecl} +iter_type do_put(iter_type s, bool intl, ios_base& str, + char_type fill, long double units) const; +iter_type do_put(iter_type s, bool intl, ios_base& str, + char_type fill, const string_type& digits) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Writes characters to \tcode{s} according to +the format specified by +a \tcode{moneypunct} facet reference \tcode{mp} and +the character mapping specified by +a \tcode{ctype} facet reference \tcode{ct} +obtained from the locale returned by \tcode{str.getloc()}, +and \tcode{str.flags()}. +The argument \tcode{units} is transformed into +a sequence of wide characters as if by +\begin{codeblock} +ct.widen(buf1, buf1 + sprintf(buf1, "%.0Lf", units), buf2) +\end{codeblock} +for character buffers \tcode{buf1} and \tcode{buf2}. +If the first character in \tcode{digits} or \tcode{buf2} +is equal to \tcode{ct.widen('-')}, +then the pattern used for formatting is the result of \tcode{mp.neg_format()}; +otherwise the pattern is the result of \tcode{mp.pos_format()}. +Digit characters are written, +interspersed with any thousands separators and decimal point +specified by the format, +in the order they appear (after the optional leading minus sign) in +\tcode{digits} or \tcode{buf2}. +In \tcode{digits}, +only the optional leading minus sign and +the immediately subsequent digit characters +(as classified according to \tcode{ct}) +are used; +any trailing characters +(including digits appearing after a non-digit character) +are ignored. +Calls \tcode{str.width(0)}. + +\pnum +\returns +An iterator pointing immediately after the last character produced. + +\pnum +\remarks +% issues 22-021, 22-030, 22-034 from 97-0058/N1096, 97-0036/N1074 +The currency symbol is generated +if and only if \tcode{(str.flags() \& str.showbase)} is nonzero. +If the number of characters generated for the specified format +is less than the value returned by \tcode{str.width()} on entry to the function, +then copies of \tcode{fill} are inserted as necessary +to pad to the specified width. +For the value \tcode{af} equal to \tcode{(str.flags() \& str.adjustfield)}, +if \tcode{(af == str.internal)} is \tcode{true}, +the fill characters are placed +where \tcode{none} or \tcode{space} appears in the formatting pattern; +otherwise if \tcode{(af == str.left)} is \tcode{true}, +they are placed after the other characters; +otherwise, they are placed before the other characters. +\begin{note} +It is possible, with some combinations of format patterns and flag values, +to produce output that cannot be parsed using \tcode{num_get<>::get}. +\end{note} +\end{itemdescr} + +\rSec4[locale.moneypunct]{Class template \tcode{moneypunct}} + +\rSec5[locale.moneypunct.general]{General} + +\indexlibraryglobal{moneypunct}% +\begin{codeblock} +namespace std { + class money_base { + public: + enum part { none, space, symbol, sign, value }; + struct pattern { char field[4]; }; + }; + + template + class moneypunct : public locale::facet, public money_base { + public: + using char_type = charT; + using string_type = basic_string; + + explicit moneypunct(size_t refs = 0); + + charT decimal_point() const; + charT thousands_sep() const; + string grouping() const; + string_type curr_symbol() const; + string_type positive_sign() const; + string_type negative_sign() const; + int frac_digits() const; + pattern pos_format() const; + pattern neg_format() const; + + static locale::id id; + static const bool intl = International; + + protected: + ~moneypunct(); + virtual charT do_decimal_point() const; + virtual charT do_thousands_sep() const; + virtual string do_grouping() const; + virtual string_type do_curr_symbol() const; + virtual string_type do_positive_sign() const; + virtual string_type do_negative_sign() const; + virtual int do_frac_digits() const; + virtual pattern do_pos_format() const; + virtual pattern do_neg_format() const; + }; +} +\end{codeblock} + +\pnum +The \tcode{moneypunct<>} facet defines monetary formatting parameters +used by \tcode{money_get<>} and \tcode{money_put<>}. +A monetary format is a sequence of four components, +specified by a \tcode{pattern} value \tcode{p}, +such that the \tcode{part} value \tcode{static_cast(p.field[i])} +determines the $\tcode{i}^\text{th}$ component of the format. +\begin{footnote} +An array of \tcode{char}, +rather than an array of \tcode{part}, +is specified for \tcode{pattern::field} purely for efficiency. +\end{footnote} +In the \tcode{field} member of a \tcode{pattern} object, +each value \tcode{symbol}, \tcode{sign}, \tcode{value}, and +either \tcode{space} or \tcode{none} +appears exactly once. +The value \tcode{none}, if present, is not first; +the value \tcode{space}, if present, is neither first nor last. + +\pnum +Where \tcode{none} or \tcode{space} appears, +whitespace is permitted in the format, +except where \tcode{none} appears at the end, +in which case no whitespace is permitted. +The value \tcode{space} indicates that +at least one space is required at that position. +Where \tcode{symbol} appears, +the sequence of characters returned by \tcode{curr_symbol()} is permitted, and +can be required. +Where \tcode{sign} appears, +the first (if any) of the sequence of characters returned by +\tcode{positive_sign()} or \tcode{negative_sign()} +(respectively as the monetary value is non-negative or negative) is required. +Any remaining characters of the sign sequence are required after +all other format components. +Where \tcode{value} appears, the absolute numeric monetary value is required. + +\pnum +The format of the numeric monetary value is a decimal number: +\begin{ncbnf} +\locnontermdef{value}\br + units \opt{fractional}\br + decimal-point digits +\end{ncbnf} +\begin{ncbnf} +\locnontermdef{fractional}\br + decimal-point \opt{digits} +\end{ncbnf} +if \tcode{frac_digits()} returns a positive value, or +\begin{ncbnf} +\locnontermdef{value}\br + units +\end{ncbnf} +otherwise. +The symbol \locgrammarterm{decimal-point} +indicates the character returned by \tcode{decimal_point()}. +The other symbols are defined as follows: + +\begin{ncbnf} +\locnontermdef{units}\br + digits\br + digits thousands-sep units +\end{ncbnf} + +\begin{ncbnf} +\locnontermdef{digits}\br + adigit \opt{digits} +\end{ncbnf} + +In the syntax specification, +the symbol \locgrammarterm{adigit} is any of the values \tcode{ct.widen(c)} +for \tcode{c} in the range \tcode{'0'} through \tcode{'9'} (inclusive) and +\tcode{ct} is a reference of type \tcode{const ctype\&} +obtained as described in the definitions +of \tcode{money_get<>} and \tcode{money_put<>}. +The symbol \locgrammarterm{thousands-sep} +is the character returned by \tcode{thousands_sep()}. +The space character used is the value \tcode{ct.widen(' ')}. +Whitespace characters are those characters \tcode{c} +for which \tcode{ci.is(space, c)} returns \tcode{true}. +The number of digits required after the decimal point (if any) +is exactly the value returned by \tcode{frac_digits()}. + +\pnum +The placement of thousands-separator characters (if any) +is determined by the value returned by \tcode{grouping()}, +defined identically as the member \tcode{numpunct<>::do_grouping()}. + +\rSec5[locale.moneypunct.members]{Members} + +\indexlibrarymember{moneypunct}{decimal_point}% +\indexlibrarymember{moneypunct}{thousands_sep}% +\indexlibrarymember{moneypunct}{grouping}% +\indexlibrarymember{moneypunct}{curr_symbol}% +\indexlibrarymember{moneypunct}{positive_sign}% +\indexlibrarymember{moneypunct}{negative_sign}% +\indexlibrarymember{moneypunct}{frac_digits}% +\indexlibrarymember{moneypunct}{positive_sign}% +\indexlibrarymember{moneypunct}{negative_sign}% +\begin{codeblock} +charT decimal_point() const; +charT thousands_sep() const; +string grouping() const; +string_type curr_symbol() const; +string_type positive_sign() const; +string_type negative_sign() const; +int frac_digits() const; +pattern pos_format() const; +pattern neg_format() const; +\end{codeblock} + +\pnum +Each of these functions \tcode{\placeholder{F}} +returns the result of calling the corresponding +virtual member function +\tcode{do_\placeholder{F}()}. + +\rSec5[locale.moneypunct.virtuals]{Virtual functions} + +\indexlibrarymember{moneypunct}{do_decimal_point}% +\begin{itemdecl} +charT do_decimal_point() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The radix separator to use +in case \tcode{do_frac_digits()} is greater than zero. +\begin{footnote} +In common U.S. locales this is \tcode{'.'}. +\end{footnote} +\end{itemdescr} + +\indexlibrarymember{moneypunct}{do_thousands_sep}% +\begin{itemdecl} +charT do_thousands_sep() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The digit group separator to use +in case \tcode{do_grouping()} specifies a digit grouping pattern. +\begin{footnote} +In common U.S. locales this is \tcode{','}. +\end{footnote} +\end{itemdescr} + +\indexlibrarymember{moneypunct}{do_grouping}% +\begin{itemdecl} +string do_grouping() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A pattern defined identically as, but not necessarily equal to, +the result of \tcode{numpunct::\brk{}do_grouping()}. +\begin{footnote} +To specify grouping by 3s, +the value is \tcode{"\textbackslash003"} \textit{not} \tcode{"3"}. +\end{footnote} +\end{itemdescr} + +\indexlibrarymember{moneypunct}{do_curr_symbol}% +\begin{itemdecl} +string_type do_curr_symbol() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A string to use as the currency identifier symbol. +\begin{note} +For specializations where the second template parameter is \tcode{true}, +this is typically four characters long: +a three-letter code as specified by ISO 4217\supercite{iso4217} +followed by a space. +\end{note} +\end{itemdescr} + +\indexlibrarymember{moneypunct}{do_positive_sign}% +\indexlibrarymember{moneypunct}{do_negative_sign}% +\begin{itemdecl} +string_type do_positive_sign() const; +string_type do_negative_sign() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_positive_sign()} +returns the string to use to indicate a positive monetary value; +\begin{footnote} +This is usually the empty string. +\end{footnote} +\tcode{do_negative_sign()} +returns the string to use to indicate a negative value. +\end{itemdescr} + +\indexlibrarymember{moneypunct}{do_frac_digits}% +\begin{itemdecl} +int do_frac_digits() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The number of digits after the decimal radix separator, if any. +\begin{footnote} +In common U.S.\ locales, this is 2. +\end{footnote} +\end{itemdescr} + +\indexlibrarymember{moneypunct}{do_pos_format}% +\indexlibrarymember{moneypunct}{do_neg_format}% +\begin{itemdecl} +pattern do_pos_format() const; +pattern do_neg_format() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The specializations required in \tref{locale.spec}\iref{locale.category}, namely +\begin{itemize} +\item \tcode{moneypunct}, +\item \tcode{moneypunct}, +\item \tcode{moneypunct}, and +\item \tcode{moneypunct}, +\end{itemize} +return an object of type \tcode{pattern} +initialized to \tcode{\{ symbol, sign, none, value \}}. +\begin{footnote} +Note that the international symbol returned by \tcode{do_curr_symbol()} +usually contains a space, itself; +for example, \tcode{"USD "}. +\end{footnote} +\end{itemdescr} + +\rSec4[locale.moneypunct.byname]{Class template \tcode{moneypunct_byname}} + +\indexlibraryglobal{moneypunct_byname}% +\begin{codeblock} +namespace std { + template + class moneypunct_byname : public moneypunct { + public: + using pattern = money_base::pattern; + using string_type = basic_string; + + explicit moneypunct_byname(const char*, size_t refs = 0); + explicit moneypunct_byname(const string&, size_t refs = 0); + + protected: + ~moneypunct_byname(); + }; +} +\end{codeblock} + +\rSec3[category.messages]{The message retrieval category} + +\rSec4[category.messages.general]{General} + +\pnum +Class \tcode{messages} +implements retrieval of strings from message catalogs. + +\rSec4[locale.messages]{Class template \tcode{messages}} + +\rSec5[locale.messages.general]{General} + +\indexlibraryglobal{messages}% +\begin{codeblock} +namespace std { + class messages_base { + public: + using catalog = @\textit{unspecified signed integer type}@; + }; + + template + class messages : public locale::facet, public messages_base { + public: + using char_type = charT; + using string_type = basic_string; + + explicit messages(size_t refs = 0); + + catalog open(const string& fn, const locale&) const; + string_type get(catalog c, int set, int msgid, + const string_type& dfault) const; + void close(catalog c) const; + + static locale::id id; + + protected: + ~messages(); + virtual catalog do_open(const string&, const locale&) const; + virtual string_type do_get(catalog, int set, int msgid, + const string_type& dfault) const; + virtual void do_close(catalog) const; + }; +} +\end{codeblock} + +\pnum +Values of type \tcode{messages_base::catalog} +usable as arguments to members \tcode{get} and \tcode{close} +can be obtained only by calling member \tcode{open}. + +\rSec5[locale.messages.members]{Members} + +\indexlibrarymember{messages}{open}% +\begin{itemdecl} +catalog open(const string& name, const locale& loc) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_open(name, loc)}. +\end{itemdescr} + +\indexlibrarymember{messages}{get}% +\begin{itemdecl} +string_type get(catalog cat, int set, int msgid, const string_type& dfault) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{do_get(cat, set, msgid, dfault)}. +\end{itemdescr} + +\indexlibrarymember{messages}{close}% +\begin{itemdecl} +void close(catalog cat) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{do_close(cat)}. +\end{itemdescr} + +\rSec5[locale.messages.virtuals]{Virtual functions} + +\indexlibrarymember{messages}{do_open}% +\begin{itemdecl} +catalog do_open(const string& name, const locale& loc) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A value that may be passed to \tcode{get()} +to retrieve a message from the message catalog +identified by the string \tcode{name} +according to an \impldef{mapping from name to catalog when calling +\tcode{mes\-sages::do_open}} mapping. +The result can be used until it is passed to \tcode{close()}. + +\pnum +Returns a value less than 0 if no such catalog can be opened. + +\pnum +\remarks +The locale argument \tcode{loc} is used for +character set code conversion when retrieving messages, if needed. +\end{itemdescr} + +\indexlibrarymember{messages}{do_get}% +\begin{itemdecl} +string_type do_get(catalog cat, int set, int msgid, const string_type& dfault) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{cat} is a catalog obtained from \tcode{open()} and not yet closed. + +\pnum +\returns +A message identified by +arguments \tcode{set}, \tcode{msgid}, and \tcode{dfault}, +according to +an \impldef{mapping to message when calling \tcode{messages::do_get}} mapping. +If no such message can be found, returns \tcode{dfault}. +\end{itemdescr} + +\indexlibrarymember{message}{do_close}% +\begin{itemdecl} +void do_close(catalog cat) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{cat} is a catalog obtained from \tcode{open()} and not yet closed. + +\pnum +\effects +Releases unspecified resources associated with \tcode{cat}. + +\pnum +\remarks +The limit on such resources, if any, is +\impldef{resource limits on a message catalog}. +\end{itemdescr} + +\rSec4[locale.messages.byname]{Class template \tcode{messages_byname}} + +\indexlibraryglobal{messages_byname}% +\begin{codeblock} +namespace std { + template + class messages_byname : public messages { + public: + using catalog = messages_base::catalog; + using string_type = basic_string; + + explicit messages_byname(const char*, size_t refs = 0); + explicit messages_byname(const string&, size_t refs = 0); + + protected: + ~messages_byname(); + }; +} +\end{codeblock} + +\rSec2[c.locales]{C library locales} + +\rSec3[clocale.syn]{Header \tcode{} synopsis} + +\indexlibraryglobal{lconv}% +\indexlibraryglobal{setlocale}% +\indexlibraryglobal{localeconv}% +\begin{codeblock} +namespace std { + struct lconv; + + char* setlocale(int category, const char* locale); + lconv* localeconv(); +} + +#define @\libmacro{NULL}@ @\textit{see \ref{support.types.nullptr}}@ +#define @\libmacro{LC_ALL}@ @\seebelow@ +#define @\libmacro{LC_COLLATE}@ @\seebelow@ +#define @\libmacro{LC_CTYPE}@ @\seebelow@ +#define @\libmacro{LC_MONETARY}@ @\seebelow@ +#define @\libmacro{LC_NUMERIC}@ @\seebelow@ +#define @\libmacro{LC_TIME}@ @\seebelow@ +\end{codeblock} + +\pnum +The contents and meaning of the header \libheaderdef{clocale} +are the same as the C standard library header \libheader{locale.h}. + +\rSec3[clocale.data.races]{Data races} + +\pnum +Calls to the function \tcode{setlocale} +may introduce a data race\iref{res.on.data.races} +with other calls to \tcode{setlocale} or +with calls to the functions listed in \tref{setlocale.data.races}. + +\xrefc{7.11} + +\begin{floattable} +{Potential \tcode{setlocale} data races} +{setlocale.data.races} +{lllll} +\topline + +\tcode{fprintf} & +\tcode{isprint} & +\tcode{iswdigit} & +\tcode{localeconv} & +\tcode{tolower} \\ + +\tcode{fscanf} & +\tcode{ispunct} & +\tcode{iswgraph} & +\tcode{mblen} & +\tcode{toupper} \\ + +\tcode{isalnum} & +\tcode{isspace} & +\tcode{iswlower} & +\tcode{mbstowcs} & +\tcode{towlower} \\ + +\tcode{isalpha} & +\tcode{isupper} & +\tcode{iswprint} & +\tcode{mbtowc} & +\tcode{towupper} \\ + +\tcode{isblank} & +\tcode{iswalnum} & +\tcode{iswpunct} & +\tcode{setlocale} & +\tcode{wcscoll} \\ + +\tcode{iscntrl} & +\tcode{iswalpha} & +\tcode{iswspace} & +\tcode{strcoll} & +\tcode{wcstod} \\ + +\tcode{isdigit} & +\tcode{iswblank} & +\tcode{iswupper} & +\tcode{strerror} & +\tcode{wcstombs} \\ + +\tcode{isgraph} & +\tcode{iswcntrl} & +\tcode{iswxdigit} & +\tcode{strtod} & +\tcode{wcsxfrm} \\ + +\tcode{islower} & +\tcode{iswctype} & +\tcode{isxdigit} & +\tcode{strxfrm} & +\tcode{wctomb} \\ +\end{floattable} + +\rSec1[text.encoding]{Text encodings identification} + +\rSec2[text.encoding.syn]{Header \tcode{} synopsis} + +\indexheader{text_encoding}% +\begin{codeblock} +namespace std { + struct text_encoding; + + // \ref{text.encoding.hash}, hash support + template struct hash; + template<> struct hash; +} +\end{codeblock} + +\rSec2[text.encoding.class]{Class \tcode{text_encoding}} + +\rSec3[text.encoding.overview]{Overview} + +\pnum +The class \tcode{text_encoding} describes an interface +for accessing the IANA Character Sets registry\supercite{iana-charset}. + +\indexlibraryglobal{text_encoding}% +\begin{codeblock} +namespace std { + struct text_encoding { + static constexpr size_t max_name_length = 63; + + // \ref{text.encoding.id}, enumeration \tcode{text_encoding::id} + enum class id : int_least32_t { + @\seebelow@ + }; + using enum id; + + constexpr text_encoding() = default; + constexpr explicit text_encoding(string_view enc) noexcept; + constexpr text_encoding(id i) noexcept; + + constexpr id mib() const noexcept; + constexpr const char* name() const noexcept; + + // \ref{text.encoding.aliases}, class \tcode{text_encoding::aliases_view} + struct aliases_view; + constexpr aliases_view aliases() const noexcept; + + friend constexpr bool operator==(const text_encoding& a, + const text_encoding& b) noexcept; + friend constexpr bool operator==(const text_encoding& encoding, id i) noexcept; + + static consteval text_encoding literal() noexcept; + static text_encoding environment(); + template static bool environment_is(); + + private: + id @\exposid{mib_}@ = id::unknown; // \expos + char @\exposid{name_}@[max_name_length + 1] = {0}; // \expos + static constexpr bool @\exposidnc{comp-name}@(string_view a, string_view b); // \expos + }; +} +\end{codeblock} + +\pnum +Class \tcode{text_encoding} is +a trivially copyable type\iref{term.trivially.copyable.type}. + +\rSec3[text.encoding.general]{General} + +\pnum +A \defnadj{registered character}{encoding} is +a character encoding scheme in the IANA Character Sets registry. +\begin{note} +The IANA Character Sets registry uses the term ``character sets'' +to refer to character encodings. +\end{note} +The primary name of a registered character encoding is +the name of that encoding specified in the IANA Character Sets registry. + +\pnum +The set of known registered character encodings contains +every registered character encoding +specified in the IANA Character Sets registry except for the following: +\begin{itemize} +\item NATS-DANO (33) +\item NATS-DANO-ADD (34) +\end{itemize} + +\pnum +Each known registered character encoding +is identified by an enumerator in \tcode{text_encoding::id}, and +has a set of zero or more \defnx{aliases}{encoding!registered character!alias}. + +\pnum +The set of aliases of a known registered character encoding is an +\impldef{set of aliases of a known registered character encoding} +superset of the aliases specified in the IANA Character Sets registry. +The set of aliases for US-ASCII includes ``ASCII''. +No two aliases or primary names of distinct registered character encodings +are equivalent when compared by \tcode{text_encoding::\exposid{comp-name}}. + +\pnum +How a \tcode{text_encoding} object +is determined to be representative of a character encoding scheme +implemented in the translation or execution environment is +\impldef{how \tcode{text_encoding} objects are +determined to be representative of a character encoding scheme}. + +\pnum +An object \tcode{e} of type \tcode{text_encoding} such that +\tcode{e.mib() == text_encoding::id::unknown} is \tcode{false} and +\tcode{e.mib() == text_encoding::id::other} is \tcode{false} +maintains the following invariants: +\begin{itemize} +\item \tcode{*e.name() == '\textbackslash 0'} is \tcode{false}, and +\item \tcode{e.mib() == text_encoding(e.name()).mib()} is \tcode{true}. +\end{itemize} + +\pnum +\recommended +\begin{itemize} +\item +Implementations should not consider registered encodings to be interchangeable. +\begin{example} +Shift_JIS and Windows-31J denote different encodings. +\end{example} +\item +Implementations should not use the name of a registered encoding +to describe another similar yet different non-registered encoding +unless there is a precedent on that implementation. +\begin{example} +Big5 +\end{example} +\end{itemize} + +\rSec3[text.encoding.members]{Members} + +\indexlibraryctor{text_encoding}% +\begin{itemdecl} +constexpr explicit text_encoding(string_view enc) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\begin{itemize} +\item +\tcode{enc} represents a string in the ordinary literal encoding +consisting only of elements of the basic character set\iref{lex.charset}. +\item +\tcode{enc.size() <= max_name_length} is \tcode{true}. +\item +\tcode{enc.contains('\textbackslash 0')} is \tcode{false}. +\end{itemize} + +\pnum +\ensures +\begin{itemize} +\item +If there exists a primary name or alias \tcode{a} +of a known registered character encoding such that +\tcode{\exposid{comp-name}(a, enc)} is \tcode{true}, +\exposid{mib_} has the value of the enumerator of \tcode{id} +associated with that registered character encoding. +Otherwise, \tcode{\exposid{mib_} == id::other} is \tcode{true}. +\item +\tcode{enc.compare(\exposid{name_}) == 0} is \tcode{true}. +\end{itemize} +\end{itemdescr} + +\indexlibraryctor{text_encoding}% +\begin{itemdecl} +constexpr text_encoding(id i) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{i} has the value of one of the enumerators of \tcode{id}. + +\pnum +\ensures +\begin{itemize} +\item +\tcode{\exposid{mib_} == i} is \tcode{true}. +\item +If \tcode{(\exposid{mib_} == id::unknown || \exposid{mib_} == id::other)} +is \tcode{true}, +\tcode{strlen(\exposid{name_}) == 0} is \tcode{true}. +Otherwise, +\tcode{ranges::contains(aliases(), string_view(\exposid{name_}))} +is \tcode{true}. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{mib}{text_encoding}% +\begin{itemdecl} +constexpr id mib() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{mib_}. +\end{itemdescr} + +\indexlibrarymember{name}{text_encoding}% +\begin{itemdecl} +constexpr const char* name() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{name_}. + +\pnum +\remarks +\tcode{name()} is an \ntbs{} and +accessing elements of \exposid{name_} +outside of the range \countedrange{name()}{strlen(name()) + 1} +is undefined behavior. +\end{itemdescr} + +\indexlibrarymember{aliases}{text_encoding}% +\begin{itemdecl} +constexpr aliases_view aliases() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +Let \tcode{r} denote an instance of \tcode{aliases_view}. +If \tcode{*this} represents a known registered character encoding, then: +\begin{itemize} +\item +\tcode{r.front()} is the primary name of the registered character encoding, +\item +\tcode{r} contains the aliases of the registered character encoding, and +\item +\tcode{r} does not contain duplicate values when compared with \tcode{strcmp}. +\end{itemize} +Otherwise, \tcode{r} is an empty range. + +\pnum +Each element in \tcode{r} +is a non-null, non-empty \ntbs{} encoded in the literal character encoding and +comprising only characters from the basic character set. + +\pnum +\returns +\tcode{r}. + +\pnum +\begin{note} +The order of aliases in \tcode{r} is unspecified. +\end{note} +\end{itemdescr} + +\indexlibrarymember{literal}{text_encoding}% +\begin{itemdecl} +static consteval text_encoding literal() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{CHAR_BIT == 8} is \tcode{true}. + +\pnum +\returns +A \tcode{text_encoding} object representing +the ordinary character literal encoding\iref{lex.charset}. +\end{itemdescr} + +\indexlibrarymember{environment}{text_encoding}% +\begin{itemdecl} +static text_encoding environment(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{CHAR_BIT == 8} is \tcode{true}. + +\pnum +\returns +A \tcode{text_encoding} object representing +the \impldef{character encoding scheme of the environment} +character encoding scheme of the environment. +On a POSIX implementation, this is the encoding scheme associated with +the POSIX locale denoted by the empty string \tcode{""}. + +\pnum +\begin{note} +This function is not affected by calls to \tcode{setlocale}. +\end{note} + +\pnum +\recommended +Implementations should return a value that is not affected by calls to +the POSIX function \tcode{setenv} and +other functions which can modify the environment\iref{support.runtime}. +\end{itemdescr} + +\indexlibrarymember{environment_is}{text_encoding}% +\begin{itemdecl} +template + static bool environment_is(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{CHAR_BIT == 8} is \tcode{true}. + +\pnum +\returns +\tcode{environment() == i}. +\end{itemdescr} + +\indexlibrarymember{\exposid{comp-name}}{text_encoding}% +\begin{itemdecl} +static constexpr bool @\exposid{comp-name}@(string_view a, string_view b); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if the two strings \tcode{a} and \tcode{b} +encoded in the ordinary literal encoding +are equal, ignoring, from left-to-right, +\begin{itemize} +\item +all elements that are not digits or letters\iref{character.seq.general}, +\item +character case, and +\item +any sequence of one or more \tcode{0} characters +not immediately preceded by a numeric prefix, where +a numeric prefix is a sequence consisting of +a digit in the range \crange{1}{9} +optionally followed by one or more elements which are not digits or letters, +\end{itemize} +and \tcode{false} otherwise. + +\begin{note} +This comparison is identical to +the ``Charset Alias Matching'' algorithm +described in the Unicode Technical Standard 22\supercite{unicode-charmap}. +\end{note} + +\begin{example} +\begin{codeblock} +static_assert(@\exposid{comp-name}@("UTF-8", "utf8") == true); +static_assert(@\exposid{comp-name}@("u.t.f-008", "utf8") == true); +static_assert(@\exposid{comp-name}@("ut8", "utf8") == false); +static_assert(@\exposid{comp-name}@("utf-80", "utf8") == false); +\end{codeblock} +\end{example} +\end{itemdescr} + +\rSec3[text.encoding.cmp]{Comparison functions} + +\indexlibrarymember{operator==}{text_encoding}% +\begin{itemdecl} +friend constexpr bool operator==(const text_encoding& a, const text_encoding& b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \tcode{a.\exposid{mib_} == id::other \&\& b.\exposid{mib_} == id::other} +is \tcode{true}, +then \tcode{\exposid{comp-name}(a.\exposid{name_},\linebreak{}b.\exposid{name_})}. +Otherwise, \tcode{a.\exposid{mib_} == b.\exposid{mib_}}. +\end{itemdescr} + +\indexlibrarymember{operator==}{text_encoding}% +\begin{itemdecl} +friend constexpr bool operator==(const text_encoding& encoding, id i) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{encoding.\exposid{mib_} == i}. + +\pnum +\remarks +This operator induces an equivalence relation on its arguments +if and only if \tcode{i != id::other} is \tcode{true}. +\end{itemdescr} + +\rSec3[text.encoding.aliases]{Class \tcode{text_encoding::aliases_view}} + +\indexlibrarymember{aliases_view}{text_encoding}% +\indexlibrarymember{begin}{text_encoding::aliases_view}% +\indexlibrarymember{end}{text_encoding::aliases_view}% +\begin{itemdecl} +struct text_encoding::aliases_view : ranges::view_interface { + constexpr @\impdefx{type of \tcode{text_encoding::aliases_view::begin()}}@ begin() const; + constexpr @\impdefx{type of \tcode{text_encoding::aliases_view::end()}}@ end() const; +}; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{text_encoding::aliases_view} models +\libconcept{copyable}, +\tcode{ranges::\libconcept{view}}, +\tcode{ranges::\libconcept{random_access_range}}, and +\tcode{ranges::\libconcept{borrowed_range}}. +\begin{note} +\tcode{text_encoding::aliases_view} is not required to satisfy +\tcode{ranges::}\libconcept{common_range}, +nor \libconcept{default_initializable}. +\end{note} + +\pnum +Both +\tcode{ranges::range_value_t} and +\tcode{ranges::range_reference_t} +denote \tcode{const char*}. + +\pnum +\tcode{ranges::iterator_t} +is a constexpr iterator\iref{iterator.requirements.general}. +\end{itemdescr} + +\rSec3[text.encoding.id]{Enumeration \tcode{text_encoding::id}} + +\indexlibrarymember{id}{text_encoding}% +\begin{codeblock} +namespace std { + enum class text_encoding::id : int_least32_t { + other = 1, + unknown = 2, + ASCII = 3, + ISOLatin1 = 4, + ISOLatin2 = 5, + ISOLatin3 = 6, + ISOLatin4 = 7, + ISOLatinCyrillic = 8, + ISOLatinArabic = 9, + ISOLatinGreek = 10, + ISOLatinHebrew = 11, + ISOLatin5 = 12, + ISOLatin6 = 13, + ISOTextComm = 14, + HalfWidthKatakana = 15, + JISEncoding = 16, + ShiftJIS = 17, + EUCPkdFmtJapanese = 18, + EUCFixWidJapanese = 19, + ISO4UnitedKingdom = 20, + ISO11SwedishForNames = 21, + ISO15Italian = 22, + ISO17Spanish = 23, + ISO21German = 24, + ISO60DanishNorwegian = 25, + ISO69French = 26, + ISO10646UTF1 = 27, + ISO646basic1983 = 28, + INVARIANT = 29, + ISO2IntlRefVersion = 30, + NATSSEFI = 31, + NATSSEFIADD = 32, + ISO10Swedish = 35, + KSC56011987 = 36, + ISO2022KR = 37, + EUCKR = 38, + ISO2022JP = 39, + ISO2022JP2 = 40, + ISO13JISC6220jp = 41, + ISO14JISC6220ro = 42, + ISO16Portuguese = 43, + ISO18Greek7Old = 44, + ISO19LatinGreek = 45, + ISO25French = 46, + ISO27LatinGreek1 = 47, + ISO5427Cyrillic = 48, + ISO42JISC62261978 = 49, + ISO47BSViewdata = 50, + ISO49INIS = 51, + ISO50INIS8 = 52, + ISO51INISCyrillic = 53, + ISO54271981 = 54, + ISO5428Greek = 55, + ISO57GB1988 = 56, + ISO58GB231280 = 57, + ISO61Norwegian2 = 58, + ISO70VideotexSupp1 = 59, + ISO84Portuguese2 = 60, + ISO85Spanish2 = 61, + ISO86Hungarian = 62, + ISO87JISX0208 = 63, + ISO88Greek7 = 64, + ISO89ASMO449 = 65, + ISO90 = 66, + ISO91JISC62291984a = 67, + ISO92JISC62991984b = 68, + ISO93JIS62291984badd = 69, + ISO94JIS62291984hand = 70, + ISO95JIS62291984handadd = 71, + ISO96JISC62291984kana = 72, + ISO2033 = 73, + ISO99NAPLPS = 74, + ISO102T617bit = 75, + ISO103T618bit = 76, + ISO111ECMACyrillic = 77, + ISO121Canadian1 = 78, + ISO122Canadian2 = 79, + ISO123CSAZ24341985gr = 80, + ISO88596E = 81, + ISO88596I = 82, + ISO128T101G2 = 83, + ISO88598E = 84, + ISO88598I = 85, + ISO139CSN369103 = 86, + ISO141JUSIB1002 = 87, + ISO143IECP271 = 88, + ISO146Serbian = 89, + ISO147Macedonian = 90, + ISO150 = 91, + ISO151Cuba = 92, + ISO6937Add = 93, + ISO153GOST1976874 = 94, + ISO8859Supp = 95, + ISO10367Box = 96, + ISO158Lap = 97, + ISO159JISX02121990 = 98, + ISO646Danish = 99, + USDK = 100, + DKUS = 101, + KSC5636 = 102, + Unicode11UTF7 = 103, + ISO2022CN = 104, + ISO2022CNEXT = 105, + UTF8 = 106, + ISO885913 = 109, + ISO885914 = 110, + ISO885915 = 111, + ISO885916 = 112, + GBK = 113, + GB18030 = 114, + OSDEBCDICDF0415 = 115, + OSDEBCDICDF03IRV = 116, + OSDEBCDICDF041 = 117, + ISO115481 = 118, + KZ1048 = 119, + UCS2 = 1000, + UCS4 = 1001, + UnicodeASCII = 1002, + UnicodeLatin1 = 1003, + UnicodeJapanese = 1004, + UnicodeIBM1261 = 1005, + UnicodeIBM1268 = 1006, + UnicodeIBM1276 = 1007, + UnicodeIBM1264 = 1008, + UnicodeIBM1265 = 1009, + Unicode11 = 1010, + SCSU = 1011, + UTF7 = 1012, + UTF16BE = 1013, + UTF16LE = 1014, + UTF16 = 1015, + CESU8 = 1016, + UTF32 = 1017, + UTF32BE = 1018, + UTF32LE = 1019, + BOCU1 = 1020, + UTF7IMAP = 1021, + Windows30Latin1 = 2000, + Windows31Latin1 = 2001, + Windows31Latin2 = 2002, + Windows31Latin5 = 2003, + HPRoman8 = 2004, + AdobeStandardEncoding = 2005, + VenturaUS = 2006, + VenturaInternational = 2007, + DECMCS = 2008, + PC850Multilingual = 2009, + PCp852 = 2010, + PC8CodePage437 = 2011, + PC8DanishNorwegian = 2012, + PC862LatinHebrew = 2013, + PC8Turkish = 2014, + IBMSymbols = 2015, + IBMThai = 2016, + HPLegal = 2017, + HPPiFont = 2018, + HPMath8 = 2019, + HPPSMath = 2020, + HPDesktop = 2021, + VenturaMath = 2022, + MicrosoftPublishing = 2023, + Windows31J = 2024, + GB2312 = 2025, + Big5 = 2026, + Macintosh = 2027, + IBM037 = 2028, + IBM038 = 2029, + IBM273 = 2030, + IBM274 = 2031, + IBM275 = 2032, + IBM277 = 2033, + IBM278 = 2034, + IBM280 = 2035, + IBM281 = 2036, + IBM284 = 2037, + IBM285 = 2038, + IBM290 = 2039, + IBM297 = 2040, + IBM420 = 2041, + IBM423 = 2042, + IBM424 = 2043, + IBM500 = 2044, + IBM851 = 2045, + IBM855 = 2046, + IBM857 = 2047, + IBM860 = 2048, + IBM861 = 2049, + IBM863 = 2050, + IBM864 = 2051, + IBM865 = 2052, + IBM868 = 2053, + IBM869 = 2054, + IBM870 = 2055, + IBM871 = 2056, + IBM880 = 2057, + IBM891 = 2058, + IBM903 = 2059, + IBM904 = 2060, + IBM905 = 2061, + IBM918 = 2062, + IBM1026 = 2063, + IBMEBCDICATDE = 2064, + EBCDICATDEA = 2065, + EBCDICCAFR = 2066, + EBCDICDKNO = 2067, + EBCDICDKNOA = 2068, + EBCDICFISE = 2069, + EBCDICFISEA = 2070, + EBCDICFR = 2071, + EBCDICIT = 2072, + EBCDICPT = 2073, + EBCDICES = 2074, + EBCDICESA = 2075, + EBCDICESS = 2076, + EBCDICUK = 2077, + EBCDICUS = 2078, + Unknown8BiT = 2079, + Mnemonic = 2080, + Mnem = 2081, + VISCII = 2082, + VIQR = 2083, + KOI8R = 2084, + HZGB2312 = 2085, + IBM866 = 2086, + PC775Baltic = 2087, + KOI8U = 2088, + IBM00858 = 2089, + IBM00924 = 2090, + IBM01140 = 2091, + IBM01141 = 2092, + IBM01142 = 2093, + IBM01143 = 2094, + IBM01144 = 2095, + IBM01145 = 2096, + IBM01146 = 2097, + IBM01147 = 2098, + IBM01148 = 2099, + IBM01149 = 2100, + Big5HKSCS = 2101, + IBM1047 = 2102, + PTCP154 = 2103, + Amiga1251 = 2104, + KOI7switched = 2105, + BRF = 2106, + TSCII = 2107, + CP51932 = 2108, + windows874 = 2109, + windows1250 = 2250, + windows1251 = 2251, + windows1252 = 2252, + windows1253 = 2253, + windows1254 = 2254, + windows1255 = 2255, + windows1256 = 2256, + windows1257 = 2257, + windows1258 = 2258, + TIS620 = 2259, + CP50220 = 2260 + }; +} +\end{codeblock} + +\begin{note} +The \tcode{text_encoding::id} enumeration +contains an enumerator for each known registered character encoding. +For each encoding, the corresponding enumerator is derived from +the alias beginning with ``\tcode{cs}'', as follows +\begin{itemize} +\item +\tcode{csUnicode} is mapped to \tcode{text_encoding::id::UCS2}, +\item +\tcode{csIBBM904} is mapped to \tcode{text_encoding::id::IBM904}, and +\item +the ``\tcode{cs}'' prefix is removed from other names. +\end{itemize} +\end{note} + +\rSec3[text.encoding.hash]{Hash support} + +\indexlibrarymember{hash}{text_encoding}% +\begin{itemdecl} +template<> struct hash; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The specialization is enabled\iref{unord.hash}. +\end{itemdescr} + +\rSec1[format]{Formatting} + +\rSec2[format.syn]{Header \tcode{} synopsis} + +\indexheader{format}% +\indexlibraryglobal{format_parse_context}% +\indexlibraryglobal{wformat_parse_context}% +\indexlibraryglobal{format_context}% +\indexlibraryglobal{wformat_context}% +\indexlibraryglobal{format_args}% +\indexlibraryglobal{wformat_args}% +\indexlibraryglobal{format_to_n_result}% +\indexlibrarymember{out}{format_to_n_result}% +\indexlibrarymember{size}{format_to_n_result}% +\begin{codeblock} +namespace std { + // \ref{format.context}, class template \tcode{basic_format_context} + template class basic_format_context; + using format_context = basic_format_context<@\unspec@, char>; + using wformat_context = basic_format_context<@\unspec@, wchar_t>; + + // \ref{format.args}, class template \tcode{basic_format_args} + template class basic_format_args; + using format_args = basic_format_args; + using wformat_args = basic_format_args; + + // \ref{format.fmt.string}, class template \tcode{basic_format_string} + template + struct basic_format_string; + + template struct @\exposid{runtime-format-string}@ { // \expos + private: + basic_string_view @\exposid{str}@; // \expos + public: + @\exposid{runtime-format-string}@(basic_string_view s) noexcept : @\exposid{str}@(s) {} + @\exposid{runtime-format-string}@(const @\exposid{runtime-format-string}@&) = delete; + @\exposid{runtime-format-string}@& operator=(const @\exposid{runtime-format-string}@&) = delete; + }; + @\exposid{runtime-format-string}@ runtime_format(string_view fmt) noexcept { return fmt; } + @\exposid{runtime-format-string}@ runtime_format(wstring_view fmt) noexcept { return fmt; } + + template + using @\libglobal{format_string}@ = basic_format_string...>; + template + using @\libglobal{wformat_string}@ = basic_format_string...>; + + // \ref{format.functions}, formatting functions + template + string format(format_string fmt, Args&&... args); + template + wstring format(wformat_string fmt, Args&&... args); + template + string format(const locale& loc, format_string fmt, Args&&... args); + template + wstring format(const locale& loc, wformat_string fmt, Args&&... args); + + string vformat(string_view fmt, format_args args); + wstring vformat(wstring_view fmt, wformat_args args); + string vformat(const locale& loc, string_view fmt, format_args args); + wstring vformat(const locale& loc, wstring_view fmt, wformat_args args); + + template + Out format_to(Out out, format_string fmt, Args&&... args); + template + Out format_to(Out out, wformat_string fmt, Args&&... args); + template + Out format_to(Out out, const locale& loc, format_string fmt, Args&&... args); + template + Out format_to(Out out, const locale& loc, wformat_string fmt, Args&&... args); + + template + Out vformat_to(Out out, string_view fmt, format_args args); + template + Out vformat_to(Out out, wstring_view fmt, wformat_args args); + template + Out vformat_to(Out out, const locale& loc, string_view fmt, format_args args); + template + Out vformat_to(Out out, const locale& loc, wstring_view fmt, wformat_args args); + + template struct format_to_n_result { + Out out; + iter_difference_t size; + }; + template + format_to_n_result format_to_n(Out out, iter_difference_t n, + format_string fmt, Args&&... args); + template + format_to_n_result format_to_n(Out out, iter_difference_t n, + wformat_string fmt, Args&&... args); + template + format_to_n_result format_to_n(Out out, iter_difference_t n, + const locale& loc, format_string fmt, + Args&&... args); + template + format_to_n_result format_to_n(Out out, iter_difference_t n, + const locale& loc, wformat_string fmt, + Args&&... args); + + template + size_t formatted_size(format_string fmt, Args&&... args); + template + size_t formatted_size(wformat_string fmt, Args&&... args); + template + size_t formatted_size(const locale& loc, format_string fmt, Args&&... args); + template + size_t formatted_size(const locale& loc, wformat_string fmt, Args&&... args); + + // \ref{format.formatter}, formatter + template struct formatter; + + // \ref{format.formatter.locking}, formatter locking + template + constexpr bool enable_nonlocking_formatter_optimization = false; + + // \ref{format.formattable}, concept \libconcept{formattable} + template + concept formattable = @\seebelow@; + + template + concept @\defexposconcept{const-formattable-range}@ = // \expos + ranges::@\libconcept{input_range}@ && + @\libconcept{formattable}@, charT>; + + template + using @\exposid{fmt-maybe-const}@ = // \expos + conditional_t<@\exposconcept{const-formattable-range}@, const R, R>; + + // \ref{format.parse.ctx}, class template \tcode{basic_format_parse_context} + template class basic_format_parse_context; + using format_parse_context = basic_format_parse_context; + using wformat_parse_context = basic_format_parse_context; + + // \ref{format.range}, formatting of ranges + // \ref{format.range.fmtkind}, variable template \tcode{format_kind} + enum class @\libglobal{range_format}@ { + @\libmember{disabled}{range_format}@, + @\libmember{map}{range_format}@, + @\libmember{set}{range_format}@, + @\libmember{sequence}{range_format}@, + @\libmember{string}{range_format}@, + @\libmember{debug_string}{range_format}@ + }; + + template + constexpr @\unspec@ format_kind = @\unspec@; + + template + requires @\libconcept{same_as}@> + constexpr range_format format_kind = @\seebelow@; + + // \ref{format.range.formatter}, class template \tcode{range_formatter} + template + requires @\libconcept{same_as}@, T> && @\libconcept{formattable}@ + class range_formatter; + + // \ref{format.range.fmtdef}, class template \exposid{range-default-formatter} + template + struct @\exposid{range-default-formatter}@; // \expos + + // \ref{format.range.fmtmap}, \ref{format.range.fmtset}, \ref{format.range.fmtstr}, specializations for maps, sets, and strings + template + requires (format_kind != range_format::disabled) && + @\libconcept{formattable}@, charT> + struct formatter : @\exposid{range-default-formatter}@, R, charT> { }; + + template + requires (format_kind != range_format::disabled) + constexpr bool enable_nonlocking_formatter_optimization = false; + + // \ref{format.arguments}, arguments + // \ref{format.arg}, class template \tcode{basic_format_arg} + template class basic_format_arg; + + // \ref{format.arg.store}, class template \exposid{format-arg-store} + template class @\exposidnc{format-arg-store}@; // \expos + + template + @\exposid{format-arg-store}@ + make_format_args(Args&... fmt_args); + template + @\exposid{format-arg-store}@ + make_wformat_args(Args&... args); + + // \ref{format.error}, class \tcode{format_error} + class format_error; +} +\end{codeblock} + + +\pnum +The class template \tcode{format_to_n_result} +has the template parameters, data members, and special members specified above. It has no base classes or members other than those specified. + +\rSec2[format.string]{Format string} + +\rSec3[format.string.general]{General} + +\pnum +A \defn{format string} for arguments \tcode{args} is +a (possibly empty) sequence of +\defnx{replacement fields}{replacement field!format string}, +\defnx{escape sequences}{escape sequence!format string}, +and characters other than \tcode{\{} and \tcode{\}}. +Let \tcode{charT} be the character type of the format string. +Each character that is not part of +a replacement field or an escape sequence +is copied unchanged to the output. +An escape sequence is one of \tcode{\{\{} or \tcode{\}\}}. +It is replaced with \tcode{\{} or \tcode{\}}, respectively, in the output. +The syntax of replacement fields is as follows: + +\begin{ncbnf} +\fmtnontermdef{replacement-field}\br + \terminal{\{} \opt{arg-id} \opt{format-specifier} \terminal{\}} +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{arg-id}\br + \terminal{0}\br + positive-integer +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{positive-integer}\br + nonzero-digit\br + positive-integer digit +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{nonnegative-integer}\br + digit\br + nonnegative-integer digit +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{nonzero-digit} \textnormal{one of}\br + \terminal{1 2 3 4 5 6 7 8 9} +\end{ncbnf} + +% FIXME: This exactly duplicates the digit grammar term from [lex] +\begin{ncbnf} +\fmtnontermdef{digit} \textnormal{one of}\br + \terminal{0 1 2 3 4 5 6 7 8 9} +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{format-specifier}\br + \terminal{:} format-spec +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{format-spec}\br + \textnormal{as specified by the \tcode{formatter} specialization for the argument type; cannot start with \terminal{\}} } +\end{ncbnf} + +\pnum +The \fmtgrammarterm{arg-id} field specifies the index of +the argument in \tcode{args} +whose value is to be formatted and inserted into the output +instead of the replacement field. +If there is no argument with +the index \fmtgrammarterm{arg-id} in \tcode{args}, +the string is not a format string for \tcode{args}. +The optional \fmtgrammarterm{format-specifier} field +explicitly specifies a format for the replacement value. + +\pnum +\begin{example} +\begin{codeblock} +string s = format("{0}-{{", 8); // value of \tcode{s} is \tcode{"8-\{"} +\end{codeblock} +\end{example} + +\pnum +If all \fmtgrammarterm{arg-id}s in a format string are omitted +(including those in the \fmtgrammarterm{format-spec}, +as interpreted by the corresponding \tcode{formatter} specialization), +argument indices 0, 1, 2, \ldots{} will automatically be used in that order. +If some \fmtgrammarterm{arg-id}s are omitted and some are present, +the string is not a format string. +\begin{note} +A format string cannot contain a +mixture of automatic and manual indexing. +\end{note} +\begin{example} +\begin{codeblock} +string s0 = format("{} to {}", "a", "b"); // OK, automatic indexing +string s1 = format("{1} to {0}", "a", "b"); // OK, manual indexing +string s2 = format("{0} to {}", "a", "b"); // not a format string (mixing automatic and manual indexing), + // ill-formed +string s3 = format("{} to {1}", "a", "b"); // not a format string (mixing automatic and manual indexing), + // ill-formed +\end{codeblock} +\end{example} + +\pnum +The \fmtgrammarterm{format-spec} field contains +\defnx{format specifications}{format specification!format string} +that define how the value should be presented. +Each type can define its own +interpretation of the \fmtgrammarterm{format-spec} field. +If \fmtgrammarterm{format-spec} does not conform +to the format specifications for +the argument type referred to by \fmtgrammarterm{arg-id}, +the string is not a format string for \tcode{args}. +\begin{example} +\begin{itemize} +\item +For arithmetic, pointer, and string types +the \fmtgrammarterm{format-spec} +is interpreted as a \fmtgrammarterm{std-format-spec} +as described in~\ref{format.string.std}. +\item +For chrono types +the \fmtgrammarterm{format-spec} +is interpreted as a \fmtgrammarterm{chrono-format-spec} +as described in~\ref{time.format}. +\item +For user-defined \tcode{formatter} specializations, +the behavior of the \tcode{parse} member function +determines how the \fmtgrammarterm{format-spec} +is interpreted. +\end{itemize} +\end{example} + +\rSec3[format.string.std]{Standard format specifiers} + +\pnum +Each \tcode{formatter} specialization +described in \ref{format.formatter.spec} +for fundamental and string types +interprets \fmtgrammarterm{format-spec} as a +\fmtgrammarterm{std-format-spec}. +\begin{note} +The format specification can be used to specify such details as +minimum field width, alignment, padding, and decimal precision. +Some of the formatting options +are only supported for arithmetic types. +\end{note} +The syntax of format specifications is as follows: + +\begin{ncbnf} +\fmtnontermdef{std-format-spec}\br + \opt{fill-and-align} \opt{sign} \opt{\terminal{\#}} \opt{\terminal{0}} \opt{width} \opt{precision} \opt{\terminal{L}} \opt{type} +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{fill-and-align}\br + \opt{fill} align +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{fill}\br + \textnormal{any character other than \tcode{\{} or \tcode{\}}} +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{align} \textnormal{one of}\br + \terminal{< > \caret} +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{sign} \textnormal{one of}\br + \terminal{+ -} \textnormal{space} +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{width}\br + positive-integer\br + \terminal{\{} \opt{arg-id} \terminal{\}} +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{precision}\br + \terminal{.} nonnegative-integer\br + \terminal{.} \terminal{\{} \opt{arg-id} \terminal{\}} +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{type} \textnormal{one of}\br + \terminal{a A b B c d e E f F g G o p P s x X ?} +\end{ncbnf} + +\pnum +Field widths are specified in \defnadj{field width}{units}; +the number of column positions required to display a sequence of +characters in a terminal. +The \defnadj{minimum}{field width} +is the number of field width units a replacement field minimally requires of +the formatted sequence of characters produced for a format argument. +The \defnadj{estimated}{field width} is the number of field width units +that are required for the formatted sequence of characters +produced for a format argument independent of +the effects of the \fmtgrammarterm{width} option. +The \defnadj{padding}{width} is the greater of \tcode{0} and +the difference of the minimum field width and the estimated field width. + +\begin{note} +The POSIX \tcode{wcswidth} function is an example of a function that, +given a string, returns the number of column positions required by +a terminal to display the string. +\end{note} + +\pnum +The \defnadj{fill}{character} is the character denoted by +the \fmtgrammarterm{fill} option or, +if the \fmtgrammarterm{fill} option is absent, the space character. +For a format specification in UTF-8, UTF-16, or UTF-32, +the fill character corresponds to a single Unicode scalar value. +\begin{note} +The presence of a \fmtgrammarterm{fill} option +is signaled by the character following it, +which must be one of the alignment options. +If the second character of \fmtgrammarterm{std-format-spec} +is not a valid alignment option, +then it is assumed that +the \fmtgrammarterm{fill} and \fmtgrammarterm{align} options +are both absent. +\end{note} + +\pnum +The \fmtgrammarterm{align} option applies to all argument types. +The meaning of the various alignment options is as specified in \tref{format.align}. +\begin{example} +\begin{codeblock} +char c = 120; +string s0 = format("{:6}", 42); // value of \tcode{s0} is \tcode{"\ \ \ \ 42"} +string s1 = format("{:6}", 'x'); // value of \tcode{s1} is \tcode{"x\ \ \ \ \ "} +string s2 = format("{:*<6}", 'x'); // value of \tcode{s2} is \tcode{"x*****"} +string s3 = format("{:*>6}", 'x'); // value of \tcode{s3} is \tcode{"*****x"} +string s4 = format("{:*@\caret{}@6}", 'x'); // value of \tcode{s4} is \tcode{"**x***"} +string s5 = format("{:6d}", c); // value of \tcode{s5} is \tcode{"\ \ \ 120"} +string s6 = format("{:6}", true); // value of \tcode{s6} is \tcode{"true\ \ "} +string s7 = format("{:*<6.3}", "123456"); // value of \tcode{s7} is \tcode{"123***"} +string s8 = format("{:02}", 1234); // value of \tcode{s8} is \tcode{"1234"} +string s9 = format("{:*<}", "12"); // value of \tcode{s9} is \tcode{"12"} +string sA = format("{:*<6}", "12345678"); // value of \tcode{sA} is \tcode{"12345678"} +string sB = format("{:@\importexample[-2pt]{example_05}\kern0.75pt\caret{}@6}", "x"); // value of \tcode{sB} is \tcode{"\importexample[-2pt]{example_05}\importexample[-2pt]{example_05}x\importexample[-2pt]{example_05}\importexample[-2pt]{example_05}\importexample[-2pt]{example_05}"} +string sC = format("{:*@\caret{}@6}", "@\importexample[-2pt]{example_05}\kern0.75pt\importexample[-2pt]{example_05}\kern0.75pt\importexample[-2pt]{example_05}\kern0.75pt@"); // value of \tcode{sC} is \tcode{"\importexample[-2pt]{example_05}\importexample[-2pt]{example_05}\importexample[-2pt]{example_05}"} +\end{codeblock} +\end{example} +\begin{note} +The \fmtgrammarterm{fill}, \fmtgrammarterm{align}, and \tcode{0} options +have no effect when the minimum field width +is not greater than the estimated field width +because padding width is \tcode{0} in that case. +Since fill characters are assumed to have a field width of \tcode{1}, +use of a character with a different field width can produce misaligned output. +The \importexample[-2pt]{example_05} (\unicode{1f921}{clown face}) character has a field width of \tcode{2}. +The examples above that include that character +illustrate the effect of the field width +when that character is used as a fill character +as opposed to when it is used as a formatting argument. +\end{note} + +\begin{floattable}{Meaning of \fmtgrammarterm{align} options}{format.align}{lp{.8\hsize}} +\topline +\lhdr{Option} & \rhdr{Meaning} \\ \rowsep +\tcode{<} & +Forces the formatted argument to be aligned to the start of the field +by inserting $n$ fill characters after the formatted argument +where $n$ is the padding width. +This is the default for +non-arithmetic non-pointer types, \tcode{charT}, and \tcode{bool}, +unless an integer presentation type is specified. +\\ \rowsep +% +\tcode{>} & +Forces the formatted argument to be aligned to the end of the field +by inserting $n$ fill characters before the formatted argument +where $n$ is the padding width. +This is the default for +arithmetic types other than \tcode{charT} and \tcode{bool}, +pointer types, +or when an integer presentation type is specified. +\\ \rowsep +% +\tcode{\caret} & +Forces the formatted argument to be centered within the field +by inserting +$\bigl\lfloor \frac{n}{2} \bigr\rfloor$ +fill characters before and +$\bigl\lceil \frac{n}{2} \bigr\rceil$ +fill characters after the formatted argument, where +$n$ is the padding width. +\\ +\end{floattable} + +\pnum +The \fmtgrammarterm{sign} option is only valid +for arithmetic types other than \tcode{charT} and \tcode{bool} +or when an integer presentation type is specified. +The meaning of the various options is as specified in \tref{format.sign}. + +\begin{floattable}{Meaning of \fmtgrammarterm{sign} options}{format.sign}{lp{.8\hsize}} +\topline +\lhdr{Option} & \rhdr{Meaning} \\ \rowsep +\tcode{+} & +Indicates that a sign should be used for both non-negative and negative +numbers. +The \tcode{+} sign is inserted before the output of \tcode{to_chars} for +non-negative numbers other than negative zero. +\begin{tailnote} +For negative numbers and negative zero +the output of \tcode{to_chars} will already contain the sign +so no additional transformation is performed. +\end{tailnote} +\\ \rowsep +% +\tcode{-} & +Indicates that a sign should be used for +negative numbers and negative zero only (this is the default behavior). +\\ \rowsep +% +space & +Indicates that a leading space should be used for +non-negative numbers other than negative zero, and +a minus sign for negative numbers and negative zero. +\\ +\end{floattable} + +\pnum +The \fmtgrammarterm{sign} option applies to floating-point infinity and NaN. +\begin{example} +\begin{codeblock} +double inf = numeric_limits::infinity(); +double nan = numeric_limits::quiet_NaN(); +string s0 = format("{0:},{0:+},{0:-},{0: }", 1); // value of \tcode{s0} is \tcode{"1,+1,1, 1"} +string s1 = format("{0:},{0:+},{0:-},{0: }", -1); // value of \tcode{s1} is \tcode{"-1,-1,-1,-1"} +string s2 = format("{0:},{0:+},{0:-},{0: }", inf); // value of \tcode{s2} is \tcode{"inf,+inf,inf, inf"} +string s3 = format("{0:},{0:+},{0:-},{0: }", nan); // value of \tcode{s3} is \tcode{"nan,+nan,nan, nan"} +\end{codeblock} +\end{example} + +\pnum +The \tcode{\#} option causes the +% FIXME: This is not a definition. +\defnx{alternate form}{alternate form!format string} +to be used for the conversion. +This option is valid for arithmetic types other than +\tcode{charT} and \tcode{bool} +or when an integer presentation type is specified, and not otherwise. +For integral types, +the alternate form inserts the +base prefix (if any) specified in \tref{format.type.int} +into the output after the sign character (possibly space) if there is one, or +before the output of \tcode{to_chars} otherwise. +For floating-point types, +the alternate form causes the result of the conversion of finite values +to always contain a decimal-point character, +even if no digits follow it. +% FIXME: This is a weird place for this part of the spec to appear. +Normally, a decimal-point character appears in the result of these +conversions only if a digit follows it. +In addition, for \tcode{g} and \tcode{G} conversions, +% FIXME: Are they normally? What does this even mean? Reach into to_chars and +% alter its behavior? +trailing zeros are not removed from the result. + +\pnum +The \tcode{0} option is valid for arithmetic types +other than \tcode{charT} and \tcode{bool}, pointer types, or +when an integer presentation type is specified. +For formatting arguments that have a value +other than an infinity or a NaN, +this option pads the formatted argument by +inserting the \tcode{0} character $n$ times +following the sign or base prefix indicators (if any) +where $n$ is \tcode{0} if the \fmtgrammarterm{align} option is present and +is the padding width otherwise. +\begin{example} +\begin{codeblock} +char c = 120; +string s1 = format("{:+06d}", c); // value of \tcode{s1} is \tcode{"+00120"} +string s2 = format("{:#06x}", 0xa); // value of \tcode{s2} is \tcode{"0x000a"} +string s3 = format("{:<06}", -42); // value of \tcode{s3} is \tcode{"-42\ \ \ "} (\tcode{0} has no effect) +string s4 = format("{:06}", inf); // value of \tcode{s4} is \tcode{"\ \ \ inf"} (\tcode{0} has no effect) +\end{codeblock} +\end{example} + +\pnum +The \fmtgrammarterm{width} option specifies the minimum field width. +If the \fmtgrammarterm{width} option is absent, +the minimum field width is \tcode{0}. + +\pnum +If \tcode{\{ \opt{\fmtgrammarterm{arg-id}} \}} is used in +a \fmtgrammarterm{width} or \fmtgrammarterm{precision} option, +the value of the corresponding formatting argument is used as the value of the option. +The option is valid only if the corresponding formatting argument is +of standard signed or unsigned integer type. +If its value is negative, +an exception of type \tcode{format_error} is thrown. + +\pnum +% FIXME: What if it's an arg-id? +If \fmtgrammarterm{positive-integer} is used in a +\fmtgrammarterm{width} option, the value of the \fmtgrammarterm{positive-integer} +is interpreted as a decimal integer and used as the value of the option. + +\pnum +For the purposes of width computation, +a string is assumed to be in +a locale-independent, +\impldef{encoding assumption for \tcode{format} width computation} encoding. +Implementations should use either UTF-8, UTF-16, or UTF-32, +on platforms capable of displaying Unicode text in a terminal. +\begin{note} +This is the case for Windows\textregistered{}-based +\begin{footnote} +Windows\textregistered\ is a registered trademark of Microsoft Corporation. +This information is given for the convenience of users of this document and +does not constitute an endorsement by ISO or IEC of this product. +\end{footnote} +and many POSIX-based operating systems. +\end{note} + +\pnum +For a sequence of characters in UTF-8, UTF-16, or UTF-32, +an implementation should use as its field width +the sum of the field widths of the first code point +of each extended grapheme cluster. +Extended grapheme clusters are defined by \UAX{29} of the Unicode Standard. +The following code points have a field width of 2: +\begin{itemize} +\item +any code point with the \tcode{East_Asian_Width="W"} or +\tcode{East_Asian_Width="F"} property as described by +\UAX{44} of the Unicode Standard +\item +\ucode{4dc0} -- \ucode{4dff} (Yijing Hexagram Symbols) +\item +\ucode{1f300} -- \ucode{1f5ff} (Miscellaneous Symbols and Pictographs) +\item +\ucode{1f900} -- \ucode{1f9ff} (Supplemental Symbols and Pictographs) +\end{itemize} +The field width of all other code points is 1. + +\pnum +For a sequence of characters in neither UTF-8, UTF-16, nor UTF-32, +the field width is unspecified. + +\pnum +The \fmtgrammarterm{precision} option is valid +for floating-point and string types. +For floating-point types, +the value of this option specifies the precision +to be used for the floating-point presentation type. +For string types, +this option specifies the longest prefix of the formatted argument +to be included in the replacement field such that +the field width of the prefix is no greater than the value of this option. + +\pnum +If \fmtgrammarterm{nonnegative-integer} is used in +a \fmtgrammarterm{precision} option, +the value of the decimal integer is used as the value of the option. + +\pnum +When the \tcode{L} option is used, the form used for the conversion is called +the \defnx{locale-specific form}{locale-specific form!format string}. +The \tcode{L} option is only valid for arithmetic types, and +its effect depends upon the type. +\begin{itemize} +\item +For integral types, the locale-specific form +causes the context's locale to be used +to insert the appropriate digit group separator characters. + +\item +For floating-point types, the locale-specific form +causes the context's locale to be used +to insert the appropriate digit group and radix separator characters. + +\item +For the textual representation of \tcode{bool}, the locale-specific form +causes the context's locale to be used +to insert the appropriate string as if obtained +with \tcode{numpunct::truename} or \tcode{numpunct::falsename}. +\end{itemize} + +\pnum +The \fmtgrammarterm{type} determines how the data should be presented. + +\pnum +% FIXME: What is a "string" here, exactly? +The available string presentation types are specified in \tref{format.type.string}. +% +\begin{floattable}{Meaning of \fmtgrammarterm{type} options for strings}{format.type.string}{ll} +\topline +\lhdr{Type} & \rhdr{Meaning} \\ \rowsep +none, \tcode{s} & +Copies the string to the output. +\\ \rowsep +% +\tcode{?} & +Copies the escaped string\iref{format.string.escaped} to the output. +\\ +\end{floattable} + +\pnum +The meaning of some non-string presentation types +is defined in terms of a call to \tcode{to_chars}. +In such cases, +let \range{first}{last} be a range +large enough to hold the \tcode{to_chars} output +and \tcode{value} be the formatting argument value. +Formatting is done as if by calling \tcode{to_chars} as specified +and copying the output through the output iterator of the format context. +\begin{note} +Additional padding and adjustments are performed +prior to copying the output through the output iterator +as specified by the format specifiers. +\end{note} + +\pnum +The available integer presentation types +for integral types other than \tcode{bool} and \tcode{charT} +are specified in \tref{format.type.int}. +\begin{example} +\begin{codeblock} +string s0 = format("{}", 42); // value of \tcode{s0} is \tcode{"42"} +string s1 = format("{0:b} {0:d} {0:o} {0:x}", 42); // value of \tcode{s1} is \tcode{"101010 42 52 2a"} +string s2 = format("{0:#x} {0:#X}", 42); // value of \tcode{s2} is \tcode{"0x2a 0X2A"} +string s3 = format("{:L}", 1234); // value of \tcode{s3} can be \tcode{"1,234"} + // (depending on the locale) +\end{codeblock} +\end{example} + +\begin{floattable}{Meaning of \fmtgrammarterm{type} options for integer types}{format.type.int}{lp{.8\hsize}} +\topline +\lhdr{Type} & \rhdr{Meaning} \\ \rowsep +\tcode{b} & +\tcode{to_chars(first, last, value, 2)}; +\indextext{base prefix}% +the base prefix is \tcode{0b}. +\\ \rowsep +% +\tcode{B} & +The same as \tcode{b}, except that +\indextext{base prefix}% +the base prefix is \tcode{0B}. +\\ \rowsep +% +\tcode{c} & +Copies the character \tcode{static_cast(value)} to the output. +Throws \tcode{format_error} if \tcode{value} is not +in the range of representable values for \tcode{charT}. +\\ \rowsep +% +\tcode{d} & +\tcode{to_chars(first, last, value)}. +\\ \rowsep +% +\tcode{o} & +\tcode{to_chars(first, last, value, 8)}; +\indextext{base prefix}% +the base prefix is \tcode{0} if \tcode{value} is nonzero and is empty otherwise. +\\ \rowsep +% +\tcode{x} & +\tcode{to_chars(first, last, value, 16)}; +\indextext{base prefix}% +the base prefix is \tcode{0x}. +\\ \rowsep +% +\tcode{X} & +The same as \tcode{x}, except that +it uses uppercase letters for digits above 9 and +\indextext{base prefix}% +the base prefix is \tcode{0X}. +\\ \rowsep +% +none & +The same as \tcode{d}. +\begin{tailnote} +If the formatting argument type is \tcode{charT} or \tcode{bool}, +the default is instead \tcode{c} or \tcode{s}, respectively. +\end{tailnote} +\\ +\end{floattable} + +\pnum +The available \tcode{charT} presentation types are specified in \tref{format.type.char}. +% +\begin{floattable}{Meaning of \fmtgrammarterm{type} options for \tcode{charT}}{format.type.char}{lp{.8\hsize}} +\topline +\lhdr{Type} & \rhdr{Meaning} \\ \rowsep +none, \tcode{c} & +Copies the character to the output. +\\ \rowsep +% +\tcode{b}, \tcode{B}, \tcode{d}, \tcode{o}, \tcode{x}, \tcode{X} & +As specified in \tref{format.type.int} +with \tcode{value} converted to the unsigned version of the underlying type. +\\ \rowsep +% +\tcode{?} & +Copies the escaped character\iref{format.string.escaped} to the output. +\\ +\end{floattable} + +\pnum +The available \tcode{bool} presentation types are specified in \tref{format.type.bool}. +% +\begin{floattable}{Meaning of \fmtgrammarterm{type} options for \tcode{bool}}{format.type.bool}{ll} +\topline +\lhdr{Type} & \rhdr{Meaning} \\ \rowsep +none, +\tcode{s} & +Copies textual representation, either \tcode{true} or \tcode{false}, to the output. +\\ \rowsep +% +\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)}. +\\ +\end{floattable} + +\pnum +The available floating-point presentation types and their meanings +for values other than infinity and NaN are +specified in \tref{format.type.float}. +For lower-case presentation types, infinity and NaN are formatted as +\tcode{inf} and \tcode{nan}, respectively. +For upper-case presentation types, infinity and NaN are formatted as +\tcode{INF} and \tcode{NAN}, respectively. +\begin{note} +In either case, a sign is included +if indicated by the \fmtgrammarterm{sign} option. +\end{note} + +\begin{floattable}{Meaning of \fmtgrammarterm{type} options for floating-point types}{format.type.float}{lp{.8\hsize}} +\topline +\lhdr{Type} & \rhdr{Meaning} \\ \rowsep +\tcode{a} & +If \fmtgrammarterm{precision} is specified, equivalent to +\begin{codeblock} +to_chars(first, last, value, chars_format::hex, precision) +\end{codeblock} +where \tcode{precision} is the specified formatting precision; equivalent to +\begin{codeblock} +to_chars(first, last, value, chars_format::hex) +\end{codeblock} +otherwise. +\\ +\rowsep +% +\tcode{A} & +The same as \tcode{a}, except that +it uses uppercase letters for digits above 9 and +\tcode{P} to indicate the exponent. +\\ \rowsep +% +\tcode{e} & +Equivalent to +\begin{codeblock} +to_chars(first, last, value, chars_format::scientific, precision) +\end{codeblock} +where \tcode{precision} is the specified formatting precision, +or \tcode{6} if \fmtgrammarterm{precision} is not specified. +\\ \rowsep +% +\tcode{E} & +The same as \tcode{e}, except that it uses \tcode{E} to indicate exponent. +\\ \rowsep +% +\tcode{f}, \tcode{F} & +Equivalent to +\begin{codeblock} +to_chars(first, last, value, chars_format::fixed, precision) +\end{codeblock} +where \tcode{precision} is the specified formatting precision, +or \tcode{6} if \fmtgrammarterm{precision} is not specified. +\\ \rowsep +% +\tcode{g} & +Equivalent to +\begin{codeblock} +to_chars(first, last, value, chars_format::general, precision) +\end{codeblock} +where \tcode{precision} is the specified formatting precision, +or \tcode{6} if \fmtgrammarterm{precision} is not specified. +\\ \rowsep +% +\tcode{G} & +The same as \tcode{g}, except that +it uses \tcode{E} to indicate exponent. +\\ \rowsep +% +none & +If \fmtgrammarterm{precision} is specified, equivalent to +\begin{codeblock} +to_chars(first, last, value, chars_format::general, precision) +\end{codeblock} +where \tcode{precision} is the specified formatting precision; equivalent to +\begin{codeblock} +to_chars(first, last, value) +\end{codeblock} +otherwise. +\\ +\end{floattable} + +\pnum +The available pointer presentation types and their mapping to +\tcode{to_chars} are specified in \tref{format.type.ptr}. +\begin{note} +Pointer presentation types also apply to \tcode{nullptr_t}. +\end{note} + +\begin{floattable}{Meaning of \fmtgrammarterm{type} options for pointer types}{format.type.ptr}{lp{.8\hsize}} +\topline +\lhdr{Type} & \rhdr{Meaning} \\ \rowsep +none, \tcode{p} & +If \tcode{uintptr_t} is defined, +\begin{codeblock} +to_chars(first, last, reinterpret_cast(value), 16) +\end{codeblock} +with the prefix \tcode{0x} inserted immediately before the output of \tcode{to_chars}; +otherwise, implementation-defined. +\\ \rowsep +\tcode{P} & +The same as \tcode{p}, +except that it uses uppercase letters for digits above \tcode{9} and +the base prefix is \tcode{0X}. +\\ +\end{floattable} + +\rSec2[format.err.report]{Error reporting} + +\pnum +Formatting functions throw \tcode{format_error} if +an argument \tcode{fmt} is passed that +is not a format string for \tcode{args}. +They propagate exceptions thrown by operations of +\tcode{formatter} specializations and iterators. +Failure to allocate storage is reported by +throwing an exception as described in~\ref{res.on.exception.handling}. + +\rSec2[format.fmt.string]{Class template \tcode{basic_format_string}} + +\begin{codeblock} +namespace std { + template + struct @\libglobal{basic_format_string}@ { + private: + basic_string_view @\exposidnc{str}@; // \expos + + public: + template consteval basic_format_string(const T& s); + basic_format_string(@\exposid{runtime-format-string}@ s) noexcept : str(s.@\exposid{str}@) {} + + constexpr basic_string_view get() const noexcept { return @\exposid{str}@; } + }; +} +\end{codeblock} + +\begin{itemdecl} +template consteval basic_format_string(const T& s); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{const T\&} models \tcode{\libconcept{convertible_to}>}. + +\pnum +\effects +Direct-non-list-initializes \exposid{str} with \tcode{s}. + +\pnum +\remarks +A call to this function is not a core constant expression\iref{expr.const} +unless there exist \tcode{args} of types \tcode{Args} +such that \exposid{str} is a format string for \tcode{args}. +\end{itemdescr} + +\rSec2[format.functions]{Formatting functions} + +\pnum +In the description of the functions, operator \tcode{+} is used +for some of the iterator categories for which it does not have to be defined. +In these cases the semantics of \tcode{a + n} are +the same as in \ref{algorithms.requirements}. + +\indexlibraryglobal{format}% +\begin{itemdecl} +template + string format(format_string fmt, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return vformat(fmt.@\exposid{str}@, make_format_args(args...)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{format}% +\begin{itemdecl} +template + wstring format(wformat_string fmt, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return vformat(fmt.@\exposid{str}@, make_wformat_args(args...)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{format}% +\begin{itemdecl} +template + string format(const locale& loc, format_string fmt, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return vformat(loc, fmt.@\exposid{str}@, make_format_args(args...)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{format}% +\begin{itemdecl} +template + wstring format(const locale& loc, wformat_string fmt, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return vformat(loc, fmt.@\exposid{str}@, make_wformat_args(args...)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{vformat}% +\begin{itemdecl} +string vformat(string_view fmt, format_args args); +wstring vformat(wstring_view fmt, wformat_args args); +string vformat(const locale& loc, string_view fmt, format_args args); +wstring vformat(const locale& loc, wstring_view fmt, wformat_args args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A string object holding the character representation of +formatting arguments provided by \tcode{args} formatted according to +specifications given in \tcode{fmt}. +If present, \tcode{loc} is used for locale-specific formatting. + +\pnum +\throws +As specified in~\ref{format.err.report}. +\end{itemdescr} + +\indexlibraryglobal{format_to}% +\begin{itemdecl} +template + Out format_to(Out out, format_string fmt, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return vformat_to(std::move(out), fmt.@\exposid{str}@, make_format_args(args...)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{format_to}% +\begin{itemdecl} +template + Out format_to(Out out, wformat_string fmt, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return vformat_to(std::move(out), fmt.@\exposid{str}@, make_wformat_args(args...)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{format_to}% +\begin{itemdecl} +template + Out format_to(Out out, const locale& loc, format_string fmt, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return vformat_to(std::move(out), loc, fmt.@\exposid{str}@, make_format_args(args...)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{format_to}% +\begin{itemdecl} +template + Out format_to(Out out, const locale& loc, wformat_string fmt, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return vformat_to(std::move(out), loc, fmt.@\exposid{str}@, make_wformat_args(args...)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{vformat_to}% +\begin{itemdecl} +template + Out vformat_to(Out out, string_view fmt, format_args args); +template + Out vformat_to(Out out, wstring_view fmt, wformat_args args); +template + Out vformat_to(Out out, const locale& loc, string_view fmt, format_args args); +template + Out vformat_to(Out out, const locale& loc, wstring_view fmt, wformat_args args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{charT} be \tcode{decltype(fmt)::value_type}. + +\pnum +\constraints +\tcode{Out} satisfies \tcode{\libconcept{output_iterator}}. + +\pnum +\expects +\tcode{Out} models \tcode{\libconcept{output_iterator}}. + +\pnum +\effects +Places the character representation of formatting +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 the number of characters in that character representation. +If present, \tcode{loc} is used for locale-specific formatting. + +\pnum +\returns +\tcode{out + N}. + +\pnum +\throws +As specified in~\ref{format.err.report}. +\end{itemdescr} + +\indexlibraryglobal{format_to_n}% +\begin{itemdecl} +template + format_to_n_result format_to_n(Out out, iter_difference_t n, + format_string fmt, Args&&... args); +template + format_to_n_result format_to_n(Out out, iter_difference_t n, + wformat_string fmt, Args&&... args); +template + format_to_n_result format_to_n(Out out, iter_difference_t n, + const locale& loc, format_string fmt, + Args&&... args); +template + format_to_n_result format_to_n(Out out, iter_difference_t n, + const locale& loc, wformat_string fmt, + Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let +\begin{itemize} +\item \tcode{charT} be \tcode{decltype(fmt.\exposid{str})::value_type}, +\item \tcode{N} be +\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, and +\item \tcode{M} be \tcode{clamp(n, 0, N)}. +\end{itemize} + +\pnum +\constraints +\tcode{Out} satisfies \tcode{\libconcept{output_iterator}}. + +\pnum +\expects +\tcode{Out} models \tcode{\libconcept{output_iterator}}, and +\tcode{formatter<}$\tcode{remove_cvref_t, charT>} +meets the \newoldconcept{BasicFormatter} requirements\iref{formatter.requirements} +for each $\tcode{T}_i$ in \tcode{Args}. + +\pnum +\effects +Places the first \tcode{M} characters of the character representation of +formatting the arguments provided by \tcode{args}, +formatted according to the specifications given in \tcode{fmt}, +into the range \range{out}{out + M}. +If present, \tcode{loc} is used for locale-specific formatting. + +\pnum +\returns +\tcode{\{out + M, N\}}. + +\pnum +\throws +As specified in~\ref{format.err.report}. +\end{itemdescr} + +\indexlibraryglobal{formatted_size}% +\begin{itemdecl} +template + size_t formatted_size(format_string fmt, Args&&... args); +template + size_t formatted_size(wformat_string fmt, Args&&... args); +template + size_t formatted_size(const locale& loc, format_string fmt, Args&&... args); +template + size_t formatted_size(const locale& loc, wformat_string fmt, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{charT} be \tcode{decltype(fmt.\exposid{str})::value_type}. + +\pnum +\expects +\tcode{formatter<}$\tcode{remove_cvref_t, charT>} +meets the \newoldconcept{BasicFormatter} requirements\iref{formatter.requirements} +for each $\tcode{T}_i$ in \tcode{Args}. + +\pnum +\returns +The number of characters in the character representation of +formatting arguments \tcode{args} +formatted according to specifications given in \tcode{fmt}. +If present, \tcode{loc} is used for locale-specific formatting. + +\pnum +\throws +As specified in~\ref{format.err.report}. +\end{itemdescr} + +\rSec2[format.formatter]{Formatter} + +\rSec3[formatter.requirements]{Formatter requirements} + +\pnum +A type \tcode{F} meets the \defnnewoldconcept{BasicFormatter} requirements if +it meets the +\begin{itemize} +\item \oldconcept{DefaultConstructible} (\tref{cpp17.defaultconstructible}), +\item \oldconcept{CopyConstructible} (\tref{cpp17.copyconstructible}), +\item \oldconcept{CopyAssignable} (\tref{cpp17.copyassignable}), +\item \oldconcept{Swappable}\iref{swappable.requirements}, and +\item \oldconcept{Destructible} (\tref{cpp17.destructible}) +\end{itemize} +requirements, and +the expressions shown in \tref{formatter.basic} are valid and +have the indicated semantics. + +\pnum +A type \tcode{F} meets the \defnnewoldconcept{Formatter} requirements +if it meets the \newoldconcept{BasicFormatter} requirements and +the expressions shown in \tref{formatter} are valid and +have the indicated semantics. + +\pnum +Given character type \tcode{charT}, output iterator type +\tcode{Out}, and formatting argument type \tcode{T}, +in \tref{formatter.basic} and \tref{formatter}: +\begin{itemize} +\item \tcode{f} is a value of type (possibly const) \tcode{F}, +\item \tcode{g} is an lvalue of type \tcode{F}, +\item \tcode{u} is an lvalue of type \tcode{T}, +\item \tcode{t} is a value of a type convertible to (possibly const) \tcode{T}, +\item \tcode{PC} is \tcode{basic_format_parse_context}, +\item \tcode{FC} is \tcode{basic_format_context}, +\item \tcode{pc} is an lvalue of type \tcode{PC}, and +\item \tcode{fc} is an lvalue of type \tcode{FC}. +\end{itemize} +\tcode{pc.begin()} points to the beginning of the +\fmtgrammarterm{format-spec}\iref{format.string} +of the replacement field being formatted +in the format string. +If \fmtgrammarterm{format-spec} is not present or empty then either +\tcode{pc.begin() == pc.end()} or +\tcode{*pc.begin() == '\}'}. + +\begin{concepttable}{\newoldconcept{BasicFormatter} requirements}{formatter.basic} +{p{1.2in}p{1in}p{2.9in}} +\topline +\hdstyle{Expression} & \hdstyle{Return type} & \hdstyle{Requirement} \\ \capsep +\tcode{g.parse(pc)} & +\tcode{PC::iterator} & +Parses \fmtgrammarterm{format-spec}\iref{format.string} +for type \tcode{T} +in the range \range{pc.begin()}{pc.end()} +until the first unmatched character. +Throws \tcode{format_error} unless the whole range is parsed +or the unmatched character is \tcode{\}}. +\begin{note} +This allows formatters to emit meaningful error messages. +\end{note} +Stores the parsed format specifiers in \tcode{*this} and +returns an iterator past the end of the parsed range. +\\ \rowsep +\tcode{f.format(u, fc)} & +\tcode{FC::iterator} & +Formats \tcode{u} according to the specifiers stored in \tcode{*this}, +writes the output to \tcode{fc.out()}, and +returns an iterator past the end of the output range. +The output shall only depend on +\tcode{u}, +\tcode{fc.locale()}, +\tcode{fc.arg(n)} for any value \tcode{n} of type \tcode{size_t}, +and the range \range{pc.begin()}{pc.end()} +from the last call to \tcode{f.parse(pc)}. +\\ +\end{concepttable} + +\begin{concepttable}{\newoldconcept{Formatter} requirements}{formatter} +{p{1.2in}p{1in}p{2.9in}} +\topline +\hdstyle{Expression} & \hdstyle{Return type} & \hdstyle{Requirement} \\ \capsep +\tcode{f.format(t, fc)} & +\tcode{FC::iterator} & +Formats \tcode{t} according to the specifiers stored in \tcode{*this}, +writes the output to \tcode{fc.out()}, and +returns an iterator past the end of the output range. +The output shall only depend on +\tcode{t}, +\tcode{fc.locale()}, +\tcode{fc.arg(n)} for any value \tcode{n} of type \tcode{size_t}, +and the range \range{pc.begin()}{pc.end()} +from the last call to \tcode{f.parse(pc)}. +\\ \rowsep +\tcode{f.format(u, fc)} & +\tcode{FC::iterator} & +As above, but does not modify \tcode{u}. +\\ +\end{concepttable} + +\rSec3[format.formatter.locking]{Formatter locking} + +\indexlibraryglobal{enable_nonlocking_formatter_optimization}% +\begin{itemdecl} +template + constexpr bool enable_nonlocking_formatter_optimization = false; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\remarks +Pursuant to \ref{namespace.std}, +users may specialize \tcode{enable_nonlocking_formatter_optimization} for +cv-unqualified program-defined types. +Such specializations shall be usable in constant expressions\iref{expr.const} +and have type \tcode{const bool}. +\end{itemdescr} + +\rSec3[format.formattable]{Concept \cname{formattable}} + +\pnum +Let \tcode{\placeholder{fmt-iter-for}} be an unspecified type +that models +\tcode{\libconcept{output_iterator}}\iref{iterator.concept.output}. + +\begin{codeblock} +template>> + concept @\defexposconcept{formattable-with}@ = // \expos + @\libconcept{semiregular}@ && + requires(Formatter& f, const Formatter& cf, T&& t, Context fc, + basic_format_parse_context pc) + { + { f.parse(pc) } -> @\libconcept{same_as}@; + { cf.format(t, fc) } -> @\libconcept{same_as}@; + }; + +template + concept @\deflibconcept{formattable}@ = + @\exposconcept{formattable-with}@, basic_format_context<@\placeholder{fmt-iter-for}@, charT>>; +\end{codeblock} + +\pnum +A type \tcode{T} and a character type \tcode{charT} +model \libconcept{formattable} +if \tcode{formatter, charT>} meets +the \newoldconcept{BasicFormatter} requirements\iref{formatter.requirements} +and, if \tcode{remove_reference_t} is const-qualified, +the \newoldconcept{Formatter} requirements. + +\rSec3[format.formatter.spec]{Formatter specializations} +\indexlibraryglobal{formatter}% + +\pnum +% FIXME: Specify this in [format.functions], not here! +The functions defined in \ref{format.functions} use +specializations of the class template \tcode{formatter} to format +individual arguments. + +\pnum +Let \tcode{charT} be either \tcode{char} or \keyword{wchar_t}. +Each specialization of \tcode{formatter} is either enabled or disabled, +as described below. +\indextext{\idxcode{formatter}!debug-enabled specialization of}% +A \defn{debug-enabled} specialization of \tcode{formatter} +additionally provides +a public, constexpr, non-static member function \tcode{set_debug_format()} +which modifies the state of the \tcode{formatter} to be as if +the type of the \fmtgrammarterm{std-format-spec} +parsed by the last call to \tcode{parse} were \tcode{?}. +Each header that declares the template \tcode{formatter} +provides the following enabled specializations: +\begin{itemize} +\item +\indexlibrary{\idxcode{formatter}!specializations!character types}% +The debug-enabled specializations +\begin{codeblock} +template<> struct formatter; +template<> struct formatter; +template<> struct formatter; +\end{codeblock} + +\item +\indexlibrary{\idxcode{formatter}!specializations!string types}% +For each \tcode{charT}, +the debug-enabled string type specializations +\begin{codeblock} +template<> struct formatter; +template<> struct formatter; +template struct formatter; +template + struct formatter, charT>; +template + struct formatter, charT>; +\end{codeblock} + +\item +\indexlibrary{\idxcode{formatter}!specializations!arithmetic types}% +For each \tcode{charT}, +for each cv-unqualified arithmetic type \tcode{ArithmeticT} +other than +\tcode{char}, +\keyword{wchar_t}, +\keyword{char8_t}, +\keyword{char16_t}, or +\keyword{char32_t}, +a specialization +\begin{codeblock} +template<> struct formatter; +\end{codeblock} + +\item +\indexlibrary{\idxcode{formatter}!specializations!pointer types}% +\indexlibrary{\idxcode{formatter}!specializations!\idxcode{nullptr_t}}% +For each \tcode{charT}, +the pointer type specializations +\begin{codeblock} +template<> struct formatter; +template<> struct formatter; +template<> struct formatter; +\end{codeblock} +\end{itemize} +The \tcode{parse} member functions of these formatters +interpret the format specification +as a \fmtgrammarterm{std-format-spec} +as described in~\ref{format.string.std}. + +\pnum +Unless specified otherwise, for each type \tcode{T} for which +a \tcode{formatter} specialization is provided by the library, +each of the headers provides the following specialization: +\begin{codeblock} +template<> inline constexpr bool enable_nonlocking_formatter_optimization = true; +\end{codeblock} +\begin{note} +Specializations such as \tcode{formatter} +that would require implicit +multibyte / wide string or character conversion are disabled. +\end{note} + +\pnum +The header \libheaderdef{format} provides +the following disabled specializations: +\begin{itemize} +\item +The string type specializations +\begin{codeblock} +template<> struct formatter; +template<> struct formatter; +template struct formatter; +template + struct formatter, wchar_t>; +template + struct formatter, wchar_t>; +\end{codeblock} +\end{itemize} + +\pnum +For any types \tcode{T} and \tcode{charT} for which +neither the library nor the user provides +an explicit or partial specialization of +the class template \tcode{formatter}, +\tcode{formatter} is disabled. + +\pnum +If the library provides an explicit or partial specialization of +\tcode{formatter}, that specialization is enabled +and meets the \newoldconcept{Formatter} requirements +except as noted otherwise. + +\pnum +If \tcode{F} is a disabled specialization of \tcode{formatter}, these +values are \tcode{false}: +\begin{itemize} +\item \tcode{is_default_constructible_v}, +\item \tcode{is_copy_constructible_v}, +\item \tcode{is_move_constructible_v}, +\item \tcode{is_copy_assignable_v}, and +\item \tcode{is_move_assignable_v}. +\end{itemize} + +\pnum +An enabled specialization \tcode{formatter} meets the +\newoldconcept{BasicFormatter} requirements\iref{formatter.requirements}. +\begin{example} +\begin{codeblock} +#include +#include + +enum color { red, green, blue }; +const char* color_names[] = { "red", "green", "blue" }; + +template<> struct std::formatter : std::formatter { + auto format(color c, format_context& ctx) const { + return formatter::format(color_names[c], ctx); + } +}; + +struct err {}; + +std::string s0 = std::format("{}", 42); // OK, library-provided formatter +std::string s1 = std::format("{}", L"foo"); // error: disabled formatter +std::string s2 = std::format("{}", red); // OK, user-provided formatter +std::string s3 = std::format("{}", err{}); // error: disabled formatter +\end{codeblock} +\end{example} + +\rSec3[format.string.escaped]{Formatting escaped characters and strings} + +\pnum +\indextext{string!formatted as escaped}% +\indextext{character!formatted as escaped}% +A character or string can be formatted as \defn{escaped} +to make it more suitable for debugging or for logging. + +\pnum +The escaped string \placeholder{E} representation of a string \placeholder{S} +is constructed by encoding a sequence of characters as follows. +The associated character encoding \placeholder{CE} +for \tcode{charT}~(\tref{lex.string.literal}) +is used to both interpret \placeholder{S} and construct \placeholder{E}. + +\begin{itemize} +\item +\unicode{0022}{quotation mark} (\tcode{"}) is appended to \placeholder{E}. + +\item +For each code unit sequence \placeholder{X} in \placeholder{S} that either +encodes a single character, +is a shift sequence, or +is a sequence of ill-formed code units, +processing is in order as follows: + +\begin{itemize} +\item +If \placeholder{X} encodes a single character \placeholder{C}, then: + +\begin{itemize} +\item +If \placeholder{C} is one of the characters in \tref{format.escape.sequences}, +then the two characters shown as the corresponding escape sequence +are appended to \placeholder{E}. + +\item +Otherwise, if \placeholder{C} is not \unicode{0020}{space} and + +\begin{itemize} +\item +\placeholder{CE} is UTF-8, UTF-16, or UTF-32 and +\placeholder{C} corresponds to a Unicode scalar value +whose Unicode property \tcode{General_Category} has a value in the groups +\tcode{Separator} (\tcode{Z}) or \tcode{Other} (\tcode{C}), +as described by \UAX{44} of the Unicode Standard, or + +\item +\placeholder{CE} is UTF-8, UTF-16, or UTF-32 and +\placeholder{C} corresponds to a Unicode scalar value +with the Unicode property \tcode{Grapheme_Extend=Yes} +as described by \UAX{44} of the Unicode Standard and +\placeholder{C} is not immediately preceded in \placeholder{S} by +a character \placeholder{P} appended to \placeholder{E} +without translation to an escape sequence, or + +\item +\placeholder{CE} is neither UTF-8, UTF-16, nor UTF-32 and +\placeholder{C} is one of an implementation-defined set +of separator or non-printable characters +\end{itemize} + +then the sequence \tcode{\textbackslash u\{\placeholder{hex-digit-sequence}\}} +is appended to \placeholder{E}, +where \tcode{\placeholder{hex-digit-sequence}} +is the shortest hexadecimal representation +of \placeholder{C} using lower-case hexadecimal digits. + +\item +Otherwise, \placeholder{C} is appended to \placeholder{E}. +\end{itemize} + +\item +Otherwise, if \placeholder{X} is a shift sequence, +the effect on \placeholder{E} and further decoding of \placeholder{S} +is unspecified. + +\recommended +A shift sequence should be represented in \placeholder{E} +such that the original code unit sequence of \placeholder{S} +can be reconstructed. + +\item +Otherwise (\placeholder{X} is a sequence of ill-formed code units), +each code unit \placeholder{U} is appended to \placeholder{E} in order +as the sequence \tcode{\textbackslash x\{\placeholder{hex-digit-sequence}\}}, +where \tcode{\placeholder{hex-digit-sequence}} +is the shortest hexadecimal representation of \placeholder{U} +using lower-case hexadecimal digits. +\end{itemize} + +\item +Finally, \unicode{0022}{quotation mark} (\tcode{"}) +is appended to \placeholder{E}. +\end{itemize} +% +\begin{floattable}{Mapping of characters to escape sequences}{format.escape.sequences}{ll} +\topline +\lhdr{Character} & \rhdr{Escape sequence} \\ \rowsep +\unicode{0009}{character tabulation} & +\tcode{\textbackslash t} +\\ \rowsep +% +\unicode{000a}{line feed} & +\tcode{\textbackslash n} +\\ \rowsep +% +\unicode{000d}{carriage return} & +\tcode{\textbackslash r} +\\ \rowsep +% +\unicode{0022}{quotation mark} & +\tcode{\textbackslash "} +\\ \rowsep +% +\unicode{005c}{reverse solidus} & +\tcode{\textbackslash\textbackslash} +\\ +\end{floattable} + +\pnum +The escaped string representation of a character \placeholder{C} +is equivalent to the escaped string representation +of a string of \placeholder{C}, except that: + +\begin{itemize} +\item +the result starts and ends with \unicode{0027}{apostrophe} (\tcode{'}) +instead of \unicode{0022}{quotation mark} (\tcode{"}), and +\item +if \placeholder{C} is \unicode{0027}{apostrophe}, +the two characters \tcode{\textbackslash '} are appended to \placeholder{E}, and +\item +if \placeholder{C} is \unicode{0022}{quotation mark}, +then \placeholder{C} is appended unchanged. +\end{itemize} + +\begin{example} +\begin{codeblock} +string s0 = format("[{}]", "h\tllo"); // \tcode{s0} has value: \tcode{[h\ \ \ \ llo]} +string s1 = format("[{:?}]", "h\tllo"); // \tcode{s1} has value: \tcode{["h\textbackslash tllo"]} +string s2 = format("[{:?}]", "@\importexample[-2.5pt]{example_01}@"); @\kern1.25pt@// \tcode{s2} has value: \tcode{["\importexample[-2.5pt]{example_01}"]} +string s3 = format("[{:?}, {:?}]", '\'', '"'); // \tcode{s3} has value: \tcode{['\textbackslash '', '"']} + +// The following examples assume use of the UTF-8 encoding +string s4 = format("[{:?}]", string("\0 \n \t \x02 \x1b", 9)); + // \tcode{s4} has value: \tcode{["\textbackslash u\{0\} \textbackslash n \textbackslash t \textbackslash u\{2\} \textbackslash u\{1b\}"]} +string s5 = format("[{:?}]", "\xc3\x28"); // invalid UTF-8, \tcode{s5} has value: \tcode{["\textbackslash x\{c3\}("]} +string s6 = format("[{:?}]", "@\importexample{example_02}@"); @\kern0.75pt@// \tcode{s6} has value: \tcode{["\importexample{example_03}\textbackslash{u}\{200d\}\importexample{example_04}"]} +string s7 = format("[{:?}]", "\u0301"); // \tcode{s7} has value: \tcode{["\textbackslash u\{301\}"]} +string s8 = format("[{:?}]", "\\\u0301"); // \tcode{s8} has value: \tcode{["\textbackslash \textbackslash \textbackslash u\{301\}"]} +string s9 = format("[{:?}]", "e\u0301\u0323"); // \tcode{s9} has value: \tcode{["\importexample[-2pt]{example_06}"]} +\end{codeblock} +\end{example} + +\rSec3[format.parse.ctx]{Class template \tcode{basic_format_parse_context}} + +\indexlibraryglobal{basic_format_parse_context}% +\indexlibrarymember{char_type}{basic_format_parse_context}% +\indexlibrarymember{const_iterator}{basic_format_parse_context}% +\indexlibrarymember{iterator}{basic_format_parse_context}% +\begin{codeblock} +namespace std { + template + class basic_format_parse_context { + public: + using char_type = charT; + using const_iterator = typename basic_string_view::const_iterator; + using iterator = const_iterator; + + private: + iterator begin_; // \expos + iterator end_; // \expos + enum indexing { unknown, manual, automatic }; // \expos + indexing indexing_; // \expos + size_t next_arg_id_; // \expos + size_t num_args_; // \expos + + public: + constexpr explicit basic_format_parse_context(basic_string_view fmt) noexcept; + basic_format_parse_context(const basic_format_parse_context&) = delete; + basic_format_parse_context& operator=(const basic_format_parse_context&) = delete; + + constexpr const_iterator begin() const noexcept; + constexpr const_iterator end() const noexcept; + constexpr void advance_to(const_iterator it); + + constexpr size_t next_arg_id(); + constexpr void check_arg_id(size_t id); + + template + constexpr void check_dynamic_spec(size_t id) noexcept; + constexpr void check_dynamic_spec_integral(size_t id) noexcept; + constexpr void check_dynamic_spec_string(size_t id) noexcept; + }; +} +\end{codeblock} + +\pnum +An instance of \tcode{basic_format_parse_context} holds +the format string parsing state, consisting of +the format string range being parsed and +the argument counter for automatic indexing. + +\pnum +If a program declares an explicit or partial specialization of +\tcode{basic_format_parse_context}, +the program is ill-formed, no diagnostic required. + +\indexlibraryctor{basic_format_parse_context}% +\begin{itemdecl} +constexpr explicit basic_format_parse_context(basic_string_view fmt) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes +\tcode{begin_} with \tcode{fmt.begin()}, +\tcode{end_} with \tcode{fmt.end()}, +\tcode{indexing_} with \tcode{unknown}, +\tcode{next_arg_id_} with \tcode{0}, and +\tcode{num_args_} with \tcode{0}. +\begin{note} +Any call to +\tcode{next_arg_id}, \tcode{check_arg_id}, or \tcode{check_dynamic_spec} +on an instance of \tcode{basic_format_parse_context} +initialized using this constructor is not a core constant expression. +\end{note} +\end{itemdescr} + +\indexlibrarymember{begin}{basic_format_parse_context}% +\begin{itemdecl} +constexpr const_iterator begin() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{begin_}. +\end{itemdescr} + +\indexlibrarymember{end}{basic_format_parse_context}% +\begin{itemdecl} +constexpr const_iterator end() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{end_}. +\end{itemdescr} + +\indexlibrarymember{advance_to}{basic_format_parse_context}% +\begin{itemdecl} +constexpr void advance_to(const_iterator it); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{end()} is reachable from \tcode{it}. + +\pnum +\effects +Equivalent to: \tcode{begin_ = it;} +\end{itemdescr} + +\indexlibrarymember{next_arg_id}{basic_format_parse_context}% +\begin{itemdecl} +constexpr size_t next_arg_id(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{indexing_ != manual} is \tcode{true}, equivalent to: +\begin{codeblock} +if (indexing_ == unknown) + indexing_ = automatic; +return next_arg_id_++; +\end{codeblock} + +\pnum +\throws +\tcode{format_error} if \tcode{indexing_ == manual} is \tcode{true}. +\begin{note} +This indicates mixing of automatic and manual argument indexing. +\end{note} + +\pnum +\remarks +Let \tcode{\placeholder{cur-arg-id}} be the value of \tcode{next_arg_id_} prior to this call. +Call expressions where \tcode{\placeholder{cur-arg-id} >= num_args_} is \tcode{true} +are not core constant expressions\iref{expr.const}. +\end{itemdescr} + +\indexlibrarymember{check_arg_id}{basic_format_parse_context}% +\begin{itemdecl} +constexpr void check_arg_id(size_t id); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If \tcode{indexing_ != automatic} is \tcode{true}, equivalent to: +\begin{codeblock} +if (indexing_ == unknown) + indexing_ = manual; +\end{codeblock} + +\pnum +\throws +\tcode{format_error} if +\tcode{indexing_ == automatic} is \tcode{true}. +\begin{note} +This indicates mixing of automatic and manual argument indexing. +\end{note} + +\pnum +\remarks +A call to this function is a core constant expression\iref{expr.const} only if +\tcode{id < num_args_} is \tcode{true}. +\end{itemdescr} + +\indexlibrarymember{check_dynamic_spec}{basic_format_parse_context}% +\begin{itemdecl} +template + constexpr void check_dynamic_spec(size_t id) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +$\tcode{sizeof...(Ts)} \ge 1$. +The types in \tcode{Ts...} are unique. +Each type in \tcode{Ts...} is one of +\keyword{bool}, +\tcode{char_type}, +\keyword{int}, +\tcode{\keyword{unsigned} \keyword{int}}, +\tcode{\keyword{long} \keyword{long} \keyword{int}}, +\tcode{\keyword{unsigned} \keyword{long} \keyword{long} \keyword{int}}, +\keyword{float}, +\keyword{double}, +\tcode{\keyword{long} \keyword{double}}, +\tcode{\keyword{const} char_type*}, +\tcode{basic_string_view}, or +\tcode{\keyword{const} \keyword{void}*}. + +\pnum +\remarks +A call to this function is a core constant expression only if +\begin{itemize} +\item +\tcode{id < num_args_} is \tcode{true} and +\item +the type of the corresponding format argument +(after conversion to \tcode{basic_format_arg}) is one of the types in \tcode{Ts...}. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{check_dynamic_spec_integral}{basic_format_parse_context}% +\begin{itemdecl} +constexpr void check_dynamic_spec_integral(size_t id) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +check_dynamic_spec(id); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{check_dynamic_spec_string}{basic_format_parse_context}% +\begin{itemdecl} +constexpr void check_dynamic_spec_string(size_t id) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +check_dynamic_spec>(id); +\end{codeblock} +\end{itemdescr} + +\rSec3[format.context]{Class template \tcode{basic_format_context}} + +\indexlibraryglobal{basic_format_context}% +\indexlibrarymember{iterator}{basic_format_context}% +\indexlibrarymember{char_type}{basic_format_context}% +\indexlibrarymember{formatter_type}{basic_format_context}% +\begin{codeblock} +namespace std { + template + class basic_format_context { + basic_format_args args_; // \expos + Out out_; // \expos + + basic_format_context(const basic_format_context&) = delete; + basic_format_context& operator=(const basic_format_context&) = delete; + + public: + using iterator = Out; + using char_type = charT; + template using formatter_type = formatter; + + basic_format_arg arg(size_t id) const noexcept; + std::locale locale(); + + iterator out(); + void advance_to(iterator it); + }; +} +\end{codeblock} + +\pnum +An instance of \tcode{basic_format_context} holds formatting state +consisting of the formatting arguments and the output iterator. + +\pnum +If a program declares an explicit or partial specialization of +\tcode{basic_format_context}, +the program is ill-formed, no diagnostic required. + +\pnum +\tcode{Out} shall model \tcode{\libconcept{output_iterator}}. + +\pnum +\indexlibraryglobal{format_context}% +\tcode{format_context} is an alias for +a specialization of \tcode{basic_format_context} +with an output iterator +that appends to \tcode{string}, +such as \tcode{back_insert_iterator}. +\indexlibraryglobal{wformat_context}% +Similarly, \tcode{wformat_context} is an alias for +a specialization of \tcode{basic_format_context} +with an output iterator +that appends to \tcode{wstring}. + +\pnum +\recommended +For a given type \tcode{charT}, +implementations should provide +a single instantiation of \tcode{basic_format_context} +for appending to +\tcode{basic_string}, +\tcode{vector}, +or any other container with contiguous storage +by wrapping those in temporary objects with a uniform interface +(such as a \tcode{span}) and polymorphic reallocation. + +\indexlibrarymember{arg}{basic_format_context}% +\begin{itemdecl} +basic_format_arg arg(size_t id) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{args_.get(id)}. +\end{itemdescr} + +\indexlibrarymember{locale}{basic_format_context}% +\begin{itemdecl} +std::locale locale(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The locale passed to the formatting function +if the latter takes one, +and \tcode{std::locale()} otherwise. +\end{itemdescr} + +\indexlibrarymember{out}{basic_format_context}% +\begin{itemdecl} +iterator out(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return std::move(out_);} +\end{itemdescr} + +\indexlibrarymember{advance_to}{basic_format_context}% +\begin{itemdecl} +void advance_to(iterator it); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{out_ = std::move(it);} +\end{itemdescr} + +\indextext{left-pad}% +\begin{example} +\begin{codeblock} +struct S { int value; }; + +template<> struct std::formatter { + size_t width_arg_id = 0; + + // Parses a width argument id in the format \tcode{\{} \fmtgrammarterm{digit} \tcode{\}}. + constexpr auto parse(format_parse_context& ctx) { + auto iter = ctx.begin(); + auto is_digit = [](auto c) { return c >= '0' && c <= '9'; }; + auto get_char = [&]() { return iter != ctx.end() ? *iter : 0; }; + if (get_char() != '{') + return iter; + ++iter; + char c = get_char(); + if (!is_digit(c) || (++iter, get_char()) != '}') + throw format_error("invalid format"); + width_arg_id = c - '0'; + ctx.check_arg_id(width_arg_id); + return ++iter; + } + + // Formats an \tcode{S} with width given by the argument \tcode{width_arg_id}. + auto format(S s, format_context& ctx) const { + int width = ctx.arg(width_arg_id).visit([](auto value) -> int { + if constexpr (!is_integral_v) + throw format_error("width is not integral"); + else if (value < 0 || value > numeric_limits::max()) + throw format_error("invalid width"); + else + return value; + }); + return format_to(ctx.out(), "{0:x>{1}}", s.value, width); + } +}; + +std::string s = std::format("{0:{1}}", S{42}, 10); // value of \tcode{s} is \tcode{"xxxxxxxx42"} +\end{codeblock} +\end{example} + +\rSec2[format.range]{Formatting of ranges} + +\rSec3[format.range.fmtkind]{Variable template \tcode{format_kind}} + +\indexlibraryglobal{format_kind} +\begin{itemdecl} +template + requires @\libconcept{same_as}@> + constexpr range_format format_kind = @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +A program that instantiates the primary template of \tcode{format_kind} +is ill-formed. + +\pnum +For a type \tcode{R}, \tcode{format_kind} is defined as follows: +\begin{itemize} +\item +If \tcode{\libconcept{same_as}>, R>} +is \tcode{true}, +\tcode{format_kind} is \tcode{range_format::disabled}. +\begin{note} +This prevents constraint recursion for ranges whose +reference type is the same range type. +For example, +\tcode{std::filesystem::path} is a range of \tcode{std::filesystem::path}. +\end{note} + +\item +Otherwise, if the \grammarterm{qualified-id} \tcode{R::key_type} +is valid and denotes a type: +\begin{itemize} +\item +If the \grammarterm{qualified-id} \tcode{R::mapped_type} +is valid and denotes a type, +let \tcode{U} be \tcode{remove_cvref_t>}. +If either \tcode{U} is a specialization of \tcode{pair} or +\tcode{U} is a specialization of \tcode{tuple} and +\tcode{tuple_size_v == 2}, +\tcode{format_kind} is \tcode{range_format::map}. +\item +Otherwise, \tcode{format_kind} is \tcode{range_format::set}. +\end{itemize} + +\item +Otherwise, \tcode{format_kind} is \tcode{range_format::sequence}. +\end{itemize} + +\pnum +\remarks +Pursuant to \ref{namespace.std}, users may specialize \tcode{format_kind} +for cv-unqualified program-defined types +that model \tcode{ranges::\libconcept{input_range}}. +Such specializations shall be usable in constant expressions\iref{expr.const} +and have type \tcode{const range_format}. +\end{itemdescr} + +\rSec3[format.range.formatter]{Class template \tcode{range_formatter}} + +\indexlibraryglobal{range_formatter}% +\begin{codeblock} +namespace std { + template + requires @\libconcept{same_as}@, T> && @\libconcept{formattable}@ + class range_formatter { + formatter @\exposid{underlying_}@; // \expos + basic_string_view @\exposid{separator_}@ = @\exposid{STATICALLY-WIDEN}@(", "); // \expos + basic_string_view @\exposid{opening-bracket_}@ = @\exposid{STATICALLY-WIDEN}@("["); // \expos + basic_string_view @\exposid{closing-bracket_}@ = @\exposid{STATICALLY-WIDEN}@("]"); // \expos + + public: + constexpr void set_separator(basic_string_view sep) noexcept; + constexpr void set_brackets(basic_string_view opening, + basic_string_view closing) noexcept; + constexpr formatter& underlying() noexcept { return @\exposid{underlying_}@; } + constexpr const formatter& underlying() const noexcept { return @\exposid{underlying_}@; } + + template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); + + template + requires @\libconcept{formattable}@, charT> && + @\libconcept{same_as}@>, T> + typename FormatContext::iterator + format(R&& r, FormatContext& ctx) const; + }; +} +\end{codeblock} + +\pnum +The class template \tcode{range_formatter} is a utility +for implementing \tcode{formatter} specializations for range types. + +\pnum +\tcode{range_formatter} interprets \fmtgrammarterm{format-spec} +as a \fmtgrammarterm{range-format-spec}. +The syntax of format specifications is as follows: + +\begin{ncbnf} +\fmtnontermdef{range-format-spec}\br + \opt{range-fill-and-align} \opt{width} \opt{\terminal{n}} \opt{range-type} \opt{range-underlying-spec} +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{range-fill-and-align}\br + \opt{range-fill} align +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{range-fill}\br + \textnormal{any character other than} \terminal{\{} \textnormal{or} \terminal{\}} \textnormal{or} \terminal{:} +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{range-type}\br + \terminal{m}\br + \terminal{s}\br + \terminal{?s} +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{range-underlying-spec}\br + \terminal{:} format-spec +\end{ncbnf} + +\pnum +For \tcode{range_formatter}, +the \fmtgrammarterm{format-spec} +in a \fmtgrammarterm{range-underlying-spec}, if any, +is interpreted by \tcode{formatter}. + +\pnum +The \fmtgrammarterm{range-fill-and-align} is interpreted +the same way as a \fmtgrammarterm{fill-and-align}\iref{format.string.std}. +The productions \fmtgrammarterm{align} and \fmtgrammarterm{width} +are described in \ref{format.string}. + +\pnum +The \tcode{n} option causes the range to be formatted +without the opening and closing brackets. +\begin{note} +This is equivalent to invoking \tcode{set_brackets(\{\}, \{\})}. +\end{note} + +\pnum +The \fmtgrammarterm{range-type} specifier changes the way a range is formatted, +with certain options only valid with certain argument types. +The meaning of the various type options +is as specified in \tref{formatter.range.type}. + +\begin{concepttable}{Meaning of \fmtgrammarterm{range-type} options}{formatter.range.type} +{p{1in}p{1.4in}p{2.7in}} +\topline +\hdstyle{Option} & \hdstyle{Requirements} & \hdstyle{Meaning} \\ \capsep +% +\tcode{m} & +\tcode{T} shall be +either a specialization of \tcode{pair} or a specialization of \tcode{tuple} +such that \tcode{tuple_size_v} is \tcode{2}. & +Indicates that +the opening bracket should be \tcode{"\{"}, +the closing bracket should be \tcode{"\}"}, +the separator should be \tcode{", "}, and +each range element should be formatted as if +\tcode{m} were specified for its \fmtgrammarterm{tuple-type}. +\begin{tailnote} +If the \tcode{n} option is provided in addition to the \tcode{m} option, +both the opening and closing brackets are still empty. +\end{tailnote} +\\ \rowsep +% +\tcode{s} & +\tcode{T} shall be \tcode{charT}. & +Indicates that the range should be formatted as a \tcode{string}. +\\ \rowsep +% +\tcode{?s} & +\tcode{T} shall be \tcode{charT}. & +Indicates that the range should be formatted as +an escaped string\iref{format.string.escaped}. +\\ +\end{concepttable} + +If the \fmtgrammarterm{range-type} is \tcode{s} or \tcode{?s}, +then there shall be +no \tcode{n} option and no \fmtgrammarterm{range-underlying-spec}. + +\indexlibrarymember{set_separator}{range_formatter}% +\begin{itemdecl} +constexpr void set_separator(basic_string_view sep) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{\exposid{separator_} = sep;} +\end{itemdescr} + +\indexlibrarymember{set_brackets}{range_formatter}% +\begin{itemdecl} +constexpr void set_brackets(basic_string_view opening, + basic_string_view closing) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{opening-bracket_}@ = opening; +@\exposid{closing-bracket_}@ = closing; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{parse}{range_formatter}% +\begin{itemdecl} +template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Parses the format specifiers as a \fmtgrammarterm{range-format-spec} and +stores the parsed specifiers in \tcode{*this}. +Calls \tcode{\exposid{underlying_}.parse(ctx)} to parse +\fmtgrammarterm{format-spec} in \fmtgrammarterm{range-format-spec} or, +if the latter is not present, an empty \fmtgrammarterm{format-spec}. +The values of +\exposid{opening-bracket_}, \exposid{closing-bracket_}, and \exposid{separator_} +are modified if and only if required by +the \fmtgrammarterm{range-type} or the \tcode{n} option, if present. +If: +\begin{itemize} +\item +the \fmtgrammarterm{range-type} is neither \tcode{s} nor \tcode{?s}, +\item +\tcode{\exposid{underlying_}.set_debug_format()} is a valid expression, and +\item +there is no \fmtgrammarterm{range-underlying-spec}, +\end{itemize} +then calls \tcode{\exposid{underlying_}.set_debug_format()}. + +\pnum +\returns +An iterator past the end of the \fmtgrammarterm{range-format-spec}. +\end{itemdescr} + +\indexlibrarymember{format}{range_formatter}% +\begin{itemdecl} +template + requires @\libconcept{formattable}@, charT> && + @\libconcept{same_as}@>, T> + typename FormatContext::iterator + format(R&& r, FormatContext& ctx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Writes the following into \tcode{ctx.out()}, +adjusted according to the \fmtgrammarterm{range-format-spec}: + +\begin{itemize} +\item +If the \fmtgrammarterm{range-type} was \tcode{s}, +then as if by formatting \tcode{basic_string(from_range, r)}. +\item +Otherwise, if the \fmtgrammarterm{range-type} was \tcode{?s}, +then as if by formatting \tcode{basic_string(from_range, r)} +as an escaped string\iref{format.string.escaped}. +\item +Otherwise, +\begin{itemize} +\item +\exposid{opening-bracket_}, +\item +for each element \tcode{e} of the range \tcode{r}: +\begin{itemize} +\item +the result of writing \tcode{e} via \exposid{underlying_} and +\item +\exposid{separator_}, unless \tcode{e} is the last element of \tcode{r}, and +\end{itemize} +\item +\exposid{closing-bracket_}. +\end{itemize} +\end{itemize} + +\pnum +\returns +An iterator past the end of the output range. +\end{itemdescr} + +\rSec3[format.range.fmtdef]{Class template \exposid{range-default-formatter}} + +\indexlibrary{range-default-formatter@\exposid{range-default-formatter}}% +\begin{codeblock} +namespace std { + template + struct @\exposidnc{range-default-formatter}@ { // \expos + private: + using @\exposidnc{maybe-const-r}@ = @\exposidnc{fmt-maybe-const}@; // \expos + range_formatter>, + charT> @\exposid{underlying_}@; // \expos + + public: + constexpr void set_separator(basic_string_view sep) noexcept; + constexpr void set_brackets(basic_string_view opening, + basic_string_view closing) noexcept; + + template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); + + template + typename FormatContext::iterator + format(@\exposid{maybe-const-r}@& elems, FormatContext& ctx) const; + }; +} +\end{codeblock} + +\indexlibrarymemberexpos{set_separator}{range-default-formatter}% +\begin{itemdecl} +constexpr void set_separator(basic_string_view sep) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{\exposid{underlying_}.set_separator(sep);} +\end{itemdescr} + +\indexlibrarymemberexpos{set_brackets}{range-default-formatter}% +\begin{itemdecl} +constexpr void set_brackets(basic_string_view opening, + basic_string_view closing) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{\exposid{underlying_}.set_brackets(opening, closing);} +\end{itemdescr} + +\indexlibrarymemberexpos{parse}{range-default-formatter}% +\begin{itemdecl} +template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +\end{itemdescr} + +\indexlibrarymemberexpos{format}{range-default-formatter}% +\begin{itemdecl} +template + typename FormatContext::iterator + format(@\exposid{maybe-const-r}@& elems, FormatContext& ctx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{underlying_}.format(elems, ctx);} +\end{itemdescr} + +\rSec3[format.range.fmtmap]{Specialization of \exposid{range-default-formatter} for maps} + +\indexlibrary{range-default-formatter@\exposid{range-default-formatter}}% +\begin{codeblock} +namespace std { + template + struct @\exposid{range-default-formatter}@ { + private: + using @\exposidnc{maybe-const-map}@ = @\exposidnc{fmt-maybe-const}@; // \expos + using @\exposidnc{element-type}@ = // \expos + remove_cvref_t>; + range_formatter<@\exposidnc{element-type}@, charT> @\exposid{underlying_}@; // \expos + + public: + constexpr @\exposid{range-default-formatter}@(); + + template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); + + template + typename FormatContext::iterator + format(@\exposid{maybe-const-map}@& r, FormatContext& ctx) const; + }; +} +\end{codeblock} + +\indexlibrarymisc{range-default-formatter@\exposid{range-default-formatter}}{constructor}% +\begin{itemdecl} +constexpr @\exposid{range-default-formatter}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +Either: +\begin{itemize} +\item +\exposid{element-type} is a specialization of \tcode{pair}, or +\item +\exposid{element-type} is a specialization of \tcode{tuple} and +\tcode{tuple_size_v<\exposid{element-type}> == 2}. +\end{itemize} + +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{underlying_}@.set_brackets(@\exposid{STATICALLY-WIDEN}@("{"), @\exposid{STATICALLY-WIDEN}@("}")); +@\exposid{underlying_}@.underlying().set_brackets({}, {}); +@\exposid{underlying_}@.underlying().set_separator(@\exposid{STATICALLY-WIDEN}@(": ")); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymemberexpos{parse}{range-default-formatter}% +\begin{itemdecl} +template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +\end{itemdescr} + +\indexlibrarymemberexpos{format}{range-default-formatter}% +\begin{itemdecl} +template + typename FormatContext::iterator + format(@\exposid{maybe-const-map}@& r, FormatContext& ctx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{underlying_}.format(r, ctx);} +\end{itemdescr} + +\rSec3[format.range.fmtset]{Specialization of \exposid{range-default-formatter} for sets} + +\indexlibrary{range-default-formatter@\exposid{range-default-formatter}}% +\begin{codeblock} +namespace std { + template + struct @\exposid{range-default-formatter}@ { + private: + using @\exposidnc{maybe-const-set}@ = @\exposidnc{fmt-maybe-const}@; // \expos + range_formatter>, + charT> @\exposid{underlying_}@; // \expos + + public: + constexpr @\exposid{range-default-formatter}@(); + + template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); + + template + typename FormatContext::iterator + format(@\exposid{maybe-const-set}@& r, FormatContext& ctx) const; + }; +} +\end{codeblock} + +\indexlibrarymisc{range-default-formatter@\exposid{range-default-formatter}}{constructor}% +\begin{itemdecl} +constexpr @\exposid{range-default-formatter}@(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{underlying_}@.set_brackets(@\exposid{STATICALLY-WIDEN}@("{"), @\exposid{STATICALLY-WIDEN}@("}")); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymemberexpos{parse}{range-default-formatter}% +\begin{itemdecl} +template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +\end{itemdescr} + +\indexlibrarymemberexpos{format}{range-default-formatter}% +\begin{itemdecl} +template + typename FormatContext::iterator + format(@\exposid{maybe-const-set}@& r, FormatContext& ctx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{underlying_}.format(r, ctx);} +\end{itemdescr} + +\rSec3[format.range.fmtstr]{Specialization of \exposid{range-default-formatter} for strings} + +\indexlibrary{range-default-formatter@\exposid{range-default-formatter}}% +\begin{codeblock} +namespace std { + template + requires (K == range_format::string || K == range_format::debug_string) + struct @\exposid{range-default-formatter}@ { + private: + formatter, charT> @\exposid{underlying_}@; // \expos + + public: + template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); + + template + typename FormatContext::iterator + format(@\seebelow@& str, FormatContext& ctx) const; + }; +} +\end{codeblock} + +\pnum +\mandates +\tcode{\libconcept{same_as}>, charT>} +is \tcode{true}. + +\indexlibrarymemberexpos{parse}{range-default-formatter}% +\begin{itemdecl} +template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto i = @\exposid{underlying_}@.parse(ctx); +if constexpr (K == range_format::debug_string) { + @\exposid{underlying_}@.set_debug_format(); +} +return i; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymemberexpos{format}{range-default-formatter}% +\begin{itemdecl} +template + typename FormatContext::iterator + format(@\seebelow@& r, FormatContext& ctx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The type of \tcode{r} is \tcode{const R\&} +if \tcode{ranges::\libconcept{input_range}} is \tcode{true} and +\tcode{R\&} otherwise. + +\pnum +\effects +Let \tcode{\placeholder{s}} be a \tcode{basic_string} such that +\tcode{ranges::equal(\placeholder{s}, r)} is \tcode{true}. +Equivalent to: \tcode{return \exposid{underlying_}.format(\placeholder{s}, ctx);} +\end{itemdescr} + +\rSec2[format.arguments]{Arguments} + +\rSec3[format.arg]{Class template \tcode{basic_format_arg}} + +\indexlibraryglobal{basic_format_arg}% +\begin{codeblock} +namespace std { + template + class basic_format_arg { + public: + class handle; + + private: + using char_type = typename Context::char_type; // \expos + + variant, + const void*, handle> value; // \expos + + template explicit basic_format_arg(T& v) noexcept; // \expos + + public: + basic_format_arg() noexcept; + + explicit operator bool() const noexcept; + + template + decltype(auto) visit(this basic_format_arg arg, Visitor&& vis); + template + R visit(this basic_format_arg arg, Visitor&& vis); + }; +} +\end{codeblock} + +\pnum +An instance of \tcode{basic_format_arg} provides access to +a formatting argument for user-defined formatters. + +\pnum +The behavior of a program that adds specializations of +\tcode{basic_format_arg} is undefined. + +\indexlibrary{\idxcode{basic_format_arg}!constructor|(}% +\begin{itemdecl} +basic_format_arg() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{!(*this)}. +\end{itemdescr} + +\begin{itemdecl} +template explicit basic_format_arg(T& v) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} satisfies \tcode{\exposconcept{formattable-with}}. + +\pnum +\expects +If \tcode{decay_t} is \tcode{char_type*} or \tcode{const char_type*}, +\tcode{static_cast(v)} points to an NTCTS\iref{defns.ntcts}. + +\pnum +\effects +Let \tcode{TD} be \tcode{remove_const_t}. +\begin{itemize} +\item +If \tcode{TD} is \tcode{bool} or \tcode{char_type}, +initializes \tcode{value} with \tcode{v}; +\item +otherwise, if \tcode{TD} is \tcode{char} and \tcode{char_type} is +\keyword{wchar_t}, initializes \tcode{value} with +\tcode{static_cast(static_cast(v))}; +\item +otherwise, if \tcode{TD} is a signed integer type\iref{basic.fundamental} +and \tcode{sizeof(TD) <= sizeof(int)}, +initializes \tcode{value} with \tcode{static_cast(v)}; +\item +otherwise, if \tcode{TD} is an unsigned integer type and +\tcode{sizeof(TD) <= sizeof(unsigned int)}, initializes +\tcode{value} with \tcode{static_cast(v)}; +\item +otherwise, if \tcode{TD} is a signed integer type and +\tcode{sizeof(TD) <= sizeof(long long int)}, initializes +\tcode{value} with \tcode{static_cast(v)}; +\item +otherwise, if \tcode{TD} is an unsigned integer type and +\tcode{sizeof(TD) <= sizeof(unsigned long long int)}, initializes +\tcode{value} with +\tcode{static_cast(v)}; +\item +otherwise, if \tcode{TD} is a standard floating-point type, +initializes \tcode{value} with \tcode{v}; +\item +otherwise, if \tcode{TD} is +a specialization of \tcode{basic_string_view} or \tcode{basic_string} and +\tcode{TD::value_type} is \tcode{char_type}, +initializes \tcode{value} with +\tcode{basic_string_view(v.data(), v.size())}; +\item +otherwise, if \tcode{decay_t} is +\tcode{char_type*} or \tcode{const char_type*}, +initializes \tcode{value} with \tcode{static_cast(v)}; +\item +otherwise, if \tcode{is_void_v>} is \tcode{true} or +\tcode{is_null_pointer_v} is \tcode{true}, +initializes \tcode{value} with \tcode{static_cast(v)}; +\item +otherwise, initializes \tcode{value} with \tcode{handle(v)}. +\end{itemize} +\begin{note} +Constructing \tcode{basic_format_arg} from a pointer to a member is ill-formed +unless the user provides an enabled specialization of \tcode{formatter} +for that pointer to member type. +\end{note} +\end{itemdescr} + +\indexlibrary{\idxcode{basic_format_arg}!constructor|)}% + +\indexlibrarymember{operator bool}{basic_format_arg}% +\begin{itemdecl} +explicit operator bool() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{!holds_alternative(value)}. +\end{itemdescr} + +\indexlibrarymember{visit}{basic_format_arg}% +\begin{itemdecl} +template + decltype(auto) visit(this basic_format_arg arg, Visitor&& vis); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return arg.value.visit(std::forward(vis));} +\end{itemdescr} + +\indexlibrarymember{visit}{basic_format_arg}% +\begin{itemdecl} +template + R visit(this basic_format_arg arg, Visitor&& vis); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return arg.value.visit(std::forward(vis));} +\end{itemdescr} + +\pnum +The class \tcode{handle} allows formatting an object of a user-defined type. + +\indexlibraryglobal{basic_format_arg::handle}% +\indexlibrarymember{handle}{basic_format_arg}% +\begin{codeblock} +namespace std { + template + class basic_format_arg::handle { + const void* ptr_; // \expos + void (*format_)(basic_format_parse_context&, + Context&, const void*); // \expos + + template explicit handle(T& val) noexcept; // \expos + + public: + void format(basic_format_parse_context&, Context& ctx) const; + }; +} +\end{codeblock} + +\indexlibraryctor{basic_format_arg::handle}% +\begin{itemdecl} +template explicit handle(T& val) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let +\begin{itemize} +\item +\tcode{TD} be \tcode{remove_const_t}, +\item +\tcode{TQ} be \tcode{const TD} if +\tcode{const TD} satisfies \tcode{\exposconcept{formattable-with}} +and \tcode{TD} otherwise. +\end{itemize} + +\pnum +\mandates +\tcode{TQ} satisfies \tcode{\exposconcept{formattable-with}}. + +\pnum +\effects +Initializes +\tcode{ptr_} with \tcode{addressof(val)} and +\tcode{format_} with +\begin{codeblock} +[](basic_format_parse_context& parse_ctx, + Context& format_ctx, const void* ptr) { + typename Context::template formatter_type f; + parse_ctx.advance_to(f.parse(parse_ctx)); + format_ctx.advance_to(f.format(*const_cast(static_cast(ptr)), + format_ctx)); +} +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{format}{basic_format_arg::handle}% +\begin{itemdecl} +void format(basic_format_parse_context& parse_ctx, Context& format_ctx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{format_(parse_ctx, format_ctx, ptr_);} +\end{itemdescr} + +\rSec3[format.arg.store]{Class template \exposid{format-arg-store}} + +\begin{codeblock} +namespace std { + template + class @\exposidnc{format-arg-store}@ { // \expos + array, sizeof...(Args)> @\exposidnc{args}@; // \expos + }; +} +\end{codeblock} + +\pnum +An instance of \exposid{format-arg-store} stores formatting arguments. + +\indexlibraryglobal{make_format_args}% +\begin{itemdecl} +template + @\exposid{format-arg-store}@ make_format_args(Args&... fmt_args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The type +\tcode{typename Context::template formatter_type>}\linebreak{} +meets the \newoldconcept{BasicFormatter} requirements\iref{formatter.requirements} +for each $\tcode{T}_i$ in \tcode{Args}. + +\pnum +\returns +An object of type \tcode{\exposid{format-arg-store}} +whose \exposid{args} data member is initialized with +\tcode{\{basic_format_arg(fmt_args)...\}}. +\end{itemdescr} + +\indexlibraryglobal{make_wformat_args}% +\begin{itemdecl} +template + @\exposid{format-arg-store}@ make_wformat_args(Args&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return make_format_args(args...);} +\end{itemdescr} + +\rSec3[format.args]{Class template \tcode{basic_format_args}} + +\begin{codeblock} +namespace std { + template + class basic_format_args { + size_t size_; // \expos + const basic_format_arg* data_; // \expos + + public: + template + basic_format_args(const @\exposid{format-arg-store}@& store) noexcept; + + basic_format_arg get(size_t i) const noexcept; + }; + + template + basic_format_args(@\exposid{format-arg-store}@) -> basic_format_args; +} +\end{codeblock} + +\pnum +An instance of \tcode{basic_format_args} provides access to formatting +arguments. +Implementations should +optimize the representation of \tcode{basic_format_args} +for a small number of formatting arguments. +\begin{note} +For example, by storing indices of type alternatives separately from values +and packing the former. +\end{note} + +\indexlibraryctor{basic_format_args}% +\begin{itemdecl} +template + basic_format_args(const @\exposid{format-arg-store}@& store) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes +\tcode{size_} with \tcode{sizeof...(Args)} and +\tcode{data_} with \tcode{store.args.data()}. +\end{itemdescr} + +\indexlibrarymember{get}{basic_format_args}% +\begin{itemdecl} +basic_format_arg get(size_t i) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{i < size_ ?\ data_[i] :\ basic_format_arg()}. +\end{itemdescr} + +\rSec2[format.tuple]{Tuple formatter} + +\pnum +For each of \tcode{pair} and \tcode{tuple}, +the library provides the following formatter specialization +where \tcode{\placeholder{pair-or-tuple}} is the name of the template: + +\indexlibraryglobal{formatter}% +\begin{codeblock} +namespace std { + template... Ts> + struct formatter<@\placeholder{pair-or-tuple}@, charT> { + private: + tuple, charT>...> @\exposid{underlying_}@; // \expos + basic_string_view @\exposid{separator_}@ = @\exposid{STATICALLY-WIDEN}@(", "); // \expos + basic_string_view @\exposid{opening-bracket_}@ = @\exposid{STATICALLY-WIDEN}@("("); // \expos + basic_string_view @\exposid{closing-bracket_}@ = @\exposid{STATICALLY-WIDEN}@(")"); // \expos + + public: + constexpr void set_separator(basic_string_view sep) noexcept; + constexpr void set_brackets(basic_string_view opening, + basic_string_view closing) noexcept; + + template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); + + template + typename FormatContext::iterator + format(@\seebelow@& elems, FormatContext& ctx) const; + }; + + template + constexpr bool enable_nonlocking_formatter_optimization<@\placeholder{pair-or-tuple}@> = + (enable_nonlocking_formatter_optimization && ...); +} +\end{codeblock} + +\pnum +The \tcode{parse} member functions of these formatters +interpret the format specification as +a \fmtgrammarterm{tuple-format-spec} according to the following syntax: + +\begin{ncbnf} +\fmtnontermdef{tuple-format-spec}\br + \opt{tuple-fill-and-align} \opt{width} \opt{tuple-type} +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{tuple-fill-and-align}\br + \opt{tuple-fill} align +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{tuple-fill}\br + \textnormal{any character other than} \terminal{\{} \textnormal{or} \terminal{\}} \textnormal{or} \terminal{:} +\end{ncbnf} + +\begin{ncbnf} +\fmtnontermdef{tuple-type}\br + \terminal{m}\br + \terminal{n} +\end{ncbnf} + +\pnum +The \fmtgrammarterm{tuple-fill-and-align} is interpreted the same way as +a \fmtgrammarterm{fill-and-align}\iref{format.string.std}. +The productions \fmtgrammarterm{align} and \fmtgrammarterm{width} +are described in \ref{format.string}. + +\pnum +The \fmtgrammarterm{tuple-type} specifier +changes the way a \tcode{pair} or \tcode{tuple} is formatted, +with certain options only valid with certain argument types. +The meaning of the various type options +is as specified in \tref{formatter.tuple.type}. + +\begin{concepttable}{Meaning of \fmtgrammarterm{tuple-type} options}{formatter.tuple.type} +{p{0.5in}p{1.4in}p{3.2in}} +\topline +\hdstyle{Option} & \hdstyle{Requirements} & \hdstyle{Meaning} \\ \capsep +% +\tcode{m} & +\tcode{sizeof...(Ts) == 2} & +Equivalent to: +\begin{codeblock} +set_separator(@\exposid{STATICALLY-WIDEN}@(": ")); +set_brackets({}, {}); +\end{codeblock}% +\\ \rowsep +% +\tcode{n} & +none & +Equivalent to: \tcode{set_brackets(\{\}, \{\});} +\\ \rowsep +% +none & +none & +No effects +\\ +\end{concepttable} + +\indexlibrarymember{set_separator}{formatter}% +\begin{itemdecl} +constexpr void set_separator(basic_string_view sep) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{\exposid{separator_} = sep;} +\end{itemdescr} + +\indexlibrarymember{set_brackets}{formatter}% +\begin{itemdecl} +constexpr void set_brackets(basic_string_view opening, + basic_string_view closing) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{opening-bracket_}@ = opening; +@\exposid{closing-bracket_}@ = closing; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{parse}{formatter}% +\begin{itemdecl} +template + constexpr typename ParseContext::iterator + parse(ParseContext& ctx); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Parses the format specifiers as a \fmtgrammarterm{tuple-format-spec} and +stores the parsed specifiers in \tcode{*this}. +The values of +\exposid{opening-bracket_}, +\exposid{closing-bracket_}, and +\exposid{separator_} +are modified if and only if +required by the \fmtgrammarterm{tuple-type}, if present. +For each element \tcode{\placeholder{e}} in \exposid{underlying_}, +calls \tcode{\placeholder{e}.parse(ctx)} to parse +an empty \fmtgrammarterm{format-spec} and, +if \tcode{\placeholder{e}.set_debug_format()} is a valid expression, +calls \tcode{\placeholder{e}.set_debug_format()}. + +\pnum +\returns +An iterator past the end of the \fmtgrammarterm{tuple-format-spec}. +\end{itemdescr} + +\indexlibrarymember{format}{formatter}% +\begin{itemdecl} +template + typename FormatContext::iterator + format(@\seebelow@& elems, FormatContext& ctx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The type of \tcode{elems} is: +\begin{itemize} +\item +If \tcode{(\libconcept{formattable} \&\& ...)} is \tcode{true}, +\tcode{const \placeholder{pair-or-tuple}\&}. +\item +Otherwise \tcode{\placeholder{pair-or-tuple}\&}. +\end{itemize} + +\pnum +\effects +Writes the following into \tcode{ctx.out()}, +adjusted according to the \fmtgrammarterm{tuple-format-spec}: +\begin{itemize} +\item +\exposid{opening-bracket_}, +\item +for each index \tcode{I} in the \range{0}{sizeof...(Ts)}: +\begin{itemize} +\item +if \tcode{I != 0}, \exposid{separator_}, +\item +the result of writing \tcode{get(elems)} +via \tcode{get(\exposid{underlying_})}, and +\end{itemize} +\item +\exposid{closing-bracket_}. +\end{itemize} + +\pnum +\returns +An iterator past the end of the output range. +\end{itemdescr} + +\rSec2[format.error]{Class \tcode{format_error}} + +\indexlibraryglobal{format_error}% +\begin{codeblock} +namespace std { + class format_error : public runtime_error { + public: + constexpr explicit format_error(const string& what_arg); + constexpr explicit format_error(const char* what_arg); + }; +} +\end{codeblock} + +\pnum +The class \tcode{format_error} defines the type of objects thrown as +exceptions to report errors from the formatting library. + +\indexlibraryctor{format_error}% +\begin{itemdecl} +constexpr format_error(const string& what_arg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{strcmp(what(), what_arg.c_str()) == 0}. + +\indexlibraryctor{format_error}% +\end{itemdescr} +\begin{itemdecl} +constexpr format_error(const char* what_arg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{strcmp(what(), what_arg) == 0}. +\end{itemdescr} + +\rSec1[re]{Regular expressions library} +\indextext{regular expression|(} + +\rSec2[re.general]{General} + +\pnum +Subclause \ref{re} describes components that \Cpp{} programs may use to +perform operations involving regular expression matching and +searching. + +\pnum +The following subclauses describe a basic regular expression class template and its +traits that can handle char-like\iref{strings.general} template arguments, +two specializations of this class template that handle sequences of \tcode{char} and \keyword{wchar_t}, +a class template that holds the +result of a regular expression match, a series of algorithms that allow a character +sequence to be operated upon by a regular expression, +and two iterator types for +enumerating regular expression matches, as summarized in \tref{re.summary}. + +\begin{libsumtab}{Regular expressions library summary}{re.summary} +\ref{re.req} & Requirements & \\ \rowsep +\ref{re.const} & Constants & \tcode{} \\ +\ref{re.badexp} & Exception type & \\ +\ref{re.traits} & Traits & \\ +\ref{re.regex} & Regular expression template & \\ +\ref{re.submatch} & Submatches & \\ +\ref{re.results} & Match results & \\ +\ref{re.alg} & Algorithms & \\ +\ref{re.iter} & Iterators & \\ \rowsep +\ref{re.grammar} & Grammar & \\ +\end{libsumtab} + +\pnum +The ECMAScript Language Specification described in Standard Ecma-262 +is called \defn{ECMA-262} in this Clause. + +\rSec2[re.req]{Requirements} + +\pnum +This subclause defines requirements on classes representing regular +expression traits. +\begin{note} +The class template +\tcode{regex_traits}, defined in \ref{re.traits}, +meets these requirements. +\end{note} + +\pnum +The class template \tcode{basic_regex}, defined in +\ref{re.regex}, needs a set of related types and +functions to complete the definition of its semantics. These types +and functions are provided as a set of member \grammarterm{typedef-name}{s} and functions +in the template parameter \tcode{traits} used by the \tcode{basic_regex} class +template. This subclause defines the semantics of these +members. + +\pnum +To specialize class template \tcode{basic_regex} for a character +container \tcode{CharT} and its related regular +expression traits class \tcode{Traits}, use \tcode{basic_regex}. + +\pnum +\indextext{regular expression traits!requirements}% +\indextext{requirements!regular expression traits}% +\indextext{regular expression!requirements}% +\indextext{locale}% +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}; +\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} + +\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} + +\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} + +\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} +Class template \tcode{regex_traits} meets the requirements for a +regular expression traits class when it is specialized for +\tcode{char} or \keyword{wchar_t}. This class template is described in +the header \libheader{regex}, and is described in \ref{re.traits}. +\end{note} + +\rSec2[re.syn]{Header \tcode{} synopsis} + +\indexheader{regex}% +\indexlibraryglobal{basic_regex}% +\indexlibraryglobal{regex}% +\indexlibraryglobal{wregex}% +\begin{codeblock} +#include // see \ref{compare.syn} +#include // see \ref{initializer.list.syn} + +namespace std { + // \ref{re.const}, regex constants + namespace regex_constants { + using syntax_option_type = @\placeholder{T1}@; + using match_flag_type = @\placeholder{T2}@; + using error_type = @\placeholder{T3}@; + } + + // \ref{re.badexp}, class \tcode{regex_error} + class regex_error; + + // \ref{re.traits}, class template \tcode{regex_traits} + template struct regex_traits; + + // \ref{re.regex}, class template \tcode{basic_regex} + template> class basic_regex; + + using regex = basic_regex; + using wregex = basic_regex; + + // \ref{re.regex.swap}, \tcode{basic_regex} swap + template + void swap(basic_regex& e1, basic_regex& e2); + + // \ref{re.submatch}, class template \tcode{sub_match} + template + class sub_match; + + using csub_match = sub_match; + using wcsub_match = sub_match; + using ssub_match = sub_match; + using wssub_match = sub_match; + + // \ref{re.submatch.op}, \tcode{sub_match} non-member operators + template + bool operator==(const sub_match& lhs, const sub_match& rhs); + template + auto operator<=>(const sub_match& lhs, const sub_match& rhs); + + template + bool operator==( + const sub_match& lhs, + const basic_string::value_type, ST, SA>& rhs); + template + auto operator<=>( + const sub_match& lhs, + const basic_string::value_type, ST, SA>& rhs); + + template + bool operator==(const sub_match& lhs, + const typename iterator_traits::value_type* rhs); + template + auto operator<=>(const sub_match& lhs, + const typename iterator_traits::value_type* rhs); + + template + bool operator==(const sub_match& lhs, + const typename iterator_traits::value_type& rhs); + template + auto operator<=>(const sub_match& lhs, + const typename iterator_traits::value_type& rhs); + + template + basic_ostream& + operator<<(basic_ostream& os, const sub_match& m); + + // \ref{re.results}, class template \tcode{match_results} + template>> + class match_results; + + using cmatch = match_results; + using wcmatch = match_results; + using smatch = match_results; + using wsmatch = match_results; + + // \tcode{match_results} comparisons + template + bool operator==(const match_results& m1, + const match_results& m2); + + // \ref{re.results.swap}, \tcode{match_results} swap + template + void swap(match_results& m1, + match_results& m2); + + // \ref{re.alg.match}, function template \tcode{regex_match} + template + bool regex_match(BidirectionalIterator first, BidirectionalIterator last, + match_results& m, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + bool regex_match(BidirectionalIterator first, BidirectionalIterator last, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + bool regex_match(const charT* str, match_results& m, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + bool regex_match(const basic_string& s, + match_results::const_iterator, + Allocator>& m, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + bool regex_match(const basic_string&&, + match_results::const_iterator, + Allocator>&, + const basic_regex&, + regex_constants::match_flag_type = regex_constants::match_default) = delete; + template + bool regex_match(const charT* str, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + bool regex_match(const basic_string& s, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); + + // \ref{re.alg.search}, function template \tcode{regex_search} + template + bool regex_search(BidirectionalIterator first, BidirectionalIterator last, + match_results& m, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + bool regex_search(BidirectionalIterator first, BidirectionalIterator last, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + bool regex_search(const charT* str, + match_results& m, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + bool regex_search(const charT* str, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + bool regex_search(const basic_string& s, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + bool regex_search(const basic_string& s, + match_results::const_iterator, + Allocator>& m, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + bool regex_search(const basic_string&&, + match_results::const_iterator, + Allocator>&, + const basic_regex&, + regex_constants::match_flag_type + = regex_constants::match_default) = delete; + + // \ref{re.alg.replace}, function template \tcode{regex_replace} + template + OutputIterator + regex_replace(OutputIterator out, + BidirectionalIterator first, BidirectionalIterator last, + const basic_regex& e, + const basic_string& fmt, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + OutputIterator + regex_replace(OutputIterator out, + BidirectionalIterator first, BidirectionalIterator last, + const basic_regex& e, + const charT* fmt, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + basic_string + regex_replace(const basic_string& s, + const basic_regex& e, + const basic_string& fmt, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + basic_string + regex_replace(const basic_string& s, + const basic_regex& e, + const charT* fmt, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + basic_string + regex_replace(const charT* s, + const basic_regex& e, + const basic_string& fmt, + regex_constants::match_flag_type flags = regex_constants::match_default); + template + basic_string + regex_replace(const charT* s, + const basic_regex& e, + const charT* fmt, + regex_constants::match_flag_type flags = regex_constants::match_default); + + // \ref{re.regiter}, class template \tcode{regex_iterator} + template::value_type, + class traits = regex_traits> + class regex_iterator; + + using cregex_iterator = regex_iterator; + using wcregex_iterator = regex_iterator; + using sregex_iterator = regex_iterator; + using wsregex_iterator = regex_iterator; + + // \ref{re.tokiter}, class template \tcode{regex_token_iterator} + template::value_type, + class traits = regex_traits> + class regex_token_iterator; + + using cregex_token_iterator = regex_token_iterator; + using wcregex_token_iterator = regex_token_iterator; + using sregex_token_iterator = regex_token_iterator; + using wsregex_token_iterator = regex_token_iterator; + + namespace pmr { + template + using match_results = + std::match_results>>; + + using cmatch = match_results; + using wcmatch = match_results; + using smatch = match_results; + using wsmatch = match_results; + } +} +\end{codeblock} + +\rSec2[re.const]{Namespace \tcode{std::regex_constants}} + +\rSec3[re.const.general]{General} + +\pnum +\indexlibraryglobal{regex_constants}% +The namespace \tcode{std::regex_constants} holds +symbolic constants used by the regular expression library. This +namespace provides three types, \tcode{syntax_option_type}, +\tcode{match_flag_type}, and \tcode{error_type}, along with several +constants of these types. + +\rSec3[re.synopt]{Bitmask type \tcode{syntax_option_type}} +\indexlibraryglobal{syntax_option_type}% +\indexlibrarymember{regex_constants}{syntax_option_type}% +\begin{codeblock} +namespace std::regex_constants { + using syntax_option_type = @\textit{T1}@; + inline constexpr syntax_option_type icase = @\unspec@; + inline constexpr syntax_option_type nosubs = @\unspec@; + inline constexpr syntax_option_type optimize = @\unspec@; + inline constexpr syntax_option_type collate = @\unspec@; + inline constexpr syntax_option_type ECMAScript = @\unspec@; + inline constexpr syntax_option_type basic = @\unspec@; + inline constexpr syntax_option_type extended = @\unspec@; + inline constexpr syntax_option_type awk = @\unspec@; + inline constexpr syntax_option_type grep = @\unspec@; + inline constexpr syntax_option_type egrep = @\unspec@; + inline constexpr syntax_option_type multiline = @\unspec@; +} +\end{codeblock} + +\pnum +\indexlibraryglobal{syntax_option_type}% +\indexlibrarymember{syntax_option_type}{icase}% +\indexlibrarymember{syntax_option_type}{nosubs}% +\indexlibrarymember{syntax_option_type}{optimize}% +\indexlibrarymember{syntax_option_type}{collate}% +\indexlibrarymember{syntax_option_type}{ECMAScript}% +\indexlibrarymember{syntax_option_type}{basic}% +\indexlibrarymember{syntax_option_type}{extended}% +\indexlibrarymember{syntax_option_type}{awk}% +\indexlibrarymember{syntax_option_type}{grep}% +\indexlibrarymember{syntax_option_type}{egrep}% +The type \tcode{syntax_option_type} is an \impldef{type of \tcode{syntax_option_type}} bitmask +type\iref{bitmask.types}. Setting its elements has the effects listed in +\tref{re.synopt}. A valid value of type +\tcode{syntax_option_type} shall have at most one of the grammar elements +\tcode{ECMAScript}, \tcode{basic}, \tcode{extended}, \tcode{awk}, \tcode{grep}, \tcode{egrep}, set. +If no grammar element is set, the default grammar is \tcode{ECMAScript}. + +\begin{libefftab} + {\tcode{syntax_option_type} effects} + {re.synopt} +% +\tcode{icase} & +Specifies that matching of regular expressions against a character +container sequence shall be performed without regard to case. +\indexlibrarymember{syntax_option_type}{icase}% +\\ \rowsep +% +\tcode{nosubs} & +Specifies that no sub-expressions shall be considered to be marked, so that +when a regular expression is matched against a +character container sequence, no sub-expression matches shall be +stored in the supplied \tcode{match_results} object. +\indexlibrarymember{syntax_option_type}{nosubs}% +\\ \rowsep +% +\tcode{optimize} & +Specifies that the regular expression engine should pay more attention +to the speed with which regular expressions are matched, and less to +the speed with which regular expression objects are +constructed. Otherwise it has no detectable effect on the program +output. +\indexlibrarymember{syntax_option_type}{optimize}% +\\ \rowsep +% +\tcode{collate} & +Specifies that character ranges of the form \tcode{"[a-b]"} shall be locale +sensitive.% +\indexlibrarymember{syntax_option_type}{collate}% +\indextext{locale}% +\\ \rowsep +% +\tcode{ECMAScript} & +Specifies that the grammar recognized by the regular expression engine +shall be that used by ECMAScript in ECMA-262, as modified in~\ref{re.grammar}. +\newline \xref{ECMA-262 15.10} +\indextext{ECMAScript}% +\indexlibrarymember{syntax_option_type}{ECMAScript}% +\\ \rowsep +% +\tcode{basic} & +Specifies that the grammar recognized by the regular expression engine +shall be that used by basic regular expressions in POSIX. +\newline \xref{POSIX, Base Definitions and Headers, Section 9.3} +\indextext{POSIX!regular expressions}% +\indexlibrarymember{syntax_option_type}{basic}% +\\ \rowsep +% +\tcode{extended} & +Specifies that the grammar recognized by the regular expression engine +shall be that used by extended regular expressions in POSIX. +\newline \xref{POSIX, Base Definitions and Headers, Section 9.4} +\indextext{POSIX!extended regular expressions}% +\indexlibrarymember{syntax_option_type}{extended}% +\\ \rowsep +% +\tcode{awk} & +Specifies that the grammar recognized by the regular expression engine +shall be that used by the utility awk in POSIX. +\indexlibrarymember{syntax_option_type}{awk}% +\\ \rowsep +% +\tcode{grep} & +Specifies that the grammar recognized by the regular expression engine +shall be that used by the utility grep in POSIX. +\indexlibrarymember{syntax_option_type}{grep}% +\\ \rowsep +% +\tcode{egrep} & +Specifies that the grammar recognized by the regular expression engine +shall be that used by the utility grep when given the -E +option in POSIX. +\indexlibrarymember{syntax_option_type}{egrep}% +\\ \rowsep +% +\tcode{multiline} & +Specifies that \tcode{\caret} shall match the beginning of a line and +\tcode{\$} shall match the end of a line, +if the \tcode{ECMAScript} engine is selected. +\indexlibrarymember{syntax_option_type}{multiline}% +\\ +% +\end{libefftab} + +\rSec3[re.matchflag]{Bitmask type \tcode{match_flag_type}} + +\indexlibraryglobal{match_flag_type}% +\indexlibrarymember{regex_constants}{match_flag_type}% +\indexlibraryglobal{match_default}% +\indexlibraryglobal{match_not_bol}% +\indexlibraryglobal{match_not_eol}% +\indexlibraryglobal{match_not_bow}% +\indexlibraryglobal{match_not_eow}% +\indexlibraryglobal{match_any}% +\indexlibraryglobal{match_not_null}% +\indexlibraryglobal{match_continuous}% +\indexlibraryglobal{match_prev_avail}% +\indexlibraryglobal{format_default}% +\indexlibraryglobal{format_sed}% +\indexlibraryglobal{format_no_copy}% +\indexlibraryglobal{format_first_only}% +\begin{codeblock} +namespace std::regex_constants { + using match_flag_type = @\textit{T2}@; + inline constexpr match_flag_type match_default = {}; + inline constexpr match_flag_type match_not_bol = @\unspec@; + inline constexpr match_flag_type match_not_eol = @\unspec@; + inline constexpr match_flag_type match_not_bow = @\unspec@; + inline constexpr match_flag_type match_not_eow = @\unspec@; + inline constexpr match_flag_type match_any = @\unspec@; + inline constexpr match_flag_type match_not_null = @\unspec@; + inline constexpr match_flag_type match_continuous = @\unspec@; + inline constexpr match_flag_type match_prev_avail = @\unspec@; + inline constexpr match_flag_type format_default = {}; + inline constexpr match_flag_type format_sed = @\unspec@; + inline constexpr match_flag_type format_no_copy = @\unspec@; + inline constexpr match_flag_type format_first_only = @\unspec@; +} +\end{codeblock} + +\pnum +\indexlibraryglobal{match_flag_type}% +The type \tcode{match_flag_type} is an +\impldef{type of \tcode{regex_constants::match_flag_type}} bitmask type\iref{bitmask.types}. +The constants of that type, except for \tcode{match_default} and +\tcode{format_default}, are bitmask elements. The \tcode{match_default} and +\tcode{format_default} constants are empty bitmasks. +Matching a regular expression against a sequence of characters +\range{first}{last} proceeds according to the rules of the grammar specified for the regular +expression object, modified according to the effects listed in \tref{re.matchflag} for +any bitmask elements set. + +\begin{longlibefftab} + {\tcode{regex_constants::match_flag_type} effects} + {re.matchflag} +% +\indexlibraryglobal{match_not_bol}% +\tcode{match_not_bol} & +The first character in the sequence \range{first}{last} shall be treated +as though it is not at the beginning of a line, so the character +\verb|^| in the regular expression shall not match \range{first}{first}. +\\ \rowsep +% +\indexlibraryglobal{match_not_eol}% +\tcode{match_not_eol} & +The last character in the sequence \range{first}{last} shall be treated +as though it is not at the end of a line, so the character +\verb|"$"| in the regular expression shall not match \range{last}{last}. +\\ \rowsep +% +\indexlibraryglobal{match_not_bow}% +\tcode{match_not_bow} & +The expression \verb|"\\b"| shall not match the +sub-sequence \range{first}{first}. +\\ \rowsep +% +\indexlibraryglobal{match_not_eow}% +\tcode{match_not_eow} & +The expression \verb|"\\b"| shall not match the +sub-sequence \range{last}{last}. +\\ \rowsep +% +\indexlibraryglobal{match_any}% +\tcode{match_any} & +If more than one match is possible then any match is an +acceptable result. +\\ \rowsep +% +\indexlibraryglobal{match_not_null}% +\tcode{match_not_null} & +The expression shall not match an empty +sequence. +\\ \rowsep +% +\indexlibraryglobal{match_continuous}% +\tcode{match_continuous} & +The expression shall only match a sub-sequence that begins at +\tcode{first}. +\\ \rowsep +% +\indexlibraryglobal{match_prev_avail}% +\tcode{match_prev_avail} & +\verb!--first! is a valid iterator position. When this flag is +set the flags \tcode{match_not_bol} and \tcode{match_not_bow} shall be ignored by the +regular expression algorithms\iref{re.alg} and iterators\iref{re.iter}. +\\ \rowsep +% +\indexlibraryglobal{format_default}% +\tcode{format_default} & +When a regular expression match is to be replaced by a +new string, the new string shall be constructed using the rules used by +the ECMAScript replace function in ECMA-262, +part 15.5.4.11 String.prototype.replace. In +addition, during search and replace operations all non-overlapping +occurrences of the regular expression shall be located and replaced, and +sections of the input that did not match the expression shall be copied +unchanged to the output string. +\\ \rowsep +% +\indexlibraryglobal{format_sed}% +\tcode{format_sed} & +When a regular expression match is to be replaced by a +new string, the new string shall be constructed using the rules used by +the sed utility in POSIX. +\\ \rowsep +% +\indexlibraryglobal{format_no_copy}% +\tcode{format_no_copy} & +During a search and replace operation, sections of +the character container sequence being searched that do not match the +regular expression shall not be copied to the output string. \\ \rowsep +% +\indexlibraryglobal{format_first_only}% +\tcode{format_first_only} & +When specified during a search and replace operation, only the +first occurrence of the regular expression shall be replaced. +\\ +\end{longlibefftab} + +\rSec3[re.err]{Implementation-defined \tcode{error_type}} +\indexlibraryglobal{error_type}% +\indexlibrarymember{regex_constants}{error_type}% +\begin{codeblock} +namespace std::regex_constants { + using error_type = @\textit{T3}@; + inline constexpr error_type error_collate = @\unspec@; + inline constexpr error_type error_ctype = @\unspec@; + inline constexpr error_type error_escape = @\unspec@; + inline constexpr error_type error_backref = @\unspec@; + inline constexpr error_type error_brack = @\unspec@; + inline constexpr error_type error_paren = @\unspec@; + inline constexpr error_type error_brace = @\unspec@; + inline constexpr error_type error_badbrace = @\unspec@; + inline constexpr error_type error_range = @\unspec@; + inline constexpr error_type error_space = @\unspec@; + inline constexpr error_type error_badrepeat = @\unspec@; + inline constexpr error_type error_complexity = @\unspec@; + inline constexpr error_type error_stack = @\unspec@; +} +\end{codeblock} + +\pnum +\indexlibraryglobal{error_type}% +\indexlibrarymember{regex_constants}{error_type}% +The type \tcode{error_type} is an \impldef{type of +\tcode{regex_constants::error_type}} enumerated type\iref{enumerated.types}. +Values of type \tcode{error_type} represent the error +conditions described in \tref{re.err}: + +\begin{longliberrtab} + {\tcode{error_type} values in the C locale} + {re.err} +\tcode{error_collate} +& +The expression contains an invalid collating element name. \\ \rowsep +% +\tcode{error_ctype} +& +The expression contains an invalid character class name. \\ \rowsep +% +\tcode{error_escape} +& +The expression contains an invalid escaped character, or a trailing +escape. \\ \rowsep +% +\tcode{error_backref} +& +The expression contains an invalid back reference. \\ \rowsep +% +\tcode{error_brack} +& +The expression contains mismatched \verb|[| and \verb|]|. \\ \rowsep +% +\tcode{error_paren} +& +The expression contains mismatched \verb|(| and \verb|)|. \\ \rowsep +% +\tcode{error_brace} +& +The expression contains mismatched \verb|{| and \verb|}|. \\ \rowsep +% +\tcode{error_badbrace} +& +The expression contains an invalid range in a \verb|{}| expression. \\ +\rowsep +% +\tcode{error_range} +& +The expression contains an invalid character range, such as +\verb|[b-a]| in most encodings. \\ \rowsep +% +\tcode{error_space} +& +There is insufficient memory to convert the expression into a finite +state machine. \\ \rowsep +% +\tcode{error_badrepeat} +& +One of \verb|*?+{| is not preceded by a valid regular expression. \\ \rowsep +% +\tcode{error_complexity} +& +The complexity of an attempted match against a regular expression +exceeds a pre-set level. \\ \rowsep +% +\tcode{error_stack} +& +There is insufficient memory to determine whether the regular +expression matches the specified character sequence. \\ +% +\end{longliberrtab} + +\rSec2[re.badexp]{Class \tcode{regex_error}} +\indexlibraryglobal{regex_error}% +\begin{codeblock} +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 +The class \tcode{regex_error} defines the type of objects thrown as +exceptions to report errors from the regular expression library. + +\indexlibraryctor{regex_error}% +\begin{itemdecl} +regex_error(regex_constants::error_type ecode); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{ecode == code()}. +\end{itemdescr} + +\indexlibraryglobal{error_type}% +\indexlibrarymember{regex_constants}{error_type}% +\begin{itemdecl} +regex_constants::error_type code() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The error code that was passed to the constructor. +\end{itemdescr} + +\rSec2[re.traits]{Class template \tcode{regex_traits}} +\indexlibraryglobal{regex_traits}% +\begin{codeblock} +namespace std { + template + struct regex_traits { + using char_type = charT; + using string_type = basic_string; + using locale_type = locale; + using char_class_type = @\placeholdernc{bitmask_type}@; + + regex_traits(); + static size_t length(const char_type* p); + charT translate(charT c) const; + charT translate_nocase(charT c) const; + template + string_type transform(ForwardIterator first, ForwardIterator last) const; + template + string_type transform_primary( + ForwardIterator first, ForwardIterator last) const; + template + string_type lookup_collatename( + ForwardIterator first, ForwardIterator last) const; + template + char_class_type lookup_classname( + ForwardIterator first, ForwardIterator last, bool icase = false) const; + bool isctype(charT c, char_class_type f) const; + int value(charT ch, int radix) const; + locale_type imbue(locale_type l); + locale_type getloc() const; + }; +} +\end{codeblock} + +\pnum +\indextext{regular expression traits!requirements}% +\indextext{requirements!regular expression traits}% +The specializations \tcode{regex_traits} and +\tcode{regex_traits} meet the +requirements for a regular expression traits class\iref{re.req}. + +\indexlibrarymember{regex_traits}{char_class_type}% +\begin{itemdecl} +using char_class_type = @\textit{bitmask_type}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +The type \tcode{char_class_type} is used to represent a character +classification and is capable of holding an implementation specific +set returned by \tcode{lookup_classname}. +\end{itemdescr} + +\indexlibrarymember{length}{regex_traits}% +\begin{itemdecl} +static size_t length(const char_type* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{char_traits::length(p)}. +\end{itemdescr} + +\indexlibrarymember{regex_traits}{translate}% +\begin{itemdecl} +charT translate(charT c) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{c}. +\end{itemdescr} + +\indexlibrarymember{regex_traits}{translate_nocase}% +\begin{itemdecl} +charT translate_nocase(charT c) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{use_facet>(getloc()).tolower(c)}. +\end{itemdescr} + +\indexlibrarymember{regex_traits}{transform}% +\begin{itemdecl} +template + string_type transform(ForwardIterator first, ForwardIterator last) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +As if by: +\begin{codeblock} +string_type str(first, last); +return use_facet>( + getloc()).transform(str.data(), str.data() + str.length()); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{regex_traits}{transform_primary}% +\begin{itemdecl} +template + string_type transform_primary(ForwardIterator first, ForwardIterator last) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +If +\begin{codeblock} +typeid(use_facet>(getloc())) == typeid(collate_byname) +\end{codeblock} +and the form of the sort key returned +by \tcode{collate_byname::transform(first, last)} is known and +can be converted into a primary sort key then returns that key, +otherwise returns an empty string. +\end{itemdescr} + +\indexlibrarymember{regex_traits}{lookup_collatename}% +\begin{itemdecl} +template + string_type lookup_collatename(ForwardIterator first, ForwardIterator last) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A sequence of one or more characters that +represents the collating element consisting of the character +sequence designated by the iterator range \range{first}{last}. +Returns an empty string if the character sequence is not a +valid collating element. +\end{itemdescr} + +\indexlibrarymember{regex_traits}{lookup_classname}% +\begin{itemdecl} +template + char_class_type lookup_classname( + ForwardIterator first, ForwardIterator last, bool icase = false) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An unspecified value that represents +the character classification named by the character sequence +designated by the iterator range \range{first}{last}. +If the parameter \tcode{icase} is \tcode{true} then the returned mask identifies the +character classification without regard to the case of the characters being +matched, otherwise it does honor the case of the characters being +matched. +\begin{footnote} +For example, if the parameter \tcode{icase} is \tcode{true} then +\tcode{[[:lower:]]} is the same as \tcode{[[:alpha:]]}. +\end{footnote} +The value +returned shall be independent of the case of the characters in +the character sequence. If the name +is not recognized then returns \tcode{char_class_type()}. + +\pnum +\remarks +For \tcode{regex_traits}, at least the narrow character names +in \tref{re.traits.classnames} shall be recognized. +For \tcode{regex_traits}, at least the wide character names +in \tref{re.traits.classnames} shall be recognized. +\end{itemdescr} + +\indexlibrarymember{regex_traits}{isctype}% +\begin{itemdecl} +bool isctype(charT c, char_class_type f) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Determines if the character \tcode{c} is a member of the character +classification represented by \tcode{f}. + +\pnum +\returns +Given the following function declaration: +\begin{codeblock} +// for exposition only +template + ctype_base::mask convert(typename regex_traits::char_class_type f); +\end{codeblock} +that returns a value in which each \tcode{ctype_base::mask} value corresponding to +a value in \tcode{f} named in \tref{re.traits.classnames} is set, then the +result is determined as if by: +\begin{codeblock} +ctype_base::mask m = convert(f); +const ctype& ct = use_facet>(getloc()); +if (ct.is(m, c)) { + return true; +} else if (c == ct.widen('_')) { + charT w[1] = { ct.widen('w') }; + char_class_type x = lookup_classname(w, w+1); + return (f&x) == x; +} else { + return false; +} +\end{codeblock} +\begin{example} +\begin{codeblock} +regex_traits t; +string d("d"); +string u("upper"); +regex_traits::char_class_type f; +f = t.lookup_classname(d.begin(), d.end()); +f |= t.lookup_classname(u.begin(), u.end()); +ctype_base::mask m = convert(f); // \tcode{m == ctype_base::digit | ctype_base::upper} +\end{codeblock} +\end{example} +\begin{example} +\begin{codeblock} +regex_traits t; +string w("w"); +regex_traits::char_class_type f; +f = t.lookup_classname(w.begin(), w.end()); +t.isctype('A', f); // returns \tcode{true} +t.isctype('_', f); // returns \tcode{true} +t.isctype(' ', f); // returns \tcode{false} +\end{codeblock} +\end{example} +\end{itemdescr} + +\indexlibrarymember{value}{regex_traits}% +\begin{itemdecl} +int value(charT ch, int radix) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +The value of \tcode{radix} is 8, 10, or 16. + +\pnum +\returns +The value represented by the digit \tcode{ch} in base +\tcode{radix} if the character \tcode{ch} is a valid digit in base +\tcode{radix}; otherwise returns \tcode{-1}. +\end{itemdescr} + +\indexlibraryglobal{locale}% +\indexlibraryglobal{imbue}% +\begin{itemdecl} +locale_type imbue(locale_type loc); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Imbues \tcode{*this} with a copy of the +locale \tcode{loc}. +\begin{note} +Calling \tcode{imbue} with a +different locale than the one currently in use invalidates all cached +data held by \tcode{*this}. +\end{note} + +\pnum +\ensures +\tcode{getloc() == loc}. + +\pnum +\returns +If no locale has been previously imbued then a copy of the +global locale in effect at the time of construction of \tcode{*this}, +otherwise a copy of the last argument passed to \tcode{imbue}. +\end{itemdescr} + +\indexlibraryglobal{locale}% +\indexlibraryglobal{getloc}% +\begin{itemdecl} +locale_type getloc() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If no locale has been imbued then a copy of the global locale +in effect at the time of construction of \tcode{*this}, otherwise a copy of +the last argument passed to \tcode{imbue}. +\end{itemdescr} + +\begin{floattable}{Character class names and corresponding \tcode{ctype} masks}{re.traits.classnames}{lll} +\topline +\lhdr{Narrow character name} & \chdr{Wide character name} & \rhdr{Corresponding \tcode{ctype_base::mask} value} \\\capsep +\tcode{"alnum"} & \tcode{L"alnum"} & \tcode{ctype_base::alnum} \\ \rowsep +\tcode{"alpha"} & \tcode{L"alpha"} & \tcode{ctype_base::alpha} \\ \rowsep +\tcode{"blank"} & \tcode{L"blank"} & \tcode{ctype_base::blank} \\ \rowsep +\tcode{"cntrl"} & \tcode{L"cntrl"} & \tcode{ctype_base::cntrl} \\ \rowsep +\tcode{"digit"} & \tcode{L"digit"} & \tcode{ctype_base::digit} \\ \rowsep +\tcode{"d"} & \tcode{L"d"} & \tcode{ctype_base::digit} \\ \rowsep +\tcode{"graph"} & \tcode{L"graph"} & \tcode{ctype_base::graph} \\ \rowsep +\tcode{"lower"} & \tcode{L"lower"} & \tcode{ctype_base::lower} \\ \rowsep +\tcode{"print"} & \tcode{L"print"} & \tcode{ctype_base::print} \\ \rowsep +\tcode{"punct"} & \tcode{L"punct"} & \tcode{ctype_base::punct} \\ \rowsep +\tcode{"space"} & \tcode{L"space"} & \tcode{ctype_base::space} \\ \rowsep +\tcode{"s"} & \tcode{L"s"} & \tcode{ctype_base::space} \\ \rowsep +\tcode{"upper"} & \tcode{L"upper"} & \tcode{ctype_base::upper} \\ \rowsep +\tcode{"w"} & \tcode{L"w"} & \tcode{ctype_base::alnum} \\ \rowsep +\tcode{"xdigit"} & \tcode{L"xdigit"} & \tcode{ctype_base::xdigit} \\ +\end{floattable} + +\rSec2[re.regex]{Class template \tcode{basic_regex}} + +\rSec3[re.regex.general]{General} +\indexlibraryglobal{basic_regex}% + +\pnum +For a char-like type \tcode{charT}, specializations of class +template \tcode{basic_regex} represent regular expressions constructed +from character sequences of \tcode{charT} characters. In the rest +of~\ref{re.regex}, \tcode{charT} denotes a given char-like +type. Storage for a regular expression is allocated and freed as +necessary by the member functions of class \tcode{basic_regex}. + +\pnum +Objects of type specialization of \tcode{basic_regex} are responsible for +converting the sequence of \tcode{charT} objects to an internal +representation. It is not specified what form this representation +takes, nor how it is accessed by algorithms that operate on regular +expressions. +\begin{note} +Implementations will typically declare +some function templates as friends of \tcode{basic_regex} to achieve +this. +\end{note} + +\pnum +\indexlibraryglobal{regex_error}% +The functions described in \ref{re.regex} report errors by throwing +exceptions of type \tcode{regex_error}. + +\indexlibraryglobal{basic_regex}% +\begin{codeblock} +namespace std { + template> + class basic_regex { + public: + // types + using value_type = charT; + using traits_type = traits; + using string_type = typename traits::string_type; + using flag_type = regex_constants::syntax_option_type; + using locale_type = typename traits::locale_type; + + // \ref{re.synopt}, constants + static constexpr flag_type icase = regex_constants::icase; + static constexpr flag_type nosubs = regex_constants::nosubs; + static constexpr flag_type optimize = regex_constants::optimize; + static constexpr flag_type collate = regex_constants::collate; + static constexpr flag_type ECMAScript = regex_constants::ECMAScript; + static constexpr flag_type basic = regex_constants::basic; + static constexpr flag_type extended = regex_constants::extended; + static constexpr flag_type awk = regex_constants::awk; + static constexpr flag_type grep = regex_constants::grep; + static constexpr flag_type egrep = regex_constants::egrep; + static constexpr flag_type multiline = regex_constants::multiline; + + // \ref{re.regex.construct}, construct/copy/destroy + basic_regex(); + explicit basic_regex(const charT* p, flag_type f = regex_constants::ECMAScript); + basic_regex(const charT* p, size_t len, flag_type f = regex_constants::ECMAScript); + basic_regex(const basic_regex&); + basic_regex(basic_regex&&) noexcept; + template + explicit basic_regex(const basic_string& s, + flag_type f = regex_constants::ECMAScript); + template + basic_regex(ForwardIterator first, ForwardIterator last, + flag_type f = regex_constants::ECMAScript); + basic_regex(initializer_list il, flag_type f = regex_constants::ECMAScript); + + ~basic_regex(); + + // \ref{re.regex.assign}, assign + basic_regex& operator=(const basic_regex& e); + basic_regex& operator=(basic_regex&& e) noexcept; + basic_regex& operator=(const charT* p); + basic_regex& operator=(initializer_list il); + template + basic_regex& operator=(const basic_string& s); + + basic_regex& assign(const basic_regex& e); + basic_regex& assign(basic_regex&& e) noexcept; + basic_regex& assign(const charT* p, flag_type f = regex_constants::ECMAScript); + basic_regex& assign(const charT* p, size_t len, flag_type f = regex_constants::ECMAScript); + template + basic_regex& assign(const basic_string& s, + flag_type f = regex_constants::ECMAScript); + template + basic_regex& assign(InputIterator first, InputIterator last, + flag_type f = regex_constants::ECMAScript); + basic_regex& assign(initializer_list, + flag_type f = regex_constants::ECMAScript); + + // \ref{re.regex.operations}, const operations + unsigned mark_count() const; + flag_type flags() const; + + // \ref{re.regex.locale}, locale + locale_type imbue(locale_type loc); + locale_type getloc() const; + + // \ref{re.regex.swap}, swap + void swap(basic_regex&); + }; + + template + basic_regex(ForwardIterator, ForwardIterator, + regex_constants::syntax_option_type = regex_constants::ECMAScript) + -> basic_regex::value_type>; +} +\end{codeblock} + +\rSec3[re.regex.construct]{Constructors} + +\indexlibraryctor{basic_regex}% +\begin{itemdecl} +basic_regex(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{*this} does not match any character sequence. +\end{itemdescr} + +\indexlibraryctor{basic_regex}% +\begin{itemdecl} +explicit basic_regex(const charT* p, flag_type f = regex_constants::ECMAScript); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\range{p}{p + char_traits::length(p)} is a valid range. + +\pnum +\effects +The object's internal finite state machine +is constructed from the regular expression contained in +the sequence of characters +\range{p}{p + char_traits::\brk{}length(p)}, and +interpreted according to the flags \tcode{f}. + +\pnum +\ensures +\tcode{flags()} returns \tcode{f}. +\tcode{mark_count()} returns the number of marked sub-expressions +within the expression. + +\pnum +\throws +\tcode{regex_error} if +\range{p}{p + char_traits::length(p)} is not a valid regular expression. +\end{itemdescr} + +\indexlibraryctor{basic_regex}% +\begin{itemdecl} +basic_regex(const charT* p, size_t len, flag_type f = regex_constants::ECMAScript); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\range{p}{p + len} is a valid range. + +\pnum +\effects +The object's internal finite state machine +is constructed from the regular expression contained in +the sequence of characters \range{p}{p + len}, and +interpreted according the flags specified in \tcode{f}. + +\pnum +\ensures +\tcode{flags()} returns \tcode{f}. +\tcode{mark_count()} returns the number of marked sub-expressions +within the expression. + +\pnum +\throws +\tcode{regex_error} if \range{p}{p + len} is not a valid regular expression. +\end{itemdescr} + +\indexlibraryctor{basic_regex}% +\begin{itemdecl} +basic_regex(const basic_regex& e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{flags()} and \tcode{mark_count()} return +\tcode{e.flags()} and \tcode{e.mark_count()}, respectively. +\end{itemdescr} + +\indexlibraryctor{basic_regex}% +\begin{itemdecl} +basic_regex(basic_regex&& e) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{flags()} and \tcode{mark_count()} return the values that +\tcode{e.flags()} and \tcode{e.mark_count()}, respectively, had before construction. +\end{itemdescr} + +\indexlibraryctor{basic_regex}% +\begin{itemdecl} +template + explicit basic_regex(const basic_string& s, + flag_type f = regex_constants::ECMAScript); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +The object's internal finite state machine +is constructed from the regular expression contained in +the string \tcode{s}, and +interpreted according to the flags specified in \tcode{f}. + +\pnum +\ensures +\tcode{flags()} returns \tcode{f}. +\tcode{mark_count()} returns the number of marked sub-expressions +within the expression. + +\pnum +\throws +\tcode{regex_error} if \tcode{s} is not a valid regular expression. +\end{itemdescr} + +\indexlibraryctor{basic_regex}% +\begin{itemdecl} +template + basic_regex(ForwardIterator first, ForwardIterator last, + flag_type f = regex_constants::ECMAScript); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +The object's internal finite state machine +is constructed from the regular expression contained in +the sequence of characters \range{first}{last}, and +interpreted according to the flags specified in \tcode{f}. + +\pnum +\ensures +\tcode{flags()} returns \tcode{f}. +\tcode{mark_count()} returns the number of marked sub-expressions +within the expression. + +\pnum +\throws +\tcode{regex_error} if the sequence \range{first}{last} is not a +valid regular expression. +\end{itemdescr} + +\indexlibraryctor{basic_regex}% +\begin{itemdecl} +basic_regex(initializer_list il, flag_type f = regex_constants::ECMAScript); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Same as \tcode{basic_regex(il.begin(), il.end(), f)}. +\end{itemdescr} + +\rSec3[re.regex.assign]{Assignment} + +\indexlibrarymember{basic_regex}{operator=}% +\begin{itemdecl} +basic_regex& operator=(const basic_regex& e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{flags()} and \tcode{mark_count()} return +\tcode{e.flags()} and \tcode{e.mark_count()}, respectively. +\end{itemdescr} + +\indexlibrarymember{basic_regex}{operator=}% +\begin{itemdecl} +basic_regex& operator=(basic_regex&& e) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{flags()} and \tcode{mark_count()} return the values that +\tcode{e.flags()} and \tcode{e.mark_count()}, respectively, had before assignment. +\tcode{e} is in a valid state with unspecified value. +\end{itemdescr} + +\indexlibrarymember{basic_regex}{operator=}% +\begin{itemdecl} +basic_regex& operator=(const charT* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return assign(p);} +\end{itemdescr} + +\indexlibrarymember{basic_regex}{operator=}% +\begin{itemdecl} +basic_regex& operator=(initializer_list il); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return assign(il.begin(), il.end());} +\end{itemdescr} + +\indexlibrarymember{basic_regex}{operator=}% +\begin{itemdecl} +template + basic_regex& operator=(const basic_string& s); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return assign(s);} +\end{itemdescr} + +\indexlibrarymember{basic_regex}{assign}% +\begin{itemdecl} +basic_regex& assign(const basic_regex& e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return *this = e;} +\end{itemdescr} + +\indexlibrarymember{basic_regex}{assign}% +\begin{itemdecl} +basic_regex& assign(basic_regex&& e) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return *this = std::move(e);} +\end{itemdescr} + +\indexlibrarymember{basic_regex}{assign}% +\begin{itemdecl} +basic_regex& assign(const charT* p, flag_type f = regex_constants::ECMAScript); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return assign(string_type(p), f);} +\end{itemdescr} + +\indexlibrarymember{basic_regex}{assign}% +\begin{itemdecl} +basic_regex& assign(const charT* p, size_t len, flag_type f = regex_constants::ECMAScript); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return assign(string_type(p, len), f);} +\end{itemdescr} + +\indexlibrarymember{basic_regex}{assign}% +\begin{itemdecl} +template + basic_regex& assign(const basic_string& s, + flag_type f = regex_constants::ECMAScript); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Assigns the regular expression contained in the string +\tcode{s}, interpreted according the flags specified in \tcode{f}. +If an exception is thrown, \tcode{*this} is unchanged. + +\pnum +\ensures +If no exception is thrown, +\tcode{flags()} returns \tcode{f} and \tcode{mark_count()} +returns the number of marked sub-expressions within the expression. + +\pnum +\returns +\tcode{*this}. + +\pnum +\throws +\tcode{regex_error} if \tcode{s} is not a valid regular expression. +\end{itemdescr} + +\indexlibrarymember{basic_regex}{assign}% +\begin{itemdecl} +template + basic_regex& assign(InputIterator first, InputIterator last, + flag_type f = regex_constants::ECMAScript); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return assign(string_type(first, last), f);} +\end{itemdescr} + +\indexlibrarymember{assign}{basic_regex}% +\begin{itemdecl} +basic_regex& assign(initializer_list il, + flag_type f = regex_constants::ECMAScript); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return assign(il.begin(), il.end(), f);} +\end{itemdescr} + + +\rSec3[re.regex.operations]{Constant operations} + +\indexlibrarymember{mark_count}{basic_regex}% +\begin{itemdecl} +unsigned mark_count() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Returns the number of marked sub-expressions within the +regular expression. +\end{itemdescr} + +\indexlibrarymember{flag_type}{basic_regex}% +\begin{itemdecl} +flag_type flags() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Returns a copy of the regular expression syntax flags that +were passed to the object's constructor or to the last call +to \tcode{assign}. +\end{itemdescr} + +\rSec3[re.regex.locale]{Locale}% +\indexlibraryglobal{locale} + +\indexlibrarymember{imbue}{basic_regex}% +\begin{itemdecl} +locale_type imbue(locale_type loc); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Returns the result of \tcode{traits_inst.imbue(loc)} where +\tcode{traits_inst} is a (default-initialized) instance of the template +type argument \tcode{traits} stored within the object. After a call +to \tcode{imbue} the \tcode{basic_regex} object does not match any +character sequence. +\end{itemdescr} + +\indexlibrarymember{getloc}{basic_regex}% +\begin{itemdecl} +locale_type getloc() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Returns the result of \tcode{traits_inst.getloc()} where +\tcode{traits_inst} is a (default-initialized) instance of the template +parameter \tcode{traits} stored within the object. +\end{itemdescr} + +\rSec3[re.regex.swap]{Swap} +\indexlibrarymember{basic_regex}{swap}% + +\indexlibrarymember{swap}{basic_regex}% +\begin{itemdecl} +void swap(basic_regex& e); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Swaps the contents of the two regular expressions. + +\pnum +\ensures +\tcode{*this} contains the regular expression +that was in \tcode{e}, \tcode{e} contains the regular expression that +was in \tcode{*this}. + +\pnum +\complexity +Constant time. +\end{itemdescr} + +\rSec3[re.regex.nonmemb]{Non-member functions} + +\indexlibrarymember{basic_regex}{swap}% +\begin{itemdecl} +template + void swap(basic_regex& lhs, basic_regex& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Calls \tcode{lhs.swap(rhs)}. +\end{itemdescr} + +\rSec2[re.submatch]{Class template \tcode{sub_match}} + +\rSec3[re.submatch.general]{General} +\pnum +\indexlibraryglobal{sub_match}% +Class template \tcode{sub_match} denotes the sequence of characters matched +by a particular marked sub-expression. + +\begin{codeblock} +namespace std { + template + class sub_match : public pair { + public: + using value_type = + typename iterator_traits::value_type; + using difference_type = + typename iterator_traits::difference_type; + using iterator = BidirectionalIterator; + using string_type = basic_string; + + bool matched; + + constexpr sub_match(); + + difference_type length() const; + operator string_type() const; + string_type str() const; + + int compare(const sub_match& s) const; + int compare(const string_type& s) const; + int compare(const value_type* s) const; + + void swap(sub_match& s) noexcept(@\seebelow@); + }; +} +\end{codeblock} + + +\rSec3[re.submatch.members]{Members} + +\indexlibraryctor{sub_match}% +\begin{itemdecl} +constexpr sub_match(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Value-initializes the \tcode{pair} base class subobject and the member +\tcode{matched}. +\end{itemdescr} + +\indexlibrarymember{sub_match}{length}% +\begin{itemdecl} +difference_type length() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{matched ?\ distance(first, second) :\ 0}. +\end{itemdescr} + +\indexlibrarymember{operator basic_string}{sub_match}% +\begin{itemdecl} +operator string_type() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{matched ?\ string_type(first, second) :\ string_type()}. +\end{itemdescr} + +\indexlibrarymember{sub_match}{str}% +\begin{itemdecl} +string_type str() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{matched ?\ string_type(first, second) :\ string_type()}. +\end{itemdescr} + +\indexlibrarymember{sub_match}{compare}% +\begin{itemdecl} +int compare(const sub_match& s) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{str().compare(s.str())}. +\end{itemdescr} + +\indexlibrarymember{sub_match}{compare}% +\begin{itemdecl} +int compare(const string_type& s) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{str().compare(s)}. +\end{itemdescr} + +\indexlibrarymember{sub_match}{compare}% +\begin{itemdecl} +int compare(const value_type* s) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{str().compare(s)}. +\end{itemdescr} + +\indexlibrarymember{sub_match}{swap}% +\begin{itemdecl} +void swap(sub_match& s) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{BidirectionalIterator} meets +the \oldconcept{Swappable} requirements\iref{swappable.requirements}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +this->pair::swap(s); +std::swap(matched, s.matched); +\end{codeblock} + +\pnum +\remarks +The exception specification is equivalent to +\tcode{is_nothrow_swappable_v}. +\end{itemdescr} + +\rSec3[re.submatch.op]{Non-member operators} + +\pnum +Let \tcode{\placeholdernc{SM-CAT}(I)} be +\begin{codeblock} +compare_three_way_result_t::value_type>> +\end{codeblock} + +\indexlibrarymember{sub_match}{operator==}% +\begin{itemdecl} +template + bool operator==(const sub_match& lhs, const sub_match& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{lhs.compare(rhs) == 0}. +\end{itemdescr} + +\indexlibrarymember{sub_match}{operator<=>}% +\begin{itemdecl} +template + auto operator<=>(const sub_match& lhs, const sub_match& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{static_cast<\placeholdernc{SM-CAT}(BiIter)>(lhs.compare(rhs) <=> 0)}. +\end{itemdescr} + +\indexlibrarymember{operator==}{sub_match}% +\begin{itemdecl} +template + bool operator==( + const sub_match& lhs, + const basic_string::value_type, ST, SA>& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +lhs.compare(typename sub_match::string_type(rhs.data(), rhs.size())) == 0 +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator<=>}{sub_match}% +\begin{itemdecl} +template + auto operator<=>( + const sub_match& lhs, + const basic_string::value_type, ST, SA>& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +static_cast<@\placeholdernc{SM-CAT}@(BiIter)>(lhs.compare( + typename sub_match::string_type(rhs.data(), rhs.size())) + <=> 0 + ) +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{sub_match}{operator==}% +\begin{itemdecl} +template + bool operator==(const sub_match& lhs, + const typename iterator_traits::value_type* rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{lhs.compare(rhs) == 0}. +\end{itemdescr} + +\indexlibrarymember{sub_match}{operator<=>}% +\begin{itemdecl} +template + auto operator<=>(const sub_match& lhs, + const typename iterator_traits::value_type* rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{static_cast<\placeholdernc{SM-CAT}(BiIter)>(lhs.compare(rhs) <=> 0)}. +\end{itemdescr} + +\indexlibrarymember{sub_match}{operator==}% +\begin{itemdecl} +template + bool operator==(const sub_match& lhs, + const typename iterator_traits::value_type& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{lhs.compare(typename sub_match::string_type(1, rhs)) == 0}. +\end{itemdescr} + +\indexlibrarymember{sub_match}{operator<=>}% +\begin{itemdecl} +template + auto operator<=>(const sub_match& lhs, + const typename iterator_traits::value_type& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +static_cast<@\placeholdernc{SM-CAT}@(BiIter)>(lhs.compare( + typename sub_match::string_type(1, rhs)) + <=> 0 + ) +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{basic_ostream}% +\indexlibrarymember{sub_match}{operator<<}% +\begin{itemdecl} +template + basic_ostream& + operator<<(basic_ostream& os, const sub_match& m); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{os << m.str()}. +\end{itemdescr} + +\rSec2[re.results]{Class template \tcode{match_results}} + +\rSec3[re.results.general]{General} +\pnum +\indexlibraryglobal{match_results}% +Class template \tcode{match_results} denotes a collection of character +sequences representing the result of a regular expression +match. Storage for the collection is allocated and freed as necessary +by the member functions of class template \tcode{match_results}. + +\pnum +\indextext{requirements!container}% +\indextext{requirements!sequence}% +The class template \tcode{match_results} meets the requirements of an +allocator-aware container\iref{container.alloc.reqmts} and of +a sequence container\iref{container.requirements.general,sequence.reqmts} +except that only +copy assignment, +move assignment, and +operations defined for const-qualified sequence containers +are supported and +that the semantics of the comparison operator functions are different from those +required for a container. + +\pnum +A default-constructed \tcode{match_results} object has no fully established result state. A +match result is \defn{ready} when, as a consequence of a completed regular expression match +modifying such an object, its result state becomes fully established. The effects of calling +most member functions from a \tcode{match_results} object that is not ready are undefined. + +\pnum +\indexlibrarymember{match_results}{matched}% +The \tcode{sub_match} object stored at index 0 represents sub-expression 0, +i.e., the whole match. In this case the \tcode{sub_match} member +\tcode{matched} is always \tcode{true}. The \tcode{sub_match} +object stored at index \tcode{n} denotes what matched the marked +sub-expression \tcode{n} within the matched expression. If the +sub-expression \tcode{n} participated in a regular expression +match then the \tcode{sub_match} member \tcode{matched} evaluates to \tcode{true}, and +members \tcode{first} and \tcode{second} denote the range of characters +\range{first}{second} which formed that +match. Otherwise \tcode{matched} is \tcode{false}, and members \tcode{first} +and \tcode{second} point to the end of the sequence +that was searched. +\begin{note} +The \tcode{sub_match} objects representing +different sub-expressions that did not participate in a regular expression +match need not be distinct. +\end{note} + +\begin{codeblock} +namespace std { + template>> + class match_results { + public: + using value_type = sub_match; + using const_reference = const value_type&; + using reference = value_type&; + using const_iterator = @\impdefx{type of \tcode{match_results::const_iterator}}@; + using iterator = const_iterator; + using difference_type = + typename iterator_traits::difference_type; + using size_type = typename allocator_traits::size_type; + using allocator_type = Allocator; + using char_type = + typename iterator_traits::value_type; + using string_type = basic_string; + + // \ref{re.results.const}, construct/copy/destroy + match_results() : match_results(Allocator()) {} + explicit match_results(const Allocator& a); + match_results(const match_results& m); + match_results(const match_results& m, const Allocator& a); + match_results(match_results&& m) noexcept; + match_results(match_results&& m, const Allocator& a); + match_results& operator=(const match_results& m); + match_results& operator=(match_results&& m); + ~match_results(); + + // \ref{re.results.state}, state + bool ready() const; + + // \ref{re.results.size}, size + size_type size() const; + size_type max_size() const; + bool empty() const; + + // \ref{re.results.acc}, element access + difference_type length(size_type sub = 0) const; + difference_type position(size_type sub = 0) const; + string_type str(size_type sub = 0) const; + const_reference operator[](size_type n) const; + + const_reference prefix() const; + const_reference suffix() const; + const_iterator begin() const; + const_iterator end() const; + const_iterator cbegin() const; + const_iterator cend() const; + + // \ref{re.results.form}, format + template + OutputIter + format(OutputIter out, + const char_type* fmt_first, const char_type* fmt_last, + regex_constants::match_flag_type flags = regex_constants::format_default) const; + template + OutputIter + format(OutputIter out, + const basic_string& fmt, + regex_constants::match_flag_type flags = regex_constants::format_default) const; + template + basic_string + format(const basic_string& fmt, + regex_constants::match_flag_type flags = regex_constants::format_default) const; + string_type + format(const char_type* fmt, + regex_constants::match_flag_type flags = regex_constants::format_default) const; + + // \ref{re.results.all}, allocator + allocator_type get_allocator() const; + + // \ref{re.results.swap}, swap + void swap(match_results& that); + }; +} +\end{codeblock} + +\rSec3[re.results.const]{Constructors} + +\pnum +\tref{re.results.const} lists the postconditions of +\tcode{match_results} copy/move constructors and copy/move assignment operators. +For move operations, +the results of the expressions depending on the parameter \tcode{m} denote +the values they had before the respective function calls. + +\indexlibraryctor{match_results}% +\begin{itemdecl} +explicit match_results(const Allocator& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +The stored \tcode{Allocator} value is constructed from \tcode{a}. + +\pnum +\ensures +\tcode{ready()} returns \tcode{false}. +\tcode{size()} returns \tcode{0}. +\end{itemdescr} + +\indexlibraryctor{match_results}% +\begin{itemdecl} +match_results(const match_results& m); +match_results(const match_results& m, const Allocator& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +For the first form, +the stored \tcode{Allocator} value is obtained +as specified in \ref{container.reqmts}. +For the second form, +the stored \tcode{Allocator} value is constructed from \tcode{a}. + +\pnum +\ensures +As specified in \tref{re.results.const}. +\end{itemdescr} + +\indexlibraryctor{match_results}% +\begin{itemdecl} +match_results(match_results&& m) noexcept; +match_results(match_results&& m, const Allocator& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +For the first form, +the stored \tcode{Allocator} value is move constructed from \tcode{m.get_allocator()}. +For the second form, +the stored \tcode{Allocator} value is constructed from \tcode{a}. + +\pnum +\ensures +As specified in \tref{re.results.const}. + +\pnum +\throws +The second form throws nothing if +\tcode{a == m.get_allocator()} is \tcode{true}. +\end{itemdescr} + +\indexlibrarymember{match_results}{operator=}% +\begin{itemdecl} +match_results& operator=(const match_results& m); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +As specified in \tref{re.results.const}. +\end{itemdescr} + +\indexlibrarymember{match_results}{operator=}% +\begin{itemdecl} +match_results& operator=(match_results&& m); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +As specified in \tref{re.results.const}. +\end{itemdescr} + +\begin{libefftabvalue} + {\tcode{match_results} copy/move operation postconditions} + {re.results.const} +\tcode{ready()} & \tcode{m.ready()} \\ \rowsep +\tcode{size()} & \tcode{m.size()} \\ \rowsep +\tcode{str(n)} & \tcode{m.str(n)} for all non-negative integers \tcode{n < m.size()} \\ \rowsep +\tcode{prefix()} & \tcode{m.prefix()} \\ \rowsep +\tcode{suffix()} & \tcode{m.suffix()} \\ \rowsep +\tcode{(*this)[n]} & \tcode{m[n]} for all non-negative integers \tcode{n < m.size()} \\ \rowsep +\tcode{length(n)} & \tcode{m.length(n)} for all non-negative integers \tcode{n < m.size()} \\ \rowsep +\tcode{position(n)} & \tcode{m.position(n)} for all non-negative integers \tcode{n < m.size()} \\ +\end{libefftabvalue} + +\rSec3[re.results.state]{State} + +\indexlibrarymember{match_results}{ready}% +\begin{itemdecl} +bool ready() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{*this} has a fully established result state, otherwise +\tcode{false}. +\end{itemdescr} + +\rSec3[re.results.size]{Size} + +\indexlibrarymember{match_results}{size}% +\begin{itemdecl} +size_type size() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +One plus the number of marked sub-expressions in the +regular expression that was matched if \tcode{*this} represents the +result of a successful match. Otherwise returns \tcode{0}. +\begin{note} +The state of a \tcode{match_results} object can be modified +only by passing that object to \tcode{regex_match} or \tcode{regex_search}. +Subclauses~\ref{re.alg.match} and~\ref{re.alg.search} specify the +effects of those algorithms on their \tcode{match_results} arguments. +\end{note} +\end{itemdescr} + +\indexlibrarymember{match_results}{max_size}% +\begin{itemdecl} +size_type max_size() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +The maximum number of \tcode{sub_match} elements that can be +stored in \tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{match_results}{empty}% +\begin{itemdecl} +bool empty() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{size() == 0}. +\end{itemdescr} + +\rSec3[re.results.acc]{Element access} + +\indexlibrarymember{length}{match_results}% +\begin{itemdecl} +difference_type length(size_type sub = 0) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{ready() == true}. + +\pnum +\returns +\tcode{(*this)[sub].length()}. +\end{itemdescr} + +\indexlibrarymember{position}{match_results}% +\begin{itemdecl} +difference_type position(size_type sub = 0) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{ready() == true}. + +\pnum +\returns +The distance from the start of the target sequence +to \tcode{(*this)[sub].first}. +\end{itemdescr} + +\indexlibrarymember{match_results}{str}% +\begin{itemdecl} +string_type str(size_type sub = 0) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{ready() == true}. + +\pnum +\returns +\tcode{string_type((*this)[sub])}. +\end{itemdescr} + +\indexlibrarymember{match_results}{operator[]}% +\begin{itemdecl} +const_reference operator[](size_type n) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{ready() == true}. + +\pnum +\returns +A reference to the \tcode{sub_match} object representing the +character sequence that matched marked sub-expression \tcode{n}. If \tcode{n == 0} +then returns a reference to a \tcode{sub_match} object representing the +character sequence that matched the whole regular expression. If +\tcode{n >= size()} then returns a \tcode{sub_match} object representing an +unmatched sub-expression. +\end{itemdescr} + +\indexlibrarymember{match_results}{prefix}% +\begin{itemdecl} +const_reference prefix() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{ready() == true}. + +\pnum +\returns +A reference to the \tcode{sub_match} object representing the +character sequence from the start of the string being +matched/searched to the start of the match found. +\end{itemdescr} + +\indexlibrarymember{match_results}{suffix}% +\begin{itemdecl} +const_reference suffix() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{ready() == true}. + +\pnum +\returns +A reference to the \tcode{sub_match} object representing the +character sequence from the end of the match found to the end of the +string being matched/searched. +\end{itemdescr} + +\indexlibrarymember{match_results}{begin}% +\begin{itemdecl} +const_iterator begin() const; +const_iterator cbegin() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A starting iterator that enumerates over all the +sub-expressions stored in \tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{match_results}{end}% +\begin{itemdecl} +const_iterator end() const; +const_iterator cend() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A terminating iterator that enumerates over all the +sub-expressions stored in \tcode{*this}. +\end{itemdescr} + +\rSec3[re.results.form]{Formatting} + +\indexlibrarymember{match_results}{format}% +\begin{itemdecl} +template + OutputIter format( + OutputIter out, + const char_type* fmt_first, const char_type* fmt_last, + regex_constants::match_flag_type flags = regex_constants::format_default) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{ready() == true} and \tcode{OutputIter} meets the requirements for a +\oldconcept{OutputIterator}\iref{output.iterators}. + +\pnum +\effects +Copies the character sequence \range{fmt_first}{fmt_last} to +OutputIter \tcode{out}. Replaces each format specifier or escape +sequence in the copied range with either the character(s) it represents or +the sequence of characters within \tcode{*this} to which it refers. +The bitmasks specified in \tcode{flags} determine which format +specifiers and escape sequences are recognized. + +\pnum +\returns +\tcode{out}. +\end{itemdescr} + +\indexlibrarymember{match_results}{format}% +\begin{itemdecl} +template + OutputIter format( + OutputIter out, + const basic_string& fmt, + regex_constants::match_flag_type flags = regex_constants::format_default) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return format(out, fmt.data(), fmt.data() + fmt.size(), flags); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{match_results}{format}% +\begin{itemdecl} +template + basic_string format( + const basic_string& fmt, + regex_constants::match_flag_type flags = regex_constants::format_default) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{ready() == true}. + +\pnum +\effects +Constructs an empty string \tcode{result} of type \tcode{basic_string} and +calls: +\begin{codeblock} +format(back_inserter(result), fmt, flags); +\end{codeblock} + +\pnum +\returns +\tcode{result}. +\end{itemdescr} + +\indexlibrarymember{match_results}{format}% +\begin{itemdecl} +string_type format( + const char_type* fmt, + regex_constants::match_flag_type flags = regex_constants::format_default) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{ready() == true}. + +\pnum +\effects +Constructs an empty string \tcode{result} of type \tcode{string_type} and +calls: +\begin{codeblock} +format(back_inserter(result), fmt, fmt + char_traits::length(fmt), flags); +\end{codeblock} + +\pnum +\returns +\tcode{result}. +\end{itemdescr} + +\rSec3[re.results.all]{Allocator}% + +\indexlibrarymember{get_allocator}{match_results}% +\begin{itemdecl} +allocator_type get_allocator() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A copy of the Allocator that was passed to the object's constructor or, if that +allocator has been replaced, a copy of the most recent replacement. +\end{itemdescr} + +\rSec3[re.results.swap]{Swap} + +\indexlibrarymember{match_results}{swap}% +\begin{itemdecl} +void swap(match_results& that); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Swaps the contents of the two sequences. + +\pnum +\ensures +\tcode{*this} contains the sequence of matched +sub-expressions that were in \tcode{that}, \tcode{that} contains the +sequence of matched sub-expressions that were in \tcode{*this}. + +\pnum +\complexity +Constant time. +\end{itemdescr} + +\indexlibrarymember{match_results}{swap}% +\begin{itemdecl} +template + void swap(match_results& m1, + match_results& m2); +\end{itemdecl} + +\pnum +\effects +As if by \tcode{m1.swap(m2)}. + +\rSec3[re.results.nonmember]{Non-member functions} + +\indexlibrarymember{operator==}{match_results}% +\begin{itemdecl} +template + bool operator==(const match_results& m1, + const match_results& m2); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if neither match result is ready, \tcode{false} if one match result is ready and the +other is not. If both match results are ready, returns \tcode{true} only if +\begin{itemize} +\item +\tcode{m1.empty() \&\& m2.empty()}, or + +\item +\tcode{!m1.empty() \&\& !m2.empty()}, and the following conditions are satisfied: +\begin{itemize} +\item +\tcode{m1.prefix() == m2.prefix()}, + +\item +\tcode{m1.size() == m2.size() \&\& equal(m1.begin(), m1.end(), m2.begin())}, and + +\item +\tcode{m1.suffix() == m2.suffix()}. +\end{itemize} +\end{itemize} +\begin{note} +The algorithm \tcode{equal} is defined in \ref{algorithms}. +\end{note} +\end{itemdescr} + +\rSec2[re.alg]{Regular expression algorithms} + +\rSec3[re.except]{Exceptions} +\pnum +The algorithms described in subclause~\ref{re.alg} may throw an exception +of type \tcode{regex_error}. If such an exception \tcode{e} is thrown, +\tcode{e.code()} shall return either \tcode{regex_constants::error_complexity} +or \tcode{regex_constants::error_stack}. + +\rSec3[re.alg.match]{\tcode{regex_match}} +\indexlibraryglobal{regex_match}% +\begin{itemdecl} +template + bool regex_match(BidirectionalIterator first, BidirectionalIterator last, + match_results& m, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{BidirectionalIterator} models +\libconcept{bidirectional_iterator}\iref{iterator.concept.bidir}. + +\pnum +\effects +Determines whether there is a match between the +regular expression \tcode{e}, and all of the character +sequence \range{first}{last}. The parameter \tcode{flags} is +used to control how the expression is matched against the character +sequence. When determining if there is a match, only potential matches +that match the entire character sequence are considered. +Returns \tcode{true} if such a match exists, \tcode{false} +otherwise. +\begin{example} +\begin{codeblock} +std::regex re("Get|GetValue"); +std::cmatch m; +regex_search("GetValue", m, re); // returns \tcode{true}, and \tcode{m[0]} contains \tcode{"Get"} +regex_match ("GetValue", m, re); // returns \tcode{true}, and \tcode{m[0]} contains \tcode{"GetValue"} +regex_search("GetValues", m, re); // returns \tcode{true}, and \tcode{m[0]} contains \tcode{"Get"} +regex_match ("GetValues", m, re); // returns \tcode{false} +\end{codeblock} +\end{example} + +\pnum +\ensures +\tcode{m.ready() == true} in all cases. +If the function returns \tcode{false}, then the effect +on parameter \tcode{m} is unspecified except that \tcode{m.size()} +returns \tcode{0} and \tcode{m.empty()} returns \tcode{true}. +Otherwise the effects on parameter \tcode{m} are given in +\tref{re.alg.match}. +\end{itemdescr} + +\begin{longlibefftabvalue} + {Effects of \tcode{regex_match} algorithm} + {re.alg.match} +\tcode{m.size()} +& +\tcode{1 + e.mark_count()} +\\ \rowsep +\tcode{m.empty()} +& +\tcode{false} +\\ \rowsep +\tcode{m.prefix().first} +& +\tcode{first} +\\ \rowsep +\tcode{m.prefix().second} +& +\tcode{first} +\\ \rowsep +\tcode{m.prefix().matched} +& +\tcode{false} +\\ \rowsep +\tcode{m.suffix().first} +& +\tcode{last} +\\ \rowsep +\tcode{m.suffix().second} +& +\tcode{last} +\\ \rowsep +\tcode{m.suffix().matched} +& +\tcode{false} +\\ \rowsep +\tcode{m[0].first} +& +\tcode{first} +\\ \rowsep +\tcode{m[0].second} +& +\tcode{last} +\\ \rowsep +\tcode{m[0].matched} +& +\tcode{true} +\\ \rowsep +\tcode{m[n].first} +& +For all integers \tcode{0 < n < m.size()}, the start of the sequence that matched +sub-expression \tcode{n}. Alternatively, if sub-expression \tcode{n} did not participate +in the match, then \tcode{last}. +\\ \rowsep +\tcode{m[n].second} +& +For all integers \tcode{0 < n < m.size()}, the end of the sequence that matched +sub-expression \tcode{n}. Alternatively, if sub-expression \tcode{n} did not participate +in the match, then \tcode{last}. +\\ \rowsep +\tcode{m[n].matched} +& +For all integers \tcode{0 < n < m.size()}, \tcode{true} if sub-expression \tcode{n} participated in +the match, \tcode{false} otherwise. +\\ +\end{longlibefftabvalue} + +\indexlibraryglobal{regex_match}% +\begin{itemdecl} +template + bool regex_match(BidirectionalIterator first, BidirectionalIterator last, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Behaves ``as if'' by constructing an instance of +\tcode{match_results what}, and then +returning the result of +\tcode{regex_match(first, last, what, e, flags)}. +\end{itemdescr} + +\indexlibraryglobal{regex_match}% +\begin{itemdecl} +template + bool regex_match(const charT* str, + match_results& m, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{regex_match(str, str + char_traits::length(str), m, e, flags)}. +\end{itemdescr} + +\indexlibraryglobal{regex_match}% +\begin{itemdecl} +template + bool regex_match(const basic_string& s, + match_results::const_iterator, + Allocator>& m, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{regex_match(s.begin(), s.end(), m, e, flags)}. +\end{itemdescr} + +\indexlibraryglobal{regex_match}% +\begin{itemdecl} +template + bool regex_match(const charT* str, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{regex_match(str, str + char_traits::length(str), e, flags)}. +\end{itemdescr} + +\indexlibraryglobal{regex_match}% +\begin{itemdecl} +template + bool regex_match(const basic_string& s, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{regex_match(s.begin(), s.end(), e, flags)}. +\end{itemdescr} + +\rSec3[re.alg.search]{\tcode{regex_search}} + +\indexlibraryglobal{regex_search}% +\begin{itemdecl} +template + bool regex_search(BidirectionalIterator first, BidirectionalIterator last, + match_results& m, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{BidirectionalIterator} models +\libconcept{bidirectional_iterator}\iref{iterator.concept.bidir}. + +\pnum +\effects +Determines whether there is some sub-sequence within \range{first}{last} that matches +the regular expression \tcode{e}. The parameter \tcode{flags} is used to control how the +expression is matched against the character sequence. Returns \tcode{true} if such a sequence +exists, \tcode{false} otherwise. + +\pnum +\ensures +\tcode{m.ready() == true} in all cases. +If the function returns \tcode{false}, then the effect +on parameter \tcode{m} is unspecified except that \tcode{m.size()} +returns \tcode{0} and \tcode{m.empty()} returns \tcode{true}. Otherwise +the effects on parameter \tcode{m} are given in \tref{re.alg.search}. +\end{itemdescr} + +\begin{longlibefftabvalue} + {Effects of \tcode{regex_search} algorithm} + {re.alg.search} +\tcode{m.size()} +& +\tcode{1 + e.mark_count()} +\\ \rowsep +\tcode{m.empty()} +& +\tcode{false} +\\ \rowsep +\tcode{m.prefix().first} +& +\tcode{first} +\\ \rowsep +\tcode{m.prefix().second} +& +\tcode{m[0].first} +\\ \rowsep +\tcode{m.prefix().matched} +& +\tcode{m.prefix().first != m.prefix().second} +\\ \rowsep +\tcode{m.suffix().first} +& +\tcode{m[0].second} +\\ \rowsep +\tcode{m.suffix().second} +& +\tcode{last} +\\ \rowsep +\tcode{m.suffix().matched} +& +\tcode{m.suffix().first != m.suffix().second} +\\ \rowsep +\tcode{m[0].first} +& +The start of the sequence of characters that matched the regular expression +\\ \rowsep +\tcode{m[0].second} +& +The end of the sequence of characters that matched the regular expression +\\ \rowsep +\tcode{m[0].matched} +& +\tcode{true} +\\ \rowsep +\tcode{m[n].first} +& +For all integers \tcode{0 < n < m.size()}, the start of the sequence that +matched sub-expression \tcode{n}. Alternatively, if sub-expression \tcode{n} +did not participate in the match, then \tcode{last}. +\\ \rowsep +\tcode{m[n].second} +& +For all integers \tcode{0 < n < m.size()}, the end of the sequence that matched +sub-expression \tcode{n}. Alternatively, if sub-expression \tcode{n} did not +participate in the match, then \tcode{last}. +\\ \rowsep +\tcode{m[n].matched} +& +For all integers \tcode{0 < n < m.size()}, \tcode{true} if sub-expression \tcode{n} +participated in the match, \tcode{false} otherwise. +\\ +\end{longlibefftabvalue} + +\indexlibraryglobal{regex_search}% +\begin{itemdecl} +template + bool regex_search(const charT* str, match_results& m, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{regex_search(str, str + char_traits::length(str), m, e, flags)}. +\end{itemdescr} + +\indexlibraryglobal{regex_search}% +\begin{itemdecl} +template + bool regex_search(const basic_string& s, + match_results::const_iterator, + Allocator>& m, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{regex_search(s.begin(), s.end(), m, e, flags)}. +\end{itemdescr} + +\indexlibraryglobal{regex_search}% +\begin{itemdecl} +template + bool regex_search(BidirectionalIterator first, BidirectionalIterator last, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Behaves ``as if'' by constructing an object \tcode{what} +of type \tcode{match_results} and returning +\tcode{regex_search(first, last, what, e, flags)}. +\end{itemdescr} + +\indexlibraryglobal{regex_search}% +\begin{itemdecl} +template + bool regex_search(const charT* str, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{regex_search(str, str + char_traits::length(str), e, flags)}. +\end{itemdescr} + +\indexlibraryglobal{regex_search}% +\begin{itemdecl} +template + bool regex_search(const basic_string& s, + const basic_regex& e, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{regex_search(s.begin(), s.end(), e, flags)}. +\end{itemdescr} + +\rSec3[re.alg.replace]{\tcode{regex_replace}} + +\indexlibraryglobal{regex_replace}% +\begin{itemdecl} +template + OutputIterator + regex_replace(OutputIterator out, + BidirectionalIterator first, BidirectionalIterator last, + const basic_regex& e, + const basic_string& fmt, + regex_constants::match_flag_type flags = regex_constants::match_default); +template + OutputIterator + regex_replace(OutputIterator out, + BidirectionalIterator first, BidirectionalIterator last, + const basic_regex& e, + const charT* fmt, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\indexlibraryglobal{format_no_copy}% +\indexlibraryglobal{format_first_only}% +\effects +Constructs a \tcode{regex_iterator} object \tcode{i} +as if by +\begin{codeblock} +regex_iterator i(first, last, e, flags) +\end{codeblock} +and uses \tcode{i} to enumerate through all +of the matches \tcode{m} of type \tcode{match_results} +that occur within the sequence \range{first}{last}. +If no such +matches are found and +\tcode{!(flags \& regex_constants::format_no_copy)}, then calls +\begin{codeblock} +out = copy(first, last, out) +\end{codeblock} +If any matches are found then, for each such match: +\begin{itemize} +\item +If \tcode{!(flags \& regex_constants::format_no_copy)}, calls +\begin{codeblock} +out = copy(m.prefix().first, m.prefix().second, out) +\end{codeblock} +\item +Then calls +\begin{codeblock} +out = m.format(out, fmt, flags) +\end{codeblock} +for the first form of the function and +\begin{codeblock} +out = m.format(out, fmt, fmt + char_traits::length(fmt), flags) +\end{codeblock} +for the second. +\end{itemize} +Finally, if such a match +is found and \tcode{!(flags \& regex_constants::format_no_copy)}, +calls +\begin{codeblock} +out = copy(last_m.suffix().first, last_m.suffix().second, out) +\end{codeblock} +where \tcode{last_m} is a copy of the last match +found. If \tcode{flags \& regex_constants::format_first_only} +is nonzero, then only the first match found is replaced. + +\pnum +\returns +\tcode{out}. +\end{itemdescr} + +\indexlibraryglobal{regex_replace}% +\begin{itemdecl} +template + basic_string + regex_replace(const basic_string& s, + const basic_regex& e, + const basic_string& fmt, + regex_constants::match_flag_type flags = regex_constants::match_default); +template + basic_string + regex_replace(const basic_string& s, + const basic_regex& e, + const charT* fmt, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty string \tcode{result} of +type \tcode{basic_string} and calls: +\begin{codeblock} +regex_replace(back_inserter(result), s.begin(), s.end(), e, fmt, flags); +\end{codeblock} + +\pnum +\returns +\tcode{result}. +\end{itemdescr} + +\indexlibraryglobal{regex_replace}% +\begin{itemdecl} +template + basic_string + regex_replace(const charT* s, + const basic_regex& e, + const basic_string& fmt, + regex_constants::match_flag_type flags = regex_constants::match_default); +template + basic_string + regex_replace(const charT* s, + const basic_regex& e, + const charT* fmt, + regex_constants::match_flag_type flags = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty string \tcode{result} of +type \tcode{basic_string} and calls: +\begin{codeblock} +regex_replace(back_inserter(result), s, s + char_traits::length(s), e, fmt, flags); +\end{codeblock} + +\pnum +\returns +\tcode{result}. +\end{itemdescr} + +\rSec2[re.iter]{Regular expression iterators} + +\rSec3[re.regiter]{Class template \tcode{regex_iterator}} + +\rSec4[re.regiter.general]{General} +\pnum +\indexlibraryglobal{regex_iterator}% +\indexlibraryglobal{match_results}% +The class template \tcode{regex_iterator} is an iterator adaptor. +It represents a new view of an existing iterator sequence, by +enumerating all the occurrences of a regular expression within that +sequence. A \tcode{regex_iterator} uses \tcode{regex_search} to find successive +regular expression matches within the sequence from which it was +constructed. After the iterator is constructed, and every time \tcode{operator++} is +used, the iterator finds and stores a value of +\tcode{match_results}. If the end of the sequence is +reached (\tcode{regex_search} returns \tcode{false}), the iterator becomes equal to +the end-of-sequence iterator value. The default constructor +constructs an end-of-sequence iterator object, +which is the only legitimate iterator to be used for the end +condition. The result of \tcode{operator*} on an end-of-sequence iterator is not +defined. For any other iterator value a +\tcode{const match_results\&} is returned. The result of +\tcode{operator->} on an end-of-sequence iterator is not defined. For any other +iterator value a \tcode{const match_results*} is +returned. It is impossible to store things into \tcode{regex_iterator}s. Two +end-of-sequence iterators are always equal. An end-of-sequence +iterator is not equal to a non-end-of-sequence iterator. Two +non-end-of-sequence iterators are equal when they are constructed from +the same arguments. + +\begin{codeblock} +namespace std { + template::value_type, + class traits = regex_traits> + class regex_iterator { + public: + using regex_type = basic_regex; + using iterator_category = forward_iterator_tag; + using iterator_concept = input_iterator_tag; + using value_type = match_results; + using difference_type = ptrdiff_t; + using pointer = const value_type*; + using reference = const value_type&; + + regex_iterator(); + regex_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + regex_constants::match_flag_type m = regex_constants::match_default); + regex_iterator(BidirectionalIterator, BidirectionalIterator, + const regex_type&&, + regex_constants::match_flag_type = regex_constants::match_default) = delete; + regex_iterator(const regex_iterator&); + regex_iterator& operator=(const regex_iterator&); + bool operator==(const regex_iterator&) const; + bool operator==(default_sentinel_t) const { return *this == regex_iterator(); } + const value_type& operator*() const; + const value_type* operator->() const; + regex_iterator& operator++(); + regex_iterator operator++(int); + + private: + BidirectionalIterator begin; // \expos + BidirectionalIterator end; // \expos + const regex_type* pregex; // \expos + regex_constants::match_flag_type flags; // \expos + match_results match; // \expos + }; +} +\end{codeblock} + +\pnum +An object of type \tcode{regex_iterator} that is not an end-of-sequence iterator +holds a \textit{zero-length match} if \tcode{match[0].matched == true} and +\tcode{match[0].first == match[0].second}. +\begin{note} +For +example, this can occur when the part of the regular expression that +matched consists only of an assertion (such as \verb|'^'|, \verb|'$'|, +\tcode{'$\backslash$b'}, \tcode{'$\backslash$B'}). +\end{note} + +\rSec4[re.regiter.cnstr]{Constructors} + +\indexlibraryctor{regex_iterator}% +\begin{itemdecl} +regex_iterator(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an end-of-sequence iterator. +\end{itemdescr} + +\indexlibraryctor{regex_iterator}% +\begin{itemdecl} +regex_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + regex_constants::match_flag_type m = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{begin} and \tcode{end} to +\tcode{a} and \tcode{b}, respectively, sets +\tcode{pregex} to \tcode{addressof(re)}, sets \tcode{flags} to +\tcode{m}, then calls \tcode{regex_search(begin, end, match, *pregex, flags)}. If this +call returns \tcode{false} the constructor sets \tcode{*this} to the end-of-sequence +iterator. +\end{itemdescr} + +\rSec4[re.regiter.comp]{Comparisons} + +\indexlibrarymember{regex_iterator}{operator==}% +\begin{itemdecl} +bool operator==(const regex_iterator& right) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{*this} and \tcode{right} are both end-of-sequence +iterators or if the following conditions all hold: +\begin{itemize} +\item \tcode{begin == right.begin}, +\item \tcode{end == right.end}, +\item \tcode{pregex == right.pregex}, +\item \tcode{flags == right.flags}, and +\item \tcode{match[0] == right.match[0]}; +\end{itemize} +otherwise \tcode{false}. +\end{itemdescr} + +\rSec4[re.regiter.deref]{Indirection} + +\indexlibrarymember{regex_iterator}{operator*}% +\begin{itemdecl} +const value_type& operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{match}. +\end{itemdescr} + +\indexlibrarymember{operator->}{regex_iterator}% +\begin{itemdecl} +const value_type* operator->() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{addressof(match)}. +\end{itemdescr} + +\rSec4[re.regiter.incr]{Increment} + +\indexlibrarymember{regex_iterator}{operator++}% +\indexlibrary{\idxcode{regex_iterator}!increment}% +\begin{itemdecl} +regex_iterator& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a local variable \tcode{start} of type \tcode{BidirectionalIterator} and +initializes it with the value of \tcode{match[0].second}. + +\pnum +If the iterator holds a zero-length match and \tcode{start == end} the operator +sets \tcode{*this} to the end-of-sequence iterator and returns \tcode{*this}. + +\pnum +\indexlibraryglobal{match_not_null}% +\indexlibraryglobal{match_continuous}% +Otherwise, if the iterator holds a zero-length match, the operator calls: +\begin{codeblock} +regex_search(start, end, match, *pregex, + flags | regex_constants::match_not_null | regex_constants::match_continuous) +\end{codeblock} +If the call returns \tcode{true} the operator +returns \tcode{*this}. Otherwise the operator increments \tcode{start} and continues as if +the most recent match was not a zero-length match. + +\pnum +\indexlibraryglobal{match_prev_avail}% +If the most recent match was not a zero-length match, the operator sets +\tcode{flags} to \tcode{flags | regex_constants::match_prev_avail} and +calls \tcode{regex_search(start, end, match, *pregex, flags)}. If the call returns +\tcode{false} the iterator sets \tcode{*this} to the end-of-sequence iterator. The +iterator then returns \tcode{*this}. + +\pnum +In all cases in which the call to \tcode{regex_search} returns \tcode{true}, +\tcode{match.prefix().first} shall be equal to the previous value of +\tcode{match[0].second}, and for each index \tcode{i} in the half-open range +\range{0}{match.size()} for which \tcode{match[i].matched} is \tcode{true}, +\tcode{match.position(i)} +shall return \tcode{distance(begin, match[i].\brk{}first)}. + +\pnum +\begin{note} +This means that \tcode{match.position(i)} gives the +offset from the beginning of the target sequence, which is often not +the same as the offset from the sequence passed in the call +to \tcode{regex_search}. +\end{note} + +\pnum +It is unspecified how the implementation makes these adjustments. + +\pnum +\begin{note} +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. +\end{note} +\end{itemdescr} + +\indexlibrarymember{regex_iterator}{operator++}% +\begin{itemdecl} +regex_iterator operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +As if by: +\begin{codeblock} +regex_iterator tmp = *this; +++(*this); +return tmp; +\end{codeblock} +\end{itemdescr} + +\rSec3[re.tokiter]{Class template \tcode{regex_token_iterator}} + +\rSec4[re.tokiter.general]{General} + +\pnum +\indexlibraryglobal{regex_token_iterator}% +The class template \tcode{regex_token_iterator} is an iterator adaptor; that +is to say it represents a new view of an existing iterator sequence, +by enumerating all the occurrences of a regular expression within that +sequence, and presenting one or more sub-expressions for each match +found. Each position enumerated by the iterator is a \tcode{sub_match} class +template instance that represents what matched a particular sub-expression +within the regular expression. + +\pnum +When class \tcode{regex_token_iterator} is used to enumerate a +single sub-expression with index $-1$ the iterator performs field +splitting: that is to say it enumerates one sub-expression for each section of +the character container sequence that does not match the regular +expression specified. + +\pnum +\indexlibraryglobal{match_results}% +After it is constructed, the iterator finds and stores a value +\tcode{regex_iterator position} +and sets the internal count \tcode{N} to zero. It also maintains a sequence +\tcode{subs} which contains a list of the sub-expressions which will be +enumerated. Every time \tcode{operator++} is used +the count \tcode{N} is incremented; if \tcode{N} exceeds or equals \tcode{subs.size()}, +then the iterator increments member \tcode{position} +and sets count \tcode{N} to zero. + +\pnum +If the end of sequence is reached (\tcode{position} is equal to the end of +sequence iterator), the iterator becomes equal to the end-of-sequence +iterator value, unless the sub-expression being enumerated has index $-1$, +in which case the iterator enumerates one last sub-expression that contains +all the characters from the end of the last regular expression match to the +end of the input sequence being enumerated, provided that this would not be an +empty sub-expression. + +\pnum +\indexlibrary{\idxcode{regex_token_iterator}!end-of-sequence}% +The default constructor constructs +an end-of-sequence iterator object, which is the only legitimate +iterator to be used for the end condition. The result of \tcode{operator*} on +an end-of-sequence iterator is not defined. For any other iterator value a +\tcode{const sub_match\&} is returned. +The result of \tcode{operator->} on an end-of-sequence iterator +is not defined. For any other iterator value a \tcode{const +sub_match*} is returned. + +\pnum +\indexlibrarymember{regex_token_iterator}{operator==}% +It is impossible to store things +into \tcode{regex_token_iterator}s. Two end-of-sequence iterators are always +equal. An end-of-sequence iterator is not equal to a +non-end-of-sequence iterator. Two non-end-of-sequence iterators are +equal when they are constructed from the same arguments. + +\begin{codeblock} +namespace std { + template::value_type, + class traits = regex_traits> + class regex_token_iterator { + public: + using regex_type = basic_regex; + using iterator_category = forward_iterator_tag; + using iterator_concept = input_iterator_tag; + using value_type = sub_match; + using difference_type = ptrdiff_t; + using pointer = const value_type*; + using reference = const value_type&; + + regex_token_iterator(); + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + int submatch = 0, + regex_constants::match_flag_type m = + regex_constants::match_default); + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + const vector& submatches, + regex_constants::match_flag_type m = + regex_constants::match_default); + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + initializer_list submatches, + regex_constants::match_flag_type m = + regex_constants::match_default); + template + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + const int (&submatches)[N], + regex_constants::match_flag_type m = + regex_constants::match_default); + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type&& re, + int submatch = 0, + regex_constants::match_flag_type m = + regex_constants::match_default) = delete; + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type&& re, + const vector& submatches, + regex_constants::match_flag_type m = + regex_constants::match_default) = delete; + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type&& re, + initializer_list submatches, + regex_constants::match_flag_type m = + regex_constants::match_default) = delete; + template + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type&& re, + const int (&submatches)[N], + regex_constants::match_flag_type m = + regex_constants::match_default) = delete; + regex_token_iterator(const regex_token_iterator&); + regex_token_iterator& operator=(const regex_token_iterator&); + bool operator==(const regex_token_iterator&) const; + bool operator==(default_sentinel_t) const { return *this == regex_token_iterator(); } + const value_type& operator*() const; + const value_type* operator->() const; + regex_token_iterator& operator++(); + regex_token_iterator operator++(int); + + private: + using position_iterator = + regex_iterator; // \expos + position_iterator position; // \expos + const value_type* result; // \expos + value_type suffix; // \expos + size_t N; // \expos + vector subs; // \expos + }; +} +\end{codeblock} + +\pnum +A \textit{suffix iterator} is a \tcode{regex_token_iterator} object +that points to a final sequence of characters at +the end of the target sequence. In a suffix iterator the +member \tcode{result} holds a pointer to the data +member \tcode{suffix}, the value of the member \tcode{suffix.match} +is \tcode{true}, \tcode{suffix.first} points to the beginning of the +final sequence, and \tcode{suffix.second} points to the end of the +final sequence. + +\pnum +\begin{note} +For a suffix iterator, data +member \tcode{suffix.first} is the same as the end of the last match +found, and \tcode{suffix\brk.second} is the same as the end of the target +sequence. +\end{note} + +\pnum +The \textit{current match} is \tcode{(*position).prefix()} if \tcode{subs[N] == -1}, or +\tcode{(*position)[subs[N]]} for any other value of \tcode{subs[N]}. + +\rSec4[re.tokiter.cnstr]{Constructors} + +\indexlibraryctor{regex_token_iterator}% +\begin{itemdecl} +regex_token_iterator(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs the end-of-sequence iterator. +\end{itemdescr} + +\indexlibraryctor{regex_token_iterator}% +\begin{itemdecl} +regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + int submatch = 0, + regex_constants::match_flag_type m = regex_constants::match_default); + +regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + const vector& submatches, + regex_constants::match_flag_type m = regex_constants::match_default); + +regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + initializer_list submatches, + regex_constants::match_flag_type m = regex_constants::match_default); + +template + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + const int (&submatches)[N], + regex_constants::match_flag_type m = regex_constants::match_default); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +Each of the initialization values of \tcode{submatches} is \tcode{>= -1}. + +\pnum +\effects +The first constructor initializes the member \tcode{subs} to hold the single +value \tcode{submatch}. +The second, third, and fourth constructors +initialize the member \tcode{subs} to hold a copy of the sequence of integer values +pointed to by the iterator range +\range{begin(submatches)}{end(submatches)}. + +\pnum +Each constructor then sets \tcode{N} to 0, and \tcode{position} to +\tcode{position_iterator(a, b, re, m)}. If \tcode{position} is not an +end-of-sequence iterator the constructor sets \tcode{result} to the +address of the current match. Otherwise if any of the values stored +in \tcode{subs} is equal to $-1$ the constructor sets \tcode{*this} to a suffix +iterator that points to the range \range{a}{b}, otherwise the constructor +sets \tcode{*this} to an end-of-sequence iterator. +\end{itemdescr} + +\rSec4[re.tokiter.comp]{Comparisons} + +\indexlibrarymember{regex_token_iterator}{operator==}% +\begin{itemdecl} +bool operator==(const regex_token_iterator& right) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{*this} and \tcode{right} are both end-of-sequence iterators, +or if \tcode{*this} and \tcode{right} are both suffix iterators and \tcode{suffix == right.suffix}; +otherwise returns \tcode{false} if \tcode{*this} or \tcode{right} is an end-of-sequence +iterator or a suffix iterator. Otherwise returns \tcode{true} if \tcode{position == right.position}, +\tcode{N == right.N}, and \tcode{subs == right.subs}. Otherwise returns \tcode{false}. +\end{itemdescr} + +\rSec4[re.tokiter.deref]{Indirection} + +\indexlibrarymember{regex_token_iterator}{operator*}% +\begin{itemdecl} +const value_type& operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{*result}. +\end{itemdescr} + +\indexlibrarymember{operator->}{regex_token_iterator}% +\begin{itemdecl} +const value_type* operator->() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{result}. +\end{itemdescr} + + +\rSec4[re.tokiter.incr]{Increment} + +\indexlibrarymember{regex_token_iterator}{operator++}% +\begin{itemdecl} +regex_token_iterator& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a local variable \tcode{prev} of +type \tcode{position_iterator}, initialized with the value +of \tcode{position}. + +\pnum +If \tcode{*this} is a suffix iterator, sets \tcode{*this} to an +end-of-sequence iterator. + +\pnum +Otherwise, if \tcode{N + 1 < subs.size()}, increments \tcode{N} and +sets \tcode{result} to the address of the current match. + +\pnum +Otherwise, sets \tcode{N} to 0 and +increments \tcode{position}. If \tcode{position} is not an +end-of-sequence iterator the operator sets \tcode{result} to the +address of the current match. + +\pnum +Otherwise, if any of the values stored in \tcode{subs} is equal to $-1$ and +\tcode{prev->suffix().length()} is not 0 the operator sets \tcode{*this} to a +suffix iterator that points to the range \range{prev->suffix().first}{prev->suffix().second}. + +\pnum +Otherwise, sets \tcode{*this} to an end-of-sequence iterator. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{regex_token_iterator}{operator++}% +\begin{itemdecl} +regex_token_iterator& operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a copy \tcode{tmp} of \tcode{*this}, then calls \tcode{++(*this)}. + +\pnum +\returns +\tcode{tmp}. +\end{itemdescr} + +\rSec2[re.grammar]{Modified ECMAScript regular expression grammar} +\indextext{regular expression!grammar}% +\indextext{grammar!regular expression}% + +\pnum +\indexlibraryglobal{basic_regex}% +\indextext{ECMAScript}% +The regular expression grammar recognized by +\tcode{basic_regex} objects constructed with the ECMAScript +flag is that specified by ECMA-262, except as specified below. + +\pnum +\indexlibraryglobal{locale}% +\indextext{regular expression traits}% +Objects of type specialization of \tcode{basic_regex} store within themselves a +default-constructed instance of their \tcode{traits} template parameter, henceforth +referred to as \tcode{traits_inst}. This \tcode{traits_inst} object is used to support localization +of the regular expression; \tcode{basic_regex} member functions shall not call +any locale dependent C or \Cpp{} API, including the formatted string input functions. +Instead they shall call the appropriate traits member function to achieve the required effect. + +\pnum +The following productions within the ECMAScript grammar are modified as follows: + +\begin{ncrebnf} +\renontermdef{ClassAtom}\br + \terminal{-}\br + ClassAtomNoDash\br + ClassAtomExClass\br + ClassAtomCollatingElement\br + ClassAtomEquivalence +\end{ncrebnf} + +\begin{ncrebnf} +\renontermdef{IdentityEscape}\br + SourceCharacter \textnormal{\textbf{but not}} \terminal{c} +\end{ncrebnf} + +\pnum +The following new productions are then added: + +\begin{ncrebnf} +\renontermdef{ClassAtomExClass}\br + \terminal{[:} ClassName \terminal{:]} +\end{ncrebnf} + +\begin{ncrebnf} +\renontermdef{ClassAtomCollatingElement}\br + \terminal{[.} ClassName \terminal{.]} +\end{ncrebnf} + +\begin{ncrebnf} +\renontermdef{ClassAtomEquivalence}\br + \terminal{[=} ClassName \terminal{=]} +\end{ncrebnf} + +\begin{ncrebnf} +\renontermdef{ClassName}\br + ClassNameCharacter\br + ClassNameCharacter ClassName +\end{ncrebnf} + +\begin{ncrebnf} +\renontermdef{ClassNameCharacter}\br + SourceCharacter \textnormal{\textbf{but not one of}} \terminal{.} \textnormal{\textbf{or}} \terminal{=} \textnormal{\textbf{or}} \terminal{:} +\end{ncrebnf} + +\pnum +The productions \regrammarterm{ClassAtomExClass}, \regrammarterm{ClassAtomCollatingElement} +and \regrammarterm{ClassAtomEquivalence} provide functionality +equivalent to that of the same features in regular expressions in POSIX. + +\pnum +The regular expression grammar may be modified by +any \tcode{regex_constants::syntax_option_type} flags specified when +constructing an object of type specialization of \tcode{basic_regex} +according to the rules in \tref{re.synopt}. + +\pnum +A \regrammarterm{ClassName} production, when used in \regrammarterm{ClassAtomExClass}, +is not valid if \tcode{traits_inst.lookup_classname} returns zero for +that name. The names recognized as valid \regrammarterm{ClassName}s are +determined by the type of the traits class, but at least the following +names shall be recognized: +\tcode{alnum}, \tcode{alpha}, \tcode{blank}, \tcode{cntrl}, \tcode{digit}, +\tcode{graph}, \tcode{lower}, \tcode{print}, \tcode{punct}, \tcode{space}, +\tcode{upper}, \tcode{xdigit}, \tcode{d}, \tcode{s}, \tcode{w}. +In addition the following expressions shall be equivalent: + +\begin{codeblock} +\d @\textnormal{and}@ [[:digit:]] + +\D @\textnormal{and}@ [^[:digit:]] + +\s @\textnormal{and}@ [[:space:]] + +\S @\textnormal{and}@ [^[:space:]] + +\w @\textnormal{and}@ [_[:alnum:]] + +\W @\textnormal{and}@ [^_[:alnum:]] +\end{codeblock} + +\pnum +\indexlibrary{regular expression traits!\idxcode{lookup_collatename}}% +\indexlibrary{\idxcode{lookup_collatename}!regular expression traits}% +A \regrammarterm{ClassName} production when used in +a \regrammarterm{ClassAtomCollatingElement} production is not valid +if the value returned by \tcode{traits_inst.lookup_collatename} for +that name is an empty string. + +\pnum +\indexlibrary{regular expression traits!\idxcode{isctype}}% +\indexlibrary{\idxcode{isctype}!regular expression traits}% +\indexlibrary{regular expression traits!\idxcode{lookup_classname}}% +\indexlibrary{\idxcode{lookup_classname}!regular expression traits}% +The results from multiple calls +to \tcode{traits_inst.lookup_classname} can be bitwise \logop{or}'ed +together and subsequently passed to \tcode{traits_inst.isctype}. + +\pnum +A \regrammarterm{ClassName} production when used in +a \regrammarterm{ClassAtomEquivalence} production is not valid if the value +returned by \tcode{traits_inst.lookup_collatename} for that name is an +empty string or if the value returned by \tcode{traits_inst\brk.transform_primary} +for the result of the call to \tcode{traits_inst.lookup_collatename} +is an empty string. + +\pnum +\indexlibraryglobal{regex_error}% +When the sequence of characters being transformed to a finite state +machine contains an invalid class name the translator shall throw an +exception object of type \tcode{regex_error}. + +\pnum +\indexlibraryglobal{regex_error}% +If the \textit{CV} of a \textit{UnicodeEscapeSequence} is greater than the largest +value that can be held in an object of type \tcode{charT} the translator shall +throw an exception object of type \tcode{regex_error}. +\begin{note} +This means that values of the form \tcode{"\textbackslash{}uxxxx"} that do not fit in +a character are invalid. +\end{note} + +\pnum +Where the regular expression grammar requires the conversion of a sequence of characters +to an integral value, this is accomplished by calling \tcode{traits_inst.value}. + +\pnum +\indexlibraryglobal{match_flag_type}% +The behavior of the internal finite state machine representation when used to match a +sequence of characters is as described in ECMA-262. +The behavior is modified according +to any \tcode{match_flag_type} flags\iref{re.matchflag} specified when using the regular expression +object in one of the regular expression algorithms\iref{re.alg}. The behavior is also +localized by interaction with the traits class template parameter as follows: +\begin{itemize} +\item During matching of a regular expression finite state machine +against a sequence of characters, two characters \tcode{c} +and \tcode{d} are compared using the following rules: +\begin{itemize} +\item if \tcode{(flags() \& regex_constants::icase)} the two characters are equal +if \tcode{traits_inst.trans\-late_nocase(c) == traits_inst.translate_nocase(d)}; +\item otherwise, if \tcode{flags() \& regex_constants::collate} the +two characters are equal if +\tcode{traits_inst\brk.translate(c) == traits_inst\brk.translate(d)}; +\indexlibrarymember{syntax_option_type}{collate}% +\item otherwise, the two characters are equal if \tcode{c == d}. +\end{itemize} + +\item During matching of a regular expression finite state machine +against a sequence of characters, comparison of a collating element +range \tcode{c1-c2} against a character \tcode{c} is +conducted as follows: if \tcode{flags() \& regex_constants::collate} +is \tcode{false} then the character \tcode{c} is matched if \tcode{c1 +<= c \&\& c <= c2}, otherwise \tcode{c} is matched in +accordance with the following algorithm: + +\begin{codeblock} +string_type str1 = string_type(1, + flags() & icase ? + traits_inst.translate_nocase(c1) : traits_inst.translate(c1)); +string_type str2 = string_type(1, + flags() & icase ? + traits_inst.translate_nocase(c2) : traits_inst.translate(c2)); +string_type str = string_type(1, + flags() & icase ? + traits_inst.translate_nocase(c) : traits_inst.translate(c)); +return traits_inst.transform(str1.begin(), str1.end()) + <= traits_inst.transform(str.begin(), str.end()) + && traits_inst.transform(str.begin(), str.end()) + <= traits_inst.transform(str2.begin(), str2.end()); +\end{codeblock} + +\item During matching of a regular expression finite state machine against a sequence of +characters, testing whether a collating element is a member of a primary equivalence +class is conducted by first converting the collating element and the equivalence +class to sort keys using \tcode{traits::transform_primary}, and then comparing the sort +keys for equality. +\indextext{regular expression traits!\idxcode{transform_primary}}% +\indextext{transform_primary@\tcode{transform_primary}!regular expression traits}% + +\item During matching of a regular expression finite state machine against a sequence +of characters, a character \tcode{c} is a member of a character class designated by an +iterator range \range{first}{last} if +\tcode{traits_inst.isctype(c, traits_inst.lookup_classname(first, last, flags() \& icase))} is \tcode{true}. +\end{itemize} +\xref{ECMA-262 15.10} +\indextext{regular expression|)} + +\rSec1[text.c.strings]{Null-terminated sequence utilities} + +\rSec2[cctype.syn]{Header \tcode{} synopsis} + +\indexlibraryglobal{isalnum}% +\indexlibraryglobal{isalpha}% +\indexlibraryglobal{isblank}% +\indexlibraryglobal{iscntrl}% +\indexlibraryglobal{isdigit}% +\indexlibraryglobal{isgraph}% +\indexlibraryglobal{islower}% +\indexlibraryglobal{isprint}% +\indexlibraryglobal{ispunct}% +\indexlibraryglobal{isspace}% +\indexlibraryglobal{isupper}% +\indexlibraryglobal{isxdigit}% +\indexlibraryglobal{tolower}% +\indexlibraryglobal{toupper}% +\begin{codeblock} +namespace std { + int isalnum(int c); + int isalpha(int c); + int isblank(int c); + int iscntrl(int c); + int isdigit(int c); + int isgraph(int c); + int islower(int c); + int isprint(int c); + int ispunct(int c); + int isspace(int c); + int isupper(int c); + int isxdigit(int c); + int tolower(int c); + int toupper(int c); +} +\end{codeblock} + +\pnum +The contents and meaning of the header \libheaderdef{cctype} +are the same as the C standard library header \libheader{ctype.h}. + +\xrefc{7.4} + +\rSec2[cwctype.syn]{Header \tcode{} synopsis} + +\indexlibraryglobal{wint_t}% +\indexlibraryglobal{wctrans_t}% +\indexlibraryglobal{wctype_t}% +\indexlibraryglobal{iswalnum}% +\indexlibraryglobal{iswalpha}% +\indexlibraryglobal{iswblank}% +\indexlibraryglobal{iswcntrl}% +\indexlibraryglobal{iswdigit}% +\indexlibraryglobal{iswgraph}% +\indexlibraryglobal{iswlower}% +\indexlibraryglobal{iswprint}% +\indexlibraryglobal{iswpunct}% +\indexlibraryglobal{iswspace}% +\indexlibraryglobal{iswupper}% +\indexlibraryglobal{iswxdigit}% +\indexlibraryglobal{iswctype}% +\indexlibraryglobal{wctype}% +\indexlibraryglobal{towlower}% +\indexlibraryglobal{towupper}% +\indexlibraryglobal{towctrans}% +\indexlibraryglobal{wctrans}% +\begin{codeblock} +namespace std { + using wint_t = @\seebelow@; + using wctrans_t = @\seebelow@; + using wctype_t = @\seebelow@; + + int iswalnum(wint_t wc); + int iswalpha(wint_t wc); + int iswblank(wint_t wc); + int iswcntrl(wint_t wc); + int iswdigit(wint_t wc); + int iswgraph(wint_t wc); + int iswlower(wint_t wc); + int iswprint(wint_t wc); + int iswpunct(wint_t wc); + int iswspace(wint_t wc); + int iswupper(wint_t wc); + int iswxdigit(wint_t wc); + int iswctype(wint_t wc, wctype_t desc); + wctype_t wctype(const char* property); + wint_t towlower(wint_t wc); + wint_t towupper(wint_t wc); + wint_t towctrans(wint_t wc, wctrans_t desc); + wctrans_t wctrans(const char* property); +} + +#define @\libmacro{WEOF}@ @\seebelow@ +\end{codeblock} + +\pnum +The contents and meaning of the header \libheaderdef{cwctype} +are the same as the C standard library header \libheader{wctype.h}. + +\xrefc{7.32} + +\rSec2[cwchar.syn]{Header \tcode{} synopsis} + +\indexheader{cwchar}% +\indexlibraryglobal{btowc}% +\indexlibraryglobal{fgetwc}% +\indexlibraryglobal{fgetws}% +\indexlibraryglobal{fputwc}% +\indexlibraryglobal{fputws}% +\indexlibraryglobal{fwide}% +\indexlibraryglobal{fwprintf}% +\indexlibraryglobal{fwscanf}% +\indexlibraryglobal{getwchar}% +\indexlibraryglobal{getwc}% +\indexlibraryglobal{mbrlen}% +\indexlibraryglobal{mbrtowc}% +\indexlibraryglobal{mbsinit}% +\indexlibraryglobal{mbsrtowcs}% +\indexlibraryglobal{mbstate_t}% +\indexlibraryglobal{putwchar}% +\indexlibraryglobal{putwc}% +\indexlibraryglobal{size_t}% +\indexlibraryglobal{swprintf}% +\indexlibraryglobal{swscanf}% +\indexlibraryglobal{tm}% +\indexlibraryglobal{ungetwc}% +\indexlibraryglobal{vfwprintf}% +\indexlibraryglobal{vfwscanf}% +\indexlibraryglobal{vswprintf}% +\indexlibraryglobal{vswscanf}% +\indexlibraryglobal{vwprintf}% +\indexlibraryglobal{vwscanf}% +\indexlibraryglobal{wcrtomb}% +\indexlibraryglobal{wcscat}% +\indexlibraryglobal{wcschr}% +\indexlibraryglobal{wcscmp}% +\indexlibraryglobal{wcscoll}% +\indexlibraryglobal{wcscpy}% +\indexlibraryglobal{wcscspn}% +\indexlibraryglobal{wcsftime}% +\indexlibraryglobal{wcslen}% +\indexlibraryglobal{wcsncat}% +\indexlibraryglobal{wcsncmp}% +\indexlibraryglobal{wcsncpy}% +\indexlibraryglobal{wcspbrk}% +\indexlibraryglobal{wcsrchr}% +\indexlibraryglobal{wcsrtombs}% +\indexlibraryglobal{wcsspn}% +\indexlibraryglobal{wcsstr}% +\indexlibraryglobal{wcstod}% +\indexlibraryglobal{wcstof}% +\indexlibraryglobal{wcstok}% +\indexlibraryglobal{wcstold}% +\indexlibraryglobal{wcstoll}% +\indexlibraryglobal{wcstol}% +\indexlibraryglobal{wcstoull}% +\indexlibraryglobal{wcstoul}% +\indexlibraryglobal{wcsxfrm}% +\indexlibraryglobal{wctob}% +\indexlibraryglobal{wint_t}% +\indexlibraryglobal{wmemchr}% +\indexlibraryglobal{wmemcmp}% +\indexlibraryglobal{wmemcpy}% +\indexlibraryglobal{wmemmove}% +\indexlibraryglobal{wmemset}% +\indexlibraryglobal{wprintf}% +\indexlibraryglobal{wscanf}% +\begin{codeblock} +#define __STDC_VERSION_WCHAR_H__ 202311L + +namespace std { + using size_t = @\textit{see \ref{support.types.layout}}@; // freestanding + using mbstate_t = @\seebelow@; // freestanding + using wint_t = @\seebelow@; // freestanding + + struct tm; + + int fwprintf(FILE* stream, const wchar_t* format, ...); + int fwscanf(FILE* stream, const wchar_t* format, ...); + int swprintf(wchar_t* s, size_t n, const wchar_t* format, ...); + int swscanf(const wchar_t* s, const wchar_t* format, ...); + int vfwprintf(FILE* stream, const wchar_t* format, va_list arg); + int vfwscanf(FILE* stream, const wchar_t* format, va_list arg); + int vswprintf(wchar_t* s, size_t n, const wchar_t* format, va_list arg); + int vswscanf(const wchar_t* s, const wchar_t* format, va_list arg); + int vwprintf(const wchar_t* format, va_list arg); + int vwscanf(const wchar_t* format, va_list arg); + int wprintf(const wchar_t* format, ...); + int wscanf(const wchar_t* format, ...); + wint_t fgetwc(FILE* stream); + wchar_t* fgetws(wchar_t* s, int n, FILE* stream); + wint_t fputwc(wchar_t c, FILE* stream); + int fputws(const wchar_t* s, FILE* stream); + int fwide(FILE* stream, int mode); + wint_t getwc(FILE* stream); + wint_t getwchar(); + wint_t putwc(wchar_t c, FILE* stream); + wint_t putwchar(wchar_t c); + wint_t ungetwc(wint_t c, FILE* stream); + double wcstod(const wchar_t* nptr, wchar_t** endptr); + float wcstof(const wchar_t* nptr, wchar_t** endptr); + long double wcstold(const wchar_t* nptr, wchar_t** endptr); + long int wcstol(const wchar_t* nptr, wchar_t** endptr, int base); + long long int wcstoll(const wchar_t* nptr, wchar_t** endptr, int base); + unsigned long int wcstoul(const wchar_t* nptr, wchar_t** endptr, int base); + unsigned long long int wcstoull(const wchar_t* nptr, wchar_t** endptr, int base); + wchar_t* wcscpy(wchar_t* s1, const wchar_t* s2); // freestanding + wchar_t* wcsncpy(wchar_t* s1, const wchar_t* s2, size_t n); // freestanding + wchar_t* wmemcpy(wchar_t* s1, const wchar_t* s2, size_t n); // freestanding + wchar_t* wmemmove(wchar_t* s1, const wchar_t* s2, size_t n); // freestanding + wchar_t* wcscat(wchar_t* s1, const wchar_t* s2); // freestanding + wchar_t* wcsncat(wchar_t* s1, const wchar_t* s2, size_t n); // freestanding + int wcscmp(const wchar_t* s1, const wchar_t* s2); // freestanding + int wcscoll(const wchar_t* s1, const wchar_t* s2); + int wcsncmp(const wchar_t* s1, const wchar_t* s2, size_t n); // freestanding + size_t wcsxfrm(wchar_t* s1, const wchar_t* s2, size_t n); + int wmemcmp(const wchar_t* s1, const wchar_t* s2, size_t n); // freestanding + const wchar_t* wcschr(const wchar_t* s, wchar_t c); // freestanding; see \ref{library.c} + wchar_t* wcschr(wchar_t* s, wchar_t c); // freestanding; see \ref{library.c} + size_t wcscspn(const wchar_t* s1, const wchar_t* s2); // freestanding + const wchar_t* wcspbrk(const wchar_t* s1, const wchar_t* s2); // freestanding; see \ref{library.c} + wchar_t* wcspbrk(wchar_t* s1, const wchar_t* s2); // freestanding; see \ref{library.c} + const wchar_t* wcsrchr(const wchar_t* s, wchar_t c); // freestanding; see \ref{library.c} + wchar_t* wcsrchr(wchar_t* s, wchar_t c); // freestanding; see \ref{library.c} + size_t wcsspn(const wchar_t* s1, const wchar_t* s2); // freestanding + const wchar_t* wcsstr(const wchar_t* s1, const wchar_t* s2); // freestanding; see \ref{library.c} + wchar_t* wcsstr(wchar_t* s1, const wchar_t* s2); // freestanding; see \ref{library.c} + wchar_t* wcstok(wchar_t* s1, const wchar_t* s2, wchar_t** ptr); // freestanding + const wchar_t* wmemchr(const wchar_t* s, wchar_t c, size_t n); // freestanding; see \ref{library.c} + wchar_t* wmemchr(wchar_t* s, wchar_t c, size_t n); // freestanding; see \ref{library.c} + size_t wcslen(const wchar_t* s); // freestanding + wchar_t* wmemset(wchar_t* s, wchar_t c, size_t n); // freestanding + size_t wcsftime(wchar_t* s, size_t maxsize, const wchar_t* format, const tm* timeptr); + wint_t btowc(int c); + int wctob(wint_t c); + + // \ref{c.mb.wcs}, multibyte / wide string and character conversion functions + int mbsinit(const mbstate_t* ps); + size_t mbrlen(const char* s, size_t n, mbstate_t* ps); + size_t mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* ps); + size_t wcrtomb(char* s, wchar_t wc, mbstate_t* ps); + size_t mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* ps); + size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* ps); +} + +#define @\libmacro{NULL}@ @\textit{see \ref{support.types.nullptr}}@ // freestanding +#define @\libmacro{WCHAR_MAX}@ @\seebelow@ // freestanding +#define @\libmacro{WCHAR_MIN}@ @\seebelow@ // freestanding +#define @\libmacro{WEOF}@ @\seebelow@ // freestanding +#define @\libmacro{WCHAR_WIDTH}@ @\seebelow@ // freestanding +\end{codeblock} + +\pnum +The contents and meaning of the header \libheader{cwchar} +are the same as the C standard library header +\libheader{wchar.h}, except that it does not declare a type \keyword{wchar_t}. + +\pnum +\begin{note} +The functions +\tcode{wcschr}, \tcode{wcspbrk}, \tcode{wcsrchr}, \tcode{wcsstr}, and \tcode{wmemchr} +have different signatures in this document, +but they have the same behavior as in the C standard library\iref{library.c}. +\end{note} + +\xrefc{7.31} + +\rSec2[cuchar.syn]{Header \tcode{} synopsis} + +\indexlibraryglobal{mbstate_t}% +\indexlibraryglobal{size_t}% +\indexlibraryglobal{mbrtoc8}% +\indexlibraryglobal{c8rtomb}% +\indexlibraryglobal{mbrtoc16}% +\indexlibraryglobal{c16rtomb}% +\indexlibraryglobal{mbrtoc32}% +\indexlibraryglobal{c32rtomb}% +\begin{codeblock} +#define __STDC_VERSION_UCHAR_H__ 202311L + +namespace std { + using mbstate_t = @\seebelow@; + using size_t = @\textit{see \ref{support.types.layout}}@; + + size_t mbrtoc8(char8_t* pc8, const char* s, size_t n, mbstate_t* ps); + size_t c8rtomb(char* s, char8_t c8, mbstate_t* ps); + size_t mbrtoc16(char16_t* pc16, const char* s, size_t n, mbstate_t* ps); + size_t c16rtomb(char* s, char16_t c16, mbstate_t* ps); + size_t mbrtoc32(char32_t* pc32, const char* s, size_t n, mbstate_t* ps); + size_t c32rtomb(char* s, char32_t c32, mbstate_t* ps); +} +\end{codeblock} + +\pnum +The contents and meaning of the header \libheaderdef{cuchar} +are the same as the C standard library header \libheader{uchar.h}, +except that it does not declare types +\keyword{char8_t}, \keyword{char16_t}, or \keyword{char32_t}. + +\xrefc{7.30} + +\rSec2[c.mb.wcs]{Multibyte / wide string and character conversion functions} + +\pnum +\begin{note} +The headers \libheaderref{cstdlib}, +\libheaderref{cuchar}, +and \libheaderref{cwchar} +declare the functions described in this subclause. +\end{note} + +\indexlibraryglobal{mbsinit}% +\indexlibraryglobal{mblen}% +\indexlibraryglobal{mbstowcs}% +\indexlibraryglobal{wcstombs}% +\begin{itemdecl} +int mbsinit(const mbstate_t* ps); +int mblen(const char* s, size_t n); +size_t mbstowcs(wchar_t* pwcs, const char* s, size_t n); +size_t wcstombs(char* s, const wchar_t* pwcs, size_t n); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +These functions have the semantics specified in the C standard library. +\end{itemdescr} + +\xrefc{7.22.7.1, 7.22.8, 7.29.6.2.1} + +\indexlibraryglobal{mbtowc}% +\indexlibraryglobal{wctomb}% +\begin{itemdecl} +int mbtowc(wchar_t* pwc, const char* s, size_t n); +int wctomb(char* s, wchar_t wchar); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +These functions have the semantics specified in the C standard library. + +\pnum +\remarks +Calls to these functions +may introduce a data race\iref{res.on.data.races} +with other calls to the same function. +\end{itemdescr} + +\xrefc{7.22.7} + +\begin{itemdecl} +size_t @\libglobal{mbrlen}@(const char* s, size_t n, mbstate_t* ps); +size_t @\libglobal{mbrtowc}@(wchar_t* pwc, const char* s, size_t n, mbstate_t* ps); +size_t @\libglobal{wcrtomb}@(char* s, wchar_t wc, mbstate_t* ps); +size_t @\libglobal{mbrtoc8}@(char8_t* pc8, const char* s, size_t n, mbstate_t* ps); +size_t @\libglobal{c8rtomb}@(char* s, char8_t c8, mbstate_t* ps); +size_t @\libglobal{mbrtoc16}@(char16_t* pc16, const char* s, size_t n, mbstate_t* ps); +size_t @\libglobal{c16rtomb}@(char* s, char16_t c16, mbstate_t* ps); +size_t @\libglobal{mbrtoc32}@(char32_t* pc32, const char* s, size_t n, mbstate_t* ps); +size_t @\libglobal{c32rtomb}@(char* s, char32_t c32, mbstate_t* ps); +size_t @\libglobal{mbsrtowcs}@(wchar_t* dst, const char** src, size_t len, mbstate_t* ps); +size_t @\libglobal{wcsrtombs}@(char* dst, const wchar_t** src, size_t len, mbstate_t* ps); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +These functions have the semantics specified in the C standard library. + +\pnum +\remarks +Calling these functions +with an \tcode{mbstate_t*} argument that is a null pointer value +may introduce a data race\iref{res.on.data.races} +with other calls to the same function +with an \tcode{mbstate_t*} argument that is a null pointer value. +\end{itemdescr} + +\xrefc{7.30.1, 7.31.6.3, 7.31.6.4} diff --git a/source/threads.tex b/source/threads.tex index c628a8a0c7..9be4571b79 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -169,7 +169,7 @@ \rSec2[thread.req.lockable]{Requirements for \oldconcept{Lockable} types} -\rSec3[thread.req.lockable.general]{In general} +\rSec3[thread.req.lockable.general]{General} \pnum An \defn{execution agent} is an entity such as a thread that may perform work in parallel with @@ -230,7 +230,7 @@ \rSec3[thread.req.lockable.basic]{\oldconcept{BasicLockable} requirements} \pnum -A type \tcode{L} meets the \oldconcept{BasicLockable} requirements if the following expressions are +A type \tcode{L} meets the \defnoldconcept{BasicLockable} requirements if the following expressions are well-formed and have the specified semantics (\tcode{m} denotes a value of type \tcode{L}). \begin{itemdecl} @@ -266,7 +266,7 @@ \rSec3[thread.req.lockable.req]{\oldconcept{Lockable} requirements} \pnum -A type \tcode{L} meets the \oldconcept{Lockable} requirements if it meets the \oldconcept{BasicLockable} +A type \tcode{L} meets the \defnoldconcept{Lockable} requirements if it meets the \oldconcept{BasicLockable} requirements and the following expressions are well-formed and have the specified semantics (\tcode{m} denotes a value of type \tcode{L}). @@ -291,7 +291,7 @@ \rSec3[thread.req.lockable.timed]{\oldconcept{TimedLockable} requirements} \pnum -A type \tcode{L} meets the \oldconcept{TimedLockable} requirements if it meets the \oldconcept{Lockable} +A type \tcode{L} meets the \defnoldconcept{TimedLockable} requirements if it meets the \oldconcept{Lockable} requirements and the following expressions are well-formed and have the specified semantics (\tcode{m} denotes a value of type \tcode{L}, \tcode{rel_time} denotes a value of an instantiation of \tcode{duration}\iref{time.duration}, and \tcode{abs_time} denotes a value @@ -342,7 +342,7 @@ \rSec3[thread.req.lockable.shared]{\oldconcept{SharedLockable} requirements} \pnum -A type \tcode{L} meets the \oldconcept{SharedLockable} requirements if +A type \tcode{L} meets the \defnoldconcept{SharedLockable} requirements if the following expressions are well-formed, have the specified semantics, and the expression \tcode{m.try_lock_shared()} has type \tcode{bool} (\tcode{m} denotes a value of type \tcode{L}): @@ -396,7 +396,7 @@ \rSec3[thread.req.lockable.shared.timed]{\oldconcept{SharedTimedLockable} requirements} \pnum -A type \tcode{L} meets the \oldconcept{SharedTimedLockable} requirements if +A type \tcode{L} meets the \defnoldconcept{SharedTimedLockable} requirements if it meets the \oldconcept{SharedLockable} requirements, and the following expressions are well-formed, have type \tcode{bool}, and have the specified semantics @@ -453,46 +453,80 @@ Such a request is called a \defn{stop request}. \pnum -\tcode{stop_source}, \tcode{stop_token}, and \tcode{stop_callback} -implement semantics of shared ownership of a \defn{stop state}. -Any \tcode{stop_source}, \tcode{stop_token}, or \tcode{stop_callback} -that shares ownership of the same stop state is an \defn{associated} -\tcode{stop_source}, \tcode{stop_token}, or \tcode{stop_callback}, respectively. -The last remaining owner of the stop state automatically -releases the resources associated with the stop state. - -\pnum -A \tcode{stop_token} can be passed to an operation which can either +The concepts +\exposconcept{stoppable-source}, +\libconcept{stoppable_token}, and +\exposconcept{stoppable-callback-for} +specify the required syntax and semantics of +shared access to a \defn{stop state}. +Any object modeling \exposconcept{stoppable-source}, +\libconcept{stoppable_token}, or +\exposconcept{stoppable-callback-for} +that refers to the same stop state is +an \defn{associated} +\exposconcept{stoppable-source}, +\libconcept{stoppable_token}, or +\exposconcept{stoppable-callback-for}, +respectively. + +\pnum +An object of a type that models \libconcept{stoppable_token} +can be passed to an operation that can either \begin{itemize} \item actively poll the token to check if there has been a stop request, or - \item register a callback using the \tcode{stop_callback} class template which + \item register a callback that will be called in the event that a stop request is made. \end{itemize} -A stop request made via a \tcode{stop_source} will be visible to all -associated \tcode{stop_token} and \tcode{stop_source} objects. +A stop request made via an object +whose type models \exposconcept{stoppable-source} +will be visible to +all associated \libconcept{stoppable_token} and +\exposconcept{stoppable-source} objects. Once a stop request has been made it cannot be withdrawn (a subsequent stop request has no effect). \pnum -Callbacks registered via a \tcode{stop_callback} object are called when -a stop request is first made by any associated \tcode{stop_source} object. +Callbacks registered via an object +whose type models \exposconcept{stoppable-callback-for} +are called when a stop request is first made +by any associated \exposconcept{stoppable-source} object. \pnum -Calls to the functions \tcode{request_stop}, \tcode{stop_requested}, -and \tcode{stop_possible} -do not introduce data races. -A call to \tcode{request_stop} that returns \tcode{true} -synchronizes with a call to \tcode{stop_requested} -on an associated \tcode{stop_token} or \tcode{stop_source} object -that returns \tcode{true}. -Registration of a callback synchronizes with the invocation of that callback. +The types \tcode{stop_source} and \tcode{stop_token} and +the class template \tcode{stop_callback} implement +the semantics of shared ownership of a stop state. +The last remaining owner of the stop state automatically releases +the resources associated with the stop state. +\pnum +An object of type \tcode{inplace_stop_source} +is the sole owner of its stop state. +An object of type \tcode{inplace_stop_token} or +of a specialization of the class template \tcode{inplace_stop_callback} +does not participate in ownership of its associated stop state. +\begin{note} +They are for use when all uses of the associated token and callback objects +are known to nest within the lifetime of the \tcode{inplace_stop_source} object. +\end{note} \rSec2[thread.stoptoken.syn]{Header \tcode{} synopsis} \indexheader{stop_token}% \begin{codeblock} namespace std { + // \ref{stoptoken.concepts}, stop token concepts + template + concept @\exposconcept{stoppable-callback-for}@ = @\seebelow@; // \expos + + template + concept @\libconcept{stoppable_token}@ = @\seebelow@; + + template + concept @\libconcept{unstoppable_token}@ = @\seebelow@; + + template + concept @\exposconcept{stoppable-source}@ = @\seebelow@; // \expos + // \ref{stoptoken}, class \tcode{stop_token} class stop_token; @@ -508,136 +542,322 @@ // \ref{stopcallback}, class template \tcode{stop_callback} template class stop_callback; -} -\end{codeblock} - - -\rSec2[stoptoken]{Class \tcode{stop_token}}% -\indexlibraryglobal{stop_token}% -\rSec3[stoptoken.general]{General} + // \ref{stoptoken.never}, class \tcode{never_stop_token} + class never_stop_token; -\pnum -\indexlibraryglobal{stop_token}% -The class \tcode{stop_token} provides an interface for querying whether -a stop request has been made (\tcode{stop_requested}) -or can ever be made (\tcode{stop_possible}) -using an associated \tcode{stop_source} object\iref{stopsource}. -A \tcode{stop_token} can also be passed to a -\tcode{stop_callback}\iref{stopcallback} constructor -to register a callback to be called when a stop request has been made -from an associated \tcode{stop_source}. + // \ref{stoptoken.inplace}, class \tcode{inplace_stop_token} + class inplace_stop_token; -\begin{codeblock} -namespace std { - class stop_token { - public: - // \ref{stoptoken.cons}, constructors, copy, and assignment - stop_token() noexcept; - - stop_token(const stop_token&) noexcept; - stop_token(stop_token&&) noexcept; - stop_token& operator=(const stop_token&) noexcept; - stop_token& operator=(stop_token&&) noexcept; - ~stop_token(); - void swap(stop_token&) noexcept; + // \ref{stopsource.inplace}, class \tcode{inplace_stop_source} + class inplace_stop_source; - // \ref{stoptoken.mem}, stop handling - [[nodiscard]] bool stop_requested() const noexcept; - [[nodiscard]] bool stop_possible() const noexcept; + // \ref{stopcallback.inplace}, class template \tcode{inplace_stop_callback} + template + class inplace_stop_callback; - [[nodiscard]] friend bool operator==(const stop_token& lhs, const stop_token& rhs) noexcept; - friend void swap(stop_token& lhs, stop_token& rhs) noexcept; - }; + template + using stop_callback_for_t = T::template callback_type; } \end{codeblock} +\rSec2[stoptoken.concepts]{Stop token concepts} -\rSec3[stoptoken.cons]{Constructors, copy, and assignment} +\pnum +The exposition-only \exposconcept{stoppable-callback-for} concept +checks for a callback compatible with a given \tcode{Token} type. +\begin{codeblock} +template + concept @\defexposconcept{stoppable-callback-for}@ = // \expos + @\libconcept{invocable}@ && + @\libconcept{constructible_from}@ && + requires { typename stop_callback_for_t; } && + @\libconcept{constructible_from}@, const Token&, Initializer>; +\end{codeblock} -\indexlibraryctor{stop_token}% -\begin{itemdecl} -stop_token() noexcept; -\end{itemdecl} +\pnum +Let \tcode{t} and \tcode{u} be distinct, valid objects of type \tcode{Token} +that reference the same logical stop state; +let \tcode{init} be an expression such that +\tcode{\libconcept{same_as}} is \tcode{true}; and +let \tcode{SCB} denote the type \tcode{stop_callback_for_t}. -\begin{itemdescr} \pnum -\ensures -\tcode{stop_possible()} is \tcode{false} and -\tcode{stop_requested()} is \tcode{false}. +The concept +\tcode{\exposconcept{stoppable-callback-for}} +is modeled only if: +\begin{itemize} +\item +The following concepts are modeled: +\begin{itemize} +\item \tcode{\libconcept{constructible_from}} +\item \tcode{\libconcept{constructible_from}} +\item \tcode{\libconcept{constructible_from}} +\end{itemize} + +\item +An object of type \tcode{SCB} has +an associated callback function of type \tcode{CallbackFn}. +Let \tcode{scb} be an object of type \tcode{SCB} and +let \tcode{callback_fn} denote \tcode{scb's} associated callback function. +Direct-non-list-initializing \tcode{scb} from +arguments \tcode{t} and \tcode{init} +shall execute a \defnadj{stoppable callback}{registration} as follows: +\begin{itemize} +\item +If \tcode{t.stop_possible()} is \tcode{true}: +\begin{itemize} +\item +\tcode{callback_fn} shall be direct-initialized with \tcode{init}. +\item +Construction of \tcode{scb} shall only throw exceptions +thrown by the initialization of \tcode{callback_fn} from \tcode{init}. +\item +The callback invocation \tcode{std::forward(callback_fn)()} +shall be registered with \tcode{t}'s associated stop state as follows: +\begin{itemize} +\item +If \tcode{t.stop_requested()} evaluates to \tcode{false} +at the time of registration, +the callback invocation is added to the stop state's list of callbacks +such that \tcode{std::forward(\newline callback_fn)()} is evaluated +if a stop request is made on the stop state. +\item +Otherwise, \tcode{std::forward(callback_fn)()} +shall be immediately evaluated +on the thread executing \tcode{scb}'s constructor, and +the callback invocation shall not be added to the list of callback invocations. +\end{itemize} +If the callback invocation was added to stop state's list of callbacks, +\tcode{scb} shall be associated with the stop state. +\end{itemize} +\item \begin{note} -Because the created \tcode{stop_token} object can never receive a stop request, -no resources are allocated for a stop state. +If \tcode{t.stop_possible()} is \tcode{false}, +there is no requirement +that the initialization of \tcode{scb} +causes the initialization of \tcode{callback_fn}. \end{note} -\end{itemdescr} +\end{itemize} -\indexlibraryctor{stop_token}% -\begin{itemdecl} -stop_token(const stop_token& rhs) noexcept; -\end{itemdecl} +\item +Destruction of \tcode{scb} shall execute +a \defnadj{stoppable}{callback deregistration} as follows (in order): +\begin{itemize} +\item +If the constructor of \tcode{scb} did not register +a callback invocation with \tcode{t}'s stop state, +then the stoppable callback deregistration shall have no effect +other than destroying \tcode{callback_fn} if it was constructed. +\item +Otherwise, the invocation of \tcode{callback_fn} shall be removed +from the associated stop state. +\item +If \tcode{callback_fn} is concurrently executing on another thread, +then the stoppable callback deregistration shall block\iref{defns.block} +until the invocation of \tcode{callback_fn} returns +such that the return from the invocation of \tcode{callback_fn} +strongly happens before\iref{intro.races} +the destruction of \tcode{callback_fn}. +\item +If \tcode{callback_fn} is executing on the current thread, +then the destructor shall not block +waiting for the return from the invocation of \tcode{callback_fn}. +\item +A stoppable callback deregistration shall not block +on the completion of the invocation of some other callback +registered with the same logical stop state. +\item +The stoppable callback deregistration shall destroy \tcode{callback_fn}. +\end{itemize} +\end{itemize} -\begin{itemdescr} \pnum -\ensures -\tcode{*this == rhs} is \tcode{true}. -\begin{note} -\tcode{*this} and \tcode{rhs} share the ownership of the same stop state, -if any. -\end{note} -\end{itemdescr} +The \libconcept{stoppable_token} concept checks +for the basic interface of a stop token +that is copyable and allows polling to see if stop has been requested and +also whether a stop request is possible. +The \libconcept{unstoppable_token} concept checks +for a \libconcept{stoppable_token} type that does not allow stopping. +\begin{codeblock} +template class> + struct @\exposid{check-type-alias-exists}@; // \expos + +template + concept @\deflibconcept{stoppable_token}@ = + requires (const Token tok) { + typename @\exposid{check-type-alias-exists}@; + { tok.stop_requested() } noexcept -> @\libconcept{same_as}@; + { tok.stop_possible() } noexcept -> @\libconcept{same_as}@; + { Token(tok) } noexcept; // see implicit expression variations\iref{concepts.equality} + } && + @\libconcept{copyable}@ && + @\libconcept{equality_comparable}@; + +template + concept @\deflibconcept{unstoppable_token}@ = + @\libconcept{stoppable_token}@ && + requires (const Token tok) { + requires bool_constant<(!tok.stop_possible())>::value; + }; +\end{codeblock} -\indexlibraryctor{stop_token}% -\begin{itemdecl} -stop_token(stop_token&& rhs) noexcept; -\end{itemdecl} -\begin{itemdescr} \pnum -\ensures -\tcode{*this} contains the value of \tcode{rhs} -prior to the start of construction -and \tcode{rhs.stop_possible()} is \tcode{false}. -\end{itemdescr} +An object whose type models \libconcept{stoppable_token} +has at most one associated logical stop state. +A \libconcept{stoppable_token} object with no associated stop state +is said to be \defn{disengaged}. -\indexlibrarydtor{stop_token}% -\begin{itemdecl} -~stop_token(); -\end{itemdecl} +\pnum +Let \tcode{SP} be an evaluation of \tcode{t.stop_possible()} +that is \tcode{false}, and +let SR be an evaluation of \tcode{t.stop_requested()} that is \tcode{true}. -\begin{itemdescr} \pnum -\effects -Releases ownership of the stop state, if any. -\end{itemdescr} +The type \tcode{Token} models \libconcept{stoppable_token} only if: +\begin{itemize} +\item +Any evaluation of \tcode{u.stop_possible()} or \tcode{u.stop_requested()} +that happens after\iref{intro.races} \tcode{SP} is \tcode{false}. +\item +Any evaluation of \tcode{u.stop_possible()} or \tcode{u.stop_requested()} +that happens after \tcode{SR} is \tcode{true}. +\item +For any types \tcode{CallbackFn} and \tcode{Initializer} such that +\tcode{\exposconcept{stoppable-callback-for}} +is satisfied, +\tcode{\exposconcept{stoppable-callback-for}} +is modeled. +\item +If \tcode{t} is disengaged, +evaluations of \tcode{t.stop_possible()} and \tcode{t.stop_requested()} +are \tcode{false}. +\item +If \tcode{t} and \tcode{u} reference the same stop state, or +if both \tcode{t} and \tcode{u} are disengaged, +\tcode{t == u} is \tcode{true}; otherwise, it is \tcode{false}. +\end{itemize} -\indexlibrarymember{operator=}{stop_token}% -\begin{itemdecl} -stop_token& operator=(const stop_token& rhs) noexcept; -\end{itemdecl} +\pnum +An object +whose type models the exposition-only \exposconcept{stoppable-source} concept +can be queried +whether stop has been requested (\tcode{stop_requested}) and +whether stop is possible (\tcode{stop_possible}). +It is a factory for associated stop tokens (\tcode{get_token}), and +a stop request can be made on it (\tcode{request_stop}). +It maintains a list of registered stop callback invocations +that it executes when a stop request is first made. +\begin{codeblock} +template + concept @\defexposconcept{stoppable-source}@ = // \expos + requires (Source& src, const Source csrc) { // see implicit expression variations\iref{concepts.equality} + { csrc.get_token() } -> stoppable_token; + { csrc.stop_possible() } noexcept -> @\libconcept{same_as}@; + { csrc.stop_requested() } noexcept -> @\libconcept{same_as}@; + { src.request_stop() } -> @\libconcept{same_as}@; + }; +\end{codeblock} -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{stop_token(rhs).swap(*this)}. +An object whose type models \exposconcept{stoppable-source} has +at most one associated logical stop state. +If it has no associated stop state, it is said to be disengaged. +Let \tcode{s} be an object whose type models \exposconcept{stoppable-source} and +that is disengaged. +\tcode{s.stop_possible()} and \tcode{s.stop_requested()} shall be \tcode{false}. \pnum -\returns -\tcode{*this}. -\end{itemdescr} +Let \tcode{t} be an object whose type models \exposconcept{stoppable-source}. +If \tcode{t} is disengaged, +\tcode{t.get_token()} shall return a disengaged stop token; +otherwise, it shall return +a stop token that is associated with the stop state of \tcode{t}. -\indexlibrarymember{operator=}{stop_token}% -\begin{itemdecl} -stop_token& operator=(stop_token&& rhs) noexcept; -\end{itemdecl} +\pnum +Calls to the member functions +\tcode{request_stop}, \tcode{stop_requested}, and \tcode{stop_possible} and +similarly named member functions +on associated \libconcept{stoppable_token} objects +do not introduce data races. +A call to \tcode{request_stop} that returns \tcode{true} synchronizes with +a call to \tcode{stop_requested} on +an associated +\libconcept{stoppable_token} or \exposconcept{stoppable-source} object +that returns \tcode{true}. +Registration of a callback synchronizes with the invocation of that callback. -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{stop_token(std::move(rhs)).swap(*this)}. +If the \exposconcept{stoppable-source} is disengaged, +\tcode{request_stop} shall have no effect and return \tcode{false}. +Otherwise, it shall execute a \defnadj{stop request}{operation} +on the associated stop state. +A stop request operation determines +whether the stop state has received a stop request, and +if not, makes a stop request. +The determination and making of the stop request shall happen atomically, +as-if by a read-modify-write operation\iref{intro.races}. +If the request was made, +the stop state's registered callback invocations shall be +synchronously executed. +If an invocation of a callback exits via an exception +then \tcode{terminate} shall be invoked\iref{except.terminate}. +\begin{note} +No constraint is placed on the order +in which the callback invocations are executed. +\end{note} +\tcode{request_stop} shall return \tcode{true} if a stop request was made, and +\tcode{false} otherwise. +After a call to \tcode{request_stop} either +a call to \tcode{stop_possible} shall return \tcode{false} or +a call to \tcode{stop_requested} shall return \tcode{true}. +\begin{note} +A stop request includes notifying +all condition variables of type \tcode{condition_variable_any} +temporarily registered during +an interruptible wait\iref{thread.condvarany.intwait}. +\end{note} + +\rSec2[stoptoken]{Class \tcode{stop_token}}% +\indexlibraryglobal{stop_token}% + +\rSec3[stoptoken.general]{General} \pnum -\returns -\tcode{*this}. -\end{itemdescr} +\indexlibraryglobal{stop_token}% +The class \tcode{stop_token} models the concept \libconcept{stoppable_token}. +It shares ownership of its stop state, if any, +with its associated \tcode{stop_source} object\iref{stopsource} and +any \tcode{stop_token} objects to which it compares equal. + +\begin{codeblock} +namespace std { + class stop_token { + public: + template + using callback_type = stop_callback; + + stop_token() noexcept = default; + + // \ref{stoptoken.mem}, member functions + void swap(stop_token&) noexcept; + + bool stop_requested() const noexcept; + bool stop_possible() const noexcept; + + bool operator==(const stop_token& rhs) noexcept = default; + + private: + shared_ptr<@\unspec@> @\exposid{stop-state}@; // \expos + }; +} +\end{codeblock} + +\pnum +\exposid{stop-state} refers to the \tcode{stop_token}'s associated stop state. +A \tcode{stop_token} object is disengaged when \exposid{stop-state} is empty. + +\rSec3[stoptoken.mem]{Member functions} \indexlibrarymember{swap}{stop_token}% \begin{itemdecl} @@ -647,117 +867,82 @@ \begin{itemdescr} \pnum \effects -Exchanges the values of \tcode{*this} and \tcode{rhs}. +Equivalent to: +\begin{codeblock} +@\exposid{stop-state}@.swap(rhs.@\exposid{stop-state}@); +\end{codeblock} \end{itemdescr} -\rSec3[stoptoken.mem]{Members} - \indexlibrarymember{stop_requested}{stop_token}% \begin{itemdecl} -[[nodiscard]] bool stop_requested() const noexcept; +bool stop_requested() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{true} if \tcode{*this} has ownership of a stop state +\tcode{true} if \exposid{stop-state} refers to a stop state that has received a stop request; otherwise, \tcode{false}. \end{itemdescr} \indexlibrarymember{stop_possible}{stop_token}% \begin{itemdecl} -[[nodiscard]] bool stop_possible() const noexcept; +bool stop_possible() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{false} if: +\tcode{false} if \begin{itemize} -\item \tcode{*this} does not have ownership of a stop state, or +\item \tcode{*this} is disengaged, or \item a stop request was not made and there are no associated \tcode{stop_source} objects; \end{itemize} otherwise, \tcode{true}. \end{itemdescr} -\rSec3[stoptoken.nonmembers]{Non-member functions} - -\indexlibrarymember{operator==}{stop_token}% -\begin{itemdecl} -[[nodiscard]] bool operator==(const stop_token& lhs, const stop_token& rhs) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if \tcode{lhs} and \tcode{rhs} have ownership of the same stop state -or if both \tcode{lhs} and \tcode{rhs} do not have ownership of a stop state; -otherwise \tcode{false}. -\end{itemdescr} - -\indexlibrarymember{swap}{stop_token}% -\begin{itemdecl} -friend void swap(stop_token& x, stop_token& y) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{x.swap(y)}. -\end{itemdescr} - \rSec2[stopsource]{Class \tcode{stop_source}}% \indexlibraryglobal{stop_source}% \rSec3[stopsource.general]{General} -\pnum -\indexlibraryglobal{stop_source}% -The class \tcode{stop_source} implements the semantics of making a stop request. -A stop request made on a \tcode{stop_source} object is visible to all -associated \tcode{stop_source} and \tcode{stop_token}\iref{stoptoken} objects. -Once a stop request has been made it cannot be withdrawn -(a subsequent stop request has no effect). - -\indexlibraryglobal{nostopstate_t}% -\indexlibraryglobal{nostopstate}% - \begin{codeblock} namespace std { - // no-shared-stop-state indicator - struct nostopstate_t { - explicit nostopstate_t() = default; - }; - inline constexpr nostopstate_t nostopstate{}; - class stop_source { public: // \ref{stopsource.cons}, constructors, copy, and assignment stop_source(); - explicit stop_source(nostopstate_t) noexcept; + explicit stop_source(nostopstate_t) noexcept {} - stop_source(const stop_source&) noexcept; - stop_source(stop_source&&) noexcept; - stop_source& operator=(const stop_source&) noexcept; - stop_source& operator=(stop_source&&) noexcept; - ~stop_source(); + // \ref{stopsource.mem}, member functions void swap(stop_source&) noexcept; - // \ref{stopsource.mem}, stop handling - [[nodiscard]] stop_token get_token() const noexcept; - [[nodiscard]] bool stop_possible() const noexcept; - [[nodiscard]] bool stop_requested() const noexcept; + stop_token get_token() const noexcept; + bool stop_possible() const noexcept; + bool stop_requested() const noexcept; bool request_stop() noexcept; - [[nodiscard]] friend bool - operator==(const stop_source& lhs, const stop_source& rhs) noexcept; - friend void swap(stop_source& lhs, stop_source& rhs) noexcept; + bool operator==(const stop_source& rhs) noexcept = default; + + private: + shared_ptr<@\unspec@> @\exposid{stop-state}@; // \expos }; } \end{codeblock} +\pnum +\exposid{stop-state} refers to the \tcode{stop_source}'s associated stop state. +A \tcode{stop_source} object is disengaged when \exposid{stop-state} is empty. + +\pnum +\tcode{stop_source} models +\exposconcept{stoppable-source}, +\libconcept{copyable}, +\libconcept{equality_comparable}, and +\libconcept{swappable}. + \rSec3[stopsource.cons]{Constructors, copy, and assignment} \indexlibraryctor{stop_source}% @@ -768,7 +953,7 @@ \begin{itemdescr} \pnum \effects -Initialises \tcode{*this} to have ownership of a new stop state. +Initializes \exposid{stop-state} with a pointer to a new stop state. \pnum \ensures @@ -780,324 +965,439 @@ \tcode{bad_alloc} if memory cannot be allocated for the stop state. \end{itemdescr} -\indexlibraryctor{stop_source}% +\rSec3[stopsource.mem]{Member functions} + +\indexlibrarymember{swap}{stop_source}% \begin{itemdecl} -explicit stop_source(nostopstate_t) noexcept; +void swap(stop_source& rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{stop_possible()} is \tcode{false} and -\tcode{stop_requested()} is \tcode{false}. -\begin{note} -No resources are allocated for the state. -\end{note} +\effects +Equivalent to: +\begin{codeblock} +@\exposid{stop-state}@.swap(rhs.@\exposid{stop-state}@); +\end{codeblock} \end{itemdescr} -\indexlibraryctor{stop_source}% +\indexlibrarymember{get_token}{stop_source}% \begin{itemdecl} -stop_source(const stop_source& rhs) noexcept; +stop_token get_token() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{*this == rhs} is \tcode{true}. -\begin{note} -\tcode{*this} and \tcode{rhs} share the ownership of the same stop state, -if any. -\end{note} +\returns +\tcode{stop_token()} if \tcode{stop_possible()} is \tcode{false}; +otherwise a new associated \tcode{stop_token} object; +i.e., its \exposid{stop-state} member is equal to +the \exposid{stop-state} member of \tcode{*this}. \end{itemdescr} -\indexlibraryctor{stop_source}% +\indexlibrarymember{stop_possible}{stop_source}% \begin{itemdecl} -stop_source(stop_source&& rhs) noexcept; +bool stop_possible() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{*this} contains the value of \tcode{rhs} -prior to the start of construction -and \tcode{rhs.stop_possible()} is \tcode{false}. +\returns +\tcode{\exposidnc{stop-state} != nullptr}. \end{itemdescr} -\indexlibrarydtor{stop_source}% +\indexlibrarymember{stop_requested}{stop_source}% \begin{itemdecl} -~stop_source(); +bool stop_requested() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Releases ownership of the stop state, if any. +\returns +\tcode{true} if \exposid{stop-state} refers to a stop state +that has received a stop request; +otherwise, \tcode{false}. \end{itemdescr} -\indexlibrarymember{operator=}{stop_source}% +\indexlibrarymember{request_stop}{stop_source}% \begin{itemdecl} -stop_source& operator=(const stop_source& rhs) noexcept; +bool request_stop() noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{stop_source(rhs).swap(*this)}. +Executes a stop request operation\iref{stoptoken.concepts} on +the associated stop state, if any. +\end{itemdescr} + +\rSec2[stopcallback]{Class template \tcode{stop_callback}}% +\indexlibraryglobal{stop_callback}% + +\rSec3[stopcallback.general]{General} \pnum -\returns -\tcode{*this}. -\end{itemdescr} +\indexlibraryglobal{stop_callback}% +\begin{codeblock} +namespace std { + template + class stop_callback { + public: + using callback_type = CallbackFn; + + // \ref{stopcallback.cons}, constructors and destructor + template + explicit stop_callback(const stop_token& st, Initializer&& init) + noexcept(is_nothrow_constructible_v); + template + explicit stop_callback(stop_token&& st, Initializer&& init) + noexcept(is_nothrow_constructible_v); + ~stop_callback(); + + stop_callback(const stop_callback&) = delete; + stop_callback(stop_callback&&) = delete; + stop_callback& operator=(const stop_callback&) = delete; + stop_callback& operator=(stop_callback&&) = delete; + + private: + CallbackFn @\exposid{callback-fn}@; // \expos + }; + + template + stop_callback(stop_token, CallbackFn) -> stop_callback; +} +\end{codeblock} + +\pnum +\mandates +\tcode{stop_callback} is instantiated with an argument for the +template parameter \tcode{CallbackFn} +that satisfies both \libconcept{invocable} +and \libconcept{destructible}. + +\pnum +\remarks +For a type \tcode{Initializer}, +if +\tcode{\exposconcept{stoppable-callback-for}} +is satisfied, then +\tcode{\exposconcept{stoppable-callback-for}} is modeled. +The exposition-only \exposid{callback-fn} member is +the associated callback function\iref{stoptoken.concepts} of +\tcode{stop_callback<\newline CallbackFn>} objects. + +\rSec3[stopcallback.cons]{Constructors and destructor} -\indexlibrarymember{operator=}{stop_source}% +\indexlibraryctor{stop_callback}% \begin{itemdecl} -stop_source& operator=(stop_source&& rhs) noexcept; +template + explicit stop_callback(const stop_token& st, Initializer&& init) + noexcept(is_nothrow_constructible_v); + +template + explicit stop_callback(stop_token&& st, Initializer&& init) + noexcept(is_nothrow_constructible_v); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{stop_source(std::move(rhs)).swap(*this)}. +\constraints +\tcode{CallbackFn} and \tcode{Initializer} satisfy +\tcode{\libconcept{constructible_from}}. \pnum -\returns -\tcode{*this}. +\effects +Initializes \exposid{callback-fn} with \tcode{std::forward(init)} +and executes a stoppable callback registration\iref{stoptoken.concepts}. +If a callback is registered with \tcode{st}'s shared stop state, +then \tcode{*this} acquires shared ownership of that stop state. \end{itemdescr} -\indexlibrarymember{swap}{stop_source}% +\indexlibrarydtor{stop_callback}% \begin{itemdecl} -void swap(stop_source& rhs) noexcept; +~stop_callback(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Exchanges the values of \tcode{*this} and \tcode{rhs}. +Executes a stoppable callback deregistration\iref{stoptoken.concepts} and +releases ownership of the stop state, if any. \end{itemdescr} -\rSec3[stopsource.mem]{Members} +\rSec2[stoptoken.never]{Class \tcode{never_stop_token}} + +\pnum +The class \tcode{never_stop_token} models +the \libconcept{unstoppable_token} concept. +It provides a stop token interface, +but also provides static information +that a stop is never possible nor requested. +\begin{codeblock} +namespace std { + class never_stop_token { + struct @\exposid{callback-type}@ { // \expos + explicit @\exposid{callback-type}@(never_stop_token, auto&&) noexcept {} + }; + public: + template + using callback_type = @\exposid{callback-type}@; + + static constexpr bool stop_requested() noexcept { return false; } + static constexpr bool stop_possible() noexcept { return false; } + + bool operator==(const never_stop_token&) const = default; + }; +} +\end{codeblock} + +\rSec2[stoptoken.inplace]{Class \tcode{inplace_stop_token}} + +\rSec3[stoptoken.inplace.general]{General} + +\pnum +The class \tcode{inplace_stop_token} models +the concept \libconcept{stoppable_token}. +It references the stop state of +its associated \tcode{inplace_stop_source} object\iref{stopsource.inplace}, +if any. +\begin{codeblock} +namespace std { + class inplace_stop_token { + public: + template + using callback_type = inplace_stop_callback; + + inplace_stop_token() = default; + bool operator==(const inplace_stop_token&) const = default; + + // \ref{stoptoken.inplace.mem}, member functions + bool stop_requested() const noexcept; + bool stop_possible() const noexcept; + void swap(inplace_stop_token&) noexcept; + + private: + const inplace_stop_source* @\exposid{stop-source}@ = nullptr; // \expos + }; +} +\end{codeblock} + +\rSec3[stoptoken.inplace.mem]{Member functions} -\indexlibrarymember{get_token}{stop_source sc}% \begin{itemdecl} -[[nodiscard]] stop_token get_token() const noexcept; +void swap(inplace_stop_token& rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{stop_token()} if \tcode{stop_possible()} is \tcode{false}; -otherwise a new associated \tcode{stop_token} object. +\effects +Exchanges the values of \exposid{stop-source} and \tcode{rhs.\exposid{stop-source}}. \end{itemdescr} -\indexlibrarymember{stop_possible}{stop_source}% \begin{itemdecl} -[[nodiscard]] bool stop_possible() const noexcept; +bool stop_requested() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{true} if \tcode{*this} has ownership of a stop state; -otherwise, \tcode{false}. +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{stop-source}@ != nullptr && @\exposid{stop-source}@->stop_requested(); +\end{codeblock} + +\pnum +\begin{note} +As specified in \ref{basic.life}, +the behavior of \tcode{stop_requested} is undefined +unless the call strongly happens before the start of +the destructor of the associated \tcode{inplace_stop_source} object, if any. +\end{note} \end{itemdescr} -\indexlibrarymember{stop_requested}{stop_source}% \begin{itemdecl} -[[nodiscard]] bool stop_requested() const noexcept; +stop_possible() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{true} if \tcode{*this} has ownership of a stop state -that has received a stop request; -otherwise, \tcode{false}. +\tcode{\exposidnc{stop-source} != nullptr}. + +\pnum +\begin{note} +As specified in \ref{basic.stc.general}, +the behavior of \tcode{stop_possible} is implementation-defined +unless the call strongly happens before +the end of the storage duration of +the associated \tcode{inplace_stop_source} object, if any. +\end{note} \end{itemdescr} -\indexlibrarymember{request_stop}{stop_source}% +\rSec2[stopsource.inplace]{Class \tcode{inplace_stop_source}} + +\rSec3[stopsource.inplace.general]{General} + +\pnum +The class \tcode{inplace_stop_source} models \exposconcept{stoppable-source}. + +\begin{codeblock} +namespace std { + class inplace_stop_source { + public: + // \ref{stopsource.inplace.cons}, constructors + constexpr inplace_stop_source() noexcept; + + inplace_stop_source(inplace_stop_source&&) = delete; + inplace_stop_source(const inplace_stop_source&) = delete; + inplace_stop_source& operator=(inplace_stop_source&&) = delete; + inplace_stop_source& operator=(const inplace_stop_source&) = delete; + ~inplace_stop_source(); + + // \ref{stopsource.inplace.mem}, stop handling + constexpr inplace_stop_token get_token() const noexcept; + static constexpr bool stop_possible() noexcept { return true; } + bool stop_requested() const noexcept; + bool request_stop() noexcept; + }; +} +\end{codeblock} + +\rSec3[stopsource.inplace.cons]{Constructors} + \begin{itemdecl} -bool request_stop() noexcept; +constexpr inplace_stop_source() noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -If \tcode{*this} does not have ownership of a stop state, returns \tcode{false}. -Otherwise, atomically determines whether the owned stop state -has received a stop request, -and if not, makes a stop request. -The determination and making of the stop request are an -atomic read-modify-write operation\iref{intro.races}. -If the request was made, -the callbacks registered by associated \tcode{stop_callback} objects -are synchronously called. -If an invocation of a callback exits via an exception -then \tcode{terminate} is invoked\iref{except.terminate}. -\begin{note} -A stop request includes notifying all condition variables -of type \tcode{condition_variable_any} -temporarily registered during -an interruptible wait\iref{thread.condvarany.intwait}. -\end{note} +Initializes a new stop state inside \tcode{*this}. \pnum \ensures -\tcode{stop_possible()} is \tcode{false} -or \tcode{stop_requested()} is \tcode{true}. +\tcode{stop_requested()} is \tcode{false}. +\end{itemdescr} + +\rSec3[stopsource.inplace.mem]{Member functions} +\begin{itemdecl} +constexpr inplace_stop_token get_token() const noexcept; +\end{itemdecl} + +\begin{itemdescr} \pnum \returns -\tcode{true} if this call made a stop request; -otherwise \tcode{false}. +A new associated \tcode{inplace_stop_token} object +whose \exposid{stop-source} member is equal to \tcode{this}. \end{itemdescr} -\rSec3[stopsource.nonmembers]{Non-member functions} - -\indexlibrarymember{operator==}{stop_source}% \begin{itemdecl} -[[nodiscard]] friend bool - operator==(const stop_source& lhs, const stop_source& rhs) noexcept; +bool stop_requested() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{true} if \tcode{lhs} and \tcode{rhs} have ownership -of the same stop state -or if both \tcode{lhs} and \tcode{rhs} do not have ownership of a stop state; -otherwise \tcode{false}. +\tcode{true} if the stop state inside \tcode{*this} +has received a stop request; otherwise, \tcode{false}. \end{itemdescr} -\indexlibrarymember{swap}{stop_source}% \begin{itemdecl} -friend void swap(stop_source& x, stop_source& y) noexcept; +bool request_stop() noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{x.swap(y)}. +Executes a stop request operation\iref{stoptoken.concepts}. + +\pnum +\ensures +\tcode{stop_requested()} is \tcode{true}. \end{itemdescr} -\rSec2[stopcallback]{Class template \tcode{stop_callback}}% -\indexlibraryglobal{stop_callback}% +\rSec2[stopcallback.inplace]{Class template \tcode{inplace_stop_callback}} -\rSec3[stopcallback.general]{General} +\rSec3[stopcallback.inplace.general]{General} -\pnum -\indexlibraryglobal{stop_callback}% \begin{codeblock} namespace std { - template - class stop_callback { + template + class inplace_stop_callback { public: - using callback_type = Callback; + using callback_type = CallbackFn; - // \ref{stopcallback.cons}, constructors and destructor - template - explicit stop_callback(const stop_token& st, C&& cb) - noexcept(is_nothrow_constructible_v); - template - explicit stop_callback(stop_token&& st, C&& cb) - noexcept(is_nothrow_constructible_v); - ~stop_callback(); + // \ref{stopcallback.inplace.cons}, constructors and destructor + template + explicit inplace_stop_callback(inplace_stop_token st, Initializer&& init) + noexcept(is_nothrow_constructible_v); + ~inplace_stop_callback(); - stop_callback(const stop_callback&) = delete; - stop_callback(stop_callback&&) = delete; - stop_callback& operator=(const stop_callback&) = delete; - stop_callback& operator=(stop_callback&&) = delete; + inplace_stop_callback(inplace_stop_callback&&) = delete; + inplace_stop_callback(const inplace_stop_callback&) = delete; + inplace_stop_callback& operator=(inplace_stop_callback&&) = delete; + inplace_stop_callback& operator=(const inplace_stop_callback&) = delete; private: - Callback callback; // \expos + CallbackFn @\exposid{callback-fn}@; // \expos }; - template - stop_callback(stop_token, Callback) -> stop_callback; + template + inplace_stop_callback(inplace_stop_token, CallbackFn) + -> inplace_stop_callback; } \end{codeblock} \pnum \mandates -\tcode{stop_callback} is instantiated with an argument for the -template parameter \tcode{Callback} -that satisfies both \libconcept{invocable} -and \libconcept{destructible}. +\tcode{CallbackFn} satisfies both +\libconcept{invocable} and \libconcept{destructible}. \pnum -\expects -\tcode{stop_callback} is instantiated with an argument for the -template parameter \tcode{Callback} -that models both \libconcept{invocable} -and \libconcept{destructible}. - +\remarks +For a type \tcode{Initializer}, if +\begin{codeblock} +@\exposconcept{stoppable-callback-for}@ +\end{codeblock} +is satisfied, then +\begin{codeblock} +@\exposconcept{stoppable-callback-for}@ +\end{codeblock} +is modeled. +For an \tcode{inplace_stop_callback} object, +the exposition-only \exposid{callback-fn} member is +its associated callback function\iref{stoptoken.concepts}. -\rSec3[stopcallback.cons]{Constructors and destructor} +\rSec3[stopcallback.inplace.cons]{Constructors and destructor} -\indexlibraryctor{stop_callback}% \begin{itemdecl} -template -explicit stop_callback(const stop_token& st, C&& cb) - noexcept(is_nothrow_constructible_v); -template -explicit stop_callback(stop_token&& st, C&& cb) - noexcept(is_nothrow_constructible_v); +template + explicit inplace_stop_callback(inplace_stop_token st, Initializer&& init) + noexcept(is_nothrow_constructible_v); \end{itemdecl} + \begin{itemdescr} \pnum \constraints -\tcode{Callback} and \tcode{C} satisfy \tcode{\libconcept{constructible_from}}. - -\pnum -\expects -\tcode{Callback} and \tcode{C} model \tcode{\libconcept{constructible_from}}. +\tcode{\libconcept{constructible_from}} is satisfied. \pnum \effects -Initializes \tcode{callback} with \tcode{std::forward(cb)}. -If \tcode{st.stop_requested()} is \tcode{true}, then -\tcode{std::forward(callback)()} -is evaluated in the current thread before the constructor returns. -Otherwise, if \tcode{st} has ownership of a stop state, -acquires shared ownership of that stop state and registers -the callback with that stop state -such that \tcode{std::forward(callback)()} -is evaluated by the first call to \tcode{request_stop()} -on an associated \tcode{stop_source}. - -\pnum -\throws -Any exception thrown by the initialization of \tcode{callback}. - -\pnum -\remarks -If evaluating -\tcode{std::forward(callback)()} -exits via an exception, -then \tcode{terminate} is invoked\iref{except.terminate}. +Initializes \exposid{callback-fn} with \tcode{std::forward(init)} +and executes a stoppable callback registration\iref{stoptoken.concepts}. \end{itemdescr} -\indexlibrarydtor{stop_callback}% \begin{itemdecl} -~stop_callback(); +~inplace_stop_callback(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Unregisters the callback from the owned stop state, if any. -The destructor does not block waiting for the execution of another callback -registered by an associated \tcode{stop_callback}. -If \tcode{callback} is concurrently executing on another thread, -then the return from the invocation of \tcode{callback} -strongly happens before\iref{intro.races} -\tcode{callback} is destroyed. -If \tcode{callback} is executing on the current thread, -then the destructor does not block\iref{defns.block} waiting for -the return from the invocation of \tcode{callback}. -Releases ownership of the stop state, if any. +Executes a stoppable callback deregistration\iref{stoptoken.concepts}. \end{itemdescr} - \rSec1[thread.threads]{Threads} \rSec2[thread.threads.general]{General} @@ -1290,7 +1590,7 @@ \begin{itemdecl} template basic_ostream& - operator<< (basic_ostream& out, thread::id id); + operator<<(basic_ostream& out, thread::id id); \end{itemdecl} \begin{itemdescr} @@ -1650,22 +1950,22 @@ // \ref{thread.jthread.mem}, members void swap(jthread&) noexcept; - [[nodiscard]] bool joinable() const noexcept; + bool joinable() const noexcept; void join(); void detach(); - [[nodiscard]] id get_id() const noexcept; - [[nodiscard]] native_handle_type native_handle(); // see~\ref{thread.req.native} + id get_id() const noexcept; + native_handle_type native_handle(); // see~\ref{thread.req.native} // \ref{thread.jthread.stop}, stop token handling - [[nodiscard]] stop_source get_stop_source() noexcept; - [[nodiscard]] stop_token get_stop_token() const noexcept; + stop_source get_stop_source() noexcept; + stop_token get_stop_token() const noexcept; bool request_stop() noexcept; // \ref{thread.jthread.special}, specialized algorithms friend void swap(jthread& lhs, jthread& rhs) noexcept; // \ref{thread.jthread.static}, static members - [[nodiscard]] static unsigned int hardware_concurrency() noexcept; + static unsigned int hardware_concurrency() noexcept; private: stop_source ssource; // \expos @@ -1835,7 +2135,7 @@ \indexlibrarymember{joinable}{jthread}% \begin{itemdecl} -[[nodiscard]] bool joinable() const noexcept; +bool joinable() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -1934,7 +2234,7 @@ \indexlibrarymember{get_stop_source}{jthread}% \begin{itemdecl} -[[nodiscard]] stop_source get_stop_source() noexcept; +stop_source get_stop_source() noexcept; \end{itemdecl} \begin{itemdescr} @@ -1945,7 +2245,7 @@ \indexlibrarymember{get_stop_token}{jthread}% \begin{itemdecl} -[[nodiscard]] stop_token get_stop_token() const noexcept; +stop_token get_stop_token() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -1983,7 +2283,7 @@ \indexlibrarymember{hardware_concurrency}{jthread}% \begin{itemdecl} -[[nodiscard]] static unsigned int hardware_concurrency() noexcept; +static unsigned int hardware_concurrency() noexcept; \end{itemdecl} \begin{itemdescr} @@ -2097,28 +2397,24 @@ // \ref{atomics.order}, order and consistency enum class memory_order : @\unspecnc@; // freestanding inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; // freestanding - inline constexpr memory_order memory_order_consume = memory_order::consume; // freestanding inline constexpr memory_order memory_order_acquire = memory_order::acquire; // freestanding inline constexpr memory_order memory_order_release = memory_order::release; // freestanding inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; // freestanding inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; // freestanding - - template - T kill_dependency(T y) noexcept; // freestanding } // \ref{atomics.lockfree}, lock-free property -#define ATOMIC_BOOL_LOCK_FREE @\unspecnc@ // freestanding -#define ATOMIC_CHAR_LOCK_FREE @\unspecnc@ // freestanding -#define ATOMIC_CHAR8_T_LOCK_FREE @\unspecnc@ // freestanding -#define ATOMIC_CHAR16_T_LOCK_FREE @\unspecnc@ // freestanding -#define ATOMIC_CHAR32_T_LOCK_FREE @\unspecnc@ // freestanding -#define ATOMIC_WCHAR_T_LOCK_FREE @\unspecnc@ // freestanding -#define ATOMIC_SHORT_LOCK_FREE @\unspecnc@ // freestanding -#define ATOMIC_INT_LOCK_FREE @\unspecnc@ // freestanding -#define ATOMIC_LONG_LOCK_FREE @\unspecnc@ // freestanding -#define ATOMIC_LLONG_LOCK_FREE @\unspecnc@ // freestanding -#define ATOMIC_POINTER_LOCK_FREE @\unspecnc@ // freestanding +#define @\libmacro{ATOMIC_BOOL_LOCK_FREE}@ @\unspecnc@ // freestanding +#define @\libmacro{ATOMIC_CHAR_LOCK_FREE}@ @\unspecnc@ // freestanding +#define @\libmacro{ATOMIC_CHAR8_T_LOCK_FREE}@ @\unspecnc@ // freestanding +#define @\libmacro{ATOMIC_CHAR16_T_LOCK_FREE}@ @\unspecnc@ // freestanding +#define @\libmacro{ATOMIC_CHAR32_T_LOCK_FREE}@ @\unspecnc@ // freestanding +#define @\libmacro{ATOMIC_WCHAR_T_LOCK_FREE}@ @\unspecnc@ // freestanding +#define @\libmacro{ATOMIC_SHORT_LOCK_FREE}@ @\unspecnc@ // freestanding +#define @\libmacro{ATOMIC_INT_LOCK_FREE}@ @\unspecnc@ // freestanding +#define @\libmacro{ATOMIC_LONG_LOCK_FREE}@ @\unspecnc@ // freestanding +#define @\libmacro{ATOMIC_LLONG_LOCK_FREE}@ @\unspecnc@ // freestanding +#define @\libmacro{ATOMIC_POINTER_LOCK_FREE}@ @\unspecnc@ // freestanding namespace std { // \ref{atomics.ref.generic}, class template \tcode{atomic_ref} @@ -2140,152 +2436,285 @@ void atomic_store(volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - void atomic_store(atomic*, typename atomic::value_type) noexcept; // freestanding + constexpr void atomic_store(atomic*, // freestanding + typename atomic::value_type) noexcept; template void atomic_store_explicit(volatile atomic*, // freestanding - typename atomic::value_type, - memory_order) noexcept; + typename atomic::value_type, memory_order) noexcept; template - void atomic_store_explicit(atomic*, typename atomic::value_type, // freestanding - memory_order) noexcept; + constexpr void atomic_store_explicit(atomic*, // freestanding + typename atomic::value_type, memory_order) noexcept; template T atomic_load(const volatile atomic*) noexcept; // freestanding template - T atomic_load(const atomic*) noexcept; // freestanding + constexpr T atomic_load(const atomic*) noexcept; // freestanding template T atomic_load_explicit(const volatile atomic*, memory_order) noexcept; // freestanding template - T atomic_load_explicit(const atomic*, memory_order) noexcept; // freestanding + constexpr T atomic_load_explicit(const atomic*, memory_order) noexcept; // freestanding template T atomic_exchange(volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - T atomic_exchange(atomic*, typename atomic::value_type) noexcept; // freestanding + constexpr T atomic_exchange(atomic*, // freestanding + typename atomic::value_type) noexcept; template T atomic_exchange_explicit(volatile atomic*, // freestanding - typename atomic::value_type, - memory_order) noexcept; + typename atomic::value_type, memory_order) noexcept; template - T atomic_exchange_explicit(atomic*, typename atomic::value_type, // freestanding - memory_order) noexcept; + constexpr T atomic_exchange_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; template bool atomic_compare_exchange_weak(volatile atomic*, // freestanding typename atomic::value_type*, typename atomic::value_type) noexcept; template - bool atomic_compare_exchange_weak(atomic*, // freestanding - typename atomic::value_type*, - typename atomic::value_type) noexcept; + constexpr bool atomic_compare_exchange_weak(atomic*, // freestanding + typename atomic::value_type*, + typename atomic::value_type) noexcept; template bool atomic_compare_exchange_strong(volatile atomic*, // freestanding typename atomic::value_type*, typename atomic::value_type) noexcept; template - bool atomic_compare_exchange_strong(atomic*, // freestanding - typename atomic::value_type*, - typename atomic::value_type) noexcept; + constexpr bool atomic_compare_exchange_strong(atomic*, // freestanding + typename atomic::value_type*, + typename atomic::value_type) noexcept; template bool atomic_compare_exchange_weak_explicit(volatile atomic*, // freestanding typename atomic::value_type*, typename atomic::value_type, memory_order, memory_order) noexcept; template - bool atomic_compare_exchange_weak_explicit(atomic*, // freestanding - typename atomic::value_type*, - typename atomic::value_type, - memory_order, memory_order) noexcept; + constexpr bool atomic_compare_exchange_weak_explicit(atomic*, // freestanding + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; template bool atomic_compare_exchange_strong_explicit(volatile atomic*, // freestanding typename atomic::value_type*, typename atomic::value_type, memory_order, memory_order) noexcept; template - bool atomic_compare_exchange_strong_explicit(atomic*, // freestanding - typename atomic::value_type*, - typename atomic::value_type, - memory_order, memory_order) noexcept; + constexpr bool atomic_compare_exchange_strong_explicit(atomic*, // freestanding + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; template T atomic_fetch_add(volatile atomic*, // freestanding typename atomic::difference_type) noexcept; template - T atomic_fetch_add(atomic*, typename atomic::difference_type) noexcept; // freestanding + constexpr T atomic_fetch_add(atomic*, // freestanding + typename atomic::difference_type) noexcept; template T atomic_fetch_add_explicit(volatile atomic*, // freestanding typename atomic::difference_type, memory_order) noexcept; template - T atomic_fetch_add_explicit(atomic*, typename atomic::difference_type, // freestanding - memory_order) noexcept; + constexpr T atomic_fetch_add_explicit(atomic*, // freestanding + typename atomic::difference_type, + memory_order) noexcept; template T atomic_fetch_sub(volatile atomic*, // freestanding typename atomic::difference_type) noexcept; template - T atomic_fetch_sub(atomic*, typename atomic::difference_type) noexcept; // freestanding + constexpr T atomic_fetch_sub(atomic*, // freestanding + typename atomic::difference_type) noexcept; template T atomic_fetch_sub_explicit(volatile atomic*, // freestanding typename atomic::difference_type, memory_order) noexcept; template - T atomic_fetch_sub_explicit(atomic*, typename atomic::difference_type, // freestanding - memory_order) noexcept; + constexpr T atomic_fetch_sub_explicit(atomic*, // freestanding + typename atomic::difference_type, + memory_order) noexcept; template T atomic_fetch_and(volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - T atomic_fetch_and(atomic*, typename atomic::value_type) noexcept; // freestanding + constexpr T atomic_fetch_and(atomic*, // freestanding + typename atomic::value_type) noexcept; template T atomic_fetch_and_explicit(volatile atomic*, // freestanding typename atomic::value_type, memory_order) noexcept; template - T atomic_fetch_and_explicit(atomic*, typename atomic::value_type, // freestanding - memory_order) noexcept; + constexpr T atomic_fetch_and_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; template T atomic_fetch_or(volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - T atomic_fetch_or(atomic*, typename atomic::value_type) noexcept; // freestanding + constexpr T atomic_fetch_or(atomic*, // freestanding + typename atomic::value_type) noexcept; template T atomic_fetch_or_explicit(volatile atomic*, // freestanding typename atomic::value_type, memory_order) noexcept; template - T atomic_fetch_or_explicit(atomic*, typename atomic::value_type, // freestanding - memory_order) noexcept; + constexpr T atomic_fetch_or_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; template T atomic_fetch_xor(volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - T atomic_fetch_xor(atomic*, typename atomic::value_type) noexcept; // freestanding + constexpr T atomic_fetch_xor(atomic*, // freestanding + typename atomic::value_type) noexcept; template T atomic_fetch_xor_explicit(volatile atomic*, // freestanding typename atomic::value_type, memory_order) noexcept; template - T atomic_fetch_xor_explicit(atomic*, typename atomic::value_type, // freestanding + constexpr T atomic_fetch_xor_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; + template + T atomic_fetch_max(volatile atomic*, // freestanding + typename atomic::value_type) noexcept; + template + constexpr T atomic_fetch_max(atomic*, // freestanding + typename atomic::value_type) noexcept; + template + T atomic_fetch_max_explicit(volatile atomic*, // freestanding + typename atomic::value_type, memory_order) noexcept; + template + constexpr T atomic_fetch_max_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; + template + T atomic_fetch_min(volatile atomic*, // freestanding + typename atomic::value_type) noexcept; + template + constexpr T atomic_fetch_min(atomic*, // freestanding + typename atomic::value_type) noexcept; + template + T atomic_fetch_min_explicit(volatile atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; + template + constexpr T atomic_fetch_min_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; + + template + void atomic_store_add(volatile atomic*, // freestanding + typename atomic::difference_type) noexcept; + template + constexpr void atomic_store_add(atomic*, // freestanding + typename atomic::difference_type) noexcept; + template + void atomic_store_add_explicit(volatile atomic*, // freestanding + typename atomic::difference_type, memory_order) noexcept; + template + constexpr void atomic_store_add_explicit(atomic*, // freestanding + typename atomic::difference_type, + memory_order) noexcept; + template + void atomic_store_sub(volatile atomic*, // freestanding + typename atomic::difference_type) noexcept; + template + constexpr void atomic_store_sub(atomic*, // freestanding + typename atomic::difference_type) noexcept; + template + void atomic_store_sub_explicit(volatile atomic*, // freestanding + typename atomic::difference_type, memory_order) noexcept; + template + constexpr void atomic_store_sub_explicit(atomic*, // freestanding + typename atomic::difference_type, + memory_order) noexcept; + template + void atomic_store_and(volatile atomic*, // freestanding + typename atomic::value_type) noexcept; + template + constexpr void atomic_store_and(atomic*, // freestanding + typename atomic::value_type) noexcept; + template + void atomic_store_and_explicit(volatile atomic*, // freestanding + typename atomic::value_type, memory_order) noexcept; + template + constexpr void atomic_store_and_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; + template + void atomic_store_or(volatile atomic*, // freestanding + typename atomic::value_type) noexcept; + template + constexpr void atomic_store_or(atomic*, // freestanding + typename atomic::value_type) noexcept; + template + void atomic_store_or_explicit(volatile atomic*, // freestanding + typename atomic::value_type, memory_order) noexcept; + template + constexpr void atomic_store_or_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; + template + void atomic_store_xor(volatile atomic*, // freestanding + typename atomic::value_type) noexcept; + template + constexpr void atomic_store_xor(atomic*, // freestanding + typename atomic::value_type) noexcept; + template + void atomic_store_xor_explicit(volatile atomic*, // freestanding + typename atomic::value_type, memory_order) noexcept; + template + constexpr void atomic_store_xor_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; + template + void atomic_store_max(volatile atomic*, // freestanding + typename atomic::value_type) noexcept; + template + constexpr void atomic_store_max(atomic*, // freestanding + typename atomic::value_type) noexcept; + template + void atomic_store_max_explicit(volatile atomic*, // freestanding + typename atomic::value_type, memory_order) noexcept; + template + constexpr void atomic_store_max_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; + template + void atomic_store_min(volatile atomic*, // freestanding + typename atomic::value_type) noexcept; + template + constexpr void atomic_store_min(atomic*, // freestanding + typename atomic::value_type) noexcept; + template + void atomic_store_min_explicit(volatile atomic*, // freestanding + typename atomic::value_type, memory_order) noexcept; + template + constexpr void atomic_store_min_explicit(atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; template void atomic_wait(const volatile atomic*, // freestanding typename atomic::value_type) noexcept; template - void atomic_wait(const atomic*, typename atomic::value_type) noexcept; // freestanding + constexpr void atomic_wait(const atomic*, // freestanding + typename atomic::value_type) noexcept; template void atomic_wait_explicit(const volatile atomic*, // freestanding typename atomic::value_type, memory_order) noexcept; template - void atomic_wait_explicit(const atomic*, typename atomic::value_type, // freestanding - memory_order) noexcept; + constexpr void atomic_wait_explicit(const atomic*, // freestanding + typename atomic::value_type, + memory_order) noexcept; template void atomic_notify_one(volatile atomic*) noexcept; // freestanding template - void atomic_notify_one(atomic*) noexcept; // freestanding + constexpr void atomic_notify_one(atomic*) noexcept; // freestanding template void atomic_notify_all(volatile atomic*) noexcept; // freestanding template - void atomic_notify_all(atomic*) noexcept; // freestanding + constexpr void atomic_notify_all(atomic*) noexcept; // freestanding // \ref{atomics.alias}, type aliases using atomic_bool = atomic; // freestanding @@ -2346,35 +2775,37 @@ struct atomic_flag; // freestanding bool atomic_flag_test(const volatile atomic_flag*) noexcept; // freestanding - bool atomic_flag_test(const atomic_flag*) noexcept; // freestanding + constexpr bool atomic_flag_test(const atomic_flag*) noexcept; // freestanding bool atomic_flag_test_explicit(const volatile atomic_flag*, // freestanding memory_order) noexcept; - bool atomic_flag_test_explicit(const atomic_flag*, memory_order) noexcept; // freestanding + constexpr bool atomic_flag_test_explicit(const atomic_flag*, // freestanding + memory_order) noexcept; bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept; // freestanding - bool atomic_flag_test_and_set(atomic_flag*) noexcept; // freestanding + constexpr bool atomic_flag_test_and_set(atomic_flag*) noexcept; // freestanding bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, // freestanding memory_order) noexcept; - bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order) noexcept; // freestanding + constexpr bool atomic_flag_test_and_set_explicit(atomic_flag*, // freestanding + memory_order) noexcept; void atomic_flag_clear(volatile atomic_flag*) noexcept; // freestanding - void atomic_flag_clear(atomic_flag*) noexcept; // freestanding + constexpr void atomic_flag_clear(atomic_flag*) noexcept; // freestanding void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept; // freestanding - void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept; // freestanding + constexpr void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept; // freestanding void atomic_flag_wait(const volatile atomic_flag*, bool) noexcept; // freestanding - void atomic_flag_wait(const atomic_flag*, bool) noexcept; // freestanding + constexpr void atomic_flag_wait(const atomic_flag*, bool) noexcept; // freestanding void atomic_flag_wait_explicit(const volatile atomic_flag*, // freestanding bool, memory_order) noexcept; - void atomic_flag_wait_explicit(const atomic_flag*, // freestanding - bool, memory_order) noexcept; + constexpr void atomic_flag_wait_explicit(const atomic_flag*, // freestanding + bool, memory_order) noexcept; void atomic_flag_notify_one(volatile atomic_flag*) noexcept; // freestanding - void atomic_flag_notify_one(atomic_flag*) noexcept; // freestanding + constexpr void atomic_flag_notify_one(atomic_flag*) noexcept; // freestanding void atomic_flag_notify_all(volatile atomic_flag*) noexcept; // freestanding - void atomic_flag_notify_all(atomic_flag*) noexcept; // freestanding - #define ATOMIC_FLAG_INIT @\seebelownc@ // freestanding + constexpr void atomic_flag_notify_all(atomic_flag*) noexcept; // freestanding + #define @\libmacro{ATOMIC_FLAG_INIT}@ @\seebelownc@ // freestanding // \ref{atomics.fences}, fences - extern "C" void atomic_thread_fence(memory_order) noexcept; // freestanding - extern "C" void atomic_signal_fence(memory_order) noexcept; // freestanding + extern "C" constexpr void atomic_thread_fence(memory_order) noexcept; // freestanding + extern "C" constexpr void atomic_signal_fence(memory_order) noexcept; // freestanding } \end{codeblock} @@ -2453,13 +2884,11 @@ \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}% @@ -2468,7 +2897,7 @@ \begin{codeblock} namespace std { enum class memory_order : @\unspec@ { - relaxed, consume, acquire, release, acq_rel, seq_cst + relaxed = 0, acquire = 2, release = 3, acq_rel = 4, seq_cst = 5 }; } \end{codeblock} @@ -2486,15 +2915,6 @@ \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. @@ -2645,56 +3065,39 @@ (in the modification order) written before the write associated with the read-modify-write operation. +\pnum +An \defnadj{atomic}{modify-write operation} is +an atomic read-modify-write operation +with weaker synchronization requirements as specified in~\ref{atomics.fences}. +\begin{note} +The intent is for atomic modify-write operations +to be implemented using mechanisms that are not ordered, in hardware, +by the implementation of acquire fences. +No other semantic or hardware property +(e.g., that the mechanism is a far atomic operation) is implied. +\end{note} + \pnum \recommended The implementation should make atomic stores visible to atomic loads, and atomic loads should observe atomic stores, 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@ +#define @\libmacro{ATOMIC_BOOL_LOCK_FREE}@ @\unspec@ +#define @\libmacro{ATOMIC_CHAR_LOCK_FREE}@ @\unspec@ +#define @\libmacro{ATOMIC_CHAR8_T_LOCK_FREE}@ @\unspec@ +#define @\libmacro{ATOMIC_CHAR16_T_LOCK_FREE}@ @\unspec@ +#define @\libmacro{ATOMIC_CHAR32_T_LOCK_FREE}@ @\unspec@ +#define @\libmacro{ATOMIC_WCHAR_T_LOCK_FREE}@ @\unspec@ +#define @\libmacro{ATOMIC_SHORT_LOCK_FREE}@ @\unspec@ +#define @\libmacro{ATOMIC_INT_LOCK_FREE}@ @\unspec@ +#define @\libmacro{ATOMIC_LONG_LOCK_FREE}@ @\unspec@ +#define @\libmacro{ATOMIC_LLONG_LOCK_FREE}@ @\unspec@ +#define @\libmacro{ATOMIC_POINTER_LOCK_FREE}@ @\unspec@ \end{codeblock} \pnum @@ -2802,34 +3205,36 @@ T* ptr; // \expos public: - using value_type = T; + using value_type = remove_cv_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; + constexpr explicit atomic_ref(T&); + constexpr 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; + constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type operator=(value_type) const noexcept; + constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; + constexpr operator value_type() const noexcept; + + constexpr value_type exchange(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr void notify_one() const noexcept; + constexpr void notify_all() const noexcept; + constexpr T* address() const noexcept; }; } \end{codeblock} @@ -2864,6 +3269,11 @@ to enable atomic operations to be applied to the referenced object. \end{note} +\pnum +The program is ill-formed +if \tcode{is_always_lock_free} is \tcode{false} and +\tcode{is_volatile_v} is \tcode{true}. + \rSec3[atomics.ref.ops]{Operations} \indexlibrarymember{required_alignment}{atomic_ref}% @@ -2928,7 +3338,7 @@ \indexlibrary{\idxcode{atomic_ref<\placeholder{integral-type}>}!constructor}% \indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point-type}>}!constructor}% \begin{itemdecl} -atomic_ref(T& obj); +constexpr atomic_ref(T& obj); \end{itemdecl} \begin{itemdescr} @@ -2950,7 +3360,7 @@ \indexlibrary{\idxcode{atomic_ref<\placeholder{integral-type}>}!constructor}% \indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point-type}>}!constructor}% \begin{itemdecl} -atomic_ref(const atomic_ref& ref) noexcept; +constexpr atomic_ref(const atomic_ref& ref) noexcept; \end{itemdecl} \begin{itemdescr} @@ -2964,10 +3374,15 @@ \indexlibrarymember{store}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{store}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -void store(T desired, memory_order order = memory_order::seq_cst) const noexcept; +constexpr void store(value_type desired, + memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \expects \tcode{order} is @@ -2987,10 +3402,14 @@ \indexlibrarymember{operator=}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{operator=}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -T operator=(T desired) const noexcept; +constexpr value_type operator=(value_type desired) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \effects Equivalent to: @@ -3005,7 +3424,7 @@ \indexlibrarymember{load}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{load}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -T load(memory_order order = memory_order::seq_cst) const noexcept; +constexpr value_type load(memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3013,8 +3432,7 @@ \expects \tcode{order} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac-\linebreak quire}, or +\tcode{memory_order::acquire}, or \tcode{memory_order::seq_cst}. \pnum @@ -3031,7 +3449,7 @@ \indexlibrarymember{operator \placeholder{integral-type}}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{operator \placeholder{floating-point-type}}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -operator T() const noexcept; +constexpr operator value_type() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3045,10 +3463,15 @@ \indexlibrarymember{exchange}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{exchange}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -T exchange(T desired, memory_order order = memory_order::seq_cst) const noexcept; +constexpr value_type exchange(value_type desired, + memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} -\begin{itemdescr} +\begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \effects Atomically replaces the value referenced by \tcode{*ptr} @@ -3071,27 +3494,30 @@ \indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -bool compare_exchange_weak(T& expected, T desired, +constexpr bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success, memory_order failure) const noexcept; -bool compare_exchange_strong(T& expected, T desired, +constexpr bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success, memory_order failure) const noexcept; -bool compare_exchange_weak(T& expected, T desired, +constexpr bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order::seq_cst) const noexcept; -bool compare_exchange_strong(T& expected, T desired, +constexpr bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \expects \tcode{failure} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac\-quire}, or -\tcode{memory_order::seq_cst}. +\tcode{memory_order::acquire}, or +\tcode{memory_order::\linebreak seq_cst}. \pnum \effects @@ -3148,7 +3574,7 @@ \indexlibrarymember{wait}{atomic_ref}% \begin{itemdecl} -void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; +constexpr void wait(value_type old, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3156,8 +3582,7 @@ \expects \tcode{order} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac- \linebreak quire}, or +\tcode{memory_order::acquire}, or \tcode{memory_order::seq_cst}. \pnum @@ -3182,10 +3607,14 @@ \indexlibrarymember{notify_one}{atomic_ref}% \begin{itemdecl} -void notify_one() const noexcept; +constexpr void notify_one() const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \effects Unblocks the execution of at least one atomic waiting operation on \tcode{*ptr} @@ -3200,10 +3629,14 @@ \indexlibrarymember{notify_all}{atomic_ref}% \begin{itemdecl} -void notify_all() const noexcept; +constexpr void notify_all() const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \effects Unblocks the execution of all atomic waiting operations on \tcode{*ptr} @@ -3211,8 +3644,19 @@ \pnum \remarks - This function is an atomic notifying operation\iref{atomics.wait} - on atomic object \tcode{*ptr}. +This function is an atomic notifying operation\iref{atomics.wait} +on atomic object \tcode{*ptr}. +\end{itemdescr} + +\indexlibrarymember{address}{atomic_ref}% +\begin{itemdecl} +constexpr T* address() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{ptr}. \end{itemdescr} \rSec3[atomics.ref.int]{Specializations for integral types} @@ -3220,23 +3664,7 @@ \pnum \indexlibrary{\idxcode{atomic_ref<\placeholder{integral-type}>}}% 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 all integral types except \cv{} \tcode{bool}. For each such type \tcode{\placeholder{integral-type}}, the specialization \tcode{atomic_ref<\placeholder{integral-type}>} provides additional atomic operations appropriate to integral types. @@ -3245,6 +3673,11 @@ uses the primary template\iref{atomics.ref.generic}. \end{note} +\pnum +The program is ill-formed +if \tcode{is_always_lock_free} is \tcode{false} and +\tcode{is_volatile_v} is \tcode{true}. + \begin{codeblock} namespace std { template<> struct atomic_ref<@\placeholder{integral-type}@> { @@ -3252,57 +3685,77 @@ @\placeholder{integral-type}@* ptr; // \expos public: - using value_type = @\placeholder{integral-type}@; + using value_type = remove_cv_t<@\placeholder{integral-type}@>; 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-type}@&); - atomic_ref(const atomic_ref&) noexcept; + constexpr explicit atomic_ref(@\placeholder{integral-type}@&); + constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; - void store(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ operator=(@\placeholder{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ load(memory_order = memory_order::seq_cst) const noexcept; - operator @\placeholdernc{integral-type}@() const noexcept; + constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type operator=(value_type) const noexcept; + constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; + constexpr operator value_type() const noexcept; - @\placeholdernc{integral-type}@ exchange(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholder{integral-type}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholder{integral-type}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholder{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholder{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - - @\placeholdernc{integral-type}@ fetch_add(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_sub(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_and(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_or(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_xor(@\placeholdernc{integral-type}@, + constexpr value_type exchange(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr value_type fetch_add(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_sub(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_and(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_or(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_xor(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_max(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_min(value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr void store_add(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_sub(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_and(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_or(value_type, memory_order = memory_order::seq_cst) const noexcept; - - @\placeholdernc{integral-type}@ operator++(int) const noexcept; - @\placeholdernc{integral-type}@ operator--(int) const noexcept; - @\placeholdernc{integral-type}@ operator++() const noexcept; - @\placeholdernc{integral-type}@ operator--() const noexcept; - @\placeholdernc{integral-type}@ operator+=(@\placeholdernc{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ operator-=(@\placeholdernc{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ operator&=(@\placeholdernc{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ operator|=(@\placeholdernc{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ operator^=(@\placeholdernc{integral-type}@) const noexcept; - - void wait(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; + constexpr void store_xor(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_max(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_min(value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr value_type operator++(int) const noexcept; + constexpr value_type operator--(int) const noexcept; + constexpr value_type operator++() const noexcept; + constexpr value_type operator--() const noexcept; + constexpr value_type operator+=(value_type) const noexcept; + constexpr value_type operator-=(value_type) const noexcept; + constexpr value_type operator&=(value_type) const noexcept; + constexpr value_type operator|=(value_type) const noexcept; + constexpr value_type operator^=(value_type) const noexcept; + + constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr void notify_one() const noexcept; + constexpr void notify_all() const noexcept; + constexpr @\placeholder{integral-type}@* address() const noexcept; }; } \end{codeblock} @@ -3318,15 +3771,21 @@ \indexlibrarymember{fetch_add}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{fetch_and}{atomic_ref<\placeholder{integral-type}>}% +\indexlibrarymember{fetch_max}{atomic_ref<\placeholder{integral-type}>}% +\indexlibrarymember{fetch_min}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{fetch_or}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{fetch_xor}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -@\placeholdernc{integral-type}@ fetch_@\placeholdernc{key}@(@\placeholdernc{integral-type}@ operand, +constexpr value_type fetch_@\placeholdernc{key}@(value_type operand, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{integral-type}>} is \tcode{false}. + \pnum \effects Atomically replaces the value referenced by \tcode{*ptr} with @@ -3343,7 +3802,7 @@ \pnum \indextext{signed integer representation!two's complement}% \remarks -For signed integer types, +Except for \tcode{fetch_max} and \tcode{fetch_min}, 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 @@ -3351,6 +3810,55 @@ \begin{note} There are no undefined results arising from the computation. \end{note} + +\pnum +For \tcode{fetch_max} and \tcode{fetch_min}, the maximum and minimum +computation is performed as if by \tcode{max} and \tcode{min} +algorithms\iref{alg.min.max}, respectively, +with the object value and the first parameter as the arguments. +\end{itemdescr} + +\indexlibrarymember{store_add}{atomic_ref<\placeholder{integral-type}>}% +\indexlibrarymember{store_and}{atomic_ref<\placeholder{integral-type}>}% +\indexlibrarymember{store_max}{atomic_ref<\placeholder{integral-type}>}% +\indexlibrarymember{store_min}{atomic_ref<\placeholder{integral-type}>}% +\indexlibrarymember{store_or}{atomic_ref<\placeholder{integral-type}>}% +\indexlibrarymember{store_sub}{atomic_ref<\placeholder{integral-type}>}% +\begin{itemdecl} +constexpr void store_@\placeholdernc{key}@(value_type operand, + memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is \tcode{memory_order::relaxed}, +\tcode{memory_order::release}, or +\tcode{memory_order::seq_cst}. + +\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 \tcode{operand}. +Memory is affected according to the value of \tcode{order}. +These operations are atomic modify-write operations\iref{atomics.order}. + +\pnum +\remarks +Except for \tcode{store_max} and \tcode{store_min}, +for signed integer types, +the result is as if \tcode{*ptr} 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} +For \tcode{store_max} and \tcode{store_min}, +the maximum and minimum computation is performed +as if by \tcode{max} and \tcode{min} algorithms\iref{alg.min.max}, respectively, +with \tcode{*ptr} and the first parameter as the arguments. \end{itemdescr} \indexlibrarymember{operator+=}{atomic_ref<\placeholder{integral-type}>}% @@ -3359,10 +3867,14 @@ \indexlibrarymember{operator"|=}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{operator\caret=}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -@\placeholdernc{integral-type}@ operator @\placeholder{op}@=(@\placeholdernc{integral-type}@ operand) const noexcept; +constexpr value_type operator @\placeholder{op}@=(value_type operand) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{integral-type}>} is \tcode{false}. + \pnum \effects Equivalent to: @@ -3374,11 +3886,16 @@ \pnum \indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point-type}>}}% There are specializations of the \tcode{atomic_ref} class template -for all cv-unqualified floating-point types. +for all floating-point types. For each such type \tcode{\placeholder{floating-point-type}}, -the specialization \tcode{atomic_ref<\placeholder{floating-\-point}>} provides +the specialization \tcode{atomic_ref<\placeholder{floating-\-point-type}>} provides additional atomic operations appropriate to floating-point types. +\pnum +The program is ill-formed +if \tcode{is_always_lock_free} is \tcode{false} and +\tcode{is_volatile_v} is \tcode{true}. + \begin{codeblock} namespace std { template<> struct atomic_ref<@\placeholder{floating-point-type}@> { @@ -3386,44 +3903,73 @@ @\placeholder{floating-point-type}@* ptr; // \expos public: - using value_type = @\placeholder{floating-point-type}@; + using value_type = remove_cv_t<@\placeholder{floating-point-type}@>; 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-type}@&); - atomic_ref(const atomic_ref&) noexcept; + constexpr explicit atomic_ref(@\placeholder{floating-point-type}@&); + constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; - void store(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point-type}@ operator=(@\placeholder{floating-point-type}@) const noexcept; - @\placeholder{floating-point-type}@ load(memory_order = memory_order::seq_cst) const noexcept; - operator @\placeholdernc{floating-point-type}@() const noexcept; - - @\placeholder{floating-point-type}@ exchange(@\placeholdernc{floating-point-type}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, - memory_order, memory_order) const noexcept; - bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, - memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, - memory_order = memory_order::seq_cst) const noexcept; + constexpr void store(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type operator=(value_type) const noexcept; + constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; + constexpr operator value_type() const noexcept; - @\placeholder{floating-point-type}@ fetch_add(@\placeholdernc{floating-point-type}@, + constexpr value_type exchange(value_type, memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point-type}@ fetch_sub(@\placeholdernc{floating-point-type}@, + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr value_type fetch_add(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_sub(value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr value_type fetch_max(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_min(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_fmaximum(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_fminimum(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_fmaximum_num(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_fminimum_num(value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr void store_add(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_sub(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_max(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_min(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_fmaximum(value_type, memory_order = memory_order::seq_cst) const noexcept; - - @\placeholder{floating-point-type}@ operator+=(@\placeholder{floating-point-type}@) const noexcept; - @\placeholder{floating-point-type}@ operator-=(@\placeholder{floating-point-type}@) const noexcept; - - void wait(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; + constexpr void store_fminimum(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_fmaximum_num(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_fminimum_num(value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr value_type operator+=(value_type) const noexcept; + constexpr value_type operator-=(value_type) const noexcept; + + constexpr void wait(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr void notify_one() const noexcept; + constexpr void notify_all() const noexcept; + constexpr @\placeholder{floating-point-type}@* address() const noexcept; }; } \end{codeblock} @@ -3435,16 +3981,34 @@ \pnum The following operations perform arithmetic computations. The correspondence among key, operator, and computation is specified -in \tref{atomic.types.int.comp}. +in \tref{atomic.types.int.comp}, +except for the keys +\tcode{max}, +\tcode{min}, +\tcode{fmaximum}, +\tcode{fminimum}, +\tcode{fmaximum_num}, and +\tcode{fminimum_num}, +which are specified below. \indexlibrarymember{fetch_add}{atomic_ref<\placeholder{floating-point-type}>}% \indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{floating-point-type}>}% -\begin{itemdecl} -@\placeholder{floating-point-type}@ fetch_@\placeholdernc{key}@(@\placeholder{floating-point-type}@ operand, +\indexlibrarymember{fetch_fmaximum}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fminimum}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fmaximum_num}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fminimum_num}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_max}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_min}{atomic_ref<\placeholder{floating-point-type}>}% +\begin{itemdecl} +constexpr value_type fetch_@\placeholdernc{key}@(value_type operand, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\exposid{floating-point-type}>} is \tcode{false}. + \pnum \effects Atomically replaces the value referenced by \tcode{*ptr} with @@ -3464,20 +4028,141 @@ the result is unspecified, but the operations otherwise have no undefined behavior. Atomic arithmetic operations on \tcode{\placeholder{floating-point-type}} should conform to -the \tcode{std::numeric_limits<\placeholder{floating-point-type}>} traits +the \tcode{std::numeric_limits} traits associated with the floating-point type\iref{limits.syn}. The floating-point environment\iref{cfenv} +for atomic arithmetic operations on \tcode{\placeholder{floating-\brk{}point-type}} +may be different than the calling thread's floating-point environment. + +\pnum +\begin{itemize} +\item +For \tcode{fetch_fmaximum} and \tcode{fetch_fminimum}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum} and \tcode{fminimum}, respectively, +with \tcode{*ptr} and the first parameter as the arguments. +\item +For \tcode{fetch_fmaximum_num} and \tcode{fetch_fminimum_num}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, +with \tcode{*ptr} and the first parameter as the arguments. +\item +For \tcode{fetch_max} and \tcode{fetch_min}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, +with \tcode{*ptr} and the first parameter as the arguments, except that: +\begin{itemize} +\item +If both arguments are NaN, an unspecified NaN value is stored at \tcode{*ptr}. +\item +If exactly one argument is a NaN, +either the other argument or an unspecified NaN value is stored at \tcode{*ptr}; +it is unspecified which. +\item +If the arguments are differently signed zeros, +which of these values is stored at \tcode{*ptr} is unspecified. +\end{itemize} +\end{itemize} + +\pnum +\recommended +The implementation of \tcode{fetch_max} and \tcode{fetch_min} +should treat negative zero as smaller than positive zero. +\end{itemdescr} + +\indexlibrarymember{store_add}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{store_sub}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{store_min}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{store_max}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{store_fminimum}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{store_fmaximum}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{store_fminimum_num}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{store_fmaximum_num}{atomic_ref<\placeholder{floating-point-type}>}% +\begin{itemdecl} +constexpr void store_@\placeholdernc{key}@(value_type operand, + memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{order} is \tcode{memory_order::relaxed}, +\tcode{memory_order::release}, or +\tcode{memory_order::seq_cst}. + +\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 \tcode{operand}. +Memory is affected according to the value of \tcode{order}. +These operations are atomic modify-write operations\iref{atomics.order}. + +\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-type}} +should conform to the \tcode{numeric_limits<\placeholder{floating-point-type}>} +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-type}} may be different than the calling thread's floating-point environment. +The arithmetic rules of floating-point atomic modify-write operations +may be different from operations on floating-point types or +atomic floating-point types. +\begin{note} +Tree reductions are permitted for atomic modify-write operations. +\end{note} + +\pnum +\begin{itemize} +\item +For \tcode{store_fmaximum} and \tcode{store_fminimum}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum} and \tcode{fminimum}, respectively, +with \tcode{*ptr} and the first parameter as the arguments. +\item +For \tcode{store_fmaximum_num} and \tcode{store_fminimum_num}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum_num }and \tcode{fminimum_num}, respectively, +with \tcode{*ptr} and the first parameter as the arguments. +\item +For \tcode{store_max} and \tcode{store_min}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, +with \tcode{*ptr} and the first parameter as the arguments, except that: +\begin{itemize} +\item +If both arguments are NaN, an unspecified NaN value is stored at \tcode{*ptr}. +\item +If exactly one argument is a NaN, +either the other argument or an unspecified NaN value is stored at \tcode{*ptr}, +it is unspecified which. +\item +If the arguments are differently signed zeros, +which of these values is stored at \tcode{*ptr} is unspecified. +\end{itemize} +\end{itemize} + +\pnum +\recommended +The implementation of \tcode{store_max} and \tcode{store_min} +should treat negative zero as smaller than positive zero. \end{itemdescr} \indexlibrarymember{operator+=}{atomic_ref<\placeholder{floating-point-type}>}% \indexlibrarymember{operator-=}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -@\placeholder{floating-point-type}@ operator @\placeholder{op}@=(@\placeholder{floating-point-type}@ operand) const noexcept; +constexpr value_type operator @\placeholder{op}@=(value_type operand) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\exposid{floating-point-type}>} is \tcode{false}. + \pnum \effects Equivalent to: @@ -3487,52 +4172,81 @@ \rSec3[atomics.ref.pointer]{Partial specialization for pointers} \indexlibraryglobal{atomic_ref}% +\pnum +There are specializations of the \tcode{atomic_ref} class template +for all pointer-to-object types. +For each such type \tcode{\placeholder{pointer-type}}, +the specialization \tcode{atomic_ref<\placeholder{pointer-type}>} provides +additional atomic operations appropriate to pointer types. + +\pnum +The program is ill-formed +if \tcode{is_always_lock_free} is \tcode{false} and +\tcode{is_volatile_v} is \tcode{true}. + \begin{codeblock} namespace std { - template struct atomic_ref { + template struct atomic_ref<@\placeholder{pointer-type}@> { private: - T** ptr; // \expos + @\placeholder{pointer-type}@* ptr; // \expos public: - using value_type = T*; + using value_type = remove_cv_t<@\placeholder{pointer-type}@>; 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; + constexpr explicit atomic_ref(@\placeholder{pointer-type}@&); + constexpr 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; + constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type operator=(value_type) const noexcept; + constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; + constexpr operator value_type() const noexcept; - void wait(T*, memory_order = memory_order::seq_cst) const noexcept; - void notify_one() const noexcept; - void notify_all() const noexcept; + constexpr value_type exchange(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order, memory_order) const noexcept; + constexpr bool compare_exchange_weak(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr bool compare_exchange_strong(value_type&, value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr value_type fetch_add(difference_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_sub(difference_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_max(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr value_type fetch_min(value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr void store_add(difference_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_sub(difference_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_max(value_type, + memory_order = memory_order::seq_cst) const noexcept; + constexpr void store_min(value_type, + memory_order = memory_order::seq_cst) const noexcept; + + constexpr value_type operator++(int) const noexcept; + constexpr value_type operator--(int) const noexcept; + constexpr value_type operator++() const noexcept; + constexpr value_type operator--() const noexcept; + constexpr value_type operator+=(difference_type) const noexcept; + constexpr value_type operator-=(difference_type) const noexcept; + + constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr void notify_one() const noexcept; + constexpr void notify_all() const noexcept; + constexpr @\placeholder{pointer-type}@* address() const noexcept; }; } \end{codeblock} @@ -3548,14 +4262,21 @@ \indexlibrarymember{fetch_add}{atomic_ref}% \indexlibrarymember{fetch_sub}{atomic_ref}% +\indexlibrarymember{fetch_max}{atomic_ref}% +\indexlibrarymember{fetch_min}{atomic_ref}% \begin{itemdecl} -T* fetch_@\placeholdernc{key}@(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept; +constexpr value_type fetch_@\placeholdernc{key}@(difference_type operand, + memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{pointer-type}>} is \tcode{false}. + \pnum \mandates -\tcode{T} is a complete object type. +\tcode{remove_pointer_t<\placeholder{pointer-type}>} is a complete object type. \pnum \effects @@ -3574,15 +4295,74 @@ \remarks The result may be an undefined address, but the operations otherwise have no undefined behavior. + +\pnum +For \tcode{fetch_max} and \tcode{fetch_min}, the maximum and minimum +computation is performed as if by \tcode{max} and \tcode{min} +algorithms\iref{alg.min.max}, respectively, with the object value and the first +parameter as the arguments. + +\begin{note} +If the pointers point to different complete objects (or subobjects thereof), +the \tcode{<} operator does not establish a strict weak ordering +(\tref{cpp17.lessthancomparable}, \ref{expr.rel}). +\end{note} +\end{itemdescr} + +\indexlibrarymember{store_add}{atomic_ref}% +\indexlibrarymember{store_sub}{atomic_ref}% +\indexlibrarymember{store_max}{atomic_ref}% +\indexlibrarymember{store_min}{atomic_ref}% +\begin{itemdecl} +constexpr void store_@\placeholdernc{key}@(@\UNSP{see above}@ operand, + memory_order order = memory_order::seq_cst) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{T} is a complete object type. + +\pnum +\expects +\tcode{order} is \tcode{memory_order::relaxed}, +\tcode{memory_order::release}, or +\tcode{memory_order::seq_cst}. + +\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 \tcode{operand}. +Memory is affected according to the value of \tcode{order}. +These operations are atomic modify-write operations\iref{atomics.order}. + +\pnum +\remarks +The result may be an undefined address, +but the operations otherwise have no undefined behavior. +For \tcode{store_max} and \tcode{store_min}, +the \tcode{maximum} and \tcode{minimum} computation is performed +as if by \tcode{max} and \tcode{min} algorithms\iref{alg.min.max}, respectively, +with \tcode{*ptr} and the first parameter as the arguments. +\begin{note} +If the pointers point to different complete objects (or subobjects thereof), +the \tcode{<} operator does not establish +a strict weak ordering~(\tref{cpp17.lessthancomparable}, \ref{expr.rel}). +\end{note} \end{itemdescr} \indexlibrarymember{operator+=}{atomic_ref}% \indexlibrarymember{operator-=}{atomic_ref}% \begin{itemdecl} -T* operator @\placeholder{op}@=(difference_type operand) const noexcept; +constexpr value_type operator @\placeholder{op}@=(difference_type operand) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{pointer-type}>} is \tcode{false}. + \pnum \effects Equivalent to: @@ -3592,13 +4372,25 @@ \rSec3[atomics.ref.memop]{Member operators common to integers and pointers to objects} +\pnum +Let \tcode{\placeholder{referred-type}} +be \tcode{\placeholder{pointer-type}} +for the specializations in \ref{atomics.ref.pointer} and +be \tcode{\placeholder{integral-type}} +for the specializations in \ref{atomics.ref.int}. + + \indexlibrarymember{operator++}{atomic_ref}% \indexlibrarymember{operator++}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -value_type operator++(int) const noexcept; +constexpr value_type operator++(int) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{referred-type}>} is \tcode{false}. + \pnum \effects Equivalent to: \tcode{return fetch_add(1);} @@ -3607,10 +4399,14 @@ \indexlibrarymember{operator--}{atomic_ref}% \indexlibrarymember{operator--}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -value_type operator--(int) const noexcept; +constexpr value_type operator--(int) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{referred-type}>} is \tcode{false}. + \pnum \effects Equivalent to: \tcode{return fetch_sub(1);} @@ -3619,10 +4415,14 @@ \indexlibrarymember{operator++}{atomic_ref}% \indexlibrarymember{operator++}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -value_type operator++() const noexcept; +constexpr value_type operator++() const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{referred-type}>} is \tcode{false}. + \pnum \effects Equivalent to: \tcode{return fetch_add(1) + 1;} @@ -3631,10 +4431,14 @@ \indexlibrarymember{operator--}{atomic_ref}% \indexlibrarymember{operator--}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -value_type operator--() const noexcept; +constexpr value_type operator--() const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{referred-type}>} is \tcode{false}. + \pnum \effects Equivalent to: \tcode{return fetch_sub(1) - 1;} @@ -3663,31 +4467,31 @@ 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; + constexpr T load(memory_order = memory_order::seq_cst) const noexcept; operator T() const volatile noexcept; - operator T() const noexcept; + constexpr 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; + constexpr void store(T, memory_order = memory_order::seq_cst) noexcept; T operator=(T) volatile noexcept; - T operator=(T) noexcept; + constexpr 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; + constexpr 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; + constexpr 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; + constexpr 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; + constexpr 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; + constexpr 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; + constexpr void wait(T, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; - void notify_one() noexcept; + constexpr void notify_one() noexcept; void notify_all() volatile noexcept; - void notify_all() noexcept; + constexpr void notify_all() noexcept; }; } \end{codeblock} @@ -3701,8 +4505,9 @@ \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} +\item \tcode{is_copy_assignable_v}, +\item \tcode{is_move_assignable_v}, or +\item \tcode{same_as>}, \end{itemize} is \tcode{false}. \begin{note} @@ -3733,7 +4538,7 @@ \begin{itemdescr} \pnum -\mandates +\constraints \tcode{is_default_constructible_v} is \tcode{true}. \pnum @@ -3815,7 +4620,7 @@ \indexlibrarymember{store}{atomic<\placeholder{floating-point-type}>}% \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; +constexpr void store(T desired, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3844,7 +4649,7 @@ \indexlibrarymember{operator=}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} T operator=(T desired) volatile noexcept; -T operator=(T desired) noexcept; +constexpr T operator=(T desired) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3870,7 +4675,7 @@ \indexlibrarymember{load}{atomic<\placeholder{floating-point-type}>}% \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; +constexpr T load(memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3883,8 +4688,7 @@ \expects \tcode{order} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac-\linebreak quire}, or +\tcode{memory_order::acquire}, or \tcode{memory_order::seq_cst}. \pnum @@ -3902,7 +4706,7 @@ \indexlibrarymember{operator \placeholder{floating-point-type}}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} operator T() const volatile noexcept; -operator T() const noexcept; +constexpr operator T() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3925,7 +4729,7 @@ \indexlibrarymember{exchange}{atomic<\placeholder{floating-point-type}>}% \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; +constexpr T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3961,19 +4765,19 @@ \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, +constexpr 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, +constexpr 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, +constexpr 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, +constexpr bool compare_exchange_strong(T& expected, T desired, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} @@ -3987,9 +4791,8 @@ \expects \tcode{failure} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac\-quire}, or -\tcode{memory_order::seq_cst}. +\tcode{memory_order::acquire}, or +\tcode{memory_order::\linebreak seq_cst}. \pnum \effects @@ -4083,7 +4886,7 @@ 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} +\IsoFloatUndated{}, 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==}. @@ -4134,7 +4937,7 @@ \indexlibrarymember{wait}{atomic<\placeholder{floating-point-type}>}% \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; +constexpr void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -4142,8 +4945,7 @@ \expects \tcode{order} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac-\linebreak quire}, or +\tcode{memory_order::acquire}, or \tcode{memory_order::seq_cst}. \pnum @@ -4171,7 +4973,7 @@ \indexlibrarymember{notify_one}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} void notify_one() volatile noexcept; -void notify_one() noexcept; +constexpr void notify_one() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4192,7 +4994,7 @@ \indexlibrarymember{notify_all}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} void notify_all() volatile noexcept; -void notify_all() noexcept; +constexpr void notify_all() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4252,81 +5054,118 @@ atomic& operator=(const atomic&) volatile = delete; void store(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - void store(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; + constexpr void store(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ operator=(@\placeholdernc{integral-type}@) volatile noexcept; - @\placeholdernc{integral-type}@ operator=(@\placeholdernc{integral-type}@) noexcept; + constexpr @\placeholdernc{integral-type}@ operator=(@\placeholdernc{integral-type}@) noexcept; @\placeholdernc{integral-type}@ load(memory_order = memory_order::seq_cst) const volatile noexcept; - @\placeholdernc{integral-type}@ load(memory_order = memory_order::seq_cst) const noexcept; + constexpr @\placeholdernc{integral-type}@ load(memory_order = memory_order::seq_cst) const noexcept; operator @\placeholdernc{integral-type}@() const volatile noexcept; - operator @\placeholdernc{integral-type}@() const noexcept; + constexpr operator @\placeholdernc{integral-type}@() const noexcept; @\placeholdernc{integral-type}@ exchange(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ exchange(@\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ exchange(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, + constexpr bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order, memory_order) noexcept; bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, + constexpr bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order, memory_order) noexcept; bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, + constexpr bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, + constexpr bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_add(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ fetch_add(@\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ fetch_add(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_sub(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ fetch_sub(@\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ fetch_sub(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_and(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ fetch_and(@\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ fetch_and(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_or(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ fetch_or(@\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ fetch_or(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ fetch_xor(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{integral-type}@ fetch_xor(@\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ fetch_xor(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{integral-type}@ fetch_max(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{integral-type}@ fetch_max( @\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{integral-type}@ fetch_min(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{integral-type}@ fetch_min(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) noexcept; + + void store_add(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_add(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) noexcept; + void store_sub(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_sub(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) noexcept; + void store_and(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_and(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) noexcept; + void store_or(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_or(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; + void store_xor(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_xor(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) noexcept; + void store_max(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_max(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) noexcept; + void store_min(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_min(@\placeholdernc{integral-type}@, + memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ operator++(int) volatile noexcept; - @\placeholdernc{integral-type}@ operator++(int) noexcept; + constexpr @\placeholdernc{integral-type}@ operator++(int) noexcept; @\placeholdernc{integral-type}@ operator--(int) volatile noexcept; - @\placeholdernc{integral-type}@ operator--(int) noexcept; + constexpr @\placeholdernc{integral-type}@ operator--(int) noexcept; @\placeholdernc{integral-type}@ operator++() volatile noexcept; - @\placeholdernc{integral-type}@ operator++() noexcept; + constexpr @\placeholdernc{integral-type}@ operator++() noexcept; @\placeholdernc{integral-type}@ operator--() volatile noexcept; - @\placeholdernc{integral-type}@ operator--() noexcept; + constexpr @\placeholdernc{integral-type}@ operator--() noexcept; @\placeholdernc{integral-type}@ operator+=(@\placeholdernc{integral-type}@) volatile noexcept; - @\placeholdernc{integral-type}@ operator+=(@\placeholdernc{integral-type}@) noexcept; + constexpr @\placeholdernc{integral-type}@ operator+=(@\placeholdernc{integral-type}@) noexcept; @\placeholdernc{integral-type}@ operator-=(@\placeholdernc{integral-type}@) volatile noexcept; - @\placeholdernc{integral-type}@ operator-=(@\placeholdernc{integral-type}@) noexcept; + constexpr @\placeholdernc{integral-type}@ operator-=(@\placeholdernc{integral-type}@) noexcept; @\placeholdernc{integral-type}@ operator&=(@\placeholdernc{integral-type}@) volatile noexcept; - @\placeholdernc{integral-type}@ operator&=(@\placeholdernc{integral-type}@) noexcept; + constexpr @\placeholdernc{integral-type}@ operator&=(@\placeholdernc{integral-type}@) noexcept; @\placeholdernc{integral-type}@ operator|=(@\placeholdernc{integral-type}@) volatile noexcept; - @\placeholdernc{integral-type}@ operator|=(@\placeholdernc{integral-type}@) noexcept; + constexpr @\placeholdernc{integral-type}@ operator|=(@\placeholdernc{integral-type}@) noexcept; @\placeholdernc{integral-type}@ operator^=(@\placeholdernc{integral-type}@) volatile noexcept; - @\placeholdernc{integral-type}@ operator^=(@\placeholdernc{integral-type}@) noexcept; + constexpr @\placeholdernc{integral-type}@ operator^=(@\placeholdernc{integral-type}@) noexcept; void wait(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) const noexcept; + constexpr void wait(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; - void notify_one() noexcept; + constexpr void notify_one() noexcept; void notify_all() volatile noexcept; - void notify_all() noexcept; + constexpr void notify_all() noexcept; }; } \end{codeblock} @@ -4357,38 +5196,50 @@ \tcode{add} & \tcode{+} & addition & +\tcode{and} & + \tcode{\&} & + bitwise and \\ \tcode{sub} & \tcode{-} & - subtraction \\ + subtraction & \tcode{or} & \tcode{|} & - bitwise inclusive or & + bitwise inclusive or \\ +\tcode{max} & + & + maximum & \tcode{xor} & \tcode{\caret} & bitwise exclusive or \\ -\tcode{and} & - \tcode{\&} & - bitwise and &&&\\ +\tcode{min} & + & + minimum &&&\\ \end{floattable} \indexlibraryglobal{atomic_fetch_add}% \indexlibraryglobal{atomic_fetch_and}% +\indexlibraryglobal{atomic_fetch_max}% +\indexlibraryglobal{atomic_fetch_min}% \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_max_explicit}% +\indexlibraryglobal{atomic_fetch_min_explicit}% \indexlibraryglobal{atomic_fetch_or_explicit}% \indexlibraryglobal{atomic_fetch_sub_explicit}% \indexlibraryglobal{atomic_fetch_xor_explicit}% \indexlibrarymember{fetch_add}{atomic<\placeholder{integral-type}>}% \indexlibrarymember{fetch_and}{atomic<\placeholder{integral-type}>}% +\indexlibrarymember{fetch_max}{atomic<\placeholder{integral-type}>}% +\indexlibrarymember{fetch_min}{atomic<\placeholder{integral-type}>}% \indexlibrarymember{fetch_or}{atomic<\placeholder{integral-type}>}% \indexlibrarymember{fetch_sub}{atomic<\placeholder{integral-type}>}% \indexlibrarymember{fetch_xor}{atomic<\placeholder{integral-type}>}% \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; +constexpr T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4412,7 +5263,7 @@ \pnum \indextext{signed integer representation!two's complement}% \remarks -For signed integer types, +Except for \tcode{fetch_max} and \tcode{fetch_min}, 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 @@ -4421,8 +5272,77 @@ There are no undefined results arising from the computation. \end{note} +\pnum +For \tcode{fetch_max} and \tcode{fetch_min}, the maximum and minimum +computation is performed as if by \tcode{max} and \tcode{min} +algorithms\iref{alg.min.max}, respectively, +with the object value and the first parameter as the arguments. +\end{itemdescr} + +\indexlibraryglobal{atomic_store_add}% +\indexlibraryglobal{atomic_store_and}% +\indexlibraryglobal{atomic_store_max}% +\indexlibraryglobal{atomic_store_min}% +\indexlibraryglobal{atomic_store_or}% +\indexlibraryglobal{atomic_store_sub}% +\indexlibraryglobal{atomic_store_add_explicit}% +\indexlibraryglobal{atomic_store_and_explicit}% +\indexlibraryglobal{atomic_store_max_explicit}% +\indexlibraryglobal{atomic_store_min_explicit}% +\indexlibraryglobal{atomic_store_or_explicit}% +\indexlibraryglobal{atomic_store_sub_explicit}% +\indexlibrarymember{store_add}{atomic<\placeholder{integral-type}>}% +\indexlibrarymember{store_and}{atomic<\placeholder{integral-type}>}% +\indexlibrarymember{store_max}{atomic<\placeholder{integral-type}>}% +\indexlibrarymember{store_min}{atomic<\placeholder{integral-type}>}% +\indexlibrarymember{store_or}{atomic<\placeholder{integral-type}>}% +\indexlibrarymember{store_sub}{atomic<\placeholder{integral-type}>}% +\begin{itemdecl} +void store_@\placeholdernc{key}@(@\placeholder{integral-type}@ operand, + memory_order order = memory_order::seq_cst) volatile noexcept; +constexpr void store_@\placeholdernc{key}@(@\placeholder{integral-type}@ 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 +\expects +\tcode{order} is +\tcode{memory_order::relaxed}, +\tcode{memory_order::release}, or +\tcode{memory_order::seq_cst}. + +\pnum +\effects +Atomically replaces the value pointed to by \tcode{this} +with the result of the computation applied to +the value pointed to by \tcode{this} and the given \tcode{operand}. +Memory is affected according to the value of \tcode{order}. +These operations are atomic modify-write operations\iref{atomics.order}. + +\pnum +\remarks +Except for \tcode{store_max} and \tcode{store_min}, +for signed integer types, the result is as if +the value pointed to by \tcode{this} 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} +For \tcode{store_max} and \tcode{store_min}, +the maximum and minimum computation is performed +as if by \tcode{max} and \tcode{min} algorithms\iref{alg.min.max}, respectively, +with the value pointed to by \tcode{this} and the first parameter as the arguments. \end{itemdescr} + \indexlibrarymember{operator+=}{atomic}% \indexlibrarymember{operator-=}{atomic}% \indexlibrarymember{operator+=}{atomic<\placeholder{integral-type}>}% @@ -4432,7 +5352,7 @@ \indexlibrarymember{operator\caret=}{atomic<\placeholder{integral-type}>}% \begin{itemdecl} T operator @\placeholder{op}@=(T operand) volatile noexcept; -T operator @\placeholder{op}@=(T operand) noexcept; +constexpr T operator @\placeholder{op}@=(T operand) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4473,55 +5393,113 @@ atomic& operator=(const atomic&) volatile = delete; void store(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - void store(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; + constexpr void store(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{floating-point-type}@ operator=(@\placeholder{floating-point-type}@) volatile noexcept; - @\placeholdernc{floating-point-type}@ operator=(@\placeholder{floating-point-type}@) noexcept; + constexpr @\placeholdernc{floating-point-type}@ operator=(@\placeholder{floating-point-type}@) noexcept; @\placeholdernc{floating-point-type}@ load(memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point-type}@ load(memory_order = memory_order::seq_cst) noexcept; + constexpr @\placeholdernc{floating-point-type}@ load(memory_order = memory_order::seq_cst) noexcept; operator @\placeholdernc{floating-point-type}@() volatile noexcept; - operator @\placeholdernc{floating-point-type}@() noexcept; + constexpr operator @\placeholdernc{floating-point-type}@() noexcept; @\placeholdernc{floating-point-type}@ exchange(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point-type}@ exchange(@\placeholdernc{floating-point-type}@, + constexpr @\placeholdernc{floating-point-type}@ exchange(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order, memory_order) volatile noexcept; - bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + constexpr bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order, memory_order) noexcept; bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order, memory_order) volatile noexcept; - bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + constexpr bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order, memory_order) noexcept; bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + constexpr bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + constexpr bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{floating-point-type}@ fetch_add(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point-type}@ fetch_add(@\placeholdernc{floating-point-type}@, + constexpr @\placeholdernc{floating-point-type}@ fetch_add(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{floating-point-type}@ fetch_sub(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - @\placeholdernc{floating-point-type}@ fetch_sub(@\placeholdernc{floating-point-type}@, + constexpr @\placeholdernc{floating-point-type}@ fetch_sub(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point-type}@ fetch_max(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_max(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point-type}@ fetch_min(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{floating-poin-type}@t fetch_min(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point-type}@ fetch_fmaximum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_fmaximum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point-type}@ fetch_fminimum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_fminimum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point-type}@ fetch_fmaximum_num(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_fmaximum_num(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point-type}@ fetch_fminimum_num(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_fminimum_num(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; + void store_add(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_add(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + void store_sub(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_sub(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + void store_max(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_max(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + void store_min(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_min(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + void store_fmaximum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_fmaximum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + void store_fminimum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_fminimum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + void store_fmaximum_num(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_fmaximum_num(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + void store_fminimum_num(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_fminimum_num(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point-type}@ operator+=(@\placeholder{floating-point-type}@) volatile noexcept; - @\placeholdernc{floating-point-type}@ operator+=(@\placeholder{floating-point-type}@) noexcept; + constexpr @\placeholdernc{floating-point-type}@ operator+=(@\placeholder{floating-point-type}@) noexcept; @\placeholdernc{floating-point-type}@ operator-=(@\placeholder{floating-point-type}@) volatile noexcept; - @\placeholdernc{floating-point-type}@ operator-=(@\placeholder{floating-point-type}@) noexcept; + constexpr @\placeholdernc{floating-point-type}@ operator-=(@\placeholder{floating-point-type}@) noexcept; void wait(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const volatile noexcept; - void wait(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; + constexpr void wait(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; - void notify_one() noexcept; + constexpr void notify_one() noexcept; void notify_all() volatile noexcept; - void notify_all() noexcept; + constexpr void notify_all() noexcept; }; } \end{codeblock} @@ -4538,7 +5516,15 @@ \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}. +in \tref{atomic.types.int.comp}, +except for the keys +\tcode{max}, +\tcode{min}, +\tcode{fmaximum}, +\tcode{fminimum}, +\tcode{fmaximum_num}, and +\tcode{fminimum_num}, +which are specified below. \indexlibraryglobal{atomic_fetch_add}% \indexlibraryglobal{atomic_fetch_sub}% @@ -4546,9 +5532,15 @@ \indexlibraryglobal{atomic_fetch_sub_explicit}% \indexlibrarymember{fetch_add}{atomic<\placeholder{floating-point-type}>}% \indexlibrarymember{fetch_sub}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fmaximum}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fminimum}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fmaximum_num}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fminimum_num}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_max}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_min}{atomic<\placeholder{floating-point-type}>}% \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; +constexpr T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4579,6 +5571,138 @@ The floating-point environment\iref{cfenv} for atomic arithmetic operations on \tcode{\placeholder{floating-point-type}} may be different than the calling thread's floating-point environment. + +\pnum +\begin{itemize} +\item +For \tcode{fetch_fmaximum} and \tcode{fetch_fminimum}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum} and \tcode{fminimum}, respectively, +with the value pointed to by \tcode{this} and the first parameter +as the arguments. +\item +For \tcode{fetch_fmaximum_num} and \tcode{fetch_fminimum_num}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, +with the value pointed to by \tcode{this} and the first parameter +as the arguments. +\item +For \tcode{fetch_max} and \tcode{fetch_min}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, +with the value pointed to by \tcode{this} and the first parameter +as the arguments, except that: +\begin{itemize} +\item +If both arguments are NaN, +an unspecified NaN value replaces the value pointed to by \tcode{this}. +\item +If exactly one argument is a NaN, +either the other argument or an unspecified NaN value +replaces the value pointed to by \tcode{this}; it is unspecified which. +\item +If the arguments are differently signed zeros, +which of these values replaces the value pointed to by this is unspecified. +\end{itemize} +\end{itemize} + +\pnum +\recommended +The implementation of \tcode{fetch_max} and \tcode{fetch_min} +should treat negative zero as smaller than positive zero. +\end{itemdescr} + +\indexlibrarymember{store_max}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{store_min}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{store_fmaximum}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{store_fminimum}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{store_fmaximum_num}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{store_fminimum_num}{atomic<\placeholder{floating-point-type}>}% +\begin{itemdecl} +void store_@\placeholdernc{key}@(@\placeholdernc{floating-point-type}@ operand, + memory_order order = memory_order::seq_cst) volatile noexcept; +constexpr void store_@\placeholdernc{key}@(@\placeholdernc{floating-point-type}@ 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 +\expects +\tcode{order} is +\tcode{memory_order::relaxed}, +\tcode{memory_order::release}, or +\tcode{memory_order::seq_cst}. + +\pnum +\effects +Atomically replaces the value pointed to by \tcode{this} +with the result of the computation applied to +the value pointed to by \tcode{this} and the given operand. +Memory is affected according to the value of \tcode{order}. +These operations are atomic modify-write operations\iref{atomics.order}. + +\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-type}} +should conform to the \tcode{numeric_limits<\placeholder{floating-point-type}>} +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-type}} +may be different than the calling thread's floating-point environment. +The arithmetic rules of floating-point atomic modify-write operations +may be different from operations on +floating-point types or atomic floating-point types. +\begin{note} +Tree reductions are permitted for atomic modify-write operations. +\end{note} + +\pnum +\begin{itemize} +\item +For \tcode{store_fmaximum} and \tcode{store_fminimum}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum} and \tcode{fminimum}, respectively, +with the value pointed to by \tcode{this} and +the first parameter as the arguments. +\item +For \tcode{store_fmaximum_num} and \tcode{store_fminimum_num}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, +with the value pointed to by \tcode{this} and +the first parameter as the arguments. +\item +For \tcode{store_max} and \tcode{store_min}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, +with the value pointed to by \tcode{this} and +the first parameter as the arguments, except that: +\begin{itemize} +\item +If both arguments are NaN, +an unspecified NaN value replaces the value pointed to by \tcode{this}. +\item +If exactly one argument is a NaN, +either the other argument or an unspecified NaN value replaces +the value pointed to by \tcode{this}; +it is unspecified which. +\item +If the arguments are differently signed zeros, +which of these values replaces the value pointed to by \tcode{this} is unspecified. +\end{itemize} +\end{itemize} + +\pnum +\recommended +The implementation of \tcode{store_max} and \tcode{store_min} +should treat negative zero as smaller than positive zero. \end{itemdescr} \indexlibrarymember{operator+=}{atomic}% @@ -4587,7 +5711,7 @@ \indexlibrarymember{operator-=}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} T operator @\placeholder{op}@=(T operand) volatile noexcept; -T operator @\placeholder{op}@=(T operand) noexcept; +constexpr T operator @\placeholder{op}@=(T operand) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4632,53 +5756,66 @@ 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; + constexpr void store(T*, memory_order = memory_order::seq_cst) noexcept; T* operator=(T*) volatile noexcept; - T* operator=(T*) noexcept; + constexpr 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; + constexpr T* load(memory_order = memory_order::seq_cst) const noexcept; operator T*() const volatile noexcept; - operator T*() const noexcept; + constexpr 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; + constexpr 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; + constexpr 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; + constexpr 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*, + constexpr 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*, + constexpr 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; + constexpr 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; + constexpr T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; + T* fetch_max(T*, memory_order = memory_order::seq_cst) volatile noexcept; + constexpr T* fetch_max(T*, memory_order = memory_order::seq_cst) noexcept; + T* fetch_min(T*, memory_order = memory_order::seq_cst) volatile noexcept; + constexpr T* fetch_min(T*, memory_order = memory_order::seq_cst) noexcept; + + void store_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; + void store_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; + void store_max(T*, memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_max(T*, memory_order = memory_order::seq_cst) noexcept; + void store_min(T*, memory_order = memory_order::seq_cst) volatile noexcept; + constexpr void store_min(T*, memory_order = memory_order::seq_cst) noexcept; T* operator++(int) volatile noexcept; - T* operator++(int) noexcept; + constexpr T* operator++(int) noexcept; T* operator--(int) volatile noexcept; - T* operator--(int) noexcept; + constexpr T* operator--(int) noexcept; T* operator++() volatile noexcept; - T* operator++() noexcept; + constexpr T* operator++() noexcept; T* operator--() volatile noexcept; - T* operator--() noexcept; + constexpr T* operator--() noexcept; T* operator+=(ptrdiff_t) volatile noexcept; - T* operator+=(ptrdiff_t) noexcept; + constexpr T* operator+=(ptrdiff_t) noexcept; T* operator-=(ptrdiff_t) volatile noexcept; - T* operator-=(ptrdiff_t) noexcept; + constexpr 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; + constexpr void wait(T*, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; - void notify_one() noexcept; + constexpr void notify_one() noexcept; void notify_all() volatile noexcept; - void notify_all() noexcept; + constexpr void notify_all() noexcept; }; } \end{codeblock} @@ -4712,17 +5849,29 @@ \tcode{sub} & \tcode{-} & subtraction \\ +\tcode{max} & + & + maximum & +\tcode{min} & + & + minimum \\ \end{floattable} \indexlibraryglobal{atomic_fetch_add}% +\indexlibraryglobal{atomic_fetch_max}% +\indexlibraryglobal{atomic_fetch_min}% \indexlibraryglobal{atomic_fetch_sub}% \indexlibraryglobal{atomic_fetch_add_explicit}% +\indexlibraryglobal{atomic_fetch_max_explicit}% +\indexlibraryglobal{atomic_fetch_min_explicit}% \indexlibraryglobal{atomic_fetch_sub_explicit}% \indexlibrarymember{fetch_add}{atomic}% +\indexlibrarymember{fetch_max}{atomic}% +\indexlibrarymember{fetch_min}{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; +constexpr T* fetch_@\placeholdernc{key}@(ptrdiff_t operand, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4754,13 +5903,79 @@ \remarks The result may be an undefined address, but the operations otherwise have no undefined behavior. + +\pnum +For \tcode{fetch_max} and \tcode{fetch_min}, the maximum and minimum +computation is performed as if by \tcode{max} and \tcode{min} +algorithms\iref{alg.min.max}, respectively, with the object value and the first +parameter as the arguments. + +\begin{note} +If the pointers point to different complete objects (or subobjects thereof), +the \tcode{<} operator does not establish a strict weak ordering +(\tref{cpp17.lessthancomparable}, \ref{expr.rel}). +\end{note} +\end{itemdescr} + +\indexlibraryglobal{atomic_store_add}% +\indexlibraryglobal{atomic_store_max}% +\indexlibraryglobal{atomic_store_min}% +\indexlibraryglobal{atomic_store_sub}% +\indexlibraryglobal{atomic_store_add_explicit}% +\indexlibraryglobal{atomic_store_max_explicit}% +\indexlibraryglobal{atomic_store_min_explicit}% +\indexlibraryglobal{atomic_store_sub_explicit}% +\indexlibrarymember{store_add}{atomic}% +\indexlibrarymember{store_max}{atomic}% +\indexlibrarymember{store_min}{atomic}% +\indexlibrarymember{store_sub}{atomic}% +\begin{itemdecl} +void store_@\placeholdernc{key}@(@\seeabovenc@ operand, memory_order order = memory_order::seq_cst) volatile noexcept; +constexpr void store_@\placeholdernc{key}@(@\seeabovenc@ 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 \tcode{this} +with the result of the computation applied to +the value pointed to by \tcode{this} and the given \tcode{operand}. +Memory is affected according to the value of \tcode{order}. +These operations are atomic modify-write operations\iref{atomics.order}. + +\pnum +\remarks +The result may be an undefined address, +but the operations otherwise have no undefined behavior. +For \tcode{store_max} and \tcode{store_min}, +the maximum and minimum computation is performed +as if by \tcode{max} and \tcode{min} algorithms\iref{alg.min.max}, respectively, +with the value pointed to by \tcode{this} and +the first parameter as the arguments. +\begin{note} +If the pointers point to different complete objects (or subobjects thereof), +the \tcode{<} operator does not establish +a strict weak ordering~(\tref{cpp17.lessthancomparable}, \ref{expr.rel}). +\end{note} \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; +constexpr T* operator @\placeholder{op}@=(ptrdiff_t operand) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4780,7 +5995,7 @@ \indexlibrarymember{operator++}{atomic<\placeholder{integral-type}>}% \begin{itemdecl} value_type operator++(int) volatile noexcept; -value_type operator++(int) noexcept; +constexpr value_type operator++(int) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4798,7 +6013,7 @@ \indexlibrarymember{operator--}{atomic<\placeholder{integral-type}>}% \begin{itemdecl} value_type operator--(int) volatile noexcept; -value_type operator--(int) noexcept; +constexpr value_type operator--(int) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4816,7 +6031,7 @@ \indexlibrarymember{operator++}{atomic<\placeholder{integral-type}>}% \begin{itemdecl} value_type operator++() volatile noexcept; -value_type operator++() noexcept; +constexpr value_type operator++() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4834,7 +6049,7 @@ \indexlibrarymember{operator--}{atomic<\placeholder{integral-type}>}% \begin{itemdecl} value_type operator--() volatile noexcept; -value_type operator--() noexcept; +constexpr value_type operator--() noexcept; \end{itemdecl} \begin{itemdescr} @@ -4923,30 +6138,32 @@ constexpr atomic() noexcept; constexpr atomic(nullptr_t) noexcept : atomic() { } - atomic(shared_ptr desired) noexcept; + constexpr 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; - void operator=(nullptr_t) 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; + constexpr shared_ptr load(memory_order order = memory_order::seq_cst) const noexcept; + constexpr operator shared_ptr() const noexcept; + constexpr void store(shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + constexpr void operator=(shared_ptr desired) noexcept; + constexpr void operator=(nullptr_t) noexcept; + + constexpr shared_ptr exchange(shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + constexpr bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, + memory_order success, memory_order failure) noexcept; + constexpr bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, + memory_order success, memory_order failure) noexcept; + constexpr bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + constexpr bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + + constexpr void wait(shared_ptr old, + memory_order order = memory_order::seq_cst) const noexcept; + constexpr void notify_one() noexcept; + constexpr void notify_all() noexcept; private: shared_ptr p; // \expos @@ -4962,12 +6179,12 @@ \begin{itemdescr} \pnum \effects -Initializes \tcode{p\{\}}. +Value-initializes \tcode{p}. \end{itemdescr} \indexlibraryctor{atomic>}% \begin{itemdecl} -atomic(shared_ptr desired) noexcept; +constexpr atomic(shared_ptr desired) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4989,7 +6206,7 @@ \indexlibrarymember{store}{atomic>}% \begin{itemdecl} -void store(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; +constexpr void store(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5009,7 +6226,7 @@ \indexlibrarymember{operator=}{atomic>}% \begin{itemdecl} -void operator=(shared_ptr desired) noexcept; +constexpr void operator=(shared_ptr desired) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5020,7 +6237,7 @@ \indexlibrarymember{operator=}{atomic>}% \begin{itemdecl} -void operator=(nullptr_t) noexcept; +constexpr void operator=(nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5031,7 +6248,7 @@ \indexlibrarymember{load}{atomic>}% \begin{itemdecl} -shared_ptr load(memory_order order = memory_order::seq_cst) const noexcept; +constexpr shared_ptr load(memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -5039,8 +6256,7 @@ \expects \tcode{order} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac-\linebreak quire}, or +\tcode{memory_order::acquire}, or \tcode{memory_order::seq_cst}. \pnum @@ -5054,7 +6270,7 @@ \indexlibrarymember{operator shared_ptr}{atomic>}% \begin{itemdecl} -operator shared_ptr() const noexcept; +constexpr operator shared_ptr() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -5065,7 +6281,8 @@ \indexlibrarymember{exchange}{atomic>}% \begin{itemdecl} -shared_ptr exchange(shared_ptr desired, memory_order order = memory_order::seq_cst) noexcept; +constexpr shared_ptr exchange(shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5084,10 +6301,10 @@ \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; +constexpr bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, + memory_order success, memory_order failure) noexcept; +constexpr bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, + memory_order success, memory_order failure) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5095,9 +6312,8 @@ \expects \tcode{failure} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac\-quire}, or -\tcode{memory_order::seq_cst}. +\tcode{memory_order::acquire}, or +\tcode{memory_order::\linebreak seq_cst}. \pnum \effects @@ -5135,8 +6351,8 @@ \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; +constexpr bool compare_exchange_weak(shared_ptr& expected, shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5155,8 +6371,8 @@ \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; +constexpr bool compare_exchange_strong(shared_ptr& expected, shared_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5175,7 +6391,7 @@ \indexlibrarymember{wait}{atomic>}% \begin{itemdecl} -void wait(shared_ptr old, memory_order order = memory_order::seq_cst) const noexcept; +constexpr void wait(shared_ptr old, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -5183,8 +6399,7 @@ \expects \tcode{order} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac-\linebreak quire}, or +\tcode{memory_order::acquire}, or \tcode{memory_order::seq_cst}. \pnum @@ -5209,7 +6424,7 @@ \indexlibrarymember{notify_one}{atomic>}% \begin{itemdecl} -void notify_one() noexcept; +constexpr void notify_one() noexcept; \end{itemdecl} \begin{itemdescr} @@ -5226,7 +6441,7 @@ \indexlibrarymember{notify_all}{atomic>}% \begin{itemdecl} -void notify_all() noexcept; +constexpr void notify_all() noexcept; \end{itemdecl} \begin{itemdescr} @@ -5252,29 +6467,31 @@ bool is_lock_free() const noexcept; constexpr atomic() noexcept; - atomic(weak_ptr desired) noexcept; + constexpr 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, + constexpr weak_ptr load(memory_order order = memory_order::seq_cst) const noexcept; + constexpr operator weak_ptr() const noexcept; + constexpr void store(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; + constexpr void operator=(weak_ptr desired) noexcept; + + constexpr weak_ptr exchange(weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + constexpr bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, + memory_order success, memory_order failure) noexcept; + constexpr bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, + memory_order success, memory_order failure) noexcept; + constexpr bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + constexpr bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; + + constexpr void wait(weak_ptr old, + memory_order order = memory_order::seq_cst) const noexcept; + constexpr void notify_one() noexcept; + constexpr void notify_all() noexcept; private: weak_ptr p; // \expos @@ -5290,12 +6507,12 @@ \begin{itemdescr} \pnum \effects -Initializes \tcode{p\{\}}. +Value-initializes \tcode{p}. \end{itemdescr} \indexlibraryctor{atomic>}% \begin{itemdecl} -atomic(weak_ptr desired) noexcept; +constexpr atomic(weak_ptr desired) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5317,7 +6534,7 @@ \indexlibrarymember{store}{atomic>}% \begin{itemdecl} -void store(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; +constexpr void store(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5337,7 +6554,7 @@ \indexlibrarymember{operator=}{atomic>}% \begin{itemdecl} -void operator=(weak_ptr desired) noexcept; +constexpr void operator=(weak_ptr desired) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5348,7 +6565,7 @@ \indexlibrarymember{load}{atomic>}% \begin{itemdecl} -weak_ptr load(memory_order order = memory_order::seq_cst) const noexcept; +constexpr weak_ptr load(memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -5356,8 +6573,7 @@ \expects \tcode{order} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac-\linebreak quire}, or +\tcode{memory_order::acquire}, or \tcode{memory_order::seq_cst}. \pnum @@ -5371,7 +6587,7 @@ \indexlibrarymember{operator weak_ptr}{atomic>}% \begin{itemdecl} -operator weak_ptr() const noexcept; +constexpr operator weak_ptr() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -5382,7 +6598,8 @@ \indexlibrarymember{exchange}{atomic>}% \begin{itemdecl} -weak_ptr exchange(weak_ptr desired, memory_order order = memory_order::seq_cst) noexcept; +constexpr weak_ptr exchange(weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5400,10 +6617,10 @@ \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; +constexpr bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, + memory_order success, memory_order failure) noexcept; +constexpr bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, + memory_order success, memory_order failure) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5411,9 +6628,8 @@ \expects \tcode{failure} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac\-quire}, or -\tcode{memory_order::seq_cst}. +\tcode{memory_order::acquire}, or +\tcode{memory_order::\linebreak seq_cst}. \pnum \effects @@ -5451,8 +6667,8 @@ \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; +constexpr bool compare_exchange_weak(weak_ptr& expected, weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5471,8 +6687,8 @@ \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; +constexpr bool compare_exchange_strong(weak_ptr& expected, weak_ptr desired, + memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5491,7 +6707,7 @@ \indexlibrarymember{wait}{atomic>}% \begin{itemdecl} -void wait(weak_ptr old, memory_order order = memory_order::seq_cst) const noexcept; +constexpr void wait(weak_ptr old, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -5499,8 +6715,7 @@ \expects \tcode{order} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac-\linebreak quire}, or +\tcode{memory_order::acquire}, or \tcode{memory_order::seq_cst}. \pnum @@ -5526,7 +6741,7 @@ \indexlibrarymember{notify_one}{atomic>}% \begin{itemdecl} -void notify_one() noexcept; +constexpr void notify_one() noexcept; \end{itemdecl} \begin{itemdescr} @@ -5543,7 +6758,7 @@ \indexlibrarymember{notify_all}{atomic>}% \begin{itemdecl} -void notify_all() noexcept; +constexpr void notify_all() noexcept; \end{itemdecl} \begin{itemdescr} @@ -5587,18 +6802,18 @@ 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; + constexpr 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; + constexpr 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; + constexpr 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; + constexpr void wait(bool, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; - void notify_one() noexcept; + constexpr void notify_one() noexcept; void notify_all() volatile noexcept; - void notify_all() noexcept; + constexpr void notify_all() noexcept; }; } \end{codeblock} @@ -5630,13 +6845,13 @@ \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; +constexpr 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, +constexpr 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; +constexpr bool atomic_flag::test(memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -5647,8 +6862,7 @@ \expects \tcode{order} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac-\linebreak quire}, or +\tcode{memory_order::acquire}, or \tcode{memory_order::seq_cst}. \pnum @@ -5665,11 +6879,11 @@ \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; +constexpr 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; +constexpr 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; +constexpr bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5688,11 +6902,11 @@ \indexlibrarymember{clear}{atomic_flag}% \begin{itemdecl} void atomic_flag_clear(volatile atomic_flag* object) noexcept; -void atomic_flag_clear(atomic_flag* object) noexcept; +constexpr 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; +constexpr 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; +constexpr void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5714,14 +6928,14 @@ \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; +constexpr 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, +constexpr 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 = +constexpr void atomic_flag::wait(bool old, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} @@ -5736,8 +6950,7 @@ \expects \tcode{order} is \tcode{memory_order::relaxed}, -\tcode{memory_order::consume}, -\tcode{memory_order::ac-\linebreak quire}, or +\tcode{memory_order::acquire}, or \tcode{memory_order::seq_cst}. \pnum @@ -5760,9 +6973,9 @@ \begin{itemdecl} void atomic_flag_notify_one(volatile atomic_flag* object) noexcept; -void atomic_flag_notify_one(atomic_flag* object) noexcept; +constexpr void atomic_flag_notify_one(atomic_flag* object) noexcept; void atomic_flag::notify_one() volatile noexcept; -void atomic_flag::notify_one() noexcept; +constexpr void atomic_flag::notify_one() noexcept; \end{itemdecl} \begin{itemdescr} @@ -5779,9 +6992,9 @@ \begin{itemdecl} void atomic_flag_notify_all(volatile atomic_flag* object) noexcept; -void atomic_flag_notify_all(atomic_flag* object) noexcept; +constexpr void atomic_flag_notify_all(atomic_flag* object) noexcept; void atomic_flag::notify_all() volatile noexcept; -void atomic_flag::notify_all() noexcept; +constexpr void atomic_flag::notify_all() noexcept; \end{itemdecl} \begin{itemdescr} @@ -5795,9 +7008,8 @@ This function is an atomic notifying operation\iref{atomics.wait}. \end{itemdescr} -\indexlibraryglobal{ATOMIC_FLAG_INIT}% \begin{itemdecl} -#define ATOMIC_FLAG_INIT @\seebelow@ +#define @\libmacro{ATOMIC_FLAG_INIT}@ @\seebelow@ \end{itemdecl} \begin{itemdescr} @@ -5825,7 +7037,9 @@ \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 +atomic operations $X$ and $Y$, +where $Y$ is not an atomic modify-write operation\iref{atomics.order}, +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 @@ -5848,7 +7062,7 @@ \indexlibraryglobal{atomic_thread_fence}% \begin{itemdecl} -extern "C" void atomic_thread_fence(memory_order order) noexcept; +extern "C" constexpr void atomic_thread_fence(memory_order order) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5858,7 +7072,7 @@ \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 an acquire fence, if \tcode{order == memory_order::acquire}; \item is a release fence, if \tcode{order == memory_order::release}; @@ -5870,7 +7084,7 @@ \indexlibraryglobal{atomic_signal_fence}% \begin{itemdecl} -extern "C" void atomic_signal_fence(memory_order order) noexcept; +extern "C" constexpr void atomic_signal_fence(memory_order order) noexcept; \end{itemdecl} \begin{itemdescr} @@ -5898,18 +7112,18 @@ template using @\exposid{std-atomic}@ = std::atomic; // \expos -#define _Atomic(T) @\exposid{std-atomic}@ +#define @\libmacro{_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@ +#define @\libmacro{ATOMIC_BOOL_LOCK_FREE}@ @\seebelow@ +#define @\libmacro{ATOMIC_CHAR_LOCK_FREE}@ @\seebelow@ +#define @\libmacro{ATOMIC_CHAR16_T_LOCK_FREE}@ @\seebelow@ +#define @\libmacro{ATOMIC_CHAR32_T_LOCK_FREE}@ @\seebelow@ +#define @\libmacro{ATOMIC_WCHAR_T_LOCK_FREE}@ @\seebelow@ +#define @\libmacro{ATOMIC_SHORT_LOCK_FREE}@ @\seebelow@ +#define @\libmacro{ATOMIC_INT_LOCK_FREE}@ @\seebelow@ +#define @\libmacro{ATOMIC_LONG_LOCK_FREE}@ @\seebelow@ +#define @\libmacro{ATOMIC_LLONG_LOCK_FREE}@ @\seebelow@ +#define @\libmacro{ATOMIC_POINTER_LOCK_FREE}@ @\seebelow@ using std::@\libglobal{memory_order}@; // \seebelow using std::@\libglobal{memory_order_relaxed}@; // \seebelow @@ -5993,7 +7207,7 @@ 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 -#define ATOMIC_FLAG_INIT @\seebelow@ +#define @\libmacro{ATOMIC_FLAG_INIT}@ @\seebelow@ using std::@\libglobal{atomic_thread_fence}@; // \seebelow using std::@\libglobal{atomic_signal_fence}@; // \seebelow @@ -6003,7 +7217,7 @@ 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)} +Each macro listed above other than \tcode{\libmacro{_Atomic}(T)} is defined as in \libheader{atomic}. It is unspecified whether \libheader{stdatomic.h} makes available any declarations in namespace \tcode{std}. @@ -6048,7 +7262,7 @@ class mutex; // \ref{thread.mutex.recursive}, class \tcode{recursive_mutex} class recursive_mutex; - // \ref{thread.timedmutex.class} class \tcode{timed_mutex} + // \ref{thread.timedmutex.class}, class \tcode{timed_mutex} class timed_mutex; // \ref{thread.timedmutex.recursive}, class \tcode{recursive_timed_mutex} class recursive_timed_mutex; @@ -6098,7 +7312,7 @@ \rSec2[thread.mutex.requirements]{Mutex requirements} -\rSec3[thread.mutex.requirements.general]{In general} +\rSec3[thread.mutex.requirements.general]{General} \pnum A mutex object facilitates protection against data races and allows safe synchronization of @@ -6375,7 +7589,7 @@ released may ownership be acquired by another thread. \pnum -The behavior of a program is undefined if: +The behavior of a program is undefined if \begin{itemize} \item it destroys a \tcode{recursive_mutex} object owned by any thread or \item a thread terminates while owning a \tcode{recursive_mutex} object. @@ -6526,7 +7740,7 @@ It is a standard-layout class\iref{class.prop}. \pnum -The behavior of a program is undefined if: +The behavior of a program is undefined if \begin{itemize} \item it destroys a \tcode{timed_mutex} object owned by any thread, \item a thread that owns a \tcode{timed_mutex} object calls \tcode{lock()}, @@ -6591,7 +7805,7 @@ may ownership of the object be acquired by another thread. \pnum -The behavior of a program is undefined if: +The behavior of a program is undefined if \begin{itemize} \item it destroys a \tcode{recursive_timed_mutex} object owned by any thread, or \item a thread terminates while owning a \tcode{recursive_timed_mutex} object. @@ -6763,7 +7977,7 @@ It is a standard-layout class\iref{class.prop}. \pnum -The behavior of a program is undefined if: +The behavior of a program is undefined if \begin{itemize} \item it destroys a \tcode{shared_mutex} object owned by any thread, \item a thread attempts to recursively gain any ownership of a \tcode{shared_mutex}, or @@ -6925,7 +8139,7 @@ It is a standard-layout class\iref{class.prop}. \pnum -The behavior of a program is undefined if: +The behavior of a program is undefined if \begin{itemize} \item it destroys a \tcode{shared_timed_mutex} object owned by any thread, \item a thread attempts to recursively gain any ownership of a \tcode{shared_timed_mutex}, or @@ -7162,7 +8376,7 @@ unique_lock& operator=(const unique_lock&) = delete; unique_lock(unique_lock&& u) noexcept; - unique_lock& operator=(unique_lock&& u); + unique_lock& operator=(unique_lock&& u) noexcept; // \ref{thread.lock.unique.locking}, locking void lock(); @@ -7181,7 +8395,7 @@ // \ref{thread.lock.unique.obs}, observers bool owns_lock() const noexcept; - explicit operator bool () const noexcept; + explicit operator bool() const noexcept; mutex_type* mutex() const noexcept; private: @@ -7349,26 +8563,17 @@ \indexlibrarymember{operator=}{unique_lock}% \begin{itemdecl} -unique_lock& operator=(unique_lock&& u); +unique_lock& operator=(unique_lock&& u) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -If \tcode{owns} calls \tcode{pm->unlock()}. +Equivalent to: \tcode{unique_lock(std::move(u)).swap(*this)} \pnum -\ensures -\tcode{pm == u_p.pm} and \tcode{owns == u_p.owns} (where \tcode{u_p} is the state of \tcode{u} just prior to this construction), \tcode{u.pm == 0} and \tcode{u.owns == false}. - -\pnum -\begin{note} -With a recursive mutex it is possible for both \tcode{*this} and \tcode{u} to own the same mutex before the assignment. In this case, \tcode{*this} will own the mutex after the assignment and \tcode{u} will not. -\end{note} - -\pnum -\throws -Nothing. +\returns +\tcode{*this}. \end{itemdescr} \indexlibrarydtor{unique_lock}% @@ -7672,7 +8877,7 @@ // \ref{thread.lock.shared.obs}, observers bool owns_lock() const noexcept; - explicit operator bool () const noexcept; + explicit operator bool() const noexcept; mutex_type* mutex() const noexcept; private: @@ -7855,13 +9060,11 @@ \begin{itemdescr} \pnum \effects -If \tcode{owns} calls \tcode{pm->unlock_shared()}. +Equivalent to: \tcode{shared_lock(std::move(sl)).swap(*this)} \pnum -\ensures -\tcode{pm == sl_p.pm} and \tcode{owns == sl_p.owns} (where -\tcode{sl_p} is the state of \tcode{sl} just prior to this assignment), -\tcode{sl.pm == nullptr} and \tcode{sl.owns == false}. +\returns +\tcode{*this}. \end{itemdescr} \rSec4[thread.lock.shared.locking]{Locking} @@ -8319,7 +9522,6 @@ \rSec2[condition.variable.syn]{Header \tcode{} synopsis} \indexheader{condition_variable}% -\indexlibraryglobal{cv_status}% \begin{codeblock} namespace std { // \ref{thread.condition.condvar}, class \tcode{condition_variable} @@ -8330,7 +9532,7 @@ // \ref{thread.condition.nonmember}, non-member functions void notify_all_at_thread_exit(condition_variable& cond, unique_lock lk); - enum class cv_status { no_timeout, timeout }; + enum class @\libglobal{cv_status}@ { @\libmember{no_timeout}{cv_status}@, @\libmember{timeout}{cv_status}@ }; } \end{codeblock} @@ -8355,7 +9557,7 @@ \effects Transfers ownership of the lock associated with \tcode{lk} into internal storage and schedules \tcode{cond} to be notified when the current -thread exits, after all objects of thread storage duration associated with +thread exits, after all objects with thread storage duration associated with the current thread have been destroyed. This notification is equivalent to: \begin{codeblock} lk.unlock(); @@ -8376,7 +9578,7 @@ \pnum \begin{note} It is the user's responsibility to ensure that waiting threads -do not erroneously assume that the thread has finished if they experience +do not incorrectly assume that the thread has finished if they experience spurious wakeups. This typically requires that the condition being waited for is satisfied while holding the lock on \tcode{lk}, and that this lock is not released and reacquired prior to calling \tcode{notify_all_at_thread_exit}. @@ -8809,7 +10011,7 @@ \rSec3[thread.condition.condvarany.general]{General} \pnum -In this subclause \ref{thread.condition.condvarany}, +In \ref{thread.condition.condvarany}, template arguments for template parameters named \tcode{Lock} shall meet the \oldconcept{Basic\-Lockable} requirements\iref{thread.req.lockable.basic}. @@ -9208,7 +10410,7 @@ \pnum \throws -Timeout-related exceptions \iref{thread.req.timing}, +Timeout-related exceptions\iref{thread.req.timing}, or any exception thrown by \tcode{pred}. \pnum @@ -9688,7 +10890,7 @@ barrier(const barrier&) = delete; barrier& operator=(const barrier&) = delete; - [[nodiscard]] arrival_token arrive(ptrdiff_t update = 1); + arrival_token arrive(ptrdiff_t update = 1); void wait(arrival_token&& arrival) const; void arrive_and_wait(); @@ -9809,7 +11011,7 @@ \indexlibrarymember{arrive}{barrier}% \begin{itemdecl} -[[nodiscard]] arrival_token arrive(ptrdiff_t update = 1); +arrival_token arrive(ptrdiff_t update = 1); \end{itemdecl} \begin{itemdescr} @@ -9942,26 +11144,25 @@ \rSec2[future.syn]{Header \tcode{} synopsis} \indexheader{future}% -\indexlibraryglobal{future_errc}% \begin{codeblock} namespace std { - enum class future_errc { - broken_promise = @\impdefx{value of \tcode{future_errc::broken_promise}}@, - future_already_retrieved = @\impdefx{value of \tcode{future_errc::future_already_retrieved}}@, - promise_already_satisfied = @\impdefx{value of \tcode{future_errc::promise_already_satisfied}}@, - no_state = @\impdefx{value of \tcode{future_errc::no_state}}@ + enum class @\libglobal{future_errc}@ { + @\libmember{broken_promise}{future_errc}@ = @\impdefx{value of \tcode{future_errc::broken_promise}}@, + @\libmember{future_already_retrieved}{future_errc}@ = @\impdefx{value of \tcode{future_errc::future_already_retrieved}}@, + @\libmember{promise_already_satisfied}{future_errc}@ = @\impdefx{value of \tcode{future_errc::promise_already_satisfied}}@, + @\libmember{no_state}{future_errc}@ = @\impdefx{value of \tcode{future_errc::no_state}}@ }; - enum class launch : @\unspec{}@ { - async = @\unspec{}@, - deferred = @\unspec{}@, + enum class @\libglobal{launch}@ : @\unspec{}@ { + @\libmember{async}{launch}@ = @\unspec{}@, + @\libmember{deferred}{launch}@ = @\unspec{}@, @\impdefx{last enumerator of \tcode{launch}}@ }; - enum class future_status { - ready, - timeout, - deferred + enum class @\libglobal{future_status}@ { + @\libmember{ready}{future_status}@, + @\libmember{timeout}{future_status}@, + @\libmember{deferred}{future_status}@ }; // \ref{futures.errors}, error handling @@ -9982,9 +11183,6 @@ template void swap(promise& x, promise& y) noexcept; - template - struct uses_allocator, Alloc>; - // \ref{futures.unique.future}, class template \tcode{future} template class future; template class future; @@ -10005,10 +11203,10 @@ // \ref{futures.async}, function template \tcode{async} template - [[nodiscard]] future, decay_t...>> + future, decay_t...>> async(F&& f, Args&&... args); template - [[nodiscard]] future, decay_t...>> + future, decay_t...>> async(launch policy, F&& f, Args&&... args); } \end{codeblock} @@ -10149,9 +11347,9 @@ state. The result of a shared state is set by respective functions on the asynchronous provider. -\begin{note} -Such as promises or tasks. -\end{note} +\begin{example} +Promises and tasks are examples of asynchronous providers. +\end{example} The means of setting the result of a shared state is specified in the description of those classes and functions that create such a state object. @@ -10262,9 +11460,6 @@ void set_value_at_thread_exit(@\seebelow@); void set_exception_at_thread_exit(exception_ptr p); }; - - template - struct uses_allocator, Alloc>; } \end{codeblock} @@ -10284,20 +11479,6 @@ they acquire a single mutex associated with the promise object while updating the promise object. -\indexlibrarymember{uses_allocator}{promise}% -\begin{itemdecl} -template - struct uses_allocator, Alloc> - : true_type { }; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\expects -\tcode{Alloc} meets -the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. -\end{itemdescr} - \indexlibraryctor{promise}% \begin{itemdecl} promise(); @@ -10488,7 +11669,7 @@ \effects Stores the value \tcode{r} in the shared state without making that state ready immediately. Schedules that state to be made ready when the current -thread exits, after all objects of thread storage duration associated with the +thread exits, after all objects with thread storage duration associated with the current thread have been destroyed. \pnum @@ -10523,7 +11704,7 @@ \effects Stores the exception pointer \tcode{p} in the shared state without making that state ready immediately. Schedules that state to be made ready when -the current thread exits, after all objects of thread storage duration +the current thread exits, after all objects with thread storage duration associated with the current thread have been destroyed. \pnum @@ -11213,10 +12394,10 @@ \indexlibraryglobal{async}% \begin{itemdecl} template - [[nodiscard]] future, decay_t...>> + future, decay_t...>> async(F&& f, Args&&... args); template - [[nodiscard]] future, decay_t...>> + future, decay_t...>> async(launch policy, F&& f, Args&&... args); \end{itemdecl} @@ -11399,6 +12580,8 @@ packaged_task() noexcept; template explicit packaged_task(F&& f); + template + explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f); ~packaged_task(); // no copy @@ -11448,6 +12631,19 @@ explicit packaged_task(F&& f); \end{itemdecl} +\begin{itemdescr} +\pnum +\effects +Equivalent to +\tcode{packaged_task(allocator_arg, allocator(), std::forward(f))}. +\end{itemdescr} + +\indexlibraryctor{packaged_task}% +\begin{itemdecl} +template + explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f); +\end{itemdecl} + \begin{itemdescr} \pnum \constraints @@ -11456,22 +12652,29 @@ \pnum \mandates -\tcode{is_invocable_r_v} is \tcode{true}. +\tcode{is_invocable_r_v\&, ArgTypes...>} is \tcode{true}. \pnum \expects -Invoking a copy of \tcode{f} behaves the same as invoking \tcode{f}. +\tcode{Allocator} meets the \oldconcept{Allocator} requirements\iref{allocator.requirements.general}. \pnum \effects -Constructs a new \tcode{packaged_task} object with a shared state and -initializes the object's stored task with \tcode{std::forward(f)}. +Let \tcode{A2} be +\tcode{allocator_traits::rebind_alloc<\unspec>} +and let \tcode{a2} be an object of type \tcode{A2} initialized with +\tcode{A2(a)}. +Constructs a new \tcode{packaged_task} object with +a stored task of type \tcode{decay_t} and a shared state. +Initializes the object's stored task with \tcode{std::forward(f)}. +Uses \tcode{a2} to allocate storage for the shared state and stores a copy +of \tcode{a2} in the shared state. \pnum \throws -Any exceptions thrown by the copy or move constructor of \tcode{f}, or -\tcode{bad_alloc} if memory for the internal data structures -cannot be allocated. +Any exceptions thrown by the initialization of the stored task. +If storage for the shared state cannot be allocated, any exception thrown by +\tcode{A2::allocate}. \end{itemdescr} \indexlibraryctor{packaged_task}% @@ -11657,7 +12860,7 @@ \tcode{*this}, otherwise the exception thrown by the task is stored. In either case, this is done without making that state ready\iref{futures.state} immediately. Schedules the shared state to be made ready when the current thread exits, -after all objects of thread storage duration associated with the current thread +after all objects with thread storage duration associated with the current thread have been destroyed. \pnum @@ -11681,9 +12884,16 @@ \begin{itemdescr} \pnum \effects -As if \tcode{*this = packaged_task(std::move(f))}, where +Equivalent to: +\begin{codeblock} +if (!valid()) { + throw future_error(future_errc::no_state); +} +*this = packaged_task(allocator_arg, a, std::move(f)); +\end{codeblock} +where \tcode{f} is the task stored in -\tcode{*this}. +\tcode{*this} and \tcode{a} is the allocator stored in the shared state. \begin{note} This constructs a new shared state for \tcode{*this}. The old state is abandoned\iref{futures.state}. @@ -11692,9 +12902,7 @@ \pnum \throws \begin{itemize} -\item \tcode{bad_alloc} if memory for the new shared state cannot be allocated. -\item Any exception thrown by the move constructor of the task stored in the shared -state. +\item Any exception thrown by the \tcode{packaged_task} constructor. \item \tcode{future_error} with an error condition of \tcode{no_state} if \tcode{*this} has no shared state. \end{itemize} @@ -11787,7 +12995,7 @@ // \ref{saferecl.rcu.domain}, class \tcode{rcu_domain} class rcu_domain; - // \ref{saferecl.rcu.domain.func} non-member functions + // \ref{saferecl.rcu.domain.func}, non-member functions rcu_domain& rcu_default_domain() noexcept; void rcu_synchronize(rcu_domain& dom = rcu_default_domain()) noexcept; void rcu_barrier(rcu_domain& dom = rcu_default_domain()) noexcept; @@ -12122,7 +13330,7 @@ \pnum A hazard-protectable object \tcode{x} is \defn{possibly-reclaimable} -with respect to an evaluation $A$ if: +with respect to an evaluation $A$ if \begin{itemize} \item \tcode{x} is not reclaimed; and @@ -12284,7 +13492,7 @@ hazard_pointer& operator=(hazard_pointer&&) noexcept; ~hazard_pointer(); - [[nodiscard]] bool empty() const noexcept; + bool empty() const noexcept; template T* protect(const atomic& src) noexcept; template bool try_protect(T*& ptr, const atomic& src) noexcept; template void reset_protection(const T* ptr) noexcept; @@ -12375,7 +13583,7 @@ \indexlibrarymember{empty}{hazard_pointer}% \begin{itemdecl} -[[nodiscard]] bool empty() const noexcept; +bool empty() const noexcept; \end{itemdecl} \begin{itemdescr} diff --git a/source/time.tex b/source/time.tex index d66ef5652c..2e3e9b5576 100644 --- a/source/time.tex +++ b/source/time.tex @@ -198,23 +198,23 @@ // \ref{time.point.comparisons}, \tcode{time_point} comparisons template - constexpr bool operator==(const time_point& lhs, - const time_point& rhs); + constexpr bool operator==(const time_point& lhs, + const time_point& rhs); template - constexpr bool operator< (const time_point& lhs, - const time_point& rhs); + constexpr bool operator< (const time_point& lhs, + const time_point& rhs); template - constexpr bool operator> (const time_point& lhs, - const time_point& rhs); + constexpr bool operator> (const time_point& lhs, + const time_point& rhs); template - constexpr bool operator<=(const time_point& lhs, - const time_point& rhs); + constexpr bool operator<=(const time_point& lhs, + const time_point& rhs); template - constexpr bool operator>=(const time_point& lhs, - const time_point& rhs); + constexpr bool operator>=(const time_point& lhs, + const time_point& rhs); template Duration2> - constexpr auto operator<=>(const time_point& lhs, - const time_point& rhs); + constexpr auto operator<=>(const time_point& lhs, + const time_point& rhs); // \ref{time.point.cast}, conversions template @@ -857,7 +857,7 @@ // \ref{time.parse}, parsing template @\unspec@ - parse(const charT* fmt, Parsable& tp); + parse(const charT* fmt, Parsable& tp); template @\unspec@ parse(const basic_string& fmt, Parsable& tp); @@ -1036,7 +1036,7 @@ \end{note} \pnum -A type \tcode{TC} meets the \oldconcept{TrivialClock} requirements if: +A type \tcode{TC} meets the \defnoldconcept{TrivialClock} requirements if \begin{itemize} \item \tcode{TC} meets the \oldconcept{Clock} requirements, @@ -1183,7 +1183,7 @@ floating-point durations can have round-off errors. \end{note} -\indexlibraryglobal{common_type}% +\indexlibrarymember{common_type}{duration}% \begin{itemdecl} template struct common_type, chrono::time_point> { @@ -1601,7 +1601,7 @@ In the function descriptions that follow, unless stated otherwise, let \tcode{CD} represent the return type of the function. -\indexlibraryglobal{common_type}% +\indexlibrarymember{operator+}{duration}% \begin{itemdecl} template constexpr common_type_t, duration> @@ -1614,11 +1614,11 @@ \tcode{CD(CD(lhs).count() + CD(rhs).count())}. \end{itemdescr} -\indexlibraryglobal{common_type}% +\indexlibrarymember{operator-}{duration}% \begin{itemdecl} template constexpr common_type_t, duration> - operator-(const duration& lhs, const duration& rhs); + operator-(const duration& lhs, const duration& rhs); \end{itemdecl} \begin{itemdescr} @@ -2655,8 +2655,8 @@ static time_point now() noexcept; // mapping to/from C type \tcode{time_t} - static time_t to_time_t (const time_point& t) noexcept; - static time_point from_time_t(time_t t) noexcept; + static time_t to_time_t (const time_point& t) noexcept; + static time_point from_time_t(time_t t) noexcept; }; } \end{codeblock} @@ -3921,7 +3921,7 @@ \rSec1[time.cal]{The civil calendar} -\rSec2[time.cal.general]{In general} +\rSec2[time.cal.general]{General} \pnum The types in \ref{time.cal} describe the civil (Gregorian) calendar @@ -5404,7 +5404,7 @@ class weekday_last { chrono::weekday wd_; // \expos - public: + public: constexpr explicit weekday_last(const chrono::weekday& wd) noexcept; constexpr chrono::weekday weekday() const noexcept; @@ -8638,8 +8638,8 @@ \begin{itemdecl} template -basic_ostream& -operator<<(basic_ostream& os, const hh_mm_ss& hms); + basic_ostream& + operator<<(basic_ostream& os, const hh_mm_ss& hms); \end{itemdecl} \begin{itemdescr} @@ -8732,7 +8732,7 @@ \rSec1[time.zone]{Time zones} -\rSec2[time.zone.general]{In general} +\rSec2[time.zone.general]{General} \pnum \ref{time.zone} describes an interface for accessing @@ -10652,11 +10652,13 @@ Equivalent to \tcode{\%Y-\%m-\%d}. \\ \rowsep \tcode{\%g} & -The last two decimal digits of the ISO week-based year. +The last two decimal digits of the calendar year +as specified in ISO 8601-1:2019 for the week calendar. If the result is a single digit it is prefixed by \tcode{0}. \\ \rowsep \tcode{\%G} & -The ISO week-based year as a decimal number. +The calendar year as a decimal number, +as specified in ISO 8601-1:2019 for the week calendar. If the result is less than four digits it is left-padded with \tcode{0} to four digits. \\ \rowsep @@ -10682,7 +10684,7 @@ the decimal number of \tcode{days} without padding. Otherwise, the day of the year as a decimal number. -Jan 1 is \tcode{001}. +January 1 is \tcode{001}. If the result is less than three digits, it is left-padded with \tcode{0} to three digits. \\ \rowsep @@ -10736,7 +10738,8 @@ Equivalent to \tcode{\%H:\%M:\%S}. \\ \rowsep \tcode{\%u} & -The ISO weekday as a decimal number (\tcode{1}-\tcode{7}), +The calendar day of week as a decimal number (\tcode{1}-\tcode{7}), +as specified in ISO 8601-1:2019, where Monday is \tcode{1}. The modified command \tcode{\%Ou} produces the locale's alternative representation. @@ -10750,7 +10753,8 @@ the locale's alternative representation. \\ \rowsep \tcode{\%V} & -The ISO week-based week number as a decimal number. +The calendar week of year as a decimal number, +as specified in ISO 8601-1:2019 for the week calendar. If the result is a single digit, it is prefixed with \tcode{0}. The modified command \tcode{\%OV} produces the locale's alternative representation. @@ -10780,20 +10784,20 @@ \\ \rowsep \tcode{\%y} & The last two decimal digits of the year. -If the result is a single digit it is prefixed by \tcode{0}. +If the result is a single digit, it is prefixed by \tcode{0}. The modified command \tcode{\%Oy} produces the locale's alternative representation. The modified command \tcode{\%Ey} produces the locale's alternative representation of offset from \tcode{\%EC} (year only). \\ \rowsep \tcode{\%Y} & The year as a decimal number. -If the result is less than four digits +If the result is less than four digits, it is left-padded with \tcode{0} to four digits. The modified command \tcode{\%EY} produces the locale's alternative full year representation. \\ \rowsep \tcode{\%z} & -The offset from UTC as specified in ISO 8601-1:2019, subclause 5.3.4.1. +The offset from UTC as specified in ISO 8601-1:2019, 5.3.4.1. For example \tcode{-0430} refers to 4 hours 30 minutes behind UTC\@. If the offset is zero, \tcode{+0000} is used. The modified commands \tcode{\%Ez} and \tcode{\%Oz} @@ -10812,7 +10816,8 @@ \end{LongTable} \pnum -If the \fmtgrammarterm{chrono-specs} is omitted, +Unless otherwise specified, +if the \fmtgrammarterm{chrono-specs} is omitted, the chrono object is formatted as if by streaming it to \tcode{basic_ostring\-stream os} with the formatting locale imbued @@ -10824,6 +10829,27 @@ \end{codeblock} \end{example} +\pnum +For \tcode{chrono::duration} +the library only provides the following specialization +of \tcode{enable_nonlocking_formatter_optimization}: +\begin{codeblock} +template + constexpr bool enable_nonlocking_formatter_optimization< + chrono::duration> = + enable_nonlocking_formatter_optimization; +\end{codeblock} + +\pnum +For \tcode{chrono::zoned_time} +the library only provides the following specialization of +\tcode{enable_nonlocking_formatter_optimization}: +\begin{codeblock} +template + constexpr bool enable_nonlocking_formatter_optimization< + chrono::zoned_time> = true; +\end{codeblock} + \indexlibrary{\idxcode{formatter}!specializations!\idxcode{chrono::sys_time}}% \begin{itemdecl} template @@ -10969,6 +10995,9 @@ \pnum \remarks +If the \fmtgrammarterm{chrono-specs} is omitted, +the result is equivalent to using \tcode{\%F \%T \%Z} as +the \fmtgrammarterm{chrono-specs}. If \tcode{\%Z} is used, it is replaced with \tcode{*f.abbrev} if \tcode{f.abbrev} is not a null pointer value. @@ -10987,7 +11016,7 @@ \begin{codeblock} template struct formatter, charT> - : formatter, charT> { + : formatter>, charT> { template typename FormatContext::iterator format(const chrono::zoned_time& tp, FormatContext& ctx) const; @@ -11007,7 +11036,7 @@ Equivalent to: \begin{codeblock} sys_info info = tp.get_info(); -return formatter, charT>:: +return formatter>, charT>:: format({tp.get_local_time(), &info.abbrev, &info.offset}, ctx); \end{codeblock} \end{itemdescr} @@ -11268,14 +11297,16 @@ the width is applied to only \tcode{\%Y}. \\ \rowsep \tcode{\%g} & -The last two decimal digits of the ISO week-based year. +The last two decimal digits of the calendar year, +as specified in ISO 8601-1:2019 for the week calendar. The modified command \tcode{\%\placeholder{N}g} specifies the maximum number of characters to read. If \tcode{\placeholder{N}} is not specified, the default is 2. Leading zeroes are permitted but not required. \\ \rowsep \tcode{\%G} & -The ISO week-based year as a decimal number. +The calendar year as a decimal number, +as specified in ISO 8601-1:2019 for the week calendar. The modified command \tcode{\%\placeholder{N}G} specifies the maximum number of characters to read. If \tcode{\placeholder{N}} is not specified, the default is 4. @@ -11307,7 +11338,7 @@ a decimal number of \tcode{days}. Otherwise, the day of the year as a decimal number. -Jan 1 is \tcode{1}. +January 1 is \tcode{1}. In either case, the modified command \tcode{\%\placeholder{N}j} specifies the maximum number of characters to read. @@ -11316,7 +11347,7 @@ \\ \rowsep \tcode{\%m} & The month as a decimal number. -Jan is \tcode{1}. +January is \tcode{1}. The modified command \tcode{\%\placeholder{N}m} specifies the maximum number of characters to read. If \tcode{\placeholder{N}} is not specified, the default is 2. @@ -11373,7 +11404,9 @@ Equivalent to \tcode{\%H:\%M:\%S}. \\ \rowsep \tcode{\%u} & -The ISO weekday as a decimal number (\tcode{1}-\tcode{7}), where Monday is \tcode{1}. +The calendar day of week as a decimal number (\tcode{1}-\tcode{7}), +as specified in ISO 8601-1:2019, +where Monday is \tcode{1}. The modified command \tcode{\%\placeholder{N}u} specifies the maximum number of characters to read. If \tcode{\placeholder{N}} is not specified, the default is \tcode{1}. @@ -11391,7 +11424,8 @@ the locale's alternative representation. \\ \rowsep \tcode{\%V} & -The ISO week-based week number as a decimal number. +The calendar week of year as a decimal number, +as specified in ISO 8601-1:2019 for the week calendar. The modified command \tcode{\%\placeholder{N}V} specifies the maximum number of characters to read. If \tcode{\placeholder{N}} is not specified, the default is 2. @@ -11573,28 +11607,32 @@ \rSec1[ctime.syn]{Header \tcode{} synopsis} \indexheader{ctime}% -\indexlibraryglobal{CLOCKS_PER_SEC}% -\indexlibraryglobal{NULL}% -\indexlibraryglobal{TIME_UTC}% -\indexlibraryglobal{asctime}% \indexlibraryglobal{clock_t}% \indexlibraryglobal{clock}% -\indexlibraryglobal{ctime}% \indexlibraryglobal{difftime}% \indexlibraryglobal{gmtime}% +\indexlibraryglobal{gmtime_r}% \indexlibraryglobal{localtime}% +\indexlibraryglobal{localtime_r}% \indexlibraryglobal{mktime}% \indexlibraryglobal{size_t}% \indexlibraryglobal{strftime}% \indexlibraryglobal{time_t}% \indexlibraryglobal{timespec_get}% +\indexlibraryglobal{timespec_getres}% \indexlibraryglobal{timespec}% \indexlibraryglobal{time}% +\indexlibraryglobal{timegm}% \indexlibraryglobal{tm}% \begin{codeblock} -#define NULL @\textit{see \ref{support.types.nullptr}}@ -#define CLOCKS_PER_SEC @\seebelow@ -#define TIME_UTC @\seebelow@ +#define __STDC_VERSION_TIME_H__ 202311L + +#define @\libmacro{NULL}@ @\textit{see \ref{support.types.nullptr}}@ +#define @\libmacro{CLOCKS_PER_SEC}@ @\seebelow@ +#define @\libmacro{TIME_UTC}@ @\seebelow@ +#define @\libmacro{TIME_MONOTONIC}@ @\seebelow@ // optional +#define @\libmacro{TIME_ACTIVE}@ @\seebelow@ // optional +#define @\libmacro{TIME_THREAD_ACTIVE}@ @\seebelow@ // optional namespace std { using size_t = @\textit{see \ref{support.types.layout}}@; @@ -11607,12 +11645,14 @@ clock_t clock(); double difftime(time_t time1, time_t time0); time_t mktime(tm* timeptr); + time_t timegm(tm* timeptr); time_t time(time_t* timer); int timespec_get(timespec* ts, int base); - char* asctime(const tm* timeptr); - char* ctime(const time_t* timer); + int timespec_getres(timespec* ts, int base); tm* gmtime(const time_t* timer); + tm* gmtime_r(const time_t* timer, tm* buf); tm* localtime(const time_t* timer); + tm* localtime_r(const time_t* timer, tm* buf); size_t strftime(char* s, size_t maxsize, const char* format, const tm* timeptr); } \end{codeblock} @@ -11627,8 +11667,8 @@ \end{footnote} \pnum -The functions \tcode{asctime}, \tcode{ctime}, \tcode{gmtime}, and +The functions \tcode{gmtime} and \tcode{localtime} are not required to avoid data races\iref{res.on.data.races}. -\xrefc{7.27} +\xrefc{7.29} diff --git a/source/uax31.tex b/source/uax31.tex index aea6e6b5ba..79f0f7d0e9 100644 --- a/source/uax31.tex +++ b/source/uax31.tex @@ -7,25 +7,27 @@ This Annex describes the choices made in application of \UAX{31} (``Unicode Identifier and Pattern Syntax'') to \Cpp{} in terms of the requirements from \UAX{31} and -how they do or do not apply to \Cpp{}. +how they do or do not apply to this document. In terms of \UAX{31}, -\Cpp{} conforms by meeting the requirements +this document conforms by meeting the requirements R1 ``Default Identifiers'' and -R4 ``Equivalent Normalized Identifiers''. -The other requirements, also listed below, -are either alternatives not taken or do not apply to \Cpp{}. +R4 ``Equivalent Normalized Identifiers'' from \UAX{31}. +The other requirements from \UAX{31}, also listed below, +are either alternatives not taken or do not apply to this document. \rSec1[uaxid.def]{R1 Default identifiers} \rSec2[uaxid.def.general]{General} +\indextext{XID_Start}% +\indextext{XID_Continue}% \pnum \UAX{31} specifies a default syntax for identifiers based on properties from the Unicode Character Database, \UAX{44}. The general syntax is -\begin{codeblock} +\begin{outputblock} := * ( +)* -\end{codeblock} +\end{outputblock} where \tcode{} has the XID_Start property, \tcode{} has the XID_Continue property, and \tcode{} is a list of characters permitted between continue characters. @@ -34,11 +36,11 @@ the \tcode{} set is empty, and the \tcode{} characters are unmodified. In the grammar used in \UAX{31}, this is -\begin{codeblock} +\begin{outputblock} := * := XID_Start + @\textrm{\ucode{005f}}@ := + XID_Continue -\end{codeblock} +\end{outputblock} \pnum This is described in the \Cpp{} grammar in \ref{lex.name}, @@ -46,17 +48,6 @@ \grammarterm{identifier-start} or \grammarterm{identifier} followed by \grammarterm{identifier-continue}. -\rSec2[uaxid.def.rfmt]{R1a Restricted format characters} - -\pnum -If an implementation of \UAX{31} wishes to allow format characters -such as \unicode{200d}{zero width joiner} or \unicode{200c}{zero width non-joiner} -it must define a profile allowing them, or -describe precisely which combinations are permitted. - -\pnum -\Cpp{} does not allow format characters in identifiers, so this does not apply. - \rSec2[uaxid.def.stable]{R1b Stable identifiers} \pnum @@ -91,7 +82,7 @@ during the processes of lexing and parsing. \pnum -\Cpp{} does not claim conformance with this requirement. +This document does not claim conformance with this requirement from \UAX{31}. \rSec1[uaxid.eqn]{R4 Equivalent normalized identifiers} @@ -100,16 +91,16 @@ how identifiers are compared and considered equivalent. \pnum -\Cpp{} requires that identifiers be in Normalization Form C and +This document requires that identifiers be in Normalization Form C and therefore identifiers that compare the same under NFC are equivalent. This is described in \ref{lex.name}. \rSec1[uaxid.eqci]{R5 Equivalent case-insensitive identifiers} \pnum -\Cpp{} considers case to be significant in identifier comparison, and +This document considers case to be significant in identifier comparison, and does not do any case folding. -This requirement does not apply to \Cpp{}. +This requirement from \UAX{31} does not apply to this document. \rSec1[uaxid.filter]{R6 Filtered normalized identifiers} @@ -118,15 +109,15 @@ \UAX{31} requires a precise specification of those exclusions. \pnum -\Cpp{} does not make any such exclusions. +This document does not make any such exclusions. \rSec1[uaxid.filterci]{R7 Filtered case-insensitive identifiers} \pnum \Cpp{} identifiers are case sensitive, and -therefore this requirement does not apply. +therefore this requirement from \UAX{31} does not apply. \rSec1[uaxid.hashtag]{R8 Hashtag identifiers} \pnum -There are no hashtags in \Cpp{}, so this requirement does not apply. +There are no hashtags in \Cpp{}, so this requirement from \UAX{31} does not apply. diff --git a/source/utilities.tex b/source/utilities.tex index a93b2f72c3..42a724196b 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -11,7 +11,7 @@ \begin{libsumtab}{General utilities library summary}{utilities.summary} \ref{utility} & Utility components & \tcode{} \\ -\ref{pairs} & Pairs & \\ \rowsep +\ref{pairs} & Pairs & \\ \rowsep \ref{tuple} & Tuples & \tcode{} \\ \rowsep \ref{optional} & Optional objects & \tcode{} \\ \rowsep \ref{variant} & Variants & \tcode{} \\ \rowsep @@ -19,12 +19,7 @@ \ref{expected} & Expected objects & \tcode{} \\ \rowsep \ref{bitset} & Fixed-size sequences of bits & \tcode{} \\ \rowsep \ref{function.objects} & Function objects & \tcode{} \\ \rowsep -\ref{type.index} & Type indexes & \tcode{} \\ \rowsep -\ref{execpol} & Execution policies & \tcode{} \\ \rowsep -\ref{charconv} & Primitive numeric conversions & \tcode{} \\ \rowsep -\ref{format} & Formatting & \tcode{} \\ \rowsep -\ref{bit} & Bit manipulation & \tcode{} \\ \rowsep -\ref{debugging} & Debugging & \tcode{} \\ +\ref{bit} & Bit manipulation & \tcode{} \\ \end{libsumtab} \rSec1[utility]{Utility components} @@ -58,7 +53,7 @@ template constexpr T&& forward(remove_reference_t&& t) noexcept; template - [[nodiscard]] constexpr auto forward_like(U&& x) noexcept -> @\seebelow@; + constexpr auto forward_like(U&& x) noexcept -> @\seebelow@; template constexpr remove_reference_t&& move(T&&) noexcept; template @@ -98,8 +93,9 @@ template constexpr underlying_type_t to_underlying(T value) noexcept; - // \ref{utility.unreachable}, unreachable + // \ref{utility.undefined}, undefined behavior [[noreturn]] void unreachable(); + void observable_checkpoint() noexcept; // \ref{intseq}, compile-time integer sequences% \indexlibraryglobal{index_sequence}% @@ -225,6 +221,21 @@ explicit nontype_t() = default; }; template constexpr nontype_t nontype{}; + + // \ref{variant.monostate}, class \tcode{monostate}% +\indexlibraryglobal{monostate} + struct monostate; + + // \ref{variant.monostate.relops}, \tcode{monostate} relational operators% +\indexlibrarymember{operator==}{monostate}% +\indexlibrarymember{operator<=>}{monostate} + constexpr bool operator==(monostate, monostate) noexcept; + constexpr strong_ordering operator<=>(monostate, monostate) noexcept; + + // \ref{variant.hash}, hash support% +\indexlibrarymember{hash}{monostate} + template struct hash; + template<> struct hash; } \end{codeblock} @@ -372,7 +383,7 @@ \indexlibraryglobal{forward_like}% \begin{itemdecl} template - [[nodiscard]] constexpr auto forward_like(U&& x) noexcept -> @\seebelow@; + constexpr auto forward_like(U&& x) noexcept -> @\seebelow@; \end{itemdecl} \begin{itemdescr} @@ -675,7 +686,7 @@ \tcode{static_cast>(value)}. \end{itemdescr} -\rSec2[utility.unreachable]{Function \tcode{unreachable}} +\rSec2[utility.undefined]{Undefined behavior} \indexlibraryglobal{unreachable}% \begin{itemdecl} @@ -709,9 +720,20 @@ \end{example} \end{itemdescr} +\indexlibraryglobal{observable_checkpoint}% +\begin{itemdecl} +void observable_checkpoint() noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Establishes an observable checkpoint\iref{intro.abstract}. +\end{itemdescr} + \rSec1[pairs]{Pairs} -\rSec2[pairs.general]{In general} +\rSec2[pairs.general]{General} \pnum The library provides a template for heterogeneous pairs of values. @@ -1282,9 +1304,11 @@ \begin{itemdescr} \pnum -\expects -Each of \tcode{decltype(x.first == y.first)} and -\tcode{decltype(x.second == y.second)} models \exposconcept{boolean-testable}. +\constraints +\tcode{x.first == y.first} and \tcode{x.second == y.second} are +valid expressions and +each of \tcode{decltype(x.first == y.first)} and +\tcode{decltype(x.second == y.second)} models \exposconceptx{boolean-\newline testable}{boolean-testable}. \pnum \returns @@ -1480,7 +1504,7 @@ \rSec1[tuple]{Tuples} -\rSec2[tuple.general]{In general} +\rSec2[tuple.general]{General} \pnum \indexlibraryglobal{tuple}% @@ -1492,6 +1516,11 @@ two arguments is similar to an instantiation of \tcode{pair} with the same two arguments. See~\ref{pairs}. +\pnum +In addition to being available via inclusion of the \libheader{tuple} header, +\tcode{ignore}\iref{tuple.syn} is available when +\libheader{utility}\iref{utility} is included. + \rSec2[tuple.syn]{Header \tcode{} synopsis} \indexheader{tuple}% @@ -1518,9 +1547,14 @@ template<@\exposconceptnc{tuple-like}@ TTuple, @\exposconceptnc{tuple-like}@ UTuple> struct common_type; - // \ref{tuple.creation}, tuple creation functions - inline constexpr @\unspec@ ignore; + // \tcode{ignore} + struct @\exposidnc{ignore-type}@ { // \expos + constexpr const @\exposid{ignore-type}@& + operator=(const auto &) const noexcept { return *this; } + }; + inline constexpr @\exposid{ignore-type}@ ignore; + // \ref{tuple.creation}, tuple creation functions template constexpr tuple...> make_tuple(TTypes&&...); @@ -1535,7 +1569,8 @@ // \ref{tuple.apply}, calling a function with a tuple of arguments template - constexpr decltype(auto) apply(F&& f, Tuple&& t) noexcept(@\seebelow@); + constexpr apply_result_t apply(F&& f, Tuple&& t) + noexcept(is_nothrow_applicable_v); template constexpr T make_from_tuple(Tuple&& t); @@ -1920,7 +1955,7 @@ \begin{itemdescr} \pnum -Let \tcode{I} be the pack \tcode{0, 1, ..., (sizeof...(Types) - 1)}.\newline +Let \tcode{I} be the pack \tcode{0, 1, $\dotsc$, (sizeof...(Types) - 1)}.\newline Let \tcode{\exposid{FWD}(u)} be \tcode{static_cast(u)}. \pnum @@ -2009,7 +2044,7 @@ \begin{itemdescr} \pnum -Let \tcode{I} be the pack \tcode{0, 1, \ldots, (sizeof...(Types) - 1)}. +Let \tcode{I} be the pack \tcode{0, 1, $\dotsc$, (sizeof...(Types) - 1)}. \pnum \constraints @@ -2049,6 +2084,12 @@ \begin{codeblock} !(is_convertible_v(std::forward(u))), Types> && ...) \end{codeblock} +The constructor is defined as deleted if +\begin{codeblock} +(reference_constructs_from_temporary_v(std::forward(u)))> + || ...) +\end{codeblock} +is \tcode{true}. \end{itemdescr} \indexlibraryctor{tuple}% @@ -2427,7 +2468,7 @@ \item \tcode{sizeof...(Types)} -equals \tcode{tuple_size_v>}, and, +equals \tcode{tuple_size_v>}, and \item \tcode{is_assignable_v<$\tcode{T}_i$\&, decltype(get<$i$>(std::forward(u)))>} @@ -2464,7 +2505,7 @@ \item \tcode{sizeof...(Types)} -equals \tcode{tuple_size_v>}, and, +equals \tcode{tuple_size_v>}, and \item \tcode{is_assignable_v(std::forward(u)))>} @@ -2583,9 +2624,7 @@ \begin{itemdescr} \pnum \returns -\tcode{tuple(t...)}. When an -argument in \tcode{t} is \tcode{ignore}, assigning -any value to the corresponding tuple element has no effect. +\tcode{tuple(t...)}. \pnum \begin{example} @@ -2650,7 +2689,8 @@ \indexlibraryglobal{apply}% \begin{itemdecl} template - constexpr decltype(auto) apply(F&& f, Tuple&& t) noexcept(@\seebelow@); + constexpr apply_result_t apply(F&& f, Tuple&& t) + noexcept(is_nothrow_applicable_v); \end{itemdecl} \begin{itemdescr} @@ -2671,15 +2711,6 @@ return @\placeholdernc{apply-impl}@(std::forward(f), std::forward(t), make_index_sequence>>{}); \end{codeblock} - -\pnum -\remarks -Let \tcode{I} be the pack -\tcode{0, 1, ..., (tuple_size_v> - 1)}. -The exception specification is equivalent to: -\begin{codeblock} -noexcept(invoke(std::forward(f), get(std::forward(t))...)) -\end{codeblock} \end{itemdescr} \indexlibraryglobal{make_from_tuple}% @@ -2740,7 +2771,7 @@ \indexlibraryglobal{tuple_size}% \begin{itemdecl} template - struct tuple_size> : public integral_constant { }; + struct tuple_size> : integral_constant { }; \end{itemdecl} \indexlibraryglobal{tuple_element}% @@ -2832,10 +2863,10 @@ get(tuple& t) noexcept; template constexpr tuple_element_t>&& - get(tuple&& t) noexcept; // Note A + get(tuple&& t) noexcept; // \#1 template constexpr const tuple_element_t>& - get(const tuple& t) noexcept; // Note B + get(const tuple& t) noexcept; // \#2 template constexpr const tuple_element_t>&& get(const tuple&& t) noexcept; \end{itemdecl} @@ -2852,8 +2883,8 @@ \pnum \begin{note} -[Note A] -If a type \tcode{T} in \tcode{Types} is some reference type \tcode{X\&}, +For the overload marked \#1, +if a type \tcode{T} in \tcode{Types} is some reference type \tcode{X\&}, the return type is \tcode{X\&}, not \tcode{X\&\&}. However, if the element type is a non-reference type \tcode{T}, the return type is \tcode{T\&\&}. @@ -2861,9 +2892,9 @@ \pnum \begin{note} -[Note B] Constness is shallow. -If a type \tcode{T} in \tcode{Types} is some reference type \tcode{X\&}, +For the overload marked \#2, +if a type \tcode{T} in \tcode{Types} is some reference type \tcode{X\&}, the return type is \tcode{X\&}, not \tcode{const X\&}. However, if the element type is a non-reference type \tcode{T}, the return type is \tcode{const T\&}. @@ -2929,18 +2960,14 @@ For the first overload let \tcode{UTuple} be \tcode{tuple}. \pnum -\mandates +\constraints For all \tcode{i}, where $0 \leq \tcode{i} < \tcode{sizeof...(TTypes)}$, -\tcode{get(t) == get(u)} is a valid expression. +\tcode{get(t) == get(u)} is a valid expression and +\tcode{decltype(get(t) == get(u))} models \exposconcept{boolean-testable}. \tcode{sizeof...(TTypes)} equals \tcode{tuple_size_v}. -\pnum -\expects -For all \tcode{i}, \tcode{decltype(get(t) == get(u))} models -\exposconcept{boolean-testable}. - \pnum \returns \tcode{true} if \tcode{get(t) == get(u)} for all @@ -3140,7 +3167,7 @@ \rSec1[optional]{Optional objects} -\rSec2[optional.general]{In general} +\rSec2[optional.general]{General} \pnum Subclause~\ref{optional} describes class template \tcode{optional} that represents @@ -3162,10 +3189,21 @@ namespace std { // \ref{optional.optional}, class template \tcode{optional} template - class optional; // partially freestanding + class optional; // partially freestanding + // \ref{optional.optional.ref}, partial specialization of \tcode{optional} for lvalue reference types template - concept @\defexposconcept{is-derived-from-optional}@ = requires(const T& t) { // \expos + class optional; // partially freestanding + + template + constexpr bool ranges::enable_view> = true; + template + constexpr auto format_kind> = range_format::disabled; + template + constexpr bool ranges::enable_borrowed_range> = true; + + template + concept @\defexposconceptnc{is-derived-from-optional}@ = requires(const T& t) { // \expos [](const optional&){ }(t); }; @@ -3221,7 +3259,7 @@ constexpr void swap(optional&, optional&) noexcept(@\seebelow@); template - constexpr optional<@\seebelow@> make_optional(T&&); + constexpr optional> make_optional(T&&); template constexpr optional make_optional(Args&&... args); template @@ -3244,7 +3282,9 @@ template class optional { public: - using value_type = T; + using value_type = T; + using iterator = @\impdefnc@; // see~\ref{optional.iterators} + using const_iterator = @\impdefnc@; // see~\ref{optional.iterators} // \ref{optional.ctor}, constructors constexpr optional() noexcept; @@ -3255,7 +3295,7 @@ constexpr explicit optional(in_place_t, Args&&...); template constexpr explicit optional(in_place_t, initializer_list, Args&&...); - template + template> constexpr explicit(@\seebelow@) optional(U&&); template constexpr explicit(@\seebelow@) optional(const optional&); @@ -3269,7 +3309,7 @@ constexpr optional& operator=(nullopt_t) noexcept; constexpr optional& operator=(const optional&); constexpr optional& operator=(optional&&) noexcept(@\seebelow@); - template constexpr optional& operator=(U&&); + template> constexpr optional& operator=(U&&); template constexpr optional& operator=(const optional&); template constexpr optional& operator=(optional&&); template constexpr T& emplace(Args&&...); @@ -3278,6 +3318,12 @@ // \ref{optional.swap}, swap constexpr void swap(optional&) noexcept(@\seebelow@); + // \ref{optional.iterators}, iterator support + constexpr iterator begin() noexcept; + constexpr const_iterator begin() const noexcept; + constexpr iterator end() noexcept; + constexpr const_iterator end() const noexcept; + // \ref{optional.observe}, observers constexpr const T* operator->() const noexcept; constexpr T* operator->() noexcept; @@ -3291,8 +3337,8 @@ constexpr T& value() &; // freestanding-deleted constexpr T&& value() &&; // freestanding-deleted constexpr const T&& value() const &&; // freestanding-deleted - template constexpr T value_or(U&&) const &; - template constexpr T value_or(U&&) &&; + 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) &; @@ -3310,7 +3356,7 @@ constexpr void reset() noexcept; private: - T *val; // \expos + T* @\exposidnc{val}@; // \expos }; template @@ -3322,8 +3368,7 @@ Any instance of \tcode{optional} at any given time either contains a value or does not contain a value. When an instance of \tcode{optional} \defnx{contains a value}{contains a value!\idxcode{optional}}, it means that an object of type \tcode{T}, referred to as the optional object's \defnx{contained value}{contained value!\idxcode{optional}}, -is allocated within the storage of the optional object. -Implementations are not permitted to use additional storage, such as dynamic memory, to allocate its contained value. +is nested within\iref{intro.object} the optional object. When an object of type \tcode{optional} is contextually converted to \tcode{bool}, the conversion returns \tcode{true} if the object contains a value; otherwise the conversion returns \tcode{false}. @@ -3333,9 +3378,14 @@ member \tcode{val} points to the contained value. \pnum -\tcode{T} shall be a type -other than \cv{} \tcode{in_place_t} or \cv{} \tcode{nullopt_t} -that meets the \oldconcept{Destructible} requirements (\tref{cpp17.destructible}). +A type \tcode{X} is a +\defnx{valid contained type}{valid contained type!\idxcode{optional}} for \tcode{optional} +if \tcode{X} is an lvalue reference type or a complete non-array object type, +and \tcode{remove_cvref_t} is a type other than \tcode{in_place_t} or \tcode{nullopt_t}. +If a specialization of \tcode{optional} is instantiated with a type \tcode{T} +that is not a valid contained type for \tcode{optional}, the program is ill-formed. +If \tcode{T} is an object type, +\tcode{T} shall meet the \oldconcept{Destructible} requirements (\tref{cpp17.destructible}). \rSec3[optional.ctor]{Constructors} @@ -3408,7 +3458,7 @@ \pnum \effects If \tcode{rhs} contains a value, direct-non-list-initializes the contained value -with \tcode{std::move(*rhs)}. +with \tcode{*std::move(rhs)}. \tcode{rhs.has_value()} is unchanged. \pnum @@ -3484,7 +3534,7 @@ \indexlibraryctor{optional}% \begin{itemdecl} -template constexpr explicit(@\seebelow@) optional(U&& v); +template> constexpr explicit(@\seebelow@) optional(U&& v); \end{itemdecl} \begin{itemdescr} @@ -3572,7 +3622,7 @@ \pnum \effects If \tcode{rhs} contains a value, -direct-non-list-initializes the contained value with \tcode{std::move(*rhs)}. +direct-non-list-initializes the contained value with \tcode{*std::move(rhs)}. \tcode{rhs.has_value()} is unchanged. \pnum @@ -3698,8 +3748,8 @@ {\tcode{*this} does not contain a value} \rowhdr{\tcode{rhs} contains a value} & -assigns \tcode{std::move(*rhs)} to the contained value & -direct-non-list-initializes the contained value with \tcode{std::move(*rhs)} \\ +assigns \tcode{*std::move(rhs)} to the contained value & +direct-non-list-initializes the contained value with \tcode{*std::move(rhs)} \\ \rowsep \rowhdr{\tcode{rhs} does not contain a value} & @@ -3736,16 +3786,18 @@ \indexlibrarymember{operator=}{optional}% \begin{itemdecl} -template constexpr optional& operator=(U&& v); +template> constexpr optional& operator=(U&& v); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_same_v, optional>} is \tcode{false}, -\tcode{conjunction_v, is_same>>} is \tcode{false}, -\tcode{is_constructible_v} is \tcode{true}, and -\tcode{is_assignable_v} is \tcode{true}. +\begin{itemize} +\item \tcode{is_same_v, optional>} is \tcode{false}, +\item \tcode{conjunction_v, is_same>>} is \tcode{false}, +\item \tcode{is_constructible_v} is \tcode{true}, and +\item \tcode{is_assignable_v} is \tcode{true}. +\end{itemize} \pnum \effects @@ -3846,8 +3898,8 @@ {\tcode{*this} does not contain a value} \rowhdr{\tcode{rhs} contains a value} & -assigns \tcode{std::move(*rhs)} to the contained value & -direct-non-list-initializes the contained value with \tcode{std::move(*rhs)} \\ +assigns \tcode{*std::move(rhs)} to the contained value & +direct-non-list-initializes the contained value with \tcode{*std::move(rhs)} \\ \rowsep \rowhdr{\tcode{rhs} does not contain a value} & @@ -3997,6 +4049,59 @@ the state of \tcode{*val} and \tcode{*rhs.val} is determined by the exception safety guarantee of \tcode{T}'s move constructor. \end{itemdescr} +\rSec3[optional.iterators]{Iterator support} + +\indexlibrarymember{iterator}{optional}% +\indexlibrarymember{const_iterator}{optional}% +\begin{itemdecl} +using iterator = @\impdef@; +using const_iterator = @\impdef@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +These types +model \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}, +meet the \oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators}, and +meet the requirements for constexpr iterators\iref{iterator.requirements.general}, +with value type \tcode{remove_cv_t}. +The reference type is \tcode{T\&} for \tcode{iterator} and +\tcode{const T\&} for \tcode{const_iterator}. + +\pnum +All requirements on container iterators\iref{container.reqmts} apply to +\tcode{optional::iterator} and \tcode{optional::\linebreak{}const_iterator} as well. + +\pnum +Any operation that initializes or destroys the contained value of an optional object invalidates all iterators into that object. +\end{itemdescr} + +\indexlibrarymember{begin}{optional}% +\begin{itemdecl} +constexpr iterator begin() noexcept; +constexpr const_iterator begin() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +If \tcode{has_value()} is \tcode{true}, +an iterator referring to the contained value. +Otherwise, a past-the-end iterator value. +\end{itemdescr} + +\indexlibrarymember{end}{optional}% +\begin{itemdecl} +constexpr iterator end() noexcept; +constexpr const_iterator end() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{begin() + has_value()}. +\end{itemdescr} + \rSec3[optional.observe]{Observers} \indexlibrarymember{operator->}{optional}% @@ -4007,8 +4112,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{*this} contains a value. +\hardexpects +\tcode{has_value()} is \tcode{true}. \pnum \returns @@ -4027,8 +4132,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{*this} contains a value. +\hardexpects +\tcode{has_value()} is \tcode{true}. \pnum \returns @@ -4047,8 +4152,8 @@ \begin{itemdescr} \pnum -\expects -\tcode{*this} contains a value. +\hardexpects +\tcode{has_value()} is \tcode{true}. \pnum \effects @@ -4118,7 +4223,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} @@ -4136,7 +4241,7 @@ \indexlibrarymember{value_or}{optional}% \begin{itemdecl} -template constexpr T value_or(U&& v) &&; +template> constexpr T value_or(U&& v) &&; \end{itemdecl} \begin{itemdescr} @@ -4162,7 +4267,7 @@ \begin{itemdescr} \pnum -Let \tcode{U} be \tcode{invoke_result_t}. +Let \tcode{U} be \tcode{invoke_result_t}. \pnum \mandates @@ -4173,7 +4278,7 @@ Equivalent to: \begin{codeblock} if (*this) { - return invoke(std::forward(f), *val); + return invoke(std::forward(f), *@\exposid{val}@); } else { return remove_cvref_t(); } @@ -4188,7 +4293,7 @@ \begin{itemdescr} \pnum -Let \tcode{U} be \tcode{invoke_result_t}. +Let \tcode{U} be \tcode{invoke_result_t}. \pnum \mandates @@ -4199,7 +4304,7 @@ Equivalent to: \begin{codeblock} if (*this) { - return invoke(std::forward(f), std::move(*val)); + return invoke(std::forward(f), std::move(*@\exposid{val}@)); } else { return remove_cvref_t(); } @@ -4214,15 +4319,14 @@ \begin{itemdescr} \pnum -Let \tcode{U} be \tcode{remove_cv_t>}. +Let \tcode{U} be \tcode{remove_cv_t>}. \pnum \mandates -\tcode{U} is a non-array object type -other than \tcode{in_place_t} or \tcode{nullopt_t}. +\tcode{U} is a valid contained type for \tcode{optional}. The declaration \begin{codeblock} -U u(invoke(std::forward(f), *val)); +U u(invoke(std::forward(f), *@\exposid{val}@)); \end{codeblock} is well-formed for some invented variable \tcode{u}. \begin{note} @@ -4233,7 +4337,7 @@ \returns If \tcode{*this} contains a value, an \tcode{optional} object whose contained value is direct-non-list-initialized with -\tcode{invoke(std::forward(f), *val)}; +\tcode{invoke(std::forward(f), *\exposid{val})}; otherwise, \tcode{optional()}. \end{itemdescr} @@ -4246,15 +4350,14 @@ \begin{itemdescr} \pnum Let \tcode{U} be -\tcode{remove_cv_t>}. +\tcode{remove_cv_t>}. \pnum \mandates -\tcode{U} is a non-array object type -other than \tcode{in_place_t} or \tcode{nullopt_t}. +\tcode{U} is a valid contained type for \tcode{optional}. The declaration \begin{codeblock} -U u(invoke(std::forward(f), std::move(*val))); +U u(invoke(std::forward(f), std::move(*@\exposid{val}@))); \end{codeblock} is well-formed for some invented variable \tcode{u}. \begin{note} @@ -4265,7 +4368,7 @@ \returns If \tcode{*this} contains a value, an \tcode{optional} object whose contained value is direct-non-list-initialized with -\tcode{invoke(std::forward(f), std::move(*val))}; +\tcode{invoke(std::forward(f), std::move(*\exposid{val}))}; otherwise, \tcode{optional()}. \end{itemdescr} @@ -4277,7 +4380,7 @@ \begin{itemdescr} \pnum \constraints -\tcode{F} models \tcode{\libconcept{invocable}<>} and +\tcode{F} models \libconcept{invocable} and \tcode{T} models \libconcept{copy_constructible}. \pnum @@ -4304,7 +4407,7 @@ \begin{itemdescr} \pnum \constraints -\tcode{F} models \tcode{\libconcept{invocable}<>} and +\tcode{F} models \libconcept{invocable} and \tcode{T} models \libconcept{move_constructible}. \pnum @@ -4341,14441 +4444,11187 @@ \tcode{*this} does not contain a value. \end{itemdescr} -\rSec2[optional.nullopt]{No-value state indicator} - -\indexlibraryglobal{nullopt_t}% -\indexlibraryglobal{nullopt}% -\begin{itemdecl} -struct nullopt_t{@\seebelow@}; -inline constexpr nullopt_t nullopt(@\unspec@); -\end{itemdecl} - -\pnum -The struct \tcode{nullopt_t} is an empty class type used as a unique type to indicate the state of not containing a value for \tcode{optional} objects. -In particular, \tcode{optional} has a constructor with \tcode{nullopt_t} as a single argument; -this indicates that an optional object not containing a value shall be constructed. - -\pnum -Type \tcode{nullopt_t} shall not have a default constructor or an initializer-list constructor, and shall not be an aggregate. - -\rSec2[optional.bad.access]{Class \tcode{bad_optional_access}} +\rSec2[optional.optional.ref]{Partial specialization of \tcode{optional} for reference types} +\rSec3[optional.optional.ref.general]{General} \begin{codeblock} 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; - }; + template + class optional { + public: + using value_type = T; + using iterator = @\impdefnc@; // see~\ref{optional.ref.iterators} + + public: + // \ref{optional.ref.ctor}, constructors + constexpr optional() noexcept = default; + constexpr optional(nullopt_t) noexcept : optional() {} + constexpr optional(const optional& rhs) noexcept = default; + + template + constexpr explicit optional(in_place_t, Arg&& arg); + template + constexpr explicit(@\seebelow@) optional(U&& u) noexcept(@\seebelow@); + template + constexpr explicit(@\seebelow@) optional(optional& rhs) noexcept(@\seebelow@); + template + constexpr explicit(@\seebelow@) optional(const optional& rhs) noexcept(@\seebelow@); + template + constexpr explicit(@\seebelow@) optional(optional&& rhs) noexcept(@\seebelow@); + template + constexpr explicit(@\seebelow@) optional(const optional&& rhs) noexcept(@\seebelow@); + + constexpr ~optional() = default; + + // \ref{optional.ref.assign}, assignment + constexpr optional& operator=(nullopt_t) noexcept; + constexpr optional& operator=(const optional& rhs) noexcept = default; + + template constexpr T& emplace(U&& u) noexcept(@\seebelow@); + + // \ref{optional.ref.swap}, swap + constexpr void swap(optional& rhs) noexcept; + + // \ref{optional.ref.iterators}, iterator support + constexpr iterator begin() const noexcept; + constexpr iterator end() const noexcept; + + // \ref{optional.ref.observe}, observers + constexpr T* operator->() const noexcept; + constexpr T& operator*() const noexcept; + constexpr explicit operator bool() const noexcept; + constexpr bool has_value() const noexcept; + constexpr T& value() const; // freestanding-deleted + template> + constexpr remove_cv_t value_or(U&& u) const; + + // \ref{optional.ref.monadic}, monadic operations + template constexpr auto and_then(F&& f) const; + template constexpr optional> transform(F&& f) const; + template constexpr optional or_else(F&& f) const; + + // \ref{optional.ref.mod}, modifiers + constexpr void reset() noexcept; + + private: + T* @\exposidnc{val}@ = nullptr; // \expos + + // \ref{optional.ref.expos}, exposition only helper functions + template + constexpr void @\exposidnc{convert-ref-init-val}@(U&& u); // \expos + }; } \end{codeblock} \pnum -The class \tcode{bad_optional_access} defines the type of objects thrown as exceptions to report the situation where an attempt is made to access the value of an optional object that does not contain a value. - -\indexlibrarymember{what}{bad_optional_access}% -\begin{itemdecl} -const char* what() const noexcept override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -An \impldef{return value of \tcode{bad_optional_access::what}} \ntbs{}. -\end{itemdescr} +An object of \tcode{optional} +\defnx{contains a value}{contains a value!\idxcode{optional.ref}} +if and only if \tcode{\exposidnc{val} != nullptr} is \tcode{true}. +When an \tcode{optional} contains a value, +the \defnx{contained value}{contained value!\idxcode{optional.ref}} +is a reference to \tcode{*\exposid{val}}. -\rSec2[optional.relops]{Relational operators} +\rSec3[optional.ref.ctor]{Constructors} -\indexlibrarymember{operator==}{optional}% \begin{itemdecl} -template constexpr bool operator==(const optional& x, const optional& y); +template + constexpr explicit optional(in_place_t, Arg&& arg); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{*x == *y} is well-formed and -its result is convertible to \tcode{bool}. -\begin{note} -\tcode{T} need not be \oldconcept{EqualityComparable}. -\end{note} +\constraints +\begin{itemize} +\item \tcode{is_constructible_v} is \tcode{true}, and +\item \tcode{reference_constructs_from_temporary_v} is \tcode{false}. +\end{itemize} \pnum -\returns -If \tcode{x.has_value() != y.has_value()}, \tcode{false}; otherwise if \tcode{x.has_value() == false}, \tcode{true}; otherwise \tcode{*x == *y}. +\effects +Equivalent to: \tcode{\exposid{convert-ref-init-val}(std::forward(arg))}. \pnum -\remarks -Specializations of this function template -for which \tcode{*x == *y} is a core constant expression -are constexpr functions. +\ensures +\tcode{*this} contains a value. \end{itemdescr} -\indexlibrarymember{operator"!=}{optional}% \begin{itemdecl} -template constexpr bool operator!=(const optional& x, const optional& y); +template + constexpr explicit(!is_convertible_v) + optional(U&& u) noexcept(is_nothrow_constructible_v); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{*x != *y} is well-formed and -its result is convertible to \tcode{bool}. +\constraints +\begin{itemize} +\item \tcode{is_same_v, optional>} is \tcode{false}, +\item \tcode{is_same_v, in_place_t>} is \tcode{false}, and +\item \tcode{is_constructible_v} is \tcode{true}. +\end{itemize} \pnum -\returns -If \tcode{x.has_value() != y.has_value()}, \tcode{true}; -otherwise, if \tcode{x.has_value() == false}, \tcode{false}; -otherwise \tcode{*x != *y}. +\effects +Equivalent to: \tcode{\exposid{convert-ref-init-val}(std::forward(u))}. + +\pnum +\ensures +\tcode{*this} contains a value. \pnum \remarks -Specializations of this function template -for which \tcode{*x != *y} is a core constant expression -are constexpr functions. + This constructor is defined as deleted if +\begin{codeblock} +reference_constructs_from_temporary_v +\end{codeblock} + is \tcode{true}. \end{itemdescr} -\indexlibrarymember{operator<}{optional}% \begin{itemdecl} -template constexpr bool operator<(const optional& x, const optional& y); +template + constexpr explicit(!is_convertible_v) + optional(optional& rhs) noexcept(is_nothrow_constructible_v); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{*x < *y} is well-formed -and its result is convertible to \tcode{bool}. +\constraints +\begin{itemize} +\item \tcode{is_same_v, optional>} is \tcode{false}, +\item \tcode{is_same_v} is \tcode{false}, and +\item \tcode{is_constructible_v} is \tcode{true}. +\end{itemize} \pnum -\returns -If \tcode{!y}, \tcode{false}; -otherwise, if \tcode{!x}, \tcode{true}; -otherwise \tcode{*x < *y}. +\effects +Equivalent to: +\begin{codeblock} +if (rhs.has_value()) @\exposid{convert-ref-init-val}@(*rhs); +\end{codeblock} \pnum \remarks -Specializations of this function template -for which \tcode{*x < *y} is a core constant expression -are constexpr functions. +This constructor is defined as deleted if +\begin{codeblock} +reference_constructs_from_temporary_v +\end{codeblock} +is \tcode{true}. \end{itemdescr} -\indexlibrarymember{operator>}{optional}% \begin{itemdecl} -template constexpr bool operator>(const optional& x, const optional& y); +template + constexpr explicit(!is_convertible_v) + optional(const optional& rhs) noexcept(is_nothrow_constructible_v); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{*x > *y} is well-formed and -its result is convertible to \tcode{bool}. +\constraints +\begin{itemize} +\item \tcode{is_same_v, optional>} is \tcode{false}, +\item \tcode{is_same_v} is \tcode{false}, and +\item \tcode{is_constructible_v} is \tcode{true}. +\end{itemize} \pnum -\returns -If \tcode{!x}, \tcode{false}; -otherwise, if \tcode{!y}, \tcode{true}; -otherwise \tcode{*x > *y}. +\effects +Equivalent to: +\begin{codeblock} +if (rhs.has_value()) @\exposid{convert-ref-init-val}@(*rhs); +\end{codeblock} \pnum \remarks -Specializations of this function template -for which \tcode{*x > *y} is a core constant expression -are constexpr functions. +This constructor is defined as deleted if +\begin{codeblock} +reference_constructs_from_temporary_v +\end{codeblock} +is \tcode{true}. \end{itemdescr} -\indexlibrarymember{operator<=}{optional}% \begin{itemdecl} -template constexpr bool operator<=(const optional& x, const optional& y); +template + constexpr explicit(!is_convertible_v) + optional(optional&& rhs) noexcept(is_nothrow_constructible_v); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{*x <= *y} is well-formed and -its result is convertible to \tcode{bool}. +\constraints +\begin{itemize} +\item \tcode{is_same_v, optional>} is \tcode{false}, +\item \tcode{is_same_v} is \tcode{false}, and +\item \tcode{is_constructible_v} is \tcode{true}. +\end{itemize} \pnum -\returns -If \tcode{!x}, \tcode{true}; -otherwise, if \tcode{!y}, \tcode{false}; -otherwise \tcode{*x <= *y}. +\effects +Equivalent to: +\begin{codeblock} +if (rhs.has_value()) @\exposid{convert-ref-init-val}@(*std::move(rhs)); +\end{codeblock} \pnum \remarks -Specializations of this function template -for which \tcode{*x <= *y} is a core constant expression -are constexpr functions. +This constructor is defined as deleted if +\begin{codeblock} +reference_constructs_from_temporary_v +\end{codeblock} +is \tcode{true}. \end{itemdescr} -\indexlibrarymember{operator>=}{optional}% \begin{itemdecl} -template constexpr bool operator>=(const optional& x, const optional& y); +template + constexpr explicit(!is_convertible_v) + optional(const optional&& rhs) noexcept(is_nothrow_constructible_v); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{*x >= *y} is well-formed and -its result is convertible to \tcode{bool}. +\constraints +\begin{itemize} +\item \tcode{is_same_v, optional>} is \tcode{false}, +\item \tcode{is_same_v} is \tcode{false}, and +\item \tcode{is_constructible_v} is \tcode{true}. +\end{itemize} \pnum -\returns -If \tcode{!y}, \tcode{true}; -otherwise, if \tcode{!x}, \tcode{false}; -otherwise \tcode{*x >= *y}. +\effects +Equivalent to: +\begin{codeblock} +if (rhs.has_value()) @\exposid{convert-ref-init-val}@(*std::move(rhs)); +\end{codeblock} \pnum \remarks -Specializations of this function template -for which \tcode{*x >= *y} is a core constant expression -are constexpr functions. +This constructor is defined as deleted if +\begin{codeblock} +reference_constructs_from_temporary_v +\end{codeblock} +is \tcode{true}. \end{itemdescr} -\indexlibrarymember{operator<=>}{optional}% +\rSec3[optional.ref.assign]{Assignment} + \begin{itemdecl} -template U> - constexpr compare_three_way_result_t - operator<=>(const optional& x, const optional& y); +constexpr optional& operator=(nullopt_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -If \tcode{x \&\& y}, \tcode{*x <=> *y}; otherwise \tcode{x.has_value() <=> y.has_value()}. +\effects +Assigns \tcode{nullptr} to \exposid{val}. \pnum -\remarks -Specializations of this function template -for which \tcode{*x <=> *y} is a core constant expression -are constexpr functions. -\end{itemdescr} +\ensures +\tcode{*this} does not contain a value. -\rSec2[optional.nullops]{Comparison with \tcode{nullopt}} +\pnum +\returns +\tcode{*this}. +\end{itemdescr} -\indexlibrarymember{operator==}{optional}% \begin{itemdecl} -template constexpr bool operator==(const optional& x, nullopt_t) noexcept; +template + constexpr T& emplace(U&& u) noexcept(is_nothrow_constructible_v); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{!x}. +\constraints +\begin{itemize} +\item \tcode{is_constructible_v} is \tcode{true}, and +\item \tcode{reference_constructs_from_temporary_v} is \tcode{false}. +\end{itemize} + +\pnum +\effects +Equivalent to: \tcode{\exposid{convert-ref-init-val}(std::forward(u))}. \end{itemdescr} -\indexlibrarymember{operator<=>}{optional}% +\rSec3[optional.ref.swap]{Swap} + \begin{itemdecl} -template constexpr strong_ordering operator<=>(const optional& x, nullopt_t) noexcept; +constexpr void swap(optional& rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x.has_value() <=> false}. +\effects +Equivalent to: \tcode{swap(\exposid{val}, rhs.\exposid{val})}. \end{itemdescr} -\rSec2[optional.comp.with.t]{Comparison with \tcode{T}} +\rSec3[optional.ref.iterators]{Iterator support} -\indexlibrarymember{operator==}{optional}% \begin{itemdecl} -template constexpr bool operator==(const optional& x, const U& v); +using iterator = @\impdef@; \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{T} need not be \oldconcept{EqualityComparable}. -\end{note} +This type +models \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}, +meets the \oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators}, +and meets the requirements for constexpr iterators\iref{iterator.requirements.general}, +with value type \tcode{remove_cv_t}. +The reference type is \tcode{T\&} for \tcode{iterator}. \pnum -\effects -Equivalent to: \tcode{return x.has_value() ? *x == v : false;} +All requirements on container iterators\iref{container.reqmts} apply to +\tcode{optional::iterator}. \end{itemdescr} -\indexlibrarymember{operator==}{optional}% \begin{itemdecl} -template constexpr bool operator==(const T& v, const optional& x); +constexpr iterator begin() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{v == *x} is well-formed and -its result is convertible to \tcode{bool}. - -\pnum -\effects -Equivalent to: \tcode{return x.has_value() ? v == *x : false;} +\returns + If \tcode{has_value()} is \tcode{true}, + an iterator referring to \tcode{*\exposid{val}}. + Otherwise, a past-the-end iterator value. \end{itemdescr} -\indexlibrarymember{operator"!=}{optional}% \begin{itemdecl} -template constexpr bool operator!=(const optional& x, const U& v); +constexpr iterator end() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{*x != v} is well-formed and -its result is convertible to \tcode{bool}. - -\pnum -\effects -Equivalent to: \tcode{return x.has_value() ? *x != v : true;} +\returns +\tcode{begin() + has_value()}. \end{itemdescr} -\indexlibrarymember{operator"!=}{optional}% +\rSec3[optional.ref.observe]{Observers} + \begin{itemdecl} -template constexpr bool operator!=(const T& v, const optional& x); +constexpr T* operator->() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{v != *x} is well-formed and -its result is convertible to \tcode{bool}. +\hardexpects +\tcode{has_value()} is \tcode{true}. \pnum -\effects -Equivalent to: \tcode{return x.has_value() ? v != *x : true;} +\returns +\exposid{val}. + \end{itemdescr} -\indexlibrarymember{operator<}{optional}% \begin{itemdecl} -template constexpr bool operator<(const optional& x, const U& v); +constexpr T& operator*() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{*x < v} is well-formed and -its result is convertible to \tcode{bool}. +\hardexpects +\tcode{has_value()} is \tcode{true}. \pnum -\effects -Equivalent to: \tcode{return x.has_value() ? *x < v : true;} +\returns +\tcode{*\exposid{val}}. \end{itemdescr} -\indexlibrarymember{operator<}{optional}% \begin{itemdecl} -template constexpr bool operator<(const T& v, const optional& x); +constexpr explicit operator bool() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{v < *x} is well-formed and -its result is convertible to \tcode{bool}. - -\pnum -\effects -Equivalent to: \tcode{return x.has_value() ? v < *x : false;} +\returns +\tcode{\exposid{val} != nullptr}. \end{itemdescr} -\indexlibrarymember{operator>}{optional}% \begin{itemdecl} -template constexpr bool operator>(const optional& x, const U& v); +constexpr bool has_value() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{*x > v} is well-formed and -its result is convertible to \tcode{bool}. +\returns +\tcode{\exposid{val} != nullptr}. +\end{itemdescr} + +\begin{itemdecl} +constexpr T& value() const; +\end{itemdecl} +\begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.has_value() ? *x > v : false;} +Equivalent to: +\begin{codeblock} +return has_value() ? *@\exposid{val}@ : throw bad_optional_access(); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator>}{optional}% \begin{itemdecl} -template constexpr bool operator>(const T& v, const optional& x); +template> constexpr remove_cv_t value_or(U&& u) const; \end{itemdecl} \begin{itemdescr} +\pnum + Let \tcode{X} be \tcode{remove_cv_t}. + \pnum \mandates -The expression \tcode{v > *x} is well-formed and -its result is convertible to \tcode{bool}. +\tcode{is_constructible_v \&\& is_convertible_v} is \tcode{true}. \pnum \effects -Equivalent to: \tcode{return x.has_value() ? v > *x : true;} + Equivalent to: +\begin{codeblock} +return has_value() ? *@\exposid{val}@ : static_cast(std::forward(u)); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator<=}{optional}% +\rSec3[optional.ref.monadic]{Monadic operations} + \begin{itemdecl} -template constexpr bool operator<=(const optional& x, const U& v); +template constexpr auto and_then(F&& f) const; \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{U} be \tcode{invoke_result_t}. + \pnum \mandates -The expression \tcode{*x <= v} is well-formed and -its result is convertible to \tcode{bool}. +\tcode{remove_cvref_t} is a specialization of \tcode{optional}. \pnum \effects -Equivalent to: \tcode{return x.has_value() ? *x <= v : true;} + Equivalent to: +\begin{codeblock} +if (has_value()) { + return invoke(std::forward(f), *@\exposid{val}@); +} else { + return remove_cvref_t(); +} +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator<=}{optional}% \begin{itemdecl} -template constexpr bool operator<=(const T& v, const optional& x); +template + constexpr optional>> transform(F&& f) const; \end{itemdecl} \begin{itemdescr} +\pnum + Let \tcode{U} be \tcode{remove_cv_t>}. + \pnum \mandates -The expression \tcode{v <= *x} is well-formed and -its result is convertible to \tcode{bool}. +The declaration +\begin{codeblock} +U u(invoke(std::forward(f), *@\exposid{val}@)); +\end{codeblock} +is well-formed for some invented variable \tcode{u}. +\begin{note} +There is no requirement that \tcode{U} is movable\iref{dcl.init.general}. +\end{note} \pnum -\effects -Equivalent to: \tcode{return x.has_value() ? v <= *x : false;} +\returns +If \tcode{*this} contains a value, an \tcode{optional} object +whose contained value is direct-non-list-initialized with +\tcode{invoke(std::forward(f), *\exposid{val})}; +otherwise, \tcode{optional()}. \end{itemdescr} -\indexlibrarymember{operator>=}{optional}% \begin{itemdecl} -template constexpr bool operator>=(const optional& x, const U& v); +template constexpr optional or_else(F&& f) const; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{F} models \tcode{\libconcept{invocable}}. + \pnum \mandates -The expression \tcode{*x >= v} is well-formed and -its result is convertible to \tcode{bool}. +\tcode{is_same_v>, optional>} is \tcode{true}. \pnum \effects -Equivalent to: \tcode{return x.has_value() ? *x >= v : false;} +Equivalent to: +\begin{codeblock} +if (has_value()) { + return *@\exposid{val}@; +} else { + return std::forward(f)(); +} +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator>=}{optional}% +\rSec3[optional.ref.mod]{Modifiers} + \begin{itemdecl} -template constexpr bool operator>=(const T& v, const optional& x); +constexpr void reset() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{v >= *x} is well-formed and -its result is convertible to \tcode{bool}. +\effects +Assigns \tcode{nullptr} to \exposid{val}. \pnum -\effects -Equivalent to: \tcode{return x.has_value() ? v >= *x : true;} +\ensures +\tcode{*this} does not contain a value. \end{itemdescr} -\indexlibrarymember{operator<=>}{optional}% +\rSec3[optional.ref.expos]{Exposition only helper functions} + \begin{itemdecl} -template - requires (!@\exposconcept{is-derived-from-optional}@) && @\libconcept{three_way_comparable_with}@ - constexpr compare_three_way_result_t - operator<=>(const optional& x, const U& v); +template + constexpr void @\exposid{convert-ref-init-val}@(U&& u); // \expos \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{return x.has_value() ? *x <=> v : strong_ordering::less;} +Creates a variable \tcode{r} as if by \tcode{T\& r(std::forward(u));} +and then initializes \exposid{val} with \tcode{addressof(r)}. \end{itemdescr} -\rSec2[optional.specalg]{Specialized algorithms} +\rSec2[optional.nullopt]{No-value state indicator} -\indexlibrarymember{swap}{optional}% +\indexlibraryglobal{nullopt_t}% +\indexlibraryglobal{nullopt}% \begin{itemdecl} -template - constexpr void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y))); +struct nullopt_t{@\seebelow@}; +inline constexpr nullopt_t nullopt(@\unspec@); \end{itemdecl} -\begin{itemdescr} \pnum -\constraints -\tcode{is_move_constructible_v} is \tcode{true} and -\tcode{is_swappable_v} is \tcode{true}. +The struct \tcode{nullopt_t} is an empty class type used as a unique type to indicate the state of not containing a value for \tcode{optional} objects. +In particular, \tcode{optional} has a constructor with \tcode{nullopt_t} as a single argument; +this indicates that an optional object not containing a value shall be constructed. \pnum -\effects -Calls \tcode{x.swap(y)}. -\end{itemdescr} +Type \tcode{nullopt_t} shall not have a default constructor or an initializer-list constructor, and shall not be an aggregate. -\indexlibraryglobal{make_optional}% +\rSec2[optional.bad.access]{Class \tcode{bad_optional_access}} + +\begin{codeblock} +namespace std { + class bad_optional_access : public exception { + public: + // see \ref{exception} for the specification of the special member functions + constexpr const char* what() const noexcept override; + }; +} +\end{codeblock} + +\pnum +The class \tcode{bad_optional_access} defines the type of objects thrown as exceptions to report the situation where an attempt is made to access the value of an optional object that does not contain a value. + +\indexlibrarymember{what}{bad_optional_access}% \begin{itemdecl} -template constexpr optional> make_optional(T&& v); +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{optional>(std::forward(v))}. +An \impldef{return value of \tcode{bad_optional_access::what}} \ntbs{}, +which during constant evaluation is encoded with +the ordinary literal encoding\iref{lex.ccon}. \end{itemdescr} -\indexlibraryglobal{make_optional}% +\rSec2[optional.relops]{Relational operators} + +\indexlibrarymember{operator==}{optional}% \begin{itemdecl} -template - constexpr optional make_optional(Args&&... args); +template constexpr bool operator==(const optional& x, const optional& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return optional(in_place, std::forward(args)...);} +\constraints +The expression \tcode{*x == *y} is well-formed and +its result is convertible to \tcode{bool}. +\begin{note} +\tcode{T} need not be \oldconcept{EqualityComparable}. +\end{note} + +\pnum +\returns +If \tcode{x.has_value() != y.has_value()}, \tcode{false}; otherwise if \tcode{x.has_value() == false}, \tcode{true}; otherwise \tcode{*x == *y}. + +\pnum +\remarks +Specializations of this function template +for which \tcode{*x == *y} is a core constant expression +are constexpr functions. \end{itemdescr} -\indexlibraryglobal{make_optional}% +\indexlibrarymember{operator"!=}{optional}% \begin{itemdecl} -template - constexpr optional make_optional(initializer_list il, Args&&... args); +template constexpr bool operator!=(const optional& x, const optional& y); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return optional(in_place, il, std::forward(args)...);} -\end{itemdescr} +\constraints +The expression \tcode{*x != *y} is well-formed and +its result is convertible to \tcode{bool}. -\rSec2[optional.hash]{Hash support} +\pnum +\returns +If \tcode{x.has_value() != y.has_value()}, \tcode{true}; +otherwise, if \tcode{x.has_value() == false}, \tcode{false}; +otherwise \tcode{*x != *y}. -\indexlibrarymember{hash}{optional}% +\pnum +\remarks +Specializations of this function template +for which \tcode{*x != *y} is a core constant expression +are constexpr functions. +\end{itemdescr} + +\indexlibrarymember{operator<}{optional}% \begin{itemdecl} -template struct hash>; +template constexpr bool operator<(const optional& x, const optional& y); \end{itemdecl} \begin{itemdescr} \pnum -The specialization \tcode{hash>} is enabled\iref{unord.hash} -if and only if \tcode{hash>} is enabled. -When enabled, for an object \tcode{o} of type \tcode{optional}, -if \tcode{o.has_value() == true}, then \tcode{hash>()(o)} -evaluates to the same value as \tcode{hash>()(*o)}; -otherwise it evaluates to an unspecified value. -The member functions are not guaranteed to be \keyword{noexcept}. -\end{itemdescr} +\constraints +\tcode{*x < *y} is well-formed +and its result is convertible to \tcode{bool}. +\pnum +\returns +If \tcode{!y}, \tcode{false}; +otherwise, if \tcode{!x}, \tcode{true}; +otherwise \tcode{*x < *y}. -\rSec1[variant]{Variants} +\pnum +\remarks +Specializations of this function template +for which \tcode{*x < *y} is a core constant expression +are constexpr functions. +\end{itemdescr} -\rSec2[variant.general]{In general} +\indexlibrarymember{operator>}{optional}% +\begin{itemdecl} +template constexpr bool operator>(const optional& x, const optional& y); +\end{itemdecl} +\begin{itemdescr} \pnum -A variant object holds and manages the lifetime of a value. -If the \tcode{variant} holds a value, that value's type has to be one -of the template argument types given to \tcode{variant}. -These template arguments are called alternatives. +\constraints +The expression \tcode{*x > *y} is well-formed and +its result is convertible to \tcode{bool}. \pnum -In subclause \ref{variant}, -\exposid{GET} denotes -a set of exposition-only function templates\iref{variant.get}. +\returns +If \tcode{!x}, \tcode{false}; +otherwise, if \tcode{!y}, \tcode{true}; +otherwise \tcode{*x > *y}. -\rSec2[variant.syn]{Header \tcode{} synopsis} -\indexheader{variant}% +\pnum +\remarks +Specializations of this function template +for which \tcode{*x > *y} is a core constant expression +are constexpr functions. +\end{itemdescr} -\begin{codeblock} -// mostly freestanding -#include // see \ref{compare.syn} +\indexlibrarymember{operator<=}{optional}% +\begin{itemdecl} +template constexpr bool operator<=(const optional& x, const optional& y); +\end{itemdecl} -namespace std { - // \ref{variant.variant}, class template \tcode{variant} - template - class variant; +\begin{itemdescr} +\pnum +\constraints +The expression \tcode{*x <= *y} is well-formed and +its result is convertible to \tcode{bool}. - // \ref{variant.helper}, variant helper classes - template struct variant_size; // \notdef - template struct variant_size; - template - constexpr size_t @\libglobal{variant_size_v}@ = variant_size::value; +\pnum +\returns +If \tcode{!x}, \tcode{true}; +otherwise, if \tcode{!y}, \tcode{false}; +otherwise \tcode{*x <= *y}. - template - struct variant_size>; +\pnum +\remarks +Specializations of this function template +for which \tcode{*x <= *y} is a core constant expression +are constexpr functions. +\end{itemdescr} - template struct variant_alternative; // \notdef - template struct variant_alternative; - template - using @\libglobal{variant_alternative_t}@ = typename variant_alternative::type; +\indexlibrarymember{operator>=}{optional}% +\begin{itemdecl} +template constexpr bool operator>=(const optional& x, const optional& y); +\end{itemdecl} - template - struct variant_alternative>; +\begin{itemdescr} +\pnum +\constraints +The expression \tcode{*x >= *y} is well-formed and +its result is convertible to \tcode{bool}. - inline constexpr size_t variant_npos = -1; +\pnum +\returns +If \tcode{!y}, \tcode{true}; +otherwise, if \tcode{!x}, \tcode{false}; +otherwise \tcode{*x >= *y}. - // \ref{variant.get}, value access - template - constexpr bool holds_alternative(const variant&) noexcept; +\pnum +\remarks +Specializations of this function template +for which \tcode{*x >= *y} is a core constant expression +are constexpr functions. +\end{itemdescr} - template - constexpr variant_alternative_t>& - get(variant&); // freestanding-deleted - template - constexpr variant_alternative_t>&& - get(variant&&); // freestanding-deleted - template - constexpr const variant_alternative_t>& - get(const variant&); // freestanding-deleted - template - constexpr const variant_alternative_t>&& - get(const variant&&); // freestanding-deleted +\indexlibrarymember{operator<=>}{optional}% +\begin{itemdecl} +template U> + constexpr compare_three_way_result_t + operator<=>(const optional& x, const optional& y); +\end{itemdecl} - template - constexpr T& get(variant&); // freestanding-deleted - template - constexpr T&& get(variant&&); // freestanding-deleted - template - constexpr const T& get(const variant&); // freestanding-deleted - template - constexpr const T&& get(const variant&&); // freestanding-deleted +\begin{itemdescr} +\pnum +\returns +If \tcode{x \&\& y}, \tcode{*x <=> *y}; otherwise \tcode{x.has_value() <=> y.has_value()}. - template - constexpr add_pointer_t>> - get_if(variant*) noexcept; - template - constexpr add_pointer_t>> - get_if(const variant*) noexcept; +\pnum +\remarks +Specializations of this function template +for which \tcode{*x <=> *y} is a core constant expression +are constexpr functions. +\end{itemdescr} - template - constexpr add_pointer_t - get_if(variant*) noexcept; - template - constexpr add_pointer_t - get_if(const variant*) noexcept; +\rSec2[optional.nullops]{Comparison with \tcode{nullopt}} - // \ref{variant.relops}, relational operators - template - constexpr bool operator==(const variant&, const variant&); - template - constexpr bool operator!=(const variant&, const variant&); - template - constexpr bool operator<(const variant&, const variant&); - template - constexpr bool operator>(const variant&, const variant&); - template - constexpr bool operator<=(const variant&, const variant&); - template - constexpr bool operator>=(const variant&, const variant&); - template requires (@\libconcept{three_way_comparable}@ && ...) - constexpr common_comparison_category_t...> - operator<=>(const variant&, const variant&); +\indexlibrarymember{operator==}{optional}% +\begin{itemdecl} +template constexpr bool operator==(const optional& x, nullopt_t) noexcept; +\end{itemdecl} - // \ref{variant.visit}, visitation - template - constexpr @\seebelow@ visit(Visitor&&, Variants&&...); - template - constexpr R visit(Visitor&&, Variants&&...); +\begin{itemdescr} +\pnum +\returns +\tcode{!x}. +\end{itemdescr} - // \ref{variant.monostate}, class \tcode{monostate} - struct monostate; +\indexlibrarymember{operator<=>}{optional}% +\begin{itemdecl} +template constexpr strong_ordering operator<=>(const optional& x, nullopt_t) noexcept; +\end{itemdecl} - // \ref{variant.monostate.relops}, \tcode{monostate} relational operators - constexpr bool operator==(monostate, monostate) noexcept; - constexpr strong_ordering operator<=>(monostate, monostate) noexcept; +\begin{itemdescr} +\pnum +\returns +\tcode{x.has_value() <=> false}. +\end{itemdescr} - // \ref{variant.specalg}, specialized algorithms - template - constexpr void swap(variant&, variant&) noexcept(@\seebelow@); +\rSec2[optional.comp.with.t]{Comparison with \tcode{T}} - // \ref{variant.bad.access}, class \tcode{bad_variant_access} - class bad_variant_access; - - // \ref{variant.hash}, hash support - template struct hash; - template struct hash>; - template<> struct hash; -} -\end{codeblock} - -\rSec2[variant.variant]{Class template \tcode{variant}}% -\indexlibraryglobal{variant}% - -\rSec3[variant.variant.general]{General} - -\begin{codeblock} -namespace std { - template - class variant { - public: - // \ref{variant.ctor}, constructors - constexpr variant() noexcept(@\seebelow@); - constexpr variant(const variant&); - constexpr variant(variant&&) noexcept(@\seebelow@); - - template - constexpr variant(T&&) noexcept(@\seebelow@); - - template - constexpr explicit variant(in_place_type_t, Args&&...); - template - constexpr explicit variant(in_place_type_t, initializer_list, Args&&...); - - template - constexpr explicit variant(in_place_index_t, Args&&...); - template - constexpr explicit variant(in_place_index_t, initializer_list, Args&&...); - - // \ref{variant.dtor}, destructor - constexpr ~variant(); +\indexlibrarymember{operator==}{optional}% +\begin{itemdecl} +template constexpr bool operator==(const optional& x, const U& v); +\end{itemdecl} - // \ref{variant.assign}, assignment - constexpr variant& operator=(const variant&); - constexpr variant& operator=(variant&&) noexcept(@\seebelow@); +\begin{itemdescr} +\pnum +\constraints +\tcode{U} is not a specialization of \tcode{optional}. +The expression \tcode{*x == v} is well-formed and +its result is convertible to \tcode{bool}. +\begin{note} +\tcode{T} need not be \oldconcept{EqualityComparable}. +\end{note} - template constexpr variant& operator=(T&&) noexcept(@\seebelow@); +\pnum +\effects +Equivalent to: \tcode{return x.has_value() ? *x == v : false;} +\end{itemdescr} - // \ref{variant.mod}, modifiers - template - constexpr T& emplace(Args&&...); - template - constexpr T& emplace(initializer_list, Args&&...); - template - constexpr variant_alternative_t>& emplace(Args&&...); - template - constexpr variant_alternative_t>& - emplace(initializer_list, Args&&...); +\indexlibrarymember{operator==}{optional}% +\begin{itemdecl} +template constexpr bool operator==(const T& v, const optional& x); +\end{itemdecl} - // \ref{variant.status}, value status - constexpr bool valueless_by_exception() const noexcept; - constexpr size_t index() const noexcept; +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is not a specialization of \tcode{optional}. +The expression \tcode{v == *x} is well-formed and +its result is convertible to \tcode{bool}. - // \ref{variant.swap}, swap - constexpr void swap(variant&) noexcept(@\seebelow@); +\pnum +\effects +Equivalent to: \tcode{return x.has_value() ? v == *x : false;} +\end{itemdescr} - // \ref{variant.visit}, visitation - template - constexpr decltype(auto) visit(this Self&&, Visitor&&); - template - constexpr R visit(this Self&&, Visitor&&); - }; -} -\end{codeblock} +\indexlibrarymember{operator"!=}{optional}% +\begin{itemdecl} +template constexpr bool operator!=(const optional& x, const U& v); +\end{itemdecl} +\begin{itemdescr} \pnum -Any instance of \tcode{variant} at any given time either holds a value -of one of its alternative types or holds no value. -When an instance of \tcode{variant} holds a value of alternative type \tcode{T}, -it means that a value of type \tcode{T}, referred to as the \tcode{variant} -object's \defnx{contained value}{contained value!\idxcode{variant}}, is allocated within the storage of the -\tcode{variant} object. -Implementations are not permitted to use additional storage, such as dynamic -memory, to allocate the contained value. +\constraints +\tcode{U} is not a specialization of \tcode{optional}. +The expression \tcode{*x != v} is well-formed and +its result is convertible to \tcode{bool}. \pnum -All types in \tcode{Types} shall meet -the \oldconcept{Destructible} requirements (\tref{cpp17.destructible}). +\effects +Equivalent to: \tcode{return x.has_value() ? *x != v : true;} +\end{itemdescr} -\pnum -A program that instantiates the definition of \tcode{variant} with -no template arguments is ill-formed. +\indexlibrarymember{operator"!=}{optional}% +\begin{itemdecl} +template constexpr bool operator!=(const T& v, const optional& x); +\end{itemdecl} +\begin{itemdescr} \pnum -If a program declares an explicit or partial specialization of \tcode{variant}, -the program is ill-formed, no diagnostic required. - -\rSec3[variant.ctor]{Constructors} +\constraints +\tcode{T} is not a specialization of \tcode{optional}. +The expression \tcode{v != *x} is well-formed and +its result is convertible to \tcode{bool}. \pnum -In the descriptions that follow, let $i$ be in the range \range{0}{sizeof...(Types)}, -and $\tcode{T}_i$ be the $i^\text{th}$ type in \tcode{Types}. +\effects +Equivalent to: \tcode{return x.has_value() ? v != *x : true;} +\end{itemdescr} -\indexlibraryctor{variant}% +\indexlibrarymember{operator<}{optional}% \begin{itemdecl} -constexpr variant() noexcept(@\seebelow@); +template constexpr bool operator<(const optional& x, const U& v); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_default_constructible_v<$\tcode{T}_0$>} is \tcode{true}. +\tcode{U} is not a specialization of \tcode{optional}. +The expression \tcode{*x < v} is well-formed and +its result is convertible to \tcode{bool}. \pnum \effects -Constructs a \tcode{variant} holding a value-initialized value of type $\tcode{T}_0$. +Equivalent to: \tcode{return x.has_value() ? *x < v : true;} +\end{itemdescr} -\pnum -\ensures -\tcode{valueless_by_exception()} is \tcode{false} and \tcode{index()} is \tcode{0}. +\indexlibrarymember{operator<}{optional}% +\begin{itemdecl} +template constexpr bool operator<(const T& v, const optional& x); +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -Any exception thrown by the value-initialization of $\tcode{T}_0$. +\constraints +\tcode{T} is not a specialization of \tcode{optional}. +The expression \tcode{v < *x} is well-formed and +its result is convertible to \tcode{bool}. \pnum -\remarks -This function is \keyword{constexpr} if and only if the -value-initialization of the alternative type $\tcode{T}_0$ -would be constexpr-suitable\iref{dcl.constexpr}. -The exception specification is equivalent to -\tcode{is_nothrow_default_constructible_v<$\tcode{T}_0$>}. -\begin{note} -See also class \tcode{monostate}. -\end{note} +\effects +Equivalent to: \tcode{return x.has_value() ? v < *x : false;} \end{itemdescr} -\indexlibraryctor{variant}% +\indexlibrarymember{operator>}{optional}% \begin{itemdecl} -constexpr variant(const variant& w); +template constexpr bool operator>(const optional& x, const U& v); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{U} is not a specialization of \tcode{optional}. +The expression \tcode{*x > v} is well-formed and +its result is convertible to \tcode{bool}. + \pnum \effects -If \tcode{w} holds a value, initializes the \tcode{variant} to hold the same -alternative as \tcode{w} and direct-initializes the contained value -with \tcode{\exposid{GET}(w)}, where \tcode{j} is \tcode{w.index()}. -Otherwise, initializes the \tcode{variant} to not hold a value. +Equivalent to: \tcode{return x.has_value() ? *x > v : false;} +\end{itemdescr} + +\indexlibrarymember{operator>}{optional}% +\begin{itemdecl} +template constexpr bool operator>(const T& v, const optional& x); +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -Any exception thrown by direct-initializing any $\tcode{T}_i$ for all $i$. +\constraints +\tcode{T} is not a specialization of \tcode{optional}. +The expression \tcode{v > *x} is well-formed and +its result is convertible to \tcode{bool}. \pnum -\remarks -This constructor is defined as deleted unless -\tcode{is_copy_constructible_v<$\tcode{T}_i$>} is \tcode{true} for all $i$. -If \tcode{is_trivially_copy_constructible_v<$\tcode{T}_i$>} -is \tcode{true} for all $i$, this constructor is trivial. +\effects +Equivalent to: \tcode{return x.has_value() ? v > *x : true;} \end{itemdescr} -\indexlibraryctor{variant}% +\indexlibrarymember{operator<=}{optional}% \begin{itemdecl} -constexpr variant(variant&& w) noexcept(@\seebelow@); +template constexpr bool operator<=(const optional& x, const U& v); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_move_constructible_v<$\tcode{T}_i$>} is \tcode{true} for all $i$. +\tcode{U} is not a specialization of \tcode{optional}. +The expression \tcode{*x <= v} is well-formed and +its result is convertible to \tcode{bool}. \pnum \effects -If \tcode{w} holds a value, initializes the \tcode{variant} to hold the same -alternative as \tcode{w} and direct-initializes the contained value with -\tcode{\exposid{GET}(std::move(w))}, where \tcode{j} is \tcode{w.index()}. -Otherwise, initializes the \tcode{variant} to not hold a value. +Equivalent to: \tcode{return x.has_value() ? *x <= v : true;} +\end{itemdescr} + +\indexlibrarymember{operator<=}{optional}% +\begin{itemdecl} +template constexpr bool operator<=(const T& v, const optional& x); +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -Any exception thrown by move-constructing any $\tcode{T}_i$ for all $i$. +\constraints +\tcode{T} is not a specialization of \tcode{optional}. +The expression \tcode{v <= *x} is well-formed and +its result is convertible to \tcode{bool}. \pnum -\remarks -The exception specification is equivalent to the logical \logop{and} of -\tcode{is_nothrow_move_con\-structible_v<$\tcode{T}_i$>} for all $i$. -If \tcode{is_trivially_move_constructible_v<$\tcode{T}_i$>} -is \tcode{true} for all $i$, this constructor is trivial. +\effects +Equivalent to: \tcode{return x.has_value() ? v <= *x : false;} \end{itemdescr} -\indexlibraryctor{variant}% +\indexlibrarymember{operator>=}{optional}% \begin{itemdecl} -template constexpr variant(T&& t) noexcept(@\seebelow@); +template constexpr bool operator>=(const optional& x, const U& v); \end{itemdecl} \begin{itemdescr} \pnum -Let $\tcode{T}_j$ be a type that is determined as follows: -build an imaginary function \tcode{\placeholdernc{FUN}($\tcode{T}_i$)} -for each alternative type $\tcode{T}_i$ -for which \tcode{$\tcode{T}_i$ x[] =} \tcode{\{std::forward(t)\};} -is well-formed for some invented variable \tcode{x}. -The overload \tcode{\placeholdernc{FUN}($\tcode{T}_j$)} selected by overload -resolution for the expression \tcode{\placeholdernc{FUN}(std::forward(\brk{}t))} defines -the alternative $\tcode{T}_j$ which is the type of the contained value after -construction. +\constraints +\tcode{U} is not a specialization of \tcode{optional}. +The expression \tcode{*x >= v} is well-formed and +its result is convertible to \tcode{bool}. \pnum -\constraints -\begin{itemize} -\item -\tcode{sizeof...(Types)} is nonzero, +\effects +Equivalent to: \tcode{return x.has_value() ? *x >= v : false;} +\end{itemdescr} -\item -\tcode{is_same_v, variant>} is \tcode{false}, - -\item -\tcode{remove_cvref_t} is neither -a specialization of \tcode{in_place_type_t} nor -a specialization of \tcode{in_place_index_t}, - -\item -\tcode{is_constructible_v<$\tcode{T}_j$, T>} is \tcode{true}, and - -\item -the expression \tcode{\placeholdernc{FUN}(}\brk\tcode{std::forward(t))} -(with \tcode{\placeholdernc{FUN}} being the above-mentioned set of -imaginary functions) is well-formed. -\begin{note} -\begin{codeblock} -variant v("abc"); -\end{codeblock} -is ill-formed, as both alternative types have an equally viable constructor -for the argument. -\end{note} -\end{itemize} - -\pnum -\effects -Initializes \tcode{*this} to hold the alternative type $\tcode{T}_j$ and -direct-non-list-initializes the contained value with \tcode{std::forward(t)}. - -\pnum -\ensures -\tcode{holds_alternative<$\tcode{T}_j$>(*this)} is \tcode{true}. - -\pnum -\throws -Any exception thrown by the initialization of the selected alternative $\tcode{T}_j$. - -\pnum -\remarks -The exception specification is equivalent to -\tcode{is_nothrow_constructible_v<$\tcode{T}_j$, T>}. -If $\tcode{T}_j$'s selected constructor is a constexpr constructor, -this constructor is a constexpr constructor. -\end{itemdescr} - -\indexlibraryctor{variant}% +\indexlibrarymember{operator>=}{optional}% \begin{itemdecl} -template constexpr explicit variant(in_place_type_t, Args&&... args); +template constexpr bool operator>=(const T& v, const optional& x); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\begin{itemize} -\item There is exactly one occurrence of \tcode{T} in \tcode{Types...} and -\item \tcode{is_constructible_v} is \tcode{true}. -\end{itemize} +\tcode{T} is not a specialization of \tcode{optional}. +The expression \tcode{v >= *x} is well-formed and +its result is convertible to \tcode{bool}. \pnum \effects -Direct-non-list-initializes the contained value of type \tcode{T} -with \tcode{std::forward(args)...}. - -\pnum -\ensures -\tcode{holds_alternative(*this)} is \tcode{true}. - -\pnum -\throws -Any exception thrown by calling the selected constructor of \tcode{T}. - -\pnum -\remarks -If \tcode{T}'s selected constructor is a constexpr constructor, this -constructor is a constexpr constructor. +Equivalent to: \tcode{return x.has_value() ? v >= *x : true;} \end{itemdescr} -\indexlibraryctor{variant}% +\indexlibrarymember{operator<=>}{optional}% \begin{itemdecl} -template - constexpr explicit variant(in_place_type_t, initializer_list il, Args&&... args); +template + requires (!@\exposconcept{is-derived-from-optional}@) && @\libconcept{three_way_comparable_with}@ + constexpr compare_three_way_result_t + operator<=>(const optional& x, const U& v); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\begin{itemize} -\item There is exactly one occurrence of \tcode{T} in \tcode{Types...} and -\item \tcode{is_constructible_v\&, Args...>} is \tcode{true}. -\end{itemize} - \pnum \effects -Direct-non-list-initializes the contained value of type \tcode{T} -with \tcode{il, std::forward(\brk{}args)...}. - -\pnum -\ensures -\tcode{holds_alternative(*this)} is \tcode{true}. - -\pnum -\throws -Any exception thrown by calling the selected constructor of \tcode{T}. - -\pnum -\remarks -If \tcode{T}'s selected constructor is a constexpr constructor, this -constructor is a constexpr constructor. +Equivalent to: \tcode{return x.has_value() ? *x <=> v : strong_ordering::less;} \end{itemdescr} -\indexlibraryctor{variant}% +\rSec2[optional.specalg]{Specialized algorithms} + +\indexlibrarymember{swap}{optional}% \begin{itemdecl} -template constexpr explicit variant(in_place_index_t, Args&&... args); +template + constexpr void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y))); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\begin{itemize} -\item -\tcode{I} is less than \tcode{sizeof...(Types)} and -\item -\tcode{is_constructible_v<$\tcode{T}_I$, Args...>} is \tcode{true}. -\end{itemize} +\begin{codeblock} +is_reference_v || (is_move_constructible_v && is_swappable_v) +\end{codeblock} +is \tcode{true}. \pnum \effects -Direct-non-list-initializes the contained value of type $\tcode{T}_I$ -with \tcode{std::forward(args)...}. - -\pnum -\ensures -\tcode{index()} is \tcode{I}. - -\pnum -\throws -Any exception thrown by calling the selected constructor of $\tcode{T}_I$. - -\pnum -\remarks -If $\tcode{T}_I$'s selected constructor is a constexpr constructor, this -constructor is a constexpr constructor. +Calls \tcode{x.swap(y)}. \end{itemdescr} -\indexlibraryctor{variant}% +\indexlibraryglobal{make_optional}% \begin{itemdecl} -template - constexpr explicit variant(in_place_index_t, initializer_list il, Args&&... args); +template constexpr optional> make_optional(T&& v); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\begin{itemize} -\item -\tcode{I} is less than \tcode{sizeof...(Types)} and -\item -\tcode{is_constructible_v<$\tcode{T}_I$, initializer_list\&, Args...>} is \tcode{true}. -\end{itemize} +The call to \tcode{make_optional} does not use +an explicit \grammarterm{template-argument-list} that +begins with a type \grammarterm{template-argument}. \pnum -\effects -Direct-non-list-initializes the contained value of type $\tcode{T}_I$ -with \tcode{il, std::forward(\brk{}args)...}. +\returns +\tcode{optional>(std::forward(v))}. +\end{itemdescr} -\pnum -\ensures -\tcode{index()} is \tcode{I}. +\indexlibraryglobal{make_optional}% +\begin{itemdecl} +template + constexpr optional make_optional(Args&&... args); +\end{itemdecl} +\begin{itemdescr} \pnum -\remarks -If $\tcode{T}_I$'s selected constructor is a constexpr constructor, this -constructor is a constexpr constructor. +\effects +Equivalent to: \tcode{return optional(in_place, std::forward(args)...);} \end{itemdescr} -\rSec3[variant.dtor]{Destructor} - -\indexlibrarydtor{variant}% +\indexlibraryglobal{make_optional}% \begin{itemdecl} -constexpr ~variant(); +template + constexpr optional make_optional(initializer_list il, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum \effects -If \tcode{valueless_by_exception()} is \tcode{false}, -destroys the currently contained value. - -\pnum -\remarks -If \tcode{is_trivially_destructible_v<$\tcode{T}_i$>} is \tcode{true} for all $\tcode{T}_i$, -then this destructor is trivial. +Equivalent to: \tcode{return optional(in_place, il, std::forward(args)...);} \end{itemdescr} -\rSec3[variant.assign]{Assignment} +\rSec2[optional.hash]{Hash support} -\indexlibrarymember{operator=}{variant}% +\indexlibrarymember{hash}{optional}% \begin{itemdecl} -constexpr variant& operator=(const variant& rhs); +template struct hash>; \end{itemdecl} \begin{itemdescr} \pnum -Let $j$ be \tcode{rhs.index()}. +The specialization \tcode{hash>} is enabled\iref{unord.hash} +if and only if \tcode{hash>} is enabled. +When enabled, for an object \tcode{o} of type \tcode{optional}, +if \tcode{o.has_value() == true}, then \tcode{hash>()(o)} +evaluates to the same value as \tcode{hash>()(*o)}; +otherwise it evaluates to an unspecified value. +The member functions are not guaranteed to be \keyword{noexcept}. +\end{itemdescr} -\pnum -\effects -\begin{itemize} -\item -If neither \tcode{*this} nor \tcode{rhs} holds a value, there is no effect. -\item -Otherwise, if \tcode{*this} holds a value but \tcode{rhs} does not, destroys the value -contained in \tcode{*this} and sets \tcode{*this} to not hold a value. -\item -Otherwise, if \tcode{index() == $j$}, assigns the value contained in \tcode{rhs} -to the value contained in \tcode{*this}. -\item -Otherwise, if either \tcode{is_nothrow_copy_constructible_v<$\tcode{T}_j$>} -is \tcode{true} or -\tcode{is_nothrow_move_con\-structible_v<$\tcode{T}_j$>} is \tcode{false}, -equivalent to \tcode{emplace<$j$>(\exposid{GET}<$j$>(rhs))}. -\item -Otherwise, equivalent to \tcode{operator=(variant(rhs))}. -\end{itemize} -\pnum -\ensures -\tcode{index() == rhs.index()}. +\rSec1[variant]{Variants} -\pnum -\returns -\tcode{*this}. +\rSec2[variant.general]{General} \pnum -\remarks -This operator is defined as deleted unless -\tcode{is_copy_constructible_v<$\tcode{T}_i$> \&\&} -\tcode{is_copy_assignable_v<$\tcode{T}_i$>} -is \tcode{true} for all $i$. -If \tcode{is_trivially_copy_constructible_v<$\tcode{T}_i$> \&\&} -\tcode{is_trivially_copy_assignable_v<$\tcode{T}_i$> \&\&} -\tcode{is_trivially_destructible_v<$\tcode{T}_i$>} -is \tcode{true} for all $i$, this assignment operator is trivial. -\end{itemdescr} - -\indexlibrarymember{operator=}{variant}% -\begin{itemdecl} -constexpr variant& operator=(variant&& rhs) noexcept(@\seebelow@); -\end{itemdecl} +A variant object holds and manages the lifetime of a value. +If the \tcode{variant} holds a value, that value's type has to be one +of the template argument types given to \tcode{variant}. +These template arguments are called alternatives. -\begin{itemdescr} \pnum -Let $j$ be \tcode{rhs.index()}. +In \ref{variant}, +\exposid{GET} denotes +a set of exposition-only function templates\iref{variant.get}. -\pnum -\constraints -\tcode{is_move_constructible_v<$\tcode{T}_i$> \&\&} -\tcode{is_move_assignable_v<$\tcode{T}_i$>} is -\tcode{true} for all $i$. +\rSec2[variant.syn]{Header \tcode{} synopsis} +\indexheader{variant}% -\pnum -\effects -\begin{itemize} -\item -If neither \tcode{*this} nor \tcode{rhs} holds a value, there is no effect. -\item -Otherwise, if \tcode{*this} holds a value but \tcode{rhs} does not, destroys the value -contained in \tcode{*this} and sets \tcode{*this} to not hold a value. -\item -Otherwise, if \tcode{index() == $j$}, assigns \tcode{\exposid{GET}<$j$>(std::move(rhs))} to -the value contained in \tcode{*this}. -\item -Otherwise, equivalent to \tcode{emplace<$j$>(\exposid{GET}<$j$>(std::move(rhs)))}. -\end{itemize} - -\pnum -\returns -\tcode{*this}. - -\pnum -\remarks -If \tcode{is_trivially_move_constructible_v<$\tcode{T}_i$> \&\&} -\tcode{is_trivially_move_assignable_v<$\tcode{T}_i$> \&\&} -\tcode{is_trivially_destructible_v<$\tcode{T}_i$>} -is \tcode{true} for all $i$, this assignment operator is trivial. -The exception specification is equivalent to -\tcode{is_nothrow_move_constructible_v<$\tcode{T}_i$> \&\& is_nothrow_move_assignable_v<$\tcode{T}_i$>} for all $i$. -\begin{itemize} -\item If an exception is thrown during the call to $\tcode{T}_j$'s move construction -(with $j$ being \tcode{rhs.index()}), the \tcode{variant} will hold no value. -\item If an exception is thrown during the call to $\tcode{T}_j$'s move assignment, -the state of the contained value is as defined by the exception safety -guarantee of $\tcode{T}_j$'s move assignment; \tcode{index()} will be $j$. -\end{itemize} -\end{itemdescr} - -\indexlibrarymember{operator=}{variant}% -\begin{itemdecl} -template constexpr variant& operator=(T&& t) noexcept(@\seebelow@); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let $\tcode{T}_j$ be a type that is determined as follows: -build an imaginary function \tcode{\placeholdernc{FUN}($\tcode{T}_i$)} -for each alternative type $\tcode{T}_i$ -for which \tcode{$\tcode{T}_i$ x[] =} \tcode{\{std::forward(t)\};} -is well-formed for some invented variable \tcode{x}. -The overload \tcode{\placeholdernc{FUN}($\tcode{T}_j$)} selected by overload -resolution for the expression \tcode{\placeholdernc{FUN}(std::forward(\brk{}t))} defines -the alternative $\tcode{T}_j$ which is the type of the contained value after -assignment. - -\pnum -\constraints -\begin{itemize} -\item -\tcode{is_same_v, variant>} is \tcode{false}, - -\item -\tcode{is_assignable_v<$\tcode{T}_j$\&, T> \&\& is_constructible_v<$\tcode{T}_j$, T>} -is \tcode{true}, and - -\item -the expression \tcode{\placeholdernc{FUN}(std::forward(t))} -(with \tcode{\placeholdernc{FUN}} being the above-mentioned set -of imaginary functions) is well-formed. -\begin{note} -\begin{codeblock} -variant v; -v = "abc"; -\end{codeblock} -is ill-formed, as both alternative types have an equally viable constructor -for the argument. -\end{note} -\end{itemize} - -\pnum -\effects -\begin{itemize} -\item -If \tcode{*this} holds a $\tcode{T}_j$, assigns \tcode{std::forward(t)} to -the value contained in \tcode{*this}. -\item -Otherwise, if \tcode{is_nothrow_constructible_v<$\tcode{T}_j$, T> ||} -\tcode{!is_nothrow_move_constructible_v<$\tcode{T}_j$>} is \tcode{true}, -equivalent to \tcode{emplace<$j$>(std::forward(t))}. -\item -Otherwise, equivalent to \tcode{emplace<$j$>($\tcode{T}_j$(std::forward(t)))}. -\end{itemize} - -\pnum -\ensures -\tcode{holds_alternative<$\tcode{T}_j$>(*this)} is \tcode{true}, with $\tcode{T}_j$ -selected by the imaginary function overload resolution described above. - -\pnum -\returns -\tcode{*this}. - -\pnum -\remarks -The exception specification is equivalent to: -\begin{codeblock} -is_nothrow_assignable_v && is_nothrow_constructible_v -\end{codeblock} -\begin{itemize} -\item If an exception is thrown during the assignment of \tcode{std::forward(t)} -to the value contained in \tcode{*this}, the state of the contained value and -\tcode{t} are as defined by the exception safety guarantee of the assignment -expression; \tcode{valueless_by_exception()} will be \tcode{false}. -\item If an exception is thrown during the initialization of the contained value, -the \tcode{variant} object is permitted to not hold a value. -\end{itemize} -\end{itemdescr} - -\rSec3[variant.mod]{Modifiers} - -\indexlibrarymember{emplace}{variant}% -\begin{itemdecl} -template constexpr T& emplace(Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}, and -\tcode{T} occurs exactly once in \tcode{Types}. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -return emplace<@$I$@>(std::forward(args)...); -\end{codeblock} -where $I$ is the zero-based index of \tcode{T} in \tcode{Types}. -\end{itemdescr} - -\indexlibrarymember{emplace}{variant}% -\begin{itemdecl} -template - constexpr T& emplace(initializer_list il, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v\&, Args...>} is \tcode{true}, -and \tcode{T} occurs exactly once in \tcode{Types}. - -\pnum -\effects -Equivalent to: -\begin{codeblock} -return emplace<@$I$@>(il, std::forward(args)...); -\end{codeblock} -where $I$ is the zero-based index of \tcode{T} in \tcode{Types}. -\end{itemdescr} - -\indexlibrarymember{emplace}{variant}% -\begin{itemdecl} -template - constexpr variant_alternative_t>& emplace(Args&&... args); -\end{itemdecl} - -\begin{itemdescr} % NOCHECK: order -\pnum -\mandates -$\tcode{I} < \tcode{sizeof...(Types)}$. - -\pnum -\constraints -\tcode{is_constructible_v<$\tcode{T}_I$, Args...>} is \tcode{true}. - -\pnum -\effects -Destroys the currently contained value if \tcode{valueless_by_exception()} -is \tcode{false}. -Then direct-non-list-initializes the contained value of type $\tcode{T}_I$ -with the arguments \tcode{std::forward(args)...}. - -\pnum -\ensures -\tcode{index()} is \tcode{I}. - -\pnum -\returns -A reference to the new contained value. - -\pnum -\throws -Any exception thrown during the initialization of the contained value. - -\pnum -\remarks -If an exception is thrown during the initialization of the contained value, -the \tcode{variant} is permitted to not hold a value. -\end{itemdescr} - -\indexlibrarymember{emplace}{variant}% -\begin{itemdecl} -template - constexpr variant_alternative_t>& - emplace(initializer_list il, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} % NOCHECK: order -\pnum -\mandates -$\tcode{I} < \tcode{sizeof...(Types)}$. - -\pnum -\constraints -\tcode{is_constructible_v<$\tcode{T}_I$, initializer_list\&, Args...>} is \tcode{true}. - -\pnum -\effects -Destroys the currently contained value if \tcode{valueless_by_exception()} -is \tcode{false}. -Then direct-non-list-initializes the contained value of type $\tcode{T}_I$ -with \tcode{il, std::forward(args)...}. - -\pnum -\ensures -\tcode{index()} is \tcode{I}. - -\pnum -\returns -A reference to the new contained value. - -\pnum -\throws -Any exception thrown during the initialization of the contained value. - -\pnum -\remarks -If an exception is thrown during the initialization of the contained value, -the \tcode{variant} is permitted to not hold a value. -\end{itemdescr} - -\rSec3[variant.status]{Value status} - -\indexlibrarymember{valueless_by_exception}{variant}% -\begin{itemdecl} -constexpr bool valueless_by_exception() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Returns \tcode{false} if and only if the \tcode{variant} holds a value. - -\pnum -\begin{note} -It is possible for a \tcode{variant} to hold no value -if an exception is thrown during a -type-changing assignment or emplacement. The latter means that even a -\tcode{variant} can become \tcode{valueless_by_exception()}, for -instance by -\begin{codeblock} -struct S { operator int() { throw 42; }}; -variant v{12.f}; -v.emplace<1>(S()); -\end{codeblock} -\end{note} -\end{itemdescr} - -\indexlibrarymember{index}{variant}% -\begin{itemdecl} -constexpr size_t index() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If \tcode{valueless_by_exception()} is \tcode{true}, returns \tcode{variant_npos}. -Otherwise, returns the zero-based index of the alternative of the contained value. -\end{itemdescr} - -\rSec3[variant.swap]{Swap} - -\indexlibrarymember{swap}{variant}% -\begin{itemdecl} -constexpr void swap(variant& rhs) noexcept(@\seebelow@); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{is_move_constructible_v<$\tcode{T}_i$>} is \tcode{true} for all $i$. - -\pnum -\expects -Each $\tcode{T}_i$ meets the \oldconcept{Swappable} requirements\iref{swappable.requirements}. - -\pnum -\effects -\begin{itemize} -\item -If \tcode{valueless_by_exception() \&\& rhs.valueless_by_exception()} no effect. -\item -Otherwise, if \tcode{index() == rhs.index()}, calls \tcode{swap(\exposid{GET}<$i$>(*this), \exposid{GET}<$i$>(rhs))} where $i$ is \tcode{index()}. -\item -Otherwise, exchanges values of \tcode{rhs} and \tcode{*this}. -\end{itemize} - -\pnum -\throws -If \tcode{index() == rhs.index()}, -any exception thrown by \tcode{swap(\exposid{GET}<$i$>(*this), \exposid{GET}<$i$>(rhs))} -with $i$ being \tcode{index()}. -Otherwise, any exception thrown by the move constructor -of $\tcode{T}_i$ or $\tcode{T}_j$ -with $i$ being \tcode{index()} and $j$ being \tcode{rhs.index()}. - -\pnum -\remarks -If an exception is thrown during the call to function \tcode{swap(\exposid{GET}<$i$>(*this), \exposid{GET}<$i$>(rhs))}, -the states of the contained values of \tcode{*this} and of \tcode{rhs} are -determined by the exception safety guarantee of \tcode{swap} for lvalues of -$\tcode{T}_i$ with $i$ being \tcode{index()}. -If an exception is thrown during the exchange of the values of \tcode{*this} -and \tcode{rhs}, the states of the values of \tcode{*this} and of \tcode{rhs} -are determined by the exception safety guarantee of \tcode{variant}'s move constructor. -The exception specification is equivalent to the logical \logop{and} of -\tcode{is_nothrow_move_constructible_v<$\tcode{T}_i$> \&\& is_nothrow_swappable_v<$\tcode{T}_i$>} for all $i$. -\end{itemdescr} - -\rSec2[variant.helper]{\tcode{variant} helper classes} - -\indexlibraryglobal{variant_size}% -\begin{itemdecl} -template struct variant_size; -\end{itemdecl} - -\begin{itemdescr} -\pnum -All specializations of \tcode{variant_size} meet the -\oldconcept{UnaryTypeTrait} requirements\iref{meta.rqmts} -with a base characteristic of \tcode{integral_constant} for some \tcode{N}. -\end{itemdescr} - -\indexlibraryglobal{variant_size}% -\begin{itemdecl} -template struct variant_size; -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VS} denote \tcode{variant_size} of the cv-unqualified -type \tcode{T}. Then each specialization of the template meets the -\oldconcept{UnaryTypeTrait} requirements\iref{meta.rqmts} with a -base characteristic of \tcode{integral_constant}. -\end{itemdescr} - -\indexlibraryglobal{variant_size}% -\begin{itemdecl} -template - struct variant_size> : integral_constant { }; -\end{itemdecl} -% No itemdescr needed for variant_size> - -\indexlibraryglobal{variant_alternative}% -\begin{itemdecl} -template struct variant_alternative; -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VA} denote \tcode{variant_alternative} of the -cv-unqualified type \tcode{T}. Then each specialization of the template -meets the \oldconcept{TransformationTrait} requirements\iref{meta.rqmts} with a -member typedef \tcode{type} that names the type \tcode{add_const_t}. -\end{itemdescr} - -\indexlibraryglobal{variant_alternative}% -\begin{itemdecl} -variant_alternative>::type -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -$\tcode{I} < \tcode{sizeof...(Types)}$. - -\pnum -\ctype -The type $\tcode{T}_I$. -\end{itemdescr} - -\rSec2[variant.get]{Value access} - -\indexlibraryglobal{holds_alternative} -\indexlibrarymember{variant}{holds_alternative} -\begin{itemdecl} -template - constexpr bool holds_alternative(const variant& v) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -The type \tcode{T} occurs exactly once in \tcode{Types}. - -\pnum -\returns -\tcode{true} if \tcode{index()} is equal to the zero-based index of \tcode{T} in \tcode{Types}. -\end{itemdescr} - -\begin{itemdecl} -template - constexpr variant_alternative_t>& - @\exposid{GET}@(variant& v); // \expos -template - constexpr variant_alternative_t>&& - @\exposid{GET}@(variant&& v); // \expos -template - constexpr const variant_alternative_t>& - @\exposid{GET}@(const variant& v); // \expos -template - constexpr const variant_alternative_t>&& - @\exposid{GET}@(const variant&& v); // \expos -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -$\tcode{I} < \tcode{sizeof...(Types)}$. - -\pnum -\expects -\tcode{v.index()} is \tcode{I}. - -\pnum -\returns -A reference to the object stored in the \tcode{variant}. -\end{itemdescr} - -\indexlibrarymember{get}{variant}% -\begin{itemdecl} -template - constexpr variant_alternative_t>& get(variant& v); -template - constexpr variant_alternative_t>&& get(variant&& v); -template - constexpr const variant_alternative_t>& get(const variant& v); -template - constexpr const variant_alternative_t>&& get(const variant&& v); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -$\tcode{I} < \tcode{sizeof...(Types)}$. - -\pnum -\effects -If \tcode{v.index()} is \tcode{I}, returns a reference to the object stored in -the \tcode{variant}. Otherwise, throws an exception of type \tcode{bad_variant_access}. -\end{itemdescr} - -\indexlibrarymember{get}{variant}% -\begin{itemdecl} -template constexpr T& get(variant& v); -template constexpr T&& get(variant&& v); -template constexpr const T& get(const variant& v); -template constexpr const T&& get(const variant&& v); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -The type \tcode{T} occurs exactly once in \tcode{Types}. - -\pnum -\effects -If \tcode{v} holds a value of type \tcode{T}, returns a reference to that value. -Otherwise, throws an exception of type \tcode{bad_variant_access}. -\end{itemdescr} - -\indexlibraryglobal{get_if}% -\indexlibrarymember{variant}{get_if}% -\begin{itemdecl} -template - constexpr add_pointer_t>> - get_if(variant* v) noexcept; -template - constexpr add_pointer_t>> - get_if(const variant* v) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -$\tcode{I} < \tcode{sizeof...(Types)}$. - -\pnum -\returns -A pointer to the value stored in the \tcode{variant}, if \tcode{v != nullptr} -and \tcode{v->index() == I}. Otherwise, returns \keyword{nullptr}. -\end{itemdescr} - -\indexlibraryglobal{get_if}% -\indexlibrarymember{variant}{get_if}% -\begin{itemdecl} -template - constexpr add_pointer_t - get_if(variant* v) noexcept; -template - constexpr add_pointer_t - get_if(const variant* v) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -The type \tcode{T} occurs exactly once in \tcode{Types}. - -\pnum -\effects -Equivalent to: \tcode{return get_if<$i$>(v);} with $i$ being the zero-based -index of \tcode{T} in \tcode{Types}. -\end{itemdescr} - -\rSec2[variant.relops]{Relational operators} - -\indexlibrarymember{operator==}{variant}% -\begin{itemdecl} -template - constexpr bool operator==(const variant& v, const variant& w); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{\exposid{GET}<$i$>(v) == \exposid{GET}<$i$>(w)} is a valid expression that is -convertible to \tcode{bool}, for all $i$. - -\pnum -\returns -If \tcode{v.index() != w.index()}, \tcode{false}; -otherwise if \tcode{v.valueless_by_exception()}, \tcode{true}; -otherwise \tcode{\exposid{GET}<$i$>(v) == \exposid{GET}<$i$>(w)} with $i$ being \tcode{v.index()}. -\end{itemdescr} - -\indexlibrarymember{operator"!=}{variant}% -\begin{itemdecl} -template - constexpr bool operator!=(const variant& v, const variant& w); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{\exposid{GET}<$i$>(v) != \exposid{GET}<$i$>(w)} is a valid expression that is -convertible to \tcode{bool}, for all $i$. - -\pnum -\returns -If \tcode{v.index() != w.index()}, \tcode{true}; -otherwise if \tcode{v.valueless_by_exception()}, \tcode{false}; -otherwise \tcode{\exposid{GET}<$i$>(v) != \exposid{GET}<$i$>(w)} with $i$ being \tcode{v.index()}. -\end{itemdescr} - -\indexlibrarymember{operator<}{variant}% -\begin{itemdecl} -template - constexpr bool operator<(const variant& v, const variant& w); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{\exposid{GET}<$i$>(v) < \exposid{GET}<$i$>(w)} is a valid expression that is -convertible to \tcode{bool}, for all $i$. - -\pnum -\returns -If \tcode{w.valueless_by_exception()}, \tcode{false}; -otherwise if \tcode{v.valueless_by_exception()}, \tcode{true}; -otherwise, if \tcode{v.index() < w.index()}, \tcode{true}; -otherwise if \tcode{v.index() > w.index()}, \tcode{false}; -otherwise \tcode{\exposid{GET}<$i$>(v) < \exposid{GET}<$i$>(w)} with $i$ being \tcode{v.index()}. -\end{itemdescr} - -\indexlibrarymember{operator>}{variant}% -\begin{itemdecl} -template - constexpr bool operator>(const variant& v, const variant& w); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{\exposid{GET}<$i$>(v) > \exposid{GET}<$i$>(w)} is a valid expression that is -convertible to \tcode{bool}, for all $i$. - -\pnum -\returns -If \tcode{v.valueless_by_exception()}, \tcode{false}; -otherwise if \tcode{w.valueless_by_exception()}, \tcode{true}; -otherwise, if \tcode{v.index() > w.index()}, \tcode{true}; -otherwise if \tcode{v.index() < w.index()}, \tcode{false}; -otherwise \tcode{\exposid{GET}<$i$>(v) > \exposid{GET}<$i$>(w)} with $i$ being \tcode{v.index()}. -\end{itemdescr} - -\indexlibrarymember{operator<=}{variant}% -\begin{itemdecl} -template - constexpr bool operator<=(const variant& v, const variant& w); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{\exposid{GET}<$i$>(v) <= \exposid{GET}<$i$>(w)} is a valid expression that is -convertible to \tcode{bool}, for all $i$. - -\pnum -\returns -If \tcode{v.valueless_by_exception()}, \tcode{true}; -otherwise if \tcode{w.valueless_by_exception()}, \tcode{false}; -otherwise, if \tcode{v.index() < w.index()}, \tcode{true}; -otherwise if \tcode{v.index() > w.index()}, \tcode{false}; -otherwise \tcode{\exposid{GET}<$i$>(v) <= \exposid{GET}<$i$>(w)} with $i$ being \tcode{v.index()}. -\end{itemdescr} - -\indexlibrarymember{operator>=}{variant}% -\begin{itemdecl} -template - constexpr bool operator>=(const variant& v, const variant& w); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{\exposid{GET}<$i$>(v) >= \exposid{GET}<$i$>(w)} is a valid expression that is -convertible to \tcode{bool}, for all $i$. - -\pnum -\returns -If \tcode{w.valueless_by_exception()}, \tcode{true}; -otherwise if \tcode{v.valueless_by_exception()}, \tcode{false}; -otherwise, if \tcode{v.index() > w.index()}, \tcode{true}; -otherwise if \tcode{v.index() < w.index()}, \tcode{false}; -otherwise \tcode{\exposid{GET}<$i$>(v) >= \exposid{GET}<$i$>(w)} with $i$ being \tcode{v.index()}. -\end{itemdescr} - -\indexlibrarymember{operator<=>}{variant}% -\begin{itemdecl} -template requires (@\libconcept{three_way_comparable}@ && ...) - constexpr common_comparison_category_t...> - operator<=>(const variant& v, const variant& w); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: -\begin{codeblock} -if (v.valueless_by_exception() && w.valueless_by_exception()) - return strong_ordering::equal; -if (v.valueless_by_exception()) return strong_ordering::less; -if (w.valueless_by_exception()) return strong_ordering::greater; -if (auto c = v.index() <=> w.index(); c != 0) return c; -return @\exposid{GET}@<@$i$@>(v) <=> @\exposid{GET}@<@$i$@>(w); -\end{codeblock} -with $i$ being \tcode{v.index()}. -\end{itemdescr} - -\rSec2[variant.visit]{Visitation} - -\indexlibraryglobal{visit}% -\indexlibrarymember{variant}{visit}% -\begin{itemdecl} -template - constexpr @\seebelow@ visit(Visitor&& vis, Variants&&... vars); -template - constexpr R visit(Visitor&& vis, Variants&&... vars); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \exposid{as-variant} denote the following exposition-only function templates: -\begin{codeblock} -template - auto&& @\exposid{as-variant}@(variant& var) { return var; } -template - auto&& @\exposid{as-variant}@(const variant& var) { return var; } -template - auto&& @\exposid{as-variant}@(variant&& var) { return std::move(var); } -template - auto&& @\exposid{as-variant}@(const variant&& var) { return std::move(var); } -\end{codeblock} -Let $n$ be \tcode{sizeof...(Variants)}. -For each $0 \leq i < n$, let -$\tcode{V}_i$ denote the type\newline -\tcode{decltype(\exposid{as-variant}(\tcode{std::forward<$\tcode{Variants}_i$>($\tcode{vars}_i$)}))}. - -\pnum -\constraints -$\tcode{V}_i$ is a valid type for all $0 \leq i < n$. - -\pnum -Let \tcode{V} denote the pack of types $\tcode{V}_i$. - -\pnum -Let $m$ be a pack of $n$ values of type \tcode{size_t}. -Such a pack is valid if\newline -$0 \leq m_i < \tcode{variant_size_v>}$ -for all $0 \leq i < n$. -For each valid pack $m$, let $e(m)$ denote the expression: -\begin{codeblock} -@\placeholder{INVOKE}@(std::forward(vis), @\exposid{GET}@<@$m$@>(std::forward(vars))...) // see \ref{func.require} -\end{codeblock} -for the first form and -\begin{codeblock} -@\placeholder{INVOKE}@(std::forward(vis), @\exposid{GET}@<@$m$@>(std::forward(vars))...) // see \ref{func.require} -\end{codeblock} -for the second form. - -\pnum -\mandates -For each valid pack $m$, $e(m)$ is a valid expression. -All such expressions are of the same type and value category. - -\pnum -\returns -$e(m)$, where $m$ is the pack for which -$m_i$ is \tcode{\exposid{as-variant}(vars$_i$).index()} for all $0 \leq i < n$. -The return type is $\tcode{decltype(}e(m)\tcode{)}$ -for the first form. - -\pnum -\throws -\tcode{bad_variant_access} if -\tcode{(\exposid{as-variant}(vars).valueless_by_exception() || ...)} -is \tcode{true}. - -\pnum -\complexity -For $n \leq 1$, the invocation of the callable object is -implemented in constant time, i.e., for $n = 1$, it does not depend on -the number of alternative types of $\tcode{V}_0$. -For $n > 1$, the invocation of the callable object has -no complexity requirements. -\end{itemdescr} - -\indexlibrarymember{visit}{variant}% -\begin{itemdecl} -template - constexpr decltype(auto) visit(this Self&& self, Visitor&& vis); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{V} be -\tcode{\exposid{OVERRIDE_REF}(Self\&\&, \exposid{COPY_CONST}(remove_reference_t, variant))}\iref{forward}. - -\pnum -\constraints -The call to \tcode{visit} does not use -an explicit \grammarterm{template-argument-list} that -begins with a type \grammarterm{template-argument}. - -\pnum -\effects -Equivalent to: \tcode{return std::visit(std::forward(vis), (V)self);} -\end{itemdescr} - -\indexlibrarymember{visit}{variant}% -\begin{itemdecl} -template - constexpr R visit(this Self&& self, Visitor&& vis); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{V} be -\tcode{\exposid{OVERRIDE_REF}(Self\&\&, \exposid{COPY_CONST}(remove_reference_t, variant))}\iref{forward}. - -\pnum -\effects -Equivalent to: \tcode{return std::visit(std::forward(vis), (V)self);} -\end{itemdescr} - -\rSec2[variant.monostate]{Class \tcode{monostate}}% -\indexlibraryglobal{monostate}% - -\begin{itemdecl} -struct monostate{}; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The class \tcode{monostate} can serve as a first alternative type for -a \tcode{variant} to make the \tcode{variant} type default constructible. -\end{itemdescr} - - -\rSec2[variant.monostate.relops]{\tcode{monostate} relational operators} - -\indexlibrarymember{operator==}{monostate}% -\indexlibrarymember{operator<=>}{monostate}% -\begin{itemdecl} -constexpr bool operator==(monostate, monostate) noexcept { return true; } -constexpr strong_ordering operator<=>(monostate, monostate) noexcept -{ return strong_ordering::equal; } -\end{itemdecl} - -\begin{itemdescr} -\pnum -\begin{note} -\tcode{monostate} objects have only a single state; they thus always compare equal. -\end{note} -\end{itemdescr} - -\rSec2[variant.specalg]{Specialized algorithms} - -\indexlibrarymember{swap}{variant}% -\begin{itemdecl} -template - constexpr void swap(variant& v, variant& w) noexcept(@\seebelow@); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{is_move_constructible_v<$\tcode{T}_i$> \&\& is_swappable_v<$\tcode{T}_i$>} -is \tcode{true} for all $i$. - -\pnum -\effects -Equivalent to \tcode{v.swap(w)}. - -\pnum -\remarks -The exception specification is equivalent to \tcode{noexcept(v.swap(w))}. -\end{itemdescr} - -\rSec2[variant.bad.access]{Class \tcode{bad_variant_access}}% -\indexlibraryglobal{bad_variant_access}% - -\begin{codeblock} -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 -Objects of type \tcode{bad_variant_access} are thrown to report invalid -accesses to the value of a \tcode{variant} object. - -\indexlibrarymember{what}{bad_variant_access}% -\begin{itemdecl} -const char* what() const noexcept override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -An \impldef{return value of \tcode{bad_variant_access::what}} \ntbs{}. -\end{itemdescr} - -\rSec2[variant.hash]{Hash support} - -\indexlibrarymember{hash}{variant}% -\begin{itemdecl} -template struct hash>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The specialization \tcode{hash>} is enabled\iref{unord.hash} -if and only if every specialization in \tcode{hash>...} is enabled. -The member functions are not guaranteed to be \keyword{noexcept}. -\end{itemdescr} - -\indexlibrarymember{hash}{monostate}% -\begin{itemdecl} -template<> struct hash; -\end{itemdecl} - -\begin{itemdescr} -\pnum -The specialization is enabled\iref{unord.hash}. -\end{itemdescr} - - -\rSec1[any]{Storage for any type} - -\rSec2[any.general]{General} - -\pnum -Subclause \ref{any} describes components that \Cpp{} programs may use to perform operations on objects of a discriminated type. - -\pnum -\begin{note} -The discriminated type can contain values of different types but does not attempt conversion between them, -i.e., \tcode{5} is held strictly as an \tcode{int} and is not implicitly convertible either to \tcode{"5"} or to \tcode{5.0}. -This indifference to interpretation but awareness of type effectively allows safe, generic containers of single values, with no scope for surprises from ambiguous conversions. -\end{note} - -\rSec2[any.synop]{Header \tcode{} synopsis} - -\indexheader{any}% - -\begin{codeblock} -namespace std { - // \ref{any.bad.any.cast}, class \tcode{bad_any_cast} - class bad_any_cast; - - // \ref{any.class}, class \tcode{any} - class any; - - // \ref{any.nonmembers}, non-member functions - void swap(any& x, any& y) noexcept; - - template - any make_any(Args&&... args); - template - any make_any(initializer_list il, Args&&... args); - - template - T any_cast(const any& operand); - template - T any_cast(any& operand); - template - T any_cast(any&& operand); - - template - const T* any_cast(const any* operand) noexcept; - template - T* any_cast(any* operand) noexcept; -} -\end{codeblock} - -\rSec2[any.bad.any.cast]{Class \tcode{bad_any_cast}} - -\indexlibraryglobal{bad_any_cast}% -\begin{codeblock} -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 -Objects of type \tcode{bad_any_cast} are thrown by a failed \tcode{any_cast}\iref{any.nonmembers}. - -\indexlibrarymember{what}{bad_any_cast}% -\begin{itemdecl} -const char* what() const noexcept override; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -An \impldef{return value of \tcode{bad_any_cast::what}} \ntbs{}. -\end{itemdescr} - -\rSec2[any.class]{Class \tcode{any}} - -\rSec3[any.class.general]{General} - -\begin{codeblock} -namespace std { - class any { - public: - // \ref{any.cons}, construction and destruction - constexpr any() noexcept; - - any(const any& other); - any(any&& other) noexcept; - - template - any(T&& value); - - template - explicit any(in_place_type_t, Args&&...); - template - explicit any(in_place_type_t, initializer_list, Args&&...); - - ~any(); - - // \ref{any.assign}, assignments - any& operator=(const any& rhs); - any& operator=(any&& rhs) noexcept; - - template - any& operator=(T&& rhs); - - // \ref{any.modifiers}, modifiers - template - decay_t& emplace(Args&&...); - template - decay_t& emplace(initializer_list, Args&&...); - void reset() noexcept; - void swap(any& rhs) noexcept; - - // \ref{any.observers}, observers - bool has_value() const noexcept; - const type_info& type() const noexcept; - }; -} -\end{codeblock} - -\pnum -An object of class \tcode{any} stores an instance of any type that meets the constructor requirements or it has no value, -and this is referred to as the \defn{state} of the class \tcode{any} object. -The stored instance is called the \defnx{contained value}{contained value!\idxcode{any}}. -Two states are equivalent if either they both have no value, or they both have a value and the contained values are equivalent. - -\pnum -The non-member \tcode{any_cast} functions provide type-safe access to the contained value. - -\pnum -Implementations should avoid the use of dynamically allocated memory for a small contained value. -However, any such small-object optimization shall only be applied to types \tcode{T} for which -\tcode{is_nothrow_move_constructible_v} is \tcode{true}. -\begin{example} -A contained value of type \tcode{int} could be stored in an internal buffer, -not in separately-allocated memory. -\end{example} - -\rSec3[any.cons]{Construction and destruction} - -\indexlibraryctor{any}% -\begin{itemdecl} -constexpr any() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{has_value()} is \tcode{false}. -\end{itemdescr} - -\indexlibraryctor{any}% -\begin{itemdecl} -any(const any& other); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If \tcode{other.has_value()} is \tcode{false}, constructs an object that has no value. -Otherwise, equivalent to \tcode{any(in_place_type, any_cast(other))} -where \tcode{T} is the type of the contained value. - -\pnum -\throws -Any exceptions arising from calling the selected constructor for the contained value. -\end{itemdescr} - -\indexlibraryctor{any}% -\begin{itemdecl} -any(any&& other) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If \tcode{other.has_value()} is \tcode{false}, constructs an object that has no value. -Otherwise, constructs an object of type \tcode{any} that -contains either the contained value of \tcode{other}, or -contains an object of the same type constructed from -the contained value of \tcode{other} considering that contained value as an rvalue. -\end{itemdescr} - -\indexlibraryctor{any}% -\begin{itemdecl} -template - any(T&& value); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VT} be \tcode{decay_t}. - -\pnum -\constraints -\tcode{VT} is not the same type as \tcode{any}, -\tcode{VT} is not a specialization of \tcode{in_place_type_t}, -and \tcode{is_copy_constructible_v} is \tcode{true}. - -\pnum -\expects -\tcode{VT} meets the \oldconcept{CopyConstructible} requirements. - -\pnum -\effects -Constructs an object of type \tcode{any} that contains an object of type \tcode{VT} direct-initialized with \tcode{std::forward(value)}. - -\pnum -\throws -Any exception thrown by the selected constructor of \tcode{VT}. -\end{itemdescr} - -\indexlibraryctor{any}% -\begin{itemdecl} -template - explicit any(in_place_type_t, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VT} be \tcode{decay_t}. - -\pnum -\constraints -\tcode{is_copy_constructible_v} is \tcode{true} and -\tcode{is_constructible_v} is \tcode{true}. - -\pnum -\expects -\tcode{VT} meets the \oldconcept{CopyConstructible} requirements. - -\pnum -\effects -Direct-non-list-initializes the contained value of type \tcode{VT} -with \tcode{std::forward(args)...}. - -\pnum -\ensures -\tcode{*this} contains a value of type \tcode{VT}. - -\pnum -\throws -Any exception thrown by the selected constructor of \tcode{VT}. -\end{itemdescr} - -\indexlibraryctor{any}% -\begin{itemdecl} -template - explicit any(in_place_type_t, initializer_list il, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VT} be \tcode{decay_t}. - -\pnum -\constraints -\tcode{is_copy_constructible_v} is \tcode{true} and -\tcode{is_constructible_v\&, Args...>} is \tcode{true}. - -\pnum -\expects -\tcode{VT} meets the \oldconcept{CopyConstructible} requirements. - -\pnum -\effects -Direct-non-list-initializes the contained value of type \tcode{VT} -with \tcode{il, std::forward(\brk{}args)...}. - -\pnum -\ensures -\tcode{*this} contains a value. - -\pnum -\throws -Any exception thrown by the selected constructor of \tcode{VT}. -\end{itemdescr} - -\indexlibrarydtor{any} -\begin{itemdecl} -~any(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by \tcode{reset()}. -\end{itemdescr} - -\rSec3[any.assign]{Assignment} - -\indexlibrarymember{operator=}{any}% -\begin{itemdecl} -any& operator=(const any& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by \tcode{any(rhs).swap(*this)}. -No effects if an exception is thrown. - -\pnum -\returns -\tcode{*this}. - -\pnum -\throws -Any exceptions arising from the copy constructor for the contained value. -\end{itemdescr} - -\indexlibrarymember{operator=}{any}% -\begin{itemdecl} -any& operator=(any&& rhs) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -As if by \tcode{any(std::move(rhs)).swap(*this)}. - -\pnum -\ensures -The state of \tcode{*this} is equivalent to the original state of \tcode{rhs}. - -\pnum -\returns -\tcode{*this}. -\end{itemdescr} - -\indexlibrarymember{operator=}{any}% -\begin{itemdecl} -template - any& operator=(T&& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VT} be \tcode{decay_t}. - -\pnum -\constraints -\tcode{VT} is not the same type as \tcode{any} and -\tcode{is_copy_constructible_v} is \tcode{true}. - -\pnum -\expects -\tcode{VT} meets the \oldconcept{CopyConstructible} requirements. - -\pnum -\effects -Constructs an object \tcode{tmp} of type \tcode{any} that contains an object of type \tcode{VT} direct-initialized with \tcode{std::forward(rhs)}, and \tcode{tmp.swap(*this)}. -No effects if an exception is thrown. - -\pnum -\returns -\tcode{*this}. - -\pnum -\throws -Any exception thrown by the selected constructor of \tcode{VT}. -\end{itemdescr} - -\rSec3[any.modifiers]{Modifiers} - -\indexlibrarymember{emplace}{any}% -\begin{itemdecl} -template - decay_t& emplace(Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VT} be \tcode{decay_t}. - -\pnum -\constraints -\tcode{is_copy_constructible_v} is \tcode{true} and -\tcode{is_constructible_v} is \tcode{true}. - -\pnum -\expects -\tcode{VT} meets the \oldconcept{CopyConstructible} requirements. - -\pnum -\effects -Calls \tcode{reset()}. -Then direct-non-list-initializes the contained value of type \tcode{VT} -with \tcode{std::for\-ward(args)...}. - -\pnum -\ensures -\tcode{*this} contains a value. - -\pnum -\returns -A reference to the new contained value. - -\pnum -\throws -Any exception thrown by the selected constructor of \tcode{VT}. - -\pnum -\remarks -If an exception is thrown during the call to \tcode{VT}'s constructor, -\tcode{*this} does not contain a value, and any previously contained value -has been destroyed. -\end{itemdescr} - -\indexlibrarymember{emplace}{any}% -\begin{itemdecl} -template - decay_t& emplace(initializer_list il, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{VT} be \tcode{decay_t}. - -\pnum -\constraints -\tcode{is_copy_constructible_v} is \tcode{true} and -\tcode{is_constructible_v\&, Args...>} is \tcode{true}. - -\pnum -\expects -\tcode{VT} meets the \oldconcept{CopyConstructible} requirements. - -\pnum -\effects -Calls \tcode{reset()}. Then direct-non-list-initializes the contained value -of type \tcode{VT} with \tcode{il, std::forward(args)...}. - -\pnum -\ensures -\tcode{*this} contains a value. - -\pnum -\returns -A reference to the new contained value. - -\pnum -\throws -Any exception thrown by the selected constructor of \tcode{VT}. - -\pnum -\remarks -If an exception is thrown during the call to \tcode{VT}'s constructor, -\tcode{*this} does not contain a value, and any previously contained value -has been destroyed. -\end{itemdescr} - -\indexlibrarymember{reset}{any}% -\begin{itemdecl} -void reset() noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -If \tcode{has_value()} is \tcode{true}, destroys the contained value. - -\pnum -\ensures -\tcode{has_value()} is \tcode{false}. -\end{itemdescr} - -\indexlibrarymember{swap}{any}% -\begin{itemdecl} -void swap(any& rhs) noexcept; -\end{itemdecl} - -\begin{itemdescr} - -\pnum -\effects -Exchanges the states of \tcode{*this} and \tcode{rhs}. -\end{itemdescr} - -\rSec3[any.observers]{Observers} - -\indexlibrarymember{has_value}{any}% -\begin{itemdecl} -bool has_value() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if \tcode{*this} contains an object, otherwise \tcode{false}. -\end{itemdescr} - -\indexlibrarymember{type}{any}% -\begin{itemdecl} -const type_info& type() const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{typeid(T)} if \tcode{*this} has a contained value of type \tcode{T}, -otherwise \tcode{typeid(void)}. - -\pnum -\begin{note} -Useful for querying against types known either at compile time or only at runtime. -\end{note} -\end{itemdescr} - -\rSec2[any.nonmembers]{Non-member functions} - -\indexlibrarymember{swap}{any}% -\begin{itemdecl} -void swap(any& x, any& y) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{x.swap(y)}. -\end{itemdescr} - -\indexlibraryglobal{make_any}% -\begin{itemdecl} -template - any make_any(Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return any(in_place_type, std::forward(args)...);} -\end{itemdescr} - -\indexlibraryglobal{make_any}% -\begin{itemdecl} -template - any make_any(initializer_list il, Args&&... args); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{return any(in_place_type, il, std::forward(args)...);} -\end{itemdescr} - -\indexlibraryglobal{any_cast}% -\begin{itemdecl} -template - T any_cast(const any& operand); -template - T any_cast(any& operand); -template - T any_cast(any&& operand); -\end{itemdecl} - -\begin{itemdescr} -\pnum -Let \tcode{U} be the type \tcode{remove_cvref_t}. - -\pnum -\mandates -For the first overload, \tcode{is_constructible_v} is \tcode{true}. -For the second overload, \tcode{is_constructible_v} is \tcode{true}. -For the third overload, \tcode{is_constructible_v} is \tcode{true}. - -\pnum -\returns -For the first and second overload, \tcode{static_cast(*any_cast(\&operand))}. -For the third overload, \tcode{static_cast(std::move(*any_cast(\&operand)))}. - -\pnum -\throws -\tcode{bad_any_cast} if \tcode{operand.type() != typeid(remove_reference_t)}. - -\pnum -\begin{example} -\begin{codeblock} -any x(5); // \tcode{x} holds \tcode{int} -assert(any_cast(x) == 5); // cast to value -any_cast(x) = 10; // cast to reference -assert(any_cast(x) == 10); - -x = "Meow"; // \tcode{x} holds \tcode{const char*} -assert(strcmp(any_cast(x), "Meow") == 0); -any_cast(x) = "Harry"; -assert(strcmp(any_cast(x), "Harry") == 0); - -x = string("Meow"); // \tcode{x} holds \tcode{string} -string s, s2("Jane"); -s = move(any_cast(x)); // move from \tcode{any} -assert(s == "Meow"); -any_cast(x) = move(s2); // move to \tcode{any} -assert(any_cast(x) == "Jane"); - -string cat("Meow"); -const any y(cat); // \tcode{const y} holds \tcode{string} -assert(any_cast(y) == cat); - -any_cast(y); // error: cannot \tcode{any_cast} away const -\end{codeblock} -\end{example} -\end{itemdescr} - -\indexlibraryglobal{any_cast}% -\begin{itemdecl} -template - const T* any_cast(const any* operand) noexcept; -template - T* any_cast(any* operand) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\mandates -\tcode{is_void_v} is \tcode{false}. - -\pnum -\returns -If \tcode{operand != nullptr \&\& operand->type() == typeid(T)} is \tcode{true}, -a pointer to the object contained by \tcode{operand}; -otherwise, \keyword{nullptr}. - -\pnum -\begin{example} -\begin{codeblock} -bool is_string(const any& operand) { - return any_cast(&operand) != nullptr; -} -\end{codeblock} -\end{example} -\end{itemdescr} - -\rSec1[expected]{Expected objects} -\indexlibraryglobal{expected}% - -\rSec2[expected.general]{In general} - -\pnum -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{E} and -manages the lifetime of the contained objects. - -\rSec2[expected.syn]{Header \tcode{} synopsis} - -\indexheader{expected}% -\indexlibraryglobal{unexpect_t}% -\indexlibraryglobal{unexpect}% -\begin{codeblock} -// mostly freestanding -namespace std { - // \ref{expected.unexpected}, class template \tcode{unexpected} - template class unexpected; - - // \ref{expected.bad}, class template \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; // partially freestanding - - // \ref{expected.void}, partial specialization of \tcode{expected} for \tcode{void} types - template requires is_void_v class expected; // partially freestanding -} -\end{codeblock} - -\rSec2[expected.unexpected]{Class template \tcode{unexpected}} - -\rSec3[expected.un.general]{General} - -\pnum -Subclause \ref{expected.unexpected} describes the class template \tcode{unexpected} -that represents unexpected objects stored in \tcode{expected} objects. - -\indexlibraryglobal{unexpected}% -\begin{codeblock} -namespace std { - template - class unexpected { - public: - // \ref{expected.un.cons}, constructors - constexpr unexpected(const unexpected&) = default; - constexpr unexpected(unexpected&&) = default; - template - constexpr explicit unexpected(Err&&); - template - constexpr explicit unexpected(in_place_t, Args&&...); - template - constexpr explicit unexpected(in_place_t, initializer_list, Args&&...); - - constexpr unexpected& operator=(const unexpected&) = default; - constexpr unexpected& operator=(unexpected&&) = default; - - constexpr const E& error() const & noexcept; - constexpr E& error() & noexcept; - constexpr const E&& error() const && noexcept; - constexpr E&& error() && 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 @\exposidnc{unex}@; // \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. - -\rSec3[expected.un.cons]{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{unex} with \tcode{std::forward(e)}. - -\pnum -\throws -Any exception thrown by the initialization of \exposid{unex}. -\end{itemdescr} - -\indexlibraryctor{unexpected}% -\begin{itemdecl} -template - constexpr explicit unexpected(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{unex} with \tcode{std::forward(args)...}. - -\pnum -\throws -Any exception thrown by the initialization of \exposid{unex}. -\end{itemdescr} - -\indexlibraryctor{unexpected}% -\begin{itemdecl} -template - constexpr explicit unexpected(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{unex} with \tcode{il, std::forward(args)...}. - -\pnum -\throws -Any exception thrown by the initialization of \exposid{unex}. -\end{itemdescr} - -\rSec3[expected.un.obs]{Observers} - -\indexlibrarymember{error}{unexpected}% -\begin{itemdecl} -constexpr const E& error() const & noexcept; -constexpr E& error() & noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\exposid{unex}. -\end{itemdescr} - -\indexlibrarymember{error}{unexpected}% -\begin{itemdecl} -constexpr E&& error() && noexcept; -constexpr const E&& error() const && noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{std::move(\exposid{unex})}. -\end{itemdescr} - -\rSec3[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{unex}, other.\exposid{unex});} -\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} - -\rSec3[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.error() == y.error()} is well-formed and -its result is convertible to \tcode{bool}. - -\pnum -\returns -\tcode{x.error() == y.error()}. -\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 @\exposidnc{unex}@; // \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{unex} 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{unex}. -\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{unex})}. -\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.cons}, constructors - constexpr expected(); - constexpr expected(const expected&); - constexpr 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 explicit(@\seebelow@) expected(const unexpected&); - template - constexpr explicit(@\seebelow@) 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& x, expected& y) noexcept(noexcept(x.swap(y))); - - // \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 &; // freestanding-deleted - constexpr T& value() &; // freestanding-deleted - constexpr const T&& value() const &&; // freestanding-deleted - constexpr T&& value() &&; // freestanding-deleted - constexpr const E& error() const & noexcept; - constexpr E& error() & noexcept; - constexpr const E&& error() const && noexcept; - constexpr E&& error() && noexcept; - template constexpr T value_or(U&&) const &; - template constexpr T value_or(U&&) &&; - template constexpr E error_or(G&&) const &; - template constexpr E error_or(G&&) &&; - - // \ref{expected.object.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 or_else(F&& f) &; - template constexpr auto or_else(F&& f) &&; - template constexpr auto or_else(F&& f) const &; - template constexpr auto or_else(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_error(F&& f) &; - template constexpr auto transform_error(F&& f) &&; - template constexpr auto transform_error(F&& f) const &; - template constexpr auto transform_error(F&& f) const &&; - - // \ref{expected.object.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 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 \tcode{E}. -Member \exposid{has_val} indicates whether the \tcode{expected} object -contains an object of type \tcode{T}. - -\pnum -A type \tcode{T} is a \term{valid value type for \tcode{expected}}, -if \tcode{remove_cv_t} is \tcode{void} -or a complete non-array object type that is not \tcode{in_place_t}, -\tcode{unexpect_t}, -or a specialization of \tcode{unexpected}. -A program which instantiates class template \tcode{expected} -with an argument \tcode{T} that is not a valid value -type for \tcode{expected} 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.cons]{Constructors} - -\pnum -The exposition-only variable template \exposid{converts-from-any-cvref} -defined in \ref{optional.ctor} -is used by some constructors for \tcode{expected}. - -\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 equivalent to -\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 -if \tcode{T} is not \cv{} \tcode{bool}, -\tcode{\exposid{converts-from-any-cvref}>} 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>} 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 -if \tcode{T} is \cv{} \tcode{bool}, -\tcode{remove_cvref_t} is not a specialization of \tcode{expected}. -\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 template: -\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 -\returns -\tcode{*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 -\returns -\tcode{*this}. - -\pnum -\remarks -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 -\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.error())); -@\exposid{has_val}@ = false; -\end{codeblock} -\item -Otherwise, equivalent to: -\tcode{\exposid{unex} = std::forward(e.error());} -\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} +// mostly freestanding +#include // see \ref{compare.syn} -\pnum -\effects -See \tref{expected.object.swap}. +namespace std { + // \ref{variant.variant}, class template \tcode{variant} + template + class variant; -\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{!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)} \\ -\lhdr{\tcode{!rhs.has_value()}} & - \seebelow & - equivalent to: \tcode{using std::swap; swap(\exposid{unex}, rhs.\exposid{unex});} \\ -\end{floattable} + // \ref{variant.helper}, variant helper classes + template struct variant_size; // \notdef + template struct variant_size; + template + constexpr size_t @\libglobal{variant_size_v}@ = variant_size::value; -For the case where \tcode{rhs.has_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} + template + struct variant_size>; -\pnum -\throws -Any exception thrown by the expressions in the \Fundescx{Effects}. + template struct variant_alternative; // \notdef + template struct variant_alternative; + template + using @\libglobal{variant_alternative_t}@ = typename variant_alternative::type; -\pnum -\remarks -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 -\end{codeblock} -\end{itemdescr} + template + struct variant_alternative>; -\indexlibrarymember{swap}{expected}% -\begin{itemdecl} -friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); -\end{itemdecl} + inline constexpr size_t variant_npos = -1; -\begin{itemdescr} -\pnum -\effects -Equivalent to \tcode{x.swap(y)}. -\end{itemdescr} + // \ref{variant.get}, value access + template + constexpr bool holds_alternative(const variant&) noexcept; -\rSec3[expected.object.obs]{Observers} + template + constexpr variant_alternative_t>& + get(variant&); // freestanding-deleted + template + constexpr variant_alternative_t>&& + get(variant&&); // freestanding-deleted + template + constexpr const variant_alternative_t>& + get(const variant&); // freestanding-deleted + template + constexpr const variant_alternative_t>&& + get(const variant&&); // freestanding-deleted -\indexlibrarymember{operator->}{expected}% -\begin{itemdecl} -constexpr const T* operator->() const noexcept; -constexpr T* operator->() noexcept; -\end{itemdecl} + template + constexpr T& get(variant&); // freestanding-deleted + template + constexpr T&& get(variant&&); // freestanding-deleted + template + constexpr const T& get(const variant&); // freestanding-deleted + template + constexpr const T&& get(const variant&&); // freestanding-deleted -\begin{itemdescr} -\pnum -\expects -\tcode{has_value()} is \tcode{true}. + template + constexpr add_pointer_t>> + get_if(variant*) noexcept; + template + constexpr add_pointer_t>> + get_if(const variant*) noexcept; -\pnum -\returns -\tcode{addressof(\exposid{val})}. -\end{itemdescr} + template + constexpr add_pointer_t + get_if(variant*) noexcept; + template + constexpr add_pointer_t + get_if(const variant*) noexcept; -\indexlibrarymember{operator*}{expected}% -\begin{itemdecl} -constexpr const T& operator*() const & noexcept; -constexpr T& operator*() & noexcept; -\end{itemdecl} + // \ref{variant.relops}, relational operators + template + constexpr bool operator==(const variant&, const variant&); + template + constexpr bool operator!=(const variant&, const variant&); + template + constexpr bool operator<(const variant&, const variant&); + template + constexpr bool operator>(const variant&, const variant&); + template + constexpr bool operator<=(const variant&, const variant&); + template + constexpr bool operator>=(const variant&, const variant&); + template requires (@\libconcept{three_way_comparable}@ && ...) + constexpr common_comparison_category_t...> + operator<=>(const variant&, const variant&); -\begin{itemdescr} -\pnum -\expects -\tcode{has_value()} is \tcode{true}. + // \ref{variant.visit}, visitation + template + constexpr @\seebelow@ visit(Visitor&&, Variants&&...); + template + constexpr R visit(Visitor&&, Variants&&...); -\pnum -\returns -\exposid{val}. -\end{itemdescr} + // \ref{variant.monostate}, class \tcode{monostate} + struct monostate; -\indexlibrarymember{operator*}{expected}% -\begin{itemdecl} -constexpr T&& operator*() && noexcept; -constexpr const T&& operator*() const && noexcept; -\end{itemdecl} + // \ref{variant.monostate.relops}, \tcode{monostate} relational operators + constexpr bool operator==(monostate, monostate) noexcept; + constexpr strong_ordering operator<=>(monostate, monostate) noexcept; -\begin{itemdescr} -\pnum -\expects -\tcode{has_value()} is \tcode{true}. + // \ref{variant.specalg}, specialized algorithms + template + constexpr void swap(variant&, variant&) noexcept(@\seebelow@); -\pnum -\returns -\tcode{std::move(\exposid{val})}. -\end{itemdescr} + // \ref{variant.bad.access}, class \tcode{bad_variant_access} + class bad_variant_access; -\indexlibrarymember{operator bool}{expected}% -\indexlibrarymember{has_value}{expected}% -\begin{itemdecl} -constexpr explicit operator bool() const noexcept; -constexpr bool has_value() const noexcept; -\end{itemdecl} + // \ref{variant.hash}, hash support + template struct hash; + template struct hash>; + template<> struct hash; +} +\end{codeblock} -\begin{itemdescr} -\pnum -\returns -\exposid{has_val}. -\end{itemdescr} +\rSec2[variant.variant]{Class template \tcode{variant}}% +\indexlibraryglobal{variant}% -\indexlibrarymember{value}{expected}% -\begin{itemdecl} -constexpr const T& value() const &; -constexpr T& value() &; -\end{itemdecl} +\rSec3[variant.variant.general]{General} -\begin{itemdescr} -\pnum -\mandates -\tcode{is_copy_constructible_v} is \tcode{true}. +\begin{codeblock} +namespace std { + template + class variant { + public: + // \ref{variant.ctor}, constructors + constexpr variant() noexcept(@\seebelow@); + constexpr variant(const variant&); + constexpr variant(variant&&) noexcept(@\seebelow@); -\pnum -\returns -\exposid{val}, if \tcode{has_value()} is \tcode{true}. + template + constexpr variant(T&&) noexcept(@\seebelow@); -\pnum -\throws -\tcode{bad_expected_access(as_const(error()))} if \tcode{has_value()} is \tcode{false}. -\end{itemdescr} + template + constexpr explicit variant(in_place_type_t, Args&&...); + template + constexpr explicit variant(in_place_type_t, initializer_list, Args&&...); -\indexlibrarymember{value}{expected}% -\begin{itemdecl} -constexpr T&& value() &&; -constexpr const T&& value() const &&; -\end{itemdecl} + template + constexpr explicit variant(in_place_index_t, Args&&...); + template + constexpr explicit variant(in_place_index_t, initializer_list, Args&&...); -\begin{itemdescr} -\pnum -\mandates -\tcode{is_copy_constructible_v} is \tcode{true} and -\tcode{is_constructible_v} is \tcode{true}. + // \ref{variant.dtor}, destructor + constexpr ~variant(); -\pnum -\returns -\tcode{std::move(\exposid{val})}, if \tcode{has_value()} is \tcode{true}. + // \ref{variant.assign}, assignment + constexpr variant& operator=(const variant&); + constexpr variant& operator=(variant&&) noexcept(@\seebelow@); -\pnum -\throws -\tcode{bad_expected_access(std::move(error()))} -if \tcode{has_value()} is \tcode{false}. -\end{itemdescr} + template constexpr variant& operator=(T&&) noexcept(@\seebelow@); -\indexlibrarymember{error}{expected}% -\begin{itemdecl} -constexpr const E& error() const & noexcept; -constexpr E& error() & noexcept; -\end{itemdecl} + // \ref{variant.mod}, modifiers + template + constexpr T& emplace(Args&&...); + template + constexpr T& emplace(initializer_list, Args&&...); + template + constexpr variant_alternative_t>& emplace(Args&&...); + template + constexpr variant_alternative_t>& + emplace(initializer_list, Args&&...); -\begin{itemdescr} -\pnum -\expects -\tcode{has_value()} is \tcode{false}. + // \ref{variant.status}, value status + constexpr bool valueless_by_exception() const noexcept; + constexpr size_t index() const noexcept; -\pnum -\returns -\exposid{unex}. -\end{itemdescr} + // \ref{variant.swap}, swap + constexpr void swap(variant&) noexcept(@\seebelow@); -\indexlibrarymember{error}{expected}% -\begin{itemdecl} -constexpr E&& error() && noexcept; -constexpr const E&& error() const && noexcept; -\end{itemdecl} + // \ref{variant.visit}, visitation + template + constexpr decltype(auto) visit(this Self&&, Visitor&&); + template + constexpr R visit(this Self&&, Visitor&&); + }; +} +\end{codeblock} -\begin{itemdescr} \pnum -\expects -\tcode{has_value()} is \tcode{false}. +Any instance of \tcode{variant} at any given time either holds a value +of one of its alternative types or holds no value. +When an instance of \tcode{variant} holds a value of alternative type \tcode{T}, +it means that a value of type \tcode{T}, referred to as the \tcode{variant} +object's \defnx{contained value}{contained value!\idxcode{variant}}, +is nested within\iref{intro.object} the +\tcode{variant} object. \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} +All types in \tcode{Types} shall meet +the \oldconcept{Destructible} requirements (\tref{cpp17.destructible}). -\begin{itemdescr} \pnum -\mandates -\tcode{is_copy_constructible_v} is \tcode{true} and -\tcode{is_convertible_v} is \tcode{true}. +A program that instantiates the definition of \tcode{variant} with +no template arguments is ill-formed. \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} +If a program declares an explicit or partial specialization of \tcode{variant}, +the program is ill-formed, no diagnostic required. -\begin{itemdescr} -\pnum -\mandates -\tcode{is_move_constructible_v} is \tcode{true} and -\tcode{is_convertible_v} is \tcode{true}. +\rSec3[variant.ctor]{Constructors} \pnum -\returns -\tcode{has_value() ? std::move(**this) : static_cast(std::forward(v))}. -\end{itemdescr} +In the descriptions that follow, let $i$ be in the range \range{0}{sizeof...(Types)}, +and $\tcode{T}_i$ be the $i^\text{th}$ type in \tcode{Types}. -\indexlibrarymember{error_or}{expected}% +\indexlibraryctor{variant}% \begin{itemdecl} -template constexpr E error_or(G&& e) const &; +constexpr variant() noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{is_copy_constructible_v} is \tcode{true} and -\tcode{is_convertible_v} is \tcode{true}. +\constraints +\tcode{is_default_constructible_v<$\tcode{T}_0$>} is \tcode{true}. \pnum -\returns -\tcode{std::forward(e)} if \tcode{has_value()} is \tcode{true}, -\tcode{error()} otherwise. -\end{itemdescr} +\effects +Constructs a \tcode{variant} holding a value-initialized value of type $\tcode{T}_0$. -\indexlibrarymember{error_or}{expected}% -\begin{itemdecl} -template constexpr E error_or(G&& e) &&; -\end{itemdecl} +\pnum +\ensures +\tcode{valueless_by_exception()} is \tcode{false} and \tcode{index()} is \tcode{0}. -\begin{itemdescr} \pnum -\mandates -\tcode{is_move_constructible_v} is \tcode{true} and -\tcode{is_convertible_v} is \tcode{true}. +\throws +Any exception thrown by the value-initialization of $\tcode{T}_0$. \pnum -\returns -\tcode{std::forward(e)} if \tcode{has_value()} is \tcode{true}, -\tcode{std::move(error())} otherwise. +\remarks +This function is \keyword{constexpr} if and only if the +value-initialization of the alternative type $\tcode{T}_0$ +would be constexpr-suitable\iref{dcl.constexpr}. +The exception specification is equivalent to +\tcode{is_nothrow_default_constructible_v<$\tcode{T}_0$>}. +\begin{note} +See also class \tcode{monostate}. +\end{note} \end{itemdescr} -\rSec3[expected.object.monadic]{Monadic operations} - -\indexlibrarymember{and_then}{expected}% +\indexlibraryctor{variant}% \begin{itemdecl} -template constexpr auto and_then(F&& f) &; -template constexpr auto and_then(F&& f) const &; +constexpr variant(const variant& w); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{U} be \tcode{remove_cvref_t>}. - -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\effects +If \tcode{w} holds a value, initializes the \tcode{variant} to hold the same +alternative as \tcode{w} and direct-initializes the contained value +with \tcode{\exposid{GET}(w)}, where \tcode{j} is \tcode{w.index()}. +Otherwise, initializes the \tcode{variant} to not hold a value. \pnum -\mandates -\tcode{U} is a specialization of \tcode{expected} and -\tcode{is_same_v} is \tcode{true}. +\throws +Any exception thrown by direct-initializing any $\tcode{T}_i$ for all $i$. \pnum -\effects -Equivalent to: -\begin{codeblock} -if (has_value()) - return invoke(std::forward(f), @\exposid{val}@); -else - return U(unexpect, error()); -\end{codeblock} +\remarks +This constructor is defined as deleted unless +\tcode{is_copy_constructible_v<$\tcode{T}_i$>} is \tcode{true} for all $i$. +If \tcode{is_trivially_copy_constructible_v<$\tcode{T}_i$>} +is \tcode{true} for all $i$, this constructor is trivial. \end{itemdescr} -\indexlibrarymember{and_then}{expected}% +\indexlibraryctor{variant}% \begin{itemdecl} -template constexpr auto and_then(F&& f) &&; -template constexpr auto and_then(F&& f) const &&; +constexpr variant(variant&& w) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{U} be -\tcode{remove_cvref_t>}. +\constraints +\tcode{is_move_constructible_v<$\tcode{T}_i$>} is \tcode{true} for all $i$. \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\effects +If \tcode{w} holds a value, initializes the \tcode{variant} to hold the same +alternative as \tcode{w} and direct-initializes the contained value with +\tcode{\exposid{GET}(std::move(w))}, where \tcode{j} is \tcode{w.index()}. +Otherwise, initializes the \tcode{variant} to not hold a value. \pnum -\mandates -\tcode{U} is a specialization of \tcode{expected} and -\tcode{is_same_v} is \tcode{true}. +\throws +Any exception thrown by move-constructing any $\tcode{T}_i$ for all $i$. \pnum -\effects -Equivalent to: -\begin{codeblock} -if (has_value()) - return invoke(std::forward(f), std::move(@\exposid{val}@)); -else - return U(unexpect, std::move(error())); -\end{codeblock} +\remarks +The exception specification is equivalent to the logical \logop{and} of +\tcode{is_nothrow_move_con\-structible_v<$\tcode{T}_i$>} for all $i$. +If \tcode{is_trivially_move_constructible_v<$\tcode{T}_i$>} +is \tcode{true} for all $i$, this constructor is trivial. \end{itemdescr} -\indexlibrarymember{or_else}{expected}% +\indexlibraryctor{variant}% \begin{itemdecl} -template constexpr auto or_else(F&& f) &; -template constexpr auto or_else(F&& f) const &; +template constexpr variant(T&& t) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{G} be \tcode{remove_cvref_t>}. +Let $\tcode{T}_j$ be a type that is determined as follows: +build an imaginary function \tcode{\placeholdernc{FUN}($\tcode{T}_i$)} +for each alternative type $\tcode{T}_i$ +for which \tcode{$\tcode{T}_i$ x[] =} \tcode{\{std::forward(t)\};} +is well-formed for some invented variable \tcode{x}. +The overload \tcode{\placeholdernc{FUN}($\tcode{T}_j$)} selected by overload +resolution for the expression \tcode{\placeholdernc{FUN}(std::forward(\brk{}t))} defines +the alternative $\tcode{T}_j$ which is the type of the contained value after +construction. \pnum \constraints -\tcode{is_constructible_v} is \tcode{true}. +\begin{itemize} +\item +\tcode{sizeof...(Types)} is nonzero, -\pnum -\mandates -\tcode{G} is a specialization of \tcode{expected} and -\tcode{is_same_v} is \tcode{true}. +\item +\tcode{is_same_v, variant>} is \tcode{false}, -\pnum -\effects -Equivalent to: +\item +\tcode{remove_cvref_t} is neither +a specialization of \tcode{in_place_type_t} nor +a specialization of \tcode{in_place_index_t}, + +\item +\tcode{is_constructible_v<$\tcode{T}_j$, T>} is \tcode{true}, and + +\item +the expression \tcode{\placeholdernc{FUN}(}\brk\tcode{std::forward(t))} +(with \tcode{\placeholdernc{FUN}} being the above-mentioned set of +imaginary functions) is well-formed. +\begin{note} \begin{codeblock} -if (has_value()) - return G(in_place, @\exposid{val}@); -else - return invoke(std::forward(f), error()); +variant v("abc"); \end{codeblock} -\end{itemdescr} - -\indexlibrarymember{or_else}{expected}% -\begin{itemdecl} -template constexpr auto or_else(F&& f) &&; -template constexpr auto or_else(F&& f) const &&; -\end{itemdecl} +is ill-formed, as both alternative types have an equally viable constructor +for the argument. +\end{note} +\end{itemize} -\begin{itemdescr} \pnum -Let \tcode{G} be -\tcode{remove_cvref_t>}. +\effects +Initializes \tcode{*this} to hold the alternative type $\tcode{T}_j$ and +direct-non-list-initializes the contained value with \tcode{std::forward(t)}. \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\ensures +\tcode{holds_alternative<$\tcode{T}_j$>(*this)} is \tcode{true}. \pnum -\mandates -\tcode{G} is a specialization of \tcode{expected} and -\tcode{is_same_v} is \tcode{true}. +\throws +Any exception thrown by the initialization of the selected alternative $\tcode{T}_j$. \pnum -\effects -Equivalent to: -\begin{codeblock} -if (has_value()) - return G(in_place, std::move(@\exposid{val}@)); -else - return invoke(std::forward(f), std::move(error())); -\end{codeblock} +\remarks +The exception specification is equivalent to +\tcode{is_nothrow_constructible_v<$\tcode{T}_j$, T>}. +If $\tcode{T}_j$'s selected constructor is a constexpr constructor, +this constructor is a constexpr constructor. \end{itemdescr} -\indexlibrarymember{transform}{expected}% +\indexlibraryctor{variant}% \begin{itemdecl} -template constexpr auto transform(F&& f) &; -template constexpr auto transform(F&& f) const &; +template constexpr explicit variant(in_place_type_t, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{U} be -\tcode{remove_cv_t>}. +\constraints +\begin{itemize} +\item There is exactly one occurrence of \tcode{T} in \tcode{Types...} and +\item \tcode{is_constructible_v} is \tcode{true}. +\end{itemize} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\effects +Direct-non-list-initializes the contained value of type \tcode{T} +with \tcode{std::forward(args)...}. \pnum -\mandates -\tcode{U} is a valid value type for \tcode{expected}. -If \tcode{is_void_v} is \tcode{false}, -the declaration -\begin{codeblock} -U u(invoke(std::forward(f), @\exposid{val}@)); -\end{codeblock} -is well-formed. +\ensures +\tcode{holds_alternative(*this)} is \tcode{true}. \pnum -\effects -\begin{itemize} -\item -If \tcode{has_value()} is \tcode{false}, returns -\tcode{expected(unexpect, error())}. -\item -Otherwise, if \tcode{is_void_v} is \tcode{false}, returns an -\tcode{expected} object whose \exposid{has_val} member is \tcode{true} -and \exposid{val} member is direct-non-list-initialized with -\tcode{invoke(std::forward(f), \exposid{val})}. -\item -Otherwise, evaluates \tcode{invoke(std::forward(f), \exposid{val})} and then -returns \tcode{expected()}. -\end{itemize} +\throws +Any exception thrown by calling the selected constructor of \tcode{T}. + +\pnum +\remarks +If \tcode{T}'s selected constructor is a constexpr constructor, this +constructor is a constexpr constructor. \end{itemdescr} -\indexlibrarymember{transform}{expected}% +\indexlibraryctor{variant}% \begin{itemdecl} -template constexpr auto transform(F&& f) &&; -template constexpr auto transform(F&& f) const &&; +template + constexpr explicit variant(in_place_type_t, initializer_list il, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{U} be -\tcode{remove_cv_t>}. +\constraints +\begin{itemize} +\item There is exactly one occurrence of \tcode{T} in \tcode{Types...} and +\item \tcode{is_constructible_v\&, Args...>} is \tcode{true}. +\end{itemize} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\effects +Direct-non-list-initializes the contained value of type \tcode{T} +with \tcode{il, std::forward(\brk{}args)...}. \pnum -\mandates -\tcode{U} is a valid value type for \tcode{expected}. If \tcode{is_void_v} is -\tcode{false}, the declaration -\begin{codeblock} -U u(invoke(std::forward(f), std::move(@\exposid{val}@))); -\end{codeblock} -is well-formed. +\ensures +\tcode{holds_alternative(*this)} is \tcode{true}. \pnum -\effects -\begin{itemize} -\item -If \tcode{has_value()} is \tcode{false}, returns -\tcode{expected(unexpect, std::move(error()))}. -\item -Otherwise, if \tcode{is_void_v} is \tcode{false}, returns an -\tcode{expected} object whose \exposid{has_val} member is \tcode{true} -and \exposid{val} member is direct-non-list-initialized with -\tcode{invoke(std::forward(f), std::move(\exposid{val}))}. -\item -Otherwise, evaluates \tcode{invoke(std::forward(f), std::move(\exposid{val}))} and -then returns \tcode{ex\-pected()}. -\end{itemize} +\throws +Any exception thrown by calling the selected constructor of \tcode{T}. + +\pnum +\remarks +If \tcode{T}'s selected constructor is a constexpr constructor, this +constructor is a constexpr constructor. \end{itemdescr} -\indexlibrarymember{transform_error}{expected}% +\indexlibraryctor{variant}% \begin{itemdecl} -template constexpr auto transform_error(F&& f) &; -template constexpr auto transform_error(F&& f) const &; +template constexpr explicit variant(in_place_index_t, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{G} be \tcode{remove_cv_t>}. +\constraints +\begin{itemize} +\item +\tcode{I} is less than \tcode{sizeof...(Types)} and +\item +\tcode{is_constructible_v<$\tcode{T}_I$, Args...>} is \tcode{true}. +\end{itemize} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\effects +Direct-non-list-initializes the contained value of type $\tcode{T}_I$ +with \tcode{std::forward(args)...}. \pnum -\mandates -\tcode{G} is a valid template argument -for \tcode{unexpected}\iref{expected.un.general} and the declaration -\begin{codeblock} -G g(invoke(std::forward(f), error())); -\end{codeblock} -is well-formed. +\ensures +\tcode{index()} is \tcode{I}. \pnum -\returns -If \tcode{has_value()} is \tcode{true}, -\tcode{expected(in_place, \exposid{val})}; otherwise, an \tcode{expected} -object whose \exposid{has_val} member is \tcode{false} and \exposid{unex} member -is direct-non-list-initialized with \tcode{invoke(std::forward(f), error())}. +\throws +Any exception thrown by calling the selected constructor of $\tcode{T}_I$. + +\pnum +\remarks +If $\tcode{T}_I$'s selected constructor is a constexpr constructor, this +constructor is a constexpr constructor. \end{itemdescr} -\indexlibrarymember{transform_error}{expected}% +\indexlibraryctor{variant}% \begin{itemdecl} -template constexpr auto transform_error(F&& f) &&; -template constexpr auto transform_error(F&& f) const &&; +template + constexpr explicit variant(in_place_index_t, initializer_list il, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{G} be -\tcode{remove_cv_t>}. +\constraints +\begin{itemize} +\item +\tcode{I} is less than \tcode{sizeof...(Types)} and +\item +\tcode{is_constructible_v<$\tcode{T}_I$, initializer_list\&, Args...>} is \tcode{true}. +\end{itemize} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\effects +Direct-non-list-initializes the contained value of type $\tcode{T}_I$ +with \tcode{il, std::forward(\brk{}args)...}. \pnum -\mandates -\tcode{G} is a valid template argument -for \tcode{unexpected}\iref{expected.un.general} and the declaration -\begin{codeblock} -G g(invoke(std::forward(f), std::move(error()))); -\end{codeblock} -is well-formed. +\ensures +\tcode{index()} is \tcode{I}. \pnum -\returns -If \tcode{has_value()} is \tcode{true}, -\tcode{expected(in_place, std::move(\exposid{val}))}; otherwise, an -\tcode{expected} object whose \exposid{has_val} member is \tcode{false} -and \exposid{unex} member is direct-non-list-initialized with -\tcode{invoke(std::forward(f), std::move(error()))}. +\remarks +If $\tcode{T}_I$'s selected constructor is a constexpr constructor, this +constructor is a constexpr constructor. \end{itemdescr} -\rSec3[expected.object.eq]{Equality operators} +\rSec3[variant.dtor]{Destructor} -\indexlibrarymember{operator==}{expected}% +\indexlibrarydtor{variant}% \begin{itemdecl} -template requires (!is_void_v) - friend constexpr bool operator==(const expected& x, const expected& y); +constexpr ~variant(); \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}. +\effects +If \tcode{valueless_by_exception()} is \tcode{false}, +destroys the currently contained value. \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()}. +\remarks +If \tcode{is_trivially_destructible_v<$\tcode{T}_i$>} is \tcode{true} for all $\tcode{T}_i$, +then this destructor is trivial. \end{itemdescr} -\indexlibrarymember{operator==}{expected}% +\rSec3[variant.assign]{Assignment} + +\indexlibrarymember{operator=}{variant}% \begin{itemdecl} -template friend constexpr bool operator==(const expected& x, const T2& v); +constexpr variant& operator=(const variant& rhs); \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{T} need not be \oldconcept{EqualityComparable}. -\end{note} +Let $j$ be \tcode{rhs.index()}. + +\pnum +\effects +\begin{itemize} +\item +If neither \tcode{*this} nor \tcode{rhs} holds a value, there is no effect. +\item +Otherwise, if \tcode{*this} holds a value but \tcode{rhs} does not, destroys the value +contained in \tcode{*this} and sets \tcode{*this} to not hold a value. +\item +Otherwise, if \tcode{index() == $j$}, assigns the value contained in \tcode{rhs} +to the value contained in \tcode{*this}. +\item +Otherwise, if either \tcode{is_nothrow_copy_constructible_v<$\tcode{T}_j$>} +is \tcode{true} or +\tcode{is_nothrow_move_con\-structible_v<$\tcode{T}_j$>} is \tcode{false}, +equivalent to \tcode{emplace<$j$>(\exposid{GET}<$j$>(rhs))}. +\item +Otherwise, equivalent to \tcode{operator=(variant(rhs))}. +\end{itemize} + +\pnum +\ensures +\tcode{index() == rhs.index()}. \pnum \returns -\tcode{x.has_value() \&\& static_cast(*x == v)}. +\tcode{*this}. + +\pnum +\remarks +This operator is defined as deleted unless +\tcode{is_copy_constructible_v<$\tcode{T}_i$> \&\&} +\tcode{is_copy_assignable_v<$\tcode{T}_i$>} +is \tcode{true} for all $i$. +If \tcode{is_trivially_copy_constructible_v<$\tcode{T}_i$> \&\&} +\tcode{is_trivially_copy_assignable_v<$\tcode{T}_i$> \&\&} +\tcode{is_trivially_destructible_v<$\tcode{T}_i$>} +is \tcode{true} for all $i$, this assignment operator is trivial. \end{itemdescr} -\indexlibrarymember{operator==}{expected}% +\indexlibrarymember{operator=}{variant}% \begin{itemdecl} -template friend constexpr bool operator==(const expected& x, const unexpected& e); +constexpr variant& operator=(variant&& rhs) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{x.error() == e.error()} is well-formed and -its result is convertible to \tcode{bool}. +Let $j$ be \tcode{rhs.index()}. \pnum -\returns -\tcode{!x.has_value() \&\& static_cast(x.error() == e.error())}. -\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.cons}, constructors - constexpr expected() noexcept; - constexpr expected(const expected&); - constexpr expected(expected&&) noexcept(@\seebelow@); - template - constexpr explicit(@\seebelow@) expected(const expected&); - template - constexpr explicit(@\seebelow@) expected(expected&&); - - template - constexpr explicit(@\seebelow@) expected(const unexpected&); - template - constexpr explicit(@\seebelow@) 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(); +\constraints +\tcode{is_move_constructible_v<$\tcode{T}_i$> \&\&} +\tcode{is_move_assignable_v<$\tcode{T}_i$>} is +\tcode{true} for all $i$. - // \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; +\pnum +\effects +\begin{itemize} +\item +If neither \tcode{*this} nor \tcode{rhs} holds a value, there is no effect. +\item +Otherwise, if \tcode{*this} holds a value but \tcode{rhs} does not, destroys the value +contained in \tcode{*this} and sets \tcode{*this} to not hold a value. +\item +Otherwise, if \tcode{index() == $j$}, assigns \tcode{\exposid{GET}<$j$>(std::move(rhs))} to +the value contained in \tcode{*this}. +\item +Otherwise, equivalent to \tcode{emplace<$j$>(\exposid{GET}<$j$>(std::move(rhs)))}. +\end{itemize} - // \ref{expected.void.swap}, swap - constexpr void swap(expected&) noexcept(@\seebelow@); - friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); +\pnum +\returns +\tcode{*this}. - // \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 &; // freestanding-deleted - constexpr void value() &&; // freestanding-deleted - constexpr const E& error() const & noexcept; - constexpr E& error() & noexcept; - constexpr const E&& error() const && noexcept; - constexpr E&& error() && noexcept; - template constexpr E error_or(G&&) const &; - template constexpr E error_or(G&&) &&; +\pnum +\remarks +If \tcode{is_trivially_move_constructible_v<$\tcode{T}_i$> \&\&} +\tcode{is_trivially_move_assignable_v<$\tcode{T}_i$> \&\&} +\tcode{is_trivially_destructible_v<$\tcode{T}_i$>} +is \tcode{true} for all $i$, this assignment operator is trivial. +The exception specification is equivalent to +\tcode{is_nothrow_move_constructible_v<$\tcode{T}_i$> \&\& is_nothrow_move_assignable_v<$\tcode{T}_i$>} for all $i$. +\begin{itemize} +\item If an exception is thrown during the call to $\tcode{T}_j$'s move construction +(with $j$ being \tcode{rhs.index()}), the \tcode{variant} will hold no value. +\item If an exception is thrown during the call to $\tcode{T}_j$'s move assignment, +the state of the contained value is as defined by the exception safety +guarantee of $\tcode{T}_j$'s move assignment; \tcode{index()} will be $j$. +\end{itemize} +\end{itemdescr} - // \ref{expected.void.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 or_else(F&& f) &; - template constexpr auto or_else(F&& f) &&; - template constexpr auto or_else(F&& f) const &; - template constexpr auto or_else(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_error(F&& f) &; - template constexpr auto transform_error(F&& f) &&; - template constexpr auto transform_error(F&& f) const &; - template constexpr auto transform_error(F&& f) const &&; +\indexlibrarymember{operator=}{variant}% +\begin{itemdecl} +template constexpr variant& operator=(T&& t) noexcept(@\seebelow@); +\end{itemdecl} - // \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&); +\begin{itemdescr} +\pnum +Let $\tcode{T}_j$ be a type that is determined as follows: +build an imaginary function \tcode{\placeholdernc{FUN}($\tcode{T}_i$)} +for each alternative type $\tcode{T}_i$ +for which \tcode{$\tcode{T}_i$ x[] =} \tcode{\{std::forward(t)\};} +is well-formed for some invented variable \tcode{x}. +The overload \tcode{\placeholdernc{FUN}($\tcode{T}_j$)} selected by overload +resolution for the expression \tcode{\placeholdernc{FUN}(std::forward(\brk{}t))} defines +the alternative $\tcode{T}_j$ which is the type of the contained value after +assignment. -private: - bool @\exposid{has_val}@; // \expos - union { - E @\exposid{unex}@; // \expos - }; -}; +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_same_v, variant>} is \tcode{false}, + +\item +\tcode{is_assignable_v<$\tcode{T}_j$\&, T> \&\& is_constructible_v<$\tcode{T}_j$, T>} +is \tcode{true}, and + +\item +the expression \tcode{\placeholdernc{FUN}(std::forward(t))} +(with \tcode{\placeholdernc{FUN}} being the above-mentioned set +of imaginary functions) is well-formed. +\begin{note} +\begin{codeblock} +variant v; +v = "abc"; \end{codeblock} +is ill-formed, as both alternative types have an equally viable constructor +for the argument. +\end{note} +\end{itemize} \pnum -Any object of type \tcode{expected} either -represents a value of type \tcode{T}, or -contains 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{E}. -Member \exposid{has_val} indicates whether the \tcode{expected} object -represents a value of type \tcode{T}. +\effects +\begin{itemize} +\item +If \tcode{*this} holds a $\tcode{T}_j$, assigns \tcode{std::forward(t)} to +the value contained in \tcode{*this}. +\item +Otherwise, if \tcode{is_nothrow_constructible_v<$\tcode{T}_j$, T> ||} +\tcode{!is_nothrow_move_constructible_v<$\tcode{T}_j$>} is \tcode{true}, +equivalent to \tcode{emplace<$j$>(std::forward(t))}. +\item +Otherwise, equivalent to \tcode{emplace<$j$>($\tcode{T}_j$(std::forward(t)))}. +\end{itemize} \pnum -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. +\ensures +\tcode{holds_alternative<$\tcode{T}_j$>(*this)} is \tcode{true}, with $\tcode{T}_j$ +selected by the imaginary function overload resolution described above. \pnum -\tcode{E} shall meet the requirements of -\oldconcept{Destructible} (\tref{cpp17.destructible}). +\returns +\tcode{*this}. -\rSec3[expected.void.cons]{Constructors} +\pnum +\remarks +The exception specification is equivalent to: +\begin{codeblock} +is_nothrow_assignable_v && is_nothrow_constructible_v +\end{codeblock} +\begin{itemize} +\item If an exception is thrown during the assignment of \tcode{std::forward(t)} +to the value contained in \tcode{*this}, the state of the contained value and +\tcode{t} are as defined by the exception safety guarantee of the assignment +expression; \tcode{valueless_by_exception()} will be \tcode{false}. +\item If an exception is thrown during the initialization of the contained value, +the \tcode{variant} object is permitted to not hold a value. +\end{itemize} +\end{itemdescr} -\indexlibraryctor{expected}% +\rSec3[variant.mod]{Modifiers} + +\indexlibrarymember{emplace}{variant}% \begin{itemdecl} -constexpr expected() noexcept; +template constexpr T& emplace(Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{has_value()} is \tcode{true}. +\constraints +\tcode{is_constructible_v} is \tcode{true}, and +\tcode{T} occurs exactly once in \tcode{Types}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +return emplace<@$I$@>(std::forward(args)...); +\end{codeblock} +where $I$ is the zero-based index of \tcode{T} in \tcode{Types}. \end{itemdescr} -\indexlibraryctor{expected}% +\indexlibrarymember{emplace}{variant}% \begin{itemdecl} -constexpr expected(const expected& rhs); +template + constexpr T& emplace(initializer_list il, Args&&... args); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v\&, Args...>} is \tcode{true}, +and \tcode{T} occurs exactly once in \tcode{Types}. + \pnum \effects -If \tcode{rhs.has_value()} is \tcode{false}, -direct-non-list-initializes \exposid{unex} with \tcode{rhs.error()}. +Equivalent to: +\begin{codeblock} +return emplace<@$I$@>(il, std::forward(args)...); +\end{codeblock} +where $I$ is the zero-based index of \tcode{T} in \tcode{Types}. +\end{itemdescr} + +\indexlibrarymember{emplace}{variant}% +\begin{itemdecl} +template + constexpr variant_alternative_t>& emplace(Args&&... args); +\end{itemdecl} + +\begin{itemdescr} % NOCHECK: order +\pnum +\mandates +$\tcode{I} < \tcode{sizeof...(Types)}$. + +\pnum +\constraints +\tcode{is_constructible_v<$\tcode{T}_I$, Args...>} is \tcode{true}. + +\pnum +\effects +Destroys the currently contained value if \tcode{valueless_by_exception()} +is \tcode{false}. +Then direct-non-list-initializes the contained value of type $\tcode{T}_I$ +with the arguments \tcode{std::forward(args)...}. \pnum \ensures -\tcode{rhs.has_value() == this->has_value()}. +\tcode{index()} is \tcode{I}. \pnum -\throws -Any exception thrown by the initialization of \exposid{unex}. +\returns +A reference to the new contained value. \pnum -\remarks -This constructor is defined as deleted -unless \tcode{is_copy_constructible_v} is \tcode{true}. +\throws +Any exception thrown during the initialization of the contained value. \pnum -This constructor is trivial -if \tcode{is_trivially_copy_constructible_v} is \tcode{true}. +\remarks +If an exception is thrown during the initialization of the contained value, +the \tcode{variant} is permitted to not hold a value. \end{itemdescr} -\indexlibraryctor{expected}% +\indexlibrarymember{emplace}{variant}% \begin{itemdecl} -constexpr expected(expected&& rhs) noexcept(is_nothrow_move_constructible_v); +template + constexpr variant_alternative_t>& + emplace(initializer_list il, Args&&... args); \end{itemdecl} -\begin{itemdescr} +\begin{itemdescr} % NOCHECK: order +\pnum +\mandates +$\tcode{I} < \tcode{sizeof...(Types)}$. + \pnum \constraints -\tcode{is_move_constructible_v} is \tcode{true}. +\tcode{is_constructible_v<$\tcode{T}_I$, initializer_list\&, Args...>} 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())}. +Destroys the currently contained value if \tcode{valueless_by_exception()} +is \tcode{false}. +Then direct-non-list-initializes the contained value of type $\tcode{T}_I$ +with \tcode{il, std::forward(args)...}. \pnum \ensures -\tcode{rhs.has_value()} is unchanged; -\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. +\tcode{index()} is \tcode{I}. + +\pnum +\returns +A reference to the new contained value. \pnum \throws -Any exception thrown by the initialization of \exposid{unex}. +Any exception thrown during the initialization of the contained value. \pnum \remarks -This constructor is trivial -if \tcode{is_trivially_move_constructible_v} is \tcode{true}. +If an exception is thrown during the initialization of the contained value, +the \tcode{variant} is permitted to not hold a value. \end{itemdescr} -\indexlibraryctor{expected}% +\rSec3[variant.status]{Value status} + +\indexlibrarymember{valueless_by_exception}{variant}% \begin{itemdecl} -template - constexpr explicit(!is_convertible_v) expected(const expected& rhs); -template - constexpr explicit(!is_convertible_v) expected(expected&& rhs); +constexpr bool valueless_by_exception() const noexcept; \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())}. +\effects +Returns \tcode{false} if and only if the \tcode{variant} holds a value. \pnum -\ensures -\tcode{rhs.has_value()} is unchanged; -\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. +\begin{note} +It is possible for a \tcode{variant} to hold no value +if an exception is thrown during a +type-changing assignment or emplacement. The latter means that even a +\tcode{variant} can become \tcode{valueless_by_exception()}, for +instance by +\begin{codeblock} +struct S { operator int() { throw 42; }}; +variant v{12.f}; +v.emplace<1>(S()); +\end{codeblock} +\end{note} +\end{itemdescr} + +\indexlibrarymember{index}{variant}% +\begin{itemdecl} +constexpr size_t index() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -Any exception thrown by the initialization of \exposid{unex}. +\effects +If \tcode{valueless_by_exception()} is \tcode{true}, returns \tcode{variant_npos}. +Otherwise, returns the zero-based index of the alternative of the contained value. \end{itemdescr} -\indexlibraryctor{expected}% +\rSec3[variant.swap]{Swap} + +\indexlibrarymember{swap}{variant}% \begin{itemdecl} -template - constexpr explicit(!is_convertible_v) expected(const unexpected& e); -template - constexpr explicit(!is_convertible_v) expected(unexpected&& e); +constexpr void swap(variant& rhs) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{GF} be \tcode{const G\&} for the first overload and -\tcode{G} for the second overload. +\mandates +\tcode{is_move_constructible_v<$\tcode{T}_i$>} is \tcode{true} for all $i$. \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\expects +Each $\tcode{T}_i$ meets the \oldconcept{Swappable} requirements\iref{swappable.requirements}. \pnum \effects -Direct-non-list-initializes \exposid{unex} -with \tcode{std::forward(e.error())}. +\begin{itemize} +\item +If \tcode{valueless_by_exception() \&\& rhs.valueless_by_exception()} no effect. +\item +Otherwise, if \tcode{index() == rhs.index()}, calls \tcode{swap(\exposid{GET}<$i$>(*this), \exposid{GET}<$i$>(rhs))} where $i$ is \tcode{index()}. +\item +Otherwise, exchanges values of \tcode{rhs} and \tcode{*this}. +\end{itemize} \pnum -\ensures -\tcode{has_value()} is \tcode{false}. +\throws +If \tcode{index() == rhs.index()}, +any exception thrown by \tcode{swap(\exposid{GET}<$i$>(*this), \exposid{GET}<$i$>(rhs))} +with $i$ being \tcode{index()}. +Otherwise, any exception thrown by the move constructor +of $\tcode{T}_i$ or $\tcode{T}_j$ +with $i$ being \tcode{index()} and $j$ being \tcode{rhs.index()}. \pnum -\throws -Any exception thrown by the initialization of \exposid{unex}. +\remarks +If an exception is thrown during the call to function \tcode{swap(\exposid{GET}<$i$>(*this), \exposid{GET}<$i$>(rhs))}, +the states of the contained values of \tcode{*this} and of \tcode{rhs} are +determined by the exception safety guarantee of \tcode{swap} for lvalues of +$\tcode{T}_i$ with $i$ being \tcode{index()}. +If an exception is thrown during the exchange of the values of \tcode{*this} +and \tcode{rhs}, the states of the values of \tcode{*this} and of \tcode{rhs} +are determined by the exception safety guarantee of \tcode{variant}'s move constructor. +The exception specification is equivalent to the logical \logop{and} of +\tcode{is_nothrow_move_constructible_v<$\tcode{T}_i$> \&\& is_nothrow_swappable_v<$\tcode{T}_i$>} for all $i$. \end{itemdescr} -\indexlibraryctor{expected}% +\rSec2[variant.helper]{\tcode{variant} helper classes} + +\indexlibraryglobal{variant_size}% \begin{itemdecl} -constexpr explicit expected(in_place_t) noexcept; +template struct variant_size; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{has_value()} is \tcode{true}. +All specializations of \tcode{variant_size} meet the +\oldconcept{UnaryTypeTrait} requirements\iref{meta.rqmts} +with a base characteristic of \tcode{integral_constant} for some \tcode{N}. \end{itemdescr} -\indexlibraryctor{expected}% +\indexlibraryglobal{variant_size}% \begin{itemdecl} -template - constexpr explicit expected(unexpect_t, Args&&... args); +template struct variant_size; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +Let \tcode{VS} denote \tcode{variant_size} of the cv-unqualified +type \tcode{T}. Then each specialization of the template meets the +\oldconcept{UnaryTypeTrait} requirements\iref{meta.rqmts} with a +base characteristic of \tcode{integral_constant}. +\end{itemdescr} -\pnum -\effects -Direct-non-list-initializes \exposid{unex} -with \tcode{std::forward(args)...}. +\indexlibraryglobal{variant_size}% +\begin{itemdecl} +template + struct variant_size> : integral_constant { }; +\end{itemdecl} +% No itemdescr needed for variant_size> -\pnum -\ensures -\tcode{has_value()} is \tcode{false}. +\indexlibraryglobal{variant_alternative}% +\begin{itemdecl} +template struct variant_alternative; +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -Any exception thrown by the initialization of \exposid{unex}. +Let \tcode{VA} denote \tcode{variant_alternative} of the +cv-unqualified type \tcode{T}. Then each specialization of the template +meets the \oldconcept{TransformationTrait} requirements\iref{meta.rqmts} with a +member typedef \tcode{type} that names the type \tcode{add_const_t}. \end{itemdescr} -\indexlibraryctor{expected}% +\indexlibraryglobal{variant_alternative}% \begin{itemdecl} -template - constexpr explicit expected(unexpect_t, initializer_list il, Args&&... args); +variant_alternative>::type \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}. +\mandates +$\tcode{I} < \tcode{sizeof...(Types)}$. \pnum -\throws -Any exception thrown by the initialization of \exposid{unex}. +\ctype +The type $\tcode{T}_I$. \end{itemdescr} -\rSec3[expected.void.dtor]{Destructor} +\rSec2[variant.get]{Value access} -\indexlibrarydtor{expected}% +\indexlibraryglobal{holds_alternative} +\indexlibrarymember{variant}{holds_alternative} \begin{itemdecl} -constexpr ~expected(); +template + constexpr bool holds_alternative(const variant& v) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -If \tcode{has_value()} is \tcode{false}, destroys \exposid{unex}. +\mandates +The type \tcode{T} occurs exactly once in \tcode{Types}. \pnum -\remarks -If \tcode{is_trivially_destructible_v} is \tcode{true}, -then this destructor is a trivial destructor. +\returns +\tcode{true} if \tcode{index()} is equal to the zero-based index of \tcode{T} in \tcode{Types}. \end{itemdescr} -\rSec3[expected.void.assign]{Assignment} - -\indexlibrarymember{operator=}{expected}% \begin{itemdecl} -constexpr expected& operator=(const expected& rhs); +template + constexpr variant_alternative_t>& + @\exposid{GET}@(variant& v); // \expos +template + constexpr variant_alternative_t>&& + @\exposid{GET}@(variant&& v); // \expos +template + constexpr const variant_alternative_t>& + @\exposid{GET}@(const variant& v); // \expos +template + constexpr const variant_alternative_t>&& + @\exposid{GET}@(const variant&& v); // \expos \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} +\mandates +$\tcode{I} < \tcode{sizeof...(Types)}$. \pnum -\returns -\tcode{*this}. +\expects +\tcode{v.index()} is \tcode{I}. \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}. +\returns +A reference to the object stored in the \tcode{variant}. \end{itemdescr} -\indexlibrarymember{operator=}{expected}% +\indexlibrarymember{get}{variant}% \begin{itemdecl} -constexpr expected& operator=(expected&& rhs) noexcept(@\seebelow@); +template + constexpr variant_alternative_t>& get(variant& v); +template + constexpr variant_alternative_t>&& get(variant&& v); +template + constexpr const variant_alternative_t>& get(const variant& v); +template + constexpr const variant_alternative_t>&& get(const variant&& v); \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +$\tcode{I} < \tcode{sizeof...(Types)}$. + \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} = std::move(rhs.error())}. -\end{itemize} +If \tcode{v.index()} is \tcode{I}, returns a reference to the object stored in +the \tcode{variant}. Otherwise, throws an exception of type \tcode{bad_variant_access}. +\end{itemdescr} + +\indexlibrarymember{get}{variant}% +\begin{itemdecl} +template constexpr T& get(variant& v); +template constexpr T&& get(variant&& v); +template constexpr const T& get(const variant& v); +template constexpr const T&& get(const variant&& v); +\end{itemdecl} +\begin{itemdescr} \pnum -\returns -\tcode{*this}. +\mandates +The type \tcode{T} occurs exactly once in \tcode{Types}. + +\pnum +\effects +If \tcode{v} holds a value of type \tcode{T}, returns a reference to that value. +Otherwise, throws an exception of type \tcode{bad_variant_access}. +\end{itemdescr} + +\indexlibraryglobal{get_if}% +\indexlibrarymember{variant}{get_if}% +\begin{itemdecl} +template + constexpr add_pointer_t>> + get_if(variant* v) noexcept; +template + constexpr add_pointer_t>> + get_if(const variant* v) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\remarks -The exception specification is equivalent to -\tcode{is_nothrow_move_constructible_v \&\& is_nothrow_move_assignable_v}. +\mandates +$\tcode{I} < \tcode{sizeof...(Types)}$. \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}. +\returns +A pointer to the value stored in the \tcode{variant}, if \tcode{v != nullptr} +and \tcode{v->index() == I}. Otherwise, returns \keyword{nullptr}. \end{itemdescr} -\indexlibrarymember{operator=}{expected}% +\indexlibraryglobal{get_if}% +\indexlibrarymember{variant}{get_if}% \begin{itemdecl} -template - constexpr expected& operator=(const unexpected& e); -template - constexpr expected& operator=(unexpected&& e); +template + constexpr add_pointer_t + get_if(variant* v) noexcept; +template + constexpr add_pointer_t + get_if(const variant* v) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{GF} be \tcode{const G\&} for the first overload and -\tcode{G} for the second overload. +\mandates +The type \tcode{T} occurs exactly once in \tcode{Types}. \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true} and -\tcode{is_assignable_v} is \tcode{true}. +\effects +Equivalent to: \tcode{return get_if<$i$>(v);} with $i$ being the zero-based +index of \tcode{T} in \tcode{Types}. +\end{itemdescr} + +\rSec2[variant.relops]{Relational operators} +\indexlibrarymember{operator==}{variant}% +\begin{itemdecl} +template + constexpr bool operator==(const variant& v, const variant& w); +\end{itemdecl} + +\begin{itemdescr} \pnum -\effects -\begin{itemize} -\item -If \tcode{has_value()} is \tcode{true}, equivalent to: -\begin{codeblock} -construct_at(addressof(@\exposid{unex}@), std::forward(e.error())); -@\exposid{has_val}@ = false; -\end{codeblock} -\item -Otherwise, equivalent to: -\tcode{\exposid{unex} = std::forward(e.error());} -\end{itemize} +\constraints +\tcode{\exposid{GET}<$i$>(v) == \exposid{GET}<$i$>(w)} is a valid expression that is +convertible to \tcode{bool}, for all $i$. \pnum \returns -\tcode{*this}. +If \tcode{v.index() != w.index()}, \tcode{false}; +otherwise if \tcode{v.valueless_by_exception()}, \tcode{true}; +otherwise \tcode{\exposid{GET}<$i$>(v) == \exposid{GET}<$i$>(w)} with $i$ being \tcode{v.index()}. \end{itemdescr} -\indexlibrarymember{emplace}{expected}% +\indexlibrarymember{operator"!=}{variant}% \begin{itemdecl} -constexpr void emplace() noexcept; +template + constexpr bool operator!=(const variant& v, const variant& w); \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} +\constraints +\tcode{\exposid{GET}<$i$>(v) != \exposid{GET}<$i$>(w)} is a valid expression that is +convertible to \tcode{bool}, for all $i$. -\rSec3[expected.void.swap]{Swap} +\pnum +\returns +If \tcode{v.index() != w.index()}, \tcode{true}; +otherwise if \tcode{v.valueless_by_exception()}, \tcode{false}; +otherwise \tcode{\exposid{GET}<$i$>(v) != \exposid{GET}<$i$>(w)} with $i$ being \tcode{v.index()}. +\end{itemdescr} -\indexlibrarymember{swap}{expected}% +\indexlibrarymember{operator<}{variant}% \begin{itemdecl} -constexpr void swap(expected& rhs) noexcept(@\seebelow@); +template + constexpr bool operator<(const variant& v, const variant& w); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_swappable_v} is \tcode{true} and -\tcode{is_move_constructible_v} is \tcode{true}. +\tcode{\exposid{GET}<$i$>(v) < \exposid{GET}<$i$>(w)} is a valid expression that is +convertible to \tcode{bool}, for all $i$. \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{!this->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} +\returns +If \tcode{w.valueless_by_exception()}, \tcode{false}; +otherwise if \tcode{v.valueless_by_exception()}, \tcode{true}; +otherwise, if \tcode{v.index() < w.index()}, \tcode{true}; +otherwise if \tcode{v.index() > w.index()}, \tcode{false}; +otherwise \tcode{\exposid{GET}<$i$>(v) < \exposid{GET}<$i$>(w)} with $i$ being \tcode{v.index()}. +\end{itemdescr} -For the case where \tcode{rhs.has_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} +\indexlibrarymember{operator>}{variant}% +\begin{itemdecl} +template + constexpr bool operator>(const variant& v, const variant& w); +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -Any exception thrown by the expressions in the \Fundescx{Effects}. +\constraints +\tcode{\exposid{GET}<$i$>(v) > \exposid{GET}<$i$>(w)} is a valid expression that is +convertible to \tcode{bool}, for all $i$. \pnum -\remarks -The exception specification is equivalent to -\tcode{is_nothrow_move_constructible_v \&\& is_nothrow_swappable_v}. +\returns +If \tcode{v.valueless_by_exception()}, \tcode{false}; +otherwise if \tcode{w.valueless_by_exception()}, \tcode{true}; +otherwise, if \tcode{v.index() > w.index()}, \tcode{true}; +otherwise if \tcode{v.index() < w.index()}, \tcode{false}; +otherwise \tcode{\exposid{GET}<$i$>(v) > \exposid{GET}<$i$>(w)} with $i$ being \tcode{v.index()}. \end{itemdescr} -\indexlibrarymember{swap}{expected}% +\indexlibrarymember{operator<=}{variant}% \begin{itemdecl} -friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); +template + constexpr bool operator<=(const variant& v, const variant& w); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{x.swap(y)}. -\end{itemdescr} +\constraints +\tcode{\exposid{GET}<$i$>(v) <= \exposid{GET}<$i$>(w)} is a valid expression that is +convertible to \tcode{bool}, for all $i$. -\rSec3[expected.void.obs]{Observers} +\pnum +\returns +If \tcode{v.valueless_by_exception()}, \tcode{true}; +otherwise if \tcode{w.valueless_by_exception()}, \tcode{false}; +otherwise, if \tcode{v.index() < w.index()}, \tcode{true}; +otherwise if \tcode{v.index() > w.index()}, \tcode{false}; +otherwise \tcode{\exposid{GET}<$i$>(v) <= \exposid{GET}<$i$>(w)} with $i$ being \tcode{v.index()}. +\end{itemdescr} -\indexlibrarymember{operator bool}{expected}% -\indexlibrarymember{has_value}{expected}% +\indexlibrarymember{operator>=}{variant}% \begin{itemdecl} -constexpr explicit operator bool() const noexcept; -constexpr bool has_value() const noexcept; +template + constexpr bool operator>=(const variant& v, const variant& w); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{\exposid{GET}<$i$>(v) >= \exposid{GET}<$i$>(w)} is a valid expression that is +convertible to \tcode{bool}, for all $i$. + \pnum \returns -\exposid{has_val}. +If \tcode{w.valueless_by_exception()}, \tcode{true}; +otherwise if \tcode{v.valueless_by_exception()}, \tcode{false}; +otherwise, if \tcode{v.index() > w.index()}, \tcode{true}; +otherwise if \tcode{v.index() < w.index()}, \tcode{false}; +otherwise \tcode{\exposid{GET}<$i$>(v) >= \exposid{GET}<$i$>(w)} with $i$ being \tcode{v.index()}. \end{itemdescr} -\indexlibrarymember{operator*}{expected}% +\indexlibrarymember{operator<=>}{variant}% \begin{itemdecl} -constexpr void operator*() const noexcept; +template requires (@\libconcept{three_way_comparable}@ && ...) + constexpr common_comparison_category_t...> + operator<=>(const variant& v, const variant& w); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{has_value()} is \tcode{true}. +\effects +Equivalent to: +\begin{codeblock} +if (v.valueless_by_exception() && w.valueless_by_exception()) + return strong_ordering::equal; +if (v.valueless_by_exception()) return strong_ordering::less; +if (w.valueless_by_exception()) return strong_ordering::greater; +if (auto c = v.index() <=> w.index(); c != 0) return c; +return @\exposid{GET}@<@$i$@>(v) <=> @\exposid{GET}@<@$i$@>(w); +\end{codeblock} +with $i$ being \tcode{v.index()}. \end{itemdescr} -\indexlibrarymember{value}{expected}% +\rSec2[variant.visit]{Visitation} + +\indexlibraryglobal{visit}% +\indexlibrarymember{variant}{visit}% \begin{itemdecl} -constexpr void value() const &; +template + constexpr @\seebelow@ visit(Visitor&& vis, Variants&&... vars); +template + constexpr R visit(Visitor&& vis, Variants&&... vars); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{is_copy_constructible_v} is \tcode{true}. +Let \exposid{as-variant} denote the following exposition-only function templates: +\begin{codeblock} +template + constexpr auto&& @\exposid{as-variant}@(variant& var) { return var; } +template + constexpr auto&& @\exposid{as-variant}@(const variant& var) { return var; } +template + constexpr auto&& @\exposid{as-variant}@(variant&& var) { return std::move(var); } +template + constexpr auto&& @\exposid{as-variant}@(const variant&& var) { return std::move(var); } +\end{codeblock} +Let $n$ be \tcode{sizeof...(Variants)}. +For each $0 \leq i < n$, let +$\tcode{V}_i$ denote the type\newline +\tcode{decltype(\exposid{as-variant}(\tcode{std::forward<$\tcode{Variants}_i$>($\tcode{vars}_i$)}))}. \pnum -\throws -\tcode{bad_expected_access(error())} if \tcode{has_value()} is \tcode{false}. -\end{itemdescr} +\constraints +$\tcode{V}_i$ is a valid type for all $0 \leq i < n$. -\indexlibrarymember{value}{expected}% -\begin{itemdecl} -constexpr void value() &&; -\end{itemdecl} +\pnum +Let \tcode{V} denote the pack of types $\tcode{V}_i$. + +\pnum +Let $m$ be a pack of $n$ values of type \tcode{size_t}. +Such a pack is valid if\newline +$0 \leq m_i < \tcode{variant_size_v>}$ +for all $0 \leq i < n$. +For each valid pack $m$, let $e(m)$ denote the expression: +\begin{codeblock} +@\placeholder{INVOKE}@(std::forward(vis), @\exposid{GET}@<@$m$@>(std::forward(vars))...) // see \ref{func.require} +\end{codeblock} +for the first form and +\begin{codeblock} +@\placeholder{INVOKE}@(std::forward(vis), @\exposid{GET}@<@$m$@>(std::forward(vars))...) // see \ref{func.require} +\end{codeblock} +for the second form. -\begin{itemdescr} \pnum \mandates -\tcode{is_copy_constructible_v} is \tcode{true} and -\tcode{is_move_constructible_v} is \tcode{true}. +For each valid pack $m$, $e(m)$ is a valid expression. +All such expressions are of the same type and value category. + +\pnum +\returns +$e(m)$, where $m$ is the pack for which +$m_i$ is \tcode{\exposid{as-variant}(vars$_i$).index()} for all $0 \leq i < n$. +The return type is $\tcode{decltype(}e(m)\tcode{)}$ +for the first form. \pnum \throws -\tcode{bad_expected_access(std::move(error()))} -if \tcode{has_value()} is \tcode{false}. +\tcode{bad_variant_access} if +\tcode{(\exposid{as-variant}(vars).valueless_by_exception() || ...)} +is \tcode{true}. + +\pnum +\complexity +For $n \leq 1$, the invocation of the callable object is +implemented in constant time, i.e., for $n = 1$, it does not depend on +the number of alternative types of $\tcode{V}_0$. +For $n > 1$, the invocation of the callable object has +no complexity requirements. \end{itemdescr} -\indexlibrarymember{error}{expected}% +\indexlibrarymember{visit}{variant}% \begin{itemdecl} -constexpr const E& error() const & noexcept; -constexpr E& error() & noexcept; +template + constexpr decltype(auto) visit(this Self&& self, Visitor&& vis); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{has_value()} is \tcode{false}. +Let \tcode{V} be +\tcode{\exposid{OVERRIDE_REF}(Self\&\&, \exposid{COPY_CONST}(remove_reference_t, variant))}\iref{forward}. \pnum -\returns -\exposid{unex}. +\constraints +The call to \tcode{visit} does not use +an explicit \grammarterm{template-argument-list} that +begins with a type \grammarterm{template-argument}. + +\pnum +\effects +Equivalent to: \tcode{return std::visit(std::forward(vis), (V)self);} \end{itemdescr} -\indexlibrarymember{error}{expected}% +\indexlibrarymember{visit}{variant}% \begin{itemdecl} -constexpr E&& error() && noexcept; -constexpr const E&& error() const && noexcept; +template + constexpr R visit(this Self&& self, Visitor&& vis); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{has_value()} is \tcode{false}. +Let \tcode{V} be +\tcode{\exposid{OVERRIDE_REF}(Self\&\&, \exposid{COPY_CONST}(remove_reference_t, variant))}\iref{forward}. \pnum -\returns -\tcode{std::move(\exposid{unex})}. +\effects +Equivalent to: \tcode{return std::visit(std::forward(vis), (V)self);} \end{itemdescr} -\indexlibrarymember{error_or}{expected}% +\rSec2[variant.monostate]{Class \tcode{monostate}}% +\indexlibraryglobal{monostate}% + \begin{itemdecl} -template constexpr E error_or(G&& e) const &; +struct monostate{}; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{is_copy_constructible_v} is \tcode{true} and -\tcode{is_convertible_v} is \tcode{true}. - -\pnum -\returns -\tcode{std::forward(e)} if \tcode{has_value()} is \tcode{true}, -\tcode{error()} otherwise. +The class \tcode{monostate} can serve as a first alternative type for +a \tcode{variant} to make the \tcode{variant} type default constructible. \end{itemdescr} -\indexlibrarymember{error_or}{expected}% + +\rSec2[variant.monostate.relops]{\tcode{monostate} relational operators} + +\indexlibrarymember{operator==}{monostate}% +\indexlibrarymember{operator<=>}{monostate}% \begin{itemdecl} -template constexpr E error_or(G&& e) &&; +constexpr bool operator==(monostate, monostate) noexcept { return true; } +constexpr strong_ordering operator<=>(monostate, monostate) noexcept +{ return strong_ordering::equal; } \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{is_move_constructible_v} is \tcode{true} and -\tcode{is_convertible_v} is \tcode{true}. - -\pnum -\returns -\tcode{std::forward(e)} if \tcode{has_value()} is \tcode{true}, -\tcode{std::move(error())} otherwise. +\begin{note} +\tcode{monostate} objects have only a single state; they thus always compare equal. +\end{note} \end{itemdescr} -\rSec3[expected.void.monadic]{Monadic operations} +\rSec2[variant.specalg]{Specialized algorithms} -\indexlibrarymember{and_then}{expected}% +\indexlibrarymember{swap}{variant}% \begin{itemdecl} -template constexpr auto and_then(F&& f) &; -template constexpr auto and_then(F&& f) const &; +template + constexpr void swap(variant& v, variant& w) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{U} be \tcode{remove_cvref_t>}. - \pnum \constraints -\tcode{is_constructible_v>} is \tcode{true}. +\tcode{is_move_constructible_v<$\tcode{T}_i$> \&\& is_swappable_v<$\tcode{T}_i$>} +is \tcode{true} for all $i$. \pnum -\mandates -\tcode{U} is a specialization of \tcode{expected} and -\tcode{is_same_v} is \tcode{true}. +\effects +Equivalent to \tcode{v.swap(w)}. \pnum -\effects -Equivalent to: +\remarks +The exception specification is equivalent to \tcode{noexcept(v.swap(w))}. +\end{itemdescr} + +\rSec2[variant.bad.access]{Class \tcode{bad_variant_access}}% +\indexlibraryglobal{bad_variant_access}% + \begin{codeblock} -if (has_value()) - return invoke(std::forward(f)); -else - return U(unexpect, error()); +namespace std { + class bad_variant_access : public exception { + public: + // see \ref{exception} for the specification of the special member functions + constexpr const char* what() const noexcept override; + }; +} \end{codeblock} -\end{itemdescr} -\indexlibrarymember{and_then}{expected}% +\pnum +Objects of type \tcode{bad_variant_access} are thrown to report invalid +accesses to the value of a \tcode{variant} object. + +\indexlibrarymember{what}{bad_variant_access}% \begin{itemdecl} -template constexpr auto and_then(F&& f) &&; -template constexpr auto and_then(F&& f) const &&; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{U} be \tcode{remove_cvref_t>}. +\returns +An \impldef{return value of \tcode{bad_variant_access::what}} \ntbs{}, +which during constant evaluation is encoded with +the ordinary literal encoding\iref{lex.ccon}. +\end{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\rSec2[variant.hash]{Hash support} -\pnum -\mandates -\tcode{U} is a specialization of \tcode{expected} and -\tcode{is_same_v} is \tcode{true}. +\indexlibrarymember{hash}{variant}% +\begin{itemdecl} +template struct hash>; +\end{itemdecl} +\begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -if (has_value()) - return invoke(std::forward(f)); -else - return U(unexpect, std::move(error())); -\end{codeblock} +The specialization \tcode{hash>} is enabled\iref{unord.hash} +if and only if every specialization in \tcode{hash>...} is enabled. +The member functions are not guaranteed to be \keyword{noexcept}. \end{itemdescr} -\indexlibrarymember{or_else}{expected}% +\indexlibrarymember{hash}{monostate}% \begin{itemdecl} -template constexpr auto or_else(F&& f) &; -template constexpr auto or_else(F&& f) const &; +template<> struct hash; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{G} be \tcode{remove_cvref_t>}. +The specialization is enabled\iref{unord.hash}. +\end{itemdescr} + + +\rSec1[any]{Storage for any type} + +\rSec2[any.general]{General} \pnum -\mandates -\tcode{G} is a specialization of \tcode{expected} and -\tcode{is_same_v} is \tcode{true}. +Subclause \ref{any} describes components that \Cpp{} programs may use to perform operations on objects of a discriminated type. \pnum -\effects -Equivalent to: +\begin{note} +The discriminated type can contain values of different types but does not attempt conversion between them, +i.e., \tcode{5} is held strictly as an \tcode{int} and is not implicitly convertible either to \tcode{"5"} or to \tcode{5.0}. +This indifference to interpretation but awareness of type effectively allows safe, generic containers of single values, with no scope for surprises from ambiguous conversions. +\end{note} + +\rSec2[any.synop]{Header \tcode{} synopsis} + +\indexheader{any}% + \begin{codeblock} -if (has_value()) - return G(); -else - return invoke(std::forward(f), error()); -\end{codeblock} -\end{itemdescr} +namespace std { + // \ref{any.bad.any.cast}, class \tcode{bad_any_cast} + class bad_any_cast; -\indexlibrarymember{or_else}{expected}% -\begin{itemdecl} -template constexpr auto or_else(F&& f) &&; -template constexpr auto or_else(F&& f) const &&; -\end{itemdecl} + // \ref{any.class}, class \tcode{any} + class any; -\begin{itemdescr} -\pnum -Let \tcode{G} be -\tcode{remove_cvref_t>}. + // \ref{any.nonmembers}, non-member functions + void swap(any& x, any& y) noexcept; -\pnum -\mandates -\tcode{G} is a specialization of \tcode{expected} and -\tcode{is_same_v} is \tcode{true}. + template + any make_any(Args&&... args); + template + any make_any(initializer_list il, Args&&... args); + + template + T any_cast(const any& operand); + template + T any_cast(any& operand); + template + T any_cast(any&& operand); + + template + const T* any_cast(const any* operand) noexcept; + template + T* any_cast(any* operand) noexcept; +} +\end{codeblock} + +\rSec2[any.bad.any.cast]{Class \tcode{bad_any_cast}} + +\indexlibraryglobal{bad_any_cast}% +\begin{codeblock} +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 -\effects -Equivalent to: -\begin{codeblock} -if (has_value()) - return G(); -else - return invoke(std::forward(f), std::move(error())); -\end{codeblock} -\end{itemdescr} +Objects of type \tcode{bad_any_cast} are thrown by a failed \tcode{any_cast}\iref{any.nonmembers}. -\indexlibrarymember{transform}{expected}% +\indexlibrarymember{what}{bad_any_cast}% \begin{itemdecl} -template constexpr auto transform(F&& f) &; -template constexpr auto transform(F&& f) const &; +const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{U} be \tcode{remove_cv_t>}. +\returns +An \impldef{return value of \tcode{bad_any_cast::what}} \ntbs{}. +\end{itemdescr} -\pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +\rSec2[any.class]{Class \tcode{any}} + +\rSec3[any.class.general]{General} -\pnum -\mandates -\tcode{U} is a valid value type for \tcode{expected}. If \tcode{is_void_v} is -\tcode{false}, the declaration \begin{codeblock} -U u(invoke(std::forward(f))); -\end{codeblock} -is well-formed. +namespace std { + class any { + public: + // \ref{any.cons}, construction and destruction + constexpr any() noexcept; -\pnum -\effects -\begin{itemize} -\item -If \tcode{has_value()} is \tcode{false}, returns -\tcode{expected(unexpect, error())}. -\item -Otherwise, if \tcode{is_void_v} is \tcode{false}, returns an -\tcode{expected} object whose \exposid{has_val} member is \tcode{true} and -\exposid{val} member is direct-non-list-initialized with -\tcode{invoke(std::forward(f))}. -\item -Otherwise, evaluates \tcode{invoke(std::forward(f))} and then returns -\tcode{expected()}. -\end{itemize} -\end{itemdescr} + any(const any& other); + any(any&& other) noexcept; -\indexlibrarymember{transform}{expected}% -\begin{itemdecl} -template constexpr auto transform(F&& f) &&; -template constexpr auto transform(F&& f) const &&; -\end{itemdecl} + template + any(T&& value); -\begin{itemdescr} -\pnum -Let \tcode{U} be \tcode{remove_cv_t>}. + template + explicit any(in_place_type_t, Args&&...); + template + explicit any(in_place_type_t, initializer_list, Args&&...); + + ~any(); + + // \ref{any.assign}, assignments + any& operator=(const any& rhs); + any& operator=(any&& rhs) noexcept; + + template + any& operator=(T&& rhs); + + // \ref{any.modifiers}, modifiers + template + decay_t& emplace(Args&&...); + template + decay_t& emplace(initializer_list, Args&&...); + void reset() noexcept; + void swap(any& rhs) noexcept; + + // \ref{any.observers}, observers + bool has_value() const noexcept; + const type_info& type() const noexcept; + }; +} +\end{codeblock} \pnum -\constraints -\tcode{is_constructible_v} is \tcode{true}. +An object of class \tcode{any} stores an instance of any type that meets the constructor requirements or it has no value, +and this is referred to as the \defn{state} of the class \tcode{any} object. +The stored instance is called the \defnx{contained value}{contained value!\idxcode{any}}. +Two states are equivalent if either they both have no value, or they both have a value and the contained values are equivalent. \pnum -\mandates -\tcode{U} is a valid value type for \tcode{expected}. If \tcode{is_void_v} is -\tcode{false}, the declaration -\begin{codeblock} -U u(invoke(std::forward(f))); -\end{codeblock} -is well-formed. +The non-member \tcode{any_cast} functions provide type-safe access to the contained value. \pnum -\effects -\begin{itemize} -\item -If \tcode{has_value()} is \tcode{false}, returns -\tcode{expected(unexpect, std::move(error()))}. -\item -Otherwise, if \tcode{is_void_v} is \tcode{false}, returns an -\tcode{expected} object whose \exposid{has_val} member is \tcode{true} and -\exposid{val} member is direct-non-list-initialized with -\tcode{invoke(std::forward(f))}. -\item -Otherwise, evaluates \tcode{invoke(std::forward(f))} and then returns -\tcode{expected()}. -\end{itemize} -\end{itemdescr} +Implementations should avoid the use of dynamically allocated memory for a small contained value. +However, any such small-object optimization shall only be applied to types \tcode{T} for which +\tcode{is_nothrow_move_constructible_v} is \tcode{true}. +\begin{example} +A contained value of type \tcode{int} could be stored in an internal buffer, +not in separately-allocated memory. +\end{example} -\indexlibrarymember{transform_error}{expected}% +\rSec3[any.cons]{Construction and destruction} + +\indexlibraryctor{any}% \begin{itemdecl} -template constexpr auto transform_error(F&& f) &; -template constexpr auto transform_error(F&& f) const &; +constexpr any() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{G} be \tcode{remove_cv_t>}. - -\pnum -\mandates -\tcode{G} is a valid template argument -for \tcode{unexpected}\iref{expected.un.general} and the declaration -\begin{codeblock} -G g(invoke(std::forward(f), error())); -\end{codeblock} -is well-formed. - -\pnum -\returns -If \tcode{has_value()} is \tcode{true}, \tcode{expected()}; otherwise, an -\tcode{expected} object whose \exposid{has_val} member is \tcode{false} -and \exposid{unex} member is direct-non-list-initialized with -\tcode{invoke(std::for\-ward(f), error())}. +\ensures +\tcode{has_value()} is \tcode{false}. \end{itemdescr} -\indexlibrarymember{transform_error}{expected}% +\indexlibraryctor{any}% \begin{itemdecl} -template constexpr auto transform_error(F&& f) &&; -template constexpr auto transform_error(F&& f) const &&; +any(const any& other); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{G} be -\tcode{remove_cv_t>}. - -\pnum -\mandates -\tcode{G} is a valid template argument -for \tcode{unexpected}\iref{expected.un.general} and the declaration -\begin{codeblock} -G g(invoke(std::forward(f), std::move(error()))); -\end{codeblock} -is well-formed. +\effects +If \tcode{other.has_value()} is \tcode{false}, constructs an object that has no value. +Otherwise, equivalent to \tcode{any(in_place_type, any_cast(other))} +where \tcode{T} is the type of the contained value. \pnum -\returns -If \tcode{has_value()} is \tcode{true}, \tcode{expected()}; otherwise, an -\tcode{expected} object whose \exposid{has_val} member is \tcode{false} -and \exposid{unex} member is direct-non-list-initialized with -\tcode{invoke(std::for\-ward(f), std::move(error()))}. +\throws +Any exceptions arising from calling the selected constructor for the contained value. \end{itemdescr} -\rSec3[expected.void.eq]{Equality operators} - -\indexlibrarymember{operator==}{expected}% +\indexlibraryctor{any}% \begin{itemdecl} -template requires is_void_v - friend constexpr bool operator==(const expected& x, const expected& y); +any(any&& other) noexcept; \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())}. +\effects +If \tcode{other.has_value()} is \tcode{false}, constructs an object that has no value. +Otherwise, constructs an object of type \tcode{any} that +contains either the contained value of \tcode{other}, or +contains an object of the same type constructed from +the contained value of \tcode{other} considering that contained value as an rvalue. \end{itemdescr} -\indexlibrarymember{operator==}{expected}% +\indexlibraryctor{any}% \begin{itemdecl} -template - friend constexpr bool operator==(const expected& x, const unexpected& e); +template + any(T&& value); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The expression \tcode{x.error() == e.error()} is well-formed and -its result is convertible to \tcode{bool}. +Let \tcode{VT} be \tcode{decay_t}. \pnum -\returns -\tcode{!x.has_value() \&\& static_cast(x.error() == e.error())}. -\end{itemdescr} - -\rSec1[bitset]{Bitsets} -\indexlibraryglobal{bitset}% - -\rSec2[bitset.syn]{Header \tcode{} synopsis}% +\constraints +\tcode{VT} is not the same type as \tcode{any}, +\tcode{VT} is not a specialization of \tcode{in_place_type_t}, +and \tcode{is_copy_constructible_v} is \tcode{true}. \pnum -The header \libheaderdef{bitset} defines a class template -and several related functions for representing -and manipulating fixed-size sequences of bits. - -\begin{codeblock} -#include // see \ref{string.syn} -#include // for \tcode{istream}\iref{istream.syn}, \tcode{ostream}\iref{ostream.syn}, see \ref{iosfwd.syn} +\expects +\tcode{VT} meets the \oldconcept{CopyConstructible} requirements. -namespace std { - template class bitset; +\pnum +\effects +Constructs an object of type \tcode{any} that contains an object of type \tcode{VT} direct-initialized with \tcode{std::forward(value)}. - // \ref{bitset.operators}, bitset operators - template - constexpr bitset operator&(const bitset&, const bitset&) noexcept; - template - constexpr bitset operator|(const bitset&, const bitset&) noexcept; - template - constexpr bitset operator^(const bitset&, const bitset&) noexcept; - template - basic_istream& - operator>>(basic_istream& is, bitset& x); - template - basic_ostream& - operator<<(basic_ostream& os, const bitset& x); -} -\end{codeblock} +\pnum +\throws +Any exception thrown by the selected constructor of \tcode{VT}. +\end{itemdescr} -\rSec2[template.bitset]{Class template \tcode{bitset}}% +\indexlibraryctor{any}% +\begin{itemdecl} +template + explicit any(in_place_type_t, Args&&... args); +\end{itemdecl} -\rSec3[template.bitset.general]{General}% -\indexlibraryglobal{bitset}% -\begin{codeblock} -namespace std { - template class bitset { - public: - // bit reference - class reference { - friend class bitset; - constexpr reference() noexcept; +\begin{itemdescr} +\pnum +Let \tcode{VT} be \tcode{decay_t}. - public: - constexpr reference(const reference&) = default; - constexpr ~reference(); - constexpr reference& operator=(bool x) noexcept; // for \tcode{b[i] = x;} - constexpr reference& operator=(const reference&) noexcept; // for \tcode{b[i] = b[j];} - constexpr bool operator~() const noexcept; // flips the bit - constexpr operator bool() const noexcept; // for \tcode{x = b[i];} - constexpr reference& flip() noexcept; // for \tcode{b[i].flip();} - }; +\pnum +\constraints +\tcode{is_copy_constructible_v} is \tcode{true} and +\tcode{is_constructible_v} is \tcode{true}. - // \ref{bitset.cons}, constructors - constexpr bitset() noexcept; - constexpr bitset(unsigned long long val) noexcept; - template - constexpr explicit bitset( - const basic_string& str, - typename basic_string::size_type pos = 0, - typename basic_string::size_type n - = basic_string::npos, - charT zero = charT('0'), - charT one = charT('1')); - template - constexpr explicit bitset( - basic_string_view str, - typename basic_string_view::size_type pos = 0, - typename basic_string_view::size_type n - = basic_string_view::npos, - charT zero = charT('0'), - charT one = charT('1')); - template - constexpr explicit bitset( - const charT* str, - typename basic_string_view::size_type n = basic_string_view::npos, - charT zero = charT('0'), - charT one = charT('1')); +\pnum +\expects +\tcode{VT} meets the \oldconcept{CopyConstructible} requirements. - // \ref{bitset.members}, bitset operations - constexpr bitset& operator&=(const bitset& rhs) noexcept; - constexpr bitset& operator|=(const bitset& rhs) noexcept; - constexpr bitset& operator^=(const bitset& rhs) noexcept; - constexpr bitset& operator<<=(size_t pos) noexcept; - constexpr bitset& operator>>=(size_t pos) noexcept; - constexpr bitset operator<<(size_t pos) const noexcept; - constexpr bitset operator>>(size_t pos) const noexcept; - constexpr bitset& set() noexcept; - constexpr bitset& set(size_t pos, bool val = true); - constexpr bitset& reset() noexcept; - constexpr bitset& reset(size_t pos); - constexpr bitset operator~() const noexcept; - constexpr bitset& flip() noexcept; - constexpr bitset& flip(size_t pos); +\pnum +\effects +Direct-non-list-initializes the contained value of type \tcode{VT} +with \tcode{std::forward(args)...}. - // element access - constexpr bool operator[](size_t pos) const; - constexpr reference operator[](size_t pos); +\pnum +\ensures +\tcode{*this} contains a value of type \tcode{VT}. - constexpr unsigned long to_ulong() const; - constexpr unsigned long long to_ullong() const; - template, - class Allocator = allocator> - constexpr basic_string - to_string(charT zero = charT('0'), charT one = charT('1')) const; +\pnum +\throws +Any exception thrown by the selected constructor of \tcode{VT}. +\end{itemdescr} - // observers - constexpr size_t count() const noexcept; - constexpr size_t size() const noexcept; - constexpr bool operator==(const bitset& rhs) const noexcept; - constexpr bool test(size_t pos) const; - constexpr bool all() const noexcept; - constexpr bool any() const noexcept; - constexpr bool none() const noexcept; - }; +\indexlibraryctor{any}% +\begin{itemdecl} +template + explicit any(in_place_type_t, initializer_list il, Args&&... args); +\end{itemdecl} - // \ref{bitset.hash}, hash support - template struct hash; - template struct hash>; -} -\end{codeblock} +\begin{itemdescr} +\pnum +Let \tcode{VT} be \tcode{decay_t}. \pnum -The class template -\tcode{bitset} -describes an object that can store a sequence consisting of a fixed number of -bits, \tcode{N}. +\constraints +\tcode{is_copy_constructible_v} is \tcode{true} and +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. \pnum -Each bit represents either the value zero (reset) or one (set). -To -\term{toggle} -a bit is to change the value zero to one, or the value one to -zero. -Each bit has a non-negative position \tcode{pos}. -When converting -between an object of class -\tcode{bitset} -and a value of some -integral type, bit position \tcode{pos} corresponds to the -\term{bit value} -\tcode{1 << pos}. -The integral value corresponding to two -or more bits is the sum of their bit values. +\expects +\tcode{VT} meets the \oldconcept{CopyConstructible} requirements. \pnum -The functions described in \ref{template.bitset} can report three kinds of -errors, each associated with a distinct exception: -\begin{itemize} -\item -an -\term{invalid-argument} -error is associated with exceptions of type -\tcode{invalid_argument}\iref{invalid.argument}; -\indexlibraryglobal{invalid_argument}% -\item -an -\term{out-of-range} -error is associated with exceptions of type -\tcode{out_of_range}\iref{out.of.range}; -\indexlibraryglobal{out_of_range}% -\item -an -\term{overflow} -error is associated with exceptions of type -\tcode{overflow_error}\iref{overflow.error}. -\indexlibraryglobal{overflow_error}% -\end{itemize} +\effects +Direct-non-list-initializes the contained value of type \tcode{VT} +with \tcode{il, std::forward(\brk{}args)...}. -\rSec3[bitset.cons]{Constructors} +\pnum +\ensures +\tcode{*this} contains a value. -\indexlibraryctor{bitset}% +\pnum +\throws +Any exception thrown by the selected constructor of \tcode{VT}. +\end{itemdescr} + +\indexlibrarydtor{any} \begin{itemdecl} -constexpr bitset() noexcept; +~any(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Initializes all bits in \tcode{*this} to zero. +As if by \tcode{reset()}. \end{itemdescr} -\indexlibraryctor{bitset}% +\rSec3[any.assign]{Assignment} + +\indexlibrarymember{operator=}{any}% \begin{itemdecl} -constexpr bitset(unsigned long long val) noexcept; +any& operator=(const any& rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects -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{term.object.representation} of \tcode{unsigned long long}. -If \tcode{M < N}, the remaining bit positions are initialized to zero. +As if by \tcode{any(rhs).swap(*this)}. +No effects if an exception is thrown. + +\pnum +\returns +\tcode{*this}. + +\pnum +\throws +Any exceptions arising from the copy constructor for the contained value. \end{itemdescr} -\indexlibraryctor{bitset}% +\indexlibrarymember{operator=}{any}% \begin{itemdecl} -template - constexpr explicit bitset( - const basic_string& str, - typename basic_string::size_type pos = 0, - typename basic_string::size_type n - = basic_string::npos, - charT zero = charT('0'), - charT one = charT('1')); -template - constexpr explicit bitset( - basic_string_view str, - typename basic_string_view::size_type pos = 0, - typename basic_string_view::size_type n - = basic_string_view::npos, - charT zero = charT('0'), - charT one = charT('1')); +any& operator=(any&& rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Determines the effective length -\tcode{rlen} of the initializing string as the smaller of -\tcode{n} and -\tcode{str.size() - pos}. -Initializes the first \tcode{M} bit -positions to values determined from the corresponding characters in the string -\tcode{str}. -\tcode{M} is the smaller of \tcode{N} and \tcode{rlen}. +As if by \tcode{any(std::move(rhs)).swap(*this)}. + +\pnum +\ensures +The state of \tcode{*this} is equivalent to the original state of \tcode{rhs}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\indexlibrarymember{operator=}{any}% +\begin{itemdecl} +template + any& operator=(T&& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{VT} be \tcode{decay_t}. + +\pnum +\constraints +\tcode{VT} is not the same type as \tcode{any} and +\tcode{is_copy_constructible_v} is \tcode{true}. \pnum -An element of the constructed object has value zero if the -corresponding character in \tcode{str}, beginning at position -\tcode{pos}, is -\tcode{zero}. -Otherwise, the element has the value one. -Character position \tcode{pos + M - 1} corresponds to bit position zero. -Subsequent decreasing character positions correspond to increasing bit positions. +\expects +\tcode{VT} meets the \oldconcept{CopyConstructible} requirements. \pnum -If \tcode{M < N}, remaining bit positions are initialized to zero. +\effects +Constructs an object \tcode{tmp} of type \tcode{any} that contains an object of type \tcode{VT} direct-initialized with \tcode{std::forward(rhs)}, and \tcode{tmp.swap(*this)}. +No effects if an exception is thrown. \pnum -The function uses \tcode{traits::eq} -to compare the character values. +\returns +\tcode{*this}. \pnum \throws -\indexlibraryglobal{out_of_range}% -\tcode{out_of_range} if \tcode{pos > str.size()} or -\indexlibraryglobal{invalid_argument}% -\tcode{invalid_argument} if any of -the \tcode{rlen} characters in \tcode{str} -beginning at position \tcode{pos} -is other than \tcode{zero} or \tcode{one}. +Any exception thrown by the selected constructor of \tcode{VT}. \end{itemdescr} -\indexlibraryctor{bitset}% +\rSec3[any.modifiers]{Modifiers} + +\indexlibrarymember{emplace}{any}% \begin{itemdecl} -template - constexpr explicit bitset( - const charT* str, - typename basic_string_view::size_type n = basic_string_view::npos, - charT zero = charT('0'), - charT one = charT('1')); +template + decay_t& emplace(Args&&... args); \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{VT} be \tcode{decay_t}. + +\pnum +\constraints +\tcode{is_copy_constructible_v} is \tcode{true} and +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\expects +\tcode{VT} meets the \oldconcept{CopyConstructible} requirements. + \pnum \effects -As if by: -\begin{codeblock} -bitset(n == basic_string_view::npos - ? basic_string_view(str) - : basic_string_view(str, n), - 0, n, zero, one) -\end{codeblock} -\end{itemdescr} +Calls \tcode{reset()}. +Then direct-non-list-initializes the contained value of type \tcode{VT} +with \tcode{std::for\-ward(args)...}. +\pnum +\ensures +\tcode{*this} contains a value. -\rSec3[bitset.members]{Members} +\pnum +\returns +A reference to the new contained value. -\indexlibrarymember{operator\&=}{bitset}% +\pnum +\throws +Any exception thrown by the selected constructor of \tcode{VT}. + +\pnum +\remarks +If an exception is thrown during the call to \tcode{VT}'s constructor, +\tcode{*this} does not contain a value, and any previously contained value +has been destroyed. +\end{itemdescr} + +\indexlibrarymember{emplace}{any}% \begin{itemdecl} -constexpr bitset& operator&=(const bitset& rhs) noexcept; +template + decay_t& emplace(initializer_list il, Args&&... args); \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{VT} be \tcode{decay_t}. + +\pnum +\constraints +\tcode{is_copy_constructible_v} is \tcode{true} and +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. + +\pnum +\expects +\tcode{VT} meets the \oldconcept{CopyConstructible} requirements. + \pnum \effects -Clears each bit in -\tcode{*this} -for which the corresponding bit in \tcode{rhs} is clear, and leaves all other bits unchanged. +Calls \tcode{reset()}. Then direct-non-list-initializes the contained value +of type \tcode{VT} with \tcode{il, std::forward(args)...}. + +\pnum +\ensures +\tcode{*this} contains a value. \pnum \returns -\tcode{*this}. +A reference to the new contained value. + +\pnum +\throws +Any exception thrown by the selected constructor of \tcode{VT}. + +\pnum +\remarks +If an exception is thrown during the call to \tcode{VT}'s constructor, +\tcode{*this} does not contain a value, and any previously contained value +has been destroyed. \end{itemdescr} -\indexlibrarymember{operator"|=}{bitset}% +\indexlibrarymember{reset}{any}% \begin{itemdecl} -constexpr bitset& operator|=(const bitset& rhs) noexcept; +void reset() noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Sets each bit in -\tcode{*this} -for which the corresponding bit in \tcode{rhs} is set, and leaves all other bits unchanged. +If \tcode{has_value()} is \tcode{true}, destroys the contained value. \pnum -\returns -\tcode{*this}. +\ensures +\tcode{has_value()} is \tcode{false}. \end{itemdescr} -\indexlibrarymember{operator\caret=}{bitset}% +\indexlibrarymember{swap}{any}% \begin{itemdecl} -constexpr bitset& operator^=(const bitset& rhs) noexcept; +void swap(any& rhs) noexcept; \end{itemdecl} \begin{itemdescr} + \pnum \effects -Toggles each bit in -\tcode{*this} -for which the corresponding bit in \tcode{rhs} is set, and leaves all other bits unchanged. +Exchanges the states of \tcode{*this} and \tcode{rhs}. +\end{itemdescr} + +\rSec3[any.observers]{Observers} + +\indexlibrarymember{has_value}{any}% +\begin{itemdecl} +bool has_value() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{*this}. +\tcode{true} if \tcode{*this} contains an object, otherwise \tcode{false}. \end{itemdescr} -\indexlibrarymember{operator<<=}{bitset}% +\indexlibrarymember{type}{any}% \begin{itemdecl} -constexpr bitset& operator<<=(size_t pos) noexcept; +const type_info& type() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Replaces each bit at position \tcode{I} in -\tcode{*this} -with a value determined as follows: - -\begin{itemize} -\item -If \tcode{I < pos}, the new value is zero; -\item -If \tcode{I >= pos}, the new value is the previous -value of the bit at position \tcode{I - pos}. -\end{itemize} +\returns +\tcode{typeid(T)} if \tcode{*this} has a contained value of type \tcode{T}, +otherwise \tcode{typeid(void)}. \pnum -\returns -\tcode{*this}. +\begin{note} +Useful for querying against types known either at compile time or only at runtime. +\end{note} \end{itemdescr} -\indexlibrarymember{operator>>=}{bitset}% +\rSec2[any.nonmembers]{Non-member functions} + +\indexlibrarymember{swap}{any}% \begin{itemdecl} -constexpr bitset& operator>>=(size_t pos) noexcept; +void swap(any& x, any& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Replaces each bit at position \tcode{I} in -\tcode{*this} -with a value determined as follows: +Equivalent to \tcode{x.swap(y)}. +\end{itemdescr} -\begin{itemize} -\item -If \tcode{pos >= N - I}, the new value is zero; -\item -If \tcode{pos < N - I}, the new value is the previous value of the bit at position \tcode{I + pos}. -\end{itemize} +\indexlibraryglobal{make_any}% +\begin{itemdecl} +template + any make_any(Args&&... args); +\end{itemdecl} +\begin{itemdescr} \pnum -\returns -\tcode{*this}. +\effects +Equivalent to: \tcode{return any(in_place_type, std::forward(args)...);} \end{itemdescr} -\indexlibrarymember{operator<<}{bitset}% +\indexlibraryglobal{make_any}% \begin{itemdecl} -constexpr bitset operator<<(size_t pos) const noexcept; +template + any make_any(initializer_list il, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{bitset(*this) <<= pos}. +\effects +Equivalent to: \tcode{return any(in_place_type, il, std::forward(args)...);} \end{itemdescr} -\indexlibrarymember{operator>>}{bitset}% +\indexlibraryglobal{any_cast}% \begin{itemdecl} -constexpr bitset operator>>(size_t pos) const noexcept; +template + T any_cast(const any& operand); +template + T any_cast(any& operand); +template + T any_cast(any&& operand); \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{U} be the type \tcode{remove_cvref_t}. + +\pnum +\mandates +For the first overload, \tcode{is_constructible_v} is \tcode{true}. +For the second overload, \tcode{is_constructible_v} is \tcode{true}. +For the third overload, \tcode{is_constructible_v} is \tcode{true}. + \pnum \returns -\tcode{bitset(*this) >>= pos}. -\end{itemdescr} +For the first and second overload, \tcode{static_cast(*any_cast(\&operand))}. +For the third overload, \tcode{static_cast(std::move(*any_cast(\&operand)))}. -% Do not use \indexlibrarymember. -\indexlibrary{\idxcode{set} (member)!\idxcode{bitset}}% -\indexlibrary{\idxcode{bitset}!\idxcode{set}}% -\begin{itemdecl} -constexpr bitset& set() noexcept; -\end{itemdecl} +\pnum +\throws +\tcode{bad_any_cast} if \tcode{operand.type() != typeid(remove_reference_t)}. + +\pnum +\begin{example} +\begin{codeblock} +any x(5); // \tcode{x} holds \tcode{int} +assert(any_cast(x) == 5); // cast to value +any_cast(x) = 10; // cast to reference +assert(any_cast(x) == 10); + +x = "Meow"; // \tcode{x} holds \tcode{const char*} +assert(strcmp(any_cast(x), "Meow") == 0); +any_cast(x) = "Harry"; +assert(strcmp(any_cast(x), "Harry") == 0); + +x = string("Meow"); // \tcode{x} holds \tcode{string} +string s, s2("Jane"); +s = move(any_cast(x)); // move from \tcode{any} +assert(s == "Meow"); +any_cast(x) = move(s2); // move to \tcode{any} +assert(any_cast(x) == "Jane"); -\begin{itemdescr} -\pnum -\effects -Sets all bits in -\tcode{*this}. +string cat("Meow"); +const any y(cat); // \tcode{const y} holds \tcode{string} +assert(any_cast(y) == cat); -\pnum -\returns -\tcode{*this}. +any_cast(y); // error: cannot \tcode{any_cast} away const +\end{codeblock} +\end{example} \end{itemdescr} -% Do not use \indexlibrarymember. -\indexlibrary{\idxcode{set} (member)!\idxcode{bitset}}% -\indexlibrary{\idxcode{bitset}!\idxcode{set}}% +\indexlibraryglobal{any_cast}% \begin{itemdecl} -constexpr bitset& set(size_t pos, bool val = true); +template + const T* any_cast(const any* operand) noexcept; +template + T* any_cast(any* operand) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Stores a new value in the bit at position \tcode{pos} in -\tcode{*this}. -If \tcode{val} is \tcode{true}, the stored value is one, otherwise it is zero. +\mandates +\tcode{is_void_v} is \tcode{false}. \pnum \returns -\tcode{*this}. +If \tcode{operand != nullptr \&\& operand->type() == typeid(T)} is \tcode{true}, +a pointer to the object contained by \tcode{operand}; +otherwise, \keyword{nullptr}. \pnum -\throws -\indexlibraryglobal{out_of_range}% -\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. +\begin{example} +\begin{codeblock} +bool is_string(const any& operand) { + return any_cast(&operand) != nullptr; +} +\end{codeblock} +\end{example} \end{itemdescr} -\indexlibrarymember{reset}{bitset}% -\begin{itemdecl} -constexpr bitset& reset() noexcept; -\end{itemdecl} +\rSec1[expected]{Expected objects} +\indexlibraryglobal{expected}% -\begin{itemdescr} -\pnum -\effects -Resets all bits in -\tcode{*this}. +\rSec2[expected.general]{General} \pnum -\returns -\tcode{*this}. -\end{itemdescr} +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{E} and +manages the lifetime of the contained objects. -\indexlibrarymember{reset}{bitset}% -\begin{itemdecl} -constexpr bitset& reset(size_t pos); -\end{itemdecl} +\rSec2[expected.syn]{Header \tcode{} synopsis} -\begin{itemdescr} -\pnum -\effects -Resets the bit at position \tcode{pos} in -\tcode{*this}. +\indexheader{expected}% +\indexlibraryglobal{unexpect_t}% +\indexlibraryglobal{unexpect}% +\begin{codeblock} +// mostly freestanding +namespace std { + // \ref{expected.unexpected}, class template \tcode{unexpected} + template class unexpected; + + // \ref{expected.bad}, class template \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; // partially freestanding + + // \ref{expected.void}, partial specialization of \tcode{expected} for \tcode{void} types + template requires is_void_v class expected; // partially freestanding +} +\end{codeblock} + +\rSec2[expected.unexpected]{Class template \tcode{unexpected}} + +\rSec3[expected.un.general]{General} \pnum -\returns -\tcode{*this}. +Subclause \ref{expected.unexpected} describes the class template \tcode{unexpected} +that represents unexpected objects stored in \tcode{expected} objects. + +\indexlibraryglobal{unexpected}% +\begin{codeblock} +namespace std { + template + class unexpected { + public: + // \ref{expected.un.cons}, constructors + constexpr unexpected(const unexpected&) = default; + constexpr unexpected(unexpected&&) = default; + template + constexpr explicit unexpected(Err&&); + template + constexpr explicit unexpected(in_place_t, Args&&...); + template + constexpr explicit unexpected(in_place_t, initializer_list, Args&&...); + + constexpr unexpected& operator=(const unexpected&) = default; + constexpr unexpected& operator=(unexpected&&) = default; + + constexpr const E& error() const & noexcept; + constexpr E& error() & noexcept; + constexpr const E&& error() const && noexcept; + constexpr E&& error() && 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 @\exposidnc{unex}@; // \expos + }; + + template unexpected(E) -> unexpected; +} +\end{codeblock} \pnum -\throws -\indexlibraryglobal{out_of_range}% -\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. -\end{itemdescr} +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. -\indexlibrarymember{operator\~{}}{bitset}% +\rSec3[expected.un.cons]{Constructors} + +\indexlibraryctor{unexpected}% \begin{itemdecl} -constexpr bitset operator~() const noexcept; +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 -Constructs an object \tcode{x} of class -\tcode{bitset} -and initializes it with -\tcode{*this}. +Direct-non-list-initializes \exposid{unex} with \tcode{std::forward(e)}. \pnum -\returns -\tcode{x.flip()}. +\throws +Any exception thrown by the initialization of \exposid{unex}. \end{itemdescr} -\indexlibrarymember{flip}{bitset}% +\indexlibraryctor{unexpected}% \begin{itemdecl} -constexpr bitset& flip() noexcept; +template + constexpr explicit unexpected(in_place_t, Args&&... args); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + \pnum \effects -Toggles all bits in -\tcode{*this}. +Direct-non-list-initializes +\exposid{unex} with \tcode{std::forward(args)...}. \pnum -\returns -\tcode{*this}. +\throws +Any exception thrown by the initialization of \exposid{unex}. \end{itemdescr} -\indexlibrarymember{flip}{bitset}% +\indexlibraryctor{unexpected}% \begin{itemdecl} -constexpr bitset& flip(size_t pos); +template + constexpr explicit unexpected(in_place_t, initializer_list il, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Toggles the bit at position \tcode{pos} in -\tcode{*this}. +\constraints +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. \pnum -\returns -\tcode{*this}. +\effects +Direct-non-list-initializes +\exposid{unex} with \tcode{il, std::forward(args)...}. \pnum \throws -\indexlibraryglobal{out_of_range}% -\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. +Any exception thrown by the initialization of \exposid{unex}. \end{itemdescr} -\indexlibrarymember{operator[]}{bitset}% +\rSec3[expected.un.obs]{Observers} + +\indexlibrarymember{error}{unexpected}% \begin{itemdecl} -constexpr bool operator[](size_t pos) const; +constexpr const E& error() const & noexcept; +constexpr E& error() & noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\expects -\tcode{pos} is valid. - \pnum \returns -\tcode{true} if the bit at position \tcode{pos} in \tcode{*this} has the value -one, otherwise \tcode{false}. - -\pnum -\throws -Nothing. +\exposid{unex}. \end{itemdescr} -\indexlibrarymember{operator[]}{bitset}% +\indexlibrarymember{error}{unexpected}% \begin{itemdecl} -constexpr bitset::reference operator[](size_t pos); +constexpr E&& error() && noexcept; +constexpr const E&& error() const && noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{pos} is valid. - -\pnum -\returns -An object of type -\tcode{bitset::reference} -such that -\tcode{(*this)[pos] == this->test(pos)}, -and such that -\tcode{(*this)[pos] = val} -is equivalent to -\tcode{this->set(pos, val)}. +\returns +\tcode{std::move(\exposid{unex})}. +\end{itemdescr} + +\rSec3[expected.un.swap]{Swap} + +\indexlibrarymember{swap}{unexpected}% +\begin{itemdecl} +constexpr void swap(unexpected& other) noexcept(is_nothrow_swappable_v); +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -Nothing. +\mandates +\tcode{is_swappable_v} is \tcode{true}. \pnum -\remarks -For the purpose of determining the presence of a data -race\iref{intro.multithread}, any access or update through the resulting -reference potentially accesses or modifies, respectively, the entire -underlying bitset. +\effects +Equivalent to: +\tcode{using std::swap; swap(\exposid{unex}, other.\exposid{unex});} \end{itemdescr} -\indexlibrarymember{to_ulong}{bitset}% \begin{itemdecl} -constexpr unsigned long to_ulong() const; +friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y))); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x}. +\constraints +\tcode{is_swappable_v} is \tcode{true}. \pnum -\throws -\indexlibraryglobal{overflow_error}% -\tcode{overflow_error} if the integral value \tcode{x} -corresponding to the bits in \tcode{*this} -cannot be represented as type \tcode{unsigned long}. +\effects +Equivalent to \tcode{x.swap(y)}. \end{itemdescr} -\indexlibrarymember{to_ullong}{bitset}% +\rSec3[expected.un.eq]{Equality operator} + +\indexlibrarymember{operator==}{unexpected}% \begin{itemdecl} -constexpr unsigned long long to_ullong() const; +template + friend constexpr bool operator==(const unexpected& x, const unexpected& y); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x}. +\mandates +The expression \tcode{x.error() == y.error()} is well-formed and +its result is convertible to \tcode{bool}. \pnum -\throws -\indexlibraryglobal{overflow_error}% -\tcode{overflow_error} if the integral value \tcode{x} -corresponding to the bits in \tcode{*this} -cannot be represented as type \tcode{unsigned long long}. +\returns +\tcode{x.error() == y.error()}. \end{itemdescr} -\indexlibrarymember{to_string}{bitset}% +\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: + constexpr explicit bad_expected_access(E); + constexpr const char* what() const noexcept override; + constexpr E& error() & noexcept; + constexpr const E& error() const & noexcept; + constexpr E&& error() && noexcept; + constexpr const E&& error() const && noexcept; + + private: + E @\exposidnc{unex}@; // \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} -template, - class Allocator = allocator> - constexpr basic_string - to_string(charT zero = charT('0'), charT one = charT('1')) const; +constexpr explicit bad_expected_access(E e); \end{itemdecl} \begin{itemdescr} \pnum \effects -Constructs a string object of the appropriate type -and initializes it to a string of length \tcode{N} characters. -Each character is determined by the value of its corresponding bit position in -\tcode{*this}. -Character position \tcode{N - 1} corresponds to bit position zero. -Subsequent decreasing character positions correspond to increasing bit -positions. -Bit value zero becomes the character \tcode{zero}, -bit value one becomes the character -\tcode{one}. +Initializes \exposid{unex} with \tcode{std::move(e)}. +\end{itemdescr} + +\indexlibrarymember{error}{bad_expected_access}% +\begin{itemdecl} +constexpr const E& error() const & noexcept; +constexpr E& error() & noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum \returns -The created object. +\exposid{unex}. \end{itemdescr} -\indexlibrarymember{count}{bitset}% +\indexlibrarymember{error}{bad_expected_access}% \begin{itemdecl} -constexpr size_t count() const noexcept; +constexpr E&& error() && noexcept; +constexpr const E&& error() const && noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -A count of the number of bits set in -\tcode{*this}. +\tcode{std::move(\exposid{unex})}. \end{itemdescr} -\indexlibrarymember{size}{bitset}% +\indexlibrarymember{what}{bad_expected_access}% \begin{itemdecl} -constexpr size_t size() const noexcept; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{N}. +An \impldef{return value of \tcode{bad_expected_access::what}} \ntbs, +which during constant evaluation is encoded with +the ordinary literal encoding\iref{lex.ccon}. \end{itemdescr} -\indexlibrarymember{operator==}{bitset}% +\rSec2[expected.bad.void]{Class template specialization \tcode{bad_expected_access}} + +\begin{codeblock} +namespace std { + template<> + class bad_expected_access : public exception { + protected: + constexpr bad_expected_access() noexcept; + constexpr bad_expected_access(const bad_expected_access&) noexcept; + constexpr bad_expected_access(bad_expected_access&&) noexcept; + constexpr bad_expected_access& operator=(const bad_expected_access&) noexcept; + constexpr bad_expected_access& operator=(bad_expected_access&&) noexcept; + constexpr ~bad_expected_access(); + + public: + constexpr const char* what() const noexcept override; + }; +} +\end{codeblock} + +\indexlibrarymember{what}{bad_expected_access}% \begin{itemdecl} -constexpr bool operator==(const bitset& rhs) const noexcept; +constexpr const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{true} if the value of each bit in -\tcode{*this} -equals the value of the corresponding bit in \tcode{rhs}. +An \impldef{return value of \tcode{bad_expected_access::what}} \ntbs, +which during constant evaluation is encoded with +the ordinary literal encoding\iref{lex.ccon}. \end{itemdescr} -\indexlibrarymember{test}{bitset}% -\begin{itemdecl} -constexpr bool test(size_t pos) const; -\end{itemdecl} +\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.cons}, constructors + constexpr expected(); + constexpr expected(const expected&); + constexpr 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 explicit(@\seebelow@) expected(const unexpected&); + template + constexpr explicit(@\seebelow@) 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& x, expected& y) noexcept(noexcept(x.swap(y))); + + // \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 &; // freestanding-deleted + constexpr T& value() &; // freestanding-deleted + constexpr const T&& value() const &&; // freestanding-deleted + constexpr T&& value() &&; // freestanding-deleted + constexpr const E& error() const & noexcept; + constexpr E& error() & noexcept; + constexpr const E&& error() const && noexcept; + constexpr E&& error() && noexcept; + template> constexpr T value_or(U&&) const &; + template> constexpr T value_or(U&&) &&; + template constexpr E error_or(G&&) const &; + template constexpr E error_or(G&&) &&; + + // \ref{expected.object.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 or_else(F&& f) &; + template constexpr auto or_else(F&& f) &&; + template constexpr auto or_else(F&& f) const &; + template constexpr auto or_else(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_error(F&& f) &; + template constexpr auto transform_error(F&& f) &&; + template constexpr auto transform_error(F&& f) const &; + template constexpr auto transform_error(F&& f) const &&; + + // \ref{expected.object.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 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} -\begin{itemdescr} \pnum -\returns -\tcode{true} -if the bit at position \tcode{pos} -in -\tcode{*this} -has the value one. +Any object of type \tcode{expected} either +contains a value of type \tcode{T} or +a value of type \tcode{E} +nested within\iref{intro.object} it. +Member \exposid{has_val} indicates whether the \tcode{expected} object +contains an object of type \tcode{T}. \pnum -\throws -\indexlibraryglobal{out_of_range}% -\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. -\end{itemdescr} - -\indexlibrarymember{all}{bitset}% -\begin{itemdecl} -constexpr bool all() const noexcept; -\end{itemdecl} +A type \tcode{T} is a \term{valid value type for \tcode{expected}}, +if \tcode{remove_cv_t} is \tcode{void} +or a complete non-array object type that is not \tcode{in_place_t}, +\tcode{unexpect_t}, +or a specialization of \tcode{unexpected}. +A program which instantiates class template \tcode{expected} +with an argument \tcode{T} that is not a valid value +type for \tcode{expected} 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. -\begin{itemdescr} \pnum -\returns -\tcode{count() == size()}. -\end{itemdescr} +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. -% Do not use \indexlibrarymember. -\indexlibrary{\idxcode{any} (member)!\idxcode{bitset}}% -\indexlibrary{\idxcode{bitset}!\idxcode{any}}% -\begin{itemdecl} -constexpr bool any() const noexcept; -\end{itemdecl} +\rSec3[expected.object.cons]{Constructors} -\begin{itemdescr} \pnum -\returns -\tcode{count() != 0}. -\end{itemdescr} +The exposition-only variable template \exposid{converts-from-any-cvref} +defined in \ref{optional.ctor} +is used by some constructors for \tcode{expected}. -\indexlibrarymember{none}{bitset}% +\indexlibraryctor{expected}% \begin{itemdecl} -constexpr bool none() const noexcept; +constexpr expected(); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{count() == 0}. -\end{itemdescr} - -\rSec2[bitset.hash]{\tcode{bitset} hash support} - -\indexlibraryglobal{hash_code}% -\begin{itemdecl} -template struct hash>; -\end{itemdecl} +\constraints +\tcode{is_default_constructible_v} is \tcode{true}. -\begin{itemdescr} \pnum -The specialization is enabled\iref{unord.hash}. -\end{itemdescr} - - -\rSec2[bitset.operators]{\tcode{bitset} operators} - -\indexlibrarymember{operator\&}{bitset}% -\begin{itemdecl} -template - constexpr bitset operator&(const bitset& lhs, const bitset& rhs) noexcept; -\end{itemdecl} +\effects +Value-initializes \exposid{val}. -\begin{itemdescr} \pnum -\returns -\tcode{bitset(lhs) \&= rhs}. -\end{itemdescr} - -\indexlibrarymember{operator"|}{bitset}% -\begin{itemdecl} -template - constexpr bitset operator|(const bitset& lhs, const bitset& rhs) noexcept; -\end{itemdecl} +\ensures +\tcode{has_value()} is \tcode{true}. -\begin{itemdescr} \pnum -\returns -\tcode{bitset(lhs) |= rhs}. +\throws +Any exception thrown by the initialization of \exposid{val}. \end{itemdescr} -\indexlibrarymember{operator\caret}{bitset}% +\indexlibraryctor{expected}% \begin{itemdecl} -template - constexpr bitset operator^(const bitset& lhs, const bitset& rhs) noexcept; +constexpr expected(const expected& rhs); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{bitset(lhs) \caret= rhs}. -\end{itemdescr} +\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()}. -\indexlibrarymember{operator>>}{bitset}% -\begin{itemdecl} -template - basic_istream& - operator>>(basic_istream& is, bitset& x); -\end{itemdecl} +\pnum +\ensures +\tcode{rhs.has_value() == this->has_value()}. -\begin{itemdescr} \pnum -A formatted input function\iref{istream.formatted}. +\throws +Any exception thrown by the initialization of \exposid{val} or \exposid{unex}. \pnum -\effects -Extracts up to \tcode{N} characters from \tcode{is}. -Stores these characters in a temporary object \tcode{str} of type -\tcode{basic_string}, -then evaluates the expression -\tcode{x = bitset(str)}. -Characters are extracted and stored until any of the following occurs: +\remarks +This constructor is defined as deleted unless \begin{itemize} \item -\tcode{N} characters have been extracted and stored; -\item -\indextext{end-of-file}% -end-of-file occurs on the input sequence; +\tcode{is_copy_constructible_v} is \tcode{true} and \item -the next input character is neither -\tcode{is.widen('0')} -nor -\tcode{is.widen('1')} -(in which case the input character is not extracted). +\tcode{is_copy_constructible_v} is \tcode{true}. \end{itemize} \pnum -If \tcode{N > 0} and no characters are stored in \tcode{str}, -\tcode{ios_base::failbit} is set in the input function's local error state -before \tcode{setstate} is called. - -\pnum -\returns -\tcode{is}. +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} -\indexlibrarymember{operator<<}{bitset}% +\indexlibraryctor{expected}% \begin{itemdecl} -template - basic_ostream& - operator<<(basic_ostream& os, const bitset& x); +constexpr expected(expected&& rhs) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\begin{codeblock} -os << x.template to_string>( - use_facet>(os.getloc()).widen('0'), - use_facet>(os.getloc()).widen('1')) -\end{codeblock} -(see~\ref{ostream.formatted}). -\end{itemdescr} - -\rSec1[function.objects]{Function objects} - -\rSec2[function.objects.general]{General} +\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 -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\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 -which has a conversion to a pointer to function. -\end{footnote} -A \defn{function object} is an -object of a function object type. In the places where one would expect to pass a -pointer to a function to an algorithmic template\iref{algorithms}, the -interface is specified to accept a function object. This not only makes -algorithmic templates work with pointers to functions, but also enables them to -work with arbitrary function objects. - -\rSec2[functional.syn]{Header \tcode{} synopsis} - -\indexheader{functional}% -\indexlibraryglobal{unwrap_ref_decay}% -\indexlibraryglobal{unwrap_ref_decay_t}% -\begin{codeblock} -namespace std { - // \ref{func.invoke}, invoke - template - constexpr invoke_result_t invoke(F&& f, Args&&... args) // freestanding - noexcept(is_nothrow_invocable_v); - - template - constexpr R invoke_r(F&& f, Args&&... args) // freestanding - noexcept(is_nothrow_invocable_r_v); - - // \ref{refwrap}, \tcode{reference_wrapper} - template class reference_wrapper; // freestanding - - template constexpr reference_wrapper ref(T&) noexcept; // freestanding - template constexpr reference_wrapper cref(const T&) noexcept; // freestanding - template void ref(const T&&) = delete; // freestanding - template void cref(const T&&) = delete; // freestanding +\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())}. - template - constexpr reference_wrapper ref(reference_wrapper) noexcept; // freestanding - template - constexpr reference_wrapper cref(reference_wrapper) noexcept; // freestanding +\pnum +\ensures +\tcode{rhs.has_value()} is unchanged; +\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. - // \ref{refwrap.common.ref}, \tcode{common_reference} related specializations - template class RQual, template class TQual> - requires @\seebelow@ - struct basic_common_reference; +\pnum +\throws +Any exception thrown by the initialization of \exposid{val} or \exposid{unex}. - template class TQual, template class RQual> - requires @\seebelow@ - struct basic_common_reference; +\pnum +\remarks +The exception specification is equivalent to +\tcode{is_nothrow_move_constructible_v \&\& +is_nothrow_move_constructible_v}. - // \ref{arithmetic.operations}, arithmetic operations - template struct plus; // freestanding - template struct minus; // freestanding - template struct multiplies; // freestanding - template struct divides; // freestanding - template struct modulus; // freestanding - template struct negate; // freestanding - template<> struct plus; // freestanding - template<> struct minus; // freestanding - template<> struct multiplies; // freestanding - template<> struct divides; // freestanding - template<> struct modulus; // freestanding - template<> struct negate; // freestanding +\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} - // \ref{comparisons}, comparisons - template struct equal_to; // freestanding - template struct not_equal_to; // freestanding - template struct greater; // freestanding - template struct less; // freestanding - template struct greater_equal; // freestanding - template struct less_equal; // freestanding - template<> struct equal_to; // freestanding - template<> struct not_equal_to; // freestanding - template<> struct greater; // freestanding - template<> struct less; // freestanding - template<> struct greater_equal; // freestanding - template<> struct less_equal; // freestanding +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit(@\seebelow@) expected(const expected& rhs); +template + constexpr explicit(@\seebelow@) expected(expected&& rhs); +\end{itemdecl} - // \ref{comparisons.three.way}, class \tcode{compare_three_way} - struct compare_three_way; // freestanding +\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} - // \ref{logical.operations}, logical operations - template struct logical_and; // freestanding - template struct logical_or; // freestanding - template struct logical_not; // freestanding - template<> struct logical_and; // freestanding - template<> struct logical_or; // freestanding - template<> struct logical_not; // freestanding +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_constructible_v} is \tcode{true}; and +\item +\tcode{is_constructible_v} is \tcode{true}; and +\item +if \tcode{T} is not \cv{} \tcode{bool}, +\tcode{\exposid{converts-from-any-cvref}>} 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} - // \ref{bitwise.operations}, bitwise operations - template struct bit_and; // freestanding - template struct bit_or; // freestanding - template struct bit_xor; // freestanding - template struct bit_not; // freestanding - template<> struct bit_and; // freestanding - template<> struct bit_or; // freestanding - template<> struct bit_xor; // freestanding - template<> struct bit_not; // freestanding +\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())}. - // \ref{func.identity}, identity - struct identity; // freestanding +\pnum +\ensures +\tcode{rhs.has_value()} is unchanged; +\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. - // \ref{func.not.fn}, function template \tcode{not_fn} - template constexpr @\unspec@ not_fn(F&& f); // freestanding - template constexpr @\unspec@ not_fn() noexcept; // freestanding +\pnum +\throws +Any exception thrown by the initialization of \exposid{val} or \exposid{unex}. - // \ref{func.bind.partial}, function templates \tcode{bind_front} and \tcode{bind_back} - template - constexpr @\unspec@ bind_front(F&&, Args&&...); // freestanding - template - constexpr @\unspec@ bind_front(Args&&...); // freestanding - template - constexpr @\unspec@ bind_back(F&&, Args&&...); // freestanding - template - constexpr @\unspec@ bind_back(Args&&...); // freestanding +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to +\tcode{!is_convertible_v || !is_convertible_v}. +\end{itemdescr} - // \ref{func.bind}, bind - template struct is_bind_expression; // freestanding - template - constexpr bool @\libglobal{is_bind_expression_v}@ = // freestanding - is_bind_expression::value; - template struct is_placeholder; // freestanding - template - constexpr int @\libglobal{is_placeholder_v}@ = // freestanding - is_placeholder::value; +\indexlibraryctor{expected}% +\begin{itemdecl} +template> + constexpr explicit(!is_convertible_v) expected(U&& v); +\end{itemdecl} - template - constexpr @\unspec@ bind(F&&, BoundArgs&&...); // freestanding - template - constexpr @\unspec@ bind(F&&, BoundArgs&&...); // freestanding +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_same_v, in_place_t>} is \tcode{false}; and +\item +\tcode{is_same_v, expected>} is \tcode{false}; and +\item +\tcode{is_same_v, unexpect_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}; and +\item +if \tcode{T} is \cv{} \tcode{bool}, +\tcode{remove_cvref_t} is not a specialization of \tcode{expected}. +\end{itemize} - namespace placeholders { - // \tcode{\placeholder{M}} is the \impldef{number of placeholders for bind expressions} number of placeholders - @\seebelownc@ _1; // freestanding - @\seebelownc@ _2; // freestanding - . - . - . - @\seebelownc@ _@\placeholdernc{M}@; // freestanding - } +\pnum +\effects +Direct-non-list-initializes \exposid{val} with \tcode{std::forward(v)}. - // \ref{func.memfn}, member function adaptors - template - constexpr @\unspec@ mem_fn(R T::*) noexcept; // freestanding +\pnum +\ensures +\tcode{has_value()} is \tcode{true}. - // \ref{func.wrap}, polymorphic function wrappers - // \ref{func.wrap.badcall}, class \tcode{bad_function_call} - class bad_function_call; +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. +\end{itemdescr} - // \ref{func.wrap.func}, class template \tcode{function} - template class function; // \notdef - template class function; +\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} - // \ref{func.wrap.func.alg}, \tcode{function} specialized algorithms - template - void swap(function&, function&) noexcept; +\begin{itemdescr} +\pnum +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. - // \ref{func.wrap.func.nullptr}, \tcode{function} null pointer comparison operator functions - template - bool operator==(const function&, nullptr_t) noexcept; +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. - // \ref{func.wrap.move}, move-only wrapper - template class move_only_function; // \notdef - template - class move_only_function; // \seebelow +\pnum +\effects +Direct-non-list-initializes \exposid{unex} with \tcode{std::forward(e.error())}. - // \ref{func.wrap.copy}, copyable wrapper - template class copyable_function; // \notdef - template - class copyable_function; // \seebelow +\pnum +\ensures +\tcode{has_value()} is \tcode{false}. - // \ref{func.wrap.ref}, non-owning wrapper - template class function_ref; // freestanding, \notdef - template - class function_ref; // freestanding, \seebelow +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. +\end{itemdescr} - // \ref{func.search}, searchers - template> - class default_searcher; // freestanding +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit expected(in_place_t, Args&&... args); +\end{itemdecl} - template::value_type>, - class BinaryPredicate = equal_to<>> - class boyer_moore_searcher; +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. - template::value_type>, - class BinaryPredicate = equal_to<>> - class boyer_moore_horspool_searcher; +\pnum +\effects +Direct-non-list-initializes \exposid{val} with \tcode{std::forward(args)...}. - // \ref{unord.hash}, class template \tcode{hash} - template - struct hash; // freestanding +\pnum +\ensures +\tcode{has_value()} is \tcode{true}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. +\end{itemdescr} - namespace ranges { - // \ref{range.cmp}, concept-constrained comparisons - struct equal_to; // freestanding - struct not_equal_to; // freestanding - struct greater; // freestanding - struct less; // freestanding - struct greater_equal; // freestanding - struct less_equal; // freestanding - } -} -\end{codeblock} +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit expected(in_place_t, initializer_list il, Args&&... args); +\end{itemdecl} +\begin{itemdescr} \pnum -\begin{example} -If a \Cpp{} program wants to have a by-element addition of two vectors \tcode{a} -and \tcode{b} containing \tcode{double} and put the result into \tcode{a}, -it can do: +\constraints +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. -\begin{codeblock} -transform(a.begin(), a.end(), b.begin(), a.begin(), plus()); -\end{codeblock} -\end{example} +\pnum +\effects +Direct-non-list-initializes \exposid{val} with +\tcode{il, std::forward(args)...}. \pnum -\begin{example} -To negate every element of \tcode{a}: +\ensures +\tcode{has_value()} is \tcode{true}. -\begin{codeblock} -transform(a.begin(), a.end(), a.begin(), negate()); -\end{codeblock} +\pnum +\throws +Any exception thrown by the initialization of \exposid{val}. +\end{itemdescr} -\end{example} +\indexlibraryctor{expected}% +\begin{itemdecl} +template + constexpr explicit expected(unexpect_t, Args&&... args); +\end{itemdecl} -\rSec2[func.def]{Definitions} +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. \pnum -The following definitions apply to this Clause: +\effects +Direct-non-list-initializes \exposid{unex} with +\tcode{std::forward(args)...}. \pnum -A \defn{call signature} is the name of a return type followed by a -parenthesized comma-separated list of zero or more argument types. +\ensures +\tcode{has_value()} is \tcode{false}. \pnum -A \defnadj{callable}{type} is a function object type\iref{function.objects} or a pointer to member. +\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 -A \defnadj{callable}{object} is an object of a callable type. +\constraints +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. \pnum -A \defnx{call wrapper type}{call wrapper!type} is a type that holds a callable object -and supports a call operation that forwards to that object. +\effects +Direct-non-list-initializes \exposid{unex} with +\tcode{il, std::forward(args)...}. \pnum -A \defn{call wrapper} is an object of a call wrapper type. +\ensures +\tcode{has_value()} is \tcode{false}. \pnum -A \defn{target object} is the callable object held by a call wrapper. +\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 -A call wrapper type may additionally hold -a sequence of objects and references -that may be passed as arguments to the target object. -These entities are collectively referred to -as \defnx{bound argument entities}{bound argument entity}. +\effects +If \tcode{has_value()} is \tcode{true}, destroys \exposid{val}, +otherwise destroys \exposid{unex}. \pnum -The target object and bound argument entities of the call wrapper are -collectively referred to as \defnx{state entities}{state entity}. +\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} -\rSec2[func.require]{Requirements} +\rSec3[expected.object.assign]{Assignment} \pnum -\indextext{invoke@\tcode{\placeholder{INVOKE}}}% -\indexlibrary{invoke@\tcode{\placeholder{INVOKE}}}% -Define \tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} as follows: +This subclause makes use of the following exposition-only function template: +\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 \tcode{(t$_1$.*f)(t$_2$, $\dotsc$, t$_N$)} when \tcode{f} is a pointer to a -member function of a class \tcode{T} -and -\tcode{is_same_v> ||} -\tcode{is_base_of_v>} is \tcode{true}; +\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;} -\item \tcode{(t$_1$.get().*f)(t$_2$, $\dotsc$, t$_N$)} when \tcode{f} is a pointer to a -member function of a class \tcode{T} -and \tcode{remove_cvref_t} is a specialization of \tcode{reference_wrapper}; +\pnum +\returns +\tcode{*this}. -\item \tcode{((*t$_1$).*f)(t$_2$, $\dotsc$, t$_N$)} when \tcode{f} is a pointer to a -member function of a class \tcode{T} -and \tcode{t$_1$} does not satisfy the previous two items; +\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} -\item \tcode{t$_1$.*f} when $N = 1$ and \tcode{f} is a pointer to -data member of a class \tcode{T} -and -\tcode{is_same_v> ||} -\tcode{is_base_of_v>} is \tcode{true}; +\indexlibrarymember{operator=}{expected}% +\begin{itemdecl} +constexpr expected& operator=(expected&& rhs) noexcept(@\seebelow@); +\end{itemdecl} -\item \tcode{t$_1$.get().*f} when $N = 1$ and \tcode{f} is a pointer to -data member of a class \tcode{T} -and \tcode{remove_cvref_t} is a specialization of \tcode{reference_wrapper}; +\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} -\item \tcode{(*t$_1$).*f} when $N = 1$ and \tcode{f} is a pointer to -data member of a class \tcode{T} -and \tcode{t$_1$} does not satisfy the previous two items; +\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 +\returns +\tcode{*this}. + +\pnum +\remarks +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 +\end{codeblock} +\end{itemdescr} -\item \tcode{f(t$_1$, t$_2$, $\dotsc$, t$_N$)} in all other cases. -\end{itemize} +\indexlibrarymember{operator=}{expected}% +\begin{itemdecl} +template> + constexpr expected& operator=(U&& v); +\end{itemdecl} +\begin{itemdescr} \pnum -\indexlibrary{invoke@\tcode{\placeholder{INVOKE}}}% -Define \tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} as -\tcode{static_cast(\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$))} -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. +\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 -\indextext{call wrapper}% -\indextext{call wrapper!simple}% -\indextext{call wrapper!forwarding}% -Every call wrapper\iref{func.def} meets the \oldconcept{MoveConstructible} -and \oldconcept{Destructible} requirements. -An \defn{argument forwarding call wrapper} is a -call wrapper that can be called with an arbitrary argument list -and delivers the arguments to the target object as references. -This forwarding step delivers rvalue arguments as rvalue references -and lvalue arguments as lvalue references. -\begin{note} -In a typical implementation, argument forwarding call wrappers have -an overloaded function call operator of the form +\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} -template - constexpr R operator()(UnBoundArgs&&... unbound_args) @\textit{cv-qual}@; +@\exposid{reinit-expected}@(@\exposid{val}@, @\exposid{unex}@, std::forward(v)); +@\exposid{has_val}@ = true; \end{codeblock} -\end{note} +\end{itemize} \pnum -\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} -as \cv{} \tcode{T\&} -when the call is performed on an lvalue of the call wrapper type and -as \cv{} \tcode{T\&\&} otherwise, -where \cv{} represents the cv-qualifiers of the call wrapper and -where \cv{} shall be neither \tcode{volatile} nor \tcode{const volatile}. +\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 -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 -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 -with references as described in the corresponding forwarding steps. +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. \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 -are constexpr functions that do not throw exceptions. +\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 -The copy/move constructor of an argument forwarding call wrapper has -the same apparent semantics -as if memberwise copy/move of its state entities -were performed\iref{class.copy.ctor}. -\begin{note} -This implies that each of the copy/move constructors has -the same exception-specification as -the corresponding implicit definition and is declared as \keyword{constexpr} -if the corresponding implicit definition would be considered to be constexpr. -\end{note} +\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.error())); +@\exposid{has_val}@ = false; +\end{codeblock} +\item +Otherwise, equivalent to: +\tcode{\exposid{unex} = std::forward(e.error());} +\end{itemize} \pnum -Argument forwarding call wrappers returned by -a given standard library function template have the same type -if the types of their corresponding state entities are the same. +\returns +\tcode{*this}. +\end{itemdescr} -\rSec2[func.invoke]{\tcode{invoke} functions} -\indexlibraryglobal{invoke}% -\indexlibrary{invoke@\tcode{\placeholder{INVOKE}}}% +\indexlibrarymember{emplace}{expected}% \begin{itemdecl} -template - constexpr invoke_result_t invoke(F&& f, Args&&... args) - noexcept(is_nothrow_invocable_v); +template + constexpr T& emplace(Args&&... args) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_invocable_v} is \tcode{true}. +\tcode{is_nothrow_constructible_v} is \tcode{true}. \pnum -\returns -\tcode{\placeholdernc{INVOKE}(std::forward(f), std::forward(args)...)}\iref{func.require}. +\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} -\indexlibraryglobal{invoke_r}% +\indexlibrarymember{emplace}{expected}% \begin{itemdecl} -template - constexpr R invoke_r(F&& f, Args&&... args) - noexcept(is_nothrow_invocable_r_v); +template + constexpr T& emplace(initializer_list il, Args&&... args) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_invocable_r_v} is \tcode{true}. +\tcode{is_nothrow_constructible_v\&, Args...>} +is \tcode{true}. \pnum -\returns -\tcode{\placeholdernc{INVOKE}(std::forward(f), std::forward(args)...)}\iref{func.require}. +\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} -\rSec2[refwrap]{Class template \tcode{reference_wrapper}} - -\rSec3[refwrap.general]{General} - -\indexlibraryglobal{reference_wrapper}% -\indextext{function object!\idxcode{reference_wrapper}}% -\begin{codeblock} -namespace std { - template class reference_wrapper { - public: - // types - using type = T; +\rSec3[expected.object.swap]{Swap} - // \ref{refwrap.const}, constructors - template - constexpr reference_wrapper(U&&) noexcept(@\seebelow@); - constexpr reference_wrapper(const reference_wrapper& x) noexcept; +\indexlibrarymember{swap}{expected}% +\begin{itemdecl} +constexpr void swap(expected& rhs) noexcept(@\seebelow@); +\end{itemdecl} - // \ref{refwrap.assign}, assignment - constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept; +\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} - // \ref{refwrap.access}, access - constexpr operator T& () const noexcept; - constexpr T& get() const noexcept; +\pnum +\effects +See \tref{expected.object.swap}. - // \ref{refwrap.invoke}, invocation - template - constexpr invoke_result_t operator()(ArgTypes&&...) const - noexcept(is_nothrow_invocable_v); - }; +\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{!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)} \\ +\lhdr{\tcode{!rhs.has_value()}} & + \seebelow & + equivalent to: \tcode{using std::swap; swap(\exposid{unex}, rhs.\exposid{unex});} \\ +\end{floattable} - template - reference_wrapper(T&) -> reference_wrapper; +For the case where \tcode{rhs.has_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 -\tcode{reference_wrapper} is a \oldconcept{CopyConstructible} and \oldconcept{CopyAssignable} wrapper -around a reference to an object or function of type \tcode{T}. - -\pnum -\tcode{reference_wrapper} is -a trivially copyable type\iref{term.trivially.copyable.type}. +\throws +Any exception thrown by the expressions in the \Fundescx{Effects}. \pnum -The template parameter \tcode{T} of \tcode{reference_wrapper} -may be an incomplete type. - -\rSec3[refwrap.const]{Constructors} +\remarks +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 +\end{codeblock} +\end{itemdescr} -\indexlibraryctor{reference_wrapper}% +\indexlibrarymember{swap}{expected}% \begin{itemdecl} -template - constexpr reference_wrapper(U&& u) noexcept(@\seebelow@); +friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); \end{itemdecl} \begin{itemdescr} -\pnum -Let \tcode{\placeholdernc{FUN}} denote the exposition-only functions -\begin{codeblock} -void @\placeholdernc{FUN}@(T&) noexcept; -void @\placeholdernc{FUN}@(T&&) = delete; -\end{codeblock} - -\pnum -\constraints -The expression \tcode{\placeholdernc{FUN}(declval())} is well-formed and -\tcode{is_same_v, reference_wrapper>} is \tcode{false}. - \pnum \effects -Creates a variable \tcode{r} -as if by \tcode{T\& r = std::forward(u)}, -then constructs a \tcode{reference_wrapper} object -that stores a reference to \tcode{r}. - -\pnum -\remarks -The exception specification is equivalent to -\tcode{noexcept(\placeholdernc{FUN}(declval()))}. +Equivalent to \tcode{x.swap(y)}. \end{itemdescr} -\indexlibraryctor{reference_wrapper}% +\rSec3[expected.object.obs]{Observers} + +\indexlibrarymember{operator->}{expected}% \begin{itemdecl} -constexpr reference_wrapper(const reference_wrapper& x) noexcept; +constexpr const T* operator->() const noexcept; +constexpr T* operator->() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Constructs a \tcode{reference_wrapper} object that -stores a reference to \tcode{x.get()}. -\end{itemdescr} +\hardexpects +\tcode{has_value()} is \tcode{true}. -\rSec3[refwrap.assign]{Assignment} +\pnum +\returns +\tcode{addressof(\exposid{val})}. +\end{itemdescr} -\indexlibrarymember{operator=}{reference_wrapper}% +\indexlibrarymember{operator*}{expected}% \begin{itemdecl} -constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept; +constexpr const T& operator*() const & noexcept; +constexpr T& operator*() & noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{*this} stores a reference to \tcode{x.get()}. -\end{itemdescr} +\hardexpects +\tcode{has_value()} is \tcode{true}. -\rSec3[refwrap.access]{Access} +\pnum +\returns +\exposid{val}. +\end{itemdescr} -\indexlibrarymember{operator T\&}{reference_wrapper}% +\indexlibrarymember{operator*}{expected}% \begin{itemdecl} -constexpr operator T& () const noexcept; +constexpr T&& operator*() && noexcept; +constexpr const T&& operator*() const && noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\hardexpects +\tcode{has_value()} is \tcode{true}. + \pnum \returns -The stored reference. +\tcode{std::move(\exposid{val})}. \end{itemdescr} -\indexlibrarymember{get}{reference_wrapper}% +\indexlibrarymember{operator bool}{expected}% +\indexlibrarymember{has_value}{expected}% \begin{itemdecl} -constexpr T& get() const noexcept; +constexpr explicit operator bool() const noexcept; +constexpr bool has_value() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -The stored reference. +\exposid{has_val}. \end{itemdescr} -\rSec3[refwrap.invoke]{Invocation} - -\indexlibrarymember{operator()}{reference_wrapper}% +\indexlibrarymember{value}{expected}% \begin{itemdecl} -template - constexpr invoke_result_t - operator()(ArgTypes&&... args) const noexcept(is_nothrow_invocable_v); +constexpr const T& value() const &; +constexpr T& value() &; \end{itemdecl} \begin{itemdescr} \pnum \mandates -\tcode{T} is a complete type. +\tcode{is_copy_constructible_v} is \tcode{true}. \pnum \returns -\tcode{\placeholdernc{INVOKE}(get(), std::forward(args)...)}.\iref{func.require} -\end{itemdescr} - - -\rSec3[refwrap.helpers]{Helper functions} +\exposid{val}, if \tcode{has_value()} is \tcode{true}. \pnum -The template parameter \tcode{T} of -the following \tcode{ref} and \tcode{cref} function templates -may be an incomplete type. +\throws +\tcode{bad_expected_access(as_const(error()))} if \tcode{has_value()} is \tcode{false}. +\end{itemdescr} -\indexlibrarymember{ref}{reference_wrapper}% +\indexlibrarymember{value}{expected}% \begin{itemdecl} -template constexpr reference_wrapper ref(T& t) noexcept; +constexpr T&& value() &&; +constexpr const T&& value() const &&; \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{is_copy_constructible_v} is \tcode{true} and +\tcode{is_constructible_v} is \tcode{true}. + \pnum \returns -\tcode{reference_wrapper(t)}. +\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{ref}{reference_wrapper}% +\indexlibrarymember{error}{expected}% \begin{itemdecl} -template constexpr reference_wrapper ref(reference_wrapper t) noexcept; +constexpr const E& error() const & noexcept; +constexpr E& error() & noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\hardexpects +\tcode{has_value()} is \tcode{false}. + \pnum \returns -\tcode{t}. +\exposid{unex}. \end{itemdescr} -\indexlibrarymember{cref}{reference_wrapper}% +\indexlibrarymember{error}{expected}% \begin{itemdecl} -template constexpr reference_wrapper cref(const T& t) noexcept; +constexpr E&& error() && noexcept; +constexpr const E&& error() const && noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\hardexpects +\tcode{has_value()} is \tcode{false}. + \pnum \returns -\tcode{reference_wrapper(t)}. +\tcode{std::move(\exposid{unex})}. \end{itemdescr} -\indexlibrarymember{cref}{reference_wrapper}% +\indexlibrarymember{value_or}{expected}% \begin{itemdecl} -template constexpr reference_wrapper cref(reference_wrapper t) noexcept; +template> constexpr T value_or(U&& v) const &; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{t}. -\end{itemdescr} - -\rSec3[refwrap.common.ref]{\tcode{common_reference} related specializations} - -\indexlibraryglobal{basic_common_reference}% -\begin{codeblock} -namespace std { - template - constexpr bool @\exposid{is-ref-wrapper}@ = false; // \expos - - template - constexpr bool @\exposid{is-ref-wrapper}@> = true; - - template - concept @\defexposconcept{ref-wrap-common-reference-exists-with}@ = // \expos - @\exposid{is-ref-wrapper}@ && - requires { typename common_reference_t; } && - @\libconcept{convertible_to}@>; - - template class RQual, template class TQual> - requires (@\exposconcept{ref-wrap-common-reference-exists-with}@, TQual> && - !@\exposconcept{ref-wrap-common-reference-exists-with}@, RQual>) - struct basic_common_reference { - using type = common_reference_t>; - }; - - template class TQual, template class RQual> - requires (@\exposconcept{ref-wrap-common-reference-exists-with}@, TQual> && - !@\exposconcept{ref-wrap-common-reference-exists-with}@, RQual>) - struct basic_common_reference { - using type = common_reference_t>; - }; -} -\end{codeblock} - -\rSec2[arithmetic.operations]{Arithmetic operations} - -\rSec3[arithmetic.operations.general]{General} +\mandates +\tcode{is_copy_constructible_v} is \tcode{true} and +\tcode{is_convertible_v} is \tcode{true}. \pnum -The library provides basic function object classes for all of the arithmetic -operators in the language\iref{expr.mul,expr.add}. - -\rSec3[arithmetic.operations.plus]{Class template \tcode{plus}} - -\indexlibraryglobal{plus}% -\begin{itemdecl} -template struct plus { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} +\returns +\tcode{has_value() ? **this : static_cast(std::forward(v))}. +\end{itemdescr} -\indexlibrarymember{operator()}{plus}% +\indexlibrarymember{value_or}{expected}% \begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; +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_v} is \tcode{true}. + \pnum \returns -\tcode{x + y}. +\tcode{has_value() ? std::move(**this) : static_cast(std::forward(v))}. \end{itemdescr} -\indexlibraryglobal{plus<>}% -\begin{itemdecl} -template<> struct plus { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) + std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{plus<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) + std::forward(u)); +\indexlibrarymember{error_or}{expected}% +\begin{itemdecl} +template constexpr E error_or(G&& e) const &; \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{is_copy_constructible_v} is \tcode{true} and +\tcode{is_convertible_v} is \tcode{true}. + \pnum \returns -\tcode{std::forward(t) + std::forward(u)}. +\tcode{std::forward(e)} if \tcode{has_value()} is \tcode{true}, +\tcode{error()} otherwise. \end{itemdescr} -\rSec3[arithmetic.operations.minus]{Class template \tcode{minus}} - -\indexlibraryglobal{minus}% -\begin{itemdecl} -template struct minus { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{minus}% +\indexlibrarymember{error_or}{expected}% \begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; +template constexpr E error_or(G&& e) &&; \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{is_move_constructible_v} is \tcode{true} and +\tcode{is_convertible_v} is \tcode{true}. + \pnum \returns -\tcode{x - y}. +\tcode{std::forward(e)} if \tcode{has_value()} is \tcode{true}, +\tcode{std::move(error())} otherwise. \end{itemdescr} -\indexlibraryglobal{minus<>}% -\begin{itemdecl} -template<> struct minus { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) - std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} +\rSec3[expected.object.monadic]{Monadic operations} -\indexlibrarymember{operator()}{minus<>}% +\indexlibrarymember{and_then}{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) - std::forward(u)); +template constexpr auto and_then(F&& f) &; +template constexpr auto and_then(F&& f) const &; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{std::forward(t) - std::forward(u)}. -\end{itemdescr} +Let \tcode{U} be \tcode{remove_cvref_t>}. -\rSec3[arithmetic.operations.multiplies]{Class template \tcode{multiplies}} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. -\indexlibraryglobal{multiplies}% -\begin{itemdecl} -template struct multiplies { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} +\pnum +\mandates +\tcode{U} is a specialization of \tcode{expected} and +\tcode{is_same_v} is \tcode{true}. -\indexlibrarymember{operator()}{multiplies}% +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (has_value()) + return invoke(std::forward(f), @\exposid{val}@); +else + return U(unexpect, error()); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{and_then}{expected}% \begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; +template constexpr auto and_then(F&& f) &&; +template constexpr auto and_then(F&& f) const &&; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x * y}. -\end{itemdescr} +Let \tcode{U} be +\tcode{remove_cvref_t>}. -\indexlibraryglobal{multiplies<>}% -\begin{itemdecl} -template<> struct multiplies { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) * std::forward(u)); +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. - using is_transparent = @\unspec@; -}; -\end{itemdecl} +\pnum +\mandates +\tcode{U} is a specialization of \tcode{expected} and +\tcode{is_same_v} is \tcode{true}. -\indexlibrarymember{operator()}{multiplies<>}% +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (has_value()) + return invoke(std::forward(f), std::move(@\exposid{val}@)); +else + return U(unexpect, std::move(error())); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{or_else}{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) * std::forward(u)); +template constexpr auto or_else(F&& f) &; +template constexpr auto or_else(F&& f) const &; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{std::forward(t) * std::forward(u)}. -\end{itemdescr} +Let \tcode{G} be \tcode{remove_cvref_t>}. -\rSec3[arithmetic.operations.divides]{Class template \tcode{divides}} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. -\indexlibraryglobal{divides}% -\begin{itemdecl} -template struct divides { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} +\pnum +\mandates +\tcode{G} is a specialization of \tcode{expected} and +\tcode{is_same_v} is \tcode{true}. -\indexlibrarymember{operator()}{divides}% +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (has_value()) + return G(in_place, @\exposid{val}@); +else + return invoke(std::forward(f), error()); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{or_else}{expected}% \begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; +template constexpr auto or_else(F&& f) &&; +template constexpr auto or_else(F&& f) const &&; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x / y}. -\end{itemdescr} +Let \tcode{G} be +\tcode{remove_cvref_t>}. -\indexlibraryglobal{divides<>}% -\begin{itemdecl} -template<> struct divides { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) / std::forward(u)); +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. - using is_transparent = @\unspec@; -}; -\end{itemdecl} +\pnum +\mandates +\tcode{G} is a specialization of \tcode{expected} and +\tcode{is_same_v} is \tcode{true}. -\indexlibrarymember{operator()}{divides<>}% +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (has_value()) + return G(in_place, std::move(@\exposid{val}@)); +else + return invoke(std::forward(f), std::move(error())); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{transform}{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) / std::forward(u)); +template constexpr auto transform(F&& f) &; +template constexpr auto transform(F&& f) const &; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{std::forward(t) / std::forward(u)}. -\end{itemdescr} +Let \tcode{U} be +\tcode{remove_cv_t>}. -\rSec3[arithmetic.operations.modulus]{Class template \tcode{modulus}} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. -\indexlibraryglobal{modulus}% -\begin{itemdecl} -template struct modulus { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} +\pnum +\mandates +\tcode{U} is a valid value type for \tcode{expected}. +If \tcode{is_void_v} is \tcode{false}, +the declaration +\begin{codeblock} +U u(invoke(std::forward(f), @\exposid{val}@)); +\end{codeblock} +is well-formed. -\indexlibrarymember{operator()}{modulus}% +\pnum +\effects +\begin{itemize} +\item +If \tcode{has_value()} is \tcode{false}, returns +\tcode{expected(unexpect, error())}. +\item +Otherwise, if \tcode{is_void_v} is \tcode{false}, returns an +\tcode{expected} object whose \exposid{has_val} member is \tcode{true} +and \exposid{val} member is direct-non-list-initialized with +\tcode{invoke(std::forward(f), \exposid{val})}. +\item +Otherwise, evaluates \tcode{invoke(std::forward(f), \exposid{val})} and then +returns \tcode{expected()}. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{transform}{expected}% \begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; +template constexpr auto transform(F&& f) &&; +template constexpr auto transform(F&& f) const &&; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x \% y}. -\end{itemdescr} +Let \tcode{U} be +\tcode{remove_cv_t>}. -\indexlibraryglobal{modulus<>}% -\begin{itemdecl} -template<> struct modulus { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) % std::forward(u)); +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\mandates +\tcode{U} is a valid value type for \tcode{expected}. If \tcode{is_void_v} is +\tcode{false}, the declaration +\begin{codeblock} +U u(invoke(std::forward(f), std::move(@\exposid{val}@))); +\end{codeblock} +is well-formed. - using is_transparent = @\unspec@; -}; -\end{itemdecl} +\pnum +\effects +\begin{itemize} +\item +If \tcode{has_value()} is \tcode{false}, returns +\tcode{expected(unexpect, std::move(error()))}. +\item +Otherwise, if \tcode{is_void_v} is \tcode{false}, returns an +\tcode{expected} object whose \exposid{has_val} member is \tcode{true} +and \exposid{val} member is direct-non-list-initialized with +\tcode{invoke(std::forward(f), std::move(\exposid{val}))}. +\item +Otherwise, evaluates \tcode{invoke(std::forward(f), std::move(\exposid{val}))} and +then returns \tcode{ex\-pected()}. +\end{itemize} +\end{itemdescr} -\indexlibrarymember{operator()}{modulus<>}% +\indexlibrarymember{transform_error}{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) % std::forward(u)); +template constexpr auto transform_error(F&& f) &; +template constexpr auto transform_error(F&& f) const &; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{std::forward(t) \% std::forward(u)}. -\end{itemdescr} - -\rSec3[arithmetic.operations.negate]{Class template \tcode{negate}} +Let \tcode{G} be \tcode{remove_cv_t>}. -\indexlibraryglobal{negate}% -\begin{itemdecl} -template struct negate { - constexpr T operator()(const T& x) const; -}; -\end{itemdecl} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. -\indexlibrarymember{operator()}{negate}% -\begin{itemdecl} -constexpr T operator()(const T& x) const; -\end{itemdecl} +\pnum +\mandates +\tcode{G} is a valid template argument +for \tcode{unexpected}\iref{expected.un.general} and the declaration +\begin{codeblock} +G g(invoke(std::forward(f), error())); +\end{codeblock} +is well-formed. -\begin{itemdescr} \pnum \returns -\tcode{-x}. +If \tcode{has_value()} is \tcode{true}, +\tcode{expected(in_place, \exposid{val})}; otherwise, an \tcode{expected} +object whose \exposid{has_val} member is \tcode{false} and \exposid{unex} member +is direct-non-list-initialized with \tcode{invoke(std::forward(f), error())}. \end{itemdescr} -\indexlibraryglobal{negate<>}% -\begin{itemdecl} -template<> struct negate { - template constexpr auto operator()(T&& t) const - -> decltype(-std::forward(t)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{negate<>}% +\indexlibrarymember{transform_error}{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t) const - -> decltype(-std::forward(t)); +template constexpr auto transform_error(F&& f) &&; +template constexpr auto transform_error(F&& f) const &&; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{-std::forward(t)}. -\end{itemdescr} - - -\rSec2[comparisons]{Comparisons} - -\rSec3[comparisons.general]{General} +Let \tcode{G} be +\tcode{remove_cv_t>}. \pnum -The library provides basic function object classes for all of the comparison -operators in the language\iref{expr.rel,expr.eq}. +\constraints +\tcode{is_constructible_v} is \tcode{true}. \pnum -For templates \tcode{less}, \tcode{greater}, \tcode{less_equal}, and -\tcode{greater_equal}, the specializations for any pointer type -yield a result consistent with the -implementation-defined strict total order over pointers\iref{defns.order.ptr}. -\begin{note} -If \tcode{a < b} is well-defined -for pointers \tcode{a} and \tcode{b} of type \tcode{P}, -then \tcode{(a < b) == less

()(a, b)}, -\tcode{(a > b) == greater

()(a, b)}, and so forth. -\end{note} -For template specializations \tcode{less}, \tcode{greater}, -\tcode{less_equal}, and \tcode{greater_equal}, -if the call operator calls a built-in operator comparing pointers, -the call operator yields a result consistent -with the implementation-defined strict total order over pointers. +\mandates +\tcode{G} is a valid template argument +for \tcode{unexpected}\iref{expected.un.general} and the declaration +\begin{codeblock} +G g(invoke(std::forward(f), std::move(error()))); +\end{codeblock} +is well-formed. -\rSec3[comparisons.equal.to]{Class template \tcode{equal_to}} +\pnum +\returns +If \tcode{has_value()} is \tcode{true}, +\tcode{expected(in_place, std::move(\exposid{val}))}; otherwise, an +\tcode{expected} object whose \exposid{has_val} member is \tcode{false} +and \exposid{unex} member is direct-non-list-initialized with +\tcode{invoke(std::forward(f), std::move(error()))}. +\end{itemdescr} -\indexlibraryglobal{equal_to}% -\begin{itemdecl} -template struct equal_to { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} +\rSec3[expected.object.eq]{Equality operators} -\indexlibrarymember{operator()}{equal_to}% +\indexlibrarymember{operator==}{expected}% \begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; +template requires (!is_void_v) + friend constexpr bool operator==(const expected& x, const expected& y); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +The expressions \tcode{*x == *y} and \tcode{x.error() == y.error()} +are well-formed and their results are convertible to \tcode{bool}. + \pnum \returns -\tcode{x == y}. +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} -\indexlibraryglobal{equal_to<>}% -\begin{itemdecl} -template<> struct equal_to { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) == std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{equal_to<>}% +\indexlibrarymember{operator==}{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) == std::forward(u)); +template friend constexpr bool operator==(const expected& x, const T2& v); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{T2} is not a specialization of \tcode{expected}. +The expression \tcode{*x == v} is well-formed and +its result is convertible to \tcode{bool}. +\begin{note} +\tcode{T} need not be \oldconcept{EqualityComparable}. +\end{note} + \pnum \returns -\tcode{std::forward(t) == std::forward(u)}. +\tcode{x.has_value() \&\& static_cast(*x == v)}. \end{itemdescr} -\rSec3[comparisons.not.equal.to]{Class template \tcode{not_equal_to}} - -\indexlibraryglobal{not_equal_to}% -\begin{itemdecl} -template struct not_equal_to { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{not_equal_to}% +\indexlibrarymember{operator==}{expected}% \begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; +template friend constexpr bool operator==(const expected& x, const unexpected& e); \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +The expression \tcode{x.error() == e.error()} is well-formed and +its result is convertible to \tcode{bool}. + \pnum \returns -\tcode{x != y}. +\tcode{!x.has_value() \&\& static_cast(x.error() == e.error())}. \end{itemdescr} -\indexlibraryglobal{not_equal_to<>}% -\begin{itemdecl} -template<> struct not_equal_to { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) != std::forward(u)); +\rSec2[expected.void]{Partial specialization of \tcode{expected} for \tcode{void} types} - using is_transparent = @\unspec@; -}; -\end{itemdecl} +\rSec3[expected.void.general]{General} -\indexlibrarymember{operator()}{not_equal_to<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) != std::forward(u)); -\end{itemdecl} +\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; -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) != std::forward(u)}. -\end{itemdescr} + template + using @\libmember{rebind}{expected}@ = expected; -\rSec3[comparisons.greater]{Class template \tcode{greater}} + // \ref{expected.void.cons}, constructors + constexpr expected() noexcept; + constexpr expected(const expected&); + constexpr expected(expected&&) noexcept(@\seebelow@); + template + constexpr explicit(@\seebelow@) expected(const expected&); + template + constexpr explicit(@\seebelow@) expected(expected&&); -\indexlibraryglobal{greater}% -\begin{itemdecl} -template struct greater { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} + template + constexpr explicit(@\seebelow@) expected(const unexpected&); + template + constexpr explicit(@\seebelow@) expected(unexpected&&); -\indexlibrarymember{operator()}{greater}% -\begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; -\end{itemdecl} + constexpr explicit expected(in_place_t) noexcept; + template + constexpr explicit expected(unexpect_t, Args&&...); + template + constexpr explicit expected(unexpect_t, initializer_list, Args&&...); -\begin{itemdescr} -\pnum -\returns -\tcode{x > y}. -\end{itemdescr} -\indexlibraryglobal{greater<>}% -\begin{itemdecl} -template<> struct greater { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) > std::forward(u)); + // \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; - using is_transparent = @\unspec@; -}; -\end{itemdecl} + // \ref{expected.void.swap}, swap + constexpr void swap(expected&) noexcept(@\seebelow@); + friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); -\indexlibrarymember{operator()}{greater<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) > std::forward(u)); -\end{itemdecl} + // \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 &; // freestanding-deleted + constexpr void value() &&; // freestanding-deleted + constexpr const E& error() const & noexcept; + constexpr E& error() & noexcept; + constexpr const E&& error() const && noexcept; + constexpr E&& error() && noexcept; + template constexpr E error_or(G&&) const &; + template constexpr E error_or(G&&) &&; -\begin{itemdescr} -\pnum -\returns -\tcode{std::forward(t) > std::forward(u)}. -\end{itemdescr} + // \ref{expected.void.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 or_else(F&& f) &; + template constexpr auto or_else(F&& f) &&; + template constexpr auto or_else(F&& f) const &; + template constexpr auto or_else(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_error(F&& f) &; + template constexpr auto transform_error(F&& f) &&; + template constexpr auto transform_error(F&& f) const &; + template constexpr auto transform_error(F&& f) const &&; -\rSec3[comparisons.less]{Class template \tcode{less}} + // \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&); -\indexlibraryglobal{less}% -\begin{itemdecl} -template struct less { - constexpr bool operator()(const T& x, const T& y) const; +private: + bool @\exposid{has_val}@; // \expos + union { + E @\exposid{unex}@; // \expos + }; }; -\end{itemdecl} +\end{codeblock} -\indexlibrarymember{operator()}{less}% -\begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; -\end{itemdecl} +\pnum +Any object of type \tcode{expected} either +represents a value of type \tcode{T}, or +contains a value of type \tcode{E} +nested within\iref{intro.object} it. +Member \exposid{has_val} indicates whether the \tcode{expected} object +represents a value of type \tcode{T}. -\begin{itemdescr} \pnum -\returns -\tcode{x < y}. -\end{itemdescr} +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. -\indexlibraryglobal{less<>}% -\begin{itemdecl} -template<> struct less { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) < std::forward(u)); +\pnum +\tcode{E} shall meet the requirements of +\oldconcept{Destructible} (\tref{cpp17.destructible}). - using is_transparent = @\unspec@; -}; -\end{itemdecl} +\rSec3[expected.void.cons]{Constructors} -\indexlibrarymember{operator()}{less<>}% +\indexlibraryctor{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) < std::forward(u)); +constexpr expected() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{std::forward(t) < std::forward(u)}. +\ensures +\tcode{has_value()} is \tcode{true}. \end{itemdescr} -\rSec3[comparisons.greater.equal]{Class template \tcode{greater_equal}} - -\indexlibraryglobal{greater_equal}% -\begin{itemdecl} -template struct greater_equal { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{greater_equal}% +\indexlibraryctor{expected}% \begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; +constexpr expected(const expected& rhs); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x >= y}. -\end{itemdescr} +\effects +If \tcode{rhs.has_value()} is \tcode{false}, +direct-non-list-initializes \exposid{unex} with \tcode{rhs.error()}. -\indexlibraryglobal{greater_equal<>}% -\begin{itemdecl} -template<> struct greater_equal { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) >= std::forward(u)); +\pnum +\ensures +\tcode{rhs.has_value() == this->has_value()}. - using is_transparent = @\unspec@; -}; -\end{itemdecl} +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. -\indexlibrarymember{operator()}{greater_equal<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) >= std::forward(u)); -\end{itemdecl} +\pnum +\remarks +This constructor is defined as deleted +unless \tcode{is_copy_constructible_v} is \tcode{true}. -\begin{itemdescr} \pnum -\returns -\tcode{std::forward(t) >= std::forward(u)}. +This constructor is trivial +if \tcode{is_trivially_copy_constructible_v} is \tcode{true}. \end{itemdescr} -\rSec3[comparisons.less.equal]{Class template \tcode{less_equal}} - -\indexlibraryglobal{less_equal}% -\begin{itemdecl} -template struct less_equal { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{less_equal}% +\indexlibraryctor{expected}% \begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; +constexpr expected(expected&& rhs) noexcept(is_nothrow_move_constructible_v); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x <= y}. -\end{itemdescr} +\constraints +\tcode{is_move_constructible_v} is \tcode{true}. -\indexlibraryglobal{less_equal<>}% -\begin{itemdecl} -template<> struct less_equal { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) <= std::forward(u)); +\pnum +\effects +If \tcode{rhs.has_value()} is \tcode{false}, +direct-non-list-initializes \exposid{unex} with \tcode{std::move(rhs.error())}. - using is_transparent = @\unspec@; -}; -\end{itemdecl} +\pnum +\ensures +\tcode{rhs.has_value()} is unchanged; +\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. -\indexlibrarymember{operator()}{less_equal<>}% -\begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) <= std::forward(u)); -\end{itemdecl} +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. -\begin{itemdescr} \pnum -\returns -\tcode{std::forward(t) <= std::forward(u)}. +\remarks +This constructor is trivial +if \tcode{is_trivially_move_constructible_v} is \tcode{true}. \end{itemdescr} -\rSec3[comparisons.three.way]{Class \tcode{compare_three_way}} - -\indexlibraryglobal{compare_three_way}% -\begin{codeblock} -namespace std { - struct compare_three_way { - template - constexpr auto operator()(T&& t, U&& u) const; - - using is_transparent = @\unspec@; - }; -} -\end{codeblock} - +\indexlibraryctor{expected}% \begin{itemdecl} -template - constexpr auto operator()(T&& t, U&& u) const; +template + constexpr explicit(!is_convertible_v) expected(const expected& rhs); +template + constexpr explicit(!is_convertible_v) expected(expected&& rhs); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{T} and \tcode{U} satisfy \libconcept{three_way_comparable_with}. - -\pnum -\expects -If the expression \tcode{std::forward(t) <=> std::forward(u)} results in -a call to a built-in operator \tcode{<=>} comparing pointers of type \tcode{P}, -the conversion sequences from both \tcode{T} and \tcode{U} to \tcode{P} -are equality-preserving\iref{concepts.equality}; -otherwise, \tcode{T} and \tcode{U} model \libconcept{three_way_comparable_with}. +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. \pnum -\effects +\constraints \begin{itemize} \item - If the expression \tcode{std::forward(t) <=> std::forward(u)} results in - a call to a built-in operator \tcode{<=>} comparing pointers of type \tcode{P}, - returns \tcode{strong_ordering::less} - if (the converted value of) \tcode{t} precedes \tcode{u} - in the implementation-defined strict total order - over pointers\iref{defns.order.ptr}, - \tcode{strong_ordering::greater} - if \tcode{u} precedes \tcode{t}, and - otherwise \tcode{strong_ordering::equal}. +\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 - Otherwise, equivalent to: \tcode{return std::forward(t) <=> std::forward(u);} +\tcode{is_constructible_v, const expected\&>} +is \tcode{false}; and +\item +\tcode{is_constructible_v, const expected>} +is \tcode{false}. \end{itemize} -\end{itemdescr} -\rSec2[range.cmp]{Concept-constrained comparisons} +\pnum +\effects +If \tcode{rhs.has_value()} is \tcode{false}, +direct-non-list-initializes \exposid{unex} +with \tcode{std::forward(rhs.er\-ror())}. -\indexlibraryglobal{equal_to}% -\begin{codeblock} -struct ranges::equal_to { - template - constexpr bool operator()(T&& t, U&& u) const; +\pnum +\ensures +\tcode{rhs.has_value()} is unchanged; +\tcode{rhs.has_value() == this->has_value()} is \tcode{true}. - using is_transparent = @\unspecnc@; -}; -\end{codeblock} +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. +\end{itemdescr} +\indexlibraryctor{expected}% \begin{itemdecl} -template - constexpr bool operator()(T&& t, U&& u) const; +template + constexpr explicit(!is_convertible_v) expected(const unexpected& e); +template + constexpr explicit(!is_convertible_v) expected(unexpected&& e); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{T} and \tcode{U} satisfy \libconcept{equality_comparable_with}. +Let \tcode{GF} be \tcode{const G\&} for the first overload and +\tcode{G} for the second overload. \pnum -\expects -If the expression \tcode{std::forward(t) == std::forward(u)} -results in a call to a built-in operator \tcode{==} comparing pointers of type -\tcode{P}, the conversion sequences from both \tcode{T} and \tcode{U} to \tcode{P} -are equality-preserving\iref{concepts.equality}; -otherwise, \tcode{T} and \tcode{U} model \libconcept{equality_comparable_with}. +\constraints +\tcode{is_constructible_v} is \tcode{true}. \pnum \effects -\begin{itemize} -\item - If the expression \tcode{std::forward(t) == std::forward(u)} results in - a call to a built-in operator \tcode{==} comparing pointers: - returns \tcode{false} if either (the converted value of) \tcode{t} precedes - \tcode{u} or \tcode{u} precedes \tcode{t} in the implementation-defined strict - total order over pointers\iref{defns.order.ptr} and otherwise \tcode{true}. +Direct-non-list-initializes \exposid{unex} +with \tcode{std::forward(e.error())}. -\item - Otherwise, equivalent to: - \tcode{return std::forward(t) == std::forward(u);} -\end{itemize} +\pnum +\ensures +\tcode{has_value()} is \tcode{false}. + +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. \end{itemdescr} -\indexlibraryglobal{not_equal_to}% -\begin{codeblock} -struct ranges::not_equal_to { - template - constexpr bool operator()(T&& t, U&& u) const; +\indexlibraryctor{expected}% +\begin{itemdecl} +constexpr explicit expected(in_place_t) noexcept; +\end{itemdecl} - using is_transparent = @\unspecnc@; -}; -\end{codeblock} +\begin{itemdescr} +\pnum +\ensures +\tcode{has_value()} is \tcode{true}. +\end{itemdescr} +\indexlibraryctor{expected}% \begin{itemdecl} -template - constexpr bool operator()(T&& t, U&& u) const; +template + constexpr explicit expected(unexpect_t, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{T} and \tcode{U} satisfy \libconcept{equality_comparable_with}. +\tcode{is_constructible_v} is \tcode{true}. \pnum \effects -Equivalent to: -\begin{codeblock} -return !ranges::equal_to{}(std::forward(t), std::forward(u)); -\end{codeblock} -\end{itemdescr} +Direct-non-list-initializes \exposid{unex} +with \tcode{std::forward(args)...}. -\indexlibraryglobal{greater}% -\begin{codeblock} -struct ranges::greater { - template - constexpr bool operator()(T&& t, U&& u) const; +\pnum +\ensures +\tcode{has_value()} is \tcode{false}. - using is_transparent = @\unspecnc@; -}; -\end{codeblock} +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. +\end{itemdescr} +\indexlibraryctor{expected}% \begin{itemdecl} -template - constexpr bool operator()(T&& t, U&& u) const; +template + constexpr explicit expected(unexpect_t, initializer_list il, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. +\tcode{is_constructible_v\&, Args...>} is \tcode{true}. \pnum \effects -Equivalent to: -\begin{codeblock} -return ranges::less{}(std::forward(u), std::forward(t)); -\end{codeblock} -\end{itemdescr} +Direct-non-list-initializes \exposid{unex} +with \tcode{il, std::forward(args)...}. -\indexlibraryglobal{less}% -\begin{codeblock} -struct ranges::less { - template - constexpr bool operator()(T&& t, U&& u) const; +\pnum +\ensures +\tcode{has_value()} is \tcode{false}. - using is_transparent = @\unspecnc@; -}; -\end{codeblock} +\pnum +\throws +Any exception thrown by the initialization of \exposid{unex}. +\end{itemdescr} + +\rSec3[expected.void.dtor]{Destructor} +\indexlibrarydtor{expected}% \begin{itemdecl} -template - constexpr bool operator()(T&& t, U&& u) const; +constexpr ~expected(); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. +\effects +If \tcode{has_value()} is \tcode{false}, destroys \exposid{unex}. \pnum -\expects -If the expression \tcode{std::forward(t) < std::forward(u)} results in a -call to a built-in operator \tcode{<} comparing pointers of type \tcode{P}, the -conversion sequences from both \tcode{T} and \tcode{U} to \tcode{P} are -equality-preserving\iref{concepts.equality}; -otherwise, \tcode{T} and \tcode{U} model \libconcept{totally_ordered_with}. -For any expressions -\tcode{ET} and \tcode{EU} such that \tcode{decltype((ET))} is \tcode{T} and -\tcode{decltype((EU))} is \tcode{U}, exactly one of -\tcode{ranges::less\{\}(ET, EU)}, -\tcode{ranges::less\{\}(EU, ET)}, or -\tcode{ranges::equal_to\{\}(ET, EU)} -is \tcode{true}. +\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 the expression \tcode{std::forward(t) < std::forward(u)} results in a -call to a built-in operator \tcode{<} comparing pointers: -returns \tcode{true} if (the converted value of) \tcode{t} precedes \tcode{u} in -the implementation-defined strict total order over pointers\iref{defns.order.ptr} -and otherwise \tcode{false}. - +If \tcode{this->has_value() \&\& rhs.has_value()} is \tcode{true}, no effects. \item -Otherwise, equivalent to: -\tcode{return std::forward(t) < std::forward(u);} +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} -\end{itemdescr} -\indexlibraryglobal{greater_equal}% -\begin{codeblock} -struct ranges::greater_equal { - template - constexpr bool operator()(T&& t, U&& u) const; +\pnum +\returns +\tcode{*this}. - using is_transparent = @\unspecnc@; -}; -\end{codeblock} +\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} -template - constexpr bool operator()(T&& t, U&& u) const; +constexpr expected& operator=(expected&& rhs) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. +\tcode{is_move_constructible_v} is \tcode{true} and +\tcode{is_move_assignable_v} is \tcode{true}. \pnum \effects -Equivalent to: +\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} -return !ranges::less{}(std::forward(t), std::forward(u)); +construct_at(addressof(@\exposid{unex}@), std::move(rhs.@\exposid{unex}@)); +@\exposid{has_val}@ = false; \end{codeblock} -\end{itemdescr} +\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} = std::move(rhs.error())}. +\end{itemize} -\indexlibraryglobal{less_equal}% -\begin{itemdecl} -struct ranges::less_equal { - template - constexpr bool operator()(T&& t, U&& u) const; +\pnum +\returns +\tcode{*this}. - using is_transparent = @\unspecnc@; -}; -\end{itemdecl} +\pnum +\remarks +The exception specification is equivalent to +\tcode{is_nothrow_move_constructible_v \&\& is_nothrow_move_assignable_v}. +\end{itemdescr} +\indexlibrarymember{operator=}{expected}% \begin{itemdecl} -template - constexpr bool operator()(T&& t, U&& u) const; +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{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. +\tcode{is_constructible_v} is \tcode{true} and +\tcode{is_assignable_v} is \tcode{true}. \pnum \effects -Equivalent to: +\begin{itemize} +\item +If \tcode{has_value()} is \tcode{true}, equivalent to: \begin{codeblock} -return !ranges::less{}(std::forward(u), std::forward(t)); +construct_at(addressof(@\exposid{unex}@), std::forward(e.error())); +@\exposid{has_val}@ = false; \end{codeblock} -\end{itemdescr} - -\rSec2[logical.operations]{Logical operations} - -\rSec3[logical.operations.general]{General} +\item +Otherwise, equivalent to: +\tcode{\exposid{unex} = std::forward(e.error());} +\end{itemize} \pnum -The library provides basic function object classes for all of the logical -operators in the language\iref{expr.log.and,expr.log.or,expr.unary.op}. - -\rSec3[logical.operations.and]{Class template \tcode{logical_and}} - -\indexlibraryglobal{logical_and}% -\begin{itemdecl} -template struct logical_and { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} +\returns +\tcode{*this}. +\end{itemdescr} -\indexlibrarymember{operator()}{logical_and}% +\indexlibrarymember{emplace}{expected}% \begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; +constexpr void emplace() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x \&\& y}. +\effects +If \tcode{has_value()} is \tcode{false}, +destroys \exposid{unex} and sets \exposid{has_val} to \tcode{true}. \end{itemdescr} -\indexlibraryglobal{logical_and<>}% -\begin{itemdecl} -template<> struct logical_and { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) && std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} +\rSec3[expected.void.swap]{Swap} -\indexlibrarymember{operator()}{logical_and<>}% +\indexlibrarymember{swap}{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) && std::forward(u)); +constexpr void swap(expected& rhs) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{std::forward(t) \&\& std::forward(u)}. -\end{itemdescr} +\constraints +\tcode{is_swappable_v} is \tcode{true} and +\tcode{is_move_constructible_v} is \tcode{true}. -\rSec3[logical.operations.or]{Class template \tcode{logical_or}} +\pnum +\effects +See \tref{expected.void.swap}. -\indexlibraryglobal{logical_or}% -\begin{itemdecl} -template struct logical_or { - constexpr bool operator()(const T& x, const T& y) const; -}; -\end{itemdecl} +\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{!this->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} -\indexlibrarymember{operator()}{logical_or}% -\begin{itemdecl} -constexpr bool operator()(const T& x, const T& y) const; -\end{itemdecl} +For the case where \tcode{rhs.has_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} -\begin{itemdescr} \pnum -\returns -\tcode{x || y}. -\end{itemdescr} - -\indexlibraryglobal{logical_or<>}% -\begin{itemdecl} -template<> struct logical_or { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) || std::forward(u)); +\throws +Any exception thrown by the expressions in the \Fundescx{Effects}. - using is_transparent = @\unspec@; -}; -\end{itemdecl} +\pnum +\remarks +The exception specification is equivalent to +\tcode{is_nothrow_move_constructible_v \&\& is_nothrow_swappable_v}. +\end{itemdescr} -\indexlibrarymember{operator()}{logical_or<>}% +\indexlibrarymember{swap}{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) || std::forward(u)); +friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{std::forward(t) || std::forward(u)}. +\effects +Equivalent to \tcode{x.swap(y)}. \end{itemdescr} -\rSec3[logical.operations.not]{Class template \tcode{logical_not}} - -\indexlibraryglobal{logical_not}% -\begin{itemdecl} -template struct logical_not { - constexpr bool operator()(const T& x) const; -}; -\end{itemdecl} +\rSec3[expected.void.obs]{Observers} -\indexlibrarymember{operator()}{logical_not}% +\indexlibrarymember{operator bool}{expected}% +\indexlibrarymember{has_value}{expected}% \begin{itemdecl} -constexpr bool operator()(const T& x) const; +constexpr explicit operator bool() const noexcept; +constexpr bool has_value() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{!x}. +\exposid{has_val}. \end{itemdescr} -\indexlibraryglobal{logical_not<>}% -\begin{itemdecl} -template<> struct logical_not { - template constexpr auto operator()(T&& t) const - -> decltype(!std::forward(t)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{logical_not<>}% +\indexlibrarymember{operator*}{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t) const - -> decltype(!std::forward(t)); +constexpr void operator*() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{!std::forward(t)}. +\hardexpects +\tcode{has_value()} is \tcode{true}. \end{itemdescr} - -\rSec2[bitwise.operations]{Bitwise operations} - -\rSec3[bitwise.operations.general]{General} - -\pnum -The library provides basic function object classes for all of the bitwise -operators in the language\iref{expr.bit.and,expr.or,expr.xor,expr.unary.op}. - -\rSec3[bitwise.operations.and]{Class template \tcode{bit_and}} - -\indexlibraryglobal{bit_and}% -\begin{itemdecl} -template struct bit_and { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{bit_and}% +\indexlibrarymember{value}{expected}% \begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; +constexpr void value() const &; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{x \& y}. -\end{itemdescr} - -\indexlibraryglobal{bit_and<>}% -\begin{itemdecl} -template<> struct bit_and { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) & std::forward(u)); +\mandates +\tcode{is_copy_constructible_v} is \tcode{true}. - using is_transparent = @\unspec@; -}; -\end{itemdecl} +\pnum +\throws +\tcode{bad_expected_access(error())} if \tcode{has_value()} is \tcode{false}. +\end{itemdescr} -\indexlibrarymember{operator()}{bit_and<>}% +\indexlibrarymember{value}{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) & std::forward(u)); +constexpr void value() &&; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{std::forward(t) \& std::forward(u)}. -\end{itemdescr} - -\rSec3[bitwise.operations.or]{Class template \tcode{bit_or}} +\mandates +\tcode{is_copy_constructible_v} is \tcode{true} and +\tcode{is_move_constructible_v} is \tcode{true}. -\indexlibraryglobal{bit_or}% -\begin{itemdecl} -template struct bit_or { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} +\pnum +\throws +\tcode{bad_expected_access(std::move(error()))} +if \tcode{has_value()} is \tcode{false}. +\end{itemdescr} -\indexlibrarymember{operator()}{bit_or}% +\indexlibrarymember{error}{expected}% \begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; +constexpr const E& error() const & noexcept; +constexpr E& error() & noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\hardexpects +\tcode{has_value()} is \tcode{false}. + \pnum \returns -\tcode{x | y}. +\exposid{unex}. \end{itemdescr} -\indexlibraryglobal{bit_or<>}% -\begin{itemdecl} -template<> struct bit_or { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) | std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{bit_or<>}% +\indexlibrarymember{error}{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) | std::forward(u)); +constexpr E&& error() && noexcept; +constexpr const E&& error() const && noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\hardexpects +\tcode{has_value()} is \tcode{false}. + \pnum \returns -\tcode{std::forward(t) | std::forward(u)}. +\tcode{std::move(\exposid{unex})}. \end{itemdescr} -\rSec3[bitwise.operations.xor]{Class template \tcode{bit_xor}} - -\indexlibraryglobal{bit_xor}% -\begin{itemdecl} -template struct bit_xor { - constexpr T operator()(const T& x, const T& y) const; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{bit_xor}% +\indexlibrarymember{error_or}{expected}% \begin{itemdecl} -constexpr T operator()(const T& x, const T& y) const; +template constexpr E error_or(G&& e) const &; \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{is_copy_constructible_v} is \tcode{true} and +\tcode{is_convertible_v} is \tcode{true}. + \pnum \returns -\tcode{x \caret{} y}. +\tcode{std::forward(e)} if \tcode{has_value()} is \tcode{true}, +\tcode{error()} otherwise. \end{itemdescr} -\indexlibraryglobal{bit_xor<>}% -\begin{itemdecl} -template<> struct bit_xor { - template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) ^ std::forward(u)); - - using is_transparent = @\unspec@; -}; -\end{itemdecl} - -\indexlibrarymember{operator()}{bit_xor<>}% +\indexlibrarymember{error_or}{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t, U&& u) const - -> decltype(std::forward(t) ^ std::forward(u)); +template constexpr E error_or(G&& e) &&; \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{is_move_constructible_v} is \tcode{true} and +\tcode{is_convertible_v} is \tcode{true}. + \pnum \returns -\tcode{std::forward(t) \caret{} std::forward(u)}. +\tcode{std::forward(e)} if \tcode{has_value()} is \tcode{true}, +\tcode{std::move(error())} otherwise. \end{itemdescr} -\rSec3[bitwise.operations.not]{Class template \tcode{bit_not}} +\rSec3[expected.void.monadic]{Monadic operations} +\indexlibrarymember{and_then}{expected}% \begin{itemdecl} -template struct bit_not { - constexpr T operator()(const T& x) const; -}; +template constexpr auto and_then(F&& f) &; +template constexpr auto and_then(F&& f) const &; \end{itemdecl} -\indexlibrarymember{operator()}{bit_not}% +\begin{itemdescr} +\pnum +Let \tcode{U} be \tcode{remove_cvref_t>}. + +\pnum +\constraints +\tcode{is_constructible_v>} is \tcode{true}. + +\pnum +\mandates +\tcode{U} is a specialization of \tcode{expected} and +\tcode{is_same_v} is \tcode{true}. + +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (has_value()) + return invoke(std::forward(f)); +else + return U(unexpect, error()); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{and_then}{expected}% \begin{itemdecl} -constexpr T operator()(const T& x) const; +template constexpr auto and_then(F&& f) &&; +template constexpr auto and_then(F&& f) const &&; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{\~{}x}. -\end{itemdescr} +Let \tcode{U} be \tcode{remove_cvref_t>}. -\indexlibraryglobal{bit_not<>}% -\begin{itemdecl} -template<> struct bit_not { - template constexpr auto operator()(T&& t) const - -> decltype(~std::forward(t)); +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. - using is_transparent = @\unspec@; -}; -\end{itemdecl} +\pnum +\mandates +\tcode{U} is a specialization of \tcode{expected} and +\tcode{is_same_v} is \tcode{true}. -\indexlibrarymember{operator()}{bit_not<>}% +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (has_value()) + return invoke(std::forward(f)); +else + return U(unexpect, std::move(error())); +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{or_else}{expected}% \begin{itemdecl} -template constexpr auto operator()(T&& t) const - -> decltype(~std::forward(t)); +template constexpr auto or_else(F&& f) &; +template constexpr auto or_else(F&& f) const &; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{\~{}std::forward(t)}. -\end{itemdescr} +Let \tcode{G} be \tcode{remove_cvref_t>}. +\pnum +\mandates +\tcode{G} is a specialization of \tcode{expected} and +\tcode{is_same_v} is \tcode{true}. -\rSec2[func.identity]{Class \tcode{identity}} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (has_value()) + return G(); +else + return invoke(std::forward(f), error()); +\end{codeblock} +\end{itemdescr} -\indexlibraryglobal{identity}% +\indexlibrarymember{or_else}{expected}% \begin{itemdecl} -struct identity { - template - constexpr T&& operator()(T&& t) const noexcept; - - using is_transparent = @\unspec@; -}; - -template - constexpr T&& operator()(T&& t) const noexcept; +template constexpr auto or_else(F&& f) &&; +template constexpr auto or_else(F&& f) const &&; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return std::forward(t);} -\end{itemdescr} +Let \tcode{G} be +\tcode{remove_cvref_t>}. +\pnum +\mandates +\tcode{G} is a specialization of \tcode{expected} and +\tcode{is_same_v} is \tcode{true}. -\rSec2[func.not.fn]{Function template \tcode{not_fn}} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (has_value()) + return G(); +else + return invoke(std::forward(f), std::move(error())); +\end{codeblock} +\end{itemdescr} -\indexlibraryglobal{not_fn}% +\indexlibrarymember{transform}{expected}% \begin{itemdecl} -template constexpr @\unspec@ not_fn(F&& f); +template constexpr auto transform(F&& f) &; +template constexpr auto transform(F&& f) const &; \end{itemdecl} \begin{itemdescr} \pnum -In the text that follows: +Let \tcode{U} be \tcode{remove_cv_t>}. + +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\mandates +\tcode{U} is a valid value type for \tcode{expected}. If \tcode{is_void_v} is +\tcode{false}, the declaration +\begin{codeblock} +U u(invoke(std::forward(f))); +\end{codeblock} +is well-formed. + +\pnum +\effects \begin{itemize} -\item \tcode{g} is a value of the result of a \tcode{not_fn} 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}, - direct-non-list-initialized with \tcode{std::forward(f)}, -\item \tcode{call_args} is an argument pack - used in a function call expression\iref{expr.call} of \tcode{g}. +\item +If \tcode{has_value()} is \tcode{false}, returns +\tcode{expected(unexpect, error())}. +\item +Otherwise, if \tcode{is_void_v} is \tcode{false}, returns an +\tcode{expected} object whose \exposid{has_val} member is \tcode{true} and +\exposid{val} member is direct-non-list-initialized with +\tcode{invoke(std::forward(f))}. +\item +Otherwise, evaluates \tcode{invoke(std::forward(f))} and then returns +\tcode{expected()}. \end{itemize} +\end{itemdescr} +\indexlibrarymember{transform}{expected}% +\begin{itemdecl} +template constexpr auto transform(F&& f) &&; +template constexpr auto transform(F&& f) const &&; +\end{itemdecl} + +\begin{itemdescr} \pnum -\mandates -\tcode{is_constructible_v \&\& is_move_constructible_v} -is \tcode{true}. +Let \tcode{U} be \tcode{remove_cv_t>}. \pnum -\expects -\tcode{FD} meets the \oldconcept{MoveConstructible} requirements. +\constraints +\tcode{is_constructible_v} is \tcode{true}. \pnum -\returns -A perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} \tcode{g} -with call pattern \tcode{!invoke(fd, call_args...)}. +\mandates +\tcode{U} is a valid value type for \tcode{expected}. If \tcode{is_void_v} is +\tcode{false}, the declaration +\begin{codeblock} +U u(invoke(std::forward(f))); +\end{codeblock} +is well-formed. \pnum -\throws -Any exception thrown by the initialization of \tcode{fd}. +\effects +\begin{itemize} +\item +If \tcode{has_value()} is \tcode{false}, returns +\tcode{expected(unexpect, std::move(error()))}. +\item +Otherwise, if \tcode{is_void_v} is \tcode{false}, returns an +\tcode{expected} object whose \exposid{has_val} member is \tcode{true} and +\exposid{val} member is direct-non-list-initialized with +\tcode{invoke(std::forward(f))}. +\item +Otherwise, evaluates \tcode{invoke(std::forward(f))} and then returns +\tcode{expected()}. +\end{itemize} \end{itemdescr} -\indexlibraryglobal{not_fn}% +\indexlibrarymember{transform_error}{expected}% \begin{itemdecl} -template constexpr @\unspec@ not_fn() noexcept; +template constexpr auto transform_error(F&& f) &; +template constexpr auto transform_error(F&& f) const &; \end{itemdecl} \begin{itemdescr} \pnum -In the text that follows: -\begin{itemize} -\item -\tcode{F} is the type of \tcode{f}, -\item -\tcode{g} is a value of the result of a \tcode{not_fn} invocation, -\item -\tcode{call_args} is an argument pack -used in a function call expression\iref{expr.call} of \tcode{g}. -\end{itemize} +Let \tcode{G} be \tcode{remove_cv_t>}. \pnum \mandates -If \tcode{is_pointer_v || is_member_pointer_v} is \tcode{true}, -then \tcode{f != nullptr} is \tcode{true}. +\tcode{G} is a valid template argument +for \tcode{unexpected}\iref{expected.un.general} and the declaration +\begin{codeblock} +G g(invoke(std::forward(f), error())); +\end{codeblock} +is well-formed. \pnum \returns -A perfect forwarding call wrapper\iref{func.require} \tcode{g} that -does not have state entities, and -has the call pattern \tcode{!invoke(f, call_args...)}. +If \tcode{has_value()} is \tcode{true}, \tcode{expected()}; otherwise, an +\tcode{expected} object whose \exposid{has_val} member is \tcode{false} +and \exposid{unex} member is direct-non-list-initialized with +\tcode{invoke(std::for\-ward(f), error())}. \end{itemdescr} -\rSec2[func.bind.partial]{Function templates \tcode{bind_front} and \tcode{bind_back}} - -\indexlibraryglobal{bind_front}% -\indexlibraryglobal{bind_back}% +\indexlibrarymember{transform_error}{expected}% \begin{itemdecl} -template - constexpr @\unspec@ bind_front(F&& f, Args&&... args); -template - constexpr @\unspec@ bind_back(F&& f, Args&&... args); +template constexpr auto transform_error(F&& f) &&; +template constexpr auto transform_error(F&& f) const &&; \end{itemdecl} \begin{itemdescr} \pnum -Within this subclause: -\begin{itemize} -\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}, - direct-non-list-initialized with \tcode{std::forward(f)}, -\item \tcode{BoundArgs} is a pack - that denotes \tcode{decay_t...}, -\item \tcode{bound_args} is - a pack of bound argument entities of \tcode{g}\iref{func.def} - of types \tcode{BoundArgs...}, - direct-non-list-initialized with \tcode{std::forward(args)...}, - respectively, and -\item \tcode{call_args} is an argument pack used in - a function call expression\iref{expr.call} of \tcode{g}. -\end{itemize} +Let \tcode{G} be +\tcode{remove_cv_t>}. \pnum \mandates +\tcode{G} is a valid template argument +for \tcode{unexpected}\iref{expected.un.general} and the declaration \begin{codeblock} -is_constructible_v && -is_move_constructible_v && -(is_constructible_v && ...) && -(is_move_constructible_v && ...) +G g(invoke(std::forward(f), std::move(error()))); \end{codeblock} -is \tcode{true}. - -\pnum -\expects -\tcode{FD} meets the \oldconcept{MoveConstructible} requirements. -For each $\tcode{T}_i$ in \tcode{BoundArgs}, -if $\tcode{T}_i$ is an object type, -$\tcode{T}_i$ meets the \oldconcept{MoveConstructible} requirements. +is well-formed. \pnum \returns -A perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} \tcode{g} -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 -Any exception thrown by -the initialization of the state entities of \tcode{g}\iref{func.def}. +If \tcode{has_value()} is \tcode{true}, \tcode{expected()}; otherwise, an +\tcode{expected} object whose \exposid{has_val} member is \tcode{false} +and \exposid{unex} member is direct-non-list-initialized with +\tcode{invoke(std::for\-ward(f), std::move(error()))}. \end{itemdescr} -\indexlibraryglobal{bind_front}% -\indexlibraryglobal{bind_back}% +\rSec3[expected.void.eq]{Equality operators} + +\indexlibrarymember{operator==}{expected}% \begin{itemdecl} -template - constexpr @\unspec@ bind_front(Args&&... args); -template - constexpr @\unspec@ bind_back(Args&&... args); +template requires is_void_v + friend constexpr bool operator==(const expected& x, const expected& y); \end{itemdecl} \begin{itemdescr} \pnum -Within this subclause: -\begin{itemize} -\item -\tcode{F} is the type of \tcode{f}, -\item -\tcode{g} is a value of the result of -a \tcode{bind_front} or \tcode{bind_back} invocation, -\item -\tcode{BoundArgs} is a pack that denotes \tcode{decay_t...}, -\item -\tcode{bound_args} is a pack of bound argument entities of -\tcode{g}\iref{func.def} of types \tcode{BoundArgs...}, -direct-non-list-initialized with \tcode{std::forward(args)...}, -respectively, and -\item -\tcode{call_args} is an argument pack used in -a function call expression\iref{expr.call} of \tcode{g}. -\end{itemize} +\constraints +The expression \tcode{x.error() == y.error()} is well-formed and +its result is convertible to \tcode{bool}. \pnum -\mandates -\begin{itemize} -\item -\tcode{(is_constructible_v \&\& ...)} is \tcode{true}, and -\item -\tcode{(is_move_constructible_v \&\& ...)} is \tcode{true}, and -\item -if \tcode{is_pointer_v || is_member_pointer_v} is \tcode{true}, -then \tcode{f != nullptr} is \tcode{true}. -\end{itemize} +\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} -\pnum -\expects -For each $\tcode{T}_i$ in \tcode{BoundArgs}, -$\tcode{T}_i$ meets the \oldconcept{MoveConstructible} requirements. +\indexlibrarymember{operator==}{expected}% +\begin{itemdecl} +template + friend constexpr bool operator==(const expected& x, const unexpected& e); +\end{itemdecl} +\begin{itemdescr} \pnum -\returns -A perfect forwarding call wrapper\iref{func.require} \tcode{g} that -does not have a target object, and has the call pattern: -\begin{itemize} -\item -\tcode{invoke(f, bound_args..., call_args...)} -for a \tcode{bind_front} invocation, or -\item -\tcode{invoke(f, call_args..., bound_args...)} -for a \tcode{bind_back} invocation. -\end{itemize} +\constraints +The expression \tcode{x.error() == e.error()} is well-formed and +its result is convertible to \tcode{bool}. \pnum -throws -Any exception thrown by the initialization of \tcode{bound_args}. +\returns +\tcode{!x.has_value() \&\& static_cast(x.error() == e.error())}. \end{itemdescr} -\rSec2[func.bind]{Function object binders}% +\rSec1[bitset]{Bitsets} +\indexlibraryglobal{bitset}% -\rSec3[func.bind.general]{General}% -\indextext{function object!binders|(} +\rSec2[bitset.syn]{Header \tcode{} synopsis}% \pnum -Subclause \ref{func.bind} describes a uniform mechanism for binding -arguments of callable objects. - -\rSec3[func.bind.isbind]{Class template \tcode{is_bind_expression}} +The header \libheaderdef{bitset} defines a class template +and several related functions for representing +and manipulating fixed-size sequences of bits. -\indexlibraryglobal{is_bind_expression}% \begin{codeblock} +#include // see \ref{string.syn} +#include // for \tcode{istream}\iref{istream.syn}, \tcode{ostream}\iref{ostream.syn}, see \ref{iosfwd.syn} + namespace std { - template struct is_bind_expression; // see below + template class bitset; + + // \ref{bitset.operators}, bitset operators + template + constexpr bitset operator&(const bitset&, const bitset&) noexcept; + template + constexpr bitset operator|(const bitset&, const bitset&) noexcept; + template + constexpr bitset operator^(const bitset&, const bitset&) noexcept; + template + basic_istream& + operator>>(basic_istream& is, bitset& x); + template + basic_ostream& + operator<<(basic_ostream& os, const bitset& x); } \end{codeblock} -\pnum -The class template \tcode{is_bind_expression} can be used to detect function objects -generated by \tcode{bind}. The function template \tcode{bind} -uses \tcode{is_bind_expression} to detect subexpressions. +\rSec2[template.bitset]{Class template \tcode{bitset}}% + +\rSec3[template.bitset.general]{General}% +\indexlibraryglobal{bitset}% +\begin{codeblock} +namespace std { + template class bitset { + public: + // bit reference + class reference { + public: + constexpr reference(const reference&) = default; + constexpr ~reference(); + constexpr reference& operator=(bool x) noexcept; // for \tcode{b[i] = x;} + constexpr reference& operator=(const reference&) noexcept; // for \tcode{b[i] = b[j];} + constexpr bool operator~() const noexcept; // flips the bit + constexpr operator bool() const noexcept; // for \tcode{x = b[i];} + constexpr reference& flip() noexcept; // for \tcode{b[i].flip();} + }; + + // \ref{bitset.cons}, constructors + constexpr bitset() noexcept; + constexpr bitset(unsigned long long val) noexcept; + template + constexpr explicit bitset( + const basic_string& str, + typename basic_string::size_type pos = 0, + typename basic_string::size_type n + = basic_string::npos, + charT zero = charT('0'), + charT one = charT('1')); + template + constexpr explicit bitset( + basic_string_view str, + typename basic_string_view::size_type pos = 0, + typename basic_string_view::size_type n + = basic_string_view::npos, + charT zero = charT('0'), + charT one = charT('1')); + template + constexpr explicit bitset( + const charT* str, + typename basic_string_view::size_type n = basic_string_view::npos, + charT zero = charT('0'), + charT one = charT('1')); + + // \ref{bitset.members}, bitset operations + constexpr bitset& operator&=(const bitset& rhs) noexcept; + constexpr bitset& operator|=(const bitset& rhs) noexcept; + constexpr bitset& operator^=(const bitset& rhs) noexcept; + constexpr bitset& operator<<=(size_t pos) noexcept; + constexpr bitset& operator>>=(size_t pos) noexcept; + constexpr bitset operator<<(size_t pos) const noexcept; + constexpr bitset operator>>(size_t pos) const noexcept; + constexpr bitset& set() noexcept; + constexpr bitset& set(size_t pos, bool val = true); + constexpr bitset& reset() noexcept; + constexpr bitset& reset(size_t pos); + constexpr bitset operator~() const noexcept; + constexpr bitset& flip() noexcept; + constexpr bitset& flip(size_t pos); + + // element access + constexpr bool operator[](size_t pos) const; + constexpr reference operator[](size_t pos); -\pnum -Specializations of the \tcode{is_bind_expression} template shall meet -the \oldconcept{UnaryTypeTrait} requirements\iref{meta.rqmts}. The implementation -provides a definition that has a base characteristic of -\tcode{true_type} if \tcode{T} is a type returned from \tcode{bind}, -otherwise it has a base characteristic of \tcode{false_type}. -A program may specialize this template for a program-defined type \tcode{T} -to have a base characteristic of \tcode{true_type} to indicate that -\tcode{T} should be treated as a subexpression in a \tcode{bind} call. + constexpr unsigned long to_ulong() const; + constexpr unsigned long long to_ullong() const; + template, + class Allocator = allocator> + constexpr basic_string + to_string(charT zero = charT('0'), charT one = charT('1')) const; -\rSec3[func.bind.isplace]{Class template \tcode{is_placeholder}} + // observers + constexpr size_t count() const noexcept; + constexpr size_t size() const noexcept; + constexpr bool operator==(const bitset& rhs) const noexcept; + constexpr bool test(size_t pos) const; + constexpr bool all() const noexcept; + constexpr bool any() const noexcept; + constexpr bool none() const noexcept; + }; -\indexlibraryglobal{is_placeholder}% -\begin{codeblock} -namespace std { - template struct is_placeholder; // see below + // \ref{bitset.hash}, hash support + template struct hash; + template struct hash>; } \end{codeblock} \pnum -\indexlibraryglobal{placeholders}% -\indexlibrary{1@\tcode{_1}}% -\indexlibrary{2@\tcode{_2}}% -\indexlibrary{3@\tcode{_3}}% -\indexlibrary{4@\tcode{_4}}% -\indexlibrary{5@\tcode{_5}}% -\indexlibrary{6@\tcode{_6}}% -\indexlibrary{7@\tcode{_7}}% -\indexlibrary{8@\tcode{_8}}% -\indexlibrary{9@\tcode{_9}}% -\indexlibrary{10@\tcode{_10}}% -The class template \tcode{is_placeholder} can be used to detect the standard placeholders -\tcode{_1}, \tcode{_2}, and so on\iref{func.bind.place}. -The function template \tcode{bind} uses -\tcode{is_placeholder} to detect placeholders. +The class template +\tcode{bitset} +describes an object that can store a sequence consisting of a fixed number of +bits, \tcode{N}. \pnum -Specializations of the \tcode{is_placeholder} template shall meet -the \oldconcept{UnaryTypeTrait} requirements\iref{meta.rqmts}. The implementation -provides a definition that has the base characteristic of -\tcode{integral_constant} if \tcode{T} is the type of -\tcode{std::placeholders::_\placeholder{J}}, otherwise it has a -base characteristic of \tcode{integral_constant}. A program -may specialize this template for a program-defined type \tcode{T} to -have a base characteristic of \tcode{integral_constant} -with \tcode{N > 0} to indicate that \tcode{T} should be -treated as a placeholder type. - -\rSec3[func.bind.bind]{Function template \tcode{bind}} -\indexlibrary{\idxcode{bind}|(} +Each bit represents either the value zero (reset) or one (set). +To +\term{toggle} +a bit is to change the value zero to one, or the value one to +zero. +Each bit has a non-negative position \tcode{pos}. +When converting +between an object of class +\tcode{bitset} +and a value of some +integral type, bit position \tcode{pos} corresponds to the +\term{bit value} +\tcode{1 << pos}. +The integral value corresponding to two +or more bits is the sum of their bit values. \pnum -In the text that follows: +The functions described in \ref{template.bitset} can report three kinds of +errors, each associated with a distinct exception: \begin{itemize} -\item \tcode{g} is a value of the result of a \tcode{bind} invocation, -\item \tcode{FD} is the type \tcode{decay_t}, -\item \tcode{fd} is an lvalue that - is a target object of \tcode{g}\iref{func.def} of type \tcode{FD} - direct-non-list-initialized with \tcode{std::forward(f)}, -\item $\tcode{T}_i$ is the $i^\text{th}$ type in the template parameter pack \tcode{BoundArgs}, -\item $\tcode{TD}_i$ is the type \tcode{decay_t<$\tcode{T}_i$>}, -\item $\tcode{t}_i$ is the $i^\text{th}$ argument in the function parameter pack \tcode{bound_args}, -\item $\tcode{td}_i$ is a bound argument entity - of \tcode{g}\iref{func.def} of type $\tcode{TD}_i$ - direct-non-list-initialized with - \tcode{std::forward<\brk{}$\tcode{T}_i$>($\tcode{t}_i$)}, -\item $\tcode{U}_j$ is the $j^\text{th}$ deduced type of the \tcode{UnBoundArgs\&\&...} parameter - of the argument forwarding call wrapper, and -\item $\tcode{u}_j$ is the $j^\text{th}$ argument associated with $\tcode{U}_j$. +\item +an +\term{invalid-argument} +error is associated with exceptions of type +\tcode{invalid_argument}\iref{invalid.argument}; +\indexlibraryglobal{invalid_argument}% +\item +an +\term{out-of-range} +error is associated with exceptions of type +\tcode{out_of_range}\iref{out.of.range}; +\indexlibraryglobal{out_of_range}% +\item +an +\term{overflow} +error is associated with exceptions of type +\tcode{overflow_error}\iref{overflow.error}. +\indexlibraryglobal{overflow_error}% \end{itemize} -\indexlibraryglobal{bind}% +\rSec3[bitset.cons]{Constructors} + +\indexlibraryctor{bitset}% \begin{itemdecl} -template - constexpr @\unspec@ bind(F&& f, BoundArgs&&... bound_args); -template - constexpr @\unspec@ bind(F&& f, BoundArgs&&... bound_args); +constexpr bitset() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{is_constructible_v} is \tcode{true}. For each $\tcode{T}_i$ -in \tcode{BoundArgs}, \tcode{is_cons\-tructible_v<$\tcode{TD}_i$, $\tcode{T}_i$>} is \tcode{true}. - -\pnum -\expects -\tcode{FD} and each $\tcode{TD}_i$ meet -the \oldconcept{MoveConstructible} and \oldconcept{Destructible} requirements. -\tcode{\placeholdernc{INVOKE}(fd, $\tcode{w}_1$, $\tcode{w}_2$, $\dotsc$, -$\tcode{w}_N$)}\iref{func.require} is a valid expression for some -values $\tcode{w}_1$, $\tcode{w}_2$, $\dotsc{}$, $\tcode{w}_N$, where -$N$ has the value \tcode{sizeof...(bound_args)}. - -\pnum -\returns -An argument forwarding call wrapper \tcode{g}\iref{func.require}. -A program that attempts to invoke a volatile-qualified \tcode{g} -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 -\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$@)) -\end{codeblock} -for the first overload, and -\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$@)) -\end{codeblock} -for the second overload, -where the values and types of the target argument $\tcode{v}_\tcode{fd}$ and -of the bound arguments -$\tcode{v}_1$, $\tcode{v}_2$, $\dotsc$, $\tcode{v}_N$ are determined as specified below. - -\pnum -\throws -Any exception thrown by the initialization of -the state entities of \tcode{g}. - -\pnum -\begin{note} -If all of \tcode{FD} and $\tcode{TD}_i$ meet -the requirements of \oldconcept{CopyConstructible}, then -the return type meets the requirements of \oldconcept{CopyConstructible}. -\end{note} +\effects +Initializes all bits in \tcode{*this} to zero. \end{itemdescr} -\pnum -\indextext{bound arguments}% -The values of the \term{bound arguments} $\tcode{v}_1$, $\tcode{v}_2$, $\dotsc$, $\tcode{v}_N$ and their -corresponding types $\tcode{V}_1$, $\tcode{V}_2$, $\dotsc$, $\tcode{V}_N$ depend on the -types $\tcode{TD}_i$ derived from -the call to \tcode{bind} and the -cv-qualifiers \cv{} of the call wrapper \tcode{g} as follows: -\begin{itemize} -\item if $\tcode{TD}_i$ is \tcode{reference_wrapper}, the -argument is \tcode{$\tcode{td}_i$.get()} and its type $\tcode{V}_i$ is \tcode{T\&}; - -\item if the value of \tcode{is_bind_expression_v<$\tcode{TD}_i$>} -is \tcode{true}, the argument is -\begin{codeblock} -static_cast<@\cv{} $\tcode{TD}_i$@&>(@$\tcode{td}_i$@)(std::forward<@$\tcode{U}_j$@>(@$\tcode{u}_j$@)...) -\end{codeblock} -and its type $\tcode{V}_i$ is -\tcode{invoke_result_t<\cv{} $\tcode{TD}_i$\&, $\tcode{U}_j$...>\&\&}; - -\item if the value \tcode{j} of \tcode{is_placeholder_v<$\tcode{TD}_i$>} -is not zero, the argument is \tcode{std::forward<$\tcode{U}_j$>($\tcode{u}_j$)} -and its type $\tcode{V}_i$ -is \tcode{$\tcode{U}_j$\&\&}; - -\item otherwise, the value is $\tcode{td}_i$ and its type $\tcode{V}_i$ -is \tcode{\cv{} $\tcode{TD}_i$\&}. -\end{itemize} +\indexlibraryctor{bitset}% +\begin{itemdecl} +constexpr bitset(unsigned long long val) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -The value of the target argument $\tcode{v}_\tcode{fd}$ is \tcode{fd} and -its corresponding type $\tcode{V}_\tcode{fd}$ is \tcode{\cv{} FD\&}. -\indexlibrary{\idxcode{bind}|)}% - -\rSec3[func.bind.place]{Placeholders} +\effects +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{term.object.representation} of \tcode{unsigned long long}. +If \tcode{M < N}, the remaining bit positions are initialized to zero. +\end{itemdescr} -\indexlibraryglobal{placeholders}% -\indexlibrary{1@\tcode{_1}}% -\indexlibrary{2@\tcode{_2}}% -\indexlibrary{3@\tcode{_3}}% -\indexlibrary{4@\tcode{_4}}% -\indexlibrary{5@\tcode{_5}}% -\indexlibrary{6@\tcode{_6}}% -\indexlibrary{7@\tcode{_7}}% -\indexlibrary{8@\tcode{_8}}% -\indexlibrary{9@\tcode{_9}}% -\indexlibrary{10@\tcode{_10}}% -% FIXME: Fomatting for M and the members _1, _2, _M below, -% as well as their usages elsewhere is inconsistent. -% Should they all follow the formatting used in delcaration of -% "namespace placeholders" in [functional.syn]? -\begin{codeblock} -namespace std::placeholders { - // M is the number of placeholders - @\seebelow@ _1; - @\seebelow@ _2; - . - . - . - @\seebelow@ _M; -} -\end{codeblock} +\indexlibraryctor{bitset}% +\begin{itemdecl} +template + constexpr explicit bitset( + const basic_string& str, + typename basic_string::size_type pos = 0, + typename basic_string::size_type n + = basic_string::npos, + charT zero = charT('0'), + charT one = charT('1')); +template + constexpr explicit bitset( + basic_string_view str, + typename basic_string_view::size_type pos = 0, + typename basic_string_view::size_type n + = basic_string_view::npos, + charT zero = charT('0'), + charT one = charT('1')); +\end{itemdecl} +\begin{itemdescr} \pnum -The number \tcode{\placeholder{M}} of placeholders is -\impldef{number of placeholders for bind expressions}. +\effects +Determines the effective length +\tcode{rlen} of the initializing string as the smaller of +\tcode{n} and +\tcode{str.size() - pos}. +Initializes the first \tcode{M} bit +positions to values determined from the corresponding characters in the string +\tcode{str}. +\tcode{M} is the smaller of \tcode{N} and \tcode{rlen}. \pnum -All placeholder types meet the \oldconcept{DefaultConstructible} and -\oldconcept{CopyConstructible} requirements, and -their default constructors and copy/move -constructors are constexpr functions that -do not throw exceptions. It is \impldef{assignability of placeholder -objects} whether -placeholder types meet the \oldconcept{CopyAssignable} requirements, -but if so, their copy assignment operators are -constexpr functions that do not throw exceptions. +An element of the constructed object has value zero if the +corresponding character in \tcode{str}, beginning at position +\tcode{pos}, is +\tcode{zero}. +Otherwise, the element has the value one. +Character position \tcode{pos + M - 1} corresponds to bit position zero. +Subsequent decreasing character positions correspond to increasing bit positions. \pnum -Placeholders should be defined as: -\begin{codeblock} -inline constexpr @\unspec@ _1{}; -\end{codeblock} -If they are not, they are declared as: -\begin{codeblock} -extern @\unspec@ _1; -\end{codeblock}% -\indextext{function object!binders|)} +If \tcode{M < N}, remaining bit positions are initialized to zero. \pnum -\indextext{placeholders!freestanding item}% -Placeholders are freestanding items\iref{freestanding.item}. +The function uses \tcode{traits::eq} +to compare the character values. -\rSec2[func.memfn]{Function template \tcode{mem_fn}}% -\indextext{function object!\idxcode{mem_fn}|(} +\pnum +\throws +\indexlibraryglobal{out_of_range}% +\tcode{out_of_range} if \tcode{pos > str.size()} or +\indexlibraryglobal{invalid_argument}% +\tcode{invalid_argument} if any of +the \tcode{rlen} characters in \tcode{str} +beginning at position \tcode{pos} +is other than \tcode{zero} or \tcode{one}. +\end{itemdescr} -\indexlibraryglobal{mem_fn}% +\indexlibraryctor{bitset}% \begin{itemdecl} -template constexpr @\unspec@ mem_fn(R T::* pm) noexcept; +template + constexpr explicit bitset( + const charT* str, + typename basic_string_view::size_type n = basic_string_view::npos, + charT zero = charT('0'), + charT one = charT('1')); \end{itemdecl} \begin{itemdescr} \pnum -\returns -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 -\tcode{call_args} is an argument pack -used in a function call expression\iref{expr.call} of \tcode{fn}. +\effects +As if by: +\begin{codeblock} +bitset(n == basic_string_view::npos + ? basic_string_view(str) + : basic_string_view(str, n), + 0, n, zero, one) +\end{codeblock} \end{itemdescr} -\indextext{function object!\idxcode{mem_fn}|)} -\rSec2[func.wrap]{Polymorphic function wrappers}% -\rSec3[func.wrap.general]{General}% -\indextext{function object!wrapper|(} +\rSec3[bitset.members]{Members} -\pnum -Subclause \ref{func.wrap} describes polymorphic wrapper classes that -encapsulate arbitrary callable objects. +\indexlibrarymember{operator\&=}{bitset}% +\begin{itemdecl} +constexpr bitset& operator&=(const bitset& rhs) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -Let \tcode{t} be an object of a type that is a specialization of -\tcode{function}, \tcode{copyable_function}, or \tcode{move_only_function}, -such that the target object \tcode{x} of \tcode{t} has a type that -is a specialization of -\tcode{function}, \tcode{copyable_function}, or \tcode{move_only_function}. -Each argument of the -invocation of \tcode{x} evaluated as part of the invocation of \tcode{t} -may alias an argument in the same position in the invocation of \tcode{t} that -has the same type, even if the corresponding parameter is not of reference type. -\begin{example} -\begin{codeblock} -move_only_function - f{copyable_function{[](T) {}}}; -T t; -f(t); // it is unspecified how many copies of \tcode{T} are made -\end{codeblock} -\end{example} +\effects +Clears each bit in +\tcode{*this} +for which the corresponding bit in \tcode{rhs} is clear, and leaves all other bits unchanged. \pnum -\recommended -Implementations should avoid double wrapping when -constructing polymorphic wrappers from one another. +\returns +\tcode{*this}. +\end{itemdescr} -\rSec3[func.wrap.badcall]{Class \tcode{bad_function_call}}% -\indexlibraryglobal{bad_function_call}% +\indexlibrarymember{operator"|=}{bitset}% +\begin{itemdecl} +constexpr bitset& operator|=(const bitset& rhs) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -An exception of type \tcode{bad_function_call} is thrown by -\tcode{function::operator()}\iref{func.wrap.func.inv} -when the function wrapper object has no target. +\effects +Sets each bit in +\tcode{*this} +for which the corresponding bit in \tcode{rhs} is set, and leaves all other bits unchanged. -\begin{codeblock} -namespace std { - class bad_function_call : public exception { - public: - // see \ref{exception} for the specification of the special member functions - const char* what() const noexcept override; - }; -} -\end{codeblock} +\pnum +\returns +\tcode{*this}. +\end{itemdescr} -\indexlibrarymember{what}{bad_function_call}% +\indexlibrarymember{operator\caret=}{bitset}% \begin{itemdecl} -const char* what() const noexcept override; +constexpr bitset& operator^=(const bitset& rhs) noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\effects +Toggles each bit in +\tcode{*this} +for which the corresponding bit in \tcode{rhs} is set, and leaves all other bits unchanged. + \pnum \returns -An -\impldef{return value of \tcode{bad_function_call::what}} \ntbs{}. +\tcode{*this}. \end{itemdescr} -\rSec3[func.wrap.func]{Class template \tcode{function}} +\indexlibrarymember{operator<<=}{bitset}% +\begin{itemdecl} +constexpr bitset& operator<<=(size_t pos) noexcept; +\end{itemdecl} -\rSec4[func.wrap.func.general]{General} -\indexlibraryglobal{function}% +\begin{itemdescr} +\pnum +\effects +Replaces each bit at position \tcode{I} in +\tcode{*this} +with a value determined as follows: -\indexlibrarymember{result_type}{function}% -\begin{codeblock} -namespace std { - template - class function { - public: - using result_type = R; +\begin{itemize} +\item +If \tcode{I < pos}, the new value is zero; +\item +If \tcode{I >= pos}, the new value is the previous +value of the bit at position \tcode{I - pos}. +\end{itemize} - // \ref{func.wrap.func.con}, construct/copy/destroy - function() noexcept; - function(nullptr_t) noexcept; - function(const function&); - function(function&&) noexcept; - template function(F&&); +\pnum +\returns +\tcode{*this}. +\end{itemdescr} - function& operator=(const function&); - function& operator=(function&&); - function& operator=(nullptr_t) noexcept; - template function& operator=(F&&); - template function& operator=(reference_wrapper) noexcept; +\indexlibrarymember{operator>>=}{bitset}% +\begin{itemdecl} +constexpr bitset& operator>>=(size_t pos) noexcept; +\end{itemdecl} - ~function(); +\begin{itemdescr} +\pnum +\effects +Replaces each bit at position \tcode{I} in +\tcode{*this} +with a value determined as follows: - // \ref{func.wrap.func.mod}, function modifiers - void swap(function&) noexcept; +\begin{itemize} +\item +If \tcode{pos >= N - I}, the new value is zero; +\item +If \tcode{pos < N - I}, the new value is the previous value of the bit at position \tcode{I + pos}. +\end{itemize} - // \ref{func.wrap.func.cap}, function capacity - explicit operator bool() const noexcept; +\pnum +\returns +\tcode{*this}. +\end{itemdescr} - // \ref{func.wrap.func.inv}, function invocation - R operator()(ArgTypes...) const; +\indexlibrarymember{operator<<}{bitset}% +\begin{itemdecl} +constexpr bitset operator<<(size_t pos) const noexcept; +\end{itemdecl} - // \ref{func.wrap.func.targ}, function target access - const type_info& target_type() const noexcept; - template T* target() noexcept; - template const T* target() const noexcept; - }; +\begin{itemdescr} +\pnum +\returns +\tcode{bitset(*this) <<= pos}. +\end{itemdescr} - template - function(R(*)(ArgTypes...)) -> function; +\indexlibrarymember{operator>>}{bitset}% +\begin{itemdecl} +constexpr bitset operator>>(size_t pos) const noexcept; +\end{itemdecl} - template function(F) -> function<@\seebelow@>; -} -\end{codeblock} +\begin{itemdescr} +\pnum +\returns +\tcode{bitset(*this) >>= pos}. +\end{itemdescr} + +% Do not use \indexlibrarymember. +\indexlibrary{\idxcode{set} (member)!\idxcode{bitset}}% +\indexlibrary{\idxcode{bitset}!\idxcode{set}}% +\begin{itemdecl} +constexpr bitset& set() noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -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}. +\effects +Sets all bits in +\tcode{*this}. \pnum -\indextext{callable type}% -A callable type\iref{func.def} \tcode{F} -is \defn{Lvalue-Callable} for argument -types \tcode{ArgTypes} -and return type \tcode{R} -if the expression -\tcode{\placeholdernc{INVOKE}(declval(), declval()...)}, -considered as an unevaluated operand\iref{term.unevaluated.operand}, is -well-formed\iref{func.require}. +\returns +\tcode{*this}. +\end{itemdescr} + +% Do not use \indexlibrarymember. +\indexlibrary{\idxcode{set} (member)!\idxcode{bitset}}% +\indexlibrary{\idxcode{bitset}!\idxcode{set}}% +\begin{itemdecl} +constexpr bitset& set(size_t pos, bool val = true); +\end{itemdecl} +\begin{itemdescr} \pnum -The \tcode{function} class template is a call -wrapper\iref{func.def} whose call signature\iref{func.def} -is \tcode{R(ArgTypes...)}. +\effects +Stores a new value in the bit at position \tcode{pos} in +\tcode{*this}. +If \tcode{val} is \tcode{true}, the stored value is one, otherwise it is zero. \pnum -\begin{note} -The types deduced by the deduction guides for \tcode{function} -might change in future revisions of \Cpp{}. -\end{note} +\returns +\tcode{*this}. -\rSec4[func.wrap.func.con]{Constructors and destructor} +\pnum +\throws +\indexlibraryglobal{out_of_range}% +\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. +\end{itemdescr} -\indexlibraryctor{function}% +\indexlibrarymember{reset}{bitset}% \begin{itemdecl} -function() noexcept; +constexpr bitset& reset() noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{!*this}. +\effects +Resets all bits in +\tcode{*this}. + +\pnum +\returns +\tcode{*this}. \end{itemdescr} -\indexlibraryctor{function}% +\indexlibrarymember{reset}{bitset}% \begin{itemdecl} -function(nullptr_t) noexcept; +constexpr bitset& reset(size_t pos); \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{!*this}. +\effects +Resets the bit at position \tcode{pos} in +\tcode{*this}. + +\pnum +\returns +\tcode{*this}. + +\pnum +\throws +\indexlibraryglobal{out_of_range}% +\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. \end{itemdescr} -\indexlibraryctor{function}% +\indexlibrarymember{operator\~{}}{bitset}% \begin{itemdecl} -function(const function& f); +constexpr bitset operator~() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{!*this} if \tcode{!f}; otherwise, -the target object of \tcode{*this} is a copy of \tcode{f.target()}. +\effects +Constructs an object \tcode{x} of class +\tcode{bitset} +and initializes it with +\tcode{*this}. \pnum -\throws -Nothing if \tcode{f}'s target is -a specialization of \tcode{reference_wrapper} or -a function pointer. Otherwise, may throw \tcode{bad_alloc} -or any exception thrown by the copy constructor of the stored callable object. +\returns +\tcode{x.flip()}. +\end{itemdescr} + +\indexlibrarymember{flip}{bitset}% +\begin{itemdecl} +constexpr bitset& flip() noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\recommended -Implementations should avoid the use of -dynamically allocated memory for small callable objects, for example, where -\tcode{f}'s target is an object holding only a pointer or reference -to an object and a member function pointer. +\effects +Toggles all bits in +\tcode{*this}. + +\pnum +\returns +\tcode{*this}. \end{itemdescr} -\indexlibraryctor{function}% +\indexlibrarymember{flip}{bitset}% \begin{itemdecl} -function(function&& f) noexcept; +constexpr bitset& flip(size_t pos); \end{itemdecl} \begin{itemdescr} \pnum -\ensures -If \tcode{!f}, \tcode{*this} has no target; -otherwise, the target of \tcode{*this} is equivalent to -the target of \tcode{f} before the construction, and -\tcode{f} is in a valid state with an unspecified value. +\effects +Toggles the bit at position \tcode{pos} in +\tcode{*this}. \pnum -\recommended -Implementations should avoid the use of -dynamically allocated memory for small callable objects, for example, -where \tcode{f}'s target is an object holding only a pointer or reference -to an object and a member function pointer. +\returns +\tcode{*this}. + +\pnum +\throws +\indexlibraryglobal{out_of_range}% +\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. \end{itemdescr} -\indexlibraryctor{function}% +\indexlibrarymember{operator[]}{bitset}% \begin{itemdecl} -template function(F&& f); +constexpr bool operator[](size_t pos) const; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{FD} be \tcode{decay_t}. +\hardexpects +\tcode{pos < size()} is \tcode{true}. \pnum -\constraints -\begin{itemize} -\item -\tcode{is_same_v, function>} is \tcode{false}, and -\item -\tcode{FD} is Lvalue-Callable\iref{func.wrap.func} for argument types -\tcode{ArgTypes...} and return type \tcode{R}. -\end{itemize} +\returns +\tcode{true} if the bit at position \tcode{pos} in \tcode{*this} has the value +one, otherwise \tcode{false}. \pnum -\mandates -\begin{itemize} -\item -\tcode{is_copy_constructible_v} is \tcode{true}, and -\item -\tcode{is_constructible_v} is \tcode{true}. -\end{itemize} +\throws +Nothing. +\end{itemdescr} -\pnum -\expects -\tcode{FD} meets the \oldconcept{CopyConstructible} requirements. +\indexlibrarymember{operator[]}{bitset}% +\begin{itemdecl} +constexpr bitset::reference operator[](size_t pos); +\end{itemdecl} +\begin{itemdescr} \pnum -\ensures -\tcode{!*this} is \tcode{true} if any of the following hold: -\begin{itemize} -\item \tcode{f} is a null function pointer value. -\item \tcode{f} is a null member pointer value. -\item \tcode{remove_cvref_t} is -a specialization of the \tcode{function} class template, and -\tcode{!f} is \tcode{true}. -\end{itemize} +\hardexpects +\tcode{pos < size()} is \tcode{true}. \pnum -Otherwise, \tcode{*this} has a target object of type \tcode{FD} -direct-non-list-initialized with \tcode{std::forward(f)}. +\returns +An object of type +\tcode{bitset::reference} +such that +\tcode{(*this)[pos] == this->test(pos)}, +and such that +\tcode{(*this)[pos] = val} +is equivalent to +\tcode{this->set(pos, val)}. \pnum \throws -Nothing if \tcode{FD} is -a specialization of \tcode{reference_wrapper} or -a function pointer type. -Otherwise, may throw \tcode{bad_alloc} or -any exception thrown by the initialization of the target object. +Nothing. \pnum -\recommended -Implementations should avoid the use of -dynamically allocated memory for small callable objects, for example, -where \tcode{f} refers to an object holding only a pointer or -reference to an object and a member function pointer. +\remarks +For the purpose of determining the presence of a data +race\iref{intro.multithread}, any access or update through the resulting +reference potentially accesses or modifies, respectively, the entire +underlying bitset. \end{itemdescr} - +\indexlibrarymember{to_ulong}{bitset}% \begin{itemdecl} -template function(F) -> function<@\seebelow@>; +constexpr unsigned long to_ulong() const; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{\&F::operator()} is well-formed when treated as an unevaluated operand and either -\begin{itemize} -\item -\tcode{F::operator()} is a non-static member function and -\tcode{decltype(\brk{}\&F::operator())} is either of the form -\tcode{R(G::*)(A...)}~\cv{}~\tcode{\opt{\&}~\opt{noexcept}} -or of the form -\tcode{R(*)(G, A...)~\opt{noexcept}} -for a type \tcode{G}, or -\item -\tcode{F::operator()} is a static member function and -\tcode{decltype(\&F::operator())} is of the form -\tcode{R(*)(A...) \opt{noexcept}}. -\end{itemize} +\returns +\tcode{x}. \pnum -\remarks -The deduced type is \tcode{function}. +\throws +\indexlibraryglobal{overflow_error}% +\tcode{overflow_error} if the integral value \tcode{x} +corresponding to the bits in \tcode{*this} +cannot be represented as type \tcode{unsigned long}. +\end{itemdescr} + +\indexlibrarymember{to_ullong}{bitset}% +\begin{itemdecl} +constexpr unsigned long long to_ullong() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x}. \pnum -\begin{example} -\begin{codeblock} -void f() { - int i{5}; - function g = [&](double) { return i; }; // deduces \tcode{function} -} -\end{codeblock} -\end{example} +\throws +\indexlibraryglobal{overflow_error}% +\tcode{overflow_error} if the integral value \tcode{x} +corresponding to the bits in \tcode{*this} +cannot be represented as type \tcode{unsigned long long}. \end{itemdescr} -\indexlibrarymember{operator=}{function}% +\indexlibrarymember{to_string}{bitset}% \begin{itemdecl} -function& operator=(const function& f); +template, + class Allocator = allocator> + constexpr basic_string + to_string(charT zero = charT('0'), charT one = charT('1')) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -As if by \tcode{function(f).swap(*this);} +Constructs a string object of the appropriate type +and initializes it to a string of length \tcode{N} characters. +Each character is determined by the value of its corresponding bit position in +\tcode{*this}. +Character position \tcode{N - 1} corresponds to bit position zero. +Subsequent decreasing character positions correspond to increasing bit +positions. +Bit value zero becomes the character \tcode{zero}, +bit value one becomes the character +\tcode{one}. \pnum \returns -\tcode{*this}. +The created object. \end{itemdescr} -\indexlibrarymember{operator=}{function}% +\indexlibrarymember{count}{bitset}% \begin{itemdecl} -function& operator=(function&& f); +constexpr size_t count() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -\effects -Replaces the target of \tcode{*this} -with the target of \tcode{f}. - \pnum \returns +A count of the number of bits set in \tcode{*this}. \end{itemdescr} -\indexlibrarymember{operator=}{function}% +\indexlibrarymember{size}{bitset}% \begin{itemdecl} -function& operator=(nullptr_t) noexcept; +constexpr size_t size() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -If \tcode{*this != nullptr}, destroys the target of \keyword{this}. +\returns +\tcode{N}. +\end{itemdescr} -\pnum -\ensures -\tcode{!(*this)}. +\indexlibrarymember{operator==}{bitset}% +\begin{itemdecl} +constexpr bool operator==(const bitset& rhs) const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{*this}. +\tcode{true} if the value of each bit in +\tcode{*this} +equals the value of the corresponding bit in \tcode{rhs}. \end{itemdescr} -\indexlibrarymember{operator=}{function}% +\indexlibrarymember{test}{bitset}% \begin{itemdecl} -template function& operator=(F&& f); +constexpr bool test(size_t pos) const; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{decay_t} is Lvalue-Callable\iref{func.wrap.func} -for argument types \tcode{ArgTypes...} and return type \tcode{R}. +\returns +\tcode{true} +if the bit at position \tcode{pos} +in +\tcode{*this} +has the value one. \pnum -\effects -As if by: \tcode{function(std::forward(f)).swap(*this);} +\throws +\indexlibraryglobal{out_of_range}% +\tcode{out_of_range} if \tcode{pos} does not correspond to a valid bit position. +\end{itemdescr} + +\indexlibrarymember{all}{bitset}% +\begin{itemdecl} +constexpr bool all() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{*this}. +\tcode{count() == size()}. \end{itemdescr} -\indexlibrarymember{operator=}{function}% +% Do not use \indexlibrarymember. +\indexlibrary{\idxcode{any} (member)!\idxcode{bitset}}% +\indexlibrary{\idxcode{bitset}!\idxcode{any}}% \begin{itemdecl} -template function& operator=(reference_wrapper f) noexcept; +constexpr bool any() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -As if by: \tcode{function(f).swap(*this);} +\returns +\tcode{count() != 0}. +\end{itemdescr} +\indexlibrarymember{none}{bitset}% +\begin{itemdecl} +constexpr bool none() const noexcept; +\end{itemdecl} + +\begin{itemdescr} \pnum \returns -\tcode{*this}. +\tcode{count() == 0}. \end{itemdescr} -\indexlibrarydtor{function}% +\rSec2[bitset.hash]{\tcode{bitset} hash support} + +\indexlibraryglobal{hash_code}% \begin{itemdecl} -~function(); +template struct hash>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -If \tcode{*this != nullptr}, destroys the target of \keyword{this}. +The specialization is enabled\iref{unord.hash}. \end{itemdescr} -\rSec4[func.wrap.func.mod]{Modifiers} -\indexlibrarymember{swap}{function}% +\rSec2[bitset.operators]{\tcode{bitset} operators} + +\indexlibrarymember{operator\&}{bitset}% \begin{itemdecl} -void swap(function& other) noexcept; +template + constexpr bitset operator&(const bitset& lhs, const bitset& rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Interchanges the target objects of \tcode{*this} and \tcode{other}. +\returns +\tcode{bitset(lhs) \&= rhs}. \end{itemdescr} -\rSec4[func.wrap.func.cap]{Capacity} +\indexlibrarymember{operator"|}{bitset}% +\begin{itemdecl} +template + constexpr bitset operator|(const bitset& lhs, const bitset& rhs) noexcept; +\end{itemdecl} -\indexlibrarymember{operator bool}{function}% +\begin{itemdescr} +\pnum +\returns +\tcode{bitset(lhs) |= rhs}. +\end{itemdescr} + +\indexlibrarymember{operator\caret}{bitset}% \begin{itemdecl} -explicit operator bool() const noexcept; +template + constexpr bitset operator^(const bitset& lhs, const bitset& rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{true} if \tcode{*this} has a target, otherwise \tcode{false}. +\tcode{bitset(lhs) \caret= rhs}. \end{itemdescr} -\rSec4[func.wrap.func.inv]{Invocation} +\indexlibrarymember{operator>>}{bitset}% +\begin{itemdecl} +template + basic_istream& + operator>>(basic_istream& is, bitset& x); +\end{itemdecl} -\indexlibrary{\idxcode{function}!invocation}% -\indexlibrarymember{operator()}{function}% +\begin{itemdescr} +\pnum +A formatted input function\iref{istream.formatted}. + +\pnum +\effects +Extracts up to \tcode{N} characters from \tcode{is}. +Stores these characters in a temporary object \tcode{str} of type +\tcode{basic_string}, +then evaluates the expression +\tcode{x = bitset(str)}. +Characters are extracted and stored until any of the following occurs: +\begin{itemize} +\item +\tcode{N} characters have been extracted and stored; +\item +\indextext{end-of-file}% +end-of-file occurs on the input sequence; +\item +the next input character is neither +\tcode{is.widen('0')} +nor +\tcode{is.widen('1')} +(in which case the input character is not extracted). +\end{itemize} + +\pnum +If \tcode{N > 0} and no characters are stored in \tcode{str}, +\tcode{ios_base::failbit} is set in the input function's local error state +before \tcode{setstate} is called. + +\pnum +\returns +\tcode{is}. +\end{itemdescr} + +\indexlibrarymember{operator<<}{bitset}% \begin{itemdecl} -R operator()(ArgTypes... args) const; +template + basic_ostream& + operator<<(basic_ostream& os, const bitset& x); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{\placeholdernc{INVOKE}(f, std::forward(args)...)}\iref{func.require}, -where \tcode{f} is the target object\iref{func.def} of \tcode{*this}. +\begin{codeblock} +os << x.template to_string>( + use_facet>(os.getloc()).widen('0'), + use_facet>(os.getloc()).widen('1')) +\end{codeblock} +(see~\ref{ostream.formatted}). +\end{itemdescr} + +\rSec1[function.objects]{Function objects} + +\rSec2[function.objects.general]{General} + +\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\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 +which has a conversion to a pointer to function. +\end{footnote} +A \defn{function object} is an +object of a function object type. In the places where one would expect to pass a +pointer to a function to an algorithmic template\iref{algorithms}, the +interface is specified to accept a function object. This not only makes +algorithmic templates work with pointers to functions, but also enables them to +work with arbitrary function objects. + +\rSec2[functional.syn]{Header \tcode{} synopsis} + +\indexheader{functional}% +\indexlibraryglobal{unwrap_ref_decay}% +\indexlibraryglobal{unwrap_ref_decay_t}% +\begin{codeblock} +namespace std { + // \ref{func.invoke}, invoke + template + constexpr invoke_result_t invoke(F&& f, Args&&... args) // freestanding + noexcept(is_nothrow_invocable_v); + + template + constexpr R invoke_r(F&& f, Args&&... args) // freestanding + noexcept(is_nothrow_invocable_r_v); + + // \ref{refwrap}, \tcode{reference_wrapper} + template class reference_wrapper; // freestanding + + template constexpr reference_wrapper ref(T&) noexcept; // freestanding + template constexpr reference_wrapper cref(const T&) noexcept; // freestanding + template void ref(const T&&) = delete; // freestanding + template void cref(const T&&) = delete; // freestanding -\pnum -\throws -\tcode{bad_function_call} if \tcode{!*this}; otherwise, any -exception thrown by the target object. -\end{itemdescr} + template + constexpr reference_wrapper ref(reference_wrapper) noexcept; // freestanding + template + constexpr reference_wrapper cref(reference_wrapper) noexcept; // freestanding -\rSec4[func.wrap.func.targ]{Target access} + // \ref{refwrap.common.ref}, \tcode{common_reference} related specializations + template class RQual, template class TQual> + requires @\seebelow@ + struct basic_common_reference; -\indexlibrarymember{target_type}{function}% -\begin{itemdecl} -const type_info& target_type() const noexcept; -\end{itemdecl} + template class TQual, template class RQual> + requires @\seebelow@ + struct basic_common_reference; -\begin{itemdescr} -\pnum -\returns -If \tcode{*this} has a target of type \tcode{T}, - \tcode{typeid(T)}; otherwise, \tcode{typeid(void)}. -\end{itemdescr} + // \ref{arithmetic.operations}, arithmetic operations + template struct plus; // freestanding + template struct minus; // freestanding + template struct multiplies; // freestanding + template struct divides; // freestanding + template struct modulus; // freestanding + template struct negate; // freestanding + template<> struct plus; // freestanding + template<> struct minus; // freestanding + template<> struct multiplies; // freestanding + template<> struct divides; // freestanding + template<> struct modulus; // freestanding + template<> struct negate; // freestanding -\indexlibrarymember{target}{function}% -\begin{itemdecl} -template T* target() noexcept; -template const T* target() const noexcept; -\end{itemdecl} + // \ref{comparisons}, comparisons + template struct equal_to; // freestanding + template struct not_equal_to; // freestanding + template struct greater; // freestanding + template struct less; // freestanding + template struct greater_equal; // freestanding + template struct less_equal; // freestanding + template<> struct equal_to; // freestanding + template<> struct not_equal_to; // freestanding + template<> struct greater; // freestanding + template<> struct less; // freestanding + template<> struct greater_equal; // freestanding + template<> struct less_equal; // freestanding -\begin{itemdescr} -\pnum -\returns -If \tcode{target_type() == typeid(T)} -a pointer to the stored function target; otherwise a null pointer. -\end{itemdescr} + // \ref{comparisons.three.way}, class \tcode{compare_three_way} + struct compare_three_way; // freestanding -\rSec4[func.wrap.func.nullptr]{Null pointer comparison operator functions} + // \ref{logical.operations}, logical operations + template struct logical_and; // freestanding + template struct logical_or; // freestanding + template struct logical_not; // freestanding + template<> struct logical_and; // freestanding + template<> struct logical_or; // freestanding + template<> struct logical_not; // freestanding -\indexlibrarymember{operator==}{function}% -\begin{itemdecl} -template - bool operator==(const function& f, nullptr_t) noexcept; -\end{itemdecl} + // \ref{bitwise.operations}, bitwise operations + template struct bit_and; // freestanding + template struct bit_or; // freestanding + template struct bit_xor; // freestanding + template struct bit_not; // freestanding + template<> struct bit_and; // freestanding + template<> struct bit_or; // freestanding + template<> struct bit_xor; // freestanding + template<> struct bit_not; // freestanding -\begin{itemdescr} -\pnum -\returns -\tcode{!f}. -\end{itemdescr} + // \ref{func.identity}, identity + struct identity; // freestanding -\rSec4[func.wrap.func.alg]{Specialized algorithms} + // \ref{func.not.fn}, function template \tcode{not_fn} + template constexpr @\unspec@ not_fn(F&& f); // freestanding + template constexpr @\unspec@ not_fn() noexcept; // freestanding -\indexlibrarymember{swap}{function}% -\begin{itemdecl} -template - void swap(function& f1, function& f2) noexcept; -\end{itemdecl} + // \ref{func.bind.partial}, function templates \tcode{bind_front} and \tcode{bind_back} + template + constexpr @\unspec@ bind_front(F&&, Args&&...); // freestanding + template + constexpr @\unspec@ bind_front(Args&&...); // freestanding + template + constexpr @\unspec@ bind_back(F&&, Args&&...); // freestanding + template + constexpr @\unspec@ bind_back(Args&&...); // freestanding -\begin{itemdescr} -\pnum -\effects -As if by: \tcode{f1.swap(f2);} -\end{itemdescr}% + // \ref{func.bind}, bind + template struct is_bind_expression; // freestanding + template + constexpr bool @\libglobal{is_bind_expression_v}@ = // freestanding + is_bind_expression::value; + template struct is_placeholder; // freestanding + template + constexpr int @\libglobal{is_placeholder_v}@ = // freestanding + is_placeholder::value; -\rSec3[func.wrap.move]{Move-only wrapper} + template + constexpr @\unspec@ bind(F&&, BoundArgs&&...); // freestanding + template + constexpr @\unspec@ bind(F&&, BoundArgs&&...); // freestanding -\rSec4[func.wrap.move.general]{General} + namespace placeholders { + // \tcode{\placeholder{M}} is the \impldef{number of placeholders for bind expressions} number of placeholders + @\seebelownc@ _1; // freestanding + @\seebelownc@ _2; // freestanding + @\vdots@ + @\seebelownc@ _@\placeholdernc{M}@; // freestanding + } -\pnum -The header provides partial specializations of \tcode{move_only_function} -for each combination of the possible replacements -of the placeholders \cv{}, \placeholder{ref}, and \placeholder{noex} where -\begin{itemize} -\item -\cv{} is either const or empty, -\item -\placeholder{ref} is either \tcode{\&}, \tcode{\&\&}, or empty, and -\item -\placeholder{noex} is either \tcode{true} or \tcode{false}. -\end{itemize} + // \ref{func.memfn}, member function adaptors + template + constexpr @\unspec@ mem_fn(R T::*) noexcept; // freestanding -\pnum -For each of the possible combinations of the placeholders mentioned above, -there is a placeholder \placeholder{inv-quals} defined as follows: -\begin{itemize} -\item -If \placeholder{ref} is empty, let \placeholder{inv-quals} be \cv{}\tcode{\&}, -\item -otherwise, let \placeholder{inv-quals} be \cv{} \placeholder{ref}. -\end{itemize} + // \ref{func.wrap}, polymorphic function wrappers + // \ref{func.wrap.badcall}, class \tcode{bad_function_call} + class bad_function_call; -\rSec4[func.wrap.move.class]{Class template \tcode{move_only_function}} + // \ref{func.wrap.func}, class template \tcode{function} + template class function; // \notdef + template class function; -\indexlibraryglobal{move_only_function}% -\begin{codeblock} -namespace std { + // \ref{func.wrap.func.alg}, \tcode{function} specialized algorithms template - class move_only_function { - public: - using result_type = R; + void swap(function&, function&) noexcept; - // \ref{func.wrap.move.ctor}, constructors, assignment, and destructor - move_only_function() noexcept; - move_only_function(nullptr_t) noexcept; - move_only_function(move_only_function&&) noexcept; - template move_only_function(F&&); - template - explicit move_only_function(in_place_type_t, Args&&...); - template - explicit move_only_function(in_place_type_t, initializer_list, Args&&...); + // \ref{func.wrap.func.nullptr}, \tcode{function} null pointer comparison operator functions + template + bool operator==(const function&, nullptr_t) noexcept; - move_only_function& operator=(move_only_function&&); - move_only_function& operator=(nullptr_t) noexcept; - template move_only_function& operator=(F&&); + // \ref{func.wrap.move}, move-only wrapper + template class move_only_function; // \notdef + template + class move_only_function; // \seebelow - ~move_only_function(); + // \ref{func.wrap.copy}, copyable wrapper + template class copyable_function; // \notdef + template + class copyable_function; // \seebelow - // \ref{func.wrap.move.inv}, invocation - explicit operator bool() const noexcept; - R operator()(ArgTypes...) @\cv{}@ @\placeholder{ref}@ noexcept(@\placeholder{noex}@); + // \ref{func.wrap.ref}, non-owning wrapper + template class function_ref; // freestanding, \notdef + template + class function_ref; // freestanding, \seebelow - // \ref{func.wrap.move.util}, utility - void swap(move_only_function&) noexcept; - friend void swap(move_only_function&, move_only_function&) noexcept; - friend bool operator==(const move_only_function&, nullptr_t) noexcept; + // \ref{func.search}, searchers + template> + class default_searcher; // freestanding - private: - template - static constexpr bool @\exposid{is-callable-from}@ = @\seebelow@; // \expos - }; -} -\end{codeblock} + template::value_type>, + class BinaryPredicate = equal_to<>> + class boyer_moore_searcher; -\pnum -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. + template::value_type>, + class BinaryPredicate = equal_to<>> + class boyer_moore_horspool_searcher; -\pnum -\recommended -Implementations should avoid the use of dynamically allocated memory -for a small contained value. -\begin{note} -Such small-object optimization can only be applied to a type \tcode{T} -for which \tcode{is_nothrow_move_constructible_v} is \tcode{true}. -\end{note} + // \ref{unord.hash}, class template \tcode{hash} + template + struct hash; // freestanding + + namespace ranges { + // \ref{range.cmp}, concept-constrained comparisons + struct equal_to; // freestanding + struct not_equal_to; // freestanding + struct greater; // freestanding + struct less; // freestanding + struct greater_equal; // freestanding + struct less_equal; // freestanding + } -\rSec4[func.wrap.move.ctor]{Constructors, assignment, and destructor} + template + concept @\defexposconceptnc{callable}@ = // \expos + requires (Fn&& fn, Args&&... args) { + std::forward(fn)(std::forward(args)...); + }; -\indextext{move_only_function::is-callable-from@\tcode{move_only_function::\exposid{is-callable-from}}}% -\begin{itemdecl} -template - static constexpr bool @\exposid{is-callable-from}@ = @\seebelow@; -\end{itemdecl} + template + concept @\defexposconceptnc{nothrow-callable}@ = // \expos + @\exposconcept{callable}@ && + requires (Fn&& fn, Args&&... args) { + { std::forward(fn)(std::forward(args)...) } noexcept; + }; + + template + using @\exposidnc{call-result-t}@ = decltype(declval()(declval()...)); // \expos + + template + using @\exposidnc{decayed-typeof}@ = decltype(auto(T)); // \expos +} +\end{codeblock} -\begin{itemdescr} \pnum -If \placeholder{noex} is \tcode{true}, -\tcode{\exposid{is-callable-from}} is equal to: +\begin{example} +If a \Cpp{} program wants to have a by-element addition of two vectors \tcode{a} +and \tcode{b} containing \tcode{double} and put the result into \tcode{a}, +it can do: + \begin{codeblock} -is_nothrow_invocable_r_v && -is_nothrow_invocable_r_v +transform(a.begin(), a.end(), b.begin(), a.begin(), plus()); \end{codeblock} -Otherwise, \tcode{\exposid{is-callable-from}} is equal to: +\end{example} + +\pnum +\begin{example} +To negate every element of \tcode{a}: + \begin{codeblock} -is_invocable_r_v && -is_invocable_r_v +transform(a.begin(), a.end(), a.begin(), negate()); \end{codeblock} -\end{itemdescr} -\indexlibraryctor{move_only_function}% -\begin{itemdecl} -move_only_function() noexcept; -move_only_function(nullptr_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\ensures -\tcode{*this} has no target object. -\end{itemdescr} +\end{example} -\indexlibraryctor{move_only_function}% -\begin{itemdecl} -move_only_function(move_only_function&& f) noexcept; -\end{itemdecl} +\rSec2[func.def]{Definitions} -\begin{itemdescr} \pnum -\ensures -The target object of \tcode{*this} is -the target object \tcode{f} had before construction, and -\tcode{f} is in a valid state with an unspecified value. -\end{itemdescr} - -\indexlibraryctor{move_only_function}% -\begin{itemdecl} -template move_only_function(F&& f); -\end{itemdecl} +The following definitions apply to this Clause: -\begin{itemdescr} \pnum -Let \tcode{VT} be \tcode{decay_t}. +A \defn{call signature} is the name of a return type followed by a +parenthesized comma-separated list of zero or more argument types. \pnum -\constraints -\begin{itemize} -\item -\tcode{remove_cvref_t} is not the same type as \tcode{move_only_function}, and -\item -\tcode{remove_cvref_t} is not a specialization of \tcode{in_place_type_t}, and -\item -\tcode{\exposid{is-callable-from}} is \tcode{true}. -\end{itemize} +A \defnadj{callable}{type} is a function object type\iref{function.objects} or a pointer to member. \pnum -\mandates -\tcode{is_constructible_v} is \tcode{true}. +A \defnadj{callable}{object} is an object of a callable type. \pnum -\expects -\tcode{VT} meets the \oldconcept{Destructible} requirements, and -if \tcode{is_move_constructible_v} is \tcode{true}, -\tcode{VT} meets the \oldconcept{MoveConstructible} requirements. +A \defnx{call wrapper type}{call wrapper!type} is a type that holds a callable object +and supports a call operation that forwards to that object. \pnum -\ensures -\tcode{*this} has no target object if any of the following hold: -\begin{itemize} -\item -\tcode{f} is a null function pointer value, or -\item -\tcode{f} is a null member pointer value, or -\item -\tcode{remove_cvref_t} is a specialization of -the \tcode{move_only_function} class template, -and \tcode{f} has no target object. -\end{itemize} -Otherwise, \tcode{*this} has a target object of type \tcode{VT} -direct-non-list-initialized with \tcode{std::forward(f)}. +A \defn{call wrapper} is an object of a call wrapper type. \pnum -\throws -Any exception thrown by the initialization of the target object. -May throw \tcode{bad_alloc} unless \tcode{VT} is -a function pointer or a specialization of \tcode{reference_wrapper}. -\end{itemdescr} +A \defn{target object} is the callable object held by a call wrapper. -\indexlibraryctor{move_only_function}% -\begin{itemdecl} -template - explicit move_only_function(in_place_type_t, Args&&... args); -\end{itemdecl} +\pnum +A call wrapper type may additionally hold +a sequence of objects and references +that may be passed as arguments to the target object. +These entities are collectively referred to +as \defnx{bound argument entities}{bound argument entity}. -\begin{itemdescr} \pnum -Let \tcode{VT} be \tcode{decay_t}. +The target object and bound argument entities of the call wrapper are +collectively referred to as \defnx{state entities}{state entity}. + +\rSec2[func.require]{Requirements} \pnum -\constraints +\indextext{invoke@\tcode{\placeholder{INVOKE}}}% +\indexlibrary{invoke@\tcode{\placeholder{INVOKE}}}% +Define \tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} as follows: \begin{itemize} -\item -\tcode{is_constructible_v} is \tcode{true}, and -\item -\tcode{\exposid{is-callable-from}} is \tcode{true}. -\end{itemize} +\item \tcode{(t$_1$.*f)(t$_2$, $\dotsc$, t$_N$)} when \tcode{f} is a pointer to a +member function of a class \tcode{T} +and +\tcode{is_same_v> ||} +\tcode{is_base_of_v>} is \tcode{true}; -\pnum -\mandates -\tcode{VT} is the same type as \tcode{T}. +\item \tcode{(t$_1$.get().*f)(t$_2$, $\dotsc$, t$_N$)} when \tcode{f} is a pointer to a +member function of a class \tcode{T} +and \tcode{remove_cvref_t} is a specialization of \tcode{reference_wrapper}; -\pnum -\expects -\tcode{VT} meets the \oldconcept{Destructible} requirements, and -if \tcode{is_move_constructible_v} is \tcode{true}, -\tcode{VT} meets the \oldconcept{MoveConstructible} requirements. +\item \tcode{((*t$_1$).*f)(t$_2$, $\dotsc$, t$_N$)} when \tcode{f} is a pointer to a +member function of a class \tcode{T} +and \tcode{t$_1$} does not satisfy the previous two items; -\pnum -\ensures -\tcode{*this} has a target object of type \tcode{VT} -direct-non-list-initialized with \tcode{std::forward\brk{}(args)...}. +\item \tcode{t$_1$.*f} when $N = 1$ and \tcode{f} is a pointer to +data member of a class \tcode{T} +and +\tcode{is_same_v> ||} +\tcode{is_base_of_v>} is \tcode{true}; -\pnum -\throws -Any exception thrown by the initialization of the target object. -May throw \tcode{bad_alloc} unless \tcode{VT} is -a function pointer or a specialization of \tcode{reference_wrapper}. -\end{itemdescr} +\item \tcode{t$_1$.get().*f} when $N = 1$ and \tcode{f} is a pointer to +data member of a class \tcode{T} +and \tcode{remove_cvref_t} is a specialization of \tcode{reference_wrapper}; -\indexlibraryctor{move_only_function}% -\begin{itemdecl} -template - explicit move_only_function(in_place_type_t, initializer_list ilist, Args&&... args); -\end{itemdecl} +\item \tcode{(*t$_1$).*f} when $N = 1$ and \tcode{f} is a pointer to +data member of a class \tcode{T} +and \tcode{t$_1$} does not satisfy the previous two items; + +\item \tcode{f(t$_1$, t$_2$, $\dotsc$, t$_N$)} in all other cases. +\end{itemize} -\begin{itemdescr} \pnum -Let \tcode{VT} be \tcode{decay_t}. +\indexlibrary{invoke@\tcode{\placeholder{INVOKE}}}% +Define \tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} as +\tcode{static_cast(\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$))} +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 -\constraints -\begin{itemize} -\item -\tcode{is_constructible_v\&, Args...>} is -\tcode{true}, and -\item -\tcode{\exposid{is-callable-from}} is \tcode{true}. -\end{itemize} +\indextext{call wrapper}% +\indextext{call wrapper!simple}% +\indextext{call wrapper!forwarding}% +Every call wrapper\iref{func.def} meets the \oldconcept{MoveConstructible} +and \oldconcept{Destructible} requirements. +An \defn{argument forwarding call wrapper} is a +call wrapper that can be called with an arbitrary argument list +and delivers the arguments to the target object as references. +This forwarding step delivers rvalue arguments as rvalue references +and lvalue arguments as lvalue references. +\begin{note} +In a typical implementation, argument forwarding call wrappers have +an overloaded function call operator of the form +\begin{codeblock} +template + constexpr R operator()(UnBoundArgs&&... unbound_args) @\textit{cv-qual}@; +\end{codeblock} +\end{note} \pnum -\mandates -\tcode{VT} is the same type as \tcode{T}. +\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} +as \cv{} \tcode{T\&} +when the call is performed on an lvalue of the call wrapper type and +as \cv{} \tcode{T\&\&} otherwise, +where \cv{} represents the cv-qualifiers of the call wrapper and +where \cv{} shall be neither \tcode{volatile} nor \tcode{const volatile}. \pnum -\expects -\tcode{VT} meets the \oldconcept{Destructible} requirements, and -if \tcode{is_move_constructible_v} is \tcode{true}, -\tcode{VT} meets the \oldconcept{MoveConstructible} requirements. +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 +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 +with references as described in the corresponding forwarding steps. \pnum -\ensures -\tcode{*this} has a target object of type \tcode{VT} -direct-non-list-initialized with -\tcode{ilist, std::for\-ward(args)...}. +\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 +are constexpr functions that do not throw exceptions. + +\pnum +The copy/move constructor of an argument forwarding call wrapper has +the same apparent semantics +as if memberwise copy/move of its state entities +were performed\iref{class.copy.ctor}. +\begin{note} +This implies that each of the copy/move constructors has +the same exception-specification as +the corresponding implicit definition and is declared as \keyword{constexpr} +if the corresponding implicit definition would be considered to be constexpr. +\end{note} \pnum -\throws -Any exception thrown by the initialization of the target object. -May throw \tcode{bad_alloc} unless \tcode{VT} is -a function pointer or a specialization of \tcode{reference_wrapper}. -\end{itemdescr} +Argument forwarding call wrappers returned by +a given standard library function template have the same type +if the types of their corresponding state entities are the same. -\indexlibrarymember{operator=}{move_only_function}% +\rSec2[func.invoke]{\tcode{invoke} functions} +\indexlibraryglobal{invoke}% +\indexlibrary{invoke@\tcode{\placeholder{INVOKE}}}% \begin{itemdecl} -move_only_function& operator=(move_only_function&& f); +template + constexpr invoke_result_t invoke(F&& f, Args&&... args) + noexcept(is_nothrow_invocable_v); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{move_only_function(std::move(f)).swap(*this);} +\constraints +\tcode{is_invocable_v} is \tcode{true}. \pnum \returns -\tcode{*this}. +\tcode{\placeholdernc{INVOKE}(std::forward(f), std::forward(args)...)}\iref{func.require}. \end{itemdescr} -\indexlibrarymember{operator=}{move_only_function}% +\indexlibraryglobal{invoke_r}% \begin{itemdecl} -move_only_function& operator=(nullptr_t) noexcept; +template + constexpr R invoke_r(F&& f, Args&&... args) + noexcept(is_nothrow_invocable_r_v); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Destroys the target object of \tcode{*this}, if any. +\constraints +\tcode{is_invocable_r_v} is \tcode{true}. \pnum \returns -\tcode{*this}. +\tcode{\placeholdernc{INVOKE}(std::forward(f), std::forward(args)...)}\iref{func.require}. \end{itemdescr} -\indexlibrarymember{operator=}{move_only_function}% -\begin{itemdecl} -template move_only_function& operator=(F&& f); -\end{itemdecl} +\rSec2[refwrap]{Class template \tcode{reference_wrapper}} -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{move_only_function(std::forward(f)).swap(*this);} +\rSec3[refwrap.general]{General} -\pnum -\returns -\tcode{*this}. -\end{itemdescr} +\indexlibraryglobal{reference_wrapper}% +\indextext{function object!\idxcode{reference_wrapper}}% +\begin{codeblock} +namespace std { + template class reference_wrapper { + public: + // types + using type = T; -\indexlibrarydtor{move_only_function}% -\begin{itemdecl} -~move_only_function(); -\end{itemdecl} + // \ref{refwrap.const}, constructors + template + constexpr reference_wrapper(U&&) noexcept(@\seebelow@); + constexpr reference_wrapper(const reference_wrapper& x) noexcept; -\begin{itemdescr} -\pnum -\effects -Destroys the target object of \tcode{*this}, if any. -\end{itemdescr} + // \ref{refwrap.assign}, assignment + constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept; -\rSec4[func.wrap.move.inv]{Invocation} + // \ref{refwrap.access}, access + constexpr operator T& () const noexcept; + constexpr T& get() const noexcept; -\indexlibrarymember{operator bool}{move_only_function}% -\begin{itemdecl} -explicit operator bool() const noexcept; -\end{itemdecl} + // \ref{refwrap.invoke}, invocation + template + constexpr invoke_result_t operator()(ArgTypes&&...) const + noexcept(is_nothrow_invocable_v); -\begin{itemdescr} -\pnum -\returns -\tcode{true} if \tcode{*this} has a target object, otherwise \tcode{false}. -\end{itemdescr} + // \ref{refwrap.comparisons}, comparisons + friend constexpr bool operator==(reference_wrapper, reference_wrapper); + friend constexpr bool operator==(reference_wrapper, const T&); + friend constexpr bool operator==(reference_wrapper, reference_wrapper); -\indexlibrarymember{operator()}{move_only_function}% -\begin{itemdecl} -R operator()(ArgTypes... args) @\cv{}@ @\placeholder{ref}@ noexcept(@\placeholder{noex}@); -\end{itemdecl} + friend constexpr auto operator<=>(reference_wrapper, reference_wrapper); + friend constexpr auto operator<=>(reference_wrapper, const T&); + friend constexpr auto operator<=>(reference_wrapper, reference_wrapper); + }; + + template + reference_wrapper(T&) -> reference_wrapper; +} +\end{codeblock} -\begin{itemdescr} \pnum -\expects -\tcode{*this} has a target object. +\tcode{reference_wrapper} is a \oldconcept{CopyConstructible} and \oldconcept{CopyAssignable} wrapper +around a reference to an object or function of type \tcode{T}. \pnum -\effects -Equivalent to: -\begin{codeblock} -return @\placeholder{INVOKE}@(static_cast(f), std::forward(args)...); -\end{codeblock} -where \tcode{f} is an lvalue designating the target object of \tcode{*this} and -\tcode{F} is the type of \tcode{f}. -\end{itemdescr} +\tcode{reference_wrapper} is +a trivially copyable type\iref{term.trivially.copyable.type}. -\rSec4[func.wrap.move.util]{Utility} +\pnum +The template parameter \tcode{T} of \tcode{reference_wrapper} +may be an incomplete type. +\begin{note} +Using the comparison operators described in \ref{refwrap.comparisons} +with \tcode{T} being an incomplete type +can lead to an ill-formed program +with no diagnostic required\iref{temp.point,temp.constr.atomic}. +\end{note} -\indexlibrarymember{swap}{move_only_function}% +\rSec3[refwrap.const]{Constructors} + +\indexlibraryctor{reference_wrapper}% \begin{itemdecl} -void swap(move_only_function& other) noexcept; +template + constexpr reference_wrapper(U&& u) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{\placeholdernc{FUN}} denote the exposition-only functions +\begin{codeblock} +void @\placeholdernc{FUN}@(T&) noexcept; +void @\placeholdernc{FUN}@(T&&) = delete; +\end{codeblock} + +\pnum +\constraints +The expression \tcode{\placeholdernc{FUN}(declval())} is well-formed and +\tcode{is_same_v, reference_wrapper>} is \tcode{false}. + \pnum \effects -Exchanges the target objects of \tcode{*this} and \tcode{other}. +Creates a variable \tcode{r} +as if by \tcode{T\& r = std::forward(u)}, +then constructs a \tcode{reference_wrapper} object +that stores a reference to \tcode{r}. + +\pnum +\remarks +The exception specification is equivalent to +\tcode{noexcept(\placeholdernc{FUN}(declval()))}. \end{itemdescr} -\indexlibrarymember{swap}{move_only_function}% +\indexlibraryctor{reference_wrapper}% \begin{itemdecl} -friend void swap(move_only_function& f1, move_only_function& f2) noexcept; +constexpr reference_wrapper(const reference_wrapper& x) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to \tcode{f1.swap(f2)}. +Constructs a \tcode{reference_wrapper} object that +stores a reference to \tcode{x.get()}. \end{itemdescr} -\indexlibrarymember{operator==}{move_only_function}% +\rSec3[refwrap.assign]{Assignment} + +\indexlibrarymember{operator=}{reference_wrapper}% \begin{itemdecl} -friend bool operator==(const move_only_function& f, nullptr_t) noexcept; +constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{true} if \tcode{f} has no target object, otherwise \tcode{false}. +\ensures +\tcode{*this} stores a reference to \tcode{x.get()}. \end{itemdescr} -\rSec3[func.wrap.copy]{Copyable wrapper} - -\rSec4[func.wrap.copy.general]{General} - -\pnum -The header provides partial specializations of \tcode{copyable_function} -for each combination of the possible replacements -of the placeholders \cv{}, \placeholder{ref}, and \placeholder{noex} where -\begin{itemize} -\item -\cv{} is either const or empty, -\item -\placeholder{ref} is either \tcode{\&}, \tcode{\&\&}, or empty, and -\item -\placeholder{noex} is either \tcode{true} or \tcode{false}. -\end{itemize} - -\pnum -For each of the possible combinations of the placeholders mentioned above, -there is a placeholder \placeholder{inv-quals} defined as follows: -\begin{itemize} -\item -If \placeholder{ref} is empty, let \placeholder{inv-quals} be \cv{}\tcode{\&}, -\item -otherwise, let \placeholder{inv-quals} be \cv{} \placeholder{ref}. -\end{itemize} - -\rSec4[func.wrap.copy.class]{Class template \tcode{copyable_function}} - -\indexlibraryglobal{copyable_function}% -\begin{codeblock} -namespace std { - template - class copyable_function { - public: - using result_type = R; - - // \ref{func.wrap.copy.ctor}, constructors, assignments, and destructors - copyable_function() noexcept; - copyable_function(nullptr_t) noexcept; - copyable_function(const copyable_function&); - copyable_function(copyable_function&&) noexcept; - template copyable_function(F&&); - template - explicit copyable_function(in_place_type_t, Args&&...); - template - explicit copyable_function(in_place_type_t, initializer_list, Args&&...); - - copyable_function& operator=(const copyable_function&); - copyable_function& operator=(copyable_function&&); - copyable_function& operator=(nullptr_t) noexcept; - template copyable_function& operator=(F&&); - - ~copyable_function(); - - // \ref{func.wrap.copy.inv}, invocation - explicit operator bool() const noexcept; - R operator()(ArgTypes...) @\cv{}@ @\placeholder{ref}@ noexcept(@\placeholder{noex}@); - - // \ref{func.wrap.copy.util}, utility - void swap(copyable_function&) noexcept; - friend void swap(copyable_function&, copyable_function&) noexcept; - friend bool operator==(const copyable_function&, nullptr_t) noexcept; - - private: - template - static constexpr bool @\exposid{is-callable-from}@ = @\seebelow@; // \expos - }; -} -\end{codeblock} - -\pnum -The \tcode{copyable_function} class template provides polymorphic wrappers -that generalize the notion of a callable object\iref{func.def}. -These wrappers can store, copy, move, and call arbitrary callable objects, -given a call signature. - -\pnum -\recommended -Implementations should avoid the use of dynamically allocated memory -for a small contained value. -\begin{note} -Such small-object optimization can only be applied to a type \tcode{T} -for which \tcode{is_nothrow_move_constructible_v} is \tcode{true}. -\end{note} - -\rSec4[func.wrap.copy.ctor]{Constructors, assignments, and destructors} +\rSec3[refwrap.access]{Access} -\indextext{copyable_function::is-callable-from@\tcode{copyable_function::\exposid{is-callable-from}}}% +\indexlibrarymember{operator T\&}{reference_wrapper}% \begin{itemdecl} -template - static constexpr bool @\exposid{is-callable-from}@ = @\seebelow@; +constexpr operator T& () const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -If \placeholder{noex} is \tcode{true}, -\tcode{\exposid{is-callable-from}} is equal to: -\begin{codeblock} -is_nothrow_invocable_r_v && -is_nothrow_invocable_r_v -\end{codeblock} -Otherwise, \tcode{\exposid{is-callable-from}} is equal to: -\begin{codeblock} -is_invocable_r_v && -is_invocable_r_v -\end{codeblock} +\returns +The stored reference. \end{itemdescr} -\indexlibraryctor{copyable_function}% +\indexlibrarymember{get}{reference_wrapper}% \begin{itemdecl} -copyable_function() noexcept; -copyable_function(nullptr_t) noexcept; +constexpr T& get() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{*this} has no target object. +\returns +The stored reference. \end{itemdescr} -\indexlibraryctor{copyable_function}% +\rSec3[refwrap.invoke]{Invocation} + +\indexlibrarymember{operator()}{reference_wrapper}% \begin{itemdecl} -copyable_function(const copyable_function& f); +template + constexpr invoke_result_t + operator()(ArgTypes&&... args) const noexcept(is_nothrow_invocable_v); \end{itemdecl} \begin{itemdescr} \pnum -\ensures -\tcode{*this} has no target object if \tcode{f} had no target object. -Otherwise, the target object of \tcode{*this} -is a copy of the target object of \tcode{f}. +\mandates +\tcode{T} is a complete type. \pnum -\throws -Any exception thrown by the initialization of the target object. -May throw \tcode{bad_alloc}. +\returns +\tcode{\placeholdernc{INVOKE}(get(), std::forward(args)...)}\iref{func.require}. \end{itemdescr} -\indexlibraryctor{copyable_function}% +\rSec3[refwrap.comparisons]{Comparisons} + \begin{itemdecl} -copyable_function(copyable_function&& f) noexcept; +friend constexpr bool operator==(reference_wrapper x, reference_wrapper y); \end{itemdecl} \begin{itemdescr} \pnum -\ensures -The target object of \tcode{*this} is -the target object \tcode{f} had before construction, and -\tcode{f} is in a valid state with an unspecified value. +\constraints +The expression \tcode{x.get() == y.get()} is well-formed and +its result is convertible to \tcode{bool}. + +\pnum +\returns +\tcode{x.get() == y.get()}. \end{itemdescr} -\indexlibraryctor{copyable_function}% \begin{itemdecl} -template copyable_function(F&& f); +friend constexpr bool operator==(reference_wrapper x, const T& y); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{VT} be \tcode{decay_t}. +\constraints +The expression \tcode{x.get() == y} is well-formed and +its result is convertible to \tcode{bool}. \pnum -\constraints -\begin{itemize} -\item -\tcode{remove_cvref_t} is not the same type as \tcode{copyable_function}, and -\item -\tcode{remove_cvref_t} is not a specialization of \tcode{in_place_type_t}, and -\item -\tcode{\exposid{is-callable-from}} is \tcode{true}. -\end{itemize} +\returns +\tcode{x.get() == y}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(reference_wrapper x, reference_wrapper y); +\end{itemdecl} +\begin{itemdescr} \pnum -\mandates -\begin{itemize} -\item -\tcode{is_constructible_v} is \tcode{true}, and -\item -\tcode{is_copy_constructible_v} is \tcode{true}. -\end{itemize} +\constraints +\tcode{is_const_v} is \tcode{false} and +the expression \tcode{x.get() == y.get()} is well-formed and +its result is convertible to \tcode{bool}. \pnum -\expects -\tcode{VT} meets the \oldconcept{Destructible} and -\oldconcept{CopyConstructible} requirements. +\returns +\tcode{x.get() == y.get()}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr auto operator<=>(reference_wrapper x, reference_wrapper y); +\end{itemdecl} +\begin{itemdescr} \pnum -\ensures -\tcode{*this} has no target object if any of the following hold: -\begin{itemize} -\item -\tcode{f} is a null function pointer value, or -\item -\tcode{f} is a null member pointer value, or -\item -\tcode{remove_cvref_t} is a specialization of -the \tcode{copyable_function} class template, -and \tcode{f} has no target object. -\end{itemize} -Otherwise, \tcode{*this} has a target object of type \tcode{VT} -direct-non-list-initialized with \tcode{std::forward(f)}. +\constraints +The expression \tcode{\exposid{synth-three-way}(x.get(), y.get())} +is well-formed. \pnum -\throws -Any exception thrown by the initialization of the target object. -May throw \tcode{bad_alloc} unless \tcode{VT} is -a function pointer or a specialization of \tcode{reference_wrapper}. +\returns +\tcode{\exposid{synth-three-way}(x.get(), y.get())}. \end{itemdescr} -\indexlibraryctor{copyable_function}% \begin{itemdecl} -template - explicit copyable_function(in_place_type_t, Args&&... args); +friend constexpr auto operator<=>(reference_wrapper x, const T& y); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{VT} be \tcode{decay_t}. +\constraints +The expression \tcode{\exposid{synth-three-way}(x.get(), y)} +is well-formed. \pnum -\constraints -\begin{itemize} -\item -\tcode{is_constructible_v} is \tcode{true}, and -\item -\tcode{\exposid{is-callable-from}} is \tcode{true}. -\end{itemize} +\returns +\tcode{\exposid{synth-three-way}(x.get(), y)}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr auto operator<=>(reference_wrapper x, reference_wrapper y); +\end{itemdecl} +\begin{itemdescr} \pnum -\mandates -\begin{itemize} -\item -\tcode{VT} is the same type as \tcode{T}, and -\item -\tcode{is_copy_constructible_v} is \tcode{true}. -\end{itemize} +\constraints +\tcode{is_const_v} is \tcode{false}. +The expression \tcode{\exposid{synth-three-way}(x.get(), y.get())} +is well-formed. \pnum -\expects -\tcode{VT} meets the \oldconcept{Destructible} and -\oldconcept{CopyConstructible} requirements. +\returns +\tcode{\exposid{synth-three-way}(x.get(), y.get())}. +\end{itemdescr} + +\rSec3[refwrap.helpers]{Helper functions} \pnum -\ensures -\tcode{*this} has a target object of type \tcode{VT} -direct-non-list-initialized with \tcode{std::forward\brk{}(args)...}. +The template parameter \tcode{T} of +the following \tcode{ref} and \tcode{cref} function templates +may be an incomplete type. + +\indexlibrarymember{ref}{reference_wrapper}% +\begin{itemdecl} +template constexpr reference_wrapper ref(T& t) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -Any exception thrown by the initialization of the target object. -May throw \tcode{bad_alloc} unless \tcode{VT} is -a pointer or a specialization of \tcode{reference_wrapper}. +\returns +\tcode{reference_wrapper(t)}. \end{itemdescr} -\indexlibraryctor{copyable_function}% +\indexlibrarymember{ref}{reference_wrapper}% \begin{itemdecl} -template - explicit copyable_function(in_place_type_t, initializer_list ilist, Args&&... args); +template constexpr reference_wrapper ref(reference_wrapper t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{VT} be \tcode{decay_t}. +\returns +\tcode{t}. +\end{itemdescr} -\pnum -\constraints -\begin{itemize} -\item -\tcode{is_constructible_v\&, Args...>} is -\tcode{true}, and -\item -\tcode{\exposid{is-callable-from}} is \tcode{true}. -\end{itemize} +\indexlibrarymember{cref}{reference_wrapper}% +\begin{itemdecl} +template constexpr reference_wrapper cref(const T& t) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\mandates -\begin{itemize} -\item -\tcode{VT} is the same type as \tcode{T}, and -\item -\tcode{is_copy_constructible_v} is \tcode{true}. -\end{itemize} +\returns +\tcode{reference_wrapper(t)}. +\end{itemdescr} -\pnum -\expects -\tcode{VT} meets the \oldconcept{Destructible} and -\oldconcept{CopyConstructible} requirements. +\indexlibrarymember{cref}{reference_wrapper}% +\begin{itemdecl} +template constexpr reference_wrapper cref(reference_wrapper t) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\ensures -\tcode{*this} has a target object of type \tcode{VT} -direct-non-list-initialized with -\tcode{ilist, std::for\-ward(args)...}. +\returns +\tcode{t}. +\end{itemdescr} + +\rSec3[refwrap.common.ref]{\tcode{common_reference} related specializations} + +\indexlibraryglobal{basic_common_reference}% +\begin{codeblock} +namespace std { + template + constexpr bool @\exposid{is-ref-wrapper}@ = false; // \expos + + template + constexpr bool @\exposid{is-ref-wrapper}@> = true; + + template + concept @\defexposconcept{ref-wrap-common-reference-exists-with}@ = // \expos + @\exposid{is-ref-wrapper}@ && + requires { typename common_reference_t; } && + @\libconcept{convertible_to}@>; + + template class RQual, template class TQual> + requires (@\exposconcept{ref-wrap-common-reference-exists-with}@, TQual> && + !@\exposconcept{ref-wrap-common-reference-exists-with}@, RQual>) + struct basic_common_reference { + using type = common_reference_t>; + }; + + template class TQual, template class RQual> + requires (@\exposconcept{ref-wrap-common-reference-exists-with}@, TQual> && + !@\exposconcept{ref-wrap-common-reference-exists-with}@, RQual>) + struct basic_common_reference { + using type = common_reference_t>; + }; +} +\end{codeblock} + +\rSec2[arithmetic.operations]{Arithmetic operations} + +\rSec3[arithmetic.operations.general]{General} \pnum -\throws -Any exception thrown by the initialization of the target object. -May throw \tcode{bad_alloc} unless \tcode{VT} is -a pointer or a specialization of \tcode{reference_wrapper}. -\end{itemdescr} +The library provides basic function object classes for all of the arithmetic +operators in the language\iref{expr.mul,expr.add}. -\indexlibrarymember{operator=}{copyable_function}% +\rSec3[arithmetic.operations.plus]{Class template \tcode{plus}} + +\indexlibraryglobal{plus}% \begin{itemdecl} -copyable_function& operator=(const copyable_function& f); +template struct plus { + constexpr T operator()(const T& x, const T& y) const; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{copyable_function(f).swap(*this);} +\indexlibrarymember{operator()}{plus}% +\begin{itemdecl} +constexpr T operator()(const T& x, const T& y) const; +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{*this}. +\tcode{x + y}. \end{itemdescr} -\indexlibrarymember{operator=}{copyable_function}% +\indexlibraryglobal{plus<>}% \begin{itemdecl} -copyable_function& operator=(copyable_function&& f); +template<> struct plus { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) + std::forward(u)); + + using is_transparent = @\unspec@; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{copyable_function(std::move(f)).swap(*this);} +\indexlibrarymember{operator()}{plus<>}% +\begin{itemdecl} +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) + std::forward(u)); +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{*this}. +\tcode{std::forward(t) + std::forward(u)}. \end{itemdescr} -\indexlibrarymember{operator=}{copyable_function}% +\rSec3[arithmetic.operations.minus]{Class template \tcode{minus}} + +\indexlibraryglobal{minus}% \begin{itemdecl} -copyable_function& operator=(nullptr_t) noexcept; +template struct minus { + constexpr T operator()(const T& x, const T& y) const; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\effects -Destroys the target object of \tcode{*this}, if any. +\indexlibrarymember{operator()}{minus}% +\begin{itemdecl} +constexpr T operator()(const T& x, const T& y) const; +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{*this}. +\tcode{x - y}. \end{itemdescr} -\indexlibrarymember{operator=}{copyable_function}% +\indexlibraryglobal{minus<>}% \begin{itemdecl} -template copyable_function& operator=(F&& f); +template<> struct minus { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) - std::forward(u)); + + using is_transparent = @\unspec@; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\effects -Equivalent to: \tcode{copyable_function(std::forward(f)).swap(*this);} +\indexlibrarymember{operator()}{minus<>}% +\begin{itemdecl} +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) - std::forward(u)); +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{*this}. +\tcode{std::forward(t) - std::forward(u)}. \end{itemdescr} -\indexlibrarydtor{copyable_function}% +\rSec3[arithmetic.operations.multiplies]{Class template \tcode{multiplies}} + +\indexlibraryglobal{multiplies}% \begin{itemdecl} -~copyable_function(); +template struct multiplies { + constexpr T operator()(const T& x, const T& y) const; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{multiplies}% +\begin{itemdecl} +constexpr T operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Destroys the target object of \tcode{*this}, if any. +\returns +\tcode{x * y}. \end{itemdescr} -\rSec4[func.wrap.copy.inv]{Invocation} +\indexlibraryglobal{multiplies<>}% +\begin{itemdecl} +template<> struct multiplies { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) * std::forward(u)); -\indexlibrarymember{operator bool}{copyable_function}% + using is_transparent = @\unspec@; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{multiplies<>}% \begin{itemdecl} -explicit operator bool() const noexcept; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) * std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{true} if \tcode{*this} has a target object, otherwise \tcode{false}. +\tcode{std::forward(t) * std::forward(u)}. \end{itemdescr} -\indexlibrarymember{operator()}{copyable_function}% +\rSec3[arithmetic.operations.divides]{Class template \tcode{divides}} + +\indexlibraryglobal{divides}% \begin{itemdecl} -R operator()(ArgTypes... args) @\cv{}@ @\placeholder{ref}@ noexcept(@\placeholder{noex}@); +template struct divides { + constexpr T operator()(const T& x, const T& y) const; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\expects -\tcode{*this} has a target object. +\indexlibrarymember{operator()}{divides}% +\begin{itemdecl} +constexpr T operator()(const T& x, const T& y) const; +\end{itemdecl} +\begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return @\placeholder{INVOKE}@(static_cast(f), std::forward(args)...); -\end{codeblock} -where \tcode{f} is an lvalue designating the target object of \tcode{*this} and -\tcode{F} is the type of \tcode{f}. +\returns +\tcode{x / y}. \end{itemdescr} -\rSec4[func.wrap.copy.util]{Utility} +\indexlibraryglobal{divides<>}% +\begin{itemdecl} +template<> struct divides { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) / std::forward(u)); -\indexlibrarymember{swap}{copyable_function}% + using is_transparent = @\unspec@; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{divides<>}% \begin{itemdecl} -void swap(copyable_function& other) noexcept; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) / std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Exchanges the target objects of \tcode{*this} and \tcode{other}. +\returns +\tcode{std::forward(t) / std::forward(u)}. \end{itemdescr} -\indexlibrarymember{swap}{copyable_function}% +\rSec3[arithmetic.operations.modulus]{Class template \tcode{modulus}} + +\indexlibraryglobal{modulus}% \begin{itemdecl} -friend void swap(copyable_function& f1, copyable_function& f2) noexcept; +template struct modulus { + constexpr T operator()(const T& x, const T& y) const; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{modulus}% +\begin{itemdecl} +constexpr T operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to \tcode{f1.swap(f2)}. +\returns +\tcode{x \% y}. \end{itemdescr} -\indexlibrarymember{operator==}{copyable_function}% +\indexlibraryglobal{modulus<>}% \begin{itemdecl} -friend bool operator==(const copyable_function& f, nullptr_t) noexcept; +template<> struct modulus { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) % std::forward(u)); + + using is_transparent = @\unspec@; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{modulus<>}% +\begin{itemdecl} +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) % std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{true} if \tcode{f} has no target object, otherwise \tcode{false}. +\tcode{std::forward(t) \% std::forward(u)}. \end{itemdescr} -\rSec3[func.wrap.ref]{Non-owning wrapper} +\rSec3[arithmetic.operations.negate]{Class template \tcode{negate}} -\rSec4[func.wrap.ref.general]{General} +\indexlibraryglobal{negate}% +\begin{itemdecl} +template struct negate { + constexpr T operator()(const T& x) const; +}; +\end{itemdecl} -\pnum -The header provides partial specializations of \tcode{function_ref} -for each combination of the possible replacements of -the placeholders \cv{} and \placeholder{noex} where: +\indexlibrarymember{operator()}{negate}% +\begin{itemdecl} +constexpr T operator()(const T& x) const; +\end{itemdecl} -\begin{itemize} -\item \cv{} is either const or empty, and -\item \placeholder{noex} is either \tcode{true} or \tcode{false}. -\end{itemize} +\begin{itemdescr} +\pnum +\returns +\tcode{-x}. +\end{itemdescr} -\rSec4[func.wrap.ref.class]{Class template \tcode{function_ref}} +\indexlibraryglobal{negate<>}% +\begin{itemdecl} +template<> struct negate { + template constexpr auto operator()(T&& t) const + -> decltype(-std::forward(t)); -\indexlibraryglobal{function_ref}% -\begin{codeblock} -namespace std { - template - class function_ref { - public: - // \ref{func.wrap.ref.ctor}, constructors and assignment operators - template function_ref(F*) noexcept; - template constexpr function_ref(F&&) noexcept; - template constexpr function_ref(nontype_t) noexcept; - template constexpr function_ref(nontype_t, U&&) noexcept; - template constexpr function_ref(nontype_t, @\cv{}@ T*) noexcept; + using is_transparent = @\unspec@; +}; +\end{itemdecl} - constexpr function_ref(const function_ref&) noexcept = default; - constexpr function_ref& operator=(const function_ref&) noexcept = default; - template function_ref& operator=(T) = delete; +\indexlibrarymember{operator()}{negate<>}% +\begin{itemdecl} +template constexpr auto operator()(T&& t) const + -> decltype(-std::forward(t)); +\end{itemdecl} - // \ref{func.wrap.ref.inv}, invocation - R operator()(ArgTypes...) const noexcept(@\placeholder{noex}@); +\begin{itemdescr} +\pnum +\returns +\tcode{-std::forward(t)}. +\end{itemdescr} - private: - template - static constexpr bool @\exposidnc{is-invocable-using}@ = @\seebelownc@; // \expos - R (*@\exposidnc{thunk-ptr}@)(@\exposidnc{BoundEntityType}@, Args&&...) noexcept(@\placeholdernc{noex}@); // \expos - @\exposidnc{BoundEntityType}@ @\exposidnc{bound-entity}@; // \expos - }; +\rSec2[comparisons]{Comparisons} - // \ref{func.wrap.ref.deduct}, deduction guides - template - function_ref(F*) -> function_ref; - template - function_ref(nontype_t) -> function_ref<@\seebelow@>; - template - function_ref(nontype_t, T&&) -> function_ref<@\seebelow@>; -} -\end{codeblock} +\rSec3[comparisons.general]{General} \pnum -An object of class -\tcode{function_ref} -stores a pointer to function \exposid{thunk-ptr} and -an object \exposid{bound-entity}. -\exposid{bound-entity} has -an unspecified trivially copyable type \exposid{BoundEntityType}, that -models \libconcept{copyable} and -is capable of storing a pointer to object value or a pointer to function value. -The type of \exposid{thunk-ptr} is -\tcode{R(*)(\exposidnc{BoundEntityType}, Args\&\&...) noexcept(\placeholder{noex})}. +The library provides basic function object classes for all of the comparison +operators in the language\iref{expr.rel,expr.eq}. \pnum -Each specialization of \tcode{function_ref} is -a trivially copyable type\iref{term.trivially.copyable.type} -that models \libconcept{copyable}. +For templates \tcode{less}, \tcode{greater}, \tcode{less_equal}, and +\tcode{greater_equal}, the specializations for any pointer type +yield a result consistent with the +implementation-defined strict total order over pointers\iref{defns.order.ptr}. +\begin{note} +If \tcode{a < b} is well-defined +for pointers \tcode{a} and \tcode{b} of type \tcode{P}, +then \tcode{(a < b) == less

()(a, b)}, +\tcode{(a > b) == greater

()(a, b)}, and so forth. +\end{note} +For template specializations \tcode{less}, \tcode{greater}, +\tcode{less_equal}, and \tcode{greater_equal}, +if the call operator calls a built-in operator comparing pointers, +the call operator yields a result consistent +with the implementation-defined strict total order over pointers. -\pnum -Within subclause \ref{func.wrap.ref}, -\tcode{\placeholder{call-args}} is an argument pack with elements such that -\tcode{decltype((\placeholder{call-args}\linebreak{}))...} denote -\tcode{Args\&\&...} respectively. +\rSec3[comparisons.equal.to]{Class template \tcode{equal_to}} -\rSec4[func.wrap.ref.ctor]{Constructors and assignment operators} +\indexlibraryglobal{equal_to}% +\begin{itemdecl} +template struct equal_to { + constexpr bool operator()(const T& x, const T& y) const; +}; +\end{itemdecl} -\indextext{function_ref::is-invocable-using@\tcode{function_ref::\exposid{is-invocable-using}}}% +\indexlibrarymember{operator()}{equal_to}% \begin{itemdecl} -template - static constexpr bool @\exposid{is-invocable-using}@ = @\seebelow@; +constexpr bool operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum -If \placeholder{noex} is \tcode{true}, -\tcode{\exposid{is-invocable-using}} is equal to: -\begin{codeblock} -is_nothrow_invocable_r_v -\end{codeblock} -Otherwise, \tcode{\exposid{is-invocable-using}} is equal to: -\begin{codeblock} -is_invocable_r_v -\end{codeblock} +\returns +\tcode{x == y}. \end{itemdescr} -\indexlibraryctor{function_ref}% +\indexlibraryglobal{equal_to<>}% \begin{itemdecl} -template function_ref(F* f) noexcept; +template<> struct equal_to { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) == std::forward(u)); + + using is_transparent = @\unspec@; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{equal_to<>}% +\begin{itemdecl} +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) == std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item \tcode{is_function_v} is \tcode{true}, and -\item \tcode{\exposid{is-invocable-using}} is \tcode{true}. -\end{itemize} +\returns +\tcode{std::forward(t) == std::forward(u)}. +\end{itemdescr} -\pnum -\expects -\tcode{f} is not a null pointer. +\rSec3[comparisons.not.equal.to]{Class template \tcode{not_equal_to}} -\pnum -\effects -Initializes -\exposid{bound-entity} with \tcode{f}, and -\exposid{thunk-ptr} with the address of a function \tcode{\placeholder{thunk}} -such that -\tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} -is expression-equivalent\iref{defns.expression.equivalent} to -\tcode{invoke_r(f, \placeholder{call-args}...)}. -\end{itemdescr} +\indexlibraryglobal{not_equal_to}% +\begin{itemdecl} +template struct not_equal_to { + constexpr bool operator()(const T& x, const T& y) const; +}; +\end{itemdecl} -\indexlibraryctor{function_ref}% +\indexlibrarymember{operator()}{not_equal_to}% \begin{itemdecl} -template constexpr function_ref(F&& f) noexcept; +constexpr bool operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{T} be \tcode{remove_reference_t}. +\returns +\tcode{x != y}. +\end{itemdescr} -\pnum -\constraints -\begin{itemize} -\item \tcode{remove_cvref_t} is not the same type as \tcode{function_ref}, -\item \tcode{is_member_pointer_v} is \tcode{false}, and -\item \tcode{\exposid{is-invocable-using}<\cv{} T\&>} is \tcode{true}. -\end{itemize} +\indexlibraryglobal{not_equal_to<>}% +\begin{itemdecl} +template<> struct not_equal_to { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) != std::forward(u)); -\pnum -\effects -Initializes -\exposid{bound-entity} with \tcode{addressof(f)}, and -\exposid{thunk-ptr} with the address of a function \tcode{\placeholder{thunk}} -such that -\tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} -is expression-equivalent\iref{defns.expression.equivalent} to -\tcode{invoke_r(static_cast<\cv{} T\&>(f), \placeholder{call-args}...)}. -\end{itemdescr} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibraryctor{function_ref}% +\indexlibrarymember{operator()}{not_equal_to<>}% \begin{itemdecl} -template constexpr function_ref(nontype_t) noexcept; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) != std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{F} be \tcode{decltype(f)}. +\returns +\tcode{std::forward(t) != std::forward(u)}. +\end{itemdescr} -\pnum -\constraints -\tcode{\exposid{is-invocable-using}} is \tcode{true}. +\rSec3[comparisons.greater]{Class template \tcode{greater}} -\pnum -\mandates -If \tcode{is_pointer_v || is_member_pointer_v} is \tcode{true}, -then \tcode{f != nullptr} is \tcode{true}. +\indexlibraryglobal{greater}% +\begin{itemdecl} +template struct greater { + constexpr bool operator()(const T& x, const T& y) const; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{greater}% +\begin{itemdecl} +constexpr bool operator()(const T& x, const T& y) const; +\end{itemdecl} +\begin{itemdescr} \pnum -\effects -Initializes -\exposid{bound-entity} with a pointer to an unspecified object or -null pointer value, and -\exposid{thunk-ptr} with the address of a function \tcode{\placeholder{thunk}} -such that -\tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} -is expression-equivalent\iref{defns.expression.equivalent} to -\tcode{invoke_r(f, \placeholder{call-args}...)}. +\returns +\tcode{x > y}. \end{itemdescr} -\indexlibraryctor{function_ref}% +\indexlibraryglobal{greater<>}% \begin{itemdecl} -template - constexpr function_ref(nontype_t, U&& obj) noexcept; +template<> struct greater { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) > std::forward(u)); + + using is_transparent = @\unspec@; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{greater<>}% +\begin{itemdecl} +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) > std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{T} be \tcode{remove_reference_t} and -\tcode{F} be \tcode{decltype(f)}. +\returns +\tcode{std::forward(t) > std::forward(u)}. +\end{itemdescr} -\pnum -\constraints -\begin{itemize} -\item \tcode{is_rvalue_reference_v} is \tcode{false}, and -\item \tcode{\exposid{is-invocable-using}} is \tcode{true}. -\end{itemize} +\rSec3[comparisons.less]{Class template \tcode{less}} -\pnum -\mandates -If \tcode{is_pointer_v || is_member_pointer_v} is \tcode{true}, -then \tcode{f != nullptr} is \tcode{true}. +\indexlibraryglobal{less}% +\begin{itemdecl} +template struct less { + constexpr bool operator()(const T& x, const T& y) const; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{less}% +\begin{itemdecl} +constexpr bool operator()(const T& x, const T& y) const; +\end{itemdecl} +\begin{itemdescr} \pnum -\effects -Initializes -\exposid{bound-entity} with \tcode{addressof(obj)}, and -\exposid{thunk-ptr} with the address of a function \tcode{\placeholder{thunk}} -such that -\tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} -is expression-equivalent\iref{defns.expression.equivalent} to -\tcode{invoke_r(f, static_cast<\cv{} T\&>(obj), \placeholder{call-args}...)}. +\returns +\tcode{x < y}. \end{itemdescr} -\indexlibraryctor{function_ref}% +\indexlibraryglobal{less<>}% +\begin{itemdecl} +template<> struct less { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) < std::forward(u)); + + using is_transparent = @\unspec@; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{less<>}% \begin{itemdecl} -template - constexpr function_ref(nontype_t, @\cv{}@ T* obj) noexcept; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) < std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{F} be \tcode{decltype(f)}. - -\pnum -\constraints -\tcode{\exposid{is-invocable-using}} is \tcode{true}. - -\pnum -\mandates -If \tcode{is_pointer_v || is_member_pointer_v} is \tcode{true}, -then \tcode{f != nullptr} is \tcode{true}. +\returns +\tcode{std::forward(t) < std::forward(u)}. +\end{itemdescr} -\pnum -\expects -If \tcode{is_member_pointer_v} is \tcode{true}, -\tcode{obj} is not a null pointer. +\rSec3[comparisons.greater.equal]{Class template \tcode{greater_equal}} -\pnum -\effects -Initializes -\exposid{bound-entity} with \tcode{obj}, and -\exposid{thunk-ptr} with the address of a function \tcode{\placeholder{thunk}} -such that -\tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} -is expression-equivalent\iref{defns.expression.equivalent} to -\tcode{invoke_r(f, obj, \placeholder{call-args}...)}. -\end{itemdescr} +\indexlibraryglobal{greater_equal}% +\begin{itemdecl} +template struct greater_equal { + constexpr bool operator()(const T& x, const T& y) const; +}; +\end{itemdecl} -\indexlibrarymember{operator=}{function_ref}% +\indexlibrarymember{operator()}{greater_equal}% \begin{itemdecl} -template function_ref& operator=(T) = delete; +constexpr bool operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item \tcode{T} is not the same type as \tcode{function_ref}, -\item \tcode{is_pointer_v} is \tcode{false}, and -\item \tcode{T} is not a specialization of \tcode{nontype_t}. -\end{itemize} +\returns +\tcode{x >= y}. \end{itemdescr} -\rSec4[func.wrap.ref.inv]{Invocation} +\indexlibraryglobal{greater_equal<>}% +\begin{itemdecl} +template<> struct greater_equal { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) >= std::forward(u)); -\indexlibrarymember{operator()}{function_ref}% + using is_transparent = @\unspec@; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{greater_equal<>}% \begin{itemdecl} -R operator()(ArgTypes... args) const noexcept(@\placeholder{noex}@); +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) >= std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\tcode{return \exposid{thunk-ptr}(\exposid{bound-entity}, std::forward(args)...);} +\returns +\tcode{std::forward(t) >= std::forward(u)}. \end{itemdescr} -\rSec4[func.wrap.ref.deduct]{Deduction guides} +\rSec3[comparisons.less.equal]{Class template \tcode{less_equal}} +\indexlibraryglobal{less_equal}% \begin{itemdecl} -template - function_ref(F*) -> function_ref; +template struct less_equal { + constexpr bool operator()(const T& x, const T& y) const; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{less_equal}% +\begin{itemdecl} +constexpr bool operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\tcode{is_function_v} is \tcode{true}. +\returns +\tcode{x <= y}. \end{itemdescr} +\indexlibraryglobal{less_equal<>}% +\begin{itemdecl} +template<> struct less_equal { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) <= std::forward(u)); + + using is_transparent = @\unspec@; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{less_equal<>}% \begin{itemdecl} -template - function_ref(nontype_t) -> function_ref<@\seebelow@>; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) <= std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{F} be \tcode{remove_pointer_t}. +\returns +\tcode{std::forward(t) <= std::forward(u)}. +\end{itemdescr} -\pnum -\constraints -\tcode{is_function_v} is \tcode{true}. +\rSec3[comparisons.three.way]{Class \tcode{compare_three_way}} -\pnum -\remarks -The deduced type is \tcode{function_ref}. -\end{itemdescr} +\indexlibraryglobal{compare_three_way}% +\begin{codeblock} +namespace std { + struct compare_three_way { + template + constexpr auto operator()(T&& t, U&& u) const; + + using is_transparent = @\unspec@; + }; +} +\end{codeblock} \begin{itemdecl} -template - function_ref(nontype_t, T&&) -> function_ref<@\seebelow@>; +template + constexpr auto operator()(T&& t, U&& u) const; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{F} be \tcode{decltype(f)}. +\constraints +\tcode{T} and \tcode{U} satisfy \libconcept{three_way_comparable_with}. \pnum -\constraints -%FIXME: R and E should be defined outside of these constraints. -%FIXME: Define R and E via "let" in paragraph above, then use them here and below. +\expects +If the expression \tcode{std::forward(t) <=> std::forward(u)} results in +a call to a built-in operator \tcode{<=>} comparing pointers of type \tcode{P}, +the conversion sequences from both \tcode{T} and \tcode{U} to \tcode{P} +are equality-preserving\iref{concepts.equality}; +otherwise, \tcode{T} and \tcode{U} model \libconcept{three_way_comparable_with}. + +\pnum +\effects \begin{itemize} \item -\tcode{F} is of the form -\tcode{R(G::*)(A...) \cv{} \opt{\&} noexcept(E)} for a type \tcode{G}, or -\item -\tcode{F} is of the form -\tcode{M G::*} for a type \tcode{G} and an object type \tcode{M}, -in which case -let \tcode{R} be \tcode{invoke_result_t}, -\tcode{A...} be an empty pack, and -\tcode{E} be \tcode{false}, or + If the expression \tcode{std::forward(t) <=> std::forward(u)} results in + a call to a built-in operator \tcode{<=>} comparing pointers of type \tcode{P}, + returns \tcode{strong_ordering::less} + if (the converted value of) \tcode{t} precedes \tcode{u} + in the implementation-defined strict total order + over pointers\iref{defns.order.ptr}, + \tcode{strong_ordering::greater} + if \tcode{u} precedes \tcode{t}, and + otherwise \tcode{strong_ordering::equal}. \item -\tcode{F} is of the form -\tcode{R(*)(G, A...) noexcept(E)} for a type \tcode{G}. + Otherwise, equivalent to: \tcode{return std::forward(t) <=> std::forward(u);} \end{itemize} - -\pnum -\remarks -The deduced type is \tcode{function_ref}. \end{itemdescr} -\indextext{function object!wrapper|)} -\rSec2[func.search]{Searchers} +\rSec2[range.cmp]{Concept-constrained comparisons} -\rSec3[func.search.general]{General} +\indexlibraryglobal{equal_to}% +\begin{codeblock} +struct ranges::equal_to { + template + constexpr bool operator()(T&& t, U&& u) const; + + using is_transparent = @\unspecnc@; +}; +\end{codeblock} + +\begin{itemdecl} +template + constexpr bool operator()(T&& t, U&& u) const; +\end{itemdecl} +\begin{itemdescr} \pnum -Subclause \ref{func.search} provides function object types\iref{function.objects} for -operations that search for a sequence \range{pat\textunderscore\nobreak first}{pat_last} in another -sequence \range{first}{last} that is provided to the object's function call -operator. The first sequence (the pattern to be searched for) is provided to -the object's constructor, and the second (the sequence to be searched) is -provided to the function call operator. +\constraints +\tcode{T} and \tcode{U} satisfy \libconcept{equality_comparable_with}. \pnum -Each specialization of a class template specified in \ref{func.search} -shall meet the \oldconcept{CopyConst\-ruct\-ible} and \oldconcept{CopyAssignable} requirements. -Template parameters named -\begin{itemize} -\item \tcode{ForwardIterator}, -\item \tcode{ForwardIterator1}, -\item \tcode{ForwardIterator2}, -\item \tcode{RandomAccessIterator}, -\item \tcode{RandomAccessIterator1}, -\item \tcode{RandomAccessIterator2}, and -\item \tcode{BinaryPredicate} -\end{itemize} -of templates specified in -\ref{func.search} shall meet the same requirements and semantics as -specified in \ref{algorithms.general}. -Template parameters named \tcode{Hash} shall meet the \oldconcept{Hash} -requirements (\tref{cpp17.hash}). +\expects +If the expression \tcode{std::forward(t) == std::forward(u)} +results in a call to a built-in operator \tcode{==} comparing pointers of type +\tcode{P}, the conversion sequences from both \tcode{T} and \tcode{U} to \tcode{P} +are equality-preserving\iref{concepts.equality}; +otherwise, \tcode{T} and \tcode{U} model \libconcept{equality_comparable_with}. \pnum -The Boyer-Moore searcher implements the Boyer-Moore search algorithm. -The Boyer-Moore-Horspool searcher implements the Boyer-Moore-Horspool search algorithm. -In general, the Boyer-Moore searcher will use more memory and give better runtime performance than Boyer-Moore-Horspool. +\effects +\begin{itemize} +\item + If the expression \tcode{std::forward(t) == std::forward(u)} results in + a call to a built-in operator \tcode{==} comparing pointers: + returns \tcode{false} if either (the converted value of) \tcode{t} precedes + \tcode{u} or \tcode{u} precedes \tcode{t} in the implementation-defined strict + total order over pointers\iref{defns.order.ptr} and otherwise \tcode{true}. -\rSec3[func.search.default]{Class template \tcode{default_searcher}} +\item + Otherwise, equivalent to: + \tcode{return std::forward(t) == std::forward(u);} +\end{itemize} +\end{itemdescr} -\indexlibraryglobal{default_searcher}% +\indexlibraryglobal{not_equal_to}% \begin{codeblock} -namespace std { - template> - class default_searcher { - public: - constexpr default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last, - BinaryPredicate pred = BinaryPredicate()); - - template - constexpr pair - operator()(ForwardIterator2 first, ForwardIterator2 last) const; +struct ranges::not_equal_to { + template + constexpr bool operator()(T&& t, U&& u) const; - private: - ForwardIterator1 pat_first_; // \expos - ForwardIterator1 pat_last_; // \expos - BinaryPredicate pred_; // \expos - }; -} + using is_transparent = @\unspecnc@; +}; \end{codeblock} -\indexlibraryctor{default_searcher}% \begin{itemdecl} -constexpr default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last, - BinaryPredicate pred = BinaryPredicate()); +template + constexpr bool operator()(T&& t, U&& u) const; \end{itemdecl} \begin{itemdescr} \pnum -\effects -% FIXME: The mbox prevents TeX from adding a bizarre hyphen after pat_last_. -Constructs a \tcode{default_searcher} object, initializing \tcode{pat_first_} -with \tcode{pat_first}, \mbox{\tcode{pat_last_}} with \tcode{pat_last}, and -\tcode{pred_} with \tcode{pred}. +\constraints +\tcode{T} and \tcode{U} satisfy \libconcept{equality_comparable_with}. \pnum -\throws -Any exception thrown by the copy constructor of \tcode{BinaryPredicate} or -\tcode{ForwardIterator1}. +\effects +Equivalent to: +\begin{codeblock} +return !ranges::equal_to{}(std::forward(t), std::forward(u)); +\end{codeblock} \end{itemdescr} -\indexlibrarymember{operator()}{default_searcher}% +\indexlibraryglobal{greater}% +\begin{codeblock} +struct ranges::greater { + template + constexpr bool operator()(T&& t, U&& u) const; + + using is_transparent = @\unspecnc@; +}; +\end{codeblock} + \begin{itemdecl} -template - constexpr pair - operator()(ForwardIterator2 first, ForwardIterator2 last) const; +template + constexpr bool operator()(T&& t, U&& u) const; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. + \pnum \effects -Returns a pair of iterators \tcode{i} and \tcode{j} such that -\begin{itemize} -\item \tcode{i == search(first, last, pat_first_, pat_last_, pred_)}, and -\item if \tcode{i == last}, then \tcode{j == last}, -otherwise \tcode{j == next(i, distance(pat_first_, pat_last_))}. -\end{itemize} +Equivalent to: +\begin{codeblock} +return ranges::less{}(std::forward(u), std::forward(t)); +\end{codeblock} \end{itemdescr} -\rSec3[func.search.bm]{Class template \tcode{boyer_moore_searcher}} - -\indexlibraryglobal{boyer_moore_searcher}% +\indexlibraryglobal{less}% \begin{codeblock} -namespace std { - template::value_type>, - class BinaryPredicate = equal_to<>> - class boyer_moore_searcher { - public: - boyer_moore_searcher(RandomAccessIterator1 pat_first, - RandomAccessIterator1 pat_last, - Hash hf = Hash(), - BinaryPredicate pred = BinaryPredicate()); - - template - pair - operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; +struct ranges::less { + template + constexpr bool operator()(T&& t, U&& u) const; - private: - RandomAccessIterator1 pat_first_; // \expos - RandomAccessIterator1 pat_last_; // \expos - Hash hash_; // \expos - BinaryPredicate pred_; // \expos - }; -} + using is_transparent = @\unspecnc@; +}; \end{codeblock} -\indexlibraryctor{boyer_moore_searcher}% \begin{itemdecl} -boyer_moore_searcher(RandomAccessIterator1 pat_first, - RandomAccessIterator1 pat_last, - Hash hf = Hash(), - BinaryPredicate pred = BinaryPredicate()); +template + constexpr bool operator()(T&& t, U&& u) const; \end{itemdecl} \begin{itemdescr} \pnum -\expects -The value type of \tcode{RandomAccessIterator1} meets -the \oldconcept{DefaultConstructible}, -the \oldconcept{Copy\-Constructible}, and -the \oldconcept{CopyAssignable} requirements. +\constraints +\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. \pnum -Let \tcode{V} be \tcode{iterator_traits::val\-ue_type}. -For any two values \tcode{A} and \tcode{B} of type \tcode{V}, -if \tcode{pred(A, B) == true}, then \tcode{hf(A) == hf(B)} is \tcode{true}. +\expects +If the expression \tcode{std::forward(t) < std::forward(u)} results in a +call to a built-in operator \tcode{<} comparing pointers of type \tcode{P}, the +conversion sequences from both \tcode{T} and \tcode{U} to \tcode{P} are +equality-preserving\iref{concepts.equality}; +otherwise, \tcode{T} and \tcode{U} model \libconcept{totally_ordered_with}. +For any expressions +\tcode{ET} and \tcode{EU} such that \tcode{decltype((ET))} is \tcode{T} and +\tcode{decltype((EU))} is \tcode{U}, exactly one of +\tcode{ranges::less\{\}(ET, EU)}, +\tcode{ranges::less\{\}(EU, ET)}, or +\tcode{ranges::equal_to\{\}(ET, EU)} +is \tcode{true}. \pnum \effects -Initializes -\tcode{pat_first_} with \tcode{pat_first}, -\tcode{pat_last_} with \tcode{pat_last}, -\tcode{hash_} with \tcode{hf}, and -% FIXME: The mbox prevents TeX from adding a bizarre hyphen after pred_. -\mbox{\tcode{pred_}} with \tcode{pred}. +\begin{itemize} +\item +If the expression \tcode{std::forward(t) < std::forward(u)} results in a +call to a built-in operator \tcode{<} comparing pointers: +returns \tcode{true} if (the converted value of) \tcode{t} precedes \tcode{u} in +the implementation-defined strict total order over pointers\iref{defns.order.ptr} +and otherwise \tcode{false}. -\pnum -\throws -Any exception thrown by the copy constructor of \tcode{RandomAccessIterator1}, -or by the default constructor, copy constructor, or the copy assignment operator of the value type of \tcode{RandomAccess\-Iterator1}, -or the copy constructor or \tcode{operator()} of \tcode{BinaryPredicate} or \tcode{Hash}. -May throw \tcode{bad_alloc} if additional memory needed for internal data structures cannot be allocated. +\item +Otherwise, equivalent to: +\tcode{return std::forward(t) < std::forward(u);} +\end{itemize} \end{itemdescr} -\indexlibrarymember{operator()}{boyer_moore_searcher}% +\indexlibraryglobal{greater_equal}% +\begin{codeblock} +struct ranges::greater_equal { + template + constexpr bool operator()(T&& t, U&& u) const; + + using is_transparent = @\unspecnc@; +}; +\end{codeblock} + \begin{itemdecl} -template - pair - operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; +template + constexpr bool operator()(T&& t, U&& u) const; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{RandomAccessIterator1} and \tcode{RandomAccessIterator2} -have the same value type. +\constraints +\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. \pnum \effects -Finds a subsequence of equal values in a sequence. +Equivalent to: +\begin{codeblock} +return !ranges::less{}(std::forward(t), std::forward(u)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{less_equal}% +\begin{itemdecl} +struct ranges::less_equal { + template + constexpr bool operator()(T&& t, U&& u) const; + + using is_transparent = @\unspecnc@; +}; +\end{itemdecl} + +\begin{itemdecl} +template + constexpr bool operator()(T&& t, U&& u) const; +\end{itemdecl} +\begin{itemdescr} \pnum -\returns -A pair of iterators \tcode{i} and \tcode{j} such that -\begin{itemize} -\item \tcode{i} is the first iterator -in the range \range{first}{last - (pat_last_ - pat_first_)} such that -for every non-negative integer \tcode{n} less than \tcode{pat_last_ - pat_first_} -the following condition holds: -\tcode{pred(*(i + n), *(pat_first_ + n)) != false}, and -\item \tcode{j == next(i, distance(pat_first_, pat_last_))}. -\end{itemize} -Returns \tcode{make_pair(first, first)} if \range{pat_first_}{pat_last_} is empty, -otherwise returns \tcode{make_pair(last, last)} if no such iterator is found. +\constraints +\tcode{T} and \tcode{U} satisfy \libconcept{totally_ordered_with}. \pnum -\complexity -At most \tcode{(last - first) * (pat_last_ - pat_first_)} applications of the predicate. +\effects +Equivalent to: +\begin{codeblock} +return !ranges::less{}(std::forward(u), std::forward(t)); +\end{codeblock} \end{itemdescr} -\rSec3[func.search.bmh]{Class template \tcode{boyer_moore_horspool_searcher}} +\rSec2[logical.operations]{Logical operations} -\indexlibraryglobal{boyer_moore_horspool_searcher}% -\begin{codeblock} -namespace std { - template::value_type>, - class BinaryPredicate = equal_to<>> - class boyer_moore_horspool_searcher { - public: - boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, - RandomAccessIterator1 pat_last, - Hash hf = Hash(), - BinaryPredicate pred = BinaryPredicate()); +\rSec3[logical.operations.general]{General} - template - pair - operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; +\pnum +The library provides basic function object classes for all of the logical +operators in the language\iref{expr.log.and,expr.log.or,expr.unary.op}. - private: - RandomAccessIterator1 pat_first_; // \expos - RandomAccessIterator1 pat_last_; // \expos - Hash hash_; // \expos - BinaryPredicate pred_; // \expos - }; -} -\end{codeblock} +\rSec3[logical.operations.and]{Class template \tcode{logical_and}} + +\indexlibraryglobal{logical_and}% +\begin{itemdecl} +template struct logical_and { + constexpr bool operator()(const T& x, const T& y) const; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{logical_and}% +\begin{itemdecl} +constexpr bool operator()(const T& x, const T& y) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x \&\& y}. +\end{itemdescr} + +\indexlibraryglobal{logical_and<>}% +\begin{itemdecl} +template<> struct logical_and { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) && std::forward(u)); -\indexlibraryctor{boyer_moore_horspool_searcher}% + using is_transparent = @\unspec@; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{logical_and<>}% \begin{itemdecl} -boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, - RandomAccessIterator1 pat_last, - Hash hf = Hash(), - BinaryPredicate pred = BinaryPredicate()); +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) && std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -\expects -The value type of \tcode{RandomAccessIterator1} meets the \oldconcept{DefaultConstructible}, -\oldconcept{Copy\-Constructible}, and \oldconcept{CopyAssignable} requirements. +\returns +\tcode{std::forward(t) \&\& std::forward(u)}. +\end{itemdescr} -\pnum -Let \tcode{V} be \tcode{iterator_traits::val\-ue_type}. -For any two values \tcode{A} and \tcode{B} of type \tcode{V}, -if \tcode{pred(A, B) == true}, then \tcode{hf(A) == hf(B)} is \tcode{true}. +\rSec3[logical.operations.or]{Class template \tcode{logical_or}} -\pnum -\effects -Initializes -\tcode{pat_first_} with \tcode{pat_first}, -\tcode{pat_last_} with \tcode{pat_last}, -\tcode{hash_} with \tcode{hf}, and -% FIXME: The mbox prevents TeX from adding a bizarre hyphen after pred_. -\mbox{\tcode{pred_}} with \tcode{pred}. +\indexlibraryglobal{logical_or}% +\begin{itemdecl} +template struct logical_or { + constexpr bool operator()(const T& x, const T& y) const; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{logical_or}% +\begin{itemdecl} +constexpr bool operator()(const T& x, const T& y) const; +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -Any exception thrown by the copy constructor of \tcode{RandomAccessIterator1}, -or by the default constructor, copy constructor, or the copy assignment operator of the value type of \tcode{RandomAccess\-Iterator1}, -or the copy constructor or \tcode{operator()} of \tcode{BinaryPredicate} or \tcode{Hash}. -May throw \tcode{bad_alloc} if additional memory needed for internal data structures cannot be allocated. +\returns +\tcode{x || y}. \end{itemdescr} -\indexlibrarymember{operator()}{boyer_moore_horspool_searcher}% +\indexlibraryglobal{logical_or<>}% \begin{itemdecl} -template - pair - operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; +template<> struct logical_or { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) || std::forward(u)); + + using is_transparent = @\unspec@; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{logical_or<>}% +\begin{itemdecl} +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) || std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -\mandates -\tcode{RandomAccessIterator1} and \tcode{RandomAccessIterator2} -have the same value type. +\returns +\tcode{std::forward(t) || std::forward(u)}. +\end{itemdescr} -\pnum -\effects -Finds a subsequence of equal values in a sequence. +\rSec3[logical.operations.not]{Class template \tcode{logical_not}} + +\indexlibraryglobal{logical_not}% +\begin{itemdecl} +template struct logical_not { + constexpr bool operator()(const T& x) const; +}; +\end{itemdecl} +\indexlibrarymember{operator()}{logical_not}% +\begin{itemdecl} +constexpr bool operator()(const T& x) const; +\end{itemdecl} + +\begin{itemdescr} \pnum \returns -A pair of iterators \tcode{i} and \tcode{j} such that -\begin{itemize} -\item \tcode{i} is the first iterator in the range -\range{first}{last - (pat_last_ - pat_first_)} such that -for every non-negative integer \tcode{n} less than \tcode{pat_last_ - pat_first_} -the following condition holds: -\tcode{pred(*(i + n), *(pat_first_ + n)) != false}, and -\item \tcode{j == next(i, distance(pat_first_, pat_last_))}. -\end{itemize} -Returns \tcode{make_pair(first, first)} if \range{pat_first_}{pat_last_} is empty, -otherwise returns \tcode{make_pair(last, last)} if no such iterator is found. +\tcode{!x}. +\end{itemdescr} + +\indexlibraryglobal{logical_not<>}% +\begin{itemdecl} +template<> struct logical_not { + template constexpr auto operator()(T&& t) const + -> decltype(!std::forward(t)); + + using is_transparent = @\unspec@; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{logical_not<>}% +\begin{itemdecl} +template constexpr auto operator()(T&& t) const + -> decltype(!std::forward(t)); +\end{itemdecl} +\begin{itemdescr} \pnum -\complexity -At most \tcode{(last - first) * (pat_last_ - pat_first_)} applications of the predicate. +\returns +\tcode{!std::forward(t)}. \end{itemdescr} -\rSec2[unord.hash]{Class template \tcode{hash}} -\pnum -\indexlibraryglobal{hash}% -\indextext{\idxcode{hash}!instantiation restrictions}% -The unordered associative containers defined in \ref{unord} use -specializations of the class template \tcode{hash}\iref{functional.syn} -as the default hash function. +\rSec2[bitwise.operations]{Bitwise operations} -\pnum -Each specialization of \tcode{hash} is either enabled or disabled, -as described below. -\begin{note} -Enabled specializations meet the \oldconcept{Hash} requirements, and -disabled specializations do not. -\end{note} -Each header that declares the template \tcode{hash} -provides enabled specializations of \tcode{hash} for \tcode{nullptr_t} and -all cv-unqualified arithmetic, enumeration, and pointer types. -For any type \tcode{Key} for which neither the library nor the user provides -an explicit or partial specialization of the class template \tcode{hash}, -\tcode{hash} is disabled. +\rSec3[bitwise.operations.general]{General} \pnum -If the library provides an explicit or partial specialization of \tcode{hash}, -that specialization is enabled except as noted otherwise, -and its member functions are \keyword{noexcept} except as noted otherwise. +The library provides basic function object classes for all of the bitwise +operators in the language\iref{expr.bit.and,expr.or,expr.xor,expr.unary.op}. -\pnum -If \tcode{H} is a disabled specialization of \tcode{hash}, -these values are \tcode{false}: -\tcode{is_default_constructible_v}, -\tcode{is_copy_constructible_v}, -\tcode{is_move_constructible_v}, -\tcode{is_copy_assignable_v}, and -\tcode{is_move_assignable_v}. -Disabled specializations of \tcode{hash} -are not function object types\iref{function.objects}. -\begin{note} -This means that the specialization of \tcode{hash} exists, but -any attempts to use it as a \oldconcept{Hash} will be ill-formed. -\end{note} +\rSec3[bitwise.operations.and]{Class template \tcode{bit_and}} + +\indexlibraryglobal{bit_and}% +\begin{itemdecl} +template struct bit_and { + constexpr T operator()(const T& x, const T& y) const; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{bit_and}% +\begin{itemdecl} +constexpr T operator()(const T& x, const T& y) const; +\end{itemdecl} +\begin{itemdescr} \pnum -An enabled specialization \tcode{hash} will: -\begin{itemize} -\item meet the \oldconcept{Hash} requirements (\tref{cpp17.hash}), -with \tcode{Key} as the function -call argument type, the \oldconcept{Default\-Constructible} requirements (\tref{cpp17.defaultconstructible}), -the \oldconcept{CopyAssignable} requirements (\tref{cpp17.copyassignable}), -the \oldconcept{Swappable} requirements\iref{swappable.requirements}, -\item meet the requirement that if \tcode{k1 == k2} is \tcode{true}, \tcode{h(k1) == h(k2)} is -also \tcode{true}, where \tcode{h} is an object of type \tcode{hash} and \tcode{k1} and \tcode{k2} -are objects of type \tcode{Key}; -\item meet the requirement that the expression \tcode{h(k)}, where \tcode{h} -is an object of type \tcode{hash} and \tcode{k} is an object of type -\tcode{Key}, shall not throw an exception unless \tcode{hash} is a -program-defined specialization. -\end{itemize} +\returns +\tcode{x \& y}. +\end{itemdescr} -\rSec1[type.index]{Class \tcode{type_index}} +\indexlibraryglobal{bit_and<>}% +\begin{itemdecl} +template<> struct bit_and { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) & std::forward(u)); -\rSec2[type.index.synopsis]{Header \tcode{} synopsis} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexheader{typeindex}% -\begin{codeblock} -#include // see \ref{compare.syn} +\indexlibrarymember{operator()}{bit_and<>}% +\begin{itemdecl} +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) & std::forward(u)); +\end{itemdecl} -namespace std { - class type_index; - template struct hash; - template<> struct hash; -} -\end{codeblock} +\begin{itemdescr} +\pnum +\returns +\tcode{std::forward(t) \& std::forward(u)}. +\end{itemdescr} -\rSec2[type.index.overview]{\tcode{type_index} overview} +\rSec3[bitwise.operations.or]{Class template \tcode{bit_or}} -\indexlibraryglobal{type_index}% -\begin{codeblock} -namespace std { - class type_index { - public: - type_index(const type_info& rhs) noexcept; - bool operator==(const type_index& rhs) const noexcept; - bool operator< (const type_index& rhs) const noexcept; - bool operator> (const type_index& rhs) const noexcept; - bool operator<=(const type_index& rhs) const noexcept; - bool operator>=(const type_index& rhs) const noexcept; - strong_ordering operator<=>(const type_index& rhs) const noexcept; - size_t hash_code() const noexcept; - const char* name() const noexcept; +\indexlibraryglobal{bit_or}% +\begin{itemdecl} +template struct bit_or { + constexpr T operator()(const T& x, const T& y) const; +}; +\end{itemdecl} - private: - const type_info* target; // \expos - // Note that the use of a pointer here, rather than a reference, - // means that the default copy/move constructor and assignment - // operators will be provided and work as expected. - }; -} -\end{codeblock} +\indexlibrarymember{operator()}{bit_or}% +\begin{itemdecl} +constexpr T operator()(const T& x, const T& y) const; +\end{itemdecl} +\begin{itemdescr} \pnum -The class \tcode{type_index} provides a simple wrapper for -\tcode{type_info} which can be used as an index type in associative -containers\iref{associative} and in unordered associative -containers\iref{unord}. +\returns +\tcode{x | y}. +\end{itemdescr} + +\indexlibraryglobal{bit_or<>}% +\begin{itemdecl} +template<> struct bit_or { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) | std::forward(u)); -\rSec2[type.index.members]{\tcode{type_index} members} + using is_transparent = @\unspec@; +}; +\end{itemdecl} -\indexlibraryctor{type_index}% +\indexlibrarymember{operator()}{bit_or<>}% \begin{itemdecl} -type_index(const type_info& rhs) noexcept; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) | std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Constructs a \tcode{type_index} object, the equivalent of \tcode{target = \&rhs}. +\returns +\tcode{std::forward(t) | std::forward(u)}. \end{itemdescr} -\indexlibrarymember{operator==}{type_index}% +\rSec3[bitwise.operations.xor]{Class template \tcode{bit_xor}} + +\indexlibraryglobal{bit_xor}% \begin{itemdecl} -bool operator==(const type_index& rhs) const noexcept; +template struct bit_xor { + constexpr T operator()(const T& x, const T& y) const; +}; \end{itemdecl} -\begin{itemdescr} -\pnum -\returns -\tcode{*target == *rhs.target}. -\end{itemdescr} - -\indexlibrarymember{operator<}{type_index}% +\indexlibrarymember{operator()}{bit_xor}% \begin{itemdecl} -bool operator<(const type_index& rhs) const noexcept; +constexpr T operator()(const T& x, const T& y) const; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{target->before(*rhs.target)}. +\tcode{x \caret{} y}. \end{itemdescr} -\indexlibrarymember{operator>}{type_index}% +\indexlibraryglobal{bit_xor<>}% +\begin{itemdecl} +template<> struct bit_xor { + template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) ^ std::forward(u)); + + using is_transparent = @\unspec@; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{bit_xor<>}% \begin{itemdecl} -bool operator>(const type_index& rhs) const noexcept; +template constexpr auto operator()(T&& t, U&& u) const + -> decltype(std::forward(t) ^ std::forward(u)); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{rhs.target->before(*target)}. +\tcode{std::forward(t) \caret{} std::forward(u)}. \end{itemdescr} -\indexlibrarymember{operator<=}{type_index}% +\rSec3[bitwise.operations.not]{Class template \tcode{bit_not}} + +\begin{itemdecl} +template struct bit_not { + constexpr T operator()(const T& x) const; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{bit_not}% \begin{itemdecl} -bool operator<=(const type_index& rhs) const noexcept; +constexpr T operator()(const T& x) const; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{!rhs.target->before(*target)}. +\tcode{\~{}x}. \end{itemdescr} -\indexlibrarymember{operator>=}{type_index}% +\indexlibraryglobal{bit_not<>}% +\begin{itemdecl} +template<> struct bit_not { + template constexpr auto operator()(T&& t) const + -> decltype(~std::forward(t)); + + using is_transparent = @\unspec@; +}; +\end{itemdecl} + +\indexlibrarymember{operator()}{bit_not<>}% \begin{itemdecl} -bool operator>=(const type_index& rhs) const noexcept; +template constexpr auto operator()(T&& t) const + -> decltype(~std::forward(t)); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{!target->before(*rhs.target)}. +\tcode{\~{}std::forward(t)}. \end{itemdescr} -\indexlibrarymember{operator<=>}{type_index}% + +\rSec2[func.identity]{Class \tcode{identity}} + +\indexlibraryglobal{identity}% \begin{itemdecl} -strong_ordering operator<=>(const type_index& rhs) const noexcept; +struct identity { + template + constexpr T&& operator()(T&& t) const noexcept; + + using is_transparent = @\unspec@; +}; + +template + constexpr T&& operator()(T&& t) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -if (*target == *rhs.target) return strong_ordering::equal; -if (target->before(*rhs.target)) return strong_ordering::less; -return strong_ordering::greater; -\end{codeblock} +Equivalent to: \tcode{return std::forward(t);} \end{itemdescr} -\indexlibrarymember{hash_code}{type_index}% + +\rSec2[func.not.fn]{Function template \tcode{not_fn}} + +\indexlibraryglobal{not_fn}% \begin{itemdecl} -size_t hash_code() const noexcept; +template constexpr @\unspec@ not_fn(F&& f); \end{itemdecl} \begin{itemdescr} +\pnum +In the text that follows: +\begin{itemize} +\item \tcode{g} is a value of the result of a \tcode{not_fn} 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}, + direct-non-list-initialized with \tcode{std::forward(f)}, +\item \tcode{call_args} is an argument pack + used in a function call expression\iref{expr.call} of \tcode{g}. +\end{itemize} + +\pnum +\mandates +\tcode{is_constructible_v \&\& is_move_constructible_v} +is \tcode{true}. + +\pnum +\expects +\tcode{FD} meets the \oldconcept{MoveConstructible} requirements. + \pnum \returns -\tcode{target->hash_code()}. +A perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} \tcode{g} +with call pattern \tcode{!invoke(fd, call_args...)}. + +\pnum +\throws +Any exception thrown by the initialization of \tcode{fd}. \end{itemdescr} -\indexlibrarymember{name}{type_index}% +\indexlibraryglobal{not_fn}% \begin{itemdecl} -const char* name() const noexcept; +template constexpr @\unspec@ not_fn() noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +In the text that follows: +\begin{itemize} +\item +\tcode{F} is the type of \tcode{f}, +\item +\tcode{g} is a value of the result of a \tcode{not_fn} invocation, +\item +\tcode{call_args} is an argument pack +used in a function call expression\iref{expr.call} of \tcode{g}. +\end{itemize} + +\pnum +\mandates +If \tcode{is_pointer_v || is_member_pointer_v} is \tcode{true}, +then \tcode{f != nullptr} is \tcode{true}. + \pnum \returns -\tcode{target->name()}. +A perfect forwarding call wrapper\iref{func.require} \tcode{g} that +does not have state entities, and +has the call pattern \tcode{!invoke(f, call_args...)}. \end{itemdescr} -\rSec2[type.index.hash]{Hash support} +\rSec2[func.bind.partial]{Function templates \tcode{bind_front} and \tcode{bind_back}} -\indexlibrarymember{hash}{type_index}% +\indexlibraryglobal{bind_front}% +\indexlibraryglobal{bind_back}% \begin{itemdecl} -template<> struct hash; +template + constexpr @\unspec@ bind_front(F&& f, Args&&... args); +template + constexpr @\unspec@ bind_back(F&& f, Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -For an object \tcode{index} of type \tcode{type_index}, -\tcode{hash()(index)} shall evaluate to the same result as \tcode{index.hash_code()}. -\end{itemdescr} - -\rSec1[execpol]{Execution policies} -\rSec2[execpol.general]{In general} +Within this subclause: +\begin{itemize} +\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}, + direct-non-list-initialized with \tcode{std::forward(f)}, +\item \tcode{BoundArgs} is a pack + that denotes \tcode{decay_t...}, +\item \tcode{bound_args} is + a pack of bound argument entities of \tcode{g}\iref{func.def} + of types \tcode{BoundArgs...}, + direct-non-list-initialized with \tcode{std::forward(args)...}, + respectively, and +\item \tcode{call_args} is an argument pack used in + a function call expression\iref{expr.call} of \tcode{g}. +\end{itemize} \pnum -Subclause~\ref{execpol} describes classes that are \defn{execution policy} types. An -object of an execution policy type indicates the kinds of parallelism allowed -in the execution of an algorithm and expresses the consequent requirements on -the element access functions. -\begin{example} +\mandates \begin{codeblock} -using namespace std; -vector v = @\commentellip@; - -// standard sequential sort -sort(v.begin(), v.end()); - -// explicitly sequential sort -sort(execution::seq, v.begin(), v.end()); - -// permitting parallel execution -sort(execution::par, v.begin(), v.end()); - -// permitting vectorization as well -sort(execution::par_unseq, v.begin(), v.end()); +is_constructible_v && +is_move_constructible_v && +(is_constructible_v && ...) && +(is_move_constructible_v && ...) \end{codeblock} -\end{example} -\begin{note} -Implementations can provide additional execution policies -to those described in this standard as extensions -to address parallel architectures that require idiosyncratic -parameters for efficient execution. -\end{note} - -\rSec2[execution.syn]{Header \tcode{} synopsis} - -\indexheader{execution}% -\begin{codeblock} -namespace std { - // \ref{execpol.type}, execution policy type trait - template struct is_execution_policy; - template constexpr bool @\libglobal{is_execution_policy_v}@ = is_execution_policy::value; -} - -namespace std::execution { - // \ref{execpol.seq}, sequenced execution policy - class sequenced_policy; - - // \ref{execpol.par}, parallel execution policy - class parallel_policy; - - // \ref{execpol.parunseq}, parallel and unsequenced execution policy - class parallel_unsequenced_policy; +is \tcode{true}. - // \ref{execpol.unseq}, unsequenced execution policy - class unsequenced_policy; +\pnum +\expects +\tcode{FD} meets the \oldconcept{MoveConstructible} requirements. +For each $\tcode{T}_i$ in \tcode{BoundArgs}, +if $\tcode{T}_i$ is an object type, +$\tcode{T}_i$ meets the \oldconcept{MoveConstructible} requirements. - // \ref{execpol.objects}, execution policy objects - inline constexpr sequenced_policy seq{ @\unspec@ }; - inline constexpr parallel_policy par{ @\unspec@ }; - inline constexpr parallel_unsequenced_policy par_unseq{ @\unspec@ }; - inline constexpr unsequenced_policy unseq{ @\unspec@ }; -} -\end{codeblock} +\pnum +\returns +A perfect forwarding call wrapper\iref{term.perfect.forwarding.call.wrapper} \tcode{g} +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} -\rSec2[execpol.type]{Execution policy type trait} +\pnum +\throws +Any exception thrown by +the initialization of the state entities of \tcode{g}\iref{func.def}. +\end{itemdescr} -\indexlibraryglobal{is_execution_policy}% +\indexlibraryglobal{bind_front}% +\indexlibraryglobal{bind_back}% \begin{itemdecl} -template struct is_execution_policy { @\seebelow@ }; +template + constexpr @\unspec@ bind_front(Args&&... args); +template + constexpr @\unspec@ bind_back(Args&&... args); \end{itemdecl} \begin{itemdescr} \pnum -\tcode{is_execution_policy} can be used to detect execution policies for the -purpose of excluding function signatures from otherwise ambiguous overload -resolution participation. +Within this subclause: +\begin{itemize} +\item +\tcode{F} is the type of \tcode{f}, +\item +\tcode{g} is a value of the result of +a \tcode{bind_front} or \tcode{bind_back} invocation, +\item +\tcode{BoundArgs} is a pack that denotes \tcode{decay_t...}, +\item +\tcode{bound_args} is a pack of bound argument entities of +\tcode{g}\iref{func.def} of types \tcode{BoundArgs...}, +direct-non-list-initialized with \tcode{std::forward(args)...}, +respectively, and +\item +\tcode{call_args} is an argument pack used in +a function call expression\iref{expr.call} of \tcode{g}. +\end{itemize} + +\pnum +\mandates +\begin{itemize} +\item +\tcode{(is_constructible_v \&\& ...)} is \tcode{true}, and +\item +\tcode{(is_move_constructible_v \&\& ...)} is \tcode{true}, and +\item +if \tcode{is_pointer_v || is_member_pointer_v} is \tcode{true}, +then \tcode{f != nullptr} is \tcode{true}. +\end{itemize} \pnum -\tcode{is_execution_policy} is a \oldconcept{UnaryTypeTrait} with a -base characteristic of \tcode{true_type} if \tcode{T} is the type of a standard -or \impldef{additional execution policies supported by parallel algorithms} -execution policy, otherwise \tcode{false_type}. +\expects +For each $\tcode{T}_i$ in \tcode{BoundArgs}, +$\tcode{T}_i$ meets the \oldconcept{MoveConstructible} requirements. -\begin{note} -This provision reserves the privilege of creating non-standard execution -policies to the library implementation. -\end{note} +\pnum +\returns +A perfect forwarding call wrapper\iref{func.require} \tcode{g} that +does not have a target object, and has the call pattern: +\begin{itemize} +\item +\tcode{invoke(f, bound_args..., call_args...)} +for a \tcode{bind_front} invocation, or +\item +\tcode{invoke(f, call_args..., bound_args...)} +for a \tcode{bind_back} invocation. +\end{itemize} \pnum -The behavior of a program that adds specializations for -\tcode{is_execution_policy} is undefined. +\throws +Any exception thrown by the initialization of \tcode{bound_args}. \end{itemdescr} -\rSec2[execpol.seq]{Sequenced execution policy} - -\indexlibraryglobal{execution::sequenced_policy}% -\begin{itemdecl} -class execution::sequenced_policy { @\unspec@ }; -\end{itemdecl} +\rSec2[func.bind]{Function object binders}% -\begin{itemdescr} -\pnum -The class \tcode{execution::sequenced_policy} is an execution policy type used -as a unique type to disambiguate parallel algorithm overloading and require -that a parallel algorithm's execution may not be parallelized. +\rSec3[func.bind.general]{General}% +\indextext{function object!binders|(} \pnum -During the execution of a parallel algorithm with -the \tcode{execution::sequenced_policy} policy, -if the invocation of an element access function exits via an exception, -\tcode{terminate} is invoked\iref{except.terminate}. -\end{itemdescr} +Subclause \ref{func.bind} describes a uniform mechanism for binding +arguments of callable objects. -\rSec2[execpol.par]{Parallel execution policy} +\rSec3[func.bind.isbind]{Class template \tcode{is_bind_expression}} -\indexlibraryglobal{execution::parallel_policy}% -\begin{itemdecl} -class execution::parallel_policy { @\unspec@ }; -\end{itemdecl} +\indexlibraryglobal{is_bind_expression}% +\begin{codeblock} +namespace std { + template struct is_bind_expression; // see below +} +\end{codeblock} -\begin{itemdescr} \pnum -The class \tcode{execution::parallel_policy} is an execution policy type used as -a unique type to disambiguate parallel algorithm overloading and indicate that -a parallel algorithm's execution may be parallelized. +The class template \tcode{is_bind_expression} can be used to detect function objects +generated by \tcode{bind}. The function template \tcode{bind} +uses \tcode{is_bind_expression} to detect subexpressions. \pnum -During the execution of a parallel algorithm with -the \tcode{execution::parallel_policy} policy, -if the invocation of an element access function exits via an exception, -\tcode{terminate} is invoked\iref{except.terminate}. -\end{itemdescr} +Specializations of the \tcode{is_bind_expression} template shall meet +the \oldconcept{UnaryTypeTrait} requirements\iref{meta.rqmts}. The implementation +provides a definition that has a base characteristic of +\tcode{true_type} if \tcode{T} is a type returned from \tcode{bind}, +otherwise it has a base characteristic of \tcode{false_type}. +A program may specialize this template for a program-defined type \tcode{T} +to have a base characteristic of \tcode{true_type} to indicate that +\tcode{T} should be treated as a subexpression in a \tcode{bind} call. -\rSec2[execpol.parunseq]{Parallel and unsequenced execution policy} +\rSec3[func.bind.isplace]{Class template \tcode{is_placeholder}} -\indexlibraryglobal{execution::parallel_unsequenced_policy}% -\begin{itemdecl} -class execution::parallel_unsequenced_policy { @\unspec@ }; -\end{itemdecl} +\indexlibraryglobal{is_placeholder}% +\begin{codeblock} +namespace std { + template struct is_placeholder; // see below +} +\end{codeblock} -\begin{itemdescr} \pnum -The class \tcode{execution::parallel_unsequenced_policy} is an execution policy type -used as a unique type to disambiguate parallel algorithm overloading and -indicate that a parallel algorithm's execution may be parallelized and -vectorized. +\indexlibraryglobal{placeholders}% +\indexlibrary{1@\tcode{_1}}% +\indexlibrary{2@\tcode{_2}}% +\indexlibrary{3@\tcode{_3}}% +\indexlibrary{4@\tcode{_4}}% +\indexlibrary{5@\tcode{_5}}% +\indexlibrary{6@\tcode{_6}}% +\indexlibrary{7@\tcode{_7}}% +\indexlibrary{8@\tcode{_8}}% +\indexlibrary{9@\tcode{_9}}% +\indexlibrary{10@\tcode{_10}}% +The class template \tcode{is_placeholder} can be used to detect the standard placeholders +\tcode{_1}, \tcode{_2}, and so on\iref{func.bind.place}. +The function template \tcode{bind} uses +\tcode{is_placeholder} to detect placeholders. \pnum -During the execution of a parallel algorithm with -the \tcode{execution::parallel_unsequenced_policy} policy, -if the invocation of an element access function exits via an exception, -\tcode{terminate} is invoked\iref{except.terminate}. -\end{itemdescr} - -\rSec2[execpol.unseq]{Unsequenced execution policy} - -\indexlibraryglobal{execution::unsequenced_policy}% -\begin{itemdecl} -class execution::unsequenced_policy { @\unspec@ }; -\end{itemdecl} +Specializations of the \tcode{is_placeholder} template shall meet +the \oldconcept{UnaryTypeTrait} requirements\iref{meta.rqmts}. The implementation +provides a definition that has the base characteristic of +\tcode{integral_constant} if \tcode{T} is the type of +\tcode{std::placeholders::_\placeholder{J}}, otherwise it has a +base characteristic of \tcode{integral_constant}. A program +may specialize this template for a program-defined type \tcode{T} to +have a base characteristic of \tcode{integral_constant} +with \tcode{N > 0} to indicate that \tcode{T} should be +treated as a placeholder type. -\begin{itemdescr} -\pnum -The class \tcode{unsequenced_policy} is an execution policy type -used as a unique type to disambiguate parallel algorithm overloading and -indicate that a parallel algorithm's execution may be vectorized, -e.g., executed on a single thread using instructions -that operate on multiple data items. +\rSec3[func.bind.bind]{Function template \tcode{bind}} +\indexlibrary{\idxcode{bind}|(} \pnum -During the execution of a parallel algorithm with -the \tcode{execution::unsequenced_policy} policy, -if the invocation of an element access function exits via an exception, -\tcode{terminate} is invoked\iref{except.terminate}. -\end{itemdescr} - -\rSec2[execpol.objects]{Execution policy objects} +In the text that follows: +\begin{itemize} +\item \tcode{g} is a value of the result of a \tcode{bind} invocation, +\item \tcode{FD} is the type \tcode{decay_t}, +\item \tcode{fd} is an lvalue that + is a target object of \tcode{g}\iref{func.def} of type \tcode{FD} + direct-non-list-initialized with \tcode{std::forward(f)}, +\item $\tcode{T}_i$ is the $i^\text{th}$ type in the template parameter pack \tcode{BoundArgs}, +\item $\tcode{TD}_i$ is the type \tcode{decay_t<$\tcode{T}_i$>}, +\item $\tcode{t}_i$ is the $i^\text{th}$ argument in the function parameter pack \tcode{bound_args}, +\item $\tcode{td}_i$ is a bound argument entity + of \tcode{g}\iref{func.def} of type $\tcode{TD}_i$ + direct-non-list-initialized with + \tcode{std::forward<\brk{}$\tcode{T}_i$>($\tcode{t}_i$)}, +\item $\tcode{U}_j$ is the $j^\text{th}$ deduced type of the \tcode{UnBoundArgs\&\&...} parameter + of the argument forwarding call wrapper, and +\item $\tcode{u}_j$ is the $j^\text{th}$ argument associated with $\tcode{U}_j$. +\end{itemize} -\indexlibraryglobal{seq}% -\indexlibraryglobal{par}% -\indexlibraryglobal{par_unseq}% -\indexlibrarymember{execution}{seq}% -\indexlibrarymember{execution}{par}% -\indexlibrarymember{execution}{par_unseq}% +\indexlibraryglobal{bind}% \begin{itemdecl} -inline constexpr execution::sequenced_policy execution::seq{ @\unspec@ }; -inline constexpr execution::parallel_policy execution::par{ @\unspec@ }; -inline constexpr execution::parallel_unsequenced_policy execution::par_unseq{ @\unspec@ }; -inline constexpr execution::unsequenced_policy execution::unseq{ @\unspec@ }; +template + constexpr @\unspec@ bind(F&& f, BoundArgs&&... bound_args); +template + constexpr @\unspec@ bind(F&& f, BoundArgs&&... bound_args); \end{itemdecl} \begin{itemdescr} \pnum -The header \libheader{execution} declares global objects associated with each type of execution policy. -\end{itemdescr} - -\rSec1[charconv]{Primitive numeric conversions} - -\rSec2[charconv.syn]{Header \tcode{} synopsis} +\mandates +\tcode{is_constructible_v} is \tcode{true}. For each $\tcode{T}_i$ +in \tcode{BoundArgs}, \tcode{is_cons\-tructible_v<$\tcode{TD}_i$, $\tcode{T}_i$>} is \tcode{true}. \pnum -When a function is specified -with a type placeholder of \tcode{\placeholder{integer-type}}, -the implementation provides overloads -for all cv-unqualified signed and unsigned integer types and \tcode{char} -in lieu of \tcode{\placeholder{integer-type}}. -When a function is specified -with a type placeholder of \tcode{\placeholder{floating-point-type}}, -the implementation provides overloads -for all cv-unqualified floating-point types\iref{basic.fundamental} -in lieu of \tcode{\placeholder{floating-point-type}}. +\expects +\tcode{FD} and each $\tcode{TD}_i$ meet +the \oldconcept{MoveConstructible} and \oldconcept{Destructible} requirements. +\tcode{\placeholdernc{INVOKE}(fd, $\tcode{w}_1$, $\tcode{w}_2$, $\dotsc$, +$\tcode{w}_N$)}\iref{func.require} is a valid expression for some +values $\tcode{w}_1$, $\tcode{w}_2$, $\dotsc{}$, $\tcode{w}_N$, where +$N$ has the value \tcode{sizeof...(bound_args)}. -\indexheader{charconv}% +\pnum +\returns +An argument forwarding call wrapper \tcode{g}\iref{func.require}. +A program that attempts to invoke a volatile-qualified \tcode{g} +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 \begin{codeblock} -@% -\indexlibraryglobal{chars_format}% -\indexlibrarymember{scientific}{chars_format}% -\indexlibrarymember{fixed}{chars_format}% -\indexlibrarymember{hex}{chars_format}% -\indexlibrarymember{general}{chars_format}% -@namespace std { - // floating-point format for primitive numerical conversion - enum class chars_format { - scientific = @\unspec@, - fixed = @\unspec@, - hex = @\unspec@, - general = fixed | scientific - }; -@% -\indexlibraryglobal{to_chars_result}% -\indexlibrarymember{ptr}{to_chars_result}% -\indexlibrarymember{ec}{to_chars_result} -@ - // \ref{charconv.to.chars}, primitive numerical output conversion - struct to_chars_result { // freestanding - char* ptr; - errc ec; - friend bool operator==(const to_chars_result&, const to_chars_result&) = default; - constexpr explicit operator bool() const noexcept { return ec == errc{}; } - }; - - constexpr to_chars_result to_chars(char* first, char* last, // freestanding - @\placeholder{integer-type}@ value, int base = 10); - to_chars_result to_chars(char* first, char* last, // freestanding - bool value, int base = 10) = delete; - - to_chars_result to_chars(char* first, char* last, // freestanding-deleted - @\placeholder{floating-point-type}@ value); - to_chars_result to_chars(char* first, char* last, // freestanding-deleted - @\placeholder{floating-point-type}@ value, chars_format fmt); - to_chars_result to_chars(char* first, char* last, // freestanding-deleted - @\placeholder{floating-point-type}@ value, chars_format fmt, int precision); -@% -\indexlibraryglobal{from_chars_result}% -\indexlibrarymember{ptr}{from_chars_result}% -\indexlibrarymember{ec}{from_chars_result} -@ - // \ref{charconv.from.chars}, primitive numerical input conversion - struct from_chars_result { // freestanding - const char* ptr; - errc ec; - friend bool operator==(const from_chars_result&, const from_chars_result&) = default; - constexpr explicit operator bool() const noexcept { return ec == errc{}; } - }; - - constexpr from_chars_result from_chars(const char* first, const char* last, // freestanding - @\placeholder{integer-type}@& value, int base = 10); - - from_chars_result from_chars(const char* first, const char* last, // freestanding-deleted - @\placeholder{floating-point-type}@& value, - chars_format fmt = chars_format::general); -} +@\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$@)) \end{codeblock} +for the first overload, and +\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$@)) +\end{codeblock} +for the second overload, +where the values and types of the target argument $\tcode{v}_\tcode{fd}$ and +of the bound arguments +$\tcode{v}_1$, $\tcode{v}_2$, $\dotsc$, $\tcode{v}_N$ are determined as specified below. \pnum -The type \tcode{chars_format} is a bitmask type\iref{bitmask.types} -with elements \tcode{scientific}, \tcode{fixed}, and \tcode{hex}. - -\pnum -The types \tcode{to_chars_result} and \tcode{from_chars_result} -have the data members and special members specified above. -They have no base classes or members other than those specified. - -\rSec2[charconv.to.chars]{Primitive numeric output conversion} - -\pnum -All functions named \tcode{to_chars} -convert \tcode{value} into a character string -by successively filling the range -\range{first}{last}, -where \range{first}{last} is required to be a valid range. -If the member \tcode{ec} -of the return value -is such that the value -is equal to the value of a value-initialized \tcode{errc}, -the conversion was successful -and the member \tcode{ptr} -is the one-past-the-end pointer of the characters written. -Otherwise, -the member \tcode{ec} has the value \tcode{errc::value_too_large}, -the member \tcode{ptr} has the value \tcode{last}, -and the contents of the range \range{first}{last} are unspecified. +\throws +Any exception thrown by the initialization of +the state entities of \tcode{g}. \pnum -The functions that take a floating-point \tcode{value} -but not a \tcode{precision} parameter -ensure that the string representation -consists of the smallest number of characters -such that -there is at least one digit before the radix point (if present) and -parsing the representation using the corresponding \tcode{from_chars} function -recovers \tcode{value} exactly. \begin{note} -This guarantee applies only if -\tcode{to_chars} and \tcode{from_chars} -are executed on the same implementation. +If all of \tcode{FD} and $\tcode{TD}_i$ meet +the requirements of \oldconcept{CopyConstructible}, then +the return type meets the requirements of \oldconcept{CopyConstructible}. \end{note} -If there are several such representations, -the representation with the smallest difference from -the floating-point argument value is chosen, -resolving any remaining ties using rounding according to -\tcode{round_to_nearest}\iref{round.style}. - -\pnum -The functions taking a \tcode{chars_format} parameter -determine the conversion specifier for \tcode{printf} as follows: -The conversion specifier is -\tcode{f} if \tcode{fmt} is \tcode{chars_format::fixed}, -\tcode{e} if \tcode{fmt} is \tcode{chars_format::scientific}, -\tcode{a} (without leading \tcode{"0x"} in the result) -if \tcode{fmt} is \tcode{chars_format::hex}, -and -\tcode{g} if \tcode{fmt} is \tcode{chars_format::general}. - -\indexlibraryglobal{to_chars}% -\begin{itemdecl} -constexpr to_chars_result to_chars(char* first, char* last, @\placeholder{integer-type}@ value, int base = 10); -\end{itemdecl} +\end{itemdescr} -\begin{itemdescr} \pnum -\expects -\tcode{base} has a value between 2 and 36 (inclusive). +\indextext{bound arguments}% +The values of the \term{bound arguments} $\tcode{v}_1$, $\tcode{v}_2$, $\dotsc$, $\tcode{v}_N$ and their +corresponding types $\tcode{V}_1$, $\tcode{V}_2$, $\dotsc$, $\tcode{V}_N$ depend on the +types $\tcode{TD}_i$ derived from +the call to \tcode{bind} and the +cv-qualifiers \cv{} of the call wrapper \tcode{g} as follows: +\begin{itemize} +\item if $\tcode{TD}_i$ is \tcode{reference_wrapper}, the +argument is \tcode{$\tcode{td}_i$.get()} and its type $\tcode{V}_i$ is \tcode{T\&}; -\pnum -\effects -The value of \tcode{value} is converted -to a string of digits in the given base -(with no redundant leading zeroes). -Digits in the range 10..35 (inclusive) -are represented as lowercase characters \tcode{a}..\tcode{z}. -If \tcode{value} is less than zero, -the representation starts with \tcode{'-'}. +\item if the value of \tcode{is_bind_expression_v<$\tcode{TD}_i$>} +is \tcode{true}, the argument is +\begin{codeblock} +static_cast<@\cv{} $\tcode{TD}_i$@&>(@$\tcode{td}_i$@)(std::forward<@$\tcode{U}_j$@>(@$\tcode{u}_j$@)...) +\end{codeblock} +and its type $\tcode{V}_i$ is +\tcode{invoke_result_t<\cv{} $\tcode{TD}_i$\&, $\tcode{U}_j$...>\&\&}; -\pnum -\throws -Nothing. -\end{itemdescr} +\item if the value \tcode{j} of \tcode{is_placeholder_v<$\tcode{TD}_i$>} +is not zero, the argument is \tcode{std::forward<$\tcode{U}_j$>($\tcode{u}_j$)} +and its type $\tcode{V}_i$ +is \tcode{$\tcode{U}_j$\&\&}; -\indexlibraryglobal{to_chars}% -\begin{itemdecl} -to_chars_result to_chars(char* first, char* last, @\placeholder{floating-point-type}@ value); -\end{itemdecl} +\item otherwise, the value is $\tcode{td}_i$ and its type $\tcode{V}_i$ +is \tcode{\cv{} $\tcode{TD}_i$\&}. +\end{itemize} -\begin{itemdescr} \pnum -\effects -\tcode{value} is converted to a string -in the style of \tcode{printf} -in the \tcode{"C"} locale. -The conversion specifier is \tcode{f} or \tcode{e}, -chosen according to the requirement for a shortest representation -(see above); -a tie is resolved in favor of \tcode{f}. +The value of the target argument $\tcode{v}_\tcode{fd}$ is \tcode{fd} and +its corresponding type $\tcode{V}_\tcode{fd}$ is \tcode{\cv{} FD\&}. +\indexlibrary{\idxcode{bind}|)}% -\pnum -\throws -Nothing. -\end{itemdescr} +\rSec3[func.bind.place]{Placeholders} -\indexlibraryglobal{to_chars}% -\begin{itemdecl} -to_chars_result to_chars(char* first, char* last, @\placeholder{floating-point-type}@ value, chars_format fmt); -\end{itemdecl} +\indexlibraryglobal{placeholders}% +\indexlibrary{1@\tcode{_1}}% +\indexlibrary{2@\tcode{_2}}% +\indexlibrary{3@\tcode{_3}}% +\indexlibrary{4@\tcode{_4}}% +\indexlibrary{5@\tcode{_5}}% +\indexlibrary{6@\tcode{_6}}% +\indexlibrary{7@\tcode{_7}}% +\indexlibrary{8@\tcode{_8}}% +\indexlibrary{9@\tcode{_9}}% +\indexlibrary{10@\tcode{_10}}% +% FIXME: Fomatting for M and the members _1, _2, _M below, +% as well as their usages elsewhere is inconsistent. +% Should they all follow the formatting used in delcaration of +% "namespace placeholders" in [functional.syn]? +\begin{codeblock} +namespace std::placeholders { + // \tcode{\placeholder{M}} is the number of placeholders + @\seebelow@ _1; + @\seebelow@ _2; + @\itcorr\vdots@ + @\seebelow@ _@\placeholdernc{M}@; +} +\end{codeblock} -\begin{itemdescr} \pnum -\expects -\tcode{fmt} has the value of -one of the enumerators of \tcode{chars_format}. +The number \tcode{\placeholder{M}} of placeholders is +\impldef{number of placeholders for bind expressions}. \pnum -\effects -\tcode{value} is converted to a string -in the style of \tcode{printf} -in the \tcode{"C"} locale. +All placeholder types meet the \oldconcept{DefaultConstructible} and +\oldconcept{CopyConstructible} requirements, and +their default constructors and copy/move +constructors are constexpr functions that +do not throw exceptions. It is \impldef{assignability of placeholder +objects} whether +placeholder types meet the \oldconcept{CopyAssignable} requirements, +but if so, their copy assignment operators are +constexpr functions that do not throw exceptions. \pnum -\throws -Nothing. -\end{itemdescr} +Placeholders should be defined as: +\begin{codeblock} +inline constexpr @\unspec@ _1{}; +\end{codeblock} +If they are not, they are declared as: +\begin{codeblock} +extern @\unspec@ _1; +\end{codeblock}% +\indextext{function object!binders|)} + +\pnum +\indextext{placeholders!freestanding item}% +Placeholders are freestanding items\iref{freestanding.item}. + +\rSec2[func.memfn]{Function template \tcode{mem_fn}}% +\indextext{function object!\idxcode{mem_fn}|(} -\indexlibraryglobal{to_chars}% +\indexlibraryglobal{mem_fn}% \begin{itemdecl} -to_chars_result to_chars(char* first, char* last, @\placeholder{floating-point-type}@ value, - chars_format fmt, int precision); +template constexpr @\unspec@ mem_fn(R T::* pm) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{fmt} has the value of -one of the enumerators of \tcode{chars_format}. - -\pnum -\effects -\tcode{value} is converted to a string -in the style of \tcode{printf} -in the \tcode{"C"} locale -with the given precision. - -\pnum -\throws -Nothing. +\returns +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 +\tcode{call_args} is an argument pack +used in a function call expression\iref{expr.call} of \tcode{fn}. \end{itemdescr} +\indextext{function object!\idxcode{mem_fn}|)} -\xrefc{7.21.6.1} +\rSec2[func.wrap]{Polymorphic function wrappers}% -\rSec2[charconv.from.chars]{Primitive numeric input conversion} +\rSec3[func.wrap.general]{General}% +\indextext{function object!wrapper|(} \pnum -All functions named \tcode{from_chars} -analyze the string \range{first}{last} -for a pattern, -where \range{first}{last} is required to be a valid range. -If no characters match the pattern, -\tcode{value} is unmodified, -the member \tcode{ptr} of the return value is \tcode{first} and -the member \tcode{ec} is equal to \tcode{errc::invalid_argument}. -\begin{note} -If the pattern allows for an optional sign, -but the string has no digit characters following the sign, -no characters match the pattern. -\end{note} -Otherwise, -the characters matching the pattern -are interpreted as a representation -of a value of the type of \tcode{value}. -The member \tcode{ptr} -of the return value -points to the first character -not matching the pattern, -or has the value \tcode{last} -if all characters match. -If the parsed value -is not in the range -representable by the type of \tcode{value}, -\tcode{value} is unmodified and -the member \tcode{ec} of the return value -is equal to \tcode{errc::result_out_of_range}. -Otherwise, -\tcode{value} is set to the parsed value, -after rounding according to \tcode{round_to_nearest}\iref{round.style}, and -the member \tcode{ec} is value-initialized. - -\indexlibraryglobal{from_chars}% -\begin{itemdecl} -constexpr from_chars_result from_chars(const char* first, const char* last, - @\placeholder{integer-type}@&@\itcorr[-1]@ value, int base = 10); -\end{itemdecl} +Subclause \ref{func.wrap} describes polymorphic wrapper classes that +encapsulate arbitrary callable objects. -\begin{itemdescr} \pnum -\expects -\tcode{base} has a value between 2 and 36 (inclusive). +Let \tcode{t} be an object of a type that is a specialization of +\tcode{function}, \tcode{copyable_function}, or \tcode{move_only_function}, +such that the target object \tcode{x} of \tcode{t} has a type that +is a specialization of +\tcode{function}, \tcode{copyable_function}, or \tcode{move_only_function}. +Each argument of the +invocation of \tcode{x} evaluated as part of the invocation of \tcode{t} +may alias an argument in the same position in the invocation of \tcode{t} that +has the same type, even if the corresponding parameter is not of reference type. +\begin{example} +\begin{codeblock} +move_only_function f{copyable_function{[](T) {}}}; +T t; +f(t); // it is unspecified how many copies of \tcode{T} are made +\end{codeblock} +\end{example} \pnum -\effects -The pattern is the expected form of the subject sequence -in the \tcode{"C"} locale -for the given nonzero base, -as described for \tcode{strtol}, -except that no \tcode{"0x"} or \tcode{"0X"} prefix shall appear -if the value of \tcode{base} is 16, -and except that \tcode{'-'} -is the only sign that may appear, -and only if \tcode{value} has a signed type. +\recommended +Implementations should avoid double wrapping when +constructing polymorphic wrappers from one another. + +\rSec3[func.wrap.badcall]{Class \tcode{bad_function_call}}% +\indexlibraryglobal{bad_function_call}% \pnum -\throws -Nothing. -\end{itemdescr} +An exception of type \tcode{bad_function_call} is thrown by +\tcode{function::operator()}\iref{func.wrap.func.inv} +when the function wrapper object has no target. + +\begin{codeblock} +namespace std { + class bad_function_call : public exception { + public: + // see \ref{exception} for the specification of the special member functions + const char* what() const noexcept override; + }; +} +\end{codeblock} -\indexlibraryglobal{from_chars}% +\indexlibrarymember{what}{bad_function_call}% \begin{itemdecl} -from_chars_result from_chars(const char* first, const char* last, @\placeholder{floating-point-type}@& value, - chars_format fmt = chars_format::general); +const char* what() const noexcept override; \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{fmt} has the value of -one of the enumerators of \tcode{chars_format}. - -\pnum -\effects -The pattern is the expected form of the subject sequence -in the \tcode{"C"} locale, -as described for \tcode{strtod}, -except that -\begin{itemize} -\item -the sign \tcode{'+'} may only appear in the exponent part; -\item -if \tcode{fmt} has \tcode{chars_format::scientific} set -but not \tcode{chars_format::fixed}, -the otherwise optional exponent part shall appear; -\item -if \tcode{fmt} has \tcode{chars_format::fixed} set -but not \tcode{chars_format::scientific}, -the optional exponent part shall not appear; and -\item -if \tcode{fmt} is \tcode{chars_format::hex}, -the prefix \tcode{"0x"} or \tcode{"0X"} is assumed. -\begin{example} -The string \tcode{0x123} -is parsed to have the value -\tcode{0} -with remaining characters \tcode{x123}. -\end{example} -\end{itemize} -In any case, the resulting \tcode{value} is one of -at most two floating-point values -closest to the value of the string matching the pattern. - -\pnum -\throws -Nothing. +\returns +An +\impldef{return value of \tcode{bad_function_call::what}} \ntbs{}. \end{itemdescr} -\xrefc{7.22.1.3, 7.22.1.4} - -\rSec1[format]{Formatting} +\rSec3[func.wrap.func]{Class template \tcode{function}} -\rSec2[format.syn]{Header \tcode{} synopsis} +\rSec4[func.wrap.func.general]{General} +\indexlibraryglobal{function}% -\indexheader{format}% -\indexlibraryglobal{format_parse_context}% -\indexlibraryglobal{wformat_parse_context}% -\indexlibraryglobal{format_context}% -\indexlibraryglobal{wformat_context}% -\indexlibraryglobal{format_args}% -\indexlibraryglobal{wformat_args}% -\indexlibraryglobal{format_to_n_result}% -\indexlibrarymember{out}{format_to_n_result}% -\indexlibrarymember{size}{format_to_n_result}% +\indexlibrarymember{result_type}{function}% \begin{codeblock} namespace std { - // \ref{format.context}, class template \tcode{basic_format_context} - template class basic_format_context; - using format_context = basic_format_context<@\unspec@, char>; - using wformat_context = basic_format_context<@\unspec@, wchar_t>; - - // \ref{format.args}, class template \tcode{basic_format_args} - template class basic_format_args; - using format_args = basic_format_args; - using wformat_args = basic_format_args; - - // \ref{format.fmt.string}, class template \tcode{basic_format_string} - template - struct basic_format_string; - - template struct @\exposid{runtime-format-string}@ { // \expos - private: - basic_string_view @\exposid{str}@; // \expos + template + class function { public: - @\exposid{runtime-format-string}@(basic_string_view s) noexcept : @\exposid{str}@(s) {} - @\exposid{runtime-format-string}@(const @\exposid{runtime-format-string}@&) = delete; - @\exposid{runtime-format-string}@& operator=(const @\exposid{runtime-format-string}@&) = delete; - }; - @\exposid{runtime-format-string}@ runtime_format(string_view fmt) noexcept { return fmt; } - @\exposid{runtime-format-string}@ runtime_format(wstring_view fmt) noexcept { return fmt; } - - template - using @\libglobal{format_string}@ = basic_format_string...>; - template - using @\libglobal{wformat_string}@ = basic_format_string...>; - - // \ref{format.functions}, formatting functions - template - string format(format_string fmt, Args&&... args); - template - wstring format(wformat_string fmt, Args&&... args); - template - string format(const locale& loc, format_string fmt, Args&&... args); - template - wstring format(const locale& loc, wformat_string fmt, Args&&... args); - - string vformat(string_view fmt, format_args args); - wstring vformat(wstring_view fmt, wformat_args args); - string vformat(const locale& loc, string_view fmt, format_args args); - wstring vformat(const locale& loc, wstring_view fmt, wformat_args args); - - template - Out format_to(Out out, format_string fmt, Args&&... args); - template - Out format_to(Out out, wformat_string fmt, Args&&... args); - template - Out format_to(Out out, const locale& loc, format_string fmt, Args&&... args); - template - Out format_to(Out out, const locale& loc, wformat_string fmt, Args&&... args); - - template - Out vformat_to(Out out, string_view fmt, format_args args); - template - Out vformat_to(Out out, wstring_view fmt, wformat_args args); - template - Out vformat_to(Out out, const locale& loc, string_view fmt, format_args args); - template - Out vformat_to(Out out, const locale& loc, wstring_view fmt, wformat_args args); - - template struct format_to_n_result { - Out out; - iter_difference_t size; - }; - template - format_to_n_result format_to_n(Out out, iter_difference_t n, - format_string fmt, Args&&... args); - template - format_to_n_result format_to_n(Out out, iter_difference_t n, - wformat_string fmt, Args&&... args); - template - format_to_n_result format_to_n(Out out, iter_difference_t n, - const locale& loc, format_string fmt, - Args&&... args); - template - format_to_n_result format_to_n(Out out, iter_difference_t n, - const locale& loc, wformat_string fmt, - Args&&... args); - - template - size_t formatted_size(format_string fmt, Args&&... args); - template - size_t formatted_size(wformat_string fmt, Args&&... args); - template - size_t formatted_size(const locale& loc, format_string fmt, Args&&... args); - template - size_t formatted_size(const locale& loc, wformat_string fmt, Args&&... args); - - // \ref{format.formatter}, formatter - template struct formatter; - - // \ref{format.formattable}, concept \libconcept{formattable} - template - concept formattable = @\seebelow@; - - template - concept @\defexposconcept{const-formattable-range}@ = // \expos - ranges::@\libconcept{input_range}@ && - @\libconcept{formattable}@, charT>; - - template - using @\exposid{fmt-maybe-const}@ = // \expos - conditional_t<@\exposconcept{const-formattable-range}@, const R, R>; - - // \ref{format.parse.ctx}, class template \tcode{basic_format_parse_context} - template class basic_format_parse_context; - using format_parse_context = basic_format_parse_context; - using wformat_parse_context = basic_format_parse_context; - - // \ref{format.range}, formatting of ranges - // \ref{format.range.fmtkind}, variable template \tcode{format_kind} - enum class @\libglobal{range_format}@ { - @\libmember{disabled}{range_format}@, - @\libmember{map}{range_format}@, - @\libmember{set}{range_format}@, - @\libmember{sequence}{range_format}@, - @\libmember{string}{range_format}@, - @\libmember{debug_string}{range_format}@ - }; + using result_type = R; - template - constexpr @\unspec@ format_kind = @\unspec@; + // \ref{func.wrap.func.con}, construct/copy/destroy + function() noexcept; + function(nullptr_t) noexcept; + function(const function&); + function(function&&) noexcept; + template function(F&&); - template - requires @\libconcept{same_as}@> - constexpr range_format format_kind = @\seebelow@; + function& operator=(const function&); + function& operator=(function&&); + function& operator=(nullptr_t) noexcept; + template function& operator=(F&&); + template function& operator=(reference_wrapper) noexcept; - // \ref{format.range.formatter}, class template \tcode{range_formatter} - template - requires @\libconcept{same_as}@, T> && @\libconcept{formattable}@ - class range_formatter; + ~function(); - // \ref{format.range.fmtdef}, class template \exposid{range-default-formatter} - template - struct @\exposid{range-default-formatter}@; // \expos + // \ref{func.wrap.func.mod}, function modifiers + void swap(function&) noexcept; - // \ref{format.range.fmtmap}, \ref{format.range.fmtset}, \ref{format.range.fmtstr}, specializations for maps, sets, and strings - template - requires (format_kind != range_format::disabled) && - @\libconcept{formattable}@, charT> - struct formatter : @\exposid{range-default-formatter}@, R, charT> { }; + // \ref{func.wrap.func.cap}, function capacity + explicit operator bool() const noexcept; - // \ref{format.arguments}, arguments - // \ref{format.arg}, class template \tcode{basic_format_arg} - template class basic_format_arg; + // \ref{func.wrap.func.inv}, function invocation + R operator()(ArgTypes...) const; - // \ref{format.arg.store}, class template \exposid{format-arg-store} - template class @\exposidnc{format-arg-store}@; // \expos + // \ref{func.wrap.func.targ}, function target access + const type_info& target_type() const noexcept; + template T* target() noexcept; + template const T* target() const noexcept; + }; - template - @\exposid{format-arg-store}@ - make_format_args(Args&... fmt_args); - template - @\exposid{format-arg-store}@ - make_wformat_args(Args&... args); + template + function(R(*)(ArgTypes...)) -> function; - // \ref{format.error}, class \tcode{format_error} - class format_error; + template function(F) -> function<@\seebelow@>; } \end{codeblock} - \pnum -The class template \tcode{format_to_n_result} -has the template parameters, data members, and special members specified above. It has no base classes or members other than those specified. - -\rSec2[format.string]{Format string} - -\rSec3[format.string.general]{In general} - -\pnum -A \defn{format string} for arguments \tcode{args} is -a (possibly empty) sequence of -\defnx{replacement fields}{replacement field!format string}, -\defnx{escape sequences}{escape sequence!format string}, -and characters other than \tcode{\{} and \tcode{\}}. -Let \tcode{charT} be the character type of the format string. -Each character that is not part of -a replacement field or an escape sequence -is copied unchanged to the output. -An escape sequence is one of \tcode{\{\{} or \tcode{\}\}}. -It is replaced with \tcode{\{} or \tcode{\}}, respectively, in the output. -The syntax of replacement fields is as follows: - -\begin{ncbnf} -\fmtnontermdef{replacement-field}\br - \terminal{\{} \opt{arg-id} \opt{format-specifier} \terminal{\}} -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{arg-id}\br - \terminal{0}\br - positive-integer -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{positive-integer}\br - nonzero-digit\br - positive-integer digit -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{nonnegative-integer}\br - digit\br - nonnegative-integer digit -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{nonzero-digit} \textnormal{one of}\br - \terminal{1 2 3 4 5 6 7 8 9} -\end{ncbnf} - -% FIXME: This exactly duplicates the digit grammar term from [lex] -\begin{ncbnf} -\fmtnontermdef{digit} \textnormal{one of}\br - \terminal{0 1 2 3 4 5 6 7 8 9} -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{format-specifier}\br - \terminal{:} format-spec -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{format-spec}\br - \textnormal{as specified by the \tcode{formatter} specialization for the argument type; cannot start with \terminal{\}} } -\end{ncbnf} - -\pnum -The \fmtgrammarterm{arg-id} field specifies the index of -the argument in \tcode{args} -whose value is to be formatted and inserted into the output -instead of the replacement field. -If there is no argument with -the index \fmtgrammarterm{arg-id} in \tcode{args}, -the string is not a format string for \tcode{args}. -The optional \fmtgrammarterm{format-specifier} field -explicitly specifies a format for the replacement value. +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}. \pnum -\begin{example} -\begin{codeblock} -string s = format("{0}-{{", 8); // value of \tcode{s} is \tcode{"8-\{"} -\end{codeblock} -\end{example} +The \tcode{function} class template is a call +wrapper\iref{func.def} whose call signature\iref{func.def} +is \tcode{R(ArgTypes...)}. \pnum -If all \fmtgrammarterm{arg-id}s in a format string are omitted -(including those in the \fmtgrammarterm{format-spec}, -as interpreted by the corresponding \tcode{formatter} specialization), -argument indices 0, 1, 2, \ldots{} will automatically be used in that order. -If some \fmtgrammarterm{arg-id}s are omitted and some are present, -the string is not a format string. \begin{note} -A format string cannot contain a -mixture of automatic and manual indexing. +The types deduced by the deduction guides for \tcode{function} +might change in future revisions of \Cpp{}. \end{note} -\begin{example} -\begin{codeblock} -string s0 = format("{} to {}", "a", "b"); // OK, automatic indexing -string s1 = format("{1} to {0}", "a", "b"); // OK, manual indexing -string s2 = format("{0} to {}", "a", "b"); // not a format string (mixing automatic and manual indexing), - // ill-formed -string s3 = format("{} to {1}", "a", "b"); // not a format string (mixing automatic and manual indexing), - // ill-formed -\end{codeblock} -\end{example} -\pnum -The \fmtgrammarterm{format-spec} field contains -\defnx{format specifications}{format specification!format string} -that define how the value should be presented. -Each type can define its own -interpretation of the \fmtgrammarterm{format-spec} field. -If \fmtgrammarterm{format-spec} does not conform -to the format specifications for -the argument type referred to by \fmtgrammarterm{arg-id}, -the string is not a format string for \tcode{args}. -\begin{example} -\begin{itemize} -\item -For arithmetic, pointer, and string types -the \fmtgrammarterm{format-spec} -is interpreted as a \fmtgrammarterm{std-format-spec} -as described in \iref{format.string.std}. -\item -For chrono types -the \fmtgrammarterm{format-spec} -is interpreted as a \fmtgrammarterm{chrono-format-spec} -as described in \iref{time.format}. -\item -For user-defined \tcode{formatter} specializations, -the behavior of the \tcode{parse} member function -determines how the \fmtgrammarterm{format-spec} -is interpreted. -\end{itemize} -\end{example} +\rSec4[func.wrap.func.con]{Constructors and destructor} -\rSec3[format.string.std]{Standard format specifiers} +\indexlibraryctor{function}% +\begin{itemdecl} +function() noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -Each \tcode{formatter} specialization -described in \ref{format.formatter.spec} -for fundamental and string types -interprets \fmtgrammarterm{format-spec} as a -\fmtgrammarterm{std-format-spec}. -\begin{note} -The format specification can be used to specify such details as -minimum field width, alignment, padding, and decimal precision. -Some of the formatting options -are only supported for arithmetic types. -\end{note} -The syntax of format specifications is as follows: - -\begin{ncbnf} -\fmtnontermdef{std-format-spec}\br - \opt{fill-and-align} \opt{sign} \opt{\terminal{\#}} \opt{\terminal{0}} \opt{width} \opt{precision} \opt{\terminal{L}} \opt{type} -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{fill-and-align}\br - \opt{fill} align -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{fill}\br - \textnormal{any character other than \tcode{\{} or \tcode{\}}} -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{align} \textnormal{one of}\br - \terminal{< > \caret} -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{sign} \textnormal{one of}\br - \terminal{+ -} \textnormal{space} -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{width}\br - positive-integer\br - \terminal{\{} \opt{arg-id} \terminal{\}} -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{precision}\br - \terminal{.} nonnegative-integer\br - \terminal{.} \terminal{\{} \opt{arg-id} \terminal{\}} -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{type} \textnormal{one of}\br - \terminal{a A b B c d e E f F g G o p P s x X ?} -\end{ncbnf} - -\pnum -Field widths are specified in \defnadj{field width}{units}; -the number of column positions required to display a sequence of -characters in a terminal. -The \defnadj{minimum}{field width} -is the number of field width units a replacement field minimally requires of -the formatted sequence of characters produced for a format argument. -The \defnadj{estimated}{field width} is the number of field width units -that are required for the formatted sequence of characters -produced for a format argument independent of -the effects of the \fmtgrammarterm{width} option. -The \defnadj{padding}{width} is the greater of \tcode{0} and -the difference of the minimum field width and the estimated field width. - -\begin{note} -The POSIX \tcode{wcswidth} function is an example of a function that, -given a string, returns the number of column positions required by -a terminal to display the string. -\end{note} +\ensures +\tcode{!*this}. +\end{itemdescr} -\pnum -The \defnadj{fill}{character} is the character denoted by -the \fmtgrammarterm{fill} option or, -if the \fmtgrammarterm{fill} option is absent, the space character. -For a format specification in UTF-8, UTF-16, or UTF-32, -the fill character corresponds to a single Unicode scalar value. -\begin{note} -The presence of a \fmtgrammarterm{fill} option -is signaled by the character following it, -which must be one of the alignment options. -If the second character of \fmtgrammarterm{std-format-spec} -is not a valid alignment option, -then it is assumed that -the \fmtgrammarterm{fill} and \fmtgrammarterm{align} options -are both absent. -\end{note} +\indexlibraryctor{function}% +\begin{itemdecl} +function(nullptr_t) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -The \fmtgrammarterm{align} option applies to all argument types. -The meaning of the various alignment options is as specified in \tref{format.align}. -\begin{example} -\begin{codeblock} -char c = 120; -string s0 = format("{:6}", 42); // value of \tcode{s0} is \tcode{"\ \ \ \ 42"} -string s1 = format("{:6}", 'x'); // value of \tcode{s1} is \tcode{"x\ \ \ \ \ "} -string s2 = format("{:*<6}", 'x'); // value of \tcode{s2} is \tcode{"x*****"} -string s3 = format("{:*>6}", 'x'); // value of \tcode{s3} is \tcode{"*****x"} -string s4 = format("{:*@\caret{}@6}", 'x'); // value of \tcode{s4} is \tcode{"**x***"} -string s5 = format("{:6d}", c); // value of \tcode{s5} is \tcode{"\ \ \ 120"} -string s6 = format("{:6}", true); // value of \tcode{s6} is \tcode{"true\ \ "} -string s7 = format("{:*<6.3}", "123456"); // value of \tcode{s7} is \tcode{"123***"} -string s8 = format("{:02}", 1234); // value of \tcode{s8} is \tcode{"1234"} -string s9 = format("{:*<}", "12"); // value of \tcode{s9} is \tcode{"12"} -string sA = format("{:*<6}", "12345678"); // value of \tcode{sA} is \tcode{"12345678"} -string sB = format("{:@\importexample[-2pt]{example_05}\kern0.75pt\caret{}@6}", "x"); // value of \tcode{sB} is \tcode{"\importexample[-2pt]{example_05}\importexample[-2pt]{example_05}x\importexample[-2pt]{example_05}\importexample[-2pt]{example_05}\importexample[-2pt]{example_05}"} -string sC = format("{:*@\caret{}@6}", "@\importexample[-2pt]{example_05}\kern0.75pt\importexample[-2pt]{example_05}\kern0.75pt\importexample[-2pt]{example_05}\kern0.75pt@"); // value of \tcode{sC} is \tcode{"\importexample[-2pt]{example_05}\importexample[-2pt]{example_05}\importexample[-2pt]{example_05}"} -\end{codeblock} -\end{example} -\begin{note} -The \fmtgrammarterm{fill}, \fmtgrammarterm{align}, and \tcode{0} options -have no effect when the minimum field width -is not greater than the estimated field width -because padding width is \tcode{0} in that case. -Since fill characters are assumed to have a field width of \tcode{1}, -use of a character with a different field width can produce misaligned output. -The \importexample[-2pt]{example_05} (\unicode{1f921}{clown face}) character has a field width of \tcode{2}. -The examples above that include that character -illustrate the effect of the field width -when that character is used as a fill character -as opposed to when it is used as a formatting argument. -\end{note} +\ensures +\tcode{!*this}. +\end{itemdescr} -\begin{floattable}{Meaning of \fmtgrammarterm{align} options}{format.align}{lp{.8\hsize}} -\topline -\lhdr{Option} & \rhdr{Meaning} \\ \rowsep -\tcode{<} & -Forces the formatted argument to be aligned to the start of the field -by inserting $n$ fill characters after the formatted argument -where $n$ is the padding width. -This is the default for -non-arithmetic non-pointer types, \tcode{charT}, and \tcode{bool}, -unless an integer presentation type is specified. -\\ \rowsep -% -\tcode{>} & -Forces the formatted argument to be aligned to the end of the field -by inserting $n$ fill characters before the formatted argument -where $n$ is the padding width. -This is the default for -arithmetic types other than \tcode{charT} and \tcode{bool}, -pointer types, -or when an integer presentation type is specified. -\\ \rowsep -% -\tcode{\caret} & -Forces the formatted argument to be centered within the field -by inserting -$\bigl\lfloor \frac{n}{2} \bigr\rfloor$ -fill characters before and -$\bigl\lceil \frac{n}{2} \bigr\rceil$ -fill characters after the formatted argument, where -$n$ is the padding width. -\\ -\end{floattable} +\indexlibraryctor{function}% +\begin{itemdecl} +function(const function& f); +\end{itemdecl} +\begin{itemdescr} \pnum -The \fmtgrammarterm{sign} option is only valid -for arithmetic types other than \tcode{charT} and \tcode{bool} -or when an integer presentation type is specified. -The meaning of the various options is as specified in \tref{format.sign}. - -\begin{floattable}{Meaning of \fmtgrammarterm{sign} options}{format.sign}{lp{.8\hsize}} -\topline -\lhdr{Option} & \rhdr{Meaning} \\ \rowsep -\tcode{+} & -Indicates that a sign should be used for both non-negative and negative -numbers. -The \tcode{+} sign is inserted before the output of \tcode{to_chars} for -non-negative numbers other than negative zero. -\begin{tailnote} -For negative numbers and negative zero -the output of \tcode{to_chars} will already contain the sign -so no additional transformation is performed. -\end{tailnote} -\\ \rowsep -% -\tcode{-} & -Indicates that a sign should be used for -negative numbers and negative zero only (this is the default behavior). -\\ \rowsep -% -space & -Indicates that a leading space should be used for -non-negative numbers other than negative zero, and -a minus sign for negative numbers and negative zero. -\\ -\end{floattable} +\ensures +\tcode{!*this} if \tcode{!f}; otherwise, +the target object of \tcode{*this} is a copy of the target object of \tcode{f}. \pnum -The \fmtgrammarterm{sign} option applies to floating-point infinity and NaN. -\begin{example} -\begin{codeblock} -double inf = numeric_limits::infinity(); -double nan = numeric_limits::quiet_NaN(); -string s0 = format("{0:},{0:+},{0:-},{0: }", 1); // value of \tcode{s0} is \tcode{"1,+1,1, 1"} -string s1 = format("{0:},{0:+},{0:-},{0: }", -1); // value of \tcode{s1} is \tcode{"-1,-1,-1,-1"} -string s2 = format("{0:},{0:+},{0:-},{0: }", inf); // value of \tcode{s2} is \tcode{"inf,+inf,inf, inf"} -string s3 = format("{0:},{0:+},{0:-},{0: }", nan); // value of \tcode{s3} is \tcode{"nan,+nan,nan, nan"} -\end{codeblock} -\end{example} +\throws +Nothing if \tcode{f}'s target is +a specialization of \tcode{reference_wrapper} or +a function pointer. Otherwise, may throw \tcode{bad_alloc} +or any exception thrown by the copy constructor of the stored callable object. \pnum -The \tcode{\#} option causes the -% FIXME: This is not a definition. -\defnx{alternate form}{alternate form!format string} -to be used for the conversion. -This option is valid for arithmetic types other than -\tcode{charT} and \tcode{bool} -or when an integer presentation type is specified, and not otherwise. -For integral types, -the alternate form inserts the -base prefix (if any) specified in \tref{format.type.int} -into the output after the sign character (possibly space) if there is one, or -before the output of \tcode{to_chars} otherwise. -For floating-point types, -the alternate form causes the result of the conversion of finite values -to always contain a decimal-point character, -even if no digits follow it. -% FIXME: This is a weird place for this part of the spec to appear. -Normally, a decimal-point character appears in the result of these -conversions only if a digit follows it. -In addition, for \tcode{g} and \tcode{G} conversions, -% FIXME: Are they normally? What does this even mean? Reach into to_chars and -% alter its behavior? -trailing zeros are not removed from the result. - -\pnum -The \tcode{0} option is valid for arithmetic types -other than \tcode{charT} and \tcode{bool}, pointer types, or -when an integer presentation type is specified. -For formatting arguments that have a value -other than an infinity or a NaN, -this option pads the formatted argument by -inserting the \tcode{0} character $n$ times -following the sign or base prefix indicators (if any) -where $n$ is \tcode{0} if the \fmtgrammarterm{align} option is present and -is the padding width otherwise. -\begin{example} -\begin{codeblock} -char c = 120; -string s1 = format("{:+06d}", c); // value of \tcode{s1} is \tcode{"+00120"} -string s2 = format("{:#06x}", 0xa); // value of \tcode{s2} is \tcode{"0x000a"} -string s3 = format("{:<06}", -42); // value of \tcode{s3} is \tcode{"-42\ \ \ "} (\tcode{0} has no effect) -string s4 = format("{:06}", inf); // value of \tcode{s4} is \tcode{"\ \ \ inf"} (\tcode{0} has no effect) -\end{codeblock} -\end{example} +\recommended +Implementations should avoid the use of +dynamically allocated memory for small callable objects, for example, where +\tcode{f}'s target is an object holding only a pointer or reference +to an object and a member function pointer. +\end{itemdescr} + +\indexlibraryctor{function}% +\begin{itemdecl} +function(function&& f) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -The \fmtgrammarterm{width} option specifies the minimum field width. -If the \fmtgrammarterm{width} option is absent, -the minimum field width is \tcode{0}. +\ensures +If \tcode{!f}, \tcode{*this} has no target; +otherwise, the target of \tcode{*this} is equivalent to +the target of \tcode{f} before the construction, and +\tcode{f} is in a valid state with an unspecified value. \pnum -If \tcode{\{ \opt{\fmtgrammarterm{arg-id}} \}} is used in -a \fmtgrammarterm{width} or \fmtgrammarterm{precision} option, -the value of the corresponding formatting argument is used as the value of the option. -The option is valid only if the corresponding formatting argument is -of standard signed or unsigned integer type. -If its value is negative, -an exception of type \tcode{format_error} is thrown. +\recommended +Implementations should avoid the use of +dynamically allocated memory for small callable objects, for example, +where \tcode{f}'s target is an object holding only a pointer or reference +to an object and a member function pointer. +\end{itemdescr} -\pnum -% FIXME: What if it's an arg-id? -If \fmtgrammarterm{positive-integer} is used in a -\fmtgrammarterm{width} option, the value of the \fmtgrammarterm{positive-integer} -is interpreted as a decimal integer and used as the value of the option. +\indexlibraryctor{function}% +\begin{itemdecl} +template function(F&& f); +\end{itemdecl} +\begin{itemdescr} \pnum -For the purposes of width computation, -a string is assumed to be in -a locale-independent, -\impldef{encoding assumption for \tcode{format} width computation} encoding. -Implementations should use either UTF-8, UTF-16, or UTF-32, -on platforms capable of displaying Unicode text in a terminal. -\begin{note} -This is the case for Windows -\begin{footnote} -Windows\textregistered\ is a registered trademark of Microsoft Corporation. -This information is given for the convenience of users of this document and -does not constitute an endorsement by ISO or IEC of this product. -\end{footnote}% --based and -many POSIX-based operating systems. -\end{note} +Let \tcode{FD} be \tcode{decay_t}. \pnum -For a sequence of characters in UTF-8, UTF-16, or UTF-32, -an implementation should use as its field width -the sum of the field widths of the first code point -of each extended grapheme cluster. -Extended grapheme clusters are defined by \UAX{29} of the Unicode Standard. -The following code points have a field width of 2: +\constraints \begin{itemize} \item -any code point with the \tcode{East_Asian_Width="W"} or -\tcode{East_Asian_Width="F"} Derived Extracted Property as described by -\UAX{44} of the Unicode Standard -\item -\ucode{4dc0} -- \ucode{4dff} (Yijing Hexagram Symbols) -\item -\ucode{1f300} -- \ucode{1f5ff} (Miscellaneous Symbols and Pictographs) +\tcode{is_same_v, function>} is \tcode{false}, and \item -\ucode{1f900} -- \ucode{1f9ff} (Supplemental Symbols and Pictographs) +\tcode{is_invocable_r_v} is \tcode{true}. \end{itemize} -The field width of all other code points is 1. - -\pnum -For a sequence of characters in neither UTF-8, UTF-16, nor UTF-32, -the field width is unspecified. \pnum -The \fmtgrammarterm{precision} option is valid -for floating-point and string types. -For floating-point types, -the value of this option specifies the precision -to be used for the floating-point presentation type. -For string types, -this option specifies the longest prefix of the formatted argument -to be included in the replacement field such that -the field width of the prefix is no greater than the value of this option. - -\pnum -If \fmtgrammarterm{nonnegative-integer} is used in -a \fmtgrammarterm{precision} option, -the value of the decimal integer is used as the value of the option. - -\pnum -When the \tcode{L} option is used, the form used for the conversion is called -the \defnx{locale-specific form}{locale-specific form!format string}. -The \tcode{L} option is only valid for arithmetic types, and -its effect depends upon the type. +\mandates \begin{itemize} \item -For integral types, the locale-specific form -causes the context's locale to be used -to insert the appropriate digit group separator characters. - -\item -For floating-point types, the locale-specific form -causes the context's locale to be used -to insert the appropriate digit group and radix separator characters. - +\tcode{is_copy_constructible_v} is \tcode{true}, and \item -For the textual representation of \tcode{bool}, the locale-specific form -causes the context's locale to be used -to insert the appropriate string as if obtained -with \tcode{numpunct::truename} or \tcode{numpunct::falsename}. +\tcode{is_constructible_v} is \tcode{true}. \end{itemize} \pnum -The \fmtgrammarterm{type} determines how the data should be presented. - -\pnum -% FIXME: What is a "string" here, exactly? -The available string presentation types are specified in \tref{format.type.string}. -% -\begin{floattable}{Meaning of \fmtgrammarterm{type} options for strings}{format.type.string}{ll} -\topline -\lhdr{Type} & \rhdr{Meaning} \\ \rowsep -none, \tcode{s} & -Copies the string to the output. -\\ \rowsep -% -\tcode{?} & -Copies the escaped string\iref{format.string.escaped} to the output. -\\ -\end{floattable} +\expects +\tcode{FD} meets the \oldconcept{CopyConstructible} requirements. \pnum -The meaning of some non-string presentation types -is defined in terms of a call to \tcode{to_chars}. -In such cases, -let \range{first}{last} be a range -large enough to hold the \tcode{to_chars} output -and \tcode{value} be the formatting argument value. -Formatting is done as if by calling \tcode{to_chars} as specified -and copying the output through the output iterator of the format context. -\begin{note} -Additional padding and adjustments are performed -prior to copying the output through the output iterator -as specified by the format specifiers. -\end{note} +\ensures +\tcode{!*this} is \tcode{true} if any of the following hold: +\begin{itemize} +\item \tcode{f} is a null function pointer value. +\item \tcode{f} is a null member pointer value. +\item \tcode{remove_cvref_t} is +a specialization of the \tcode{function} class template, and +\tcode{!f} is \tcode{true}. +\end{itemize} \pnum -The available integer presentation types -for integral types other than \tcode{bool} and \tcode{charT} -are specified in \tref{format.type.int}. -\begin{example} -\begin{codeblock} -string s0 = format("{}", 42); // value of \tcode{s0} is \tcode{"42"} -string s1 = format("{0:b} {0:d} {0:o} {0:x}", 42); // value of \tcode{s1} is \tcode{"101010 42 52 2a"} -string s2 = format("{0:#x} {0:#X}", 42); // value of \tcode{s2} is \tcode{"0x2a 0X2A"} -string s3 = format("{:L}", 1234); // value of \tcode{s3} can be \tcode{"1,234"} - // (depending on the locale) -\end{codeblock} -\end{example} - -\begin{floattable}{Meaning of \fmtgrammarterm{type} options for integer types}{format.type.int}{lp{.8\hsize}} -\topline -\lhdr{Type} & \rhdr{Meaning} \\ \rowsep -\tcode{b} & -\tcode{to_chars(first, last, value, 2)}; -\indextext{base prefix}% -the base prefix is \tcode{0b}. -\\ \rowsep -% -\tcode{B} & -The same as \tcode{b}, except that -\indextext{base prefix}% -the base prefix is \tcode{0B}. -\\ \rowsep -% -\tcode{c} & -Copies the character \tcode{static_cast(value)} to the output. -Throws \tcode{format_error} if \tcode{value} is not -in the range of representable values for \tcode{charT}. -\\ \rowsep -% -\tcode{d} & -\tcode{to_chars(first, last, value)}. -\\ \rowsep -% -\tcode{o} & -\tcode{to_chars(first, last, value, 8)}; -\indextext{base prefix}% -the base prefix is \tcode{0} if \tcode{value} is nonzero and is empty otherwise. -\\ \rowsep -% -\tcode{x} & -\tcode{to_chars(first, last, value, 16)}; -\indextext{base prefix}% -the base prefix is \tcode{0x}. -\\ \rowsep -% -\tcode{X} & -The same as \tcode{x}, except that -it uses uppercase letters for digits above 9 and -\indextext{base prefix}% -the base prefix is \tcode{0X}. -\\ \rowsep -% -none & -The same as \tcode{d}. -\begin{tailnote} -If the formatting argument type is \tcode{charT} or \tcode{bool}, -the default is instead \tcode{c} or \tcode{s}, respectively. -\end{tailnote} -\\ -\end{floattable} +Otherwise, \tcode{*this} has a target object of type \tcode{FD} +direct-non-list-initialized with \tcode{std::forward(f)}. \pnum -The available \tcode{charT} presentation types are specified in \tref{format.type.char}. -% -\begin{floattable}{Meaning of \fmtgrammarterm{type} options for \tcode{charT}}{format.type.char}{lp{.8\hsize}} -\topline -\lhdr{Type} & \rhdr{Meaning} \\ \rowsep -none, \tcode{c} & -Copies the character to the output. -\\ \rowsep -% -\tcode{b}, \tcode{B}, \tcode{d}, \tcode{o}, \tcode{x}, \tcode{X} & -As specified in \tref{format.type.int} -with \tcode{value} converted to the unsigned version of the underlying type. -\\ \rowsep -% -\tcode{?} & -Copies the escaped character\iref{format.string.escaped} to the output. -\\ -\end{floattable} +\throws +Nothing if \tcode{FD} is +a specialization of \tcode{reference_wrapper} or +a function pointer type. +Otherwise, may throw \tcode{bad_alloc} or +any exception thrown by the initialization of the target object. \pnum -The available \tcode{bool} presentation types are specified in \tref{format.type.bool}. -% -\begin{floattable}{Meaning of \fmtgrammarterm{type} options for \tcode{bool}}{format.type.bool}{ll} -\topline -\lhdr{Type} & \rhdr{Meaning} \\ \rowsep -none, -\tcode{s} & -Copies textual representation, either \tcode{true} or \tcode{false}, to the output. -\\ \rowsep -% -\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)}. -\\ -\end{floattable} +\recommended +Implementations should avoid the use of +dynamically allocated memory for small callable objects, for example, +where \tcode{f} refers to an object holding only a pointer or +reference to an object and a member function pointer. +\end{itemdescr} -\pnum -The available floating-point presentation types and their meanings -for values other than infinity and NaN are -specified in \tref{format.type.float}. -For lower-case presentation types, infinity and NaN are formatted as -\tcode{inf} and \tcode{nan}, respectively. -For upper-case presentation types, infinity and NaN are formatted as -\tcode{INF} and \tcode{NAN}, respectively. -\begin{note} -In either case, a sign is included -if indicated by the \fmtgrammarterm{sign} option. -\end{note} -\begin{floattable}{Meaning of \fmtgrammarterm{type} options for floating-point types}{format.type.float}{lp{.8\hsize}} -\topline -\lhdr{Type} & \rhdr{Meaning} \\ \rowsep -\tcode{a} & -If \fmtgrammarterm{precision} is specified, equivalent to -\begin{codeblock} -to_chars(first, last, value, chars_format::hex, precision) -\end{codeblock} -where \tcode{precision} is the specified formatting precision; equivalent to -\begin{codeblock} -to_chars(first, last, value, chars_format::hex) -\end{codeblock} -otherwise. -\\ -\rowsep -% -\tcode{A} & -The same as \tcode{a}, except that -it uses uppercase letters for digits above 9 and -\tcode{P} to indicate the exponent. -\\ \rowsep -% -\tcode{e} & -Equivalent to -\begin{codeblock} -to_chars(first, last, value, chars_format::scientific, precision) -\end{codeblock} -where \tcode{precision} is the specified formatting precision, -or \tcode{6} if \fmtgrammarterm{precision} is not specified. -\\ \rowsep -% -\tcode{E} & -The same as \tcode{e}, except that it uses \tcode{E} to indicate exponent. -\\ \rowsep -% -\tcode{f}, \tcode{F} & -Equivalent to -\begin{codeblock} -to_chars(first, last, value, chars_format::fixed, precision) -\end{codeblock} -where \tcode{precision} is the specified formatting precision, -or \tcode{6} if \fmtgrammarterm{precision} is not specified. -\\ \rowsep -% -\tcode{g} & -Equivalent to -\begin{codeblock} -to_chars(first, last, value, chars_format::general, precision) -\end{codeblock} -where \tcode{precision} is the specified formatting precision, -or \tcode{6} if \fmtgrammarterm{precision} is not specified. -\\ \rowsep -% -\tcode{G} & -The same as \tcode{g}, except that -it uses \tcode{E} to indicate exponent. -\\ \rowsep -% -none & -If \fmtgrammarterm{precision} is specified, equivalent to -\begin{codeblock} -to_chars(first, last, value, chars_format::general, precision) -\end{codeblock} -where \tcode{precision} is the specified formatting precision; equivalent to -\begin{codeblock} -to_chars(first, last, value) -\end{codeblock} -otherwise. -\\ -\end{floattable} +\begin{itemdecl} +template function(F) -> function<@\seebelow@>; +\end{itemdecl} +\begin{itemdescr} \pnum -The available pointer presentation types and their mapping to -\tcode{to_chars} are specified in \tref{format.type.ptr}. -\begin{note} -Pointer presentation types also apply to \tcode{nullptr_t}. -\end{note} - -\begin{floattable}{Meaning of \fmtgrammarterm{type} options for pointer types}{format.type.ptr}{lp{.8\hsize}} -\topline -\lhdr{Type} & \rhdr{Meaning} \\ \rowsep -none, \tcode{p} & -If \tcode{uintptr_t} is defined, -\begin{codeblock} -to_chars(first, last, reinterpret_cast(value), 16) -\end{codeblock} -with the prefix \tcode{0x} inserted immediately before the output of \tcode{to_chars}; -otherwise, implementation-defined. -\\ \rowsep -\tcode{P} & -The same as \tcode{p}, -except that it uses uppercase letters for digits above \tcode{9} and -the base prefix is \tcode{0X}. -\\ -\end{floattable} - -\rSec2[format.err.report]{Error reporting} +\constraints +\tcode{\&F::operator()} is well-formed when treated as an unevaluated operand and either +\begin{itemize} +\item +\tcode{F::operator()} is a non-static member function and +\tcode{decltype(\brk{}\&F::operator())} is either of the form +\tcode{R(G::*)(A...)}~\cv{}~\tcode{\opt{\&}~\opt{noexcept}} +or of the form +\tcode{R(*)(G, A...)~\opt{noexcept}} +for a type \tcode{G}, or +\item +\tcode{F::operator()} is a static member function and +\tcode{decltype(\&F::operator())} is of the form +\tcode{R(*)(A...) \opt{noexcept}}. +\end{itemize} \pnum -Formatting functions throw \tcode{format_error} if -an argument \tcode{fmt} is passed that -is not a format string for \tcode{args}. -They propagate exceptions thrown by operations of -\tcode{formatter} specializations and iterators. -Failure to allocate storage is reported by -throwing an exception as described in~\ref{res.on.exception.handling}. - -\rSec2[format.fmt.string]{Class template \tcode{basic_format_string}} +\remarks +The deduced type is \tcode{function}. +\pnum +\begin{example} \begin{codeblock} -namespace std { - template - struct @\libglobal{basic_format_string}@ { - private: - basic_string_view @\exposidnc{str}@; // \expos - - public: - template consteval basic_format_string(const T& s); - basic_format_string(@\exposid{runtime-format-string}@ s) noexcept : str(s.@\exposid{str}@) {} - - constexpr basic_string_view get() const noexcept { return @\exposid{str}@; } - }; +void f() { + int i{5}; + function g = [&](double) { return i; }; // deduces \tcode{function} } \end{codeblock} +\end{example} +\end{itemdescr} +\indexlibrarymember{operator=}{function}% \begin{itemdecl} -template consteval basic_format_string(const T& s); +function& operator=(const function& f); \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{const T\&} models \tcode{\libconcept{convertible_to}>}. - \pnum \effects -Direct-non-list-initializes \exposid{str} with \tcode{s}. +As if by \tcode{function(f).swap(*this);} \pnum -\remarks -A call to this function is not a core constant expression\iref{expr.const} -unless there exist \tcode{args} of types \tcode{Args} -such that \exposid{str} is a format string for \tcode{args}. +\returns +\tcode{*this}. \end{itemdescr} -\rSec2[format.functions]{Formatting functions} - -\pnum -In the description of the functions, operator \tcode{+} is used -for some of the iterator categories for which it does not have to be defined. -In these cases the semantics of \tcode{a + n} are -the same as in \ref{algorithms.requirements}. - -\indexlibraryglobal{format}% +\indexlibrarymember{operator=}{function}% \begin{itemdecl} -template - string format(format_string fmt, Args&&... args); +function& operator=(function&& f); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return vformat(fmt.@\exposid{str}@, make_format_args(args...)); -\end{codeblock} -\end{itemdescr} - -\indexlibraryglobal{format}% -\begin{itemdecl} -template - wstring format(wformat_string fmt, Args&&... args); -\end{itemdecl} +Replaces the target of \tcode{*this} +with the target of \tcode{f}. -\begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return vformat(fmt.@\exposid{str}@, make_wformat_args(args...)); -\end{codeblock} +\returns +\tcode{*this}. \end{itemdescr} -\indexlibraryglobal{format}% +\indexlibrarymember{operator=}{function}% \begin{itemdecl} -template - string format(const locale& loc, format_string fmt, Args&&... args); +function& operator=(nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return vformat(loc, fmt.@\exposid{str}@, make_format_args(args...)); -\end{codeblock} -\end{itemdescr} +If \tcode{*this != nullptr}, destroys the target of \keyword{this}. -\indexlibraryglobal{format}% -\begin{itemdecl} -template - wstring format(const locale& loc, wformat_string fmt, Args&&... args); -\end{itemdecl} +\pnum +\ensures +\tcode{!(*this)}. -\begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return vformat(loc, fmt.@\exposid{str}@, make_wformat_args(args...)); -\end{codeblock} +\returns +\tcode{*this}. \end{itemdescr} -\indexlibraryglobal{vformat}% +\indexlibrarymember{operator=}{function}% \begin{itemdecl} -string vformat(string_view fmt, format_args args); -wstring vformat(wstring_view fmt, wformat_args args); -string vformat(const locale& loc, string_view fmt, format_args args); -wstring vformat(const locale& loc, wstring_view fmt, wformat_args args); +template function& operator=(F&& f); \end{itemdecl} \begin{itemdescr} \pnum -\returns -A string object holding the character representation of -formatting arguments provided by \tcode{args} formatted according to -specifications given in \tcode{fmt}. -If present, \tcode{loc} is used for locale-specific formatting. +\constraints +\tcode{is_invocable_r_v\&, ArgTypes...>} is \tcode{true}. \pnum -\throws -As specified in~\ref{format.err.report}. +\effects +As if by: \tcode{function(std::forward(f)).swap(*this);} + +\pnum +\returns +\tcode{*this}. \end{itemdescr} -\indexlibraryglobal{format_to}% +\indexlibrarymember{operator=}{function}% \begin{itemdecl} -template - Out format_to(Out out, format_string fmt, Args&&... args); +template function& operator=(reference_wrapper f) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return vformat_to(std::move(out), fmt.@\exposid{str}@, make_format_args(args...)); -\end{codeblock} +As if by: \tcode{function(f).swap(*this);} + +\pnum +\returns +\tcode{*this}. \end{itemdescr} -\indexlibraryglobal{format_to}% +\indexlibrarydtor{function}% \begin{itemdecl} -template - Out format_to(Out out, wformat_string fmt, Args&&... args); +~function(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return vformat_to(std::move(out), fmt.@\exposid{str}@, make_wformat_args(args...)); -\end{codeblock} +If \tcode{*this != nullptr}, destroys the target of \keyword{this}. \end{itemdescr} -\indexlibraryglobal{format_to}% +\rSec4[func.wrap.func.mod]{Modifiers} + +\indexlibrarymember{swap}{function}% \begin{itemdecl} -template - Out format_to(Out out, const locale& loc, format_string fmt, Args&&... args); +void swap(function& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -return vformat_to(std::move(out), loc, fmt.@\exposid{str}@, make_format_args(args...)); -\end{codeblock} +Interchanges the target objects of \tcode{*this} and \tcode{other}. \end{itemdescr} -\indexlibraryglobal{format_to}% +\rSec4[func.wrap.func.cap]{Capacity} + +\indexlibrarymember{operator bool}{function}% \begin{itemdecl} -template - Out format_to(Out out, const locale& loc, wformat_string fmt, Args&&... args); +explicit operator bool() const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -return vformat_to(std::move(out), loc, fmt.@\exposid{str}@, make_wformat_args(args...)); -\end{codeblock} +\returns +\tcode{true} if \tcode{*this} has a target, otherwise \tcode{false}. \end{itemdescr} -\indexlibraryglobal{vformat_to}% +\rSec4[func.wrap.func.inv]{Invocation} + +\indexlibrary{\idxcode{function}!invocation}% +\indexlibrarymember{operator()}{function}% \begin{itemdecl} -template - Out vformat_to(Out out, string_view fmt, format_args args); -template - Out vformat_to(Out out, wstring_view fmt, wformat_args args); -template - Out vformat_to(Out out, const locale& loc, string_view fmt, format_args args); -template - Out vformat_to(Out out, const locale& loc, wstring_view fmt, wformat_args args); +R operator()(ArgTypes... args) const; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{charT} be \tcode{decltype(fmt)::value_type}. +\returns +\tcode{\placeholdernc{INVOKE}(f, std::forward(args)...)}\iref{func.require}, +where \tcode{f} is the target object\iref{func.def} of \tcode{*this}. \pnum -\constraints -\tcode{Out} satisfies \tcode{\libconcept{output_iterator}}. +\throws +\tcode{bad_function_call} if \tcode{!*this}; otherwise, any +exception thrown by the target object. +\end{itemdescr} -\pnum -\expects -\tcode{Out} models \tcode{\libconcept{output_iterator}}. +\rSec4[func.wrap.func.targ]{Target access} -\pnum -\effects -Places the character representation of formatting -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 the number of characters in that character representation. -If present, \tcode{loc} is used for locale-specific formatting. +\indexlibrarymember{target_type}{function}% +\begin{itemdecl} +const type_info& target_type() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum \returns -\tcode{out + N}. - -\pnum -\throws -As specified in~\ref{format.err.report}. +If \tcode{*this} has a target of type \tcode{T}, + \tcode{typeid(T)}; otherwise, \tcode{typeid(void)}. \end{itemdescr} -\indexlibraryglobal{format_to_n}% +\indexlibrarymember{target}{function}% \begin{itemdecl} -template - format_to_n_result format_to_n(Out out, iter_difference_t n, - format_string fmt, Args&&... args); -template - format_to_n_result format_to_n(Out out, iter_difference_t n, - wformat_string fmt, Args&&... args); -template - format_to_n_result format_to_n(Out out, iter_difference_t n, - const locale& loc, format_string fmt, - Args&&... args); -template - format_to_n_result format_to_n(Out out, iter_difference_t n, - const locale& loc, wformat_string fmt, - Args&&... args); +template T* target() noexcept; +template const T* target() const noexcept; \end{itemdecl} \begin{itemdescr} -\pnum -Let -\begin{itemize} -\item \tcode{charT} be \tcode{decltype(fmt.\exposid{str})::value_type}, -\item \tcode{N} be -\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, and -\item \tcode{M} be \tcode{clamp(n, 0, N)}. -\end{itemize} - -\pnum -\constraints -\tcode{Out} satisfies \tcode{\libconcept{output_iterator}}. - -\pnum -\expects -\tcode{Out} models \tcode{\libconcept{output_iterator}}, and -\tcode{formatter<}$\tcode{remove_cvref_t, charT>} -meets the \newoldconcept{BasicFormatter} requirements\iref{formatter.requirements} -for each $\tcode{T}_i$ in \tcode{Args}. - -\pnum -\effects -Places the first \tcode{M} characters of the character representation of -formatting the arguments provided by \tcode{args}, -formatted according to the specifications given in \tcode{fmt}, -into the range \range{out}{out + M}. -If present, \tcode{loc} is used for locale-specific formatting. - \pnum \returns -\tcode{\{out + M, N\}}. - -\pnum -\throws -As specified in~\ref{format.err.report}. +If \tcode{target_type() == typeid(T)} +a pointer to the stored function target; otherwise a null pointer. \end{itemdescr} -\indexlibraryglobal{formatted_size}% +\rSec4[func.wrap.func.nullptr]{Null pointer comparison operator functions} + +\indexlibrarymember{operator==}{function}% \begin{itemdecl} -template - size_t formatted_size(format_string fmt, Args&&... args); -template - size_t formatted_size(wformat_string fmt, Args&&... args); -template - size_t formatted_size(const locale& loc, format_string fmt, Args&&... args); -template - size_t formatted_size(const locale& loc, wformat_string fmt, Args&&... args); +template + bool operator==(const function& f, nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -Let \tcode{charT} be \tcode{decltype(fmt.\exposid{str})::value_type}. +\returns +\tcode{!f}. +\end{itemdescr} -\pnum -\expects -\tcode{formatter<}$\tcode{remove_cvref_t, charT>} -meets the \newoldconcept{BasicFormatter} requirements\iref{formatter.requirements} -for each $\tcode{T}_i$ in \tcode{Args}. +\rSec4[func.wrap.func.alg]{Specialized algorithms} -\pnum -\returns -The number of characters in the character representation of -formatting arguments \tcode{args} -formatted according to specifications given in \tcode{fmt}. -If present, \tcode{loc} is used for locale-specific formatting. +\indexlibrarymember{swap}{function}% +\begin{itemdecl} +template + void swap(function& f1, function& f2) noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\throws -As specified in~\ref{format.err.report}. -\end{itemdescr} +\effects +As if by: \tcode{f1.swap(f2);} +\end{itemdescr}% -\rSec2[format.formatter]{Formatter} +\rSec3[func.wrap.move]{Move-only wrapper} -\rSec3[formatter.requirements]{Formatter requirements} +\rSec4[func.wrap.move.general]{General} \pnum -A type \tcode{F} meets the \defnnewoldconcept{BasicFormatter} requirements if -it meets the +The header provides partial specializations of \tcode{move_only_function} +for each combination of the possible replacements +of the placeholders \cv{}, \placeholder{ref}, and \placeholder{noex} where \begin{itemize} -\item \oldconcept{DefaultConstructible} (\tref{cpp17.defaultconstructible}), -\item \oldconcept{CopyConstructible} (\tref{cpp17.copyconstructible}), -\item \oldconcept{CopyAssignable} (\tref{cpp17.copyassignable}), -\item \oldconcept{Swappable}\iref{swappable.requirements}, and -\item \oldconcept{Destructible} (\tref{cpp17.destructible}) +\item +\cv{} is either const or empty, +\item +\placeholder{ref} is either \tcode{\&}, \tcode{\&\&}, or empty, and +\item +\placeholder{noex} is either \tcode{true} or \tcode{false}. \end{itemize} -requirements, and -the expressions shown in \tref{formatter.basic} are valid and -have the indicated semantics. - -\pnum -A type \tcode{F} meets the \defnnewoldconcept{Formatter} requirements -if it meets the \newoldconcept{BasicFormatter} requirements and -the expressions shown in \tref{formatter} are valid and -have the indicated semantics. \pnum -Given character type \tcode{charT}, output iterator type -\tcode{Out}, and formatting argument type \tcode{T}, -in \tref{formatter.basic} and \tref{formatter}: +For each of the possible combinations of the placeholders mentioned above, +there is a placeholder \placeholder{inv-quals} defined as follows: \begin{itemize} -\item \tcode{f} is a value of type (possibly const) \tcode{F}, -\item \tcode{g} is an lvalue of type \tcode{F}, -\item \tcode{u} is an lvalue of type \tcode{T}, -\item \tcode{t} is a value of a type convertible to (possibly const) \tcode{T}, -\item \tcode{PC} is \tcode{basic_format_parse_context}, -\item \tcode{FC} is \tcode{basic_format_context}, -\item \tcode{pc} is an lvalue of type \tcode{PC}, and -\item \tcode{fc} is an lvalue of type \tcode{FC}. +\item +If \placeholder{ref} is empty, let \placeholder{inv-quals} be \cv{}\tcode{\&}, +\item +otherwise, let \placeholder{inv-quals} be \cv{} \placeholder{ref}. \end{itemize} -\tcode{pc.begin()} points to the beginning of the -\fmtgrammarterm{format-spec}\iref{format.string} -of the replacement field being formatted -in the format string. -If \fmtgrammarterm{format-spec} is not present or empty then either -\tcode{pc.begin() == pc.end()} or -\tcode{*pc.begin() == '\}'}. - -\begin{concepttable}{\newoldconcept{BasicFormatter} requirements}{formatter.basic} -{p{1.2in}p{1in}p{2.9in}} -\topline -\hdstyle{Expression} & \hdstyle{Return type} & \hdstyle{Requirement} \\ \capsep -\tcode{g.parse(pc)} & -\tcode{PC::iterator} & -Parses \fmtgrammarterm{format-spec}\iref{format.string} -for type \tcode{T} -in the range \range{pc.begin()}{pc.end()} -until the first unmatched character. -Throws \tcode{format_error} unless the whole range is parsed -or the unmatched character is \tcode{\}}. -\begin{note} -This allows formatters to emit meaningful error messages. -\end{note} -Stores the parsed format specifiers in \tcode{*this} and -returns an iterator past the end of the parsed range. -\\ \rowsep -\tcode{f.format(u, fc)} & -\tcode{FC::iterator} & -Formats \tcode{u} according to the specifiers stored in \tcode{*this}, -writes the output to \tcode{fc.out()}, and -returns an iterator past the end of the output range. -The output shall only depend on -\tcode{u}, -\tcode{fc.locale()}, -\tcode{fc.arg(n)} for any value \tcode{n} of type \tcode{size_t}, -and the range \range{pc.begin()}{pc.end()} -from the last call to \tcode{f.parse(pc)}. -\\ -\end{concepttable} - -\begin{concepttable}{\newoldconcept{Formatter} requirements}{formatter} -{p{1.2in}p{1in}p{2.9in}} -\topline -\hdstyle{Expression} & \hdstyle{Return type} & \hdstyle{Requirement} \\ \capsep -\tcode{f.format(t, fc)} & -\tcode{FC::iterator} & -Formats \tcode{t} according to the specifiers stored in \tcode{*this}, -writes the output to \tcode{fc.out()}, and -returns an iterator past the end of the output range. -The output shall only depend on -\tcode{t}, -\tcode{fc.locale()}, -\tcode{fc.arg(n)} for any value \tcode{n} of type \tcode{size_t}, -and the range \range{pc.begin()}{pc.end()} -from the last call to \tcode{f.parse(pc)}. -\\ \rowsep -\tcode{f.format(u, fc)} & -\tcode{FC::iterator} & -As above, but does not modify \tcode{u}. -\\ -\end{concepttable} - -\rSec3[format.formattable]{Concept \cname{formattable}} - -\pnum -Let \tcode{\placeholder{fmt-iter-for}} be an unspecified type -that models -\tcode{\libconcept{output_iterator}}\iref{iterator.concept.output}. +\rSec4[func.wrap.move.class]{Class template \tcode{move_only_function}} + +\indexlibraryglobal{move_only_function}% \begin{codeblock} -template>> - concept @\defexposconcept{formattable-with}@ = // \expos - @\libconcept{semiregular}@ && - requires(Formatter& f, const Formatter& cf, T&& t, Context fc, - basic_format_parse_context pc) - { - { f.parse(pc) } -> @\libconcept{same_as}@; - { cf.format(t, fc) } -> @\libconcept{same_as}@; - }; +namespace std { + template + class move_only_function { + public: + using result_type = R; -template - concept @\deflibconcept{formattable}@ = - @\exposconcept{formattable-with}@, basic_format_context<@\placeholder{fmt-iter-for}@, charT>>; -\end{codeblock} + // \ref{func.wrap.move.ctor}, constructors, assignment, and destructor + move_only_function() noexcept; + move_only_function(nullptr_t) noexcept; + move_only_function(move_only_function&&) noexcept; + template move_only_function(F&&); + template + explicit move_only_function(in_place_type_t, Args&&...); + template + explicit move_only_function(in_place_type_t, initializer_list, Args&&...); -\pnum -A type \tcode{T} and a character type \tcode{charT} -model \libconcept{formattable} -if \tcode{formatter, charT>} meets -the \newoldconcept{BasicFormatter} requirements\iref{formatter.requirements} -and, if \tcode{remove_reference_t} is const-qualified, -the \newoldconcept{Formatter} requirements. + move_only_function& operator=(move_only_function&&); + move_only_function& operator=(nullptr_t) noexcept; + template move_only_function& operator=(F&&); -\rSec3[format.formatter.spec]{Formatter specializations} -\indexlibraryglobal{formatter}% + ~move_only_function(); -\pnum -% FIXME: Specify this in [format.functions], not here! -The functions defined in \ref{format.functions} use -specializations of the class template \tcode{formatter} to format -individual arguments. + // \ref{func.wrap.move.inv}, invocation + explicit operator bool() const noexcept; + R operator()(ArgTypes...) @\cv{}@ @\placeholder{ref}@ noexcept(@\placeholder{noex}@); -\pnum -Let \tcode{charT} be either \tcode{char} or \keyword{wchar_t}. -Each specialization of \tcode{formatter} is either enabled or disabled, -as described below. -\indextext{\idxcode{formatter}!debug-enabled specialization of}% -A \defn{debug-enabled} specialization of \tcode{formatter} -additionally provides -a public, constexpr, non-static member function \tcode{set_debug_format()} -which modifies the state of the \tcode{formatter} to be as if -the type of the \fmtgrammarterm{std-format-spec} -parsed by the last call to \tcode{parse} were \tcode{?}. -Each header that declares the template \tcode{formatter} -provides the following enabled specializations: -\begin{itemize} -\item -\indexlibrary{\idxcode{formatter}!specializations!character types}% -The debug-enabled specializations -\begin{codeblock} -template<> struct formatter; -template<> struct formatter; -template<> struct formatter; -\end{codeblock} + // \ref{func.wrap.move.util}, utility + void swap(move_only_function&) noexcept; + friend void swap(move_only_function&, move_only_function&) noexcept; + friend bool operator==(const move_only_function&, nullptr_t) noexcept; -\item -\indexlibrary{\idxcode{formatter}!specializations!string types}% -For each \tcode{charT}, -the debug-enabled string type specializations -\begin{codeblock} -template<> struct formatter; -template<> struct formatter; -template struct formatter; -template - struct formatter, charT>; -template - struct formatter, charT>; + private: + template + static constexpr bool @\exposid{is-callable-from}@ = @\seebelow@; // \expos + }; +} \end{codeblock} -\item -\indexlibrary{\idxcode{formatter}!specializations!arithmetic types}% -For each \tcode{charT}, -for each cv-unqualified arithmetic type \tcode{ArithmeticT} -other than -\tcode{char}, -\keyword{wchar_t}, -\keyword{char8_t}, -\keyword{char16_t}, or -\keyword{char32_t}, -a specialization -\begin{codeblock} -template<> struct formatter; -\end{codeblock} +\pnum +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. -\item -\indexlibrary{\idxcode{formatter}!specializations!pointer types}% -\indexlibrary{\idxcode{formatter}!specializations!\idxcode{nullptr_t}}% -For each \tcode{charT}, -the pointer type specializations -\begin{codeblock} -template<> struct formatter; -template<> struct formatter; -template<> struct formatter; -\end{codeblock} -\end{itemize} -The \tcode{parse} member functions of these formatters -interpret the format specification -as a \fmtgrammarterm{std-format-spec} -as described in \ref{format.string.std}. +\pnum +\recommended +Implementations should avoid the use of dynamically allocated memory +for a small contained value. \begin{note} -Specializations such as \tcode{formatter} -and \tcode{formatter} -that would require implicit -multibyte / wide string or character conversion are disabled. +Such small-object optimization can only be applied to a type \tcode{T} +for which \tcode{is_nothrow_move_constructible_v} is \tcode{true}. \end{note} -\pnum -For any types \tcode{T} and \tcode{charT} for which -neither the library nor the user provides -an explicit or partial specialization of -the class template \tcode{formatter}, -\tcode{formatter} is disabled. - -\pnum -If the library provides an explicit or partial specialization of -\tcode{formatter}, that specialization is enabled -and meets the \newoldconcept{Formatter} requirements -except as noted otherwise. +\rSec4[func.wrap.move.ctor]{Constructors, assignment, and destructor} -\pnum -If \tcode{F} is a disabled specialization of \tcode{formatter}, these -values are \tcode{false}: -\begin{itemize} -\item \tcode{is_default_constructible_v}, -\item \tcode{is_copy_constructible_v}, -\item \tcode{is_move_constructible_v}, -\item \tcode{is_copy_assignable_v}, and -\item \tcode{is_move_assignable_v}. -\end{itemize} +\indextext{move_only_function::is-callable-from@\tcode{move_only_function::\exposid{is-callable-from}}}% +\begin{itemdecl} +template + static constexpr bool @\exposid{is-callable-from}@ = @\seebelow@; +\end{itemdecl} +\begin{itemdescr} \pnum -An enabled specialization \tcode{formatter} meets the -\newoldconcept{BasicFormatter} requirements\iref{formatter.requirements}. -\begin{example} +If \placeholder{noex} is \tcode{true}, +\tcode{\exposid{is-callable-from}} is equal to: +\begin{codeblock} +is_nothrow_invocable_r_v && +is_nothrow_invocable_r_v +\end{codeblock} +Otherwise, \tcode{\exposid{is-callable-from}} is equal to: \begin{codeblock} -#include -#include +is_invocable_r_v && +is_invocable_r_v +\end{codeblock} +\end{itemdescr} -enum color { red, green, blue }; -const char* color_names[] = { "red", "green", "blue" }; +\indexlibraryctor{move_only_function}% +\begin{itemdecl} +move_only_function() noexcept; +move_only_function(nullptr_t) noexcept; +\end{itemdecl} -template<> struct std::formatter : std::formatter { - auto format(color c, format_context& ctx) const { - return formatter::format(color_names[c], ctx); - } -}; +\begin{itemdescr} +\pnum +\ensures +\tcode{*this} has no target object. +\end{itemdescr} -struct err {}; +\indexlibraryctor{move_only_function}% +\begin{itemdecl} +move_only_function(move_only_function&& f) noexcept; +\end{itemdecl} -std::string s0 = std::format("{}", 42); // OK, library-provided formatter -std::string s1 = std::format("{}", L"foo"); // error: disabled formatter -std::string s2 = std::format("{}", red); // OK, user-provided formatter -std::string s3 = std::format("{}", err{}); // error: disabled formatter -\end{codeblock} -\end{example} +\begin{itemdescr} +\pnum +\ensures +The target object of \tcode{*this} is +the target object \tcode{f} had before construction, and +\tcode{f} is in a valid state with an unspecified value. +\end{itemdescr} -\rSec3[format.string.escaped]{Formatting escaped characters and strings} +\indexlibraryctor{move_only_function}% +\begin{itemdecl} +template move_only_function(F&& f); +\end{itemdecl} +\begin{itemdescr} \pnum -\indextext{string!formatted as escaped}% -\indextext{character!formatted as escaped}% -A character or string can be formatted as \defn{escaped} -to make it more suitable for debugging or for logging. +Let \tcode{VT} be \tcode{decay_t}. \pnum -The escaped string \placeholder{E} representation of a string \placeholder{S} -is constructed by encoding a sequence of characters as follows. -The associated character encoding \placeholder{CE} -for \tcode{charT}~(\tref{lex.string.literal}) -is used to both interpret \placeholder{S} and construct \placeholder{E}. - +\constraints \begin{itemize} \item -\unicode{0022}{quotation mark} (\tcode{"}) is appended to \placeholder{E}. - +\tcode{remove_cvref_t} is not the same type as \tcode{move_only_function}, and \item -For each code unit sequence \placeholder{X} in \placeholder{S} that either -encodes a single character, -is a shift sequence, or -is a sequence of ill-formed code units, -processing is in order as follows: - -\begin{itemize} +\tcode{remove_cvref_t} is not a specialization of \tcode{in_place_type_t}, and \item -If \placeholder{X} encodes a single character \placeholder{C}, then: +\tcode{\exposid{is-callable-from}} is \tcode{true}. +\end{itemize} -\begin{itemize} -\item -If \placeholder{C} is one of the characters in \tref{format.escape.sequences}, -then the two characters shown as the corresponding escape sequence -are appended to \placeholder{E}. +\pnum +\mandates +\tcode{is_constructible_v} is \tcode{true}. -\item -Otherwise, if \placeholder{C} is not \unicode{0020}{space} and +\pnum +\expects +\tcode{VT} meets the \oldconcept{Destructible} requirements, and +if \tcode{is_move_constructible_v} is \tcode{true}, +\tcode{VT} meets the \oldconcept{MoveConstructible} requirements. +\pnum +\ensures +\tcode{*this} has no target object if any of the following hold: \begin{itemize} \item -\placeholder{CE} is UTF-8, UTF-16, or UTF-32 and -\placeholder{C} corresponds to a Unicode scalar value -whose Unicode property \tcode{General_Category} has a value in the groups -\tcode{Separator} (\tcode{Z}) or \tcode{Other} (\tcode{C}), -as described by \UAX{44} of the Unicode Standard, or - -\item -\placeholder{CE} is UTF-8, UTF-16, or UTF-32 and -\placeholder{C} corresponds to a Unicode scalar value -with the Unicode property \tcode{Grapheme_Extend=Yes} -as described by \UAX{44} of the Unicode Standard and -\placeholder{C} is not immediately preceded in \placeholder{S} by -a character \placeholder{P} appended to \placeholder{E} -without translation to an escape sequence, or - +\tcode{f} is a null function pointer value, or \item -\placeholder{CE} is neither UTF-8, UTF-16, nor UTF-32 and -\placeholder{C} is one of an implementation-defined set -of separator or non-printable characters -\end{itemize} - -then the sequence \tcode{\textbackslash u\{\placeholder{hex-digit-sequence}\}} -is appended to \placeholder{E}, -where \tcode{\placeholder{hex-digit-sequence}} -is the shortest hexadecimal representation -of \placeholder{C} using lower-case hexadecimal digits. - +\tcode{f} is a null member pointer value, or \item -Otherwise, \placeholder{C} is appended to \placeholder{E}. +\tcode{remove_cvref_t} is a specialization of +the \tcode{move_only_function} class template, +and \tcode{f} has no target object. \end{itemize} +Otherwise, \tcode{*this} has a target object of type \tcode{VT} +direct-non-list-initialized with \tcode{std::forward(f)}. -\item -Otherwise, if \placeholder{X} is a shift sequence, -the effect on \placeholder{E} and further decoding of \placeholder{S} -is unspecified. - -\recommended -A shift sequence should be represented in \placeholder{E} -such that the original code unit sequence of \placeholder{S} -can be reconstructed. - -\item -Otherwise (\placeholder{X} is a sequence of ill-formed code units), -each code unit \placeholder{U} is appended to \placeholder{E} in order -as the sequence \tcode{\textbackslash x\{\placeholder{hex-digit-sequence}\}}, -where \tcode{\placeholder{hex-digit-sequence}} -is the shortest hexadecimal representation of \placeholder{U} -using lower-case hexadecimal digits. -\end{itemize} +\pnum +\throws +Any exception thrown by the initialization of the target object. +May throw \tcode{bad_alloc} unless \tcode{VT} is +a function pointer or a specialization of \tcode{reference_wrapper}. +\end{itemdescr} -\item -Finally, \unicode{0022}{quotation mark} (\tcode{"}) -is appended to \placeholder{E}. -\end{itemize} -% -\begin{floattable}{Mapping of characters to escape sequences}{format.escape.sequences}{ll} -\topline -\lhdr{Character} & \rhdr{Escape sequence} \\ \rowsep -\unicode{0009}{character tabulation} & -\tcode{\textbackslash t} -\\ \rowsep -% -\unicode{000a}{line feed} & -\tcode{\textbackslash n} -\\ \rowsep -% -\unicode{000d}{carriage return} & -\tcode{\textbackslash r} -\\ \rowsep -% -\unicode{0022}{quotation mark} & -\tcode{\textbackslash "} -\\ \rowsep -% -\unicode{005c}{reverse solidus} & -\tcode{\textbackslash\textbackslash} -\\ -\end{floattable} +\indexlibraryctor{move_only_function}% +\begin{itemdecl} +template + explicit move_only_function(in_place_type_t, Args&&... args); +\end{itemdecl} +\begin{itemdescr} \pnum -The escaped string representation of a character \placeholder{C} -is equivalent to the escaped string representation -of a string of \placeholder{C}, except that: +Let \tcode{VT} be \tcode{decay_t}. +\pnum +\constraints \begin{itemize} \item -the result starts and ends with \unicode{0027}{apostrophe} (\tcode{'}) -instead of \unicode{0022}{quotation mark} (\tcode{"}), and -\item -if \placeholder{C} is \unicode{0027}{apostrophe}, -the two characters \tcode{\textbackslash '} are appended to \placeholder{E}, and +\tcode{is_constructible_v} is \tcode{true}, and \item -if \placeholder{C} is \unicode{0022}{quotation mark}, -then \placeholder{C} is appended unchanged. +\tcode{\exposid{is-callable-from}} is \tcode{true}. \end{itemize} -\begin{example} -\begin{codeblock} -string s0 = format("[{}]", "h\tllo"); // \tcode{s0} has value: \tcode{[h\ \ \ \ llo]} -string s1 = format("[{:?}]", "h\tllo"); // \tcode{s1} has value: \tcode{["h\textbackslash tllo"]} -string s2 = format("[{:?}]", "@\importexample[-2.5pt]{example_01}@"); @\kern1.25pt@// \tcode{s2} has value: \tcode{["\importexample[-2.5pt]{example_01}"]} -string s3 = format("[{:?}, {:?}]", '\'', '"'); // \tcode{s3} has value: \tcode{['\textbackslash '', '"']} - -// The following examples assume use of the UTF-8 encoding -string s4 = format("[{:?}]", string("\0 \n \t \x02 \x1b", 9)); - // \tcode{s4} has value: \tcode{["\textbackslash u\{0\} \textbackslash n \textbackslash t \textbackslash u\{2\} \textbackslash u\{1b\}"]} -string s5 = format("[{:?}]", "\xc3\x28"); // invalid UTF-8, \tcode{s5} has value: \tcode{["\textbackslash x\{c3\}("]} -string s6 = format("[{:?}]", "@\importexample{example_02}@"); @\kern0.75pt@// \tcode{s6} has value: \tcode{["\importexample{example_03}\textbackslash{u}\{200d\}\importexample{example_04}"]} -string s7 = format("[{:?}]", "\u0301"); // \tcode{s7} has value: \tcode{["\textbackslash u\{301\}"]} -string s8 = format("[{:?}]", "\\\u0301"); // \tcode{s8} has value: \tcode{["\textbackslash \textbackslash \textbackslash u\{301\}"]} -string s9 = format("[{:?}]", "e\u0301\u0323"); // \tcode{s9} has value: \tcode{["\importexample[-2pt]{example_06}"]} -\end{codeblock} -\end{example} +\pnum +\mandates +\tcode{VT} is the same type as \tcode{T}. -\rSec3[format.parse.ctx]{Class template \tcode{basic_format_parse_context}} +\pnum +\expects +\tcode{VT} meets the \oldconcept{Destructible} requirements, and +if \tcode{is_move_constructible_v} is \tcode{true}, +\tcode{VT} meets the \oldconcept{MoveConstructible} requirements. -\indexlibraryglobal{basic_format_parse_context}% -\indexlibrarymember{char_type}{basic_format_parse_context}% -\indexlibrarymember{const_iterator}{basic_format_parse_context}% -\indexlibrarymember{iterator}{basic_format_parse_context}% -\begin{codeblock} -namespace std { - template - class basic_format_parse_context { - public: - using char_type = charT; - using const_iterator = typename basic_string_view::const_iterator; - using iterator = const_iterator; +\pnum +\ensures +\tcode{*this} has a target object of type \tcode{VT} +direct-non-list-initialized with \tcode{std::forward\brk{}(args)...}. - private: - iterator begin_; // \expos - iterator end_; // \expos - enum indexing { unknown, manual, automatic }; // \expos - indexing indexing_; // \expos - size_t next_arg_id_; // \expos - size_t num_args_; // \expos +\pnum +\throws +Any exception thrown by the initialization of the target object. +May throw \tcode{bad_alloc} unless \tcode{VT} is +a function pointer or a specialization of \tcode{reference_wrapper}. +\end{itemdescr} - public: - constexpr explicit basic_format_parse_context(basic_string_view fmt) noexcept; - basic_format_parse_context(const basic_format_parse_context&) = delete; - basic_format_parse_context& operator=(const basic_format_parse_context&) = delete; +\indexlibraryctor{move_only_function}% +\begin{itemdecl} +template + explicit move_only_function(in_place_type_t, initializer_list ilist, Args&&... args); +\end{itemdecl} - constexpr const_iterator begin() const noexcept; - constexpr const_iterator end() const noexcept; - constexpr void advance_to(const_iterator it); +\begin{itemdescr} +\pnum +Let \tcode{VT} be \tcode{decay_t}. - constexpr size_t next_arg_id(); - constexpr void check_arg_id(size_t id); +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_constructible_v\&, Args...>} is +\tcode{true}, and +\item +\tcode{\exposid{is-callable-from}} is \tcode{true}. +\end{itemize} - template - constexpr void check_dynamic_spec(size_t id) noexcept; - constexpr void check_dynamic_spec_integral(size_t id) noexcept; - constexpr void check_dynamic_spec_string(size_t id) noexcept; - }; -} -\end{codeblock} +\pnum +\mandates +\tcode{VT} is the same type as \tcode{T}. \pnum -An instance of \tcode{basic_format_parse_context} holds -the format string parsing state, consisting of -the format string range being parsed and -the argument counter for automatic indexing. +\expects +\tcode{VT} meets the \oldconcept{Destructible} requirements, and +if \tcode{is_move_constructible_v} is \tcode{true}, +\tcode{VT} meets the \oldconcept{MoveConstructible} requirements. -\indexlibraryctor{basic_format_parse_context}% -\begin{itemdecl} -constexpr explicit basic_format_parse_context(basic_string_view fmt) noexcept; -\end{itemdecl} +\pnum +\ensures +\tcode{*this} has a target object of type \tcode{VT} +direct-non-list-initialized with +\tcode{ilist, std::for\-ward(args)...}. -\begin{itemdescr} \pnum -\effects -Initializes -\tcode{begin_} with \tcode{fmt.begin()}, -\tcode{end_} with \tcode{fmt.end()}, -\tcode{indexing_} with \tcode{unknown}, -\tcode{next_arg_id_} with \tcode{0}, and -\tcode{num_args_} with \tcode{0}. -\begin{note} -Any call to -\tcode{next_arg_id}, \tcode{check_arg_id}, or \tcode{check_dynamic_spec} -on an instance of \tcode{basic_format_parse_context} -initialized using this constructor is not a core constant expression. -\end{note} +\throws +Any exception thrown by the initialization of the target object. +May throw \tcode{bad_alloc} unless \tcode{VT} is +a function pointer or a specialization of \tcode{reference_wrapper}. \end{itemdescr} -\indexlibrarymember{begin}{basic_format_parse_context}% +\indexlibrarymember{operator=}{move_only_function}% \begin{itemdecl} -constexpr const_iterator begin() const noexcept; +move_only_function& operator=(move_only_function&& f); \end{itemdecl} \begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{move_only_function(std::move(f)).swap(*this);} + \pnum \returns -\tcode{begin_}. +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{end}{basic_format_parse_context}% +\indexlibrarymember{operator=}{move_only_function}% \begin{itemdecl} -constexpr const_iterator end() const noexcept; +move_only_function& operator=(nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\effects +Destroys the target object of \tcode{*this}, if any. + \pnum \returns -\tcode{end_}. +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{advance_to}{basic_format_parse_context}% +\indexlibrarymember{operator=}{move_only_function}% \begin{itemdecl} -constexpr void advance_to(const_iterator it); +template move_only_function& operator=(F&& f); \end{itemdecl} \begin{itemdescr} \pnum -\expects -\tcode{end()} is reachable from \tcode{it}. +\effects +Equivalent to: \tcode{move_only_function(std::forward(f)).swap(*this);} \pnum -\effects -Equivalent to: \tcode{begin_ = it;} +\returns +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{next_arg_id}{basic_format_parse_context}% +\indexlibrarydtor{move_only_function}% \begin{itemdecl} -constexpr size_t next_arg_id(); +~move_only_function(); \end{itemdecl} \begin{itemdescr} \pnum \effects -If \tcode{indexing_ != manual} is \tcode{true}, equivalent to: -\begin{codeblock} -if (indexing_ == unknown) - indexing_ = automatic; -return next_arg_id_++; -\end{codeblock} +Destroys the target object of \tcode{*this}, if any. +\end{itemdescr} -\pnum -\throws -\tcode{format_error} if \tcode{indexing_ == manual} is \tcode{true}. -\begin{note} -This indicates mixing of automatic and manual argument indexing. -\end{note} +\rSec4[func.wrap.move.inv]{Invocation} + +\indexlibrarymember{operator bool}{move_only_function}% +\begin{itemdecl} +explicit operator bool() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum -\remarks -Let \tcode{\placeholder{cur-arg-id}} be the value of \tcode{next_arg_id_} prior to this call. -Call expressions where \tcode{\placeholder{cur-arg-id} >= num_args_} is \tcode{true} -are not core constant expressions\iref{expr.const}. +\returns +\tcode{true} if \tcode{*this} has a target object, otherwise \tcode{false}. \end{itemdescr} -\indexlibrarymember{check_arg_id}{basic_format_parse_context}% +\indexlibrarymember{operator()}{move_only_function}% \begin{itemdecl} -constexpr void check_arg_id(size_t id); +R operator()(ArgTypes... args) @\cv{}@ @\placeholder{ref}@ noexcept(@\placeholder{noex}@); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{*this} has a target object. + \pnum \effects -If \tcode{indexing_ != automatic} is \tcode{true}, equivalent to: +Equivalent to: \begin{codeblock} -if (indexing_ == unknown) - indexing_ = manual; +return @\placeholder{INVOKE}@(static_cast(f), std::forward(args)...); \end{codeblock} - -\pnum -\throws -\tcode{format_error} if -\tcode{indexing_ == automatic} is \tcode{true}. -\begin{note} -This indicates mixing of automatic and manual argument indexing. -\end{note} - -\pnum -\remarks -A call to this function is a core constant expression\iref{expr.const} only if -\tcode{id < num_args_} is \tcode{true}. +where \tcode{f} is an lvalue designating the target object of \tcode{*this} and +\tcode{F} is the type of \tcode{f}. \end{itemdescr} -\indexlibrarymember{check_dynamic_spec}{basic_format_parse_context}% +\rSec4[func.wrap.move.util]{Utility} + +\indexlibrarymember{swap}{move_only_function}% \begin{itemdecl} -template - constexpr void check_dynamic_spec(size_t id) noexcept; +void swap(move_only_function& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\mandates -The types in \tcode{Ts...} are unique. -Each type in \tcode{Ts...} is one of -\keyword{bool}, -\tcode{char_type}, -\keyword{int}, -\tcode{\keyword{unsigned} \keyword{int}}, -\tcode{\keyword{long} \keyword{long} \keyword{int}}, -\tcode{\keyword{unsigned} \keyword{long} \keyword{long} \keyword{int}}, -\keyword{float}, -\keyword{double}, -\tcode{\keyword{long} \keyword{double}}, -\tcode{\keyword{const} char_type*}, -\tcode{basic_string_view}, or -\tcode{\keyword{const} \keyword{void}*}. - -\pnum -\remarks -A call to this function is a core constant expression only if -\begin{itemize} -\item -\tcode{id < num_args_} is \tcode{true} and -\item -the type of the corresponding format argument -(after conversion to \tcode{basic_format_arg}) is one of the types in \tcode{Ts...}. -\end{itemize} +\effects +Exchanges the target objects of \tcode{*this} and \tcode{other}. \end{itemdescr} -\indexlibrarymember{check_dynamic_spec_integral}{basic_format_parse_context}% +\indexlibrarymember{swap}{move_only_function}% \begin{itemdecl} -constexpr void check_dynamic_spec_integral(size_t id) noexcept; +friend void swap(move_only_function& f1, move_only_function& f2) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -check_dynamic_spec(id); -\end{codeblock} +Equivalent to \tcode{f1.swap(f2)}. \end{itemdescr} -\indexlibrarymember{check_dynamic_spec_string}{basic_format_parse_context}% +\indexlibrarymember{operator==}{move_only_function}% \begin{itemdecl} -constexpr void check_dynamic_spec_string(size_t id) noexcept; +friend bool operator==(const move_only_function& f, nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -check_dynamic_spec>(id); -\end{codeblock} +\returns +\tcode{true} if \tcode{f} has no target object, otherwise \tcode{false}. \end{itemdescr} -\rSec3[format.context]{Class template \tcode{basic_format_context}} +\rSec3[func.wrap.copy]{Copyable wrapper} + +\rSec4[func.wrap.copy.general]{General} + +\pnum +The header provides partial specializations of \tcode{copyable_function} +for each combination of the possible replacements +of the placeholders \cv{}, \placeholder{ref}, and \placeholder{noex} where +\begin{itemize} +\item +\cv{} is either const or empty, +\item +\placeholder{ref} is either \tcode{\&}, \tcode{\&\&}, or empty, and +\item +\placeholder{noex} is either \tcode{true} or \tcode{false}. +\end{itemize} + +\pnum +For each of the possible combinations of the placeholders mentioned above, +there is a placeholder \placeholder{inv-quals} defined as follows: +\begin{itemize} +\item +If \placeholder{ref} is empty, let \placeholder{inv-quals} be \cv{}\tcode{\&}, +\item +otherwise, let \placeholder{inv-quals} be \cv{} \placeholder{ref}. +\end{itemize} + +\rSec4[func.wrap.copy.class]{Class template \tcode{copyable_function}} -\indexlibraryglobal{basic_format_context}% -\indexlibrarymember{iterator}{basic_format_context}% -\indexlibrarymember{char_type}{basic_format_context}% -\indexlibrarymember{formatter_type}{basic_format_context}% +\indexlibraryglobal{copyable_function}% \begin{codeblock} namespace std { - template - class basic_format_context { - basic_format_args args_; // \expos - Out out_; // \expos - + template + class copyable_function { public: - using iterator = Out; - using char_type = charT; - template using formatter_type = formatter; + using result_type = R; + + // \ref{func.wrap.copy.ctor}, constructors, assignments, and destructors + copyable_function() noexcept; + copyable_function(nullptr_t) noexcept; + copyable_function(const copyable_function&); + copyable_function(copyable_function&&) noexcept; + template copyable_function(F&&); + template + explicit copyable_function(in_place_type_t, Args&&...); + template + explicit copyable_function(in_place_type_t, initializer_list, Args&&...); + + copyable_function& operator=(const copyable_function&); + copyable_function& operator=(copyable_function&&); + copyable_function& operator=(nullptr_t) noexcept; + template copyable_function& operator=(F&&); + + ~copyable_function(); + + // \ref{func.wrap.copy.inv}, invocation + explicit operator bool() const noexcept; + R operator()(ArgTypes...) @\cv{}@ @\placeholder{ref}@ noexcept(@\placeholder{noex}@); - basic_format_arg arg(size_t id) const noexcept; - std::locale locale(); + // \ref{func.wrap.copy.util}, utility + void swap(copyable_function&) noexcept; + friend void swap(copyable_function&, copyable_function&) noexcept; + friend bool operator==(const copyable_function&, nullptr_t) noexcept; - iterator out(); - void advance_to(iterator it); + private: + template + static constexpr bool @\exposid{is-callable-from}@ = @\seebelow@; // \expos }; } \end{codeblock} \pnum -An instance of \tcode{basic_format_context} holds formatting state -consisting of the formatting arguments and the output iterator. - -\pnum -\tcode{Out} shall model \tcode{\libconcept{output_iterator}}. - -\pnum -\indexlibraryglobal{format_context}% -\tcode{format_context} is an alias for -a specialization of \tcode{basic_format_context} -with an output iterator -that appends to \tcode{string}, -such as \tcode{back_insert_iterator}. -\indexlibraryglobal{wformat_context}% -Similarly, \tcode{wformat_context} is an alias for -a specialization of \tcode{basic_format_context} -with an output iterator -that appends to \tcode{wstring}. +The \tcode{copyable_function} class template provides polymorphic wrappers +that generalize the notion of a callable object\iref{func.def}. +These wrappers can store, copy, move, and call arbitrary callable objects, +given a call signature. \pnum \recommended -For a given type \tcode{charT}, -implementations should provide -a single instantiation of \tcode{basic_format_context} -for appending to -\tcode{basic_string}, -\tcode{vector}, -or any other container with contiguous storage -by wrapping those in temporary objects with a uniform interface -(such as a \tcode{span}) and polymorphic reallocation. +Implementations should avoid the use of dynamically allocated memory +for a small contained value. +\begin{note} +Such small-object optimization can only be applied to a type \tcode{T} +for which \tcode{is_nothrow_move_constructible_v} is \tcode{true}. +\end{note} + +\rSec4[func.wrap.copy.ctor]{Constructors, assignments, and destructors} -\indexlibrarymember{arg}{basic_format_context}% +\indextext{copyable_function::is-callable-from@\tcode{copyable_function::\exposid{is-callable-from}}}% \begin{itemdecl} -basic_format_arg arg(size_t id) const noexcept; +template + static constexpr bool @\exposid{is-callable-from}@ = @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{args_.get(id)}. +If \placeholder{noex} is \tcode{true}, +\tcode{\exposid{is-callable-from}} is equal to: +\begin{codeblock} +is_nothrow_invocable_r_v && +is_nothrow_invocable_r_v +\end{codeblock} +Otherwise, \tcode{\exposid{is-callable-from}} is equal to: +\begin{codeblock} +is_invocable_r_v && +is_invocable_r_v +\end{codeblock} \end{itemdescr} -\indexlibrarymember{locale}{basic_format_context}% +\indexlibraryctor{copyable_function}% \begin{itemdecl} -std::locale locale(); +copyable_function() noexcept; +copyable_function(nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -The locale passed to the formatting function -if the latter takes one, -and \tcode{std::locale()} otherwise. +\ensures +\tcode{*this} has no target object. \end{itemdescr} -\indexlibrarymember{out}{basic_format_context}% +\indexlibraryctor{copyable_function}% \begin{itemdecl} -iterator out(); +copyable_function(const copyable_function& f); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return std::move(out_);} +\ensures +\tcode{*this} has no target object if \tcode{f} had no target object. +Otherwise, the target object of \tcode{*this} +is a copy of the target object of \tcode{f}. + +\pnum +\throws +Any exception thrown by the initialization of the target object. +May throw \tcode{bad_alloc}. \end{itemdescr} -\indexlibrarymember{advance_to}{basic_format_context}% +\indexlibraryctor{copyable_function}% \begin{itemdecl} -void advance_to(iterator it); +copyable_function(copyable_function&& f) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{out_ = std::move(it);} +\ensures +The target object of \tcode{*this} is +the target object \tcode{f} had before construction, and +\tcode{f} is in a valid state with an unspecified value. \end{itemdescr} -\indextext{left-pad}% -\begin{example} -\begin{codeblock} -struct S { int value; }; - -template<> struct std::formatter { - size_t width_arg_id = 0; - - // Parses a width argument id in the format \tcode{\{} \fmtgrammarterm{digit} \tcode{\}}. - constexpr auto parse(format_parse_context& ctx) { - auto iter = ctx.begin(); - auto get_char = [&]() { return iter != ctx.end() ? *iter : 0; }; - if (get_char() != '{') - return iter; - ++iter; - char c = get_char(); - if (!isdigit(c) || (++iter, get_char()) != '}') - throw format_error("invalid format"); - width_arg_id = c - '0'; - ctx.check_arg_id(width_arg_id); - return ++iter; - } - - // Formats an \tcode{S} with width given by the argument \tcode{width_arg_id}. - auto format(S s, format_context& ctx) const { - int width = ctx.arg(width_arg_id).visit([](auto value) -> int { - if constexpr (!is_integral_v) - throw format_error("width is not integral"); - else if (value < 0 || value > numeric_limits::max()) - throw format_error("invalid width"); - else - return value; - }); - return format_to(ctx.out(), "{0:x<{1}}", s.value, width); - } -}; - -std::string s = std::format("{0:{1}}", S{42}, 10); // value of \tcode{s} is \tcode{"xxxxxxxx42"} -\end{codeblock} -\end{example} - -\rSec2[format.range]{Formatting of ranges} - -\rSec3[format.range.fmtkind]{Variable template \tcode{format_kind}} - -\indexlibraryglobal{format_kind} +\indexlibraryctor{copyable_function}% \begin{itemdecl} -template - requires @\libconcept{same_as}@> - constexpr range_format format_kind = @\seebelow@; +template copyable_function(F&& f); \end{itemdecl} \begin{itemdescr} \pnum -A program that instantiates the primary template of \tcode{format_kind} -is ill-formed. +Let \tcode{VT} be \tcode{decay_t}. \pnum -For a type \tcode{R}, \tcode{format_kind} is defined as follows: +\constraints \begin{itemize} \item -If \tcode{\libconcept{same_as}>, R>} -is \tcode{true}, -\tcode{format_kind} is \tcode{range_format::disabled}. -\begin{note} -This prevents constraint recursion for ranges whose -reference type is the same range type. -For example, -\tcode{std::filesystem::path} is a range of \tcode{std::filesystem::path}. -\end{note} - +\tcode{remove_cvref_t} is not the same type as \tcode{copyable_function}, and +\item +\tcode{remove_cvref_t} is not a specialization of \tcode{in_place_type_t}, and \item -Otherwise, if the \grammarterm{qualified-id} \tcode{R::key_type} -is valid and denotes a type: +\tcode{\exposid{is-callable-from}} is \tcode{true}. +\end{itemize} + +\pnum +\mandates \begin{itemize} \item -If the \grammarterm{qualified-id} \tcode{R::mapped_type} -is valid and denotes a type, -let \tcode{U} be \tcode{remove_cvref_t>}. -If either \tcode{U} is a specialization of \tcode{pair} or -\tcode{U} is a specialization of \tcode{tuple} and -\tcode{tuple_size_v == 2}, -\tcode{format_kind} is \tcode{range_format::map}. +\tcode{is_constructible_v} is \tcode{true}, and \item -Otherwise, \tcode{format_kind} is \tcode{range_format::set}. +\tcode{is_copy_constructible_v} is \tcode{true}. \end{itemize} +\pnum +\expects +\tcode{VT} meets the \oldconcept{Destructible} and +\oldconcept{CopyConstructible} requirements. + +\pnum +\ensures +\tcode{*this} has no target object if any of the following hold: +\begin{itemize} +\item +\tcode{f} is a null function pointer value, or +\item +\tcode{f} is a null member pointer value, or \item -Otherwise, \tcode{format_kind} is \tcode{range_format::sequence}. +\tcode{remove_cvref_t} is a specialization of +the \tcode{copyable_function} class template, +and \tcode{f} has no target object. \end{itemize} +Otherwise, \tcode{*this} has a target object of type \tcode{VT} +direct-non-list-initialized with \tcode{std::forward(f)}. \pnum -\remarks -Pursuant to \ref{namespace.std}, users may specialize \tcode{format_kind} -for cv-unqualified program-defined types -that model \tcode{ranges::\libconcept{input_range}}. -Such specializations shall be usable in constant expressions\iref{expr.const} -and have type \tcode{const range_format}. +\throws +Any exception thrown by the initialization of the target object. +May throw \tcode{bad_alloc} unless \tcode{VT} is +a function pointer or a specialization of \tcode{reference_wrapper}. \end{itemdescr} -\rSec3[format.range.formatter]{Class template \tcode{range_formatter}} +\indexlibraryctor{copyable_function}% +\begin{itemdecl} +template + explicit copyable_function(in_place_type_t, Args&&... args); +\end{itemdecl} -\indexlibraryglobal{range_formatter}% -\begin{codeblock} -namespace std { - template - requires @\libconcept{same_as}@, T> && @\libconcept{formattable}@ - class range_formatter { - formatter @\exposid{underlying_}@; // \expos - basic_string_view @\exposid{separator_}@ = @\exposid{STATICALLY-WIDEN}@(", "); // \expos - basic_string_view @\exposid{opening-bracket_}@ = @\exposid{STATICALLY-WIDEN}@("["); // \expos - basic_string_view @\exposid{closing-bracket_}@ = @\exposid{STATICALLY-WIDEN}@("]"); // \expos +\begin{itemdescr} +\pnum +Let \tcode{VT} be \tcode{decay_t}. - public: - constexpr void set_separator(basic_string_view sep) noexcept; - constexpr void set_brackets(basic_string_view opening, - basic_string_view closing) noexcept; - constexpr formatter& underlying() noexcept { return @\exposid{underlying_}@; } - constexpr const formatter& underlying() const noexcept { return @\exposid{underlying_}@; } - - template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); - - template - requires @\libconcept{formattable}@, charT> && - @\libconcept{same_as}@>, T> - typename FormatContext::iterator - format(R&& r, FormatContext& ctx) const; - }; -} -\end{codeblock} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_constructible_v} is \tcode{true}, and +\item +\tcode{\exposid{is-callable-from}} is \tcode{true}. +\end{itemize} \pnum -The class template \tcode{range_formatter} is a utility -for implementing \tcode{formatter} specializations for range types. +\mandates +\begin{itemize} +\item +\tcode{VT} is the same type as \tcode{T}, and +\item +\tcode{is_copy_constructible_v} is \tcode{true}. +\end{itemize} \pnum -\tcode{range_formatter} interprets \fmtgrammarterm{format-spec} -as a \fmtgrammarterm{range-format-spec}. -The syntax of format specifications is as follows: +\expects +\tcode{VT} meets the \oldconcept{Destructible} and +\oldconcept{CopyConstructible} requirements. -\begin{ncbnf} -\fmtnontermdef{range-format-spec}\br - \opt{range-fill-and-align} \opt{width} \opt{\terminal{n}} \opt{range-type} \opt{range-underlying-spec} -\end{ncbnf} +\pnum +\ensures +\tcode{*this} has a target object of type \tcode{VT} +direct-non-list-initialized with \tcode{std::forward\brk{}(args)...}. -\begin{ncbnf} -\fmtnontermdef{range-fill-and-align}\br - \opt{range-fill} align -\end{ncbnf} +\pnum +\throws +Any exception thrown by the initialization of the target object. +May throw \tcode{bad_alloc} unless \tcode{VT} is +a pointer or a specialization of \tcode{reference_wrapper}. +\end{itemdescr} -\begin{ncbnf} -\fmtnontermdef{range-fill}\br - \textnormal{any character other than} \terminal{\{} \textnormal{or} \terminal{\}} \textnormal{or} \terminal{:} -\end{ncbnf} +\indexlibraryctor{copyable_function}% +\begin{itemdecl} +template + explicit copyable_function(in_place_type_t, initializer_list ilist, Args&&... args); +\end{itemdecl} -\begin{ncbnf} -\fmtnontermdef{range-type}\br - \terminal{m}\br - \terminal{s}\br - \terminal{?s} -\end{ncbnf} +\begin{itemdescr} +\pnum +Let \tcode{VT} be \tcode{decay_t}. -\begin{ncbnf} -\fmtnontermdef{range-underlying-spec}\br - \terminal{:} format-spec -\end{ncbnf} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_constructible_v\&, Args...>} is +\tcode{true}, and +\item +\tcode{\exposid{is-callable-from}} is \tcode{true}. +\end{itemize} \pnum -For \tcode{range_formatter}, -the \fmtgrammarterm{format-spec} -in a \fmtgrammarterm{range-underlying-spec}, if any, -is interpreted by \tcode{formatter}. +\mandates +\begin{itemize} +\item +\tcode{VT} is the same type as \tcode{T}, and +\item +\tcode{is_copy_constructible_v} is \tcode{true}. +\end{itemize} \pnum -The \fmtgrammarterm{range-fill-and-align} is interpreted -the same way as a \fmtgrammarterm{fill-and-align}\iref{format.string.std}. -The productions \fmtgrammarterm{align} and \fmtgrammarterm{width} -are described in \ref{format.string}. +\expects +\tcode{VT} meets the \oldconcept{Destructible} and +\oldconcept{CopyConstructible} requirements. \pnum -The \tcode{n} option causes the range to be formatted -without the opening and closing brackets. -\begin{note} -This is equivalent to invoking \tcode{set_brackets(\{\}, \{\})}. -\end{note} +\ensures +\tcode{*this} has a target object of type \tcode{VT} +direct-non-list-initialized with +\tcode{ilist, std::for\-ward(args)...}. \pnum -The \fmtgrammarterm{range-type} specifier changes the way a range is formatted, -with certain options only valid with certain argument types. -The meaning of the various type options -is as specified in \tref{formatter.range.type}. +\throws +Any exception thrown by the initialization of the target object. +May throw \tcode{bad_alloc} unless \tcode{VT} is +a pointer or a specialization of \tcode{reference_wrapper}. +\end{itemdescr} -\begin{concepttable}{Meaning of \fmtgrammarterm{range-type} options}{formatter.range.type} -{p{1in}p{1.4in}p{2.7in}} -\topline -\hdstyle{Option} & \hdstyle{Requirements} & \hdstyle{Meaning} \\ \capsep -% -\tcode{m} & -\tcode{T} shall be -either a specialization of \tcode{pair} or a specialization of \tcode{tuple} -such that \tcode{tuple_size_v} is \tcode{2}. & -Indicates that -the opening bracket should be \tcode{"\{"}, -the closing bracket should be \tcode{"\}"}, -the separator should be \tcode{", "}, and -each range element should be formatted as if -\tcode{m} were specified for its \fmtgrammarterm{tuple-type}. -\begin{tailnote} -If the \tcode{n} option is provided in addition to the \tcode{m} option, -both the opening and closing brackets are still empty. -\end{tailnote} -\\ \rowsep -% -\tcode{s} & -\tcode{T} shall be \tcode{charT}. & -Indicates that the range should be formatted as a \tcode{string}. -\\ \rowsep -% -\tcode{?s} & -\tcode{T} shall be \tcode{charT}. & -Indicates that the range should be formatted as -an escaped string\iref{format.string.escaped}. -\\ -\end{concepttable} +\indexlibrarymember{operator=}{copyable_function}% +\begin{itemdecl} +copyable_function& operator=(const copyable_function& f); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{copyable_function(f).swap(*this);} -If the \fmtgrammarterm{range-type} is \tcode{s} or \tcode{?s}, -then there shall be -no \tcode{n} option and no \fmtgrammarterm{range-underlying-spec}. +\pnum +\returns +\tcode{*this}. +\end{itemdescr} -\indexlibrarymember{set_separator}{range_formatter}% +\indexlibrarymember{operator=}{copyable_function}% \begin{itemdecl} -constexpr void set_separator(basic_string_view sep) noexcept; +copyable_function& operator=(copyable_function&& f); \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{\exposid{separator_} = sep;} +Equivalent to: \tcode{copyable_function(std::move(f)).swap(*this);} + +\pnum +\returns +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{set_brackets}{range_formatter}% +\indexlibrarymember{operator=}{copyable_function}% \begin{itemdecl} -constexpr void set_brackets(basic_string_view opening, - basic_string_view closing) noexcept; +copyable_function& operator=(nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -@\exposid{opening-bracket_}@ = opening; -@\exposid{closing-bracket_}@ = closing; -\end{codeblock} +Destroys the target object of \tcode{*this}, if any. + +\pnum +\returns +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{parse}{range_formatter}% +\indexlibrarymember{operator=}{copyable_function}% \begin{itemdecl} -template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); +template copyable_function& operator=(F&& f); \end{itemdecl} \begin{itemdescr} \pnum \effects -Parses the format specifiers as a \fmtgrammarterm{range-format-spec} and -stores the parsed specifiers in \tcode{*this}. -Calls \tcode{\exposid{underlying_}.parse(ctx)} to parse -\fmtgrammarterm{format-spec} in \fmtgrammarterm{range-format-spec} or, -if the latter is not present, an empty \fmtgrammarterm{format-spec}. -The values of -\exposid{opening-bracket_}, \exposid{closing-bracket_}, and \exposid{separator_} -are modified if and only if required by -the \fmtgrammarterm{range-type} or the \tcode{n} option, if present. -If: -\begin{itemize} -\item -the \fmtgrammarterm{range-type} is neither \tcode{s} nor \tcode{?s}, -\item -\tcode{\exposid{underlying_}.set_debug_format()} is a valid expression, and -\item -there is no \fmtgrammarterm{range-underlying-spec}, -\end{itemize} -then calls \tcode{\exposid{underlying_}.set_debug_format()}. +Equivalent to: \tcode{copyable_function(std::forward(f)).swap(*this);} \pnum \returns -An iterator past the end of the \fmtgrammarterm{range-format-spec}. +\tcode{*this}. \end{itemdescr} -\indexlibrarymember{format}{range_formatter}% +\indexlibrarydtor{copyable_function}% \begin{itemdecl} -template - requires @\libconcept{formattable}@, charT> && - @\libconcept{same_as}@>, T> - typename FormatContext::iterator - format(R&& r, FormatContext& ctx) const; +~copyable_function(); \end{itemdecl} \begin{itemdescr} \pnum \effects -Writes the following into \tcode{ctx.out()}, -adjusted according to the \fmtgrammarterm{range-format-spec}: +Destroys the target object of \tcode{*this}, if any. +\end{itemdescr} -\begin{itemize} -\item -If the \fmtgrammarterm{range-type} was \tcode{s}, -then as if by formatting \tcode{basic_string(from_range, r)}. -\item -Otherwise, if the \fmtgrammarterm{range-type} was \tcode{?s}, -then as if by formatting \tcode{basic_string(from_range, r)} -as an escaped string\iref{format.string.escaped}. -\item -Otherwise, -\begin{itemize} -\item -\exposid{opening-bracket_}, -\item -for each element \tcode{e} of the range \tcode{r}: -\begin{itemize} -\item -the result of writing \tcode{e} via \exposid{underlying_} and -\item -\exposid{separator_}, unless \tcode{e} is the last element of \tcode{r}, and -\end{itemize} -\item -\exposid{closing-bracket_}. -\end{itemize} -\end{itemize} +\rSec4[func.wrap.copy.inv]{Invocation} + +\indexlibrarymember{operator bool}{copyable_function}% +\begin{itemdecl} +explicit operator bool() const noexcept; +\end{itemdecl} +\begin{itemdescr} \pnum \returns -An iterator past the end of the output range. +\tcode{true} if \tcode{*this} has a target object, otherwise \tcode{false}. \end{itemdescr} -\rSec3[format.range.fmtdef]{Class template \exposid{range-default-formatter}} - -\indexlibrary{range-default-formatter@\exposid{range-default-formatter}}% -\begin{codeblock} -namespace std { - template - struct @\exposidnc{range-default-formatter}@ { // \expos - private: - using @\exposidnc{maybe-const-r}@ = @\exposidnc{fmt-maybe-const}@; // \expos - range_formatter>, - charT> @\exposid{underlying_}@; // \expos - - public: - constexpr void set_separator(basic_string_view sep) noexcept; - constexpr void set_brackets(basic_string_view opening, - basic_string_view closing) noexcept; +\indexlibrarymember{operator()}{copyable_function}% +\begin{itemdecl} +R operator()(ArgTypes... args) @\cv{}@ @\placeholder{ref}@ noexcept(@\placeholder{noex}@); +\end{itemdecl} - template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); +\begin{itemdescr} +\pnum +\expects +\tcode{*this} has a target object. - template - typename FormatContext::iterator - format(@\exposid{maybe-const-r}@& elems, FormatContext& ctx) const; - }; -} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\placeholder{INVOKE}@(static_cast(f), std::forward(args)...); \end{codeblock} +where \tcode{f} is an lvalue designating the target object of \tcode{*this} and +\tcode{F} is the type of \tcode{f}. +\end{itemdescr} + +\rSec4[func.wrap.copy.util]{Utility} -\indexlibrarymemberexpos{set_separator}{range-default-formatter}% +\indexlibrarymember{swap}{copyable_function}% \begin{itemdecl} -constexpr void set_separator(basic_string_view sep) noexcept; +void swap(copyable_function& other) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{\exposid{underlying_}.set_separator(sep);} +Exchanges the target objects of \tcode{*this} and \tcode{other}. \end{itemdescr} -\indexlibrarymemberexpos{set_brackets}{range-default-formatter}% +\indexlibrarymember{swap}{copyable_function}% \begin{itemdecl} -constexpr void set_brackets(basic_string_view opening, - basic_string_view closing) noexcept; +friend void swap(copyable_function& f1, copyable_function& f2) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{\exposid{underlying_}.set_brackets(opening, closing);} +Equivalent to \tcode{f1.swap(f2)}. \end{itemdescr} -\indexlibrarymemberexpos{parse}{range-default-formatter}% +\indexlibrarymember{operator==}{copyable_function}% \begin{itemdecl} -template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); +friend bool operator==(const copyable_function& f, nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +\returns +\tcode{true} if \tcode{f} has no target object, otherwise \tcode{false}. \end{itemdescr} -\indexlibrarymemberexpos{format}{range-default-formatter}% -\begin{itemdecl} -template - typename FormatContext::iterator - format(@\exposid{maybe-const-r}@& elems, FormatContext& ctx) const; -\end{itemdecl} +\rSec3[func.wrap.ref]{Non-owning wrapper} + +\rSec4[func.wrap.ref.general]{General} -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \exposid{underlying_}.format(elems, ctx);} -\end{itemdescr} +The header provides partial specializations of \tcode{function_ref} +for each combination of the possible replacements of +the placeholders \cv{} and \placeholder{noex} where: + +\begin{itemize} +\item \cv{} is either const or empty, and +\item \placeholder{noex} is either \tcode{true} or \tcode{false}. +\end{itemize} -\rSec3[format.range.fmtmap]{Specialization of \exposid{range-default-formatter} for maps} +\rSec4[func.wrap.ref.class]{Class template \tcode{function_ref}} -\indexlibrary{range-default-formatter@\exposid{range-default-formatter}}% +\indexlibraryglobal{function_ref}% \begin{codeblock} namespace std { - template - struct @\exposid{range-default-formatter}@ { - private: - using @\exposidnc{maybe-const-map}@ = @\exposidnc{fmt-maybe-const}@; // \expos - using @\exposidnc{element-type}@ = // \expos - remove_cvref_t>; - range_formatter<@\exposidnc{element-type}@, charT> @\exposid{underlying_}@; // \expos - + template + class function_ref { public: - constexpr @\exposid{range-default-formatter}@(); + // \ref{func.wrap.ref.ctor}, constructors and assignment operators + template function_ref(F*) noexcept; + template constexpr function_ref(F&&) noexcept; + template constexpr function_ref(nontype_t) noexcept; + template constexpr function_ref(nontype_t, U&&) noexcept; + template constexpr function_ref(nontype_t, @\cv{}@ T*) noexcept; + + constexpr function_ref(const function_ref&) noexcept = default; + constexpr function_ref& operator=(const function_ref&) noexcept = default; + template function_ref& operator=(T) = delete; + + // \ref{func.wrap.ref.inv}, invocation + R operator()(ArgTypes...) const noexcept(@\placeholder{noex}@); - template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); + private: + template + static constexpr bool @\exposidnc{is-invocable-using}@ = @\seebelownc@; // \expos - template - typename FormatContext::iterator - format(@\exposid{maybe-const-map}@& r, FormatContext& ctx) const; + R (*@\exposidnc{thunk-ptr}@)(@\exposidnc{BoundEntityType}@, Args&&...) noexcept(@\placeholdernc{noex}@); // \expos + @\exposidnc{BoundEntityType}@ @\exposidnc{bound-entity}@; // \expos }; + + // \ref{func.wrap.ref.deduct}, deduction guides + template + function_ref(F*) -> function_ref; + template + function_ref(nontype_t) -> function_ref<@\seebelow@>; + template + function_ref(nontype_t, T&&) -> function_ref<@\seebelow@>; } \end{codeblock} -\indexlibrarymisc{range-default-formatter@\exposid{range-default-formatter}}{constructor}% -\begin{itemdecl} -constexpr @\exposid{range-default-formatter}@(); -\end{itemdecl} +\pnum +An object of class +\tcode{function_ref} +stores a pointer to function \exposid{thunk-ptr} and +an object \exposid{bound-entity}. +\exposid{bound-entity} has +an unspecified trivially copyable type \exposid{BoundEntityType}, that +models \libconcept{copyable} and +is capable of storing a pointer to object value or a pointer to function value. +The type of \exposid{thunk-ptr} is +\tcode{R(*)(\exposidnc{BoundEntityType}, Args\&\&...) noexcept(\placeholder{noex})}. -\begin{itemdescr} \pnum -\mandates -Either: -\begin{itemize} -\item -\exposid{element-type} is a specialization of \tcode{pair}, or -\item -\exposid{element-type} is a specialization of \tcode{tuple} and -\tcode{tuple_size_v<\exposid{element-type}> == 2}. -\end{itemize} +Each specialization of \tcode{function_ref} is +a trivially copyable type\iref{term.trivially.copyable.type} +that models \libconcept{copyable}. \pnum -\effects -Equivalent to: -\begin{codeblock} -@\exposid{underlying_}@.set_brackets(@\exposid{STATICALLY-WIDEN}@("{"), @\exposid{STATICALLY-WIDEN}@("}")); -@\exposid{underlying_}@.underlying().set_brackets({}, {}); -@\exposid{underlying_}@.underlying().set_separator(@\exposid{STATICALLY-WIDEN}@(": ")); -\end{codeblock} -\end{itemdescr} +Within \ref{func.wrap.ref}, +\tcode{\placeholder{call-args}} is an argument pack with elements such that +\tcode{decltype((\placeholder{call-args}\linebreak{}))...} denote +\tcode{Args\&\&...} respectively. -\indexlibrarymemberexpos{parse}{range-default-formatter}% +\rSec4[func.wrap.ref.ctor]{Constructors and assignment operators} + +\indextext{function_ref::is-invocable-using@\tcode{function_ref::\exposid{is-invocable-using}}}% \begin{itemdecl} -template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); +template + static constexpr bool @\exposid{is-invocable-using}@ = @\seebelow@; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +If \placeholder{noex} is \tcode{true}, +\tcode{\exposid{is-invocable-using}} is equal to: +\begin{codeblock} +is_nothrow_invocable_r_v +\end{codeblock} +Otherwise, \tcode{\exposid{is-invocable-using}} is equal to: +\begin{codeblock} +is_invocable_r_v +\end{codeblock} \end{itemdescr} -\indexlibrarymemberexpos{format}{range-default-formatter}% +\indexlibraryctor{function_ref}% \begin{itemdecl} -template - typename FormatContext::iterator - format(@\exposid{maybe-const-map}@& r, FormatContext& ctx) const; +template function_ref(F* f) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \exposid{underlying_}.format(r, ctx);} -\end{itemdescr} - -\rSec3[format.range.fmtset]{Specialization of \exposid{range-default-formatter} for sets} - -\indexlibrary{range-default-formatter@\exposid{range-default-formatter}}% -\begin{codeblock} -namespace std { - template - struct @\exposid{range-default-formatter}@ { - private: - using @\exposidnc{maybe-const-set}@ = @\exposidnc{fmt-maybe-const}@; // \expos - range_formatter>, - charT> @\exposid{underlying_}@; // \expos - - public: - constexpr @\exposid{range-default-formatter}@(); - - template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); - - template - typename FormatContext::iterator - format(@\exposid{maybe-const-set}@& r, FormatContext& ctx) const; - }; -} -\end{codeblock} +\constraints +\begin{itemize} +\item \tcode{is_function_v} is \tcode{true}, and +\item \tcode{\exposid{is-invocable-using}} is \tcode{true}. +\end{itemize} -\indexlibrarymisc{range-default-formatter@\exposid{range-default-formatter}}{constructor}% -\begin{itemdecl} -constexpr @\exposid{range-default-formatter}@(); -\end{itemdecl} +\pnum +\expects +\tcode{f} is not a null pointer. -\begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -@\exposid{underlying_}@.set_brackets(@\exposid{STATICALLY-WIDEN}@("{"), @\exposid{STATICALLY-WIDEN}@("}")); -\end{codeblock} +Initializes +\exposid{bound-entity} with \tcode{f}, and +\exposid{thunk-ptr} with the address of a function \tcode{\placeholder{thunk}} +such that +\tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} +is expression-equivalent\iref{defns.expression.equivalent} to +\tcode{invoke_r(f, \placeholder{call-args}...)}. \end{itemdescr} -\indexlibrarymemberexpos{parse}{range-default-formatter}% +\indexlibraryctor{function_ref}% \begin{itemdecl} -template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); +template constexpr function_ref(F&& f) noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{T} be \tcode{remove_reference_t}. + +\pnum +\constraints +\begin{itemize} +\item \tcode{remove_cvref_t} is not the same type as \tcode{function_ref}, +\item \tcode{is_member_pointer_v} is \tcode{false}, and +\item \tcode{\exposid{is-invocable-using}<\cv{} T\&>} is \tcode{true}. +\end{itemize} + \pnum \effects -Equivalent to: \tcode{return \exposid{underlying_}.parse(ctx);} +Initializes +\exposid{bound-entity} with \tcode{addressof(f)}, and +\exposid{thunk-ptr} with the address of a function \tcode{\placeholder{thunk}} +such that +\tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} +is expression-equivalent\iref{defns.expression.equivalent} to +\tcode{invoke_r(static_cast<\cv{} T\&>(f), \placeholder{call-args}...)}. \end{itemdescr} -\indexlibrarymemberexpos{format}{range-default-formatter}% +\indexlibraryctor{function_ref}% \begin{itemdecl} -template - typename FormatContext::iterator - format(@\exposid{maybe-const-set}@& r, FormatContext& ctx) const; +template constexpr function_ref(nontype_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return \exposid{underlying_}.format(r, ctx);} -\end{itemdescr} - -\rSec3[format.range.fmtstr]{Specialization of \exposid{range-default-formatter} for strings} - -\indexlibrary{range-default-formatter@\exposid{range-default-formatter}}% -\begin{codeblock} -namespace std { - template - requires (K == range_format::string || K == range_format::debug_string) - struct @\exposid{range-default-formatter}@ { - private: - formatter, charT> @\exposid{underlying_}@; // \expos - - public: - template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); +Let \tcode{F} be \tcode{decltype(f)}. - template - typename FormatContext::iterator - format(@\seebelow@& str, FormatContext& ctx) const; - }; -} -\end{codeblock} +\pnum +\constraints +\tcode{\exposid{is-invocable-using}} is \tcode{true}. \pnum \mandates -\tcode{\libconcept{same_as}>, charT>} -is \tcode{true}. - -\indexlibrarymemberexpos{parse}{range-default-formatter}% -\begin{itemdecl} -template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); -\end{itemdecl} +If \tcode{is_pointer_v || is_member_pointer_v} is \tcode{true}, +then \tcode{f != nullptr} is \tcode{true}. -\begin{itemdescr} \pnum \effects -Equivalent to: -\begin{codeblock} -auto i = @\exposid{underlying_}@.parse(ctx); -if constexpr (K == range_format::debug_string) { - @\exposid{underlying_}@.set_debug_format(); -} -return i; -\end{codeblock} +Initializes +\exposid{bound-entity} with a pointer to an unspecified object or +null pointer value, and +\exposid{thunk-ptr} with the address of a function \tcode{\placeholder{thunk}} +such that +\tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} +is expression-equivalent\iref{defns.expression.equivalent} to +\tcode{invoke_r(f, \placeholder{call-args}...)}. \end{itemdescr} -\indexlibrarymemberexpos{format}{range-default-formatter}% +\indexlibraryctor{function_ref}% \begin{itemdecl} -template - typename FormatContext::iterator - format(@\seebelow@& r, FormatContext& ctx) const; +template + constexpr function_ref(nontype_t, U&& obj) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -The type of \tcode{r} is \tcode{const R\&} -if \tcode{ranges::\libconcept{input_range}} is \tcode{true} and -\tcode{R\&} otherwise. +Let \tcode{T} be \tcode{remove_reference_t} and +\tcode{F} be \tcode{decltype(f)}. \pnum -\effects -Let \tcode{\placeholder{s}} be a \tcode{basic_string} such that -\tcode{ranges::equal(\placeholder{s}, r)} is \tcode{true}. -Equivalent to: \tcode{return \exposid{underlying_}.format(\placeholder{s}, ctx);} -\end{itemdescr} - -\rSec2[format.arguments]{Arguments} - -\rSec3[format.arg]{Class template \tcode{basic_format_arg}} - -\indexlibraryglobal{basic_format_arg}% -\begin{codeblock} -namespace std { - template - class basic_format_arg { - public: - class handle; - - private: - using char_type = typename Context::char_type; // \expos - - variant, - const void*, handle> value; // \expos +\constraints +\begin{itemize} +\item \tcode{is_rvalue_reference_v} is \tcode{false}, and +\item \tcode{\exposid{is-invocable-using}} is \tcode{true}. +\end{itemize} - template explicit basic_format_arg(T& v) noexcept; // \expos +\pnum +\mandates +If \tcode{is_pointer_v || is_member_pointer_v} is \tcode{true}, +then \tcode{f != nullptr} is \tcode{true}. - public: - basic_format_arg() noexcept; +\pnum +\effects +Initializes +\exposid{bound-entity} with \tcode{addressof(obj)}, and +\exposid{thunk-ptr} with the address of a function \tcode{\placeholder{thunk}} +such that +\tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} +is expression-equivalent\iref{defns.expression.equivalent} to +\tcode{invoke_r(f, static_cast<\cv{} T\&>(obj), \placeholder{call-args}...)}. +\end{itemdescr} - explicit operator bool() const noexcept; +\indexlibraryctor{function_ref}% +\begin{itemdecl} +template + constexpr function_ref(nontype_t, @\cv{}@ T* obj) noexcept; +\end{itemdecl} - template - decltype(auto) visit(this basic_format_arg arg, Visitor&& vis); - template - R visit(this basic_format_arg arg, Visitor&& vis); - }; -} -\end{codeblock} +\begin{itemdescr} +\pnum +Let \tcode{F} be \tcode{decltype(f)}. \pnum -An instance of \tcode{basic_format_arg} provides access to -a formatting argument for user-defined formatters. +\constraints +\tcode{\exposid{is-invocable-using}} is \tcode{true}. \pnum -The behavior of a program that adds specializations of -\tcode{basic_format_arg} is undefined. +\mandates +If \tcode{is_pointer_v || is_member_pointer_v} is \tcode{true}, +then \tcode{f != nullptr} is \tcode{true}. -\indexlibrary{\idxcode{basic_format_arg}!constructor|(}% -\begin{itemdecl} -basic_format_arg() noexcept; -\end{itemdecl} +\pnum +\expects +If \tcode{is_member_pointer_v} is \tcode{true}, +\tcode{obj} is not a null pointer. -\begin{itemdescr} \pnum -\ensures -\tcode{!(*this)}. +\effects +Initializes +\exposid{bound-entity} with \tcode{obj}, and +\exposid{thunk-ptr} with the address of a function \tcode{\placeholder{thunk}} +such that +\tcode{\placeholder{thunk}(\exposid{bound-entity}, \placeholder{call-args}...)} +is expression-equivalent\iref{defns.expression.equivalent} to +\tcode{invoke_r(f, obj, \placeholder{call-args}...)}. \end{itemdescr} +\indexlibrarymember{operator=}{function_ref}% \begin{itemdecl} -template explicit basic_format_arg(T& v) noexcept; +template function_ref& operator=(T) = delete; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{T} satisfies \tcode{\exposconcept{formattable-with}}. - -\pnum -\expects -If \tcode{decay_t} is \tcode{char_type*} or \tcode{const char_type*}, -\tcode{static_cast(v)} points to a NTCTS\iref{defns.ntcts}. - -\pnum -\effects -Let \tcode{TD} be \tcode{remove_const_t}. \begin{itemize} -\item -If \tcode{TD} is \tcode{bool} or \tcode{char_type}, -initializes \tcode{value} with \tcode{v}; -\item -otherwise, if \tcode{TD} is \tcode{char} and \tcode{char_type} is -\keyword{wchar_t}, initializes \tcode{value} with -\tcode{static_cast(static_cast(v))}; -\item -otherwise, if \tcode{TD} is a signed integer type\iref{basic.fundamental} -and \tcode{sizeof(TD) <= sizeof(int)}, -initializes \tcode{value} with \tcode{static_cast(v)}; -\item -otherwise, if \tcode{TD} is an unsigned integer type and -\tcode{sizeof(TD) <= sizeof(unsigned int)}, initializes -\tcode{value} with \tcode{static_cast(v)}; -\item -otherwise, if \tcode{TD} is a signed integer type and -\tcode{sizeof(TD) <= sizeof(long long int)}, initializes -\tcode{value} with \tcode{static_cast(v)}; -\item -otherwise, if \tcode{TD} is an unsigned integer type and -\tcode{sizeof(TD) <= sizeof(unsigned long long int)}, initializes -\tcode{value} with -\tcode{static_cast(v)}; -\item -otherwise, if \tcode{TD} is a standard floating-point type, -initializes \tcode{value} with \tcode{v}; -\item -otherwise, if \tcode{TD} is -a specialization of \tcode{basic_string_view} or \tcode{basic_string} and -\tcode{TD::value_type} is \tcode{char_type}, -initializes \tcode{value} with -\tcode{basic_string_view(v.data(), v.size())}; -\item -otherwise, if \tcode{decay_t} is -\tcode{char_type*} or \tcode{const char_type*}, -initializes \tcode{value} with \tcode{static_cast(v)}; -\item -otherwise, if \tcode{is_void_v>} is \tcode{true} or -\tcode{is_null_pointer_v} is \tcode{true}, -initializes \tcode{value} with \tcode{static_cast(v)}; -\item -otherwise, initializes \tcode{value} with \tcode{handle(v)}. +\item \tcode{T} is not the same type as \tcode{function_ref}, +\item \tcode{is_pointer_v} is \tcode{false}, and +\item \tcode{T} is not a specialization of \tcode{nontype_t}. \end{itemize} -\begin{note} -Constructing \tcode{basic_format_arg} from a pointer to a member is ill-formed -unless the user provides an enabled specialization of \tcode{formatter} -for that pointer to member type. -\end{note} \end{itemdescr} -\indexlibrary{\idxcode{basic_format_arg}!constructor|)}% +\rSec4[func.wrap.ref.inv]{Invocation} -\indexlibrarymember{operator bool}{basic_format_arg}% +\indexlibrarymember{operator()}{function_ref}% \begin{itemdecl} -explicit operator bool() const noexcept; +R operator()(ArgTypes... args) const noexcept(@\placeholder{noex}@); \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{!holds_alternative(value)}. +\effects +Equivalent to: +\tcode{return \exposid{thunk-ptr}(\exposid{bound-entity}, std::forward(args)...);} \end{itemdescr} -\indexlibrarymember{visit}{basic_format_arg}% +\rSec4[func.wrap.ref.deduct]{Deduction guides} + \begin{itemdecl} -template - decltype(auto) visit(this basic_format_arg arg, Visitor&& vis); +template + function_ref(F*) -> function_ref; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return arg.value.visit(std::forward(vis));} +\constraints +\tcode{is_function_v} is \tcode{true}. \end{itemdescr} -\indexlibrarymember{visit}{basic_format_arg}% \begin{itemdecl} -template - R visit(this basic_format_arg arg, Visitor&& vis); +template + function_ref(nontype_t) -> function_ref<@\seebelow@>; \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{return arg.value.visit(std::forward(vis));} -\end{itemdescr} +Let \tcode{F} be \tcode{remove_pointer_t}. \pnum -The class \tcode{handle} allows formatting an object of a user-defined type. - -\indexlibraryglobal{basic_format_arg::handle}% -\indexlibrarymember{handle}{basic_format_arg}% -\begin{codeblock} -namespace std { - template - class basic_format_arg::handle { - const void* ptr_; // \expos - void (*format_)(basic_format_parse_context&, - Context&, const void*); // \expos - - template explicit handle(T& val) noexcept; // \expos - - friend class basic_format_arg; // \expos +\constraints +\tcode{is_function_v} is \tcode{true}. - public: - void format(basic_format_parse_context&, Context& ctx) const; - }; -} -\end{codeblock} +\pnum +\remarks +The deduced type is \tcode{function_ref}. +\end{itemdescr} -\indexlibraryctor{basic_format_arg::handle}% \begin{itemdecl} -template explicit handle(T& val) noexcept; +template + function_ref(nontype_t, T&&) -> function_ref<@\seebelow@>; \end{itemdecl} \begin{itemdescr} \pnum -Let +Let \tcode{F} be \tcode{decltype(f)}. + +\pnum +\constraints +%FIXME: R and E should be defined outside of these constraints. +%FIXME: Define R and E via "let" in paragraph above, then use them here and below. \begin{itemize} \item -\tcode{TD} be \tcode{remove_const_t}, +\tcode{F} is of the form +\tcode{R(G::*)(A...) \cv{} \opt{\&} noexcept(E)} for a type \tcode{G}, or +\item +\tcode{F} is of the form +\tcode{M G::*} for a type \tcode{G} and an object type \tcode{M}, +in which case +let \tcode{R} be \tcode{invoke_result_t}, +\tcode{A...} be an empty pack, and +\tcode{E} be \tcode{false}, or \item -\tcode{TQ} be \tcode{const TD} if -\tcode{const TD} satisfies \tcode{\exposconcept{formattable-with}} -and \tcode{TD} otherwise. +\tcode{F} is of the form +\tcode{R(*)(G, A...) noexcept(E)} for a type \tcode{G}. \end{itemize} \pnum -\mandates -\tcode{TQ} satisfies \tcode{\exposconcept{formattable-with}}. +\remarks +The deduced type is \tcode{function_ref}. +\end{itemdescr} +\indextext{function object!wrapper|)} + +\rSec2[func.search]{Searchers} + +\rSec3[func.search.general]{General} \pnum -\effects -Initializes -\tcode{ptr_} with \tcode{addressof(val)} and -\tcode{format_} with -\begin{codeblock} -[](basic_format_parse_context& parse_ctx, - Context& format_ctx, const void* ptr) { - typename Context::template formatter_type f; - parse_ctx.advance_to(f.parse(parse_ctx)); - format_ctx.advance_to(f.format(*const_cast(static_cast(ptr)), - format_ctx)); -} -\end{codeblock} -\end{itemdescr} +Subclause \ref{func.search} provides function object types\iref{function.objects} for +operations that search for a sequence \range{pat\textunderscore\nobreak first}{pat_last} in another +sequence \range{first}{last} that is provided to the object's function call +operator. The first sequence (the pattern to be searched for) is provided to +the object's constructor, and the second (the sequence to be searched) is +provided to the function call operator. -\indexlibrarymember{format}{basic_format_arg::handle}% -\begin{itemdecl} -void format(basic_format_parse_context& parse_ctx, Context& format_ctx) const; -\end{itemdecl} +\pnum +Each specialization of a class template specified in \ref{func.search} +shall meet the \oldconcept{CopyConst\-ruct\-ible} and \oldconcept{CopyAssignable} requirements. +Template parameters named +\begin{itemize} +\item \tcode{ForwardIterator}, +\item \tcode{ForwardIterator1}, +\item \tcode{ForwardIterator2}, +\item \tcode{RandomAccessIterator}, +\item \tcode{RandomAccessIterator1}, +\item \tcode{RandomAccessIterator2}, and +\item \tcode{BinaryPredicate} +\end{itemize} +of templates specified in +\ref{func.search} shall meet the same requirements and semantics as +specified in \ref{algorithms.general}. +Template parameters named \tcode{Hash} shall meet the \oldconcept{Hash} +requirements (\tref{cpp17.hash}). -\begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{format_(parse_ctx, format_ctx, ptr_);} -\end{itemdescr} +The Boyer-Moore searcher implements the Boyer-Moore search algorithm. +The Boyer-Moore-Horspool searcher implements the Boyer-Moore-Horspool search algorithm. +In general, the Boyer-Moore searcher will use more memory and give better runtime performance than Boyer-Moore-Horspool. -\rSec3[format.arg.store]{Class template \exposid{format-arg-store}} +\rSec3[func.search.default]{Class template \tcode{default_searcher}} +\indexlibraryglobal{default_searcher}% \begin{codeblock} namespace std { - template - class @\exposidnc{format-arg-store}@ { // \expos - array, sizeof...(Args)> @\exposidnc{args}@; // \expos + template> + class default_searcher { + public: + constexpr default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last, + BinaryPredicate pred = BinaryPredicate()); + + template + constexpr pair + operator()(ForwardIterator2 first, ForwardIterator2 last) const; + + private: + ForwardIterator1 pat_first_; // \expos + ForwardIterator1 pat_last_; // \expos + BinaryPredicate pred_; // \expos }; } \end{codeblock} -\pnum -An instance of \exposid{format-arg-store} stores formatting arguments. - -\indexlibraryglobal{make_format_args}% +\indexlibraryctor{default_searcher}% \begin{itemdecl} -template - @\exposid{format-arg-store}@ make_format_args(Args&... fmt_args); +constexpr default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last, + BinaryPredicate pred = BinaryPredicate()); \end{itemdecl} \begin{itemdescr} \pnum -\expects -The type -\tcode{typename Context::template formatter_type>}\linebreak{} -meets the \newoldconcept{BasicFormatter} requirements\iref{formatter.requirements} -for each $\tcode{T}_i$ in \tcode{Args}. +\effects +% FIXME: The mbox prevents TeX from adding a bizarre hyphen after pat_last_. +Constructs a \tcode{default_searcher} object, initializing \tcode{pat_first_} +with \tcode{pat_first}, \mbox{\tcode{pat_last_}} with \tcode{pat_last}, and +\tcode{pred_} with \tcode{pred}. \pnum -\returns -An object of type \tcode{\exposid{format-arg-store}} -whose \exposid{args} data member is initialized with -\tcode{\{basic_format_arg(fmt_args)...\}}. +\throws +Any exception thrown by the copy constructor of \tcode{BinaryPredicate} or +\tcode{ForwardIterator1}. \end{itemdescr} -\indexlibraryglobal{make_wformat_args}% +\indexlibrarymember{operator()}{default_searcher}% \begin{itemdecl} -template - @\exposid{format-arg-store}@ make_wformat_args(Args&... args); +template + constexpr pair + operator()(ForwardIterator2 first, ForwardIterator2 last) const; \end{itemdecl} \begin{itemdescr} \pnum \effects -Equivalent to: -\tcode{return make_format_args(args...);} +Returns a pair of iterators \tcode{i} and \tcode{j} such that +\begin{itemize} +\item \tcode{i == search(first, last, pat_first_, pat_last_, pred_)}, and +\item if \tcode{i == last}, then \tcode{j == last}, +otherwise \tcode{j == next(i, distance(pat_first_, pat_last_))}. +\end{itemize} \end{itemdescr} -\rSec3[format.args]{Class template \tcode{basic_format_args}} +\rSec3[func.search.bm]{Class template \tcode{boyer_moore_searcher}} +\indexlibraryglobal{boyer_moore_searcher}% \begin{codeblock} namespace std { - template - class basic_format_args { - size_t size_; // \expos - const basic_format_arg* data_; // \expos - + template::value_type>, + class BinaryPredicate = equal_to<>> + class boyer_moore_searcher { public: - basic_format_args() noexcept; + boyer_moore_searcher(RandomAccessIterator1 pat_first, + RandomAccessIterator1 pat_last, + Hash hf = Hash(), + BinaryPredicate pred = BinaryPredicate()); - template - basic_format_args(const @\exposid{format-arg-store}@& store) noexcept; + template + pair + operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; - basic_format_arg get(size_t i) const noexcept; + private: + RandomAccessIterator1 pat_first_; // \expos + RandomAccessIterator1 pat_last_; // \expos + Hash hash_; // \expos + BinaryPredicate pred_; // \expos }; - - template - basic_format_args(@\exposid{format-arg-store}@) -> basic_format_args; } \end{codeblock} -\pnum -An instance of \tcode{basic_format_args} provides access to formatting -arguments. -Implementations should -optimize the representation of \tcode{basic_format_args} -for a small number of formatting arguments. -\begin{note} -For example, by storing indices of type alternatives separately from values -and packing the former. -\end{note} - -\indexlibraryctor{basic_format_args}% +\indexlibraryctor{boyer_moore_searcher}% \begin{itemdecl} -basic_format_args() noexcept; +boyer_moore_searcher(RandomAccessIterator1 pat_first, + RandomAccessIterator1 pat_last, + Hash hf = Hash(), + BinaryPredicate pred = BinaryPredicate()); \end{itemdecl} \begin{itemdescr} +\pnum +\expects +The value type of \tcode{RandomAccessIterator1} meets +the \oldconcept{DefaultConstructible}, +\oldconcept{CopyConstructible}, and +\oldconcept{CopyAssignable} requirements. + +\pnum +Let \tcode{V} be \tcode{iterator_traits::val\-ue_type}. +For any two values \tcode{A} and \tcode{B} of type \tcode{V}, +if \tcode{pred(A, B) == true}, then \tcode{hf(A) == hf(B)} is \tcode{true}. + \pnum \effects -Initializes \tcode{size_} with \tcode{0}. +Initializes +\tcode{pat_first_} with \tcode{pat_first}, +\tcode{pat_last_} with \tcode{pat_last}, +\tcode{hash_} with \tcode{hf}, and +% FIXME: The mbox prevents TeX from adding a bizarre hyphen after pred_. +\mbox{\tcode{pred_}} with \tcode{pred}. + +\pnum +\throws +Any exception thrown by the copy constructor of \tcode{RandomAccessIterator1}, +or by the default constructor, copy constructor, or the copy assignment operator of the value type of \tcode{RandomAccess\-Iterator1}, +or the copy constructor or \tcode{operator()} of \tcode{BinaryPredicate} or \tcode{Hash}. +May throw \tcode{bad_alloc} if additional memory needed for internal data structures cannot be allocated. \end{itemdescr} -\indexlibraryctor{basic_format_args}% +\indexlibrarymember{operator()}{boyer_moore_searcher}% \begin{itemdecl} -template - basic_format_args(const @\exposid{format-arg-store}@& store) noexcept; +template + pair + operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\tcode{RandomAccessIterator1} and \tcode{RandomAccessIterator2} +have the same value type. + \pnum \effects -Initializes -\tcode{size_} with \tcode{sizeof...(Args)} and -\tcode{data_} with \tcode{store.args.data()}. -\end{itemdescr} +Finds a subsequence of equal values in a sequence. -\indexlibrarymember{get}{basic_format_args}% -\begin{itemdecl} -basic_format_arg get(size_t i) const noexcept; -\end{itemdecl} +\pnum +\returns +A pair of iterators \tcode{i} and \tcode{j} such that +\begin{itemize} +\item \tcode{i} is the first iterator +in the range \range{first}{last - (pat_last_ - pat_first_)} such that +for every non-negative integer \tcode{n} less than \tcode{pat_last_ - pat_first_} +the following condition holds: +\tcode{pred(*(i + n), *(pat_first_ + n)) != false}, and +\item \tcode{j == next(i, distance(pat_first_, pat_last_))}. +\end{itemize} +Returns \tcode{make_pair(first, first)} if \range{pat_first_}{pat_last_} is empty, +otherwise returns \tcode{make_pair(last, last)} if no such iterator is found. -\begin{itemdescr} \pnum -\returns -\tcode{i < size_ ?\ data_[i] :\ basic_format_arg()}. +\complexity +At most \tcode{(last - first) * (pat_last_ - pat_first_)} applications of the predicate. \end{itemdescr} -\rSec2[format.tuple]{Tuple formatter} - -\pnum -For each of \tcode{pair} and \tcode{tuple}, -the library provides the following formatter specialization -where \tcode{\placeholder{pair-or-tuple}} is the name of the template: +\rSec3[func.search.bmh]{Class template \tcode{boyer_moore_horspool_searcher}} -\indexlibraryglobal{formatter}% +\indexlibraryglobal{boyer_moore_horspool_searcher}% \begin{codeblock} namespace std { - template... Ts> - struct formatter<@\placeholder{pair-or-tuple}@, charT> { - private: - tuple, charT>...> @\exposid{underlying_}@; // \expos - basic_string_view @\exposid{separator_}@ = @\exposid{STATICALLY-WIDEN}@(", "); // \expos - basic_string_view @\exposid{opening-bracket_}@ = @\exposid{STATICALLY-WIDEN}@("("); // \expos - basic_string_view @\exposid{closing-bracket_}@ = @\exposid{STATICALLY-WIDEN}@(")"); // \expos - + template::value_type>, + class BinaryPredicate = equal_to<>> + class boyer_moore_horspool_searcher { public: - constexpr void set_separator(basic_string_view sep) noexcept; - constexpr void set_brackets(basic_string_view opening, - basic_string_view closing) noexcept; + boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, + RandomAccessIterator1 pat_last, + Hash hf = Hash(), + BinaryPredicate pred = BinaryPredicate()); - template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); + template + pair + operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; - template - typename FormatContext::iterator - format(@\seebelow@& elems, FormatContext& ctx) const; + private: + RandomAccessIterator1 pat_first_; // \expos + RandomAccessIterator1 pat_last_; // \expos + Hash hash_; // \expos + BinaryPredicate pred_; // \expos }; } \end{codeblock} -\pnum -The \tcode{parse} member functions of these formatters -interpret the format specification as -a \fmtgrammarterm{tuple-format-spec} according to the following syntax: - -\begin{ncbnf} -\fmtnontermdef{tuple-format-spec}\br - \opt{tuple-fill-and-align} \opt{width} \opt{tuple-type} -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{tuple-fill-and-align}\br - \opt{tuple-fill} align -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{tuple-fill}\br - \textnormal{any character other than} \terminal{\{} \textnormal{or} \terminal{\}} \textnormal{or} \terminal{:} -\end{ncbnf} - -\begin{ncbnf} -\fmtnontermdef{tuple-type}\br - \terminal{m}\br - \terminal{n} -\end{ncbnf} - -\pnum -The \fmtgrammarterm{tuple-fill-and-align} is interpreted the same way as -a \fmtgrammarterm{fill-and-align}\iref{format.string.std}. -The productions \fmtgrammarterm{align} and \fmtgrammarterm{width} -are described in \ref{format.string}. - -\pnum -The \fmtgrammarterm{tuple-type} specifier -changes the way a \tcode{pair} or \tcode{tuple} is formatted, -with certain options only valid with certain argument types. -The meaning of the various type options -is as specified in \tref{formatter.tuple.type}. - -\begin{concepttable}{Meaning of \fmtgrammarterm{tuple-type} options}{formatter.tuple.type} -{p{0.5in}p{1.4in}p{3.2in}} -\topline -\hdstyle{Option} & \hdstyle{Requirements} & \hdstyle{Meaning} \\ \capsep -% -\tcode{m} & -\tcode{sizeof...(Ts) == 2} & -Equivalent to: -\begin{codeblock} -set_separator(@\exposid{STATICALLY-WIDEN}@(": ")); -set_brackets({}, {}); -\end{codeblock}% -\\ \rowsep -% -\tcode{n} & -none & -Equivalent to: \tcode{set_brackets(\{\}, \{\});} -\\ \rowsep -% -none & -none & -No effects -\\ -\end{concepttable} - -\indexlibrarymember{set_separator}{formatter}% +\indexlibraryctor{boyer_moore_horspool_searcher}% \begin{itemdecl} -constexpr void set_separator(basic_string_view sep) noexcept; +boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, + RandomAccessIterator1 pat_last, + Hash hf = Hash(), + BinaryPredicate pred = BinaryPredicate()); \end{itemdecl} \begin{itemdescr} \pnum -\effects -Equivalent to: \tcode{\exposid{separator_} = sep;} -\end{itemdescr} - -\indexlibrarymember{set_brackets}{formatter}% -\begin{itemdecl} -constexpr void set_brackets(basic_string_view opening, - basic_string_view closing) noexcept; -\end{itemdecl} +\expects +The value type of \tcode{RandomAccessIterator1} meets the \oldconcept{DefaultConstructible}, +\oldconcept{Copy\-Constructible}, and \oldconcept{CopyAssignable} requirements. -\begin{itemdescr} \pnum -\effects -Equivalent to: -\begin{codeblock} -@\exposid{opening-bracket_}@ = opening; -@\exposid{closing-bracket_}@ = closing; -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{parse}{formatter}% -\begin{itemdecl} -template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); -\end{itemdecl} +Let \tcode{V} be \tcode{iterator_traits::val\-ue_type}. +For any two values \tcode{A} and \tcode{B} of type \tcode{V}, +if \tcode{pred(A, B) == true}, then \tcode{hf(A) == hf(B)} is \tcode{true}. -\begin{itemdescr} \pnum \effects -Parses the format specifiers as a \fmtgrammarterm{tuple-format-spec} and -stores the parsed specifiers in \tcode{*this}. -The values of -\exposid{opening-bracket_}, -\exposid{closing-bracket_}, and -\exposid{separator_} -are modified if and only if -required by the \fmtgrammarterm{tuple-type}, if present. -For each element \tcode{\placeholder{e}} in \exposid{underlying_}, -calls \tcode{\placeholder{e}.parse(ctx)} to parse -an empty \fmtgrammarterm{format-spec} and, -if \tcode{\placeholder{e}.set_debug_format()} is a valid expression, -calls \tcode{\placeholder{e}.set_debug_format()}. +Initializes +\tcode{pat_first_} with \tcode{pat_first}, +\tcode{pat_last_} with \tcode{pat_last}, +\tcode{hash_} with \tcode{hf}, and +% FIXME: The mbox prevents TeX from adding a bizarre hyphen after pred_. +\mbox{\tcode{pred_}} with \tcode{pred}. \pnum -\returns -An iterator past the end of the \fmtgrammarterm{tuple-format-spec}. +\throws +Any exception thrown by the copy constructor of \tcode{RandomAccessIterator1}, +or by the default constructor, copy constructor, or the copy assignment operator of the value type of \tcode{RandomAccess\-Iterator1}, +or the copy constructor or \tcode{operator()} of \tcode{BinaryPredicate} or \tcode{Hash}. +May throw \tcode{bad_alloc} if additional memory needed for internal data structures cannot be allocated. \end{itemdescr} -\indexlibrarymember{format}{formatter}% +\indexlibrarymember{operator()}{boyer_moore_horspool_searcher}% \begin{itemdecl} -template - typename FormatContext::iterator - format(@\seebelow@& elems, FormatContext& ctx) const; +template + pair + operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; \end{itemdecl} \begin{itemdescr} \pnum -The type of \tcode{elems} is: -\begin{itemize} -\item -If \tcode{(\libconcept{formattable} \&\& ...)} is \tcode{true}, -\tcode{const \placeholder{pair-or-tuple}\&}. -\item -Otherwise \tcode{\placeholder{pair-or-tuple}\&}. -\end{itemize} +\mandates +\tcode{RandomAccessIterator1} and \tcode{RandomAccessIterator2} +have the same value type. \pnum \effects -Writes the following into \tcode{ctx.out()}, -adjusted according to the \fmtgrammarterm{tuple-format-spec}: -\begin{itemize} -\item -\exposid{opening-bracket_}, -\item -for each index \tcode{I} in the \range{0}{sizeof...(Ts)}: +Finds a subsequence of equal values in a sequence. + +\pnum +\returns +A pair of iterators \tcode{i} and \tcode{j} such that \begin{itemize} -\item -if \tcode{I != 0}, \exposid{separator_}, -\item -the result of writing \tcode{get(elems)} -via \tcode{get(\exposid{underlying_})}, and -\end{itemize} -\item -\exposid{closing-bracket_}. +\item \tcode{i} is the first iterator in the range +\range{first}{last - (pat_last_ - pat_first_)} such that +for every non-negative integer \tcode{n} less than \tcode{pat_last_ - pat_first_} +the following condition holds: +\tcode{pred(*(i + n), *(pat_first_ + n)) != false}, and +\item \tcode{j == next(i, distance(pat_first_, pat_last_))}. \end{itemize} +Returns \tcode{make_pair(first, first)} if \range{pat_first_}{pat_last_} is empty, +otherwise returns \tcode{make_pair(last, last)} if no such iterator is found. \pnum -\returns -An iterator past the end of the output range. +\complexity +At most \tcode{(last - first) * (pat_last_ - pat_first_)} applications of the predicate. \end{itemdescr} -\rSec2[format.error]{Class \tcode{format_error}} - -\indexlibraryglobal{format_error}% -\begin{codeblock} -namespace std { - class format_error : public runtime_error { - public: - explicit format_error(const string& what_arg); - explicit format_error(const char* what_arg); - }; -} -\end{codeblock} +\rSec2[unord.hash]{Class template \tcode{hash}} \pnum -The class \tcode{format_error} defines the type of objects thrown as -exceptions to report errors from the formatting library. +\indexlibraryglobal{hash}% +\indextext{\idxcode{hash}!instantiation restrictions}% +The unordered associative containers defined in \ref{unord} use +specializations of the class template \tcode{hash}\iref{functional.syn} +as the default hash function. -\indexlibraryctor{format_error}% -\begin{itemdecl} -format_error(const string& what_arg); -\end{itemdecl} +\pnum +Each specialization of \tcode{hash} is either enabled or disabled, +as described below. +\begin{note} +Enabled specializations meet the \oldconcept{Hash} requirements, and +disabled specializations do not. +\end{note} +Each header that declares the template \tcode{hash} +provides enabled specializations of \tcode{hash} for \tcode{nullptr_t} and +all cv-unqualified arithmetic, enumeration, and pointer types. +For any type \tcode{Key} for which neither the library nor the user provides +an explicit or partial specialization of the class template \tcode{hash}, +\tcode{hash} is disabled. -\begin{itemdescr} \pnum -\ensures -\tcode{strcmp(what(), what_arg.c_str()) == 0}. +If the library provides an explicit or partial specialization of \tcode{hash}, +that specialization is enabled except as noted otherwise, +and its member functions are \keyword{noexcept} except as noted otherwise. -\indexlibraryctor{format_error}% -\end{itemdescr} -\begin{itemdecl} -format_error(const char* what_arg); -\end{itemdecl} +\pnum +If \tcode{H} is a disabled specialization of \tcode{hash}, +these values are \tcode{false}: +\tcode{is_default_constructible_v}, +\tcode{is_copy_constructible_v}, +\tcode{is_move_constructible_v}, +\tcode{is_copy_assignable_v}, and +\tcode{is_move_assignable_v}. +Disabled specializations of \tcode{hash} +are not function object types\iref{function.objects}. +\begin{note} +This means that the specialization of \tcode{hash} exists, but +any attempts to use it as a \oldconcept{Hash} will be ill-formed. +\end{note} -\begin{itemdescr} \pnum -\ensures -\tcode{strcmp(what(), what_arg) == 0}. -\end{itemdescr} +An enabled specialization \tcode{hash} will: +\begin{itemize} +\item meet the \oldconcept{Hash} requirements (\tref{cpp17.hash}), +with \tcode{Key} as the function +call argument type, the \oldconcept{Default\-Constructible} requirements (\tref{cpp17.defaultconstructible}), +the \oldconcept{CopyAssignable} requirements (\tref{cpp17.copyassignable}), +the \oldconcept{Swappable} requirements\iref{swappable.requirements}, +\item meet the requirement that if \tcode{k1 == k2} is \tcode{true}, \tcode{h(k1) == h(k2)} is +also \tcode{true}, where \tcode{h} is an object of type \tcode{hash} and \tcode{k1} and \tcode{k2} +are objects of type \tcode{Key}; +\item meet the requirement that the expression \tcode{h(k)}, where \tcode{h} +is an object of type \tcode{hash} and \tcode{k} is an object of type +\tcode{Key}, shall not throw an exception unless \tcode{hash} is a +program-defined specialization. +\end{itemize} \rSec1[bit]{Bit manipulation} @@ -18810,9 +15659,9 @@ // \ref{bit.rotate}, rotating template - [[nodiscard]] constexpr T rotl(T x, int s) noexcept; + constexpr T rotl(T x, int s) noexcept; template - [[nodiscard]] constexpr T rotr(T x, int s) noexcept; + constexpr T rotr(T x, int s) noexcept; // \ref{bit.count}, counting template @@ -18852,6 +15701,22 @@ \item \tcode{is_trivially_copyable_v} is \tcode{true}. \end{itemize} +\pnum +\mandates +Neither \tcode{To} nor \tcode{From} are consteval-only types\iref{expr.const}. + +\pnum +\constantwhen +\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} + \pnum \returns An object of type \tcode{To}. @@ -18865,26 +15730,27 @@ 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 +corresponds to a bit +for which the smallest enclosing object 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: +A bit in the value representation of the result is erroneous +if it corresponds to a bit +for which the smallest enclosing object has an erroneous value. +For each bit $b$ in the value representation of the result +that is indeterminate or erroneous, +let $u$ be the smallest object containing that bit enclosing $b$: \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. +\item +If $u$ is of unsigned ordinary character type or \tcode{std::byte} type, +$u$ has an indeterminate value +if any of the bits in its value representation are indeterminate, or +otherwise has an erroneous value. +\item +Otherwise, if $b$ is indeterminate, the behavior is undefined. +\item +Otherwise, the behavior is erroneous, and the result is as specified above. \end{itemize} +The result does not otherwise contain any indeterminate or erroneous values. \end{itemdescr} \rSec2[bit.byteswap]{\tcode{byteswap}} @@ -19014,7 +15880,7 @@ \begin{itemdecl} template - [[nodiscard]] constexpr T rotl(T x, int s) noexcept; + constexpr T rotl(T x, int s) noexcept; \end{itemdecl} \indexlibraryglobal{rotl}% @@ -19035,7 +15901,7 @@ \begin{itemdecl} template - [[nodiscard]] constexpr T rotr(T x, int s) noexcept; + constexpr T rotr(T x, int s) noexcept; \end{itemdecl} \indexlibraryglobal{rotr}% @@ -19192,86 +16058,133 @@ to either \tcode{endian::big} or \tcode{endian::little}. \end{itemdescr} -\rSec1[debugging]{Debugging} - -\rSec2[debugging.general]{General} - -\pnum -Subclause \ref{debugging} describes functionality to introspect and -interact with the execution of the program. - -\begin{note} -The facilities provided by the debugging functionality interact with a program -that could be tracing the execution of a \Cpp{} program, such as a debugger. -\end{note} +\rSec1[stdbit.h.syn]{Header \tcode{} synopsis} -\rSec2[debugging.syn]{Header \tcode{} synopsis} - -\indexheader{debugging}% +\indexheader{stdbit.h}% \begin{codeblock} // all freestanding -namespace std { - // \ref{debugging.utility}, utility - void breakpoint() noexcept; - void breakpoint_if_debugging() noexcept; - bool is_debugger_present() noexcept; -} -\end{codeblock} - -\rSec2[debugging.utility]{Utility} - -\indexlibraryglobal{breakpoint}% -\begin{itemdecl} -void breakpoint() noexcept; -\end{itemdecl} - -\begin{itemdescr} - -\pnum -The semantics of this function are \impldef{semantics of \tcode{breakpoint}}. - -\begin{note} -When invoked, the execution of the program temporarily halts and execution is -handed to the debugger until such a time as: The program is terminated by the -debugger, or the debugger resumes execution of the program as if the function -was not invoked. -\end{note} - -\end{itemdescr} - -\indexlibraryglobal{breakpoint_if_debugging}% -\begin{itemdecl} -void breakpoint_if_debugging() noexcept; -\end{itemdecl} -\begin{itemdescr} +#define @\libmacro{__STDC_VERSION_STDBIT_H__}@ 202311L + +#define @\libmacro{__STDC_ENDIAN_BIG__}@ @\seebelow@ +#define @\libmacro{__STDC_ENDIAN_LITTLE__}@ @\seebelow@ +#define @\libmacro{__STDC_ENDIAN_NATIVE__}@ @\seebelow@ + +unsigned int @\libglobal{stdc_leading_zeros_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_leading_zeros_us}@(unsigned short value); +unsigned int @\libglobal{stdc_leading_zeros_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_leading_zeros_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_leading_zeros_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_leading_zeros}@(T value); + +unsigned int @\libglobal{stdc_leading_ones_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_leading_ones_us}@(unsigned short value); +unsigned int @\libglobal{stdc_leading_ones_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_leading_ones_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_leading_ones_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_leading_ones}@(T value); + +unsigned int @\libglobal{stdc_trailing_zeros_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_trailing_zeros_us}@(unsigned short value); +unsigned int @\libglobal{stdc_trailing_zeros_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_trailing_zeros_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_trailing_zeros_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_trailing_zeros}@(T value); + +unsigned int @\libglobal{stdc_trailing_ones_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_trailing_ones_us}@(unsigned short value); +unsigned int @\libglobal{stdc_trailing_ones_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_trailing_ones_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_trailing_ones_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_trailing_ones}@(T value); + +unsigned int @\libglobal{stdc_first_leading_zero_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_first_leading_zero_us}@(unsigned short value); +unsigned int @\libglobal{stdc_first_leading_zero_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_first_leading_zero_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_first_leading_zero_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_first_leading_zero}@(T value); + +unsigned int @\libglobal{stdc_first_leading_one_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_first_leading_one_us}@(unsigned short value); +unsigned int @\libglobal{stdc_first_leading_one_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_first_leading_one_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_first_leading_one_ull}@(unsigned long long int value); +template @\seebelow@ stdc_first_leading_one(T value); + +unsigned int @\libglobal{stdc_first_trailing_zero_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_first_trailing_zero_us}@(unsigned short value); +unsigned int @\libglobal{stdc_first_trailing_zero_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_first_trailing_zero_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_first_trailing_zero_ull}@(unsigned long long int value); +template @\seebelow@ stdc_first_trailing_zero(T value); + +unsigned int @\libglobal{stdc_first_trailing_one_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_first_trailing_one_us}@(unsigned short value); +unsigned int @\libglobal{stdc_first_trailing_one_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_first_trailing_one_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_first_trailing_one_ull}@(unsigned long long int value); +template @\seebelow@ stdc_first_trailing_one(T value); + +unsigned int @\libglobal{stdc_count_zeros_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_count_zeros_us}@(unsigned short value); +unsigned int @\libglobal{stdc_count_zeros_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_count_zeros_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_count_zeros_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_count_zeros}@(T value); + +unsigned int @\libglobal{stdc_count_ones_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_count_ones_us}@(unsigned short value); +unsigned int @\libglobal{stdc_count_ones_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_count_ones_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_count_ones_ull}@(unsigned long long int value); +template @\seebelow@ stdc_count_ones(T value); + +bool @\libglobal{stdc_has_single_bit_uc}@(unsigned char value); +bool @\libglobal{stdc_has_single_bit_us}@(unsigned short value); +bool @\libglobal{stdc_has_single_bit_ui}@(unsigned int value); +bool @\libglobal{stdc_has_single_bit_ul}@(unsigned long int value); +bool @\libglobal{stdc_has_single_bit_ull}@(unsigned long long int value); +template bool @\libglobal{stdc_has_single_bit}@(T value); + +unsigned int @\libglobal{stdc_bit_width_uc}@(unsigned char value); +unsigned int @\libglobal{stdc_bit_width_us}@(unsigned short value); +unsigned int @\libglobal{stdc_bit_width_ui}@(unsigned int value); +unsigned int @\libglobal{stdc_bit_width_ul}@(unsigned long int value); +unsigned int @\libglobal{stdc_bit_width_ull}@(unsigned long long int value); +template @\seebelow@ @\libglobal{stdc_bit_width}@(T value); + +unsigned char @\libglobal{stdc_bit_floor_uc}@(unsigned char value); +unsigned short @\libglobal{stdc_bit_floor_us}@(unsigned short value); +unsigned int @\libglobal{stdc_bit_floor_ui}@(unsigned int value); +unsigned long int @\libglobal{stdc_bit_floor_ul}@(unsigned long int value); +unsigned long long int @\libglobal{stdc_bit_floor_ull}@(unsigned long long int value); +template T @\libglobal{stdc_bit_floor}@(T value); + +unsigned char @\libglobal{stdc_bit_ceil_uc}@(unsigned char value); +unsigned short @\libglobal{stdc_bit_ceil_us}@(unsigned short value); +unsigned int @\libglobal{stdc_bit_ceil_ui}@(unsigned int value); +unsigned long int @\libglobal{stdc_bit_ceil_ul}@(unsigned long int value); +unsigned long long int @\libglobal{stdc_bit_ceil_ull}@(unsigned long long int value); +template T @\libglobal{stdc_bit_ceil}@(T value); +\end{codeblock} + +\pnum +For a function template whose return type is not specified above, +the return type is +an \impldef{return types for \tcode{} functions} unsigned integer type +large enough to represent all possible result values. +Each function template has the same semantics +as the corresponding type-generic function with the same name +specified in \IsoCUndated{}:2024, 7.18. %% change to \xrefc{7.18} \pnum -\effects -Equivalent to: -\begin{codeblock} -if (is_debugger_present()) breakpoint(); -\end{codeblock} - -\end{itemdescr} - -\indexlibraryglobal{is_debugger_present}% -\begin{itemdecl} -bool is_debugger_present() noexcept; -\end{itemdecl} - -\begin{itemdescr} +\mandates +\tcode{T} is an unsigned integer type. \pnum -The semantics of this function are \impldef{semantics of \tcode{is_debugger_present}}. - -\begin{note} -When tracing the execution of a program with a debugger, an implementation -returns \tcode{true}. An implementation performs an immediate query, as needed, -to determine if the program is traced by a debugger. On Windows or equivalent -systems, this can be achieved by calling the \tcode{::IsDebuggerPresent()} Win32 -function. On POSIX, this can be achieved by checking for a tracer parent process, -with best effort determination that such a tracer parent process is a debugger. -\end{note} +Otherwise, +the contents and meaning of the header \libheader{stdbit.h} are the same as +the C standard library header \tcode{}. -\end{itemdescr} +\xref{\IsoCUndated{}:2024, 7.18} %% TODO: change to \xrefc{7.18} diff --git a/source/xrefdelta.tex b/source/xrefdelta.tex index 56d006ae82..e1c6be970c 100644 --- a/source/xrefdelta.tex +++ b/source/xrefdelta.tex @@ -19,9 +19,387 @@ % % \removedxref{removed.label} +\movedxref{res.on.expects}{structure.specifications} +\removedxref{variant.traits} + +% [facets.examples] was removed. +\removedxref{facets.examples} + +% P0588 replaced function prototype scope with function parameter scope. +\movedxref{basic.scope.proto}{basic.scope.param} + +\movedxref{expr.pseudo}{expr.prim.id.dtor} + +\movedxref{utility.from.chars}{charconv.from.chars} +\movedxref{utility.to.chars}{charconv.to.chars} + +% [fs.definitions] and its contents were integrated into the main text. +% Note that ISO C++17 does not contain the [fs.def.*] subclauses. +\movedxrefs{fs.definitions}{% + \secref{fs.class.path}, + \secref{fs.conform.os}, + \secref{fs.general}, + \secref{fs.path.fmt.cvt}, + \secref{fs.path.generic}, + \secref{fs.race.behavior}} + +% Single-item array subclauses were dissolved. +\movedxref{array.size}{array.members} +\movedxref{array.data}{array.members} +\movedxref{array.fill}{array.members} +\movedxref{array.swap}{array.members} + +% Contents of [util.smartptr] was integrated into the parent. +\removedxref{util.smartptr} + +% Avoid duplication with synopsis. +\movedxref{re.regex.const}{re.regex} + +% Single-item [insert.iterators] subclauses were dissolved. +\movedxref{back.insert.iter.cons}{back.insert.iter.ops} +\movedxref{back.insert.iter.op=}{back.insert.iter.ops} +\movedxref{back.insert.iter.op*}{back.insert.iter.ops} +\movedxref{back.insert.iter.op++}{back.insert.iter.ops} + +\movedxref{front.insert.iter.cons}{front.insert.iter.ops} +\movedxref{front.insert.iter.op=}{front.insert.iter.ops} +\movedxref{front.insert.iter.op*}{front.insert.iter.ops} +\movedxref{front.insert.iter.op++}{front.insert.iter.ops} + +\movedxref{insert.iter.cons}{insert.iter.ops} +\movedxref{insert.iter.op=}{insert.iter.ops} +\movedxref{insert.iter.op*}{insert.iter.ops} +\movedxref{insert.iter.op++}{insert.iter.ops} + +% Single-item [reverse.iterators] subclauses were dissolved. +\movedxref{reverse.iter.op=}{reverse.iter.cons} + +\movedxref{reverse.iter.op==}{reverse.iter.cmp} +\movedxref{reverse.iter.op<}{reverse.iter.cmp} +\movedxref{reverse.iter.op!=}{reverse.iter.cmp} +\movedxref{reverse.iter.op>}{reverse.iter.cmp} +\movedxref{reverse.iter.op>=}{reverse.iter.cmp} +\movedxref{reverse.iter.op<=}{reverse.iter.cmp} + +\movedxref{reverse.iter.op.star}{reverse.iter.elem} +\movedxref{reverse.iter.opref}{reverse.iter.elem} +\movedxref{reverse.iter.opindex}{reverse.iter.elem} + +\movedxref{reverse.iter.op+}{reverse.iter.nav} +\movedxref{reverse.iter.op-}{reverse.iter.nav} +\movedxref{reverse.iter.op++}{reverse.iter.nav} +\movedxref{reverse.iter.op+=}{reverse.iter.nav} +\movedxref{reverse.iter.op--}{reverse.iter.nav} +\movedxref{reverse.iter.op-=}{reverse.iter.nav} + +\movedxref{reverse.iter.opdiff}{reverse.iter.nonmember} +\movedxref{reverse.iter.opsum}{reverse.iter.nonmember} +\movedxref{reverse.iter.make}{reverse.iter.nonmember} + +\removedxref{reverse.iter.ops} + +% Single-item [move.iterators] subclauses were dissolved. +\movedxref{move.iter.op=}{move.iter.cons} +\movedxref{move.iter.op.const}{move.iter.cons} + +\movedxref{move.iter.op.star}{move.iter.elem} +\movedxref{move.iter.op.ref}{move.iter.elem} +\movedxref{move.iter.op.index}{move.iter.elem} + +\movedxref{move.iter.op.+}{move.iter.nav} +\movedxref{move.iter.op.-}{move.iter.nav} +\movedxref{move.iter.op.incr}{move.iter.nav} +\movedxref{move.iter.op.+=}{move.iter.nav} +\movedxref{move.iter.op.decr}{move.iter.nav} +\movedxref{move.iter.op.-=}{move.iter.nav} + +\removedxref{move.iter.ops} + +% Individual swap sections were removed. +\removedxref{deque.special} +\removedxref{forwardlist.spec} +\removedxref{list.special} +\removedxref{vector.special} +\removedxref{map.special} +\removedxref{multimap.special} +\removedxref{set.special} +\removedxref{multiset.special} +\removedxref{unord.map.swap} +\removedxref{unord.multimap.swap} +\removedxref{unord.set.swap} +\removedxref{unord.multiset.swap} +\movedxref{re.regex.nmswap}{re.regex.nonmemb} + +% Deprecated features were removed. +\removedxref{depr.except.spec} +\removedxref{depr.cpp.headers} +\removedxref{depr.uncaught} +\removedxref{depr.func.adaptor.binding} +\removedxref{depr.weak.result_type} +\removedxref{depr.func.adaptor.typedefs} +\removedxref{depr.negators} +\removedxref{depr.default.allocator} +\removedxref{depr.storage.iterator} +\removedxref{depr.temporary.buffer} +\removedxref{depr.util.smartptr.shared.obs} + +% Deprecated headers were removed for some headers +\removedxref{depr.ccomplex.syn} +\removedxref{depr.cstdalign.syn} +\removedxref{depr.cstdbool.syn} +\removedxref{depr.ctgmath.syn} + +\movedxref{class.copy}{class.mem} + +% Top-level clause merging caused some Annex A subclauses to vanish. +\movedxref{gram.decl}{gram.dcl} +\movedxref{gram.derived}{gram.class} +\movedxref{gram.special}{gram.class} + +% Top-level clause merging caused some Annex C subclauses to vanish, too. +\movedxref{diff.conv}{diff.expr} +\movedxref{diff.decl}{diff.dcl} +\movedxref{diff.special}{diff.class} +\movedxref{diff.cpp03.conv}{diff.cpp03.expr} +\movedxref{diff.cpp03.dcl.decl}{diff.cpp03.dcl.dcl} +\movedxref{diff.cpp03.special}{diff.cpp03.class} +\movedxref{diff.cpp11.dcl.decl}{diff.cpp11.dcl.dcl} +\movedxref{diff.cpp14.decl}{diff.cpp14.dcl.dcl} +\movedxref{diff.cpp14.special}{diff.cpp14.class} + +% P1148R0 consolidated some Clause 20 subclauses. +\movedxref{string.rfind}{string.find} +\movedxref{string.find.first.of}{string.find} +\movedxref{string.find.last.of}{string.find} +\movedxref{string.find.first.not.of}{string.find} +\movedxref{string.find.last.not.of}{string.find} +\movedxref{string.op+=}{string.op.append} +\movedxref{string.op+}{string.op.plus} +\movedxref{string.operator==}{string.cmp} +\movedxref{string.op!=}{string.cmp} +\movedxref{string.op<}{string.cmp} +\movedxref{string.op>}{string.cmp} +\movedxref{string.op<=}{string.cmp} +\movedxref{string.op>=}{string.cmp} + +\movedxref{istream::sentry}{istream.sentry} +\movedxref{ostream::sentry}{ostream.sentry} +\movedxref{ios::failure}{ios.failure} +\movedxref{ios::fmtflags}{ios.fmtflags} +\movedxref{ios::iostate}{ios.iostate} +\movedxref{ios::openmode}{ios.openmode} +\movedxref{ios::seekdir}{ios.seekdir} +\movedxref{ios::Init}{ios.init} + +\removedxref{thread.decaycopy} + +\movedxref{iterator.container}{iterator.range} + +% Remove underscores in stable labels. +\movedxref{alg.all_of}{alg.all.of} +\movedxref{alg.any_of}{alg.any.of} +\movedxref{alg.is_permutation}{alg.is.permutation} +\movedxref{alg.none_of}{alg.none.of} +\movedxref{any.bad_any_cast}{any.bad.any.cast} +\movedxref{char.traits.specializations.char16_t}{char.traits.specializations.char16.t} +\movedxref{char.traits.specializations.char32_t}{char.traits.specializations.char32.t} +\movedxref{comparisons.equal_to}{comparisons.equal.to} +\movedxref{comparisons.greater_equal}{comparisons.greater.equal} +\movedxref{comparisons.less_equal}{comparisons.less.equal} +\movedxref{comparisons.not_equal_to}{comparisons.not.equal.to} +\movedxref{condition_variable.syn}{condition.variable.syn} +\movedxref{depr.static_constexpr}{depr.static.constexpr} +\movedxref{forward_list.syn}{forward.list.syn} +\movedxref{fs.class.directory_entry}{fs.class.directory.entry} +\movedxref{fs.class.directory_iterator}{fs.class.directory.iterator} +\movedxref{fs.class.file_status}{fs.class.file.status} +\movedxref{fs.class.filesystem_error}{fs.class.filesystem.error} +\movedxref{fs.enum.file_type}{fs.enum.file.type} +\movedxref{fs.file_status.cons}{fs.file.status.cons} +\movedxref{fs.file_status.mods}{fs.file.status.mods} +\movedxref{fs.file_status.obs}{fs.file.status.obs} +\movedxref{fs.filesystem_error.members}{fs.filesystem.error.members} +\movedxref{fs.op.copy_file}{fs.op.copy.file} +\movedxref{fs.op.copy_symlink}{fs.op.copy.symlink} +\movedxref{fs.op.create_directories}{fs.op.create.directories} +\movedxref{fs.op.create_directory}{fs.op.create.directory} +\movedxref{fs.op.create_dir_symlk}{fs.op.create.dir.symlk} +\movedxref{fs.op.create_hard_lk}{fs.op.create.hard.lk} +\movedxref{fs.op.create_symlink}{fs.op.create.symlink} +\movedxref{fs.op.current_path}{fs.op.current.path} +\movedxref{fs.op.file_size}{fs.op.file.size} +\movedxref{fs.op.hard_lk_ct}{fs.op.hard.lk.ct} +\movedxref{fs.op.is_block_file}{fs.op.is.block.file} +\movedxref{fs.op.is_char_file}{fs.op.is.char.file} +\movedxref{fs.op.is_directory}{fs.op.is.directory} +\movedxref{fs.op.is_empty}{fs.op.is.empty} +\movedxref{fs.op.is_fifo}{fs.op.is.fifo} +\movedxref{fs.op.is_other}{fs.op.is.other} +\movedxref{fs.op.is_regular_file}{fs.op.is.regular.file} +\movedxref{fs.op.is_socket}{fs.op.is.socket} +\movedxref{fs.op.is_symlink}{fs.op.is.symlink} +\movedxref{fs.op.last_write_time}{fs.op.last.write.time} +\movedxref{fs.op.read_symlink}{fs.op.read.symlink} +\movedxref{fs.op.remove_all}{fs.op.remove.all} +\movedxref{fs.op.resize_file}{fs.op.resize.file} +\movedxref{fs.op.status_known}{fs.op.status.known} +\movedxref{fs.op.symlink_status}{fs.op.symlink.status} +\movedxref{fs.op.temp_dir_path}{fs.op.temp.dir.path} +\movedxref{fs.op.weakly_canonical}{fs.op.weakly.canonical} +\movedxref{func.not_fn}{func.not.fn} +\movedxref{futures.future_error}{futures.future.error} +\movedxref{futures.shared_future}{futures.shared.future} +\movedxref{futures.unique_future}{futures.unique.future} +\movedxref{initializer_list.syn}{initializer.list.syn} +\movedxref{optional.comp_with_t}{optional.comp.with.t} +\movedxref{sf.cmath.assoc_laguerre}{sf.cmath.assoc.laguerre} +\movedxref{sf.cmath.assoc_legendre}{sf.cmath.assoc.legendre} +\movedxref{sf.cmath.comp_ellint_1}{sf.cmath.comp.ellint.1} +\movedxref{sf.cmath.comp_ellint_2}{sf.cmath.comp.ellint.2} +\movedxref{sf.cmath.comp_ellint_3}{sf.cmath.comp.ellint.3} +\movedxref{sf.cmath.cyl_bessel_i}{sf.cmath.cyl.bessel.i} +\movedxref{sf.cmath.cyl_bessel_j}{sf.cmath.cyl.bessel.j} +\movedxref{sf.cmath.cyl_bessel_k}{sf.cmath.cyl.bessel.k} +\movedxref{sf.cmath.cyl_neumann}{sf.cmath.cyl.neumann} +\movedxref{sf.cmath.ellint_1}{sf.cmath.ellint.1} +\movedxref{sf.cmath.ellint_2}{sf.cmath.ellint.2} +\movedxref{sf.cmath.ellint_3}{sf.cmath.ellint.3} +\movedxref{sf.cmath.riemann_zeta}{sf.cmath.riemann.zeta} +\movedxref{sf.cmath.sph_bessel}{sf.cmath.sph.bessel} +\movedxref{sf.cmath.sph_legendre}{sf.cmath.sph.legendre} +\movedxref{sf.cmath.sph_neumann}{sf.cmath.sph.neumann} +\movedxref{shared_mutex.syn}{shared.mutex.syn} +\movedxref{system_error.syn}{system.error.syn} +\movedxref{time.traits.duration_values}{time.traits.duration.values} +\movedxref{time.traits.is_fp}{time.traits.is.fp} +\movedxref{utility.as_const}{utility.as.const} + +% Dissolved subclause. +\movedxref{func.wrap.badcall.const}{func.wrap.badcall} + +% Shortened label +\movedxref{language.support}{support} + +% Other fixes +\removedxref{intro.ack} + +\movedxref{conversions}{locale.convenience} + +% CD and DIS C++20 +\removedxref{fs.norm.ref} +\movedxref{definitions}{intro.defs} +\removedxref{defns.arbitrary.stream} +\removedxref{defns.comparison} +\removedxref{defns.default.behavior.func} +\removedxref{defns.iostream.templates} +\removedxref{defns.repositional.stream} + +% Fix solitary subclauses +\movedxref{unreachable.sentinels}{unreachable.sentinel} +\movedxref{default.sentinels}{default.sentinel} +\movedxref{depr.iterator.primitives}{depr.iterator} +\movedxref{depr.iterator.basic}{depr.iterator} + +\movedxref{re.def}{intro.defs} +\movedxref{basic.scope.declarative}{basic.scope.scope} +\movedxref{basic.funscope}{stmt.label} +\movedxref{basic.scope.hiding}{basic.lookup} +\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.nested.type}{diff.basic} +\movedxref{over.load}{basic.scope.scope} +\movedxref{over.dcl}{basic.link} +\movedxref{temp.nondep}{temp.res} +\movedxref{temp.inject}{temp.friend} + +% P2096R2 Generalized wording for partial specializations +\movedxref{temp.class.spec}{temp.spec.partial} +\movedxref{temp.class.spec.general}{temp.spec.partial.general} +\movedxref{temp.class.spec.match}{temp.spec.partial.match} +\movedxref{temp.class.order}{temp.spec.partial.order} +\movedxref{temp.class.spec.mfunc}{temp.spec.partial.member} + +\movedxref{forwardlist}{forward.list} +\movedxref{forwardlist.overview}{forward.list.overview} +\movedxref{forwardlist.cons}{forward.list.cons} +\movedxref{forwardlist.iter}{forward.list.iter} +\movedxref{forwardlist.access}{forward.list.access} +\movedxref{forwardlist.modifiers}{forward.list.modifiers} +\movedxref{forwardlist.ops}{forward.list.ops} + +% P2186R2 Removing Garbage Collection Support +\removedxref{basic.stc.dynamic.safety} +\removedxref{util.dynamic.safety} +\removedxref{res.on.pointer.storage} + +% LWG2818 "::std::" everywhere rule needs tweaking +\removedxref{fs.req.namespace} +\movedxref{fs.req.general}{fs.req} + +% P2325R3 Views should not be required to be default constructible +% P2494R2 Relaxing range adaptors to allow for move only types +% range.semi.wrap => range.copy.wrap => range.move.wrap +\movedxref{range.semi.wrap}{range.move.wrap} + +% P2210R2 Superior String Splitting +\movedxref{range.split.outer}{range.lazy.split.outer} +\movedxref{range.split.outer.value}{range.lazy.split.outer.value} +\movedxref{range.split.inner}{range.lazy.split.inner} + +% P2128R6 Multidimensional subscript operator +\removedxref{depr.comma.subscript} + +% P2340R1 Clarifying the status of the "C headers" +\movedxref{depr.c.headers}{support.c.headers} +\movedxref{depr.c.headers.general}{support.c.headers.general} +\movedxref{depr.c.headers.other}{support.c.headers.other} +\movedxref{depr.complex.h.syn}{complex.h.syn} +\movedxref{depr.iso646.h.syn}{iso646.h.syn} +\movedxref{depr.stdalign.h.syn}{stdalign.h.syn} +\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} + +% 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}{dcl.init.list} +\movedxref{defns.expression-equivalent}{defns.expression.equivalent} + +% P1467R9 Extended floating-point types and standard names +\movedxref{complex.special}{complex.members} +\movedxref{cstdint}{support.arith.types} +\removedxref{cstdint.general} + +% LWG3659 Consider ATOMIC_FLAG_INIT undeprecation +\removedxref{depr.atomics.flag} + +% LWG3818 Exposition-only concepts are not described in library intro +\movedxref{expos.only.func}{expos.only.entity} +\removedxref{expos.only.types} + +% P2614R2 Deprecate numeric_limits::has_denorm +\movedxref{denorm.style}{depr.numeric.limits.has.denorm} +\removedxref{fp.style} + +% CD and DIS C++2023 +\movedxref{defns.multibyte}{multibyte.strings} + % P2864R2 Remove deprecated arithmetic conversions \removedxref{depr.arith.conv.enum} +% P2866R5 Remove deprecated array comparisons +\removedxref{depr.array.comp} + % P2871R3 Remove deprecated header \removedxref{depr.codecvt.syn} \removedxref{depr.locale.stdcvt} @@ -37,6 +415,45 @@ % P2870R3 Remove `basic_string::reserve()` with no parameters \removedxref{depr.string.capacity} +% P2867R2 Remove deprecated strstreams +\removedxref{depr.istrstream} +\removedxref{depr.istrstream.cons} +\removedxref{depr.istrstream.general} +\removedxref{depr.istrstream.members} +\removedxref{depr.ostrstream} +\removedxref{depr.ostrstream.cons} +\removedxref{depr.ostrstream.general} +\removedxref{depr.ostrstream.members} +\removedxref{depr.str.strstreams} +\removedxref{depr.strstream} +\removedxref{depr.strstream.cons} +\removedxref{depr.strstream.dest} +\removedxref{depr.strstream.general} +\removedxref{depr.strstream.oper} +\removedxref{depr.strstream.syn} +\removedxref{depr.strstreambuf} +\removedxref{depr.strstreambuf.cons} +\removedxref{depr.strstreambuf.general} +\removedxref{depr.strstreambuf.members} +\removedxref{depr.strstreambuf.virtuals} + +% P2869R4 Remove deprecated shared_ptr atomic access +\removedxref{depr.util.smartptr.shared.atomic} + +% P2872R3 Remove wstring_convert +\removedxref{depr.conversions} +\removedxref{depr.conversions.buffer} +\removedxref{depr.conversions.general} +\removedxref{depr.conversions.string} + +% Clause restructuring +\removedxref{type.index.overview} +\removedxref{type.index.members} +\removedxref{type.index.hash} + +% CWG 2843 removed [uaxid.def.rfmt] +\removedxref{uaxid.def.rfmt} + %%% Renamed sections. %%% Examples: % @@ -48,10 +465,48 @@ % https://github.com/cplusplus/draft/pull/6255 \movedxref{container.gen.reqmts}{container.requirements.general} +% P2875R4 Undeprecate polymorphic_allocator::destroy +\movedxref{depr.mem.poly.allocator.mem}{mem.poly.allocator.mem} + % https://github.com/cplusplus/draft/pull/6653 \movedxref{mismatch}{alg.mismatch} +% P2300R10 std::execution +\movedxref{stopsource.nonmembers}{stopsource} +\movedxref{stoptoken.cons}{stopsource} +\movedxref{stoptoken.nonmembers}{stopsource} + +% https://github.com/cplusplus/draft/pull/7276 +\movedxref{except.uncaught}{except.throw} + +% https://github.com/cplusplus/draft/pull/7345 +\movedxref{basic.stc.inherit}{basic.stc.general} + +% https://github.com/cplusplus/draft/pull/7524 +\movedxref{expr.ass}{expr.assign} +\movedxref{over.ass}{over.assign} + +% CWG 2024-11-20 in Wroclaw; https://github.com/cplusplus/draft/pull/7485 +\movedxref{stmt.stmt}{stmt} +\movedxref{dcl.dcl}{dcl} + +% P1494R5 added more to this section and expanded its scope +\movedxref{utility.unreachable}{utility.undefined} + %%% Deprecated features. %%% Example: % % \deprxref{old.label} (if moved to depr.old.label, otherwise use \movedxref) + +\removedxref{util.smartptr.shared.atomic} +\removedxref{res.on.required} +\deprxref{fs.path.factory} +\movedxref{operators}{depr.relops} + +% P3475R2 Defang and deprecate memory_order::consume +\removedxref{dcl.attr.depend} + +% P3348R3 C++26 should refer to C23 not C17 +\removedxref{diff.header.assert.h} +\removedxref{diff.header.stdalign.h} +\removedxref{diff.header.stdbool.h} diff --git a/source/xrefprev b/source/xrefprev index 72e4f16ee5..c59156d80d 100644 --- a/source/xrefprev +++ b/source/xrefprev @@ -1,3072 +1,2757 @@ -\glossaryentry{intro.scope@ {\memgloterm{intro.scope}}{\memglodesc{(\ref {intro.scope})}} {\memgloref{}}|memjustarg}{1} -\glossaryentry{intro.refs@ {\memgloterm{intro.refs}}{\memglodesc{(\ref {intro.refs})}} {\memgloref{}}|memjustarg}{2} -\glossaryentry{intro.defs@ {\memgloterm{intro.defs}}{\memglodesc{(\ref {intro.defs})}} {\memgloref{}}|memjustarg}{3} -\glossaryentry{defns.access@ {\memgloterm{defns.access}}{\memglodesc{(\ref {defns.access})}} {\memgloref{}}|memjustarg}{3} -\glossaryentry{defns.argument@ {\memgloterm{defns.argument}}{\memglodesc{(\ref {defns.argument})}} {\memgloref{}}|memjustarg}{3} -\glossaryentry{defns.argument.macro@ {\memgloterm{defns.argument.macro}}{\memglodesc{(\ref {defns.argument.macro})}} {\memgloref{}}|memjustarg}{3} -\glossaryentry{defns.argument.throw@ {\memgloterm{defns.argument.throw}}{\memglodesc{(\ref {defns.argument.throw})}} {\memgloref{}}|memjustarg}{3} -\glossaryentry{defns.argument.templ@ {\memgloterm{defns.argument.templ}}{\memglodesc{(\ref {defns.argument.templ})}} {\memgloref{}}|memjustarg}{3} -\glossaryentry{defns.block@ {\memgloterm{defns.block}}{\memglodesc{(\ref {defns.block})}} {\memgloref{}}|memjustarg}{3} -\glossaryentry{defns.block.stmt@ {\memgloterm{defns.block.stmt}}{\memglodesc{(\ref {defns.block.stmt})}} {\memgloref{}}|memjustarg}{3} -\glossaryentry{defns.character@ {\memgloterm{defns.character}}{\memglodesc{(\ref {defns.character})}} {\memgloref{}}|memjustarg}{3} -\glossaryentry{defns.character.container@ {\memgloterm{defns.character.container}}{\memglodesc{(\ref {defns.character.container})}} {\memgloref{}}|memjustarg}{3} -\glossaryentry{defns.regex.collating.element@ {\memgloterm{defns.regex.collating.element}}{\memglodesc{(\ref {defns.regex.collating.element})}} {\memgloref{}}|memjustarg}{4} -\glossaryentry{defns.component@ {\memgloterm{defns.component}}{\memglodesc{(\ref {defns.component})}} {\memgloref{}}|memjustarg}{4} -\glossaryentry{defns.cond.supp@ {\memgloterm{defns.cond.supp}}{\memglodesc{(\ref {defns.cond.supp})}} {\memgloref{}}|memjustarg}{4} -\glossaryentry{defns.const.subexpr@ {\memgloterm{defns.const.subexpr}}{\memglodesc{(\ref {defns.const.subexpr})}} {\memgloref{}}|memjustarg}{4} -\glossaryentry{defns.deadlock@ {\memgloterm{defns.deadlock}}{\memglodesc{(\ref {defns.deadlock})}} {\memgloref{}}|memjustarg}{4} -\glossaryentry{defns.default.behavior.impl@ {\memgloterm{defns.default.behavior.impl}}{\memglodesc{(\ref {defns.default.behavior.impl})}} {\memgloref{}}|memjustarg}{4} -\glossaryentry{defns.diagnostic@ {\memgloterm{defns.diagnostic}}{\memglodesc{(\ref {defns.diagnostic})}} {\memgloref{}}|memjustarg}{4} -\glossaryentry{defns.dynamic.type@ {\memgloterm{defns.dynamic.type}}{\memglodesc{(\ref {defns.dynamic.type})}} {\memgloref{}}|memjustarg}{4} -\glossaryentry{defns.dynamic.type.prvalue@ {\memgloterm{defns.dynamic.type.prvalue}}{\memglodesc{(\ref {defns.dynamic.type.prvalue})}} {\memgloref{}}|memjustarg}{4} -\glossaryentry{defns.expression.equivalent@ {\memgloterm{defns.expression.equivalent}}{\memglodesc{(\ref {defns.expression.equivalent})}} {\memgloref{}}|memjustarg}{4} -\glossaryentry{defns.regex.finite.state.machine@ {\memgloterm{defns.regex.finite.state.machine}}{\memglodesc{(\ref {defns.regex.finite.state.machine})}} {\memgloref{}}|memjustarg}{5} -\glossaryentry{defns.regex.format.specifier@ {\memgloterm{defns.regex.format.specifier}}{\memglodesc{(\ref {defns.regex.format.specifier})}} {\memgloref{}}|memjustarg}{5} -\glossaryentry{defns.handler@ {\memgloterm{defns.handler}}{\memglodesc{(\ref {defns.handler})}} {\memgloref{}}|memjustarg}{5} -\glossaryentry{defns.ill.formed@ {\memgloterm{defns.ill.formed}}{\memglodesc{(\ref {defns.ill.formed})}} {\memgloref{}}|memjustarg}{5} -\glossaryentry{defns.impl.defined@ {\memgloterm{defns.impl.defined}}{\memglodesc{(\ref {defns.impl.defined})}} {\memgloref{}}|memjustarg}{5} -\glossaryentry{defns.order.ptr@ {\memgloterm{defns.order.ptr}}{\memglodesc{(\ref {defns.order.ptr})}} {\memgloref{}}|memjustarg}{5} -\glossaryentry{defns.impl.limits@ {\memgloterm{defns.impl.limits}}{\memglodesc{(\ref {defns.impl.limits})}} {\memgloref{}}|memjustarg}{5} -\glossaryentry{defns.locale.specific@ {\memgloterm{defns.locale.specific}}{\memglodesc{(\ref {defns.locale.specific})}} {\memgloref{}}|memjustarg}{5} -\glossaryentry{defns.regex.matched@ {\memgloterm{defns.regex.matched}}{\memglodesc{(\ref {defns.regex.matched})}} {\memgloref{}}|memjustarg}{5} -\glossaryentry{defns.modifier@ {\memgloterm{defns.modifier}}{\memglodesc{(\ref {defns.modifier})}} {\memgloref{}}|memjustarg}{5} -\glossaryentry{defns.move.assign@ {\memgloterm{defns.move.assign}}{\memglodesc{(\ref {defns.move.assign})}} {\memgloref{}}|memjustarg}{6} -\glossaryentry{defns.move.constr@ {\memgloterm{defns.move.constr}}{\memglodesc{(\ref {defns.move.constr})}} {\memgloref{}}|memjustarg}{6} -\glossaryentry{defns.nonconst.libcall@ {\memgloterm{defns.nonconst.libcall}}{\memglodesc{(\ref {defns.nonconst.libcall})}} {\memgloref{}}|memjustarg}{6} -\glossaryentry{defns.ntcts@ {\memgloterm{defns.ntcts}}{\memglodesc{(\ref {defns.ntcts})}} {\memgloref{}}|memjustarg}{6} -\glossaryentry{defns.observer@ {\memgloterm{defns.observer}}{\memglodesc{(\ref {defns.observer})}} {\memgloref{}}|memjustarg}{6} -\glossaryentry{defns.parameter@ {\memgloterm{defns.parameter}}{\memglodesc{(\ref {defns.parameter})}} {\memgloref{}}|memjustarg}{6} -\glossaryentry{defns.parameter.macro@ {\memgloterm{defns.parameter.macro}}{\memglodesc{(\ref {defns.parameter.macro})}} {\memgloref{}}|memjustarg}{6} -\glossaryentry{defns.parameter.templ@ {\memgloterm{defns.parameter.templ}}{\memglodesc{(\ref {defns.parameter.templ})}} {\memgloref{}}|memjustarg}{6} -\glossaryentry{defns.regex.primary.equivalence.class@ {\memgloterm{defns.regex.primary.equivalence.class}}{\memglodesc{(\ref {defns.regex.primary.equivalence.class})}} {\memgloref{}}|memjustarg}{6} -\glossaryentry{defns.prog.def.spec@ {\memgloterm{defns.prog.def.spec}}{\memglodesc{(\ref {defns.prog.def.spec})}} {\memgloref{}}|memjustarg}{6} -\glossaryentry{defns.prog.def.type@ {\memgloterm{defns.prog.def.type}}{\memglodesc{(\ref {defns.prog.def.type})}} {\memgloref{}}|memjustarg}{6} -\glossaryentry{defns.projection@ {\memgloterm{defns.projection}}{\memglodesc{(\ref {defns.projection})}} {\memgloref{}}|memjustarg}{6} -\glossaryentry{defns.referenceable@ {\memgloterm{defns.referenceable}}{\memglodesc{(\ref {defns.referenceable})}} {\memgloref{}}|memjustarg}{7} -\glossaryentry{defns.regex.regular.expression@ {\memgloterm{defns.regex.regular.expression}}{\memglodesc{(\ref {defns.regex.regular.expression})}} {\memgloref{}}|memjustarg}{7} -\glossaryentry{defns.replacement@ {\memgloterm{defns.replacement}}{\memglodesc{(\ref {defns.replacement})}} {\memgloref{}}|memjustarg}{7} -\glossaryentry{defns.required.behavior@ {\memgloterm{defns.required.behavior}}{\memglodesc{(\ref {defns.required.behavior})}} {\memgloref{}}|memjustarg}{7} -\glossaryentry{defns.reserved.function@ {\memgloterm{defns.reserved.function}}{\memglodesc{(\ref {defns.reserved.function})}} {\memgloref{}}|memjustarg}{7} -\glossaryentry{defns.signature@ {\memgloterm{defns.signature}}{\memglodesc{(\ref {defns.signature})}} {\memgloref{}}|memjustarg}{7} -\glossaryentry{defns.signature.friend@ {\memgloterm{defns.signature.friend}}{\memglodesc{(\ref {defns.signature.friend})}} {\memgloref{}}|memjustarg}{7} -\glossaryentry{defns.signature.templ@ {\memgloterm{defns.signature.templ}}{\memglodesc{(\ref {defns.signature.templ})}} {\memgloref{}}|memjustarg}{7} -\glossaryentry{defns.signature.templ.friend@ {\memgloterm{defns.signature.templ.friend}}{\memglodesc{(\ref {defns.signature.templ.friend})}} {\memgloref{}}|memjustarg}{7} -\glossaryentry{defns.signature.spec@ {\memgloterm{defns.signature.spec}}{\memglodesc{(\ref {defns.signature.spec})}} {\memgloref{}}|memjustarg}{8} -\glossaryentry{defns.signature.member@ {\memgloterm{defns.signature.member}}{\memglodesc{(\ref {defns.signature.member})}} {\memgloref{}}|memjustarg}{8} -\glossaryentry{defns.signature.member.templ@ {\memgloterm{defns.signature.member.templ}}{\memglodesc{(\ref {defns.signature.member.templ})}} {\memgloref{}}|memjustarg}{8} -\glossaryentry{defns.signature.member.spec@ {\memgloterm{defns.signature.member.spec}}{\memglodesc{(\ref {defns.signature.member.spec})}} {\memgloref{}}|memjustarg}{8} -\glossaryentry{defns.signature.template.head@ {\memgloterm{defns.signature.template.head}}{\memglodesc{(\ref {defns.signature.template.head})}} {\memgloref{}}|memjustarg}{8} -\glossaryentry{defns.stable@ {\memgloterm{defns.stable}}{\memglodesc{(\ref {defns.stable})}} {\memgloref{}}|memjustarg}{8} -\glossaryentry{defns.static.type@ {\memgloterm{defns.static.type}}{\memglodesc{(\ref {defns.static.type})}} {\memgloref{}}|memjustarg}{8} -\glossaryentry{defns.regex.subexpression@ {\memgloterm{defns.regex.subexpression}}{\memglodesc{(\ref {defns.regex.subexpression})}} {\memgloref{}}|memjustarg}{8} -\glossaryentry{defns.traits@ {\memgloterm{defns.traits}}{\memglodesc{(\ref {defns.traits})}} {\memgloref{}}|memjustarg}{8} -\glossaryentry{defns.unblock@ {\memgloterm{defns.unblock}}{\memglodesc{(\ref {defns.unblock})}} {\memgloref{}}|memjustarg}{8} -\glossaryentry{defns.undefined@ {\memgloterm{defns.undefined}}{\memglodesc{(\ref {defns.undefined})}} {\memgloref{}}|memjustarg}{8} -\glossaryentry{defns.unspecified@ {\memgloterm{defns.unspecified}}{\memglodesc{(\ref {defns.unspecified})}} {\memgloref{}}|memjustarg}{9} -\glossaryentry{defns.valid@ {\memgloterm{defns.valid}}{\memglodesc{(\ref {defns.valid})}} {\memgloref{}}|memjustarg}{9} -\glossaryentry{defns.well.formed@ {\memgloterm{defns.well.formed}}{\memglodesc{(\ref {defns.well.formed})}} {\memgloref{}}|memjustarg}{9} -\glossaryentry{intro@ {\memgloterm{intro}}{\memglodesc{(\ref {intro})}} {\memgloref{}}|memjustarg}{10} -\glossaryentry{intro.compliance@ {\memgloterm{intro.compliance}}{\memglodesc{(\ref {intro.compliance})}} {\memgloref{}}|memjustarg}{10} -\glossaryentry{intro.compliance.general@ {\memgloterm{intro.compliance.general}}{\memglodesc{(\ref {intro.compliance.general})}} {\memgloref{}}|memjustarg}{10} -\glossaryentry{intro.abstract@ {\memgloterm{intro.abstract}}{\memglodesc{(\ref {intro.abstract})}} {\memgloref{}}|memjustarg}{11} -\glossaryentry{intro.structure@ {\memgloterm{intro.structure}}{\memglodesc{(\ref {intro.structure})}} {\memgloref{}}|memjustarg}{11} -\glossaryentry{syntax@ {\memgloterm{syntax}}{\memglodesc{(\ref {syntax})}} {\memgloref{}}|memjustarg}{12} -\glossaryentry{lex@ {\memgloterm{lex}}{\memglodesc{(\ref {lex})}} {\memgloref{}}|memjustarg}{13} -\glossaryentry{lex.separate@ {\memgloterm{lex.separate}}{\memglodesc{(\ref {lex.separate})}} {\memgloref{}}|memjustarg}{13} -\glossaryentry{lex.phases@ {\memgloterm{lex.phases}}{\memglodesc{(\ref {lex.phases})}} {\memgloref{}}|memjustarg}{13} -\glossaryentry{lex.charset@ {\memgloterm{lex.charset}}{\memglodesc{(\ref {lex.charset})}} {\memgloref{}}|memjustarg}{14} -\glossaryentry{lex.pptoken@ {\memgloterm{lex.pptoken}}{\memglodesc{(\ref {lex.pptoken})}} {\memgloref{}}|memjustarg}{17} -\glossaryentry{lex.digraph@ {\memgloterm{lex.digraph}}{\memglodesc{(\ref {lex.digraph})}} {\memgloref{}}|memjustarg}{18} -\glossaryentry{lex.token@ {\memgloterm{lex.token}}{\memglodesc{(\ref {lex.token})}} {\memgloref{}}|memjustarg}{18} -\glossaryentry{lex.comment@ {\memgloterm{lex.comment}}{\memglodesc{(\ref {lex.comment})}} {\memgloref{}}|memjustarg}{18} -\glossaryentry{lex.header@ {\memgloterm{lex.header}}{\memglodesc{(\ref {lex.header})}} {\memgloref{}}|memjustarg}{18} -\glossaryentry{lex.ppnumber@ {\memgloterm{lex.ppnumber}}{\memglodesc{(\ref {lex.ppnumber})}} {\memgloref{}}|memjustarg}{19} -\glossaryentry{lex.name@ {\memgloterm{lex.name}}{\memglodesc{(\ref {lex.name})}} {\memgloref{}}|memjustarg}{19} -\glossaryentry{lex.key@ {\memgloterm{lex.key}}{\memglodesc{(\ref {lex.key})}} {\memgloref{}}|memjustarg}{20} -\glossaryentry{lex.operators@ {\memgloterm{lex.operators}}{\memglodesc{(\ref {lex.operators})}} {\memgloref{}}|memjustarg}{20} -\glossaryentry{lex.literal@ {\memgloterm{lex.literal}}{\memglodesc{(\ref {lex.literal})}} {\memgloref{}}|memjustarg}{21} -\glossaryentry{lex.literal.kinds@ {\memgloterm{lex.literal.kinds}}{\memglodesc{(\ref {lex.literal.kinds})}} {\memgloref{}}|memjustarg}{21} -\glossaryentry{lex.icon@ {\memgloterm{lex.icon}}{\memglodesc{(\ref {lex.icon})}} {\memgloref{}}|memjustarg}{21} -\glossaryentry{lex.ccon@ {\memgloterm{lex.ccon}}{\memglodesc{(\ref {lex.ccon})}} {\memgloref{}}|memjustarg}{23} -\glossaryentry{lex.fcon@ {\memgloterm{lex.fcon}}{\memglodesc{(\ref {lex.fcon})}} {\memgloref{}}|memjustarg}{25} -\glossaryentry{lex.string@ {\memgloterm{lex.string}}{\memglodesc{(\ref {lex.string})}} {\memgloref{}}|memjustarg}{26} -\glossaryentry{lex.bool@ {\memgloterm{lex.bool}}{\memglodesc{(\ref {lex.bool})}} {\memgloref{}}|memjustarg}{29} -\glossaryentry{lex.nullptr@ {\memgloterm{lex.nullptr}}{\memglodesc{(\ref {lex.nullptr})}} {\memgloref{}}|memjustarg}{29} -\glossaryentry{lex.ext@ {\memgloterm{lex.ext}}{\memglodesc{(\ref {lex.ext})}} {\memgloref{}}|memjustarg}{29} -\glossaryentry{basic@ {\memgloterm{basic}}{\memglodesc{(\ref {basic})}} {\memgloref{}}|memjustarg}{32} -\glossaryentry{basic.pre@ {\memgloterm{basic.pre}}{\memglodesc{(\ref {basic.pre})}} {\memgloref{}}|memjustarg}{32} -\glossaryentry{basic.def@ {\memgloterm{basic.def}}{\memglodesc{(\ref {basic.def})}} {\memgloref{}}|memjustarg}{33} -\glossaryentry{basic.def.odr@ {\memgloterm{basic.def.odr}}{\memglodesc{(\ref {basic.def.odr})}} {\memgloref{}}|memjustarg}{34} -\glossaryentry{basic.scope@ {\memgloterm{basic.scope}}{\memglodesc{(\ref {basic.scope})}} {\memgloref{}}|memjustarg}{39} -\glossaryentry{basic.scope.scope@ {\memgloterm{basic.scope.scope}}{\memglodesc{(\ref {basic.scope.scope})}} {\memgloref{}}|memjustarg}{39} -\glossaryentry{basic.scope.pdecl@ {\memgloterm{basic.scope.pdecl}}{\memglodesc{(\ref {basic.scope.pdecl})}} {\memgloref{}}|memjustarg}{41} -\glossaryentry{basic.scope.block@ {\memgloterm{basic.scope.block}}{\memglodesc{(\ref {basic.scope.block})}} {\memgloref{}}|memjustarg}{42} -\glossaryentry{basic.scope.param@ {\memgloterm{basic.scope.param}}{\memglodesc{(\ref {basic.scope.param})}} {\memgloref{}}|memjustarg}{43} -\glossaryentry{basic.scope.lambda@ {\memgloterm{basic.scope.lambda}}{\memglodesc{(\ref {basic.scope.lambda})}} {\memgloref{}}|memjustarg}{43} -\glossaryentry{basic.scope.namespace@ {\memgloterm{basic.scope.namespace}}{\memglodesc{(\ref {basic.scope.namespace})}} {\memgloref{}}|memjustarg}{43} -\glossaryentry{basic.scope.class@ {\memgloterm{basic.scope.class}}{\memglodesc{(\ref {basic.scope.class})}} {\memgloref{}}|memjustarg}{44} -\glossaryentry{basic.scope.enum@ {\memgloterm{basic.scope.enum}}{\memglodesc{(\ref {basic.scope.enum})}} {\memgloref{}}|memjustarg}{44} -\glossaryentry{basic.scope.temp@ {\memgloterm{basic.scope.temp}}{\memglodesc{(\ref {basic.scope.temp})}} {\memgloref{}}|memjustarg}{44} -\glossaryentry{basic.lookup@ {\memgloterm{basic.lookup}}{\memglodesc{(\ref {basic.lookup})}} {\memgloref{}}|memjustarg}{44} -\glossaryentry{basic.lookup.general@ {\memgloterm{basic.lookup.general}}{\memglodesc{(\ref {basic.lookup.general})}} {\memgloref{}}|memjustarg}{44} -\glossaryentry{class.member.lookup@ {\memgloterm{class.member.lookup}}{\memglodesc{(\ref {class.member.lookup})}} {\memgloref{}}|memjustarg}{45} -\glossaryentry{basic.lookup.unqual@ {\memgloterm{basic.lookup.unqual}}{\memglodesc{(\ref {basic.lookup.unqual})}} {\memgloref{}}|memjustarg}{48} -\glossaryentry{basic.lookup.argdep@ {\memgloterm{basic.lookup.argdep}}{\memglodesc{(\ref {basic.lookup.argdep})}} {\memgloref{}}|memjustarg}{49} -\glossaryentry{basic.lookup.qual@ {\memgloterm{basic.lookup.qual}}{\memglodesc{(\ref {basic.lookup.qual})}} {\memgloref{}}|memjustarg}{52} -\glossaryentry{basic.lookup.qual.general@ {\memgloterm{basic.lookup.qual.general}}{\memglodesc{(\ref {basic.lookup.qual.general})}} {\memgloref{}}|memjustarg}{52} -\glossaryentry{class.qual@ {\memgloterm{class.qual}}{\memglodesc{(\ref {class.qual})}} {\memgloref{}}|memjustarg}{54} -\glossaryentry{namespace.qual@ {\memgloterm{namespace.qual}}{\memglodesc{(\ref {namespace.qual})}} {\memgloref{}}|memjustarg}{54} -\glossaryentry{basic.lookup.elab@ {\memgloterm{basic.lookup.elab}}{\memglodesc{(\ref {basic.lookup.elab})}} {\memgloref{}}|memjustarg}{56} -\glossaryentry{basic.lookup.udir@ {\memgloterm{basic.lookup.udir}}{\memglodesc{(\ref {basic.lookup.udir})}} {\memgloref{}}|memjustarg}{57} -\glossaryentry{basic.link@ {\memgloterm{basic.link}}{\memglodesc{(\ref {basic.link})}} {\memgloref{}}|memjustarg}{57} -\glossaryentry{basic.memobj@ {\memgloterm{basic.memobj}}{\memglodesc{(\ref {basic.memobj})}} {\memgloref{}}|memjustarg}{61} -\glossaryentry{intro.memory@ {\memgloterm{intro.memory}}{\memglodesc{(\ref {intro.memory})}} {\memgloref{}}|memjustarg}{61} -\glossaryentry{intro.object@ {\memgloterm{intro.object}}{\memglodesc{(\ref {intro.object})}} {\memgloref{}}|memjustarg}{62} -\glossaryentry{basic.life@ {\memgloterm{basic.life}}{\memglodesc{(\ref {basic.life})}} {\memgloref{}}|memjustarg}{64} -\glossaryentry{basic.indet@ {\memgloterm{basic.indet}}{\memglodesc{(\ref {basic.indet})}} {\memgloref{}}|memjustarg}{67} -\glossaryentry{basic.stc@ {\memgloterm{basic.stc}}{\memglodesc{(\ref {basic.stc})}} {\memgloref{}}|memjustarg}{67} -\glossaryentry{basic.stc.general@ {\memgloterm{basic.stc.general}}{\memglodesc{(\ref {basic.stc.general})}} {\memgloref{}}|memjustarg}{67} -\glossaryentry{basic.stc.static@ {\memgloterm{basic.stc.static}}{\memglodesc{(\ref {basic.stc.static})}} {\memgloref{}}|memjustarg}{68} -\glossaryentry{basic.stc.thread@ {\memgloterm{basic.stc.thread}}{\memglodesc{(\ref {basic.stc.thread})}} {\memgloref{}}|memjustarg}{68} -\glossaryentry{basic.stc.auto@ {\memgloterm{basic.stc.auto}}{\memglodesc{(\ref {basic.stc.auto})}} {\memgloref{}}|memjustarg}{68} -\glossaryentry{basic.stc.dynamic@ {\memgloterm{basic.stc.dynamic}}{\memglodesc{(\ref {basic.stc.dynamic})}} {\memgloref{}}|memjustarg}{68} -\glossaryentry{basic.stc.dynamic.general@ {\memgloterm{basic.stc.dynamic.general}}{\memglodesc{(\ref {basic.stc.dynamic.general})}} {\memgloref{}}|memjustarg}{68} -\glossaryentry{basic.stc.dynamic.allocation@ {\memgloterm{basic.stc.dynamic.allocation}}{\memglodesc{(\ref {basic.stc.dynamic.allocation})}} {\memgloref{}}|memjustarg}{69} -\glossaryentry{basic.stc.dynamic.deallocation@ {\memgloterm{basic.stc.dynamic.deallocation}}{\memglodesc{(\ref {basic.stc.dynamic.deallocation})}} {\memgloref{}}|memjustarg}{70} -\glossaryentry{basic.stc.inherit@ {\memgloterm{basic.stc.inherit}}{\memglodesc{(\ref {basic.stc.inherit})}} {\memgloref{}}|memjustarg}{70} -\glossaryentry{basic.align@ {\memgloterm{basic.align}}{\memglodesc{(\ref {basic.align})}} {\memgloref{}}|memjustarg}{70} -\glossaryentry{class.temporary@ {\memgloterm{class.temporary}}{\memglodesc{(\ref {class.temporary})}} {\memgloref{}}|memjustarg}{71} -\glossaryentry{basic.types@ {\memgloterm{basic.types}}{\memglodesc{(\ref {basic.types})}} {\memgloref{}}|memjustarg}{74} -\glossaryentry{basic.types.general@ {\memgloterm{basic.types.general}}{\memglodesc{(\ref {basic.types.general})}} {\memgloref{}}|memjustarg}{74} -\glossaryentry{basic.fundamental@ {\memgloterm{basic.fundamental}}{\memglodesc{(\ref {basic.fundamental})}} {\memgloref{}}|memjustarg}{76} -\glossaryentry{basic.extended.fp@ {\memgloterm{basic.extended.fp}}{\memglodesc{(\ref {basic.extended.fp})}} {\memgloref{}}|memjustarg}{78} -\glossaryentry{basic.compound@ {\memgloterm{basic.compound}}{\memglodesc{(\ref {basic.compound})}} {\memgloref{}}|memjustarg}{79} -\glossaryentry{basic.type.qualifier@ {\memgloterm{basic.type.qualifier}}{\memglodesc{(\ref {basic.type.qualifier})}} {\memgloref{}}|memjustarg}{80} -\glossaryentry{conv.rank@ {\memgloterm{conv.rank}}{\memglodesc{(\ref {conv.rank})}} {\memgloref{}}|memjustarg}{81} -\glossaryentry{basic.exec@ {\memgloterm{basic.exec}}{\memglodesc{(\ref {basic.exec})}} {\memgloref{}}|memjustarg}{82} -\glossaryentry{intro.execution@ {\memgloterm{intro.execution}}{\memglodesc{(\ref {intro.execution})}} {\memgloref{}}|memjustarg}{82} -\glossaryentry{intro.multithread@ {\memgloterm{intro.multithread}}{\memglodesc{(\ref {intro.multithread})}} {\memgloref{}}|memjustarg}{85} -\glossaryentry{intro.multithread.general@ {\memgloterm{intro.multithread.general}}{\memglodesc{(\ref {intro.multithread.general})}} {\memgloref{}}|memjustarg}{85} -\glossaryentry{intro.races@ {\memgloterm{intro.races}}{\memglodesc{(\ref {intro.races})}} {\memgloref{}}|memjustarg}{85} -\glossaryentry{intro.progress@ {\memgloterm{intro.progress}}{\memglodesc{(\ref {intro.progress})}} {\memgloref{}}|memjustarg}{88} -\glossaryentry{basic.start@ {\memgloterm{basic.start}}{\memglodesc{(\ref {basic.start})}} {\memgloref{}}|memjustarg}{90} -\glossaryentry{basic.start.main@ {\memgloterm{basic.start.main}}{\memglodesc{(\ref {basic.start.main})}} {\memgloref{}}|memjustarg}{90} -\glossaryentry{basic.start.static@ {\memgloterm{basic.start.static}}{\memglodesc{(\ref {basic.start.static})}} {\memgloref{}}|memjustarg}{91} -\glossaryentry{basic.start.dynamic@ {\memgloterm{basic.start.dynamic}}{\memglodesc{(\ref {basic.start.dynamic})}} {\memgloref{}}|memjustarg}{91} -\glossaryentry{basic.start.term@ {\memgloterm{basic.start.term}}{\memglodesc{(\ref {basic.start.term})}} {\memgloref{}}|memjustarg}{93} -\glossaryentry{expr@ {\memgloterm{expr}}{\memglodesc{(\ref {expr})}} {\memgloref{}}|memjustarg}{94} -\glossaryentry{expr.pre@ {\memgloterm{expr.pre}}{\memglodesc{(\ref {expr.pre})}} {\memgloref{}}|memjustarg}{94} -\glossaryentry{expr.prop@ {\memgloterm{expr.prop}}{\memglodesc{(\ref {expr.prop})}} {\memgloref{}}|memjustarg}{95} -\glossaryentry{basic.lval@ {\memgloterm{basic.lval}}{\memglodesc{(\ref {basic.lval})}} {\memgloref{}}|memjustarg}{95} -\glossaryentry{expr.type@ {\memgloterm{expr.type}}{\memglodesc{(\ref {expr.type})}} {\memgloref{}}|memjustarg}{96} -\glossaryentry{expr.context@ {\memgloterm{expr.context}}{\memglodesc{(\ref {expr.context})}} {\memgloref{}}|memjustarg}{97} -\glossaryentry{conv@ {\memgloterm{conv}}{\memglodesc{(\ref {conv})}} {\memgloref{}}|memjustarg}{98} -\glossaryentry{conv.general@ {\memgloterm{conv.general}}{\memglodesc{(\ref {conv.general})}} {\memgloref{}}|memjustarg}{98} -\glossaryentry{conv.lval@ {\memgloterm{conv.lval}}{\memglodesc{(\ref {conv.lval})}} {\memgloref{}}|memjustarg}{99} -\glossaryentry{conv.array@ {\memgloterm{conv.array}}{\memglodesc{(\ref {conv.array})}} {\memgloref{}}|memjustarg}{99} -\glossaryentry{conv.func@ {\memgloterm{conv.func}}{\memglodesc{(\ref {conv.func})}} {\memgloref{}}|memjustarg}{99} -\glossaryentry{conv.rval@ {\memgloterm{conv.rval}}{\memglodesc{(\ref {conv.rval})}} {\memgloref{}}|memjustarg}{99} -\glossaryentry{conv.qual@ {\memgloterm{conv.qual}}{\memglodesc{(\ref {conv.qual})}} {\memgloref{}}|memjustarg}{100} -\glossaryentry{conv.prom@ {\memgloterm{conv.prom}}{\memglodesc{(\ref {conv.prom})}} {\memgloref{}}|memjustarg}{100} -\glossaryentry{conv.fpprom@ {\memgloterm{conv.fpprom}}{\memglodesc{(\ref {conv.fpprom})}} {\memgloref{}}|memjustarg}{101} -\glossaryentry{conv.integral@ {\memgloterm{conv.integral}}{\memglodesc{(\ref {conv.integral})}} {\memgloref{}}|memjustarg}{101} -\glossaryentry{conv.double@ {\memgloterm{conv.double}}{\memglodesc{(\ref {conv.double})}} {\memgloref{}}|memjustarg}{101} -\glossaryentry{conv.fpint@ {\memgloterm{conv.fpint}}{\memglodesc{(\ref {conv.fpint})}} {\memgloref{}}|memjustarg}{101} -\glossaryentry{conv.ptr@ {\memgloterm{conv.ptr}}{\memglodesc{(\ref {conv.ptr})}} {\memgloref{}}|memjustarg}{102} -\glossaryentry{conv.mem@ {\memgloterm{conv.mem}}{\memglodesc{(\ref {conv.mem})}} {\memgloref{}}|memjustarg}{102} -\glossaryentry{conv.fctptr@ {\memgloterm{conv.fctptr}}{\memglodesc{(\ref {conv.fctptr})}} {\memgloref{}}|memjustarg}{102} -\glossaryentry{conv.bool@ {\memgloterm{conv.bool}}{\memglodesc{(\ref {conv.bool})}} {\memgloref{}}|memjustarg}{103} -\glossaryentry{expr.arith.conv@ {\memgloterm{expr.arith.conv}}{\memglodesc{(\ref {expr.arith.conv})}} {\memgloref{}}|memjustarg}{103} -\glossaryentry{expr.prim@ {\memgloterm{expr.prim}}{\memglodesc{(\ref {expr.prim})}} {\memgloref{}}|memjustarg}{103} -\glossaryentry{expr.prim.literal@ {\memgloterm{expr.prim.literal}}{\memglodesc{(\ref {expr.prim.literal})}} {\memgloref{}}|memjustarg}{103} -\glossaryentry{expr.prim.this@ {\memgloterm{expr.prim.this}}{\memglodesc{(\ref {expr.prim.this})}} {\memgloref{}}|memjustarg}{104} -\glossaryentry{expr.prim.paren@ {\memgloterm{expr.prim.paren}}{\memglodesc{(\ref {expr.prim.paren})}} {\memgloref{}}|memjustarg}{104} -\glossaryentry{expr.prim.id@ {\memgloterm{expr.prim.id}}{\memglodesc{(\ref {expr.prim.id})}} {\memgloref{}}|memjustarg}{104} -\glossaryentry{expr.prim.id.general@ {\memgloterm{expr.prim.id.general}}{\memglodesc{(\ref {expr.prim.id.general})}} {\memgloref{}}|memjustarg}{104} -\glossaryentry{expr.prim.id.unqual@ {\memgloterm{expr.prim.id.unqual}}{\memglodesc{(\ref {expr.prim.id.unqual})}} {\memgloref{}}|memjustarg}{105} -\glossaryentry{expr.prim.id.qual@ {\memgloterm{expr.prim.id.qual}}{\memglodesc{(\ref {expr.prim.id.qual})}} {\memgloref{}}|memjustarg}{107} -\glossaryentry{expr.prim.id.dtor@ {\memgloterm{expr.prim.id.dtor}}{\memglodesc{(\ref {expr.prim.id.dtor})}} {\memgloref{}}|memjustarg}{108} -\glossaryentry{expr.prim.lambda@ {\memgloterm{expr.prim.lambda}}{\memglodesc{(\ref {expr.prim.lambda})}} {\memgloref{}}|memjustarg}{108} -\glossaryentry{expr.prim.lambda.general@ {\memgloterm{expr.prim.lambda.general}}{\memglodesc{(\ref {expr.prim.lambda.general})}} {\memgloref{}}|memjustarg}{108} -\glossaryentry{expr.prim.lambda.closure@ {\memgloterm{expr.prim.lambda.closure}}{\memglodesc{(\ref {expr.prim.lambda.closure})}} {\memgloref{}}|memjustarg}{109} -\glossaryentry{expr.prim.lambda.capture@ {\memgloterm{expr.prim.lambda.capture}}{\memglodesc{(\ref {expr.prim.lambda.capture})}} {\memgloref{}}|memjustarg}{113} -\glossaryentry{expr.prim.fold@ {\memgloterm{expr.prim.fold}}{\memglodesc{(\ref {expr.prim.fold})}} {\memgloref{}}|memjustarg}{118} -\glossaryentry{expr.prim.req@ {\memgloterm{expr.prim.req}}{\memglodesc{(\ref {expr.prim.req})}} {\memgloref{}}|memjustarg}{119} -\glossaryentry{expr.prim.req.general@ {\memgloterm{expr.prim.req.general}}{\memglodesc{(\ref {expr.prim.req.general})}} {\memgloref{}}|memjustarg}{119} -\glossaryentry{expr.prim.req.simple@ {\memgloterm{expr.prim.req.simple}}{\memglodesc{(\ref {expr.prim.req.simple})}} {\memgloref{}}|memjustarg}{120} -\glossaryentry{expr.prim.req.type@ {\memgloterm{expr.prim.req.type}}{\memglodesc{(\ref {expr.prim.req.type})}} {\memgloref{}}|memjustarg}{120} -\glossaryentry{expr.prim.req.compound@ {\memgloterm{expr.prim.req.compound}}{\memglodesc{(\ref {expr.prim.req.compound})}} {\memgloref{}}|memjustarg}{120} -\glossaryentry{expr.prim.req.nested@ {\memgloterm{expr.prim.req.nested}}{\memglodesc{(\ref {expr.prim.req.nested})}} {\memgloref{}}|memjustarg}{121} -\glossaryentry{expr.compound@ {\memgloterm{expr.compound}}{\memglodesc{(\ref {expr.compound})}} {\memgloref{}}|memjustarg}{122} -\glossaryentry{expr.post@ {\memgloterm{expr.post}}{\memglodesc{(\ref {expr.post})}} {\memgloref{}}|memjustarg}{122} -\glossaryentry{expr.post.general@ {\memgloterm{expr.post.general}}{\memglodesc{(\ref {expr.post.general})}} {\memgloref{}}|memjustarg}{122} -\glossaryentry{expr.sub@ {\memgloterm{expr.sub}}{\memglodesc{(\ref {expr.sub})}} {\memgloref{}}|memjustarg}{122} -\glossaryentry{expr.call@ {\memgloterm{expr.call}}{\memglodesc{(\ref {expr.call})}} {\memgloref{}}|memjustarg}{122} -\glossaryentry{expr.type.conv@ {\memgloterm{expr.type.conv}}{\memglodesc{(\ref {expr.type.conv})}} {\memgloref{}}|memjustarg}{124} -\glossaryentry{expr.ref@ {\memgloterm{expr.ref}}{\memglodesc{(\ref {expr.ref})}} {\memgloref{}}|memjustarg}{125} -\glossaryentry{expr.post.incr@ {\memgloterm{expr.post.incr}}{\memglodesc{(\ref {expr.post.incr})}} {\memgloref{}}|memjustarg}{126} -\glossaryentry{expr.dynamic.cast@ {\memgloterm{expr.dynamic.cast}}{\memglodesc{(\ref {expr.dynamic.cast})}} {\memgloref{}}|memjustarg}{126} -\glossaryentry{expr.typeid@ {\memgloterm{expr.typeid}}{\memglodesc{(\ref {expr.typeid})}} {\memgloref{}}|memjustarg}{127} -\glossaryentry{expr.static.cast@ {\memgloterm{expr.static.cast}}{\memglodesc{(\ref {expr.static.cast})}} {\memgloref{}}|memjustarg}{128} -\glossaryentry{expr.reinterpret.cast@ {\memgloterm{expr.reinterpret.cast}}{\memglodesc{(\ref {expr.reinterpret.cast})}} {\memgloref{}}|memjustarg}{130} -\glossaryentry{expr.const.cast@ {\memgloterm{expr.const.cast}}{\memglodesc{(\ref {expr.const.cast})}} {\memgloref{}}|memjustarg}{131} -\glossaryentry{expr.unary@ {\memgloterm{expr.unary}}{\memglodesc{(\ref {expr.unary})}} {\memgloref{}}|memjustarg}{132} -\glossaryentry{expr.unary.general@ {\memgloterm{expr.unary.general}}{\memglodesc{(\ref {expr.unary.general})}} {\memgloref{}}|memjustarg}{132} -\glossaryentry{expr.unary.op@ {\memgloterm{expr.unary.op}}{\memglodesc{(\ref {expr.unary.op})}} {\memgloref{}}|memjustarg}{133} -\glossaryentry{expr.pre.incr@ {\memgloterm{expr.pre.incr}}{\memglodesc{(\ref {expr.pre.incr})}} {\memgloref{}}|memjustarg}{134} -\glossaryentry{expr.await@ {\memgloterm{expr.await}}{\memglodesc{(\ref {expr.await})}} {\memgloref{}}|memjustarg}{134} -\glossaryentry{expr.sizeof@ {\memgloterm{expr.sizeof}}{\memglodesc{(\ref {expr.sizeof})}} {\memgloref{}}|memjustarg}{136} -\glossaryentry{expr.alignof@ {\memgloterm{expr.alignof}}{\memglodesc{(\ref {expr.alignof})}} {\memgloref{}}|memjustarg}{136} -\glossaryentry{expr.unary.noexcept@ {\memgloterm{expr.unary.noexcept}}{\memglodesc{(\ref {expr.unary.noexcept})}} {\memgloref{}}|memjustarg}{137} -\glossaryentry{expr.new@ {\memgloterm{expr.new}}{\memglodesc{(\ref {expr.new})}} {\memgloref{}}|memjustarg}{137} -\glossaryentry{expr.delete@ {\memgloterm{expr.delete}}{\memglodesc{(\ref {expr.delete})}} {\memgloref{}}|memjustarg}{141} -\glossaryentry{expr.cast@ {\memgloterm{expr.cast}}{\memglodesc{(\ref {expr.cast})}} {\memgloref{}}|memjustarg}{143} -\glossaryentry{expr.mptr.oper@ {\memgloterm{expr.mptr.oper}}{\memglodesc{(\ref {expr.mptr.oper})}} {\memgloref{}}|memjustarg}{144} -\glossaryentry{expr.mul@ {\memgloterm{expr.mul}}{\memglodesc{(\ref {expr.mul})}} {\memgloref{}}|memjustarg}{145} -\glossaryentry{expr.add@ {\memgloterm{expr.add}}{\memglodesc{(\ref {expr.add})}} {\memgloref{}}|memjustarg}{145} -\glossaryentry{expr.shift@ {\memgloterm{expr.shift}}{\memglodesc{(\ref {expr.shift})}} {\memgloref{}}|memjustarg}{146} -\glossaryentry{expr.spaceship@ {\memgloterm{expr.spaceship}}{\memglodesc{(\ref {expr.spaceship})}} {\memgloref{}}|memjustarg}{147} -\glossaryentry{expr.rel@ {\memgloterm{expr.rel}}{\memglodesc{(\ref {expr.rel})}} {\memgloref{}}|memjustarg}{147} -\glossaryentry{expr.eq@ {\memgloterm{expr.eq}}{\memglodesc{(\ref {expr.eq})}} {\memgloref{}}|memjustarg}{148} -\glossaryentry{expr.bit.and@ {\memgloterm{expr.bit.and}}{\memglodesc{(\ref {expr.bit.and})}} {\memgloref{}}|memjustarg}{149} -\glossaryentry{expr.xor@ {\memgloterm{expr.xor}}{\memglodesc{(\ref {expr.xor})}} {\memgloref{}}|memjustarg}{149} -\glossaryentry{expr.or@ {\memgloterm{expr.or}}{\memglodesc{(\ref {expr.or})}} {\memgloref{}}|memjustarg}{150} -\glossaryentry{expr.log.and@ {\memgloterm{expr.log.and}}{\memglodesc{(\ref {expr.log.and})}} {\memgloref{}}|memjustarg}{150} -\glossaryentry{expr.log.or@ {\memgloterm{expr.log.or}}{\memglodesc{(\ref {expr.log.or})}} {\memgloref{}}|memjustarg}{150} -\glossaryentry{expr.cond@ {\memgloterm{expr.cond}}{\memglodesc{(\ref {expr.cond})}} {\memgloref{}}|memjustarg}{150} -\glossaryentry{expr.yield@ {\memgloterm{expr.yield}}{\memglodesc{(\ref {expr.yield})}} {\memgloref{}}|memjustarg}{152} -\glossaryentry{expr.throw@ {\memgloterm{expr.throw}}{\memglodesc{(\ref {expr.throw})}} {\memgloref{}}|memjustarg}{152} -\glossaryentry{expr.ass@ {\memgloterm{expr.ass}}{\memglodesc{(\ref {expr.ass})}} {\memgloref{}}|memjustarg}{153} -\glossaryentry{expr.comma@ {\memgloterm{expr.comma}}{\memglodesc{(\ref {expr.comma})}} {\memgloref{}}|memjustarg}{154} -\glossaryentry{expr.const@ {\memgloterm{expr.const}}{\memglodesc{(\ref {expr.const})}} {\memgloref{}}|memjustarg}{154} -\glossaryentry{stmt.stmt@ {\memgloterm{stmt.stmt}}{\memglodesc{(\ref {stmt.stmt})}} {\memgloref{}}|memjustarg}{163} -\glossaryentry{stmt.pre@ {\memgloterm{stmt.pre}}{\memglodesc{(\ref {stmt.pre})}} {\memgloref{}}|memjustarg}{163} -\glossaryentry{stmt.label@ {\memgloterm{stmt.label}}{\memglodesc{(\ref {stmt.label})}} {\memgloref{}}|memjustarg}{164} -\glossaryentry{stmt.expr@ {\memgloterm{stmt.expr}}{\memglodesc{(\ref {stmt.expr})}} {\memgloref{}}|memjustarg}{164} -\glossaryentry{stmt.block@ {\memgloterm{stmt.block}}{\memglodesc{(\ref {stmt.block})}} {\memgloref{}}|memjustarg}{164} -\glossaryentry{stmt.select@ {\memgloterm{stmt.select}}{\memglodesc{(\ref {stmt.select})}} {\memgloref{}}|memjustarg}{164} -\glossaryentry{stmt.select.general@ {\memgloterm{stmt.select.general}}{\memglodesc{(\ref {stmt.select.general})}} {\memgloref{}}|memjustarg}{164} -\glossaryentry{stmt.if@ {\memgloterm{stmt.if}}{\memglodesc{(\ref {stmt.if})}} {\memgloref{}}|memjustarg}{165} -\glossaryentry{stmt.switch@ {\memgloterm{stmt.switch}}{\memglodesc{(\ref {stmt.switch})}} {\memgloref{}}|memjustarg}{166} -\glossaryentry{stmt.iter@ {\memgloterm{stmt.iter}}{\memglodesc{(\ref {stmt.iter})}} {\memgloref{}}|memjustarg}{167} -\glossaryentry{stmt.iter.general@ {\memgloterm{stmt.iter.general}}{\memglodesc{(\ref {stmt.iter.general})}} {\memgloref{}}|memjustarg}{167} -\glossaryentry{stmt.while@ {\memgloterm{stmt.while}}{\memglodesc{(\ref {stmt.while})}} {\memgloref{}}|memjustarg}{167} -\glossaryentry{stmt.do@ {\memgloterm{stmt.do}}{\memglodesc{(\ref {stmt.do})}} {\memgloref{}}|memjustarg}{168} -\glossaryentry{stmt.for@ {\memgloterm{stmt.for}}{\memglodesc{(\ref {stmt.for})}} {\memgloref{}}|memjustarg}{168} -\glossaryentry{stmt.ranged@ {\memgloterm{stmt.ranged}}{\memglodesc{(\ref {stmt.ranged})}} {\memgloref{}}|memjustarg}{168} -\glossaryentry{stmt.jump@ {\memgloterm{stmt.jump}}{\memglodesc{(\ref {stmt.jump})}} {\memgloref{}}|memjustarg}{169} -\glossaryentry{stmt.jump.general@ {\memgloterm{stmt.jump.general}}{\memglodesc{(\ref {stmt.jump.general})}} {\memgloref{}}|memjustarg}{169} -\glossaryentry{stmt.break@ {\memgloterm{stmt.break}}{\memglodesc{(\ref {stmt.break})}} {\memgloref{}}|memjustarg}{169} -\glossaryentry{stmt.cont@ {\memgloterm{stmt.cont}}{\memglodesc{(\ref {stmt.cont})}} {\memgloref{}}|memjustarg}{169} -\glossaryentry{stmt.return@ {\memgloterm{stmt.return}}{\memglodesc{(\ref {stmt.return})}} {\memgloref{}}|memjustarg}{170} -\glossaryentry{stmt.return.coroutine@ {\memgloterm{stmt.return.coroutine}}{\memglodesc{(\ref {stmt.return.coroutine})}} {\memgloref{}}|memjustarg}{170} -\glossaryentry{stmt.goto@ {\memgloterm{stmt.goto}}{\memglodesc{(\ref {stmt.goto})}} {\memgloref{}}|memjustarg}{171} -\glossaryentry{stmt.dcl@ {\memgloterm{stmt.dcl}}{\memglodesc{(\ref {stmt.dcl})}} {\memgloref{}}|memjustarg}{171} -\glossaryentry{stmt.ambig@ {\memgloterm{stmt.ambig}}{\memglodesc{(\ref {stmt.ambig})}} {\memgloref{}}|memjustarg}{172} -\glossaryentry{dcl.dcl@ {\memgloterm{dcl.dcl}}{\memglodesc{(\ref {dcl.dcl})}} {\memgloref{}}|memjustarg}{173} -\glossaryentry{dcl.pre@ {\memgloterm{dcl.pre}}{\memglodesc{(\ref {dcl.pre})}} {\memgloref{}}|memjustarg}{173} -\glossaryentry{dcl.spec@ {\memgloterm{dcl.spec}}{\memglodesc{(\ref {dcl.spec})}} {\memgloref{}}|memjustarg}{175} -\glossaryentry{dcl.spec.general@ {\memgloterm{dcl.spec.general}}{\memglodesc{(\ref {dcl.spec.general})}} {\memgloref{}}|memjustarg}{175} -\glossaryentry{dcl.stc@ {\memgloterm{dcl.stc}}{\memglodesc{(\ref {dcl.stc})}} {\memgloref{}}|memjustarg}{176} -\glossaryentry{dcl.fct.spec@ {\memgloterm{dcl.fct.spec}}{\memglodesc{(\ref {dcl.fct.spec})}} {\memgloref{}}|memjustarg}{178} -\glossaryentry{dcl.typedef@ {\memgloterm{dcl.typedef}}{\memglodesc{(\ref {dcl.typedef})}} {\memgloref{}}|memjustarg}{178} -\glossaryentry{dcl.friend@ {\memgloterm{dcl.friend}}{\memglodesc{(\ref {dcl.friend})}} {\memgloref{}}|memjustarg}{179} -\glossaryentry{dcl.constexpr@ {\memgloterm{dcl.constexpr}}{\memglodesc{(\ref {dcl.constexpr})}} {\memgloref{}}|memjustarg}{179} -\glossaryentry{dcl.constinit@ {\memgloterm{dcl.constinit}}{\memglodesc{(\ref {dcl.constinit})}} {\memgloref{}}|memjustarg}{181} -\glossaryentry{dcl.inline@ {\memgloterm{dcl.inline}}{\memglodesc{(\ref {dcl.inline})}} {\memgloref{}}|memjustarg}{181} -\glossaryentry{dcl.type@ {\memgloterm{dcl.type}}{\memglodesc{(\ref {dcl.type})}} {\memgloref{}}|memjustarg}{182} -\glossaryentry{dcl.type.general@ {\memgloterm{dcl.type.general}}{\memglodesc{(\ref {dcl.type.general})}} {\memgloref{}}|memjustarg}{182} -\glossaryentry{dcl.type.cv@ {\memgloterm{dcl.type.cv}}{\memglodesc{(\ref {dcl.type.cv})}} {\memgloref{}}|memjustarg}{183} -\glossaryentry{dcl.type.simple@ {\memgloterm{dcl.type.simple}}{\memglodesc{(\ref {dcl.type.simple})}} {\memgloref{}}|memjustarg}{184} -\glossaryentry{dcl.type.elab@ {\memgloterm{dcl.type.elab}}{\memglodesc{(\ref {dcl.type.elab})}} {\memgloref{}}|memjustarg}{184} -\glossaryentry{dcl.type.decltype@ {\memgloterm{dcl.type.decltype}}{\memglodesc{(\ref {dcl.type.decltype})}} {\memgloref{}}|memjustarg}{186} -\glossaryentry{dcl.spec.auto@ {\memgloterm{dcl.spec.auto}}{\memglodesc{(\ref {dcl.spec.auto})}} {\memgloref{}}|memjustarg}{187} -\glossaryentry{dcl.spec.auto.general@ {\memgloterm{dcl.spec.auto.general}}{\memglodesc{(\ref {dcl.spec.auto.general})}} {\memgloref{}}|memjustarg}{187} -\glossaryentry{dcl.type.auto.deduct@ {\memgloterm{dcl.type.auto.deduct}}{\memglodesc{(\ref {dcl.type.auto.deduct})}} {\memgloref{}}|memjustarg}{190} -\glossaryentry{dcl.type.class.deduct@ {\memgloterm{dcl.type.class.deduct}}{\memglodesc{(\ref {dcl.type.class.deduct})}} {\memgloref{}}|memjustarg}{191} -\glossaryentry{dcl.decl@ {\memgloterm{dcl.decl}}{\memglodesc{(\ref {dcl.decl})}} {\memgloref{}}|memjustarg}{192} -\glossaryentry{dcl.decl.general@ {\memgloterm{dcl.decl.general}}{\memglodesc{(\ref {dcl.decl.general})}} {\memgloref{}}|memjustarg}{192} -\glossaryentry{dcl.name@ {\memgloterm{dcl.name}}{\memglodesc{(\ref {dcl.name})}} {\memgloref{}}|memjustarg}{193} -\glossaryentry{dcl.ambig.res@ {\memgloterm{dcl.ambig.res}}{\memglodesc{(\ref {dcl.ambig.res})}} {\memgloref{}}|memjustarg}{194} -\glossaryentry{dcl.meaning@ {\memgloterm{dcl.meaning}}{\memglodesc{(\ref {dcl.meaning})}} {\memgloref{}}|memjustarg}{195} -\glossaryentry{dcl.meaning.general@ {\memgloterm{dcl.meaning.general}}{\memglodesc{(\ref {dcl.meaning.general})}} {\memgloref{}}|memjustarg}{195} -\glossaryentry{dcl.ptr@ {\memgloterm{dcl.ptr}}{\memglodesc{(\ref {dcl.ptr})}} {\memgloref{}}|memjustarg}{197} -\glossaryentry{dcl.ref@ {\memgloterm{dcl.ref}}{\memglodesc{(\ref {dcl.ref})}} {\memgloref{}}|memjustarg}{198} -\glossaryentry{dcl.mptr@ {\memgloterm{dcl.mptr}}{\memglodesc{(\ref {dcl.mptr})}} {\memgloref{}}|memjustarg}{199} -\glossaryentry{dcl.array@ {\memgloterm{dcl.array}}{\memglodesc{(\ref {dcl.array})}} {\memgloref{}}|memjustarg}{200} -\glossaryentry{dcl.fct@ {\memgloterm{dcl.fct}}{\memglodesc{(\ref {dcl.fct})}} {\memgloref{}}|memjustarg}{201} -\glossaryentry{dcl.fct.default@ {\memgloterm{dcl.fct.default}}{\memglodesc{(\ref {dcl.fct.default})}} {\memgloref{}}|memjustarg}{206} -\glossaryentry{dcl.init@ {\memgloterm{dcl.init}}{\memglodesc{(\ref {dcl.init})}} {\memgloref{}}|memjustarg}{209} -\glossaryentry{dcl.init.general@ {\memgloterm{dcl.init.general}}{\memglodesc{(\ref {dcl.init.general})}} {\memgloref{}}|memjustarg}{209} -\glossaryentry{dcl.init.aggr@ {\memgloterm{dcl.init.aggr}}{\memglodesc{(\ref {dcl.init.aggr})}} {\memgloref{}}|memjustarg}{213} -\glossaryentry{dcl.init.string@ {\memgloterm{dcl.init.string}}{\memglodesc{(\ref {dcl.init.string})}} {\memgloref{}}|memjustarg}{217} -\glossaryentry{dcl.init.ref@ {\memgloterm{dcl.init.ref}}{\memglodesc{(\ref {dcl.init.ref})}} {\memgloref{}}|memjustarg}{218} -\glossaryentry{dcl.init.list@ {\memgloterm{dcl.init.list}}{\memglodesc{(\ref {dcl.init.list})}} {\memgloref{}}|memjustarg}{220} -\glossaryentry{dcl.fct.def@ {\memgloterm{dcl.fct.def}}{\memglodesc{(\ref {dcl.fct.def})}} {\memgloref{}}|memjustarg}{225} -\glossaryentry{dcl.fct.def.general@ {\memgloterm{dcl.fct.def.general}}{\memglodesc{(\ref {dcl.fct.def.general})}} {\memgloref{}}|memjustarg}{225} -\glossaryentry{dcl.fct.def.default@ {\memgloterm{dcl.fct.def.default}}{\memglodesc{(\ref {dcl.fct.def.default})}} {\memgloref{}}|memjustarg}{226} -\glossaryentry{dcl.fct.def.delete@ {\memgloterm{dcl.fct.def.delete}}{\memglodesc{(\ref {dcl.fct.def.delete})}} {\memgloref{}}|memjustarg}{227} -\glossaryentry{dcl.fct.def.coroutine@ {\memgloterm{dcl.fct.def.coroutine}}{\memglodesc{(\ref {dcl.fct.def.coroutine})}} {\memgloref{}}|memjustarg}{228} -\glossaryentry{dcl.struct.bind@ {\memgloterm{dcl.struct.bind}}{\memglodesc{(\ref {dcl.struct.bind})}} {\memgloref{}}|memjustarg}{231} -\glossaryentry{enum@ {\memgloterm{enum}}{\memglodesc{(\ref {enum})}} {\memgloref{}}|memjustarg}{232} -\glossaryentry{dcl.enum@ {\memgloterm{dcl.enum}}{\memglodesc{(\ref {dcl.enum})}} {\memgloref{}}|memjustarg}{232} -\glossaryentry{enum.udecl@ {\memgloterm{enum.udecl}}{\memglodesc{(\ref {enum.udecl})}} {\memgloref{}}|memjustarg}{235} -\glossaryentry{basic.namespace@ {\memgloterm{basic.namespace}}{\memglodesc{(\ref {basic.namespace})}} {\memgloref{}}|memjustarg}{235} -\glossaryentry{basic.namespace.general@ {\memgloterm{basic.namespace.general}}{\memglodesc{(\ref {basic.namespace.general})}} {\memgloref{}}|memjustarg}{235} -\glossaryentry{namespace.def@ {\memgloterm{namespace.def}}{\memglodesc{(\ref {namespace.def})}} {\memgloref{}}|memjustarg}{236} -\glossaryentry{namespace.def.general@ {\memgloterm{namespace.def.general}}{\memglodesc{(\ref {namespace.def.general})}} {\memgloref{}}|memjustarg}{236} -\glossaryentry{namespace.unnamed@ {\memgloterm{namespace.unnamed}}{\memglodesc{(\ref {namespace.unnamed})}} {\memgloref{}}|memjustarg}{237} -\glossaryentry{namespace.alias@ {\memgloterm{namespace.alias}}{\memglodesc{(\ref {namespace.alias})}} {\memgloref{}}|memjustarg}{238} -\glossaryentry{namespace.udir@ {\memgloterm{namespace.udir}}{\memglodesc{(\ref {namespace.udir})}} {\memgloref{}}|memjustarg}{238} -\glossaryentry{namespace.udecl@ {\memgloterm{namespace.udecl}}{\memglodesc{(\ref {namespace.udecl})}} {\memgloref{}}|memjustarg}{240} -\glossaryentry{dcl.asm@ {\memgloterm{dcl.asm}}{\memglodesc{(\ref {dcl.asm})}} {\memgloref{}}|memjustarg}{245} -\glossaryentry{dcl.link@ {\memgloterm{dcl.link}}{\memglodesc{(\ref {dcl.link})}} {\memgloref{}}|memjustarg}{245} -\glossaryentry{dcl.attr@ {\memgloterm{dcl.attr}}{\memglodesc{(\ref {dcl.attr})}} {\memgloref{}}|memjustarg}{247} -\glossaryentry{dcl.attr.grammar@ {\memgloterm{dcl.attr.grammar}}{\memglodesc{(\ref {dcl.attr.grammar})}} {\memgloref{}}|memjustarg}{247} -\glossaryentry{dcl.align@ {\memgloterm{dcl.align}}{\memglodesc{(\ref {dcl.align})}} {\memgloref{}}|memjustarg}{249} -\glossaryentry{dcl.attr.assume@ {\memgloterm{dcl.attr.assume}}{\memglodesc{(\ref {dcl.attr.assume})}} {\memgloref{}}|memjustarg}{250} -\glossaryentry{dcl.attr.depend@ {\memgloterm{dcl.attr.depend}}{\memglodesc{(\ref {dcl.attr.depend})}} {\memgloref{}}|memjustarg}{250} -\glossaryentry{dcl.attr.deprecated@ {\memgloterm{dcl.attr.deprecated}}{\memglodesc{(\ref {dcl.attr.deprecated})}} {\memgloref{}}|memjustarg}{251} -\glossaryentry{dcl.attr.fallthrough@ {\memgloterm{dcl.attr.fallthrough}}{\memglodesc{(\ref {dcl.attr.fallthrough})}} {\memgloref{}}|memjustarg}{251} -\glossaryentry{dcl.attr.likelihood@ {\memgloterm{dcl.attr.likelihood}}{\memglodesc{(\ref {dcl.attr.likelihood})}} {\memgloref{}}|memjustarg}{252} -\glossaryentry{dcl.attr.unused@ {\memgloterm{dcl.attr.unused}}{\memglodesc{(\ref {dcl.attr.unused})}} {\memgloref{}}|memjustarg}{253} -\glossaryentry{dcl.attr.nodiscard@ {\memgloterm{dcl.attr.nodiscard}}{\memglodesc{(\ref {dcl.attr.nodiscard})}} {\memgloref{}}|memjustarg}{253} -\glossaryentry{dcl.attr.noreturn@ {\memgloterm{dcl.attr.noreturn}}{\memglodesc{(\ref {dcl.attr.noreturn})}} {\memgloref{}}|memjustarg}{254} -\glossaryentry{dcl.attr.nouniqueaddr@ {\memgloterm{dcl.attr.nouniqueaddr}}{\memglodesc{(\ref {dcl.attr.nouniqueaddr})}} {\memgloref{}}|memjustarg}{254} -\glossaryentry{module@ {\memgloterm{module}}{\memglodesc{(\ref {module})}} {\memgloref{}}|memjustarg}{256} -\glossaryentry{module.unit@ {\memgloterm{module.unit}}{\memglodesc{(\ref {module.unit})}} {\memgloref{}}|memjustarg}{256} -\glossaryentry{module.interface@ {\memgloterm{module.interface}}{\memglodesc{(\ref {module.interface})}} {\memgloref{}}|memjustarg}{257} -\glossaryentry{module.import@ {\memgloterm{module.import}}{\memglodesc{(\ref {module.import})}} {\memgloref{}}|memjustarg}{260} -\glossaryentry{module.global.frag@ {\memgloterm{module.global.frag}}{\memglodesc{(\ref {module.global.frag})}} {\memgloref{}}|memjustarg}{261} -\glossaryentry{module.private.frag@ {\memgloterm{module.private.frag}}{\memglodesc{(\ref {module.private.frag})}} {\memgloref{}}|memjustarg}{263} -\glossaryentry{module.context@ {\memgloterm{module.context}}{\memglodesc{(\ref {module.context})}} {\memgloref{}}|memjustarg}{264} -\glossaryentry{module.reach@ {\memgloterm{module.reach}}{\memglodesc{(\ref {module.reach})}} {\memgloref{}}|memjustarg}{265} -\glossaryentry{class@ {\memgloterm{class}}{\memglodesc{(\ref {class})}} {\memgloref{}}|memjustarg}{267} -\glossaryentry{class.pre@ {\memgloterm{class.pre}}{\memglodesc{(\ref {class.pre})}} {\memgloref{}}|memjustarg}{267} -\glossaryentry{class.prop@ {\memgloterm{class.prop}}{\memglodesc{(\ref {class.prop})}} {\memgloref{}}|memjustarg}{268} -\glossaryentry{class.name@ {\memgloterm{class.name}}{\memglodesc{(\ref {class.name})}} {\memgloref{}}|memjustarg}{269} -\glossaryentry{class.mem@ {\memgloterm{class.mem}}{\memglodesc{(\ref {class.mem})}} {\memgloref{}}|memjustarg}{271} -\glossaryentry{class.mem.general@ {\memgloterm{class.mem.general}}{\memglodesc{(\ref {class.mem.general})}} {\memgloref{}}|memjustarg}{271} -\glossaryentry{class.mfct@ {\memgloterm{class.mfct}}{\memglodesc{(\ref {class.mfct})}} {\memgloref{}}|memjustarg}{274} -\glossaryentry{class.mfct.non.static@ {\memgloterm{class.mfct.non.static}}{\memglodesc{(\ref {class.mfct.non.static})}} {\memgloref{}}|memjustarg}{275} -\glossaryentry{special@ {\memgloterm{special}}{\memglodesc{(\ref {special})}} {\memgloref{}}|memjustarg}{276} -\glossaryentry{class.ctor@ {\memgloterm{class.ctor}}{\memglodesc{(\ref {class.ctor})}} {\memgloref{}}|memjustarg}{277} -\glossaryentry{class.ctor.general@ {\memgloterm{class.ctor.general}}{\memglodesc{(\ref {class.ctor.general})}} {\memgloref{}}|memjustarg}{277} -\glossaryentry{class.default.ctor@ {\memgloterm{class.default.ctor}}{\memglodesc{(\ref {class.default.ctor})}} {\memgloref{}}|memjustarg}{277} -\glossaryentry{class.copy.ctor@ {\memgloterm{class.copy.ctor}}{\memglodesc{(\ref {class.copy.ctor})}} {\memgloref{}}|memjustarg}{278} -\glossaryentry{class.copy.assign@ {\memgloterm{class.copy.assign}}{\memglodesc{(\ref {class.copy.assign})}} {\memgloref{}}|memjustarg}{281} -\glossaryentry{class.dtor@ {\memgloterm{class.dtor}}{\memglodesc{(\ref {class.dtor})}} {\memgloref{}}|memjustarg}{283} -\glossaryentry{class.conv@ {\memgloterm{class.conv}}{\memglodesc{(\ref {class.conv})}} {\memgloref{}}|memjustarg}{286} -\glossaryentry{class.conv.general@ {\memgloterm{class.conv.general}}{\memglodesc{(\ref {class.conv.general})}} {\memgloref{}}|memjustarg}{286} -\glossaryentry{class.conv.ctor@ {\memgloterm{class.conv.ctor}}{\memglodesc{(\ref {class.conv.ctor})}} {\memgloref{}}|memjustarg}{286} -\glossaryentry{class.conv.fct@ {\memgloterm{class.conv.fct}}{\memglodesc{(\ref {class.conv.fct})}} {\memgloref{}}|memjustarg}{287} -\glossaryentry{class.static@ {\memgloterm{class.static}}{\memglodesc{(\ref {class.static})}} {\memgloref{}}|memjustarg}{289} -\glossaryentry{class.static.general@ {\memgloterm{class.static.general}}{\memglodesc{(\ref {class.static.general})}} {\memgloref{}}|memjustarg}{289} -\glossaryentry{class.static.mfct@ {\memgloterm{class.static.mfct}}{\memglodesc{(\ref {class.static.mfct})}} {\memgloref{}}|memjustarg}{289} -\glossaryentry{class.static.data@ {\memgloterm{class.static.data}}{\memglodesc{(\ref {class.static.data})}} {\memgloref{}}|memjustarg}{289} -\glossaryentry{class.bit@ {\memgloterm{class.bit}}{\memglodesc{(\ref {class.bit})}} {\memgloref{}}|memjustarg}{290} -\glossaryentry{class.free@ {\memgloterm{class.free}}{\memglodesc{(\ref {class.free})}} {\memgloref{}}|memjustarg}{291} -\glossaryentry{class.nest@ {\memgloterm{class.nest}}{\memglodesc{(\ref {class.nest})}} {\memgloref{}}|memjustarg}{292} -\glossaryentry{class.union@ {\memgloterm{class.union}}{\memglodesc{(\ref {class.union})}} {\memgloref{}}|memjustarg}{293} -\glossaryentry{class.union.general@ {\memgloterm{class.union.general}}{\memglodesc{(\ref {class.union.general})}} {\memgloref{}}|memjustarg}{293} -\glossaryentry{class.union.anon@ {\memgloterm{class.union.anon}}{\memglodesc{(\ref {class.union.anon})}} {\memgloref{}}|memjustarg}{294} -\glossaryentry{class.local@ {\memgloterm{class.local}}{\memglodesc{(\ref {class.local})}} {\memgloref{}}|memjustarg}{295} -\glossaryentry{class.derived@ {\memgloterm{class.derived}}{\memglodesc{(\ref {class.derived})}} {\memgloref{}}|memjustarg}{296} -\glossaryentry{class.derived.general@ {\memgloterm{class.derived.general}}{\memglodesc{(\ref {class.derived.general})}} {\memgloref{}}|memjustarg}{296} -\glossaryentry{class.mi@ {\memgloterm{class.mi}}{\memglodesc{(\ref {class.mi})}} {\memgloref{}}|memjustarg}{297} -\glossaryentry{class.virtual@ {\memgloterm{class.virtual}}{\memglodesc{(\ref {class.virtual})}} {\memgloref{}}|memjustarg}{299} -\glossaryentry{class.abstract@ {\memgloterm{class.abstract}}{\memglodesc{(\ref {class.abstract})}} {\memgloref{}}|memjustarg}{303} -\glossaryentry{class.access@ {\memgloterm{class.access}}{\memglodesc{(\ref {class.access})}} {\memgloref{}}|memjustarg}{304} -\glossaryentry{class.access.general@ {\memgloterm{class.access.general}}{\memglodesc{(\ref {class.access.general})}} {\memgloref{}}|memjustarg}{304} -\glossaryentry{class.access.spec@ {\memgloterm{class.access.spec}}{\memglodesc{(\ref {class.access.spec})}} {\memgloref{}}|memjustarg}{306} -\glossaryentry{class.access.base@ {\memgloterm{class.access.base}}{\memglodesc{(\ref {class.access.base})}} {\memgloref{}}|memjustarg}{307} -\glossaryentry{class.friend@ {\memgloterm{class.friend}}{\memglodesc{(\ref {class.friend})}} {\memgloref{}}|memjustarg}{309} -\glossaryentry{class.protected@ {\memgloterm{class.protected}}{\memglodesc{(\ref {class.protected})}} {\memgloref{}}|memjustarg}{312} -\glossaryentry{class.access.virt@ {\memgloterm{class.access.virt}}{\memglodesc{(\ref {class.access.virt})}} {\memgloref{}}|memjustarg}{313} -\glossaryentry{class.paths@ {\memgloterm{class.paths}}{\memglodesc{(\ref {class.paths})}} {\memgloref{}}|memjustarg}{313} -\glossaryentry{class.access.nest@ {\memgloterm{class.access.nest}}{\memglodesc{(\ref {class.access.nest})}} {\memgloref{}}|memjustarg}{313} -\glossaryentry{class.init@ {\memgloterm{class.init}}{\memglodesc{(\ref {class.init})}} {\memgloref{}}|memjustarg}{314} -\glossaryentry{class.init.general@ {\memgloterm{class.init.general}}{\memglodesc{(\ref {class.init.general})}} {\memgloref{}}|memjustarg}{314} -\glossaryentry{class.expl.init@ {\memgloterm{class.expl.init}}{\memglodesc{(\ref {class.expl.init})}} {\memgloref{}}|memjustarg}{314} -\glossaryentry{class.base.init@ {\memgloterm{class.base.init}}{\memglodesc{(\ref {class.base.init})}} {\memgloref{}}|memjustarg}{315} -\glossaryentry{class.inhctor.init@ {\memgloterm{class.inhctor.init}}{\memglodesc{(\ref {class.inhctor.init})}} {\memgloref{}}|memjustarg}{319} -\glossaryentry{class.cdtor@ {\memgloterm{class.cdtor}}{\memglodesc{(\ref {class.cdtor})}} {\memgloref{}}|memjustarg}{320} -\glossaryentry{class.copy.elision@ {\memgloterm{class.copy.elision}}{\memglodesc{(\ref {class.copy.elision})}} {\memgloref{}}|memjustarg}{323} -\glossaryentry{class.compare@ {\memgloterm{class.compare}}{\memglodesc{(\ref {class.compare})}} {\memgloref{}}|memjustarg}{325} -\glossaryentry{class.compare.default@ {\memgloterm{class.compare.default}}{\memglodesc{(\ref {class.compare.default})}} {\memgloref{}}|memjustarg}{325} -\glossaryentry{class.eq@ {\memgloterm{class.eq}}{\memglodesc{(\ref {class.eq})}} {\memgloref{}}|memjustarg}{326} -\glossaryentry{class.spaceship@ {\memgloterm{class.spaceship}}{\memglodesc{(\ref {class.spaceship})}} {\memgloref{}}|memjustarg}{327} -\glossaryentry{class.compare.secondary@ {\memgloterm{class.compare.secondary}}{\memglodesc{(\ref {class.compare.secondary})}} {\memgloref{}}|memjustarg}{327} -\glossaryentry{over@ {\memgloterm{over}}{\memglodesc{(\ref {over})}} {\memgloref{}}|memjustarg}{329} -\glossaryentry{over.pre@ {\memgloterm{over.pre}}{\memglodesc{(\ref {over.pre})}} {\memgloref{}}|memjustarg}{329} -\glossaryentry{over.match@ {\memgloterm{over.match}}{\memglodesc{(\ref {over.match})}} {\memgloref{}}|memjustarg}{329} -\glossaryentry{over.match.general@ {\memgloterm{over.match.general}}{\memglodesc{(\ref {over.match.general})}} {\memgloref{}}|memjustarg}{329} -\glossaryentry{over.match.funcs@ {\memgloterm{over.match.funcs}}{\memglodesc{(\ref {over.match.funcs})}} {\memgloref{}}|memjustarg}{330} -\glossaryentry{over.match.funcs.general@ {\memgloterm{over.match.funcs.general}}{\memglodesc{(\ref {over.match.funcs.general})}} {\memgloref{}}|memjustarg}{330} -\glossaryentry{over.match.call@ {\memgloterm{over.match.call}}{\memglodesc{(\ref {over.match.call})}} {\memgloref{}}|memjustarg}{331} -\glossaryentry{over.match.call.general@ {\memgloterm{over.match.call.general}}{\memglodesc{(\ref {over.match.call.general})}} {\memgloref{}}|memjustarg}{331} -\glossaryentry{over.call.func@ {\memgloterm{over.call.func}}{\memglodesc{(\ref {over.call.func})}} {\memgloref{}}|memjustarg}{332} -\glossaryentry{over.call.object@ {\memgloterm{over.call.object}}{\memglodesc{(\ref {over.call.object})}} {\memgloref{}}|memjustarg}{333} -\glossaryentry{over.match.oper@ {\memgloterm{over.match.oper}}{\memglodesc{(\ref {over.match.oper})}} {\memgloref{}}|memjustarg}{334} -\glossaryentry{over.match.ctor@ {\memgloterm{over.match.ctor}}{\memglodesc{(\ref {over.match.ctor})}} {\memgloref{}}|memjustarg}{337} -\glossaryentry{over.match.copy@ {\memgloterm{over.match.copy}}{\memglodesc{(\ref {over.match.copy})}} {\memgloref{}}|memjustarg}{337} -\glossaryentry{over.match.conv@ {\memgloterm{over.match.conv}}{\memglodesc{(\ref {over.match.conv})}} {\memgloref{}}|memjustarg}{337} -\glossaryentry{over.match.ref@ {\memgloterm{over.match.ref}}{\memglodesc{(\ref {over.match.ref})}} {\memgloref{}}|memjustarg}{338} -\glossaryentry{over.match.list@ {\memgloterm{over.match.list}}{\memglodesc{(\ref {over.match.list})}} {\memgloref{}}|memjustarg}{338} -\glossaryentry{over.match.class.deduct@ {\memgloterm{over.match.class.deduct}}{\memglodesc{(\ref {over.match.class.deduct})}} {\memgloref{}}|memjustarg}{338} -\glossaryentry{over.match.viable@ {\memgloterm{over.match.viable}}{\memglodesc{(\ref {over.match.viable})}} {\memgloref{}}|memjustarg}{343} -\glossaryentry{over.match.best@ {\memgloterm{over.match.best}}{\memglodesc{(\ref {over.match.best})}} {\memgloref{}}|memjustarg}{343} -\glossaryentry{over.match.best.general@ {\memgloterm{over.match.best.general}}{\memglodesc{(\ref {over.match.best.general})}} {\memgloref{}}|memjustarg}{343} -\glossaryentry{over.best.ics@ {\memgloterm{over.best.ics}}{\memglodesc{(\ref {over.best.ics})}} {\memgloref{}}|memjustarg}{346} -\glossaryentry{over.best.ics.general@ {\memgloterm{over.best.ics.general}}{\memglodesc{(\ref {over.best.ics.general})}} {\memgloref{}}|memjustarg}{346} -\glossaryentry{over.ics.scs@ {\memgloterm{over.ics.scs}}{\memglodesc{(\ref {over.ics.scs})}} {\memgloref{}}|memjustarg}{348} -\glossaryentry{over.ics.user@ {\memgloterm{over.ics.user}}{\memglodesc{(\ref {over.ics.user})}} {\memgloref{}}|memjustarg}{348} -\glossaryentry{over.ics.ellipsis@ {\memgloterm{over.ics.ellipsis}}{\memglodesc{(\ref {over.ics.ellipsis})}} {\memgloref{}}|memjustarg}{349} -\glossaryentry{over.ics.ref@ {\memgloterm{over.ics.ref}}{\memglodesc{(\ref {over.ics.ref})}} {\memgloref{}}|memjustarg}{349} -\glossaryentry{over.ics.list@ {\memgloterm{over.ics.list}}{\memglodesc{(\ref {over.ics.list})}} {\memgloref{}}|memjustarg}{349} -\glossaryentry{over.ics.rank@ {\memgloterm{over.ics.rank}}{\memglodesc{(\ref {over.ics.rank})}} {\memgloref{}}|memjustarg}{352} -\glossaryentry{over.over@ {\memgloterm{over.over}}{\memglodesc{(\ref {over.over})}} {\memgloref{}}|memjustarg}{355} -\glossaryentry{over.oper@ {\memgloterm{over.oper}}{\memglodesc{(\ref {over.oper})}} {\memgloref{}}|memjustarg}{356} -\glossaryentry{over.oper.general@ {\memgloterm{over.oper.general}}{\memglodesc{(\ref {over.oper.general})}} {\memgloref{}}|memjustarg}{356} -\glossaryentry{over.unary@ {\memgloterm{over.unary}}{\memglodesc{(\ref {over.unary})}} {\memgloref{}}|memjustarg}{358} -\glossaryentry{over.binary@ {\memgloterm{over.binary}}{\memglodesc{(\ref {over.binary})}} {\memgloref{}}|memjustarg}{358} -\glossaryentry{over.binary.general@ {\memgloterm{over.binary.general}}{\memglodesc{(\ref {over.binary.general})}} {\memgloref{}}|memjustarg}{358} -\glossaryentry{over.ass@ {\memgloterm{over.ass}}{\memglodesc{(\ref {over.ass})}} {\memgloref{}}|memjustarg}{358} -\glossaryentry{over.call@ {\memgloterm{over.call}}{\memglodesc{(\ref {over.call})}} {\memgloref{}}|memjustarg}{359} -\glossaryentry{over.sub@ {\memgloterm{over.sub}}{\memglodesc{(\ref {over.sub})}} {\memgloref{}}|memjustarg}{359} -\glossaryentry{over.ref@ {\memgloterm{over.ref}}{\memglodesc{(\ref {over.ref})}} {\memgloref{}}|memjustarg}{359} -\glossaryentry{over.inc@ {\memgloterm{over.inc}}{\memglodesc{(\ref {over.inc})}} {\memgloref{}}|memjustarg}{359} -\glossaryentry{over.built@ {\memgloterm{over.built}}{\memglodesc{(\ref {over.built})}} {\memgloref{}}|memjustarg}{360} -\glossaryentry{over.literal@ {\memgloterm{over.literal}}{\memglodesc{(\ref {over.literal})}} {\memgloref{}}|memjustarg}{362} -\glossaryentry{temp@ {\memgloterm{temp}}{\memglodesc{(\ref {temp})}} {\memgloref{}}|memjustarg}{364} -\glossaryentry{temp.pre@ {\memgloterm{temp.pre}}{\memglodesc{(\ref {temp.pre})}} {\memgloref{}}|memjustarg}{364} -\glossaryentry{temp.param@ {\memgloterm{temp.param}}{\memglodesc{(\ref {temp.param})}} {\memgloref{}}|memjustarg}{365} -\glossaryentry{temp.names@ {\memgloterm{temp.names}}{\memglodesc{(\ref {temp.names})}} {\memgloref{}}|memjustarg}{369} -\glossaryentry{temp.arg@ {\memgloterm{temp.arg}}{\memglodesc{(\ref {temp.arg})}} {\memgloref{}}|memjustarg}{372} -\glossaryentry{temp.arg.general@ {\memgloterm{temp.arg.general}}{\memglodesc{(\ref {temp.arg.general})}} {\memgloref{}}|memjustarg}{372} -\glossaryentry{temp.arg.type@ {\memgloterm{temp.arg.type}}{\memglodesc{(\ref {temp.arg.type})}} {\memgloref{}}|memjustarg}{374} -\glossaryentry{temp.arg.nontype@ {\memgloterm{temp.arg.nontype}}{\memglodesc{(\ref {temp.arg.nontype})}} {\memgloref{}}|memjustarg}{374} -\glossaryentry{temp.arg.template@ {\memgloterm{temp.arg.template}}{\memglodesc{(\ref {temp.arg.template})}} {\memgloref{}}|memjustarg}{376} -\glossaryentry{temp.constr@ {\memgloterm{temp.constr}}{\memglodesc{(\ref {temp.constr})}} {\memgloref{}}|memjustarg}{377} -\glossaryentry{temp.constr.general@ {\memgloterm{temp.constr.general}}{\memglodesc{(\ref {temp.constr.general})}} {\memgloref{}}|memjustarg}{377} -\glossaryentry{temp.constr.constr@ {\memgloterm{temp.constr.constr}}{\memglodesc{(\ref {temp.constr.constr})}} {\memgloref{}}|memjustarg}{377} -\glossaryentry{temp.constr.constr.general@ {\memgloterm{temp.constr.constr.general}}{\memglodesc{(\ref {temp.constr.constr.general})}} {\memgloref{}}|memjustarg}{377} -\glossaryentry{temp.constr.op@ {\memgloterm{temp.constr.op}}{\memglodesc{(\ref {temp.constr.op})}} {\memgloref{}}|memjustarg}{378} -\glossaryentry{temp.constr.atomic@ {\memgloterm{temp.constr.atomic}}{\memglodesc{(\ref {temp.constr.atomic})}} {\memgloref{}}|memjustarg}{379} -\glossaryentry{temp.constr.decl@ {\memgloterm{temp.constr.decl}}{\memglodesc{(\ref {temp.constr.decl})}} {\memgloref{}}|memjustarg}{380} -\glossaryentry{temp.constr.normal@ {\memgloterm{temp.constr.normal}}{\memglodesc{(\ref {temp.constr.normal})}} {\memgloref{}}|memjustarg}{381} -\glossaryentry{temp.constr.order@ {\memgloterm{temp.constr.order}}{\memglodesc{(\ref {temp.constr.order})}} {\memgloref{}}|memjustarg}{382} -\glossaryentry{temp.type@ {\memgloterm{temp.type}}{\memglodesc{(\ref {temp.type})}} {\memgloref{}}|memjustarg}{382} -\glossaryentry{temp.decls@ {\memgloterm{temp.decls}}{\memglodesc{(\ref {temp.decls})}} {\memgloref{}}|memjustarg}{383} -\glossaryentry{temp.decls.general@ {\memgloterm{temp.decls.general}}{\memglodesc{(\ref {temp.decls.general})}} {\memgloref{}}|memjustarg}{383} -\glossaryentry{temp.class@ {\memgloterm{temp.class}}{\memglodesc{(\ref {temp.class})}} {\memgloref{}}|memjustarg}{384} -\glossaryentry{temp.class.general@ {\memgloterm{temp.class.general}}{\memglodesc{(\ref {temp.class.general})}} {\memgloref{}}|memjustarg}{384} -\glossaryentry{temp.mem.func@ {\memgloterm{temp.mem.func}}{\memglodesc{(\ref {temp.mem.func})}} {\memgloref{}}|memjustarg}{385} -\glossaryentry{temp.deduct.guide@ {\memgloterm{temp.deduct.guide}}{\memglodesc{(\ref {temp.deduct.guide})}} {\memgloref{}}|memjustarg}{385} -\glossaryentry{temp.mem.class@ {\memgloterm{temp.mem.class}}{\memglodesc{(\ref {temp.mem.class})}} {\memgloref{}}|memjustarg}{386} -\glossaryentry{temp.static@ {\memgloterm{temp.static}}{\memglodesc{(\ref {temp.static})}} {\memgloref{}}|memjustarg}{386} -\glossaryentry{temp.mem.enum@ {\memgloterm{temp.mem.enum}}{\memglodesc{(\ref {temp.mem.enum})}} {\memgloref{}}|memjustarg}{387} -\glossaryentry{temp.mem@ {\memgloterm{temp.mem}}{\memglodesc{(\ref {temp.mem})}} {\memgloref{}}|memjustarg}{387} -\glossaryentry{temp.variadic@ {\memgloterm{temp.variadic}}{\memglodesc{(\ref {temp.variadic})}} {\memgloref{}}|memjustarg}{388} -\glossaryentry{temp.friend@ {\memgloterm{temp.friend}}{\memglodesc{(\ref {temp.friend})}} {\memgloref{}}|memjustarg}{391} -\glossaryentry{temp.spec.partial@ {\memgloterm{temp.spec.partial}}{\memglodesc{(\ref {temp.spec.partial})}} {\memgloref{}}|memjustarg}{393} -\glossaryentry{temp.spec.partial.general@ {\memgloterm{temp.spec.partial.general}}{\memglodesc{(\ref {temp.spec.partial.general})}} {\memgloref{}}|memjustarg}{393} -\glossaryentry{temp.spec.partial.match@ {\memgloterm{temp.spec.partial.match}}{\memglodesc{(\ref {temp.spec.partial.match})}} {\memgloref{}}|memjustarg}{395} -\glossaryentry{temp.spec.partial.order@ {\memgloterm{temp.spec.partial.order}}{\memglodesc{(\ref {temp.spec.partial.order})}} {\memgloref{}}|memjustarg}{396} -\glossaryentry{temp.spec.partial.member@ {\memgloterm{temp.spec.partial.member}}{\memglodesc{(\ref {temp.spec.partial.member})}} {\memgloref{}}|memjustarg}{396} -\glossaryentry{temp.fct@ {\memgloterm{temp.fct}}{\memglodesc{(\ref {temp.fct})}} {\memgloref{}}|memjustarg}{397} -\glossaryentry{temp.fct.general@ {\memgloterm{temp.fct.general}}{\memglodesc{(\ref {temp.fct.general})}} {\memgloref{}}|memjustarg}{397} -\glossaryentry{temp.over.link@ {\memgloterm{temp.over.link}}{\memglodesc{(\ref {temp.over.link})}} {\memgloref{}}|memjustarg}{398} -\glossaryentry{temp.func.order@ {\memgloterm{temp.func.order}}{\memglodesc{(\ref {temp.func.order})}} {\memgloref{}}|memjustarg}{400} -\glossaryentry{temp.alias@ {\memgloterm{temp.alias}}{\memglodesc{(\ref {temp.alias})}} {\memgloref{}}|memjustarg}{403} -\glossaryentry{temp.concept@ {\memgloterm{temp.concept}}{\memglodesc{(\ref {temp.concept})}} {\memgloref{}}|memjustarg}{404} -\glossaryentry{temp.res@ {\memgloterm{temp.res}}{\memglodesc{(\ref {temp.res})}} {\memgloref{}}|memjustarg}{404} -\glossaryentry{temp.res.general@ {\memgloterm{temp.res.general}}{\memglodesc{(\ref {temp.res.general})}} {\memgloref{}}|memjustarg}{404} -\glossaryentry{temp.local@ {\memgloterm{temp.local}}{\memglodesc{(\ref {temp.local})}} {\memgloref{}}|memjustarg}{408} -\glossaryentry{temp.dep@ {\memgloterm{temp.dep}}{\memglodesc{(\ref {temp.dep})}} {\memgloref{}}|memjustarg}{410} -\glossaryentry{temp.dep.general@ {\memgloterm{temp.dep.general}}{\memglodesc{(\ref {temp.dep.general})}} {\memgloref{}}|memjustarg}{410} -\glossaryentry{temp.dep.type@ {\memgloterm{temp.dep.type}}{\memglodesc{(\ref {temp.dep.type})}} {\memgloref{}}|memjustarg}{410} -\glossaryentry{temp.dep.expr@ {\memgloterm{temp.dep.expr}}{\memglodesc{(\ref {temp.dep.expr})}} {\memgloref{}}|memjustarg}{413} -\glossaryentry{temp.dep.constexpr@ {\memgloterm{temp.dep.constexpr}}{\memglodesc{(\ref {temp.dep.constexpr})}} {\memgloref{}}|memjustarg}{414} -\glossaryentry{temp.dep.temp@ {\memgloterm{temp.dep.temp}}{\memglodesc{(\ref {temp.dep.temp})}} {\memgloref{}}|memjustarg}{415} -\glossaryentry{temp.dep.res@ {\memgloterm{temp.dep.res}}{\memglodesc{(\ref {temp.dep.res})}} {\memgloref{}}|memjustarg}{415} -\glossaryentry{temp.point@ {\memgloterm{temp.point}}{\memglodesc{(\ref {temp.point})}} {\memgloref{}}|memjustarg}{415} -\glossaryentry{temp.dep.candidate@ {\memgloterm{temp.dep.candidate}}{\memglodesc{(\ref {temp.dep.candidate})}} {\memgloref{}}|memjustarg}{416} -\glossaryentry{temp.spec@ {\memgloterm{temp.spec}}{\memglodesc{(\ref {temp.spec})}} {\memgloref{}}|memjustarg}{418} -\glossaryentry{temp.spec.general@ {\memgloterm{temp.spec.general}}{\memglodesc{(\ref {temp.spec.general})}} {\memgloref{}}|memjustarg}{418} -\glossaryentry{temp.inst@ {\memgloterm{temp.inst}}{\memglodesc{(\ref {temp.inst})}} {\memgloref{}}|memjustarg}{420} -\glossaryentry{temp.explicit@ {\memgloterm{temp.explicit}}{\memglodesc{(\ref {temp.explicit})}} {\memgloref{}}|memjustarg}{424} -\glossaryentry{temp.expl.spec@ {\memgloterm{temp.expl.spec}}{\memglodesc{(\ref {temp.expl.spec})}} {\memgloref{}}|memjustarg}{426} -\glossaryentry{temp.fct.spec@ {\memgloterm{temp.fct.spec}}{\memglodesc{(\ref {temp.fct.spec})}} {\memgloref{}}|memjustarg}{431} -\glossaryentry{temp.fct.spec.general@ {\memgloterm{temp.fct.spec.general}}{\memglodesc{(\ref {temp.fct.spec.general})}} {\memgloref{}}|memjustarg}{431} -\glossaryentry{temp.arg.explicit@ {\memgloterm{temp.arg.explicit}}{\memglodesc{(\ref {temp.arg.explicit})}} {\memgloref{}}|memjustarg}{431} -\glossaryentry{temp.deduct@ {\memgloterm{temp.deduct}}{\memglodesc{(\ref {temp.deduct})}} {\memgloref{}}|memjustarg}{433} -\glossaryentry{temp.deduct.general@ {\memgloterm{temp.deduct.general}}{\memglodesc{(\ref {temp.deduct.general})}} {\memgloref{}}|memjustarg}{433} -\glossaryentry{temp.deduct.call@ {\memgloterm{temp.deduct.call}}{\memglodesc{(\ref {temp.deduct.call})}} {\memgloref{}}|memjustarg}{437} -\glossaryentry{temp.deduct.funcaddr@ {\memgloterm{temp.deduct.funcaddr}}{\memglodesc{(\ref {temp.deduct.funcaddr})}} {\memgloref{}}|memjustarg}{440} -\glossaryentry{temp.deduct.conv@ {\memgloterm{temp.deduct.conv}}{\memglodesc{(\ref {temp.deduct.conv})}} {\memgloref{}}|memjustarg}{441} -\glossaryentry{temp.deduct.partial@ {\memgloterm{temp.deduct.partial}}{\memglodesc{(\ref {temp.deduct.partial})}} {\memgloref{}}|memjustarg}{441} -\glossaryentry{temp.deduct.type@ {\memgloterm{temp.deduct.type}}{\memglodesc{(\ref {temp.deduct.type})}} {\memgloref{}}|memjustarg}{443} -\glossaryentry{temp.deduct.decl@ {\memgloterm{temp.deduct.decl}}{\memglodesc{(\ref {temp.deduct.decl})}} {\memgloref{}}|memjustarg}{449} -\glossaryentry{temp.over@ {\memgloterm{temp.over}}{\memglodesc{(\ref {temp.over})}} {\memgloref{}}|memjustarg}{449} -\glossaryentry{except@ {\memgloterm{except}}{\memglodesc{(\ref {except})}} {\memgloref{}}|memjustarg}{452} -\glossaryentry{except.pre@ {\memgloterm{except.pre}}{\memglodesc{(\ref {except.pre})}} {\memgloref{}}|memjustarg}{452} -\glossaryentry{except.throw@ {\memgloterm{except.throw}}{\memglodesc{(\ref {except.throw})}} {\memgloref{}}|memjustarg}{453} -\glossaryentry{except.ctor@ {\memgloterm{except.ctor}}{\memglodesc{(\ref {except.ctor})}} {\memgloref{}}|memjustarg}{454} -\glossaryentry{except.handle@ {\memgloterm{except.handle}}{\memglodesc{(\ref {except.handle})}} {\memgloref{}}|memjustarg}{455} -\glossaryentry{except.spec@ {\memgloterm{except.spec}}{\memglodesc{(\ref {except.spec})}} {\memgloref{}}|memjustarg}{457} -\glossaryentry{except.special@ {\memgloterm{except.special}}{\memglodesc{(\ref {except.special})}} {\memgloref{}}|memjustarg}{459} -\glossaryentry{except.special.general@ {\memgloterm{except.special.general}}{\memglodesc{(\ref {except.special.general})}} {\memgloref{}}|memjustarg}{459} -\glossaryentry{except.terminate@ {\memgloterm{except.terminate}}{\memglodesc{(\ref {except.terminate})}} {\memgloref{}}|memjustarg}{459} -\glossaryentry{except.uncaught@ {\memgloterm{except.uncaught}}{\memglodesc{(\ref {except.uncaught})}} {\memgloref{}}|memjustarg}{460} -\glossaryentry{cpp@ {\memgloterm{cpp}}{\memglodesc{(\ref {cpp})}} {\memgloref{}}|memjustarg}{461} -\glossaryentry{cpp.pre@ {\memgloterm{cpp.pre}}{\memglodesc{(\ref {cpp.pre})}} {\memgloref{}}|memjustarg}{461} -\glossaryentry{cpp.cond@ {\memgloterm{cpp.cond}}{\memglodesc{(\ref {cpp.cond})}} {\memgloref{}}|memjustarg}{463} -\glossaryentry{cpp.include@ {\memgloterm{cpp.include}}{\memglodesc{(\ref {cpp.include})}} {\memgloref{}}|memjustarg}{465} -\glossaryentry{cpp.module@ {\memgloterm{cpp.module}}{\memglodesc{(\ref {cpp.module})}} {\memgloref{}}|memjustarg}{466} -\glossaryentry{cpp.import@ {\memgloterm{cpp.import}}{\memglodesc{(\ref {cpp.import})}} {\memgloref{}}|memjustarg}{467} -\glossaryentry{cpp.replace@ {\memgloterm{cpp.replace}}{\memglodesc{(\ref {cpp.replace})}} {\memgloref{}}|memjustarg}{468} -\glossaryentry{cpp.replace.general@ {\memgloterm{cpp.replace.general}}{\memglodesc{(\ref {cpp.replace.general})}} {\memgloref{}}|memjustarg}{468} -\glossaryentry{cpp.subst@ {\memgloterm{cpp.subst}}{\memglodesc{(\ref {cpp.subst})}} {\memgloref{}}|memjustarg}{470} -\glossaryentry{cpp.stringize@ {\memgloterm{cpp.stringize}}{\memglodesc{(\ref {cpp.stringize})}} {\memgloref{}}|memjustarg}{471} -\glossaryentry{cpp.concat@ {\memgloterm{cpp.concat}}{\memglodesc{(\ref {cpp.concat})}} {\memgloref{}}|memjustarg}{471} -\glossaryentry{cpp.rescan@ {\memgloterm{cpp.rescan}}{\memglodesc{(\ref {cpp.rescan})}} {\memgloref{}}|memjustarg}{473} -\glossaryentry{cpp.scope@ {\memgloterm{cpp.scope}}{\memglodesc{(\ref {cpp.scope})}} {\memgloref{}}|memjustarg}{473} -\glossaryentry{cpp.line@ {\memgloterm{cpp.line}}{\memglodesc{(\ref {cpp.line})}} {\memgloref{}}|memjustarg}{473} -\glossaryentry{cpp.error@ {\memgloterm{cpp.error}}{\memglodesc{(\ref {cpp.error})}} {\memgloref{}}|memjustarg}{474} -\glossaryentry{cpp.pragma@ {\memgloterm{cpp.pragma}}{\memglodesc{(\ref {cpp.pragma})}} {\memgloref{}}|memjustarg}{474} -\glossaryentry{cpp.null@ {\memgloterm{cpp.null}}{\memglodesc{(\ref {cpp.null})}} {\memgloref{}}|memjustarg}{474} -\glossaryentry{cpp.predefined@ {\memgloterm{cpp.predefined}}{\memglodesc{(\ref {cpp.predefined})}} {\memgloref{}}|memjustarg}{474} -\glossaryentry{cpp.pragma.op@ {\memgloterm{cpp.pragma.op}}{\memglodesc{(\ref {cpp.pragma.op})}} {\memgloref{}}|memjustarg}{477} -\glossaryentry{library@ {\memgloterm{library}}{\memglodesc{(\ref {library})}} {\memgloref{}}|memjustarg}{478} -\glossaryentry{library.general@ {\memgloterm{library.general}}{\memglodesc{(\ref {library.general})}} {\memgloref{}}|memjustarg}{478} -\glossaryentry{library.c@ {\memgloterm{library.c}}{\memglodesc{(\ref {library.c})}} {\memgloref{}}|memjustarg}{479} -\glossaryentry{description@ {\memgloterm{description}}{\memglodesc{(\ref {description})}} {\memgloref{}}|memjustarg}{479} -\glossaryentry{description.general@ {\memgloterm{description.general}}{\memglodesc{(\ref {description.general})}} {\memgloref{}}|memjustarg}{479} -\glossaryentry{structure@ {\memgloterm{structure}}{\memglodesc{(\ref {structure})}} {\memgloref{}}|memjustarg}{479} -\glossaryentry{structure.elements@ {\memgloterm{structure.elements}}{\memglodesc{(\ref {structure.elements})}} {\memgloref{}}|memjustarg}{479} -\glossaryentry{structure.summary@ {\memgloterm{structure.summary}}{\memglodesc{(\ref {structure.summary})}} {\memgloref{}}|memjustarg}{479} -\glossaryentry{structure.requirements@ {\memgloterm{structure.requirements}}{\memglodesc{(\ref {structure.requirements})}} {\memgloref{}}|memjustarg}{480} -\glossaryentry{structure.specifications@ {\memgloterm{structure.specifications}}{\memglodesc{(\ref {structure.specifications})}} {\memgloref{}}|memjustarg}{480} -\glossaryentry{structure.see.also@ {\memgloterm{structure.see.also}}{\memglodesc{(\ref {structure.see.also})}} {\memgloref{}}|memjustarg}{482} -\glossaryentry{conventions@ {\memgloterm{conventions}}{\memglodesc{(\ref {conventions})}} {\memgloref{}}|memjustarg}{482} -\glossaryentry{conventions.general@ {\memgloterm{conventions.general}}{\memglodesc{(\ref {conventions.general})}} {\memgloref{}}|memjustarg}{482} -\glossaryentry{expos.only.entity@ {\memgloterm{expos.only.entity}}{\memglodesc{(\ref {expos.only.entity})}} {\memgloref{}}|memjustarg}{482} -\glossaryentry{type.descriptions@ {\memgloterm{type.descriptions}}{\memglodesc{(\ref {type.descriptions})}} {\memgloref{}}|memjustarg}{482} -\glossaryentry{type.descriptions.general@ {\memgloterm{type.descriptions.general}}{\memglodesc{(\ref {type.descriptions.general})}} {\memgloref{}}|memjustarg}{482} -\glossaryentry{enumerated.types@ {\memgloterm{enumerated.types}}{\memglodesc{(\ref {enumerated.types})}} {\memgloref{}}|memjustarg}{483} -\glossaryentry{bitmask.types@ {\memgloterm{bitmask.types}}{\memglodesc{(\ref {bitmask.types})}} {\memgloref{}}|memjustarg}{483} -\glossaryentry{character.seq@ {\memgloterm{character.seq}}{\memglodesc{(\ref {character.seq})}} {\memgloref{}}|memjustarg}{484} -\glossaryentry{character.seq.general@ {\memgloterm{character.seq.general}}{\memglodesc{(\ref {character.seq.general})}} {\memgloref{}}|memjustarg}{484} -\glossaryentry{byte.strings@ {\memgloterm{byte.strings}}{\memglodesc{(\ref {byte.strings})}} {\memgloref{}}|memjustarg}{484} -\glossaryentry{multibyte.strings@ {\memgloterm{multibyte.strings}}{\memglodesc{(\ref {multibyte.strings})}} {\memgloref{}}|memjustarg}{484} -\glossaryentry{customization.point.object@ {\memgloterm{customization.point.object}}{\memglodesc{(\ref {customization.point.object})}} {\memgloref{}}|memjustarg}{485} -\glossaryentry{functions.within.classes@ {\memgloterm{functions.within.classes}}{\memglodesc{(\ref {functions.within.classes})}} {\memgloref{}}|memjustarg}{485} -\glossaryentry{objects.within.classes@ {\memgloterm{objects.within.classes}}{\memglodesc{(\ref {objects.within.classes})}} {\memgloref{}}|memjustarg}{485} -\glossaryentry{freestanding.item@ {\memgloterm{freestanding.item}}{\memglodesc{(\ref {freestanding.item})}} {\memgloref{}}|memjustarg}{485} -\glossaryentry{requirements@ {\memgloterm{requirements}}{\memglodesc{(\ref {requirements})}} {\memgloref{}}|memjustarg}{486} -\glossaryentry{requirements.general@ {\memgloterm{requirements.general}}{\memglodesc{(\ref {requirements.general})}} {\memgloref{}}|memjustarg}{486} -\glossaryentry{organization@ {\memgloterm{organization}}{\memglodesc{(\ref {organization})}} {\memgloref{}}|memjustarg}{486} -\glossaryentry{organization.general@ {\memgloterm{organization.general}}{\memglodesc{(\ref {organization.general})}} {\memgloref{}}|memjustarg}{486} -\glossaryentry{contents@ {\memgloterm{contents}}{\memglodesc{(\ref {contents})}} {\memgloref{}}|memjustarg}{486} -\glossaryentry{headers@ {\memgloterm{headers}}{\memglodesc{(\ref {headers})}} {\memgloref{}}|memjustarg}{487} -\glossaryentry{std.modules@ {\memgloterm{std.modules}}{\memglodesc{(\ref {std.modules})}} {\memgloref{}}|memjustarg}{488} -\glossaryentry{compliance@ {\memgloterm{compliance}}{\memglodesc{(\ref {compliance})}} {\memgloref{}}|memjustarg}{489} -\glossaryentry{using@ {\memgloterm{using}}{\memglodesc{(\ref {using})}} {\memgloref{}}|memjustarg}{489} -\glossaryentry{using.overview@ {\memgloterm{using.overview}}{\memglodesc{(\ref {using.overview})}} {\memgloref{}}|memjustarg}{489} -\glossaryentry{using.headers@ {\memgloterm{using.headers}}{\memglodesc{(\ref {using.headers})}} {\memgloref{}}|memjustarg}{489} -\glossaryentry{using.linkage@ {\memgloterm{using.linkage}}{\memglodesc{(\ref {using.linkage})}} {\memgloref{}}|memjustarg}{490} -\glossaryentry{utility.requirements@ {\memgloterm{utility.requirements}}{\memglodesc{(\ref {utility.requirements})}} {\memgloref{}}|memjustarg}{490} -\glossaryentry{utility.requirements.general@ {\memgloterm{utility.requirements.general}}{\memglodesc{(\ref {utility.requirements.general})}} {\memgloref{}}|memjustarg}{490} -\glossaryentry{utility.arg.requirements@ {\memgloterm{utility.arg.requirements}}{\memglodesc{(\ref {utility.arg.requirements})}} {\memgloref{}}|memjustarg}{490} -\glossaryentry{swappable.requirements@ {\memgloterm{swappable.requirements}}{\memglodesc{(\ref {swappable.requirements})}} {\memgloref{}}|memjustarg}{492} -\glossaryentry{nullablepointer.requirements@ {\memgloterm{nullablepointer.requirements}}{\memglodesc{(\ref {nullablepointer.requirements})}} {\memgloref{}}|memjustarg}{493} -\glossaryentry{hash.requirements@ {\memgloterm{hash.requirements}}{\memglodesc{(\ref {hash.requirements})}} {\memgloref{}}|memjustarg}{493} -\glossaryentry{allocator.requirements@ {\memgloterm{allocator.requirements}}{\memglodesc{(\ref {allocator.requirements})}} {\memgloref{}}|memjustarg}{494} -\glossaryentry{allocator.requirements.general@ {\memgloterm{allocator.requirements.general}}{\memglodesc{(\ref {allocator.requirements.general})}} {\memgloref{}}|memjustarg}{494} -\glossaryentry{allocator.requirements.completeness@ {\memgloterm{allocator.requirements.completeness}}{\memglodesc{(\ref {allocator.requirements.completeness})}} {\memgloref{}}|memjustarg}{499} -\glossaryentry{constraints@ {\memgloterm{constraints}}{\memglodesc{(\ref {constraints})}} {\memgloref{}}|memjustarg}{499} -\glossaryentry{constraints.overview@ {\memgloterm{constraints.overview}}{\memglodesc{(\ref {constraints.overview})}} {\memgloref{}}|memjustarg}{499} -\glossaryentry{namespace.constraints@ {\memgloterm{namespace.constraints}}{\memglodesc{(\ref {namespace.constraints})}} {\memgloref{}}|memjustarg}{499} -\glossaryentry{namespace.std@ {\memgloterm{namespace.std}}{\memglodesc{(\ref {namespace.std})}} {\memgloref{}}|memjustarg}{499} -\glossaryentry{namespace.posix@ {\memgloterm{namespace.posix}}{\memglodesc{(\ref {namespace.posix})}} {\memgloref{}}|memjustarg}{500} -\glossaryentry{namespace.future@ {\memgloterm{namespace.future}}{\memglodesc{(\ref {namespace.future})}} {\memgloref{}}|memjustarg}{500} -\glossaryentry{reserved.names@ {\memgloterm{reserved.names}}{\memglodesc{(\ref {reserved.names})}} {\memgloref{}}|memjustarg}{500} -\glossaryentry{reserved.names.general@ {\memgloterm{reserved.names.general}}{\memglodesc{(\ref {reserved.names.general})}} {\memgloref{}}|memjustarg}{500} -\glossaryentry{zombie.names@ {\memgloterm{zombie.names}}{\memglodesc{(\ref {zombie.names})}} {\memgloref{}}|memjustarg}{501} -\glossaryentry{macro.names@ {\memgloterm{macro.names}}{\memglodesc{(\ref {macro.names})}} {\memgloref{}}|memjustarg}{502} -\glossaryentry{extern.names@ {\memgloterm{extern.names}}{\memglodesc{(\ref {extern.names})}} {\memgloref{}}|memjustarg}{502} -\glossaryentry{extern.types@ {\memgloterm{extern.types}}{\memglodesc{(\ref {extern.types})}} {\memgloref{}}|memjustarg}{502} -\glossaryentry{usrlit.suffix@ {\memgloterm{usrlit.suffix}}{\memglodesc{(\ref {usrlit.suffix})}} {\memgloref{}}|memjustarg}{502} -\glossaryentry{alt.headers@ {\memgloterm{alt.headers}}{\memglodesc{(\ref {alt.headers})}} {\memgloref{}}|memjustarg}{502} -\glossaryentry{derived.classes@ {\memgloterm{derived.classes}}{\memglodesc{(\ref {derived.classes})}} {\memgloref{}}|memjustarg}{503} -\glossaryentry{replacement.functions@ {\memgloterm{replacement.functions}}{\memglodesc{(\ref {replacement.functions})}} {\memgloref{}}|memjustarg}{503} -\glossaryentry{handler.functions@ {\memgloterm{handler.functions}}{\memglodesc{(\ref {handler.functions})}} {\memgloref{}}|memjustarg}{503} -\glossaryentry{res.on.functions@ {\memgloterm{res.on.functions}}{\memglodesc{(\ref {res.on.functions})}} {\memgloref{}}|memjustarg}{503} -\glossaryentry{res.on.arguments@ {\memgloterm{res.on.arguments}}{\memglodesc{(\ref {res.on.arguments})}} {\memgloref{}}|memjustarg}{504} -\glossaryentry{res.on.objects@ {\memgloterm{res.on.objects}}{\memglodesc{(\ref {res.on.objects})}} {\memgloref{}}|memjustarg}{504} -\glossaryentry{res.on.requirements@ {\memgloterm{res.on.requirements}}{\memglodesc{(\ref {res.on.requirements})}} {\memgloref{}}|memjustarg}{504} -\glossaryentry{conforming@ {\memgloterm{conforming}}{\memglodesc{(\ref {conforming})}} {\memgloref{}}|memjustarg}{504} -\glossaryentry{conforming.overview@ {\memgloterm{conforming.overview}}{\memglodesc{(\ref {conforming.overview})}} {\memgloref{}}|memjustarg}{504} -\glossaryentry{res.on.headers@ {\memgloterm{res.on.headers}}{\memglodesc{(\ref {res.on.headers})}} {\memgloref{}}|memjustarg}{505} -\glossaryentry{res.on.macro.definitions@ {\memgloterm{res.on.macro.definitions}}{\memglodesc{(\ref {res.on.macro.definitions})}} {\memgloref{}}|memjustarg}{505} -\glossaryentry{global.functions@ {\memgloterm{global.functions}}{\memglodesc{(\ref {global.functions})}} {\memgloref{}}|memjustarg}{505} -\glossaryentry{member.functions@ {\memgloterm{member.functions}}{\memglodesc{(\ref {member.functions})}} {\memgloref{}}|memjustarg}{505} -\glossaryentry{hidden.friends@ {\memgloterm{hidden.friends}}{\memglodesc{(\ref {hidden.friends})}} {\memgloref{}}|memjustarg}{505} -\glossaryentry{constexpr.functions@ {\memgloterm{constexpr.functions}}{\memglodesc{(\ref {constexpr.functions})}} {\memgloref{}}|memjustarg}{506} -\glossaryentry{algorithm.stable@ {\memgloterm{algorithm.stable}}{\memglodesc{(\ref {algorithm.stable})}} {\memgloref{}}|memjustarg}{506} -\glossaryentry{reentrancy@ {\memgloterm{reentrancy}}{\memglodesc{(\ref {reentrancy})}} {\memgloref{}}|memjustarg}{506} -\glossaryentry{res.on.data.races@ {\memgloterm{res.on.data.races}}{\memglodesc{(\ref {res.on.data.races})}} {\memgloref{}}|memjustarg}{506} -\glossaryentry{protection.within.classes@ {\memgloterm{protection.within.classes}}{\memglodesc{(\ref {protection.within.classes})}} {\memgloref{}}|memjustarg}{506} -\glossaryentry{derivation@ {\memgloterm{derivation}}{\memglodesc{(\ref {derivation})}} {\memgloref{}}|memjustarg}{506} -\glossaryentry{res.on.exception.handling@ {\memgloterm{res.on.exception.handling}}{\memglodesc{(\ref {res.on.exception.handling})}} {\memgloref{}}|memjustarg}{507} -\glossaryentry{value.error.codes@ {\memgloterm{value.error.codes}}{\memglodesc{(\ref {value.error.codes})}} {\memgloref{}}|memjustarg}{507} -\glossaryentry{lib.types.movedfrom@ {\memgloterm{lib.types.movedfrom}}{\memglodesc{(\ref {lib.types.movedfrom})}} {\memgloref{}}|memjustarg}{507} -\glossaryentry{support@ {\memgloterm{support}}{\memglodesc{(\ref {support})}} {\memgloref{}}|memjustarg}{508} -\glossaryentry{support.general@ {\memgloterm{support.general}}{\memglodesc{(\ref {support.general})}} {\memgloref{}}|memjustarg}{508} -\glossaryentry{support.types@ {\memgloterm{support.types}}{\memglodesc{(\ref {support.types})}} {\memgloref{}}|memjustarg}{508} -\glossaryentry{cstddef.syn@ {\memgloterm{cstddef.syn}}{\memglodesc{(\ref {cstddef.syn})}} {\memgloref{}}|memjustarg}{508} -\glossaryentry{cstdlib.syn@ {\memgloterm{cstdlib.syn}}{\memglodesc{(\ref {cstdlib.syn})}} {\memgloref{}}|memjustarg}{509} -\glossaryentry{support.types.nullptr@ {\memgloterm{support.types.nullptr}}{\memglodesc{(\ref {support.types.nullptr})}} {\memgloref{}}|memjustarg}{510} -\glossaryentry{support.types.layout@ {\memgloterm{support.types.layout}}{\memglodesc{(\ref {support.types.layout})}} {\memgloref{}}|memjustarg}{510} -\glossaryentry{support.types.byteops@ {\memgloterm{support.types.byteops}}{\memglodesc{(\ref {support.types.byteops})}} {\memgloref{}}|memjustarg}{511} -\glossaryentry{support.limits@ {\memgloterm{support.limits}}{\memglodesc{(\ref {support.limits})}} {\memgloref{}}|memjustarg}{512} -\glossaryentry{support.limits.general@ {\memgloterm{support.limits.general}}{\memglodesc{(\ref {support.limits.general})}} {\memgloref{}}|memjustarg}{512} -\glossaryentry{version.syn@ {\memgloterm{version.syn}}{\memglodesc{(\ref {version.syn})}} {\memgloref{}}|memjustarg}{512} -\glossaryentry{limits.syn@ {\memgloterm{limits.syn}}{\memglodesc{(\ref {limits.syn})}} {\memgloref{}}|memjustarg}{515} -\glossaryentry{round.style@ {\memgloterm{round.style}}{\memglodesc{(\ref {round.style})}} {\memgloref{}}|memjustarg}{516} -\glossaryentry{numeric.limits@ {\memgloterm{numeric.limits}}{\memglodesc{(\ref {numeric.limits})}} {\memgloref{}}|memjustarg}{516} -\glossaryentry{numeric.limits.general@ {\memgloterm{numeric.limits.general}}{\memglodesc{(\ref {numeric.limits.general})}} {\memgloref{}}|memjustarg}{516} -\glossaryentry{numeric.limits.members@ {\memgloterm{numeric.limits.members}}{\memglodesc{(\ref {numeric.limits.members})}} {\memgloref{}}|memjustarg}{517} -\glossaryentry{numeric.special@ {\memgloterm{numeric.special}}{\memglodesc{(\ref {numeric.special})}} {\memgloref{}}|memjustarg}{520} -\glossaryentry{climits.syn@ {\memgloterm{climits.syn}}{\memglodesc{(\ref {climits.syn})}} {\memgloref{}}|memjustarg}{522} -\glossaryentry{cfloat.syn@ {\memgloterm{cfloat.syn}}{\memglodesc{(\ref {cfloat.syn})}} {\memgloref{}}|memjustarg}{522} -\glossaryentry{support.arith.types@ {\memgloterm{support.arith.types}}{\memglodesc{(\ref {support.arith.types})}} {\memgloref{}}|memjustarg}{523} -\glossaryentry{cstdint.syn@ {\memgloterm{cstdint.syn}}{\memglodesc{(\ref {cstdint.syn})}} {\memgloref{}}|memjustarg}{523} -\glossaryentry{stdfloat.syn@ {\memgloterm{stdfloat.syn}}{\memglodesc{(\ref {stdfloat.syn})}} {\memgloref{}}|memjustarg}{524} -\glossaryentry{support.start.term@ {\memgloterm{support.start.term}}{\memglodesc{(\ref {support.start.term})}} {\memgloref{}}|memjustarg}{525} -\glossaryentry{support.dynamic@ {\memgloterm{support.dynamic}}{\memglodesc{(\ref {support.dynamic})}} {\memgloref{}}|memjustarg}{526} -\glossaryentry{support.dynamic.general@ {\memgloterm{support.dynamic.general}}{\memglodesc{(\ref {support.dynamic.general})}} {\memgloref{}}|memjustarg}{526} -\glossaryentry{new.syn@ {\memgloterm{new.syn}}{\memglodesc{(\ref {new.syn})}} {\memgloref{}}|memjustarg}{526} -\glossaryentry{new.delete@ {\memgloterm{new.delete}}{\memglodesc{(\ref {new.delete})}} {\memgloref{}}|memjustarg}{527} -\glossaryentry{new.delete.general@ {\memgloterm{new.delete.general}}{\memglodesc{(\ref {new.delete.general})}} {\memgloref{}}|memjustarg}{527} -\glossaryentry{new.delete.single@ {\memgloterm{new.delete.single}}{\memglodesc{(\ref {new.delete.single})}} {\memgloref{}}|memjustarg}{527} -\glossaryentry{new.delete.array@ {\memgloterm{new.delete.array}}{\memglodesc{(\ref {new.delete.array})}} {\memgloref{}}|memjustarg}{529} -\glossaryentry{new.delete.placement@ {\memgloterm{new.delete.placement}}{\memglodesc{(\ref {new.delete.placement})}} {\memgloref{}}|memjustarg}{530} -\glossaryentry{new.delete.dataraces@ {\memgloterm{new.delete.dataraces}}{\memglodesc{(\ref {new.delete.dataraces})}} {\memgloref{}}|memjustarg}{531} -\glossaryentry{alloc.errors@ {\memgloterm{alloc.errors}}{\memglodesc{(\ref {alloc.errors})}} {\memgloref{}}|memjustarg}{531} -\glossaryentry{bad.alloc@ {\memgloterm{bad.alloc}}{\memglodesc{(\ref {bad.alloc})}} {\memgloref{}}|memjustarg}{531} -\glossaryentry{new.badlength@ {\memgloterm{new.badlength}}{\memglodesc{(\ref {new.badlength})}} {\memgloref{}}|memjustarg}{531} -\glossaryentry{new.handler@ {\memgloterm{new.handler}}{\memglodesc{(\ref {new.handler})}} {\memgloref{}}|memjustarg}{531} -\glossaryentry{set.new.handler@ {\memgloterm{set.new.handler}}{\memglodesc{(\ref {set.new.handler})}} {\memgloref{}}|memjustarg}{532} -\glossaryentry{get.new.handler@ {\memgloterm{get.new.handler}}{\memglodesc{(\ref {get.new.handler})}} {\memgloref{}}|memjustarg}{532} -\glossaryentry{ptr.launder@ {\memgloterm{ptr.launder}}{\memglodesc{(\ref {ptr.launder})}} {\memgloref{}}|memjustarg}{532} -\glossaryentry{hardware.interference@ {\memgloterm{hardware.interference}}{\memglodesc{(\ref {hardware.interference})}} {\memgloref{}}|memjustarg}{532} -\glossaryentry{support.rtti@ {\memgloterm{support.rtti}}{\memglodesc{(\ref {support.rtti})}} {\memgloref{}}|memjustarg}{533} -\glossaryentry{support.rtti.general@ {\memgloterm{support.rtti.general}}{\memglodesc{(\ref {support.rtti.general})}} {\memgloref{}}|memjustarg}{533} -\glossaryentry{typeinfo.syn@ {\memgloterm{typeinfo.syn}}{\memglodesc{(\ref {typeinfo.syn})}} {\memgloref{}}|memjustarg}{533} -\glossaryentry{type.info@ {\memgloterm{type.info}}{\memglodesc{(\ref {type.info})}} {\memgloref{}}|memjustarg}{533} -\glossaryentry{bad.cast@ {\memgloterm{bad.cast}}{\memglodesc{(\ref {bad.cast})}} {\memgloref{}}|memjustarg}{534} -\glossaryentry{bad.typeid@ {\memgloterm{bad.typeid}}{\memglodesc{(\ref {bad.typeid})}} {\memgloref{}}|memjustarg}{534} -\glossaryentry{support.srcloc@ {\memgloterm{support.srcloc}}{\memglodesc{(\ref {support.srcloc})}} {\memgloref{}}|memjustarg}{534} -\glossaryentry{source.location.syn@ {\memgloterm{source.location.syn}}{\memglodesc{(\ref {source.location.syn})}} {\memgloref{}}|memjustarg}{534} -\glossaryentry{support.srcloc.class@ {\memgloterm{support.srcloc.class}}{\memglodesc{(\ref {support.srcloc.class})}} {\memgloref{}}|memjustarg}{534} -\glossaryentry{support.srcloc.class.general@ {\memgloterm{support.srcloc.class.general}}{\memglodesc{(\ref {support.srcloc.class.general})}} {\memgloref{}}|memjustarg}{534} -\glossaryentry{support.srcloc.cons@ {\memgloterm{support.srcloc.cons}}{\memglodesc{(\ref {support.srcloc.cons})}} {\memgloref{}}|memjustarg}{535} -\glossaryentry{support.srcloc.obs@ {\memgloterm{support.srcloc.obs}}{\memglodesc{(\ref {support.srcloc.obs})}} {\memgloref{}}|memjustarg}{536} -\glossaryentry{support.exception@ {\memgloterm{support.exception}}{\memglodesc{(\ref {support.exception})}} {\memgloref{}}|memjustarg}{536} -\glossaryentry{support.exception.general@ {\memgloterm{support.exception.general}}{\memglodesc{(\ref {support.exception.general})}} {\memgloref{}}|memjustarg}{536} -\glossaryentry{exception.syn@ {\memgloterm{exception.syn}}{\memglodesc{(\ref {exception.syn})}} {\memgloref{}}|memjustarg}{537} -\glossaryentry{exception@ {\memgloterm{exception}}{\memglodesc{(\ref {exception})}} {\memgloref{}}|memjustarg}{537} -\glossaryentry{bad.exception@ {\memgloterm{bad.exception}}{\memglodesc{(\ref {bad.exception})}} {\memgloref{}}|memjustarg}{538} -\glossaryentry{exception.terminate@ {\memgloterm{exception.terminate}}{\memglodesc{(\ref {exception.terminate})}} {\memgloref{}}|memjustarg}{538} -\glossaryentry{terminate.handler@ {\memgloterm{terminate.handler}}{\memglodesc{(\ref {terminate.handler})}} {\memgloref{}}|memjustarg}{538} -\glossaryentry{set.terminate@ {\memgloterm{set.terminate}}{\memglodesc{(\ref {set.terminate})}} {\memgloref{}}|memjustarg}{538} -\glossaryentry{get.terminate@ {\memgloterm{get.terminate}}{\memglodesc{(\ref {get.terminate})}} {\memgloref{}}|memjustarg}{538} -\glossaryentry{terminate@ {\memgloterm{terminate}}{\memglodesc{(\ref {terminate})}} {\memgloref{}}|memjustarg}{538} -\glossaryentry{uncaught.exceptions@ {\memgloterm{uncaught.exceptions}}{\memglodesc{(\ref {uncaught.exceptions})}} {\memgloref{}}|memjustarg}{538} -\glossaryentry{propagation@ {\memgloterm{propagation}}{\memglodesc{(\ref {propagation})}} {\memgloref{}}|memjustarg}{539} -\glossaryentry{except.nested@ {\memgloterm{except.nested}}{\memglodesc{(\ref {except.nested})}} {\memgloref{}}|memjustarg}{539} -\glossaryentry{support.initlist@ {\memgloterm{support.initlist}}{\memglodesc{(\ref {support.initlist})}} {\memgloref{}}|memjustarg}{540} -\glossaryentry{support.initlist.general@ {\memgloterm{support.initlist.general}}{\memglodesc{(\ref {support.initlist.general})}} {\memgloref{}}|memjustarg}{540} -\glossaryentry{initializer.list.syn@ {\memgloterm{initializer.list.syn}}{\memglodesc{(\ref {initializer.list.syn})}} {\memgloref{}}|memjustarg}{540} -\glossaryentry{support.initlist.cons@ {\memgloterm{support.initlist.cons}}{\memglodesc{(\ref {support.initlist.cons})}} {\memgloref{}}|memjustarg}{541} -\glossaryentry{support.initlist.access@ {\memgloterm{support.initlist.access}}{\memglodesc{(\ref {support.initlist.access})}} {\memgloref{}}|memjustarg}{541} -\glossaryentry{support.initlist.range@ {\memgloterm{support.initlist.range}}{\memglodesc{(\ref {support.initlist.range})}} {\memgloref{}}|memjustarg}{541} -\glossaryentry{cmp@ {\memgloterm{cmp}}{\memglodesc{(\ref {cmp})}} {\memgloref{}}|memjustarg}{541} -\glossaryentry{compare.syn@ {\memgloterm{compare.syn}}{\memglodesc{(\ref {compare.syn})}} {\memgloref{}}|memjustarg}{541} -\glossaryentry{cmp.categories@ {\memgloterm{cmp.categories}}{\memglodesc{(\ref {cmp.categories})}} {\memgloref{}}|memjustarg}{542} -\glossaryentry{cmp.categories.pre@ {\memgloterm{cmp.categories.pre}}{\memglodesc{(\ref {cmp.categories.pre})}} {\memgloref{}}|memjustarg}{542} -\glossaryentry{cmp.partialord@ {\memgloterm{cmp.partialord}}{\memglodesc{(\ref {cmp.partialord})}} {\memgloref{}}|memjustarg}{542} -\glossaryentry{cmp.weakord@ {\memgloterm{cmp.weakord}}{\memglodesc{(\ref {cmp.weakord})}} {\memgloref{}}|memjustarg}{544} -\glossaryentry{cmp.strongord@ {\memgloterm{cmp.strongord}}{\memglodesc{(\ref {cmp.strongord})}} {\memgloref{}}|memjustarg}{545} -\glossaryentry{cmp.common@ {\memgloterm{cmp.common}}{\memglodesc{(\ref {cmp.common})}} {\memgloref{}}|memjustarg}{546} -\glossaryentry{cmp.concept@ {\memgloterm{cmp.concept}}{\memglodesc{(\ref {cmp.concept})}} {\memgloref{}}|memjustarg}{546} -\glossaryentry{cmp.result@ {\memgloterm{cmp.result}}{\memglodesc{(\ref {cmp.result})}} {\memgloref{}}|memjustarg}{547} -\glossaryentry{cmp.alg@ {\memgloterm{cmp.alg}}{\memglodesc{(\ref {cmp.alg})}} {\memgloref{}}|memjustarg}{548} -\glossaryentry{support.coroutine@ {\memgloterm{support.coroutine}}{\memglodesc{(\ref {support.coroutine})}} {\memgloref{}}|memjustarg}{549} -\glossaryentry{support.coroutine.general@ {\memgloterm{support.coroutine.general}}{\memglodesc{(\ref {support.coroutine.general})}} {\memgloref{}}|memjustarg}{549} -\glossaryentry{coroutine.syn@ {\memgloterm{coroutine.syn}}{\memglodesc{(\ref {coroutine.syn})}} {\memgloref{}}|memjustarg}{550} -\glossaryentry{coroutine.traits@ {\memgloterm{coroutine.traits}}{\memglodesc{(\ref {coroutine.traits})}} {\memgloref{}}|memjustarg}{550} -\glossaryentry{coroutine.traits.general@ {\memgloterm{coroutine.traits.general}}{\memglodesc{(\ref {coroutine.traits.general})}} {\memgloref{}}|memjustarg}{550} -\glossaryentry{coroutine.traits.primary@ {\memgloterm{coroutine.traits.primary}}{\memglodesc{(\ref {coroutine.traits.primary})}} {\memgloref{}}|memjustarg}{550} -\glossaryentry{coroutine.handle@ {\memgloterm{coroutine.handle}}{\memglodesc{(\ref {coroutine.handle})}} {\memgloref{}}|memjustarg}{550} -\glossaryentry{coroutine.handle.general@ {\memgloterm{coroutine.handle.general}}{\memglodesc{(\ref {coroutine.handle.general})}} {\memgloref{}}|memjustarg}{550} -\glossaryentry{coroutine.handle.con@ {\memgloterm{coroutine.handle.con}}{\memglodesc{(\ref {coroutine.handle.con})}} {\memgloref{}}|memjustarg}{551} -\glossaryentry{coroutine.handle.conv@ {\memgloterm{coroutine.handle.conv}}{\memglodesc{(\ref {coroutine.handle.conv})}} {\memgloref{}}|memjustarg}{552} -\glossaryentry{coroutine.handle.export.import@ {\memgloterm{coroutine.handle.export.import}}{\memglodesc{(\ref {coroutine.handle.export.import})}} {\memgloref{}}|memjustarg}{552} -\glossaryentry{coroutine.handle.observers@ {\memgloterm{coroutine.handle.observers}}{\memglodesc{(\ref {coroutine.handle.observers})}} {\memgloref{}}|memjustarg}{552} -\glossaryentry{coroutine.handle.resumption@ {\memgloterm{coroutine.handle.resumption}}{\memglodesc{(\ref {coroutine.handle.resumption})}} {\memgloref{}}|memjustarg}{552} -\glossaryentry{coroutine.handle.promise@ {\memgloterm{coroutine.handle.promise}}{\memglodesc{(\ref {coroutine.handle.promise})}} {\memgloref{}}|memjustarg}{553} -\glossaryentry{coroutine.handle.compare@ {\memgloterm{coroutine.handle.compare}}{\memglodesc{(\ref {coroutine.handle.compare})}} {\memgloref{}}|memjustarg}{553} -\glossaryentry{coroutine.handle.hash@ {\memgloterm{coroutine.handle.hash}}{\memglodesc{(\ref {coroutine.handle.hash})}} {\memgloref{}}|memjustarg}{553} -\glossaryentry{coroutine.noop@ {\memgloterm{coroutine.noop}}{\memglodesc{(\ref {coroutine.noop})}} {\memgloref{}}|memjustarg}{553} -\glossaryentry{coroutine.promise.noop@ {\memgloterm{coroutine.promise.noop}}{\memglodesc{(\ref {coroutine.promise.noop})}} {\memgloref{}}|memjustarg}{553} -\glossaryentry{coroutine.handle.noop@ {\memgloterm{coroutine.handle.noop}}{\memglodesc{(\ref {coroutine.handle.noop})}} {\memgloref{}}|memjustarg}{553} -\glossaryentry{coroutine.handle.noop.conv@ {\memgloterm{coroutine.handle.noop.conv}}{\memglodesc{(\ref {coroutine.handle.noop.conv})}} {\memgloref{}}|memjustarg}{553} -\glossaryentry{coroutine.handle.noop.observers@ {\memgloterm{coroutine.handle.noop.observers}}{\memglodesc{(\ref {coroutine.handle.noop.observers})}} {\memgloref{}}|memjustarg}{554} -\glossaryentry{coroutine.handle.noop.resumption@ {\memgloterm{coroutine.handle.noop.resumption}}{\memglodesc{(\ref {coroutine.handle.noop.resumption})}} {\memgloref{}}|memjustarg}{554} -\glossaryentry{coroutine.handle.noop.promise@ {\memgloterm{coroutine.handle.noop.promise}}{\memglodesc{(\ref {coroutine.handle.noop.promise})}} {\memgloref{}}|memjustarg}{554} -\glossaryentry{coroutine.handle.noop.address@ {\memgloterm{coroutine.handle.noop.address}}{\memglodesc{(\ref {coroutine.handle.noop.address})}} {\memgloref{}}|memjustarg}{554} -\glossaryentry{coroutine.noop.coroutine@ {\memgloterm{coroutine.noop.coroutine}}{\memglodesc{(\ref {coroutine.noop.coroutine})}} {\memgloref{}}|memjustarg}{554} -\glossaryentry{coroutine.trivial.awaitables@ {\memgloterm{coroutine.trivial.awaitables}}{\memglodesc{(\ref {coroutine.trivial.awaitables})}} {\memgloref{}}|memjustarg}{554} -\glossaryentry{support.runtime@ {\memgloterm{support.runtime}}{\memglodesc{(\ref {support.runtime})}} {\memgloref{}}|memjustarg}{554} -\glossaryentry{support.runtime.general@ {\memgloterm{support.runtime.general}}{\memglodesc{(\ref {support.runtime.general})}} {\memgloref{}}|memjustarg}{554} -\glossaryentry{cstdarg.syn@ {\memgloterm{cstdarg.syn}}{\memglodesc{(\ref {cstdarg.syn})}} {\memgloref{}}|memjustarg}{555} -\glossaryentry{csetjmp.syn@ {\memgloterm{csetjmp.syn}}{\memglodesc{(\ref {csetjmp.syn})}} {\memgloref{}}|memjustarg}{555} -\glossaryentry{csignal.syn@ {\memgloterm{csignal.syn}}{\memglodesc{(\ref {csignal.syn})}} {\memgloref{}}|memjustarg}{555} -\glossaryentry{support.signal@ {\memgloterm{support.signal}}{\memglodesc{(\ref {support.signal})}} {\memgloref{}}|memjustarg}{556} -\glossaryentry{support.c.headers@ {\memgloterm{support.c.headers}}{\memglodesc{(\ref {support.c.headers})}} {\memgloref{}}|memjustarg}{556} -\glossaryentry{support.c.headers.general@ {\memgloterm{support.c.headers.general}}{\memglodesc{(\ref {support.c.headers.general})}} {\memgloref{}}|memjustarg}{556} -\glossaryentry{complex.h.syn@ {\memgloterm{complex.h.syn}}{\memglodesc{(\ref {complex.h.syn})}} {\memgloref{}}|memjustarg}{557} -\glossaryentry{iso646.h.syn@ {\memgloterm{iso646.h.syn}}{\memglodesc{(\ref {iso646.h.syn})}} {\memgloref{}}|memjustarg}{557} -\glossaryentry{stdalign.h.syn@ {\memgloterm{stdalign.h.syn}}{\memglodesc{(\ref {stdalign.h.syn})}} {\memgloref{}}|memjustarg}{557} -\glossaryentry{stdbool.h.syn@ {\memgloterm{stdbool.h.syn}}{\memglodesc{(\ref {stdbool.h.syn})}} {\memgloref{}}|memjustarg}{557} -\glossaryentry{tgmath.h.syn@ {\memgloterm{tgmath.h.syn}}{\memglodesc{(\ref {tgmath.h.syn})}} {\memgloref{}}|memjustarg}{557} -\glossaryentry{support.c.headers.other@ {\memgloterm{support.c.headers.other}}{\memglodesc{(\ref {support.c.headers.other})}} {\memgloref{}}|memjustarg}{557} -\glossaryentry{concepts@ {\memgloterm{concepts}}{\memglodesc{(\ref {concepts})}} {\memgloref{}}|memjustarg}{559} -\glossaryentry{concepts.general@ {\memgloterm{concepts.general}}{\memglodesc{(\ref {concepts.general})}} {\memgloref{}}|memjustarg}{559} -\glossaryentry{concepts.equality@ {\memgloterm{concepts.equality}}{\memglodesc{(\ref {concepts.equality})}} {\memgloref{}}|memjustarg}{559} -\glossaryentry{concepts.syn@ {\memgloterm{concepts.syn}}{\memglodesc{(\ref {concepts.syn})}} {\memgloref{}}|memjustarg}{560} -\glossaryentry{concepts.lang@ {\memgloterm{concepts.lang}}{\memglodesc{(\ref {concepts.lang})}} {\memgloref{}}|memjustarg}{562} -\glossaryentry{concepts.lang.general@ {\memgloterm{concepts.lang.general}}{\memglodesc{(\ref {concepts.lang.general})}} {\memgloref{}}|memjustarg}{562} -\glossaryentry{concept.same@ {\memgloterm{concept.same}}{\memglodesc{(\ref {concept.same})}} {\memgloref{}}|memjustarg}{562} -\glossaryentry{concept.derived@ {\memgloterm{concept.derived}}{\memglodesc{(\ref {concept.derived})}} {\memgloref{}}|memjustarg}{562} -\glossaryentry{concept.convertible@ {\memgloterm{concept.convertible}}{\memglodesc{(\ref {concept.convertible})}} {\memgloref{}}|memjustarg}{563} -\glossaryentry{concept.commonref@ {\memgloterm{concept.commonref}}{\memglodesc{(\ref {concept.commonref})}} {\memgloref{}}|memjustarg}{563} -\glossaryentry{concept.common@ {\memgloterm{concept.common}}{\memglodesc{(\ref {concept.common})}} {\memgloref{}}|memjustarg}{563} -\glossaryentry{concepts.arithmetic@ {\memgloterm{concepts.arithmetic}}{\memglodesc{(\ref {concepts.arithmetic})}} {\memgloref{}}|memjustarg}{564} -\glossaryentry{concept.assignable@ {\memgloterm{concept.assignable}}{\memglodesc{(\ref {concept.assignable})}} {\memgloref{}}|memjustarg}{564} -\glossaryentry{concept.swappable@ {\memgloterm{concept.swappable}}{\memglodesc{(\ref {concept.swappable})}} {\memgloref{}}|memjustarg}{565} -\glossaryentry{concept.destructible@ {\memgloterm{concept.destructible}}{\memglodesc{(\ref {concept.destructible})}} {\memgloref{}}|memjustarg}{566} -\glossaryentry{concept.constructible@ {\memgloterm{concept.constructible}}{\memglodesc{(\ref {concept.constructible})}} {\memgloref{}}|memjustarg}{566} -\glossaryentry{concept.default.init@ {\memgloterm{concept.default.init}}{\memglodesc{(\ref {concept.default.init})}} {\memgloref{}}|memjustarg}{567} -\glossaryentry{concept.moveconstructible@ {\memgloterm{concept.moveconstructible}}{\memglodesc{(\ref {concept.moveconstructible})}} {\memgloref{}}|memjustarg}{567} -\glossaryentry{concept.copyconstructible@ {\memgloterm{concept.copyconstructible}}{\memglodesc{(\ref {concept.copyconstructible})}} {\memgloref{}}|memjustarg}{567} -\glossaryentry{concepts.compare@ {\memgloterm{concepts.compare}}{\memglodesc{(\ref {concepts.compare})}} {\memgloref{}}|memjustarg}{567} -\glossaryentry{concepts.compare.general@ {\memgloterm{concepts.compare.general}}{\memglodesc{(\ref {concepts.compare.general})}} {\memgloref{}}|memjustarg}{567} -\glossaryentry{concept.booleantestable@ {\memgloterm{concept.booleantestable}}{\memglodesc{(\ref {concept.booleantestable})}} {\memgloref{}}|memjustarg}{567} -\glossaryentry{concept.comparisoncommontype@ {\memgloterm{concept.comparisoncommontype}}{\memglodesc{(\ref {concept.comparisoncommontype})}} {\memgloref{}}|memjustarg}{568} -\glossaryentry{concept.equalitycomparable@ {\memgloterm{concept.equalitycomparable}}{\memglodesc{(\ref {concept.equalitycomparable})}} {\memgloref{}}|memjustarg}{569} -\glossaryentry{concept.totallyordered@ {\memgloterm{concept.totallyordered}}{\memglodesc{(\ref {concept.totallyordered})}} {\memgloref{}}|memjustarg}{569} -\glossaryentry{concepts.object@ {\memgloterm{concepts.object}}{\memglodesc{(\ref {concepts.object})}} {\memgloref{}}|memjustarg}{570} -\glossaryentry{concepts.callable@ {\memgloterm{concepts.callable}}{\memglodesc{(\ref {concepts.callable})}} {\memgloref{}}|memjustarg}{570} -\glossaryentry{concepts.callable.general@ {\memgloterm{concepts.callable.general}}{\memglodesc{(\ref {concepts.callable.general})}} {\memgloref{}}|memjustarg}{570} -\glossaryentry{concept.invocable@ {\memgloterm{concept.invocable}}{\memglodesc{(\ref {concept.invocable})}} {\memgloref{}}|memjustarg}{571} -\glossaryentry{concept.regularinvocable@ {\memgloterm{concept.regularinvocable}}{\memglodesc{(\ref {concept.regularinvocable})}} {\memgloref{}}|memjustarg}{571} -\glossaryentry{concept.predicate@ {\memgloterm{concept.predicate}}{\memglodesc{(\ref {concept.predicate})}} {\memgloref{}}|memjustarg}{571} -\glossaryentry{concept.relation@ {\memgloterm{concept.relation}}{\memglodesc{(\ref {concept.relation})}} {\memgloref{}}|memjustarg}{571} -\glossaryentry{concept.equiv@ {\memgloterm{concept.equiv}}{\memglodesc{(\ref {concept.equiv})}} {\memgloref{}}|memjustarg}{571} -\glossaryentry{concept.strictweakorder@ {\memgloterm{concept.strictweakorder}}{\memglodesc{(\ref {concept.strictweakorder})}} {\memgloref{}}|memjustarg}{571} -\glossaryentry{diagnostics@ {\memgloterm{diagnostics}}{\memglodesc{(\ref {diagnostics})}} {\memgloref{}}|memjustarg}{572} -\glossaryentry{diagnostics.general@ {\memgloterm{diagnostics.general}}{\memglodesc{(\ref {diagnostics.general})}} {\memgloref{}}|memjustarg}{572} -\glossaryentry{std.exceptions@ {\memgloterm{std.exceptions}}{\memglodesc{(\ref {std.exceptions})}} {\memgloref{}}|memjustarg}{572} -\glossaryentry{std.exceptions.general@ {\memgloterm{std.exceptions.general}}{\memglodesc{(\ref {std.exceptions.general})}} {\memgloref{}}|memjustarg}{572} -\glossaryentry{stdexcept.syn@ {\memgloterm{stdexcept.syn}}{\memglodesc{(\ref {stdexcept.syn})}} {\memgloref{}}|memjustarg}{572} -\glossaryentry{logic.error@ {\memgloterm{logic.error}}{\memglodesc{(\ref {logic.error})}} {\memgloref{}}|memjustarg}{572} -\glossaryentry{domain.error@ {\memgloterm{domain.error}}{\memglodesc{(\ref {domain.error})}} {\memgloref{}}|memjustarg}{573} -\glossaryentry{invalid.argument@ {\memgloterm{invalid.argument}}{\memglodesc{(\ref {invalid.argument})}} {\memgloref{}}|memjustarg}{573} -\glossaryentry{length.error@ {\memgloterm{length.error}}{\memglodesc{(\ref {length.error})}} {\memgloref{}}|memjustarg}{573} -\glossaryentry{out.of.range@ {\memgloterm{out.of.range}}{\memglodesc{(\ref {out.of.range})}} {\memgloref{}}|memjustarg}{574} -\glossaryentry{runtime.error@ {\memgloterm{runtime.error}}{\memglodesc{(\ref {runtime.error})}} {\memgloref{}}|memjustarg}{574} -\glossaryentry{range.error@ {\memgloterm{range.error}}{\memglodesc{(\ref {range.error})}} {\memgloref{}}|memjustarg}{574} -\glossaryentry{overflow.error@ {\memgloterm{overflow.error}}{\memglodesc{(\ref {overflow.error})}} {\memgloref{}}|memjustarg}{574} -\glossaryentry{underflow.error@ {\memgloterm{underflow.error}}{\memglodesc{(\ref {underflow.error})}} {\memgloref{}}|memjustarg}{575} -\glossaryentry{assertions@ {\memgloterm{assertions}}{\memglodesc{(\ref {assertions})}} {\memgloref{}}|memjustarg}{575} -\glossaryentry{assertions.general@ {\memgloterm{assertions.general}}{\memglodesc{(\ref {assertions.general})}} {\memgloref{}}|memjustarg}{575} -\glossaryentry{cassert.syn@ {\memgloterm{cassert.syn}}{\memglodesc{(\ref {cassert.syn})}} {\memgloref{}}|memjustarg}{575} -\glossaryentry{assertions.assert@ {\memgloterm{assertions.assert}}{\memglodesc{(\ref {assertions.assert})}} {\memgloref{}}|memjustarg}{575} -\glossaryentry{errno@ {\memgloterm{errno}}{\memglodesc{(\ref {errno})}} {\memgloref{}}|memjustarg}{575} -\glossaryentry{errno.general@ {\memgloterm{errno.general}}{\memglodesc{(\ref {errno.general})}} {\memgloref{}}|memjustarg}{575} -\glossaryentry{cerrno.syn@ {\memgloterm{cerrno.syn}}{\memglodesc{(\ref {cerrno.syn})}} {\memgloref{}}|memjustarg}{575} -\glossaryentry{syserr@ {\memgloterm{syserr}}{\memglodesc{(\ref {syserr})}} {\memgloref{}}|memjustarg}{577} -\glossaryentry{syserr.general@ {\memgloterm{syserr.general}}{\memglodesc{(\ref {syserr.general})}} {\memgloref{}}|memjustarg}{577} -\glossaryentry{system.error.syn@ {\memgloterm{system.error.syn}}{\memglodesc{(\ref {system.error.syn})}} {\memgloref{}}|memjustarg}{577} -\glossaryentry{syserr.errcat@ {\memgloterm{syserr.errcat}}{\memglodesc{(\ref {syserr.errcat})}} {\memgloref{}}|memjustarg}{579} -\glossaryentry{syserr.errcat.overview@ {\memgloterm{syserr.errcat.overview}}{\memglodesc{(\ref {syserr.errcat.overview})}} {\memgloref{}}|memjustarg}{579} -\glossaryentry{syserr.errcat.virtuals@ {\memgloterm{syserr.errcat.virtuals}}{\memglodesc{(\ref {syserr.errcat.virtuals})}} {\memgloref{}}|memjustarg}{579} -\glossaryentry{syserr.errcat.nonvirtuals@ {\memgloterm{syserr.errcat.nonvirtuals}}{\memglodesc{(\ref {syserr.errcat.nonvirtuals})}} {\memgloref{}}|memjustarg}{580} -\glossaryentry{syserr.errcat.derived@ {\memgloterm{syserr.errcat.derived}}{\memglodesc{(\ref {syserr.errcat.derived})}} {\memgloref{}}|memjustarg}{580} -\glossaryentry{syserr.errcat.objects@ {\memgloterm{syserr.errcat.objects}}{\memglodesc{(\ref {syserr.errcat.objects})}} {\memgloref{}}|memjustarg}{580} -\glossaryentry{syserr.errcode@ {\memgloterm{syserr.errcode}}{\memglodesc{(\ref {syserr.errcode})}} {\memgloref{}}|memjustarg}{581} -\glossaryentry{syserr.errcode.overview@ {\memgloterm{syserr.errcode.overview}}{\memglodesc{(\ref {syserr.errcode.overview})}} {\memgloref{}}|memjustarg}{581} -\glossaryentry{syserr.errcode.constructors@ {\memgloterm{syserr.errcode.constructors}}{\memglodesc{(\ref {syserr.errcode.constructors})}} {\memgloref{}}|memjustarg}{581} -\glossaryentry{syserr.errcode.modifiers@ {\memgloterm{syserr.errcode.modifiers}}{\memglodesc{(\ref {syserr.errcode.modifiers})}} {\memgloref{}}|memjustarg}{582} -\glossaryentry{syserr.errcode.observers@ {\memgloterm{syserr.errcode.observers}}{\memglodesc{(\ref {syserr.errcode.observers})}} {\memgloref{}}|memjustarg}{582} -\glossaryentry{syserr.errcode.nonmembers@ {\memgloterm{syserr.errcode.nonmembers}}{\memglodesc{(\ref {syserr.errcode.nonmembers})}} {\memgloref{}}|memjustarg}{582} -\glossaryentry{syserr.errcondition@ {\memgloterm{syserr.errcondition}}{\memglodesc{(\ref {syserr.errcondition})}} {\memgloref{}}|memjustarg}{582} -\glossaryentry{syserr.errcondition.overview@ {\memgloterm{syserr.errcondition.overview}}{\memglodesc{(\ref {syserr.errcondition.overview})}} {\memgloref{}}|memjustarg}{582} -\glossaryentry{syserr.errcondition.constructors@ {\memgloterm{syserr.errcondition.constructors}}{\memglodesc{(\ref {syserr.errcondition.constructors})}} {\memgloref{}}|memjustarg}{583} -\glossaryentry{syserr.errcondition.modifiers@ {\memgloterm{syserr.errcondition.modifiers}}{\memglodesc{(\ref {syserr.errcondition.modifiers})}} {\memgloref{}}|memjustarg}{583} -\glossaryentry{syserr.errcondition.observers@ {\memgloterm{syserr.errcondition.observers}}{\memglodesc{(\ref {syserr.errcondition.observers})}} {\memgloref{}}|memjustarg}{583} -\glossaryentry{syserr.errcondition.nonmembers@ {\memgloterm{syserr.errcondition.nonmembers}}{\memglodesc{(\ref {syserr.errcondition.nonmembers})}} {\memgloref{}}|memjustarg}{584} -\glossaryentry{syserr.compare@ {\memgloterm{syserr.compare}}{\memglodesc{(\ref {syserr.compare})}} {\memgloref{}}|memjustarg}{584} -\glossaryentry{syserr.hash@ {\memgloterm{syserr.hash}}{\memglodesc{(\ref {syserr.hash})}} {\memgloref{}}|memjustarg}{584} -\glossaryentry{syserr.syserr@ {\memgloterm{syserr.syserr}}{\memglodesc{(\ref {syserr.syserr})}} {\memgloref{}}|memjustarg}{584} -\glossaryentry{syserr.syserr.overview@ {\memgloterm{syserr.syserr.overview}}{\memglodesc{(\ref {syserr.syserr.overview})}} {\memgloref{}}|memjustarg}{584} -\glossaryentry{syserr.syserr.members@ {\memgloterm{syserr.syserr.members}}{\memglodesc{(\ref {syserr.syserr.members})}} {\memgloref{}}|memjustarg}{585} -\glossaryentry{stacktrace@ {\memgloterm{stacktrace}}{\memglodesc{(\ref {stacktrace})}} {\memgloref{}}|memjustarg}{585} -\glossaryentry{stacktrace.general@ {\memgloterm{stacktrace.general}}{\memglodesc{(\ref {stacktrace.general})}} {\memgloref{}}|memjustarg}{585} -\glossaryentry{stacktrace.syn@ {\memgloterm{stacktrace.syn}}{\memglodesc{(\ref {stacktrace.syn})}} {\memgloref{}}|memjustarg}{585} -\glossaryentry{stacktrace.entry@ {\memgloterm{stacktrace.entry}}{\memglodesc{(\ref {stacktrace.entry})}} {\memgloref{}}|memjustarg}{586} -\glossaryentry{stacktrace.entry.overview@ {\memgloterm{stacktrace.entry.overview}}{\memglodesc{(\ref {stacktrace.entry.overview})}} {\memgloref{}}|memjustarg}{586} -\glossaryentry{stacktrace.entry.cons@ {\memgloterm{stacktrace.entry.cons}}{\memglodesc{(\ref {stacktrace.entry.cons})}} {\memgloref{}}|memjustarg}{586} -\glossaryentry{stacktrace.entry.obs@ {\memgloterm{stacktrace.entry.obs}}{\memglodesc{(\ref {stacktrace.entry.obs})}} {\memgloref{}}|memjustarg}{587} -\glossaryentry{stacktrace.entry.query@ {\memgloterm{stacktrace.entry.query}}{\memglodesc{(\ref {stacktrace.entry.query})}} {\memgloref{}}|memjustarg}{587} -\glossaryentry{stacktrace.entry.cmp@ {\memgloterm{stacktrace.entry.cmp}}{\memglodesc{(\ref {stacktrace.entry.cmp})}} {\memgloref{}}|memjustarg}{587} -\glossaryentry{stacktrace.basic@ {\memgloterm{stacktrace.basic}}{\memglodesc{(\ref {stacktrace.basic})}} {\memgloref{}}|memjustarg}{587} -\glossaryentry{stacktrace.basic.overview@ {\memgloterm{stacktrace.basic.overview}}{\memglodesc{(\ref {stacktrace.basic.overview})}} {\memgloref{}}|memjustarg}{587} -\glossaryentry{stacktrace.basic.cons@ {\memgloterm{stacktrace.basic.cons}}{\memglodesc{(\ref {stacktrace.basic.cons})}} {\memgloref{}}|memjustarg}{588} -\glossaryentry{stacktrace.basic.obs@ {\memgloterm{stacktrace.basic.obs}}{\memglodesc{(\ref {stacktrace.basic.obs})}} {\memgloref{}}|memjustarg}{589} -\glossaryentry{stacktrace.basic.cmp@ {\memgloterm{stacktrace.basic.cmp}}{\memglodesc{(\ref {stacktrace.basic.cmp})}} {\memgloref{}}|memjustarg}{590} -\glossaryentry{stacktrace.basic.mod@ {\memgloterm{stacktrace.basic.mod}}{\memglodesc{(\ref {stacktrace.basic.mod})}} {\memgloref{}}|memjustarg}{590} -\glossaryentry{stacktrace.basic.nonmem@ {\memgloterm{stacktrace.basic.nonmem}}{\memglodesc{(\ref {stacktrace.basic.nonmem})}} {\memgloref{}}|memjustarg}{590} -\glossaryentry{stacktrace.format@ {\memgloterm{stacktrace.format}}{\memglodesc{(\ref {stacktrace.format})}} {\memgloref{}}|memjustarg}{591} -\glossaryentry{stacktrace.basic.hash@ {\memgloterm{stacktrace.basic.hash}}{\memglodesc{(\ref {stacktrace.basic.hash})}} {\memgloref{}}|memjustarg}{591} -\glossaryentry{mem@ {\memgloterm{mem}}{\memglodesc{(\ref {mem})}} {\memgloref{}}|memjustarg}{592} -\glossaryentry{mem.general@ {\memgloterm{mem.general}}{\memglodesc{(\ref {mem.general})}} {\memgloref{}}|memjustarg}{592} -\glossaryentry{memory@ {\memgloterm{memory}}{\memglodesc{(\ref {memory})}} {\memgloref{}}|memjustarg}{592} -\glossaryentry{memory.general@ {\memgloterm{memory.general}}{\memglodesc{(\ref {memory.general})}} {\memgloref{}}|memjustarg}{592} -\glossaryentry{memory.syn@ {\memgloterm{memory.syn}}{\memglodesc{(\ref {memory.syn})}} {\memgloref{}}|memjustarg}{592} -\glossaryentry{pointer.traits@ {\memgloterm{pointer.traits}}{\memglodesc{(\ref {pointer.traits})}} {\memgloref{}}|memjustarg}{600} -\glossaryentry{pointer.traits.general@ {\memgloterm{pointer.traits.general}}{\memglodesc{(\ref {pointer.traits.general})}} {\memgloref{}}|memjustarg}{600} -\glossaryentry{pointer.traits.types@ {\memgloterm{pointer.traits.types}}{\memglodesc{(\ref {pointer.traits.types})}} {\memgloref{}}|memjustarg}{601} -\glossaryentry{pointer.traits.functions@ {\memgloterm{pointer.traits.functions}}{\memglodesc{(\ref {pointer.traits.functions})}} {\memgloref{}}|memjustarg}{601} -\glossaryentry{pointer.traits.optmem@ {\memgloterm{pointer.traits.optmem}}{\memglodesc{(\ref {pointer.traits.optmem})}} {\memgloref{}}|memjustarg}{602} -\glossaryentry{pointer.conversion@ {\memgloterm{pointer.conversion}}{\memglodesc{(\ref {pointer.conversion})}} {\memgloref{}}|memjustarg}{602} -\glossaryentry{ptr.align@ {\memgloterm{ptr.align}}{\memglodesc{(\ref {ptr.align})}} {\memgloref{}}|memjustarg}{602} -\glossaryentry{obj.lifetime@ {\memgloterm{obj.lifetime}}{\memglodesc{(\ref {obj.lifetime})}} {\memgloref{}}|memjustarg}{602} -\glossaryentry{allocator.tag@ {\memgloterm{allocator.tag}}{\memglodesc{(\ref {allocator.tag})}} {\memgloref{}}|memjustarg}{603} -\glossaryentry{allocator.uses@ {\memgloterm{allocator.uses}}{\memglodesc{(\ref {allocator.uses})}} {\memgloref{}}|memjustarg}{603} -\glossaryentry{allocator.uses.trait@ {\memgloterm{allocator.uses.trait}}{\memglodesc{(\ref {allocator.uses.trait})}} {\memgloref{}}|memjustarg}{603} -\glossaryentry{allocator.uses.construction@ {\memgloterm{allocator.uses.construction}}{\memglodesc{(\ref {allocator.uses.construction})}} {\memgloref{}}|memjustarg}{603} -\glossaryentry{allocator.traits@ {\memgloterm{allocator.traits}}{\memglodesc{(\ref {allocator.traits})}} {\memgloref{}}|memjustarg}{606} -\glossaryentry{allocator.traits.general@ {\memgloterm{allocator.traits.general}}{\memglodesc{(\ref {allocator.traits.general})}} {\memgloref{}}|memjustarg}{606} -\glossaryentry{allocator.traits.types@ {\memgloterm{allocator.traits.types}}{\memglodesc{(\ref {allocator.traits.types})}} {\memgloref{}}|memjustarg}{607} -\glossaryentry{allocator.traits.members@ {\memgloterm{allocator.traits.members}}{\memglodesc{(\ref {allocator.traits.members})}} {\memgloref{}}|memjustarg}{608} -\glossaryentry{allocator.traits.other@ {\memgloterm{allocator.traits.other}}{\memglodesc{(\ref {allocator.traits.other})}} {\memgloref{}}|memjustarg}{608} -\glossaryentry{default.allocator@ {\memgloterm{default.allocator}}{\memglodesc{(\ref {default.allocator})}} {\memgloref{}}|memjustarg}{608} -\glossaryentry{default.allocator.general@ {\memgloterm{default.allocator.general}}{\memglodesc{(\ref {default.allocator.general})}} {\memgloref{}}|memjustarg}{608} -\glossaryentry{allocator.members@ {\memgloterm{allocator.members}}{\memglodesc{(\ref {allocator.members})}} {\memgloref{}}|memjustarg}{609} -\glossaryentry{allocator.globals@ {\memgloterm{allocator.globals}}{\memglodesc{(\ref {allocator.globals})}} {\memgloref{}}|memjustarg}{609} -\glossaryentry{specialized.addressof@ {\memgloterm{specialized.addressof}}{\memglodesc{(\ref {specialized.addressof})}} {\memgloref{}}|memjustarg}{610} -\glossaryentry{c.malloc@ {\memgloterm{c.malloc}}{\memglodesc{(\ref {c.malloc})}} {\memgloref{}}|memjustarg}{610} -\glossaryentry{smartptr@ {\memgloterm{smartptr}}{\memglodesc{(\ref {smartptr})}} {\memgloref{}}|memjustarg}{610} -\glossaryentry{unique.ptr@ {\memgloterm{unique.ptr}}{\memglodesc{(\ref {unique.ptr})}} {\memgloref{}}|memjustarg}{610} -\glossaryentry{unique.ptr.general@ {\memgloterm{unique.ptr.general}}{\memglodesc{(\ref {unique.ptr.general})}} {\memgloref{}}|memjustarg}{610} -\glossaryentry{unique.ptr.dltr@ {\memgloterm{unique.ptr.dltr}}{\memglodesc{(\ref {unique.ptr.dltr})}} {\memgloref{}}|memjustarg}{610} -\glossaryentry{unique.ptr.dltr.general@ {\memgloterm{unique.ptr.dltr.general}}{\memglodesc{(\ref {unique.ptr.dltr.general})}} {\memgloref{}}|memjustarg}{610} -\glossaryentry{unique.ptr.dltr.dflt@ {\memgloterm{unique.ptr.dltr.dflt}}{\memglodesc{(\ref {unique.ptr.dltr.dflt})}} {\memgloref{}}|memjustarg}{611} -\glossaryentry{unique.ptr.dltr.dflt1@ {\memgloterm{unique.ptr.dltr.dflt1}}{\memglodesc{(\ref {unique.ptr.dltr.dflt1})}} {\memgloref{}}|memjustarg}{611} -\glossaryentry{unique.ptr.single@ {\memgloterm{unique.ptr.single}}{\memglodesc{(\ref {unique.ptr.single})}} {\memgloref{}}|memjustarg}{611} -\glossaryentry{unique.ptr.single.general@ {\memgloterm{unique.ptr.single.general}}{\memglodesc{(\ref {unique.ptr.single.general})}} {\memgloref{}}|memjustarg}{611} -\glossaryentry{unique.ptr.single.ctor@ {\memgloterm{unique.ptr.single.ctor}}{\memglodesc{(\ref {unique.ptr.single.ctor})}} {\memgloref{}}|memjustarg}{612} -\glossaryentry{unique.ptr.single.dtor@ {\memgloterm{unique.ptr.single.dtor}}{\memglodesc{(\ref {unique.ptr.single.dtor})}} {\memgloref{}}|memjustarg}{613} -\glossaryentry{unique.ptr.single.asgn@ {\memgloterm{unique.ptr.single.asgn}}{\memglodesc{(\ref {unique.ptr.single.asgn})}} {\memgloref{}}|memjustarg}{614} -\glossaryentry{unique.ptr.single.observers@ {\memgloterm{unique.ptr.single.observers}}{\memglodesc{(\ref {unique.ptr.single.observers})}} {\memgloref{}}|memjustarg}{614} -\glossaryentry{unique.ptr.single.modifiers@ {\memgloterm{unique.ptr.single.modifiers}}{\memglodesc{(\ref {unique.ptr.single.modifiers})}} {\memgloref{}}|memjustarg}{615} -\glossaryentry{unique.ptr.runtime@ {\memgloterm{unique.ptr.runtime}}{\memglodesc{(\ref {unique.ptr.runtime})}} {\memgloref{}}|memjustarg}{615} -\glossaryentry{unique.ptr.runtime.general@ {\memgloterm{unique.ptr.runtime.general}}{\memglodesc{(\ref {unique.ptr.runtime.general})}} {\memgloref{}}|memjustarg}{615} -\glossaryentry{unique.ptr.runtime.ctor@ {\memgloterm{unique.ptr.runtime.ctor}}{\memglodesc{(\ref {unique.ptr.runtime.ctor})}} {\memgloref{}}|memjustarg}{616} -\glossaryentry{unique.ptr.runtime.asgn@ {\memgloterm{unique.ptr.runtime.asgn}}{\memglodesc{(\ref {unique.ptr.runtime.asgn})}} {\memgloref{}}|memjustarg}{616} -\glossaryentry{unique.ptr.runtime.observers@ {\memgloterm{unique.ptr.runtime.observers}}{\memglodesc{(\ref {unique.ptr.runtime.observers})}} {\memgloref{}}|memjustarg}{617} -\glossaryentry{unique.ptr.runtime.modifiers@ {\memgloterm{unique.ptr.runtime.modifiers}}{\memglodesc{(\ref {unique.ptr.runtime.modifiers})}} {\memgloref{}}|memjustarg}{617} -\glossaryentry{unique.ptr.create@ {\memgloterm{unique.ptr.create}}{\memglodesc{(\ref {unique.ptr.create})}} {\memgloref{}}|memjustarg}{617} -\glossaryentry{unique.ptr.special@ {\memgloterm{unique.ptr.special}}{\memglodesc{(\ref {unique.ptr.special})}} {\memgloref{}}|memjustarg}{617} -\glossaryentry{unique.ptr.io@ {\memgloterm{unique.ptr.io}}{\memglodesc{(\ref {unique.ptr.io})}} {\memgloref{}}|memjustarg}{619} -\glossaryentry{util.sharedptr@ {\memgloterm{util.sharedptr}}{\memglodesc{(\ref {util.sharedptr})}} {\memgloref{}}|memjustarg}{619} -\glossaryentry{util.smartptr.weak.bad@ {\memgloterm{util.smartptr.weak.bad}}{\memglodesc{(\ref {util.smartptr.weak.bad})}} {\memgloref{}}|memjustarg}{619} -\glossaryentry{util.smartptr.shared@ {\memgloterm{util.smartptr.shared}}{\memglodesc{(\ref {util.smartptr.shared})}} {\memgloref{}}|memjustarg}{619} -\glossaryentry{util.smartptr.shared.general@ {\memgloterm{util.smartptr.shared.general}}{\memglodesc{(\ref {util.smartptr.shared.general})}} {\memgloref{}}|memjustarg}{619} -\glossaryentry{util.smartptr.shared.const@ {\memgloterm{util.smartptr.shared.const}}{\memglodesc{(\ref {util.smartptr.shared.const})}} {\memgloref{}}|memjustarg}{621} -\glossaryentry{util.smartptr.shared.dest@ {\memgloterm{util.smartptr.shared.dest}}{\memglodesc{(\ref {util.smartptr.shared.dest})}} {\memgloref{}}|memjustarg}{623} -\glossaryentry{util.smartptr.shared.assign@ {\memgloterm{util.smartptr.shared.assign}}{\memglodesc{(\ref {util.smartptr.shared.assign})}} {\memgloref{}}|memjustarg}{623} -\glossaryentry{util.smartptr.shared.mod@ {\memgloterm{util.smartptr.shared.mod}}{\memglodesc{(\ref {util.smartptr.shared.mod})}} {\memgloref{}}|memjustarg}{623} -\glossaryentry{util.smartptr.shared.obs@ {\memgloterm{util.smartptr.shared.obs}}{\memglodesc{(\ref {util.smartptr.shared.obs})}} {\memgloref{}}|memjustarg}{624} -\glossaryentry{util.smartptr.shared.create@ {\memgloterm{util.smartptr.shared.create}}{\memglodesc{(\ref {util.smartptr.shared.create})}} {\memgloref{}}|memjustarg}{624} -\glossaryentry{util.smartptr.shared.cmp@ {\memgloterm{util.smartptr.shared.cmp}}{\memglodesc{(\ref {util.smartptr.shared.cmp})}} {\memgloref{}}|memjustarg}{627} -\glossaryentry{util.smartptr.shared.spec@ {\memgloterm{util.smartptr.shared.spec}}{\memglodesc{(\ref {util.smartptr.shared.spec})}} {\memgloref{}}|memjustarg}{628} -\glossaryentry{util.smartptr.shared.cast@ {\memgloterm{util.smartptr.shared.cast}}{\memglodesc{(\ref {util.smartptr.shared.cast})}} {\memgloref{}}|memjustarg}{628} -\glossaryentry{util.smartptr.getdeleter@ {\memgloterm{util.smartptr.getdeleter}}{\memglodesc{(\ref {util.smartptr.getdeleter})}} {\memgloref{}}|memjustarg}{629} -\glossaryentry{util.smartptr.shared.io@ {\memgloterm{util.smartptr.shared.io}}{\memglodesc{(\ref {util.smartptr.shared.io})}} {\memgloref{}}|memjustarg}{629} -\glossaryentry{util.smartptr.weak@ {\memgloterm{util.smartptr.weak}}{\memglodesc{(\ref {util.smartptr.weak})}} {\memgloref{}}|memjustarg}{629} -\glossaryentry{util.smartptr.weak.general@ {\memgloterm{util.smartptr.weak.general}}{\memglodesc{(\ref {util.smartptr.weak.general})}} {\memgloref{}}|memjustarg}{629} -\glossaryentry{util.smartptr.weak.const@ {\memgloterm{util.smartptr.weak.const}}{\memglodesc{(\ref {util.smartptr.weak.const})}} {\memgloref{}}|memjustarg}{630} -\glossaryentry{util.smartptr.weak.dest@ {\memgloterm{util.smartptr.weak.dest}}{\memglodesc{(\ref {util.smartptr.weak.dest})}} {\memgloref{}}|memjustarg}{630} -\glossaryentry{util.smartptr.weak.assign@ {\memgloterm{util.smartptr.weak.assign}}{\memglodesc{(\ref {util.smartptr.weak.assign})}} {\memgloref{}}|memjustarg}{631} -\glossaryentry{util.smartptr.weak.mod@ {\memgloterm{util.smartptr.weak.mod}}{\memglodesc{(\ref {util.smartptr.weak.mod})}} {\memgloref{}}|memjustarg}{631} -\glossaryentry{util.smartptr.weak.obs@ {\memgloterm{util.smartptr.weak.obs}}{\memglodesc{(\ref {util.smartptr.weak.obs})}} {\memgloref{}}|memjustarg}{631} -\glossaryentry{util.smartptr.weak.spec@ {\memgloterm{util.smartptr.weak.spec}}{\memglodesc{(\ref {util.smartptr.weak.spec})}} {\memgloref{}}|memjustarg}{631} -\glossaryentry{util.smartptr.ownerless@ {\memgloterm{util.smartptr.ownerless}}{\memglodesc{(\ref {util.smartptr.ownerless})}} {\memgloref{}}|memjustarg}{631} -\glossaryentry{util.smartptr.enab@ {\memgloterm{util.smartptr.enab}}{\memglodesc{(\ref {util.smartptr.enab})}} {\memgloref{}}|memjustarg}{632} -\glossaryentry{util.smartptr.hash@ {\memgloterm{util.smartptr.hash}}{\memglodesc{(\ref {util.smartptr.hash})}} {\memgloref{}}|memjustarg}{633} -\glossaryentry{smartptr.adapt@ {\memgloterm{smartptr.adapt}}{\memglodesc{(\ref {smartptr.adapt})}} {\memgloref{}}|memjustarg}{633} -\glossaryentry{out.ptr.t@ {\memgloterm{out.ptr.t}}{\memglodesc{(\ref {out.ptr.t})}} {\memgloref{}}|memjustarg}{633} -\glossaryentry{out.ptr@ {\memgloterm{out.ptr}}{\memglodesc{(\ref {out.ptr})}} {\memgloref{}}|memjustarg}{635} -\glossaryentry{inout.ptr.t@ {\memgloterm{inout.ptr.t}}{\memglodesc{(\ref {inout.ptr.t})}} {\memgloref{}}|memjustarg}{635} -\glossaryentry{inout.ptr@ {\memgloterm{inout.ptr}}{\memglodesc{(\ref {inout.ptr})}} {\memgloref{}}|memjustarg}{637} -\glossaryentry{mem.res@ {\memgloterm{mem.res}}{\memglodesc{(\ref {mem.res})}} {\memgloref{}}|memjustarg}{637} -\glossaryentry{mem.res.syn@ {\memgloterm{mem.res.syn}}{\memglodesc{(\ref {mem.res.syn})}} {\memgloref{}}|memjustarg}{637} -\glossaryentry{mem.res.class@ {\memgloterm{mem.res.class}}{\memglodesc{(\ref {mem.res.class})}} {\memgloref{}}|memjustarg}{637} -\glossaryentry{mem.res.class.general@ {\memgloterm{mem.res.class.general}}{\memglodesc{(\ref {mem.res.class.general})}} {\memgloref{}}|memjustarg}{637} -\glossaryentry{mem.res.public@ {\memgloterm{mem.res.public}}{\memglodesc{(\ref {mem.res.public})}} {\memgloref{}}|memjustarg}{638} -\glossaryentry{mem.res.private@ {\memgloterm{mem.res.private}}{\memglodesc{(\ref {mem.res.private})}} {\memgloref{}}|memjustarg}{638} -\glossaryentry{mem.res.eq@ {\memgloterm{mem.res.eq}}{\memglodesc{(\ref {mem.res.eq})}} {\memgloref{}}|memjustarg}{639} -\glossaryentry{mem.poly.allocator.class@ {\memgloterm{mem.poly.allocator.class}}{\memglodesc{(\ref {mem.poly.allocator.class})}} {\memgloref{}}|memjustarg}{639} -\glossaryentry{mem.poly.allocator.class.general@ {\memgloterm{mem.poly.allocator.class.general}}{\memglodesc{(\ref {mem.poly.allocator.class.general})}} {\memgloref{}}|memjustarg}{639} -\glossaryentry{mem.poly.allocator.ctor@ {\memgloterm{mem.poly.allocator.ctor}}{\memglodesc{(\ref {mem.poly.allocator.ctor})}} {\memgloref{}}|memjustarg}{640} -\glossaryentry{mem.poly.allocator.mem@ {\memgloterm{mem.poly.allocator.mem}}{\memglodesc{(\ref {mem.poly.allocator.mem})}} {\memgloref{}}|memjustarg}{640} -\glossaryentry{mem.poly.allocator.eq@ {\memgloterm{mem.poly.allocator.eq}}{\memglodesc{(\ref {mem.poly.allocator.eq})}} {\memgloref{}}|memjustarg}{641} -\glossaryentry{mem.res.global@ {\memgloterm{mem.res.global}}{\memglodesc{(\ref {mem.res.global})}} {\memgloref{}}|memjustarg}{641} -\glossaryentry{mem.res.pool@ {\memgloterm{mem.res.pool}}{\memglodesc{(\ref {mem.res.pool})}} {\memgloref{}}|memjustarg}{642} -\glossaryentry{mem.res.pool.overview@ {\memgloterm{mem.res.pool.overview}}{\memglodesc{(\ref {mem.res.pool.overview})}} {\memgloref{}}|memjustarg}{642} -\glossaryentry{mem.res.pool.options@ {\memgloterm{mem.res.pool.options}}{\memglodesc{(\ref {mem.res.pool.options})}} {\memgloref{}}|memjustarg}{643} -\glossaryentry{mem.res.pool.ctor@ {\memgloterm{mem.res.pool.ctor}}{\memglodesc{(\ref {mem.res.pool.ctor})}} {\memgloref{}}|memjustarg}{643} -\glossaryentry{mem.res.pool.mem@ {\memgloterm{mem.res.pool.mem}}{\memglodesc{(\ref {mem.res.pool.mem})}} {\memgloref{}}|memjustarg}{644} -\glossaryentry{mem.res.monotonic.buffer@ {\memgloterm{mem.res.monotonic.buffer}}{\memglodesc{(\ref {mem.res.monotonic.buffer})}} {\memgloref{}}|memjustarg}{644} -\glossaryentry{mem.res.monotonic.buffer.general@ {\memgloterm{mem.res.monotonic.buffer.general}}{\memglodesc{(\ref {mem.res.monotonic.buffer.general})}} {\memgloref{}}|memjustarg}{644} -\glossaryentry{mem.res.monotonic.buffer.ctor@ {\memgloterm{mem.res.monotonic.buffer.ctor}}{\memglodesc{(\ref {mem.res.monotonic.buffer.ctor})}} {\memgloref{}}|memjustarg}{645} -\glossaryentry{mem.res.monotonic.buffer.mem@ {\memgloterm{mem.res.monotonic.buffer.mem}}{\memglodesc{(\ref {mem.res.monotonic.buffer.mem})}} {\memgloref{}}|memjustarg}{645} -\glossaryentry{allocator.adaptor@ {\memgloterm{allocator.adaptor}}{\memglodesc{(\ref {allocator.adaptor})}} {\memgloref{}}|memjustarg}{646} -\glossaryentry{allocator.adaptor.syn@ {\memgloterm{allocator.adaptor.syn}}{\memglodesc{(\ref {allocator.adaptor.syn})}} {\memgloref{}}|memjustarg}{646} -\glossaryentry{allocator.adaptor.types@ {\memgloterm{allocator.adaptor.types}}{\memglodesc{(\ref {allocator.adaptor.types})}} {\memgloref{}}|memjustarg}{647} -\glossaryentry{allocator.adaptor.cnstr@ {\memgloterm{allocator.adaptor.cnstr}}{\memglodesc{(\ref {allocator.adaptor.cnstr})}} {\memgloref{}}|memjustarg}{648} -\glossaryentry{allocator.adaptor.members@ {\memgloterm{allocator.adaptor.members}}{\memglodesc{(\ref {allocator.adaptor.members})}} {\memgloref{}}|memjustarg}{648} -\glossaryentry{scoped.adaptor.operators@ {\memgloterm{scoped.adaptor.operators}}{\memglodesc{(\ref {scoped.adaptor.operators})}} {\memgloref{}}|memjustarg}{649} -\glossaryentry{meta@ {\memgloterm{meta}}{\memglodesc{(\ref {meta})}} {\memgloref{}}|memjustarg}{650} -\glossaryentry{meta.general@ {\memgloterm{meta.general}}{\memglodesc{(\ref {meta.general})}} {\memgloref{}}|memjustarg}{650} -\glossaryentry{intseq@ {\memgloterm{intseq}}{\memglodesc{(\ref {intseq})}} {\memgloref{}}|memjustarg}{650} -\glossaryentry{intseq.general@ {\memgloterm{intseq.general}}{\memglodesc{(\ref {intseq.general})}} {\memgloref{}}|memjustarg}{650} -\glossaryentry{intseq.intseq@ {\memgloterm{intseq.intseq}}{\memglodesc{(\ref {intseq.intseq})}} {\memgloref{}}|memjustarg}{650} -\glossaryentry{intseq.make@ {\memgloterm{intseq.make}}{\memglodesc{(\ref {intseq.make})}} {\memgloref{}}|memjustarg}{650} -\glossaryentry{type.traits@ {\memgloterm{type.traits}}{\memglodesc{(\ref {type.traits})}} {\memgloref{}}|memjustarg}{650} -\glossaryentry{type.traits.general@ {\memgloterm{type.traits.general}}{\memglodesc{(\ref {type.traits.general})}} {\memgloref{}}|memjustarg}{650} -\glossaryentry{meta.rqmts@ {\memgloterm{meta.rqmts}}{\memglodesc{(\ref {meta.rqmts})}} {\memgloref{}}|memjustarg}{651} -\glossaryentry{meta.type.synop@ {\memgloterm{meta.type.synop}}{\memglodesc{(\ref {meta.type.synop})}} {\memgloref{}}|memjustarg}{651} -\glossaryentry{meta.help@ {\memgloterm{meta.help}}{\memglodesc{(\ref {meta.help})}} {\memgloref{}}|memjustarg}{658} -\glossaryentry{meta.unary@ {\memgloterm{meta.unary}}{\memglodesc{(\ref {meta.unary})}} {\memgloref{}}|memjustarg}{658} -\glossaryentry{meta.unary.general@ {\memgloterm{meta.unary.general}}{\memglodesc{(\ref {meta.unary.general})}} {\memgloref{}}|memjustarg}{658} -\glossaryentry{meta.unary.cat@ {\memgloterm{meta.unary.cat}}{\memglodesc{(\ref {meta.unary.cat})}} {\memgloref{}}|memjustarg}{658} -\glossaryentry{meta.unary.comp@ {\memgloterm{meta.unary.comp}}{\memglodesc{(\ref {meta.unary.comp})}} {\memgloref{}}|memjustarg}{659} -\glossaryentry{meta.unary.prop@ {\memgloterm{meta.unary.prop}}{\memglodesc{(\ref {meta.unary.prop})}} {\memgloref{}}|memjustarg}{659} -\glossaryentry{meta.unary.prop.query@ {\memgloterm{meta.unary.prop.query}}{\memglodesc{(\ref {meta.unary.prop.query})}} {\memgloref{}}|memjustarg}{666} -\glossaryentry{meta.rel@ {\memgloterm{meta.rel}}{\memglodesc{(\ref {meta.rel})}} {\memgloref{}}|memjustarg}{667} -\glossaryentry{meta.trans@ {\memgloterm{meta.trans}}{\memglodesc{(\ref {meta.trans})}} {\memgloref{}}|memjustarg}{669} -\glossaryentry{meta.trans.general@ {\memgloterm{meta.trans.general}}{\memglodesc{(\ref {meta.trans.general})}} {\memgloref{}}|memjustarg}{669} -\glossaryentry{meta.trans.cv@ {\memgloterm{meta.trans.cv}}{\memglodesc{(\ref {meta.trans.cv})}} {\memgloref{}}|memjustarg}{669} -\glossaryentry{meta.trans.ref@ {\memgloterm{meta.trans.ref}}{\memglodesc{(\ref {meta.trans.ref})}} {\memgloref{}}|memjustarg}{669} -\glossaryentry{meta.trans.sign@ {\memgloterm{meta.trans.sign}}{\memglodesc{(\ref {meta.trans.sign})}} {\memgloref{}}|memjustarg}{670} -\glossaryentry{meta.trans.arr@ {\memgloterm{meta.trans.arr}}{\memglodesc{(\ref {meta.trans.arr})}} {\memgloref{}}|memjustarg}{670} -\glossaryentry{meta.trans.ptr@ {\memgloterm{meta.trans.ptr}}{\memglodesc{(\ref {meta.trans.ptr})}} {\memgloref{}}|memjustarg}{671} -\glossaryentry{meta.trans.other@ {\memgloterm{meta.trans.other}}{\memglodesc{(\ref {meta.trans.other})}} {\memgloref{}}|memjustarg}{671} -\glossaryentry{meta.logical@ {\memgloterm{meta.logical}}{\memglodesc{(\ref {meta.logical})}} {\memgloref{}}|memjustarg}{674} -\glossaryentry{meta.member@ {\memgloterm{meta.member}}{\memglodesc{(\ref {meta.member})}} {\memgloref{}}|memjustarg}{675} -\glossaryentry{meta.const.eval@ {\memgloterm{meta.const.eval}}{\memglodesc{(\ref {meta.const.eval})}} {\memgloref{}}|memjustarg}{675} -\glossaryentry{ratio@ {\memgloterm{ratio}}{\memglodesc{(\ref {ratio})}} {\memgloref{}}|memjustarg}{676} -\glossaryentry{ratio.general@ {\memgloterm{ratio.general}}{\memglodesc{(\ref {ratio.general})}} {\memgloref{}}|memjustarg}{676} -\glossaryentry{ratio.syn@ {\memgloterm{ratio.syn}}{\memglodesc{(\ref {ratio.syn})}} {\memgloref{}}|memjustarg}{676} -\glossaryentry{ratio.ratio@ {\memgloterm{ratio.ratio}}{\memglodesc{(\ref {ratio.ratio})}} {\memgloref{}}|memjustarg}{677} -\glossaryentry{ratio.arithmetic@ {\memgloterm{ratio.arithmetic}}{\memglodesc{(\ref {ratio.arithmetic})}} {\memgloref{}}|memjustarg}{677} -\glossaryentry{ratio.comparison@ {\memgloterm{ratio.comparison}}{\memglodesc{(\ref {ratio.comparison})}} {\memgloref{}}|memjustarg}{678} -\glossaryentry{ratio.si@ {\memgloterm{ratio.si}}{\memglodesc{(\ref {ratio.si})}} {\memgloref{}}|memjustarg}{678} -\glossaryentry{utilities@ {\memgloterm{utilities}}{\memglodesc{(\ref {utilities})}} {\memgloref{}}|memjustarg}{679} -\glossaryentry{utilities.general@ {\memgloterm{utilities.general}}{\memglodesc{(\ref {utilities.general})}} {\memgloref{}}|memjustarg}{679} -\glossaryentry{utility@ {\memgloterm{utility}}{\memglodesc{(\ref {utility})}} {\memgloref{}}|memjustarg}{679} -\glossaryentry{utility.syn@ {\memgloterm{utility.syn}}{\memglodesc{(\ref {utility.syn})}} {\memgloref{}}|memjustarg}{679} -\glossaryentry{utility.swap@ {\memgloterm{utility.swap}}{\memglodesc{(\ref {utility.swap})}} {\memgloref{}}|memjustarg}{682} -\glossaryentry{utility.exchange@ {\memgloterm{utility.exchange}}{\memglodesc{(\ref {utility.exchange})}} {\memgloref{}}|memjustarg}{682} -\glossaryentry{forward@ {\memgloterm{forward}}{\memglodesc{(\ref {forward})}} {\memgloref{}}|memjustarg}{682} -\glossaryentry{utility.as.const@ {\memgloterm{utility.as.const}}{\memglodesc{(\ref {utility.as.const})}} {\memgloref{}}|memjustarg}{684} -\glossaryentry{declval@ {\memgloterm{declval}}{\memglodesc{(\ref {declval})}} {\memgloref{}}|memjustarg}{684} -\glossaryentry{utility.intcmp@ {\memgloterm{utility.intcmp}}{\memglodesc{(\ref {utility.intcmp})}} {\memgloref{}}|memjustarg}{684} -\glossaryentry{utility.underlying@ {\memgloterm{utility.underlying}}{\memglodesc{(\ref {utility.underlying})}} {\memgloref{}}|memjustarg}{685} -\glossaryentry{utility.unreachable@ {\memgloterm{utility.unreachable}}{\memglodesc{(\ref {utility.unreachable})}} {\memgloref{}}|memjustarg}{685} -\glossaryentry{pairs@ {\memgloterm{pairs}}{\memglodesc{(\ref {pairs})}} {\memgloref{}}|memjustarg}{686} -\glossaryentry{pairs.general@ {\memgloterm{pairs.general}}{\memglodesc{(\ref {pairs.general})}} {\memgloref{}}|memjustarg}{686} -\glossaryentry{pairs.pair@ {\memgloterm{pairs.pair}}{\memglodesc{(\ref {pairs.pair})}} {\memgloref{}}|memjustarg}{686} -\glossaryentry{pairs.spec@ {\memgloterm{pairs.spec}}{\memglodesc{(\ref {pairs.spec})}} {\memgloref{}}|memjustarg}{690} -\glossaryentry{pair.astuple@ {\memgloterm{pair.astuple}}{\memglodesc{(\ref {pair.astuple})}} {\memgloref{}}|memjustarg}{690} -\glossaryentry{pair.piecewise@ {\memgloterm{pair.piecewise}}{\memglodesc{(\ref {pair.piecewise})}} {\memgloref{}}|memjustarg}{691} -\glossaryentry{tuple@ {\memgloterm{tuple}}{\memglodesc{(\ref {tuple})}} {\memgloref{}}|memjustarg}{691} -\glossaryentry{tuple.general@ {\memgloterm{tuple.general}}{\memglodesc{(\ref {tuple.general})}} {\memgloref{}}|memjustarg}{691} -\glossaryentry{tuple.syn@ {\memgloterm{tuple.syn}}{\memglodesc{(\ref {tuple.syn})}} {\memgloref{}}|memjustarg}{692} -\glossaryentry{tuple.like@ {\memgloterm{tuple.like}}{\memglodesc{(\ref {tuple.like})}} {\memgloref{}}|memjustarg}{693} -\glossaryentry{tuple.tuple@ {\memgloterm{tuple.tuple}}{\memglodesc{(\ref {tuple.tuple})}} {\memgloref{}}|memjustarg}{693} -\glossaryentry{tuple.cnstr@ {\memgloterm{tuple.cnstr}}{\memglodesc{(\ref {tuple.cnstr})}} {\memgloref{}}|memjustarg}{695} -\glossaryentry{tuple.assign@ {\memgloterm{tuple.assign}}{\memglodesc{(\ref {tuple.assign})}} {\memgloref{}}|memjustarg}{698} -\glossaryentry{tuple.swap@ {\memgloterm{tuple.swap}}{\memglodesc{(\ref {tuple.swap})}} {\memgloref{}}|memjustarg}{700} -\glossaryentry{tuple.creation@ {\memgloterm{tuple.creation}}{\memglodesc{(\ref {tuple.creation})}} {\memgloref{}}|memjustarg}{701} -\glossaryentry{tuple.apply@ {\memgloterm{tuple.apply}}{\memglodesc{(\ref {tuple.apply})}} {\memgloref{}}|memjustarg}{702} -\glossaryentry{tuple.helper@ {\memgloterm{tuple.helper}}{\memglodesc{(\ref {tuple.helper})}} {\memgloref{}}|memjustarg}{702} -\glossaryentry{tuple.elem@ {\memgloterm{tuple.elem}}{\memglodesc{(\ref {tuple.elem})}} {\memgloref{}}|memjustarg}{703} -\glossaryentry{tuple.rel@ {\memgloterm{tuple.rel}}{\memglodesc{(\ref {tuple.rel})}} {\memgloref{}}|memjustarg}{704} -\glossaryentry{tuple.common.ref@ {\memgloterm{tuple.common.ref}}{\memglodesc{(\ref {tuple.common.ref})}} {\memgloref{}}|memjustarg}{704} -\glossaryentry{tuple.traits@ {\memgloterm{tuple.traits}}{\memglodesc{(\ref {tuple.traits})}} {\memgloref{}}|memjustarg}{705} -\glossaryentry{tuple.special@ {\memgloterm{tuple.special}}{\memglodesc{(\ref {tuple.special})}} {\memgloref{}}|memjustarg}{705} -\glossaryentry{optional@ {\memgloterm{optional}}{\memglodesc{(\ref {optional})}} {\memgloref{}}|memjustarg}{705} -\glossaryentry{optional.general@ {\memgloterm{optional.general}}{\memglodesc{(\ref {optional.general})}} {\memgloref{}}|memjustarg}{705} -\glossaryentry{optional.syn@ {\memgloterm{optional.syn}}{\memglodesc{(\ref {optional.syn})}} {\memgloref{}}|memjustarg}{705} -\glossaryentry{optional.optional@ {\memgloterm{optional.optional}}{\memglodesc{(\ref {optional.optional})}} {\memgloref{}}|memjustarg}{707} -\glossaryentry{optional.optional.general@ {\memgloterm{optional.optional.general}}{\memglodesc{(\ref {optional.optional.general})}} {\memgloref{}}|memjustarg}{707} -\glossaryentry{optional.ctor@ {\memgloterm{optional.ctor}}{\memglodesc{(\ref {optional.ctor})}} {\memgloref{}}|memjustarg}{708} -\glossaryentry{optional.dtor@ {\memgloterm{optional.dtor}}{\memglodesc{(\ref {optional.dtor})}} {\memgloref{}}|memjustarg}{710} -\glossaryentry{optional.assign@ {\memgloterm{optional.assign}}{\memglodesc{(\ref {optional.assign})}} {\memgloref{}}|memjustarg}{710} -\glossaryentry{optional.swap@ {\memgloterm{optional.swap}}{\memglodesc{(\ref {optional.swap})}} {\memgloref{}}|memjustarg}{713} -\glossaryentry{optional.observe@ {\memgloterm{optional.observe}}{\memglodesc{(\ref {optional.observe})}} {\memgloref{}}|memjustarg}{713} -\glossaryentry{optional.monadic@ {\memgloterm{optional.monadic}}{\memglodesc{(\ref {optional.monadic})}} {\memgloref{}}|memjustarg}{714} -\glossaryentry{optional.mod@ {\memgloterm{optional.mod}}{\memglodesc{(\ref {optional.mod})}} {\memgloref{}}|memjustarg}{715} -\glossaryentry{optional.nullopt@ {\memgloterm{optional.nullopt}}{\memglodesc{(\ref {optional.nullopt})}} {\memgloref{}}|memjustarg}{715} -\glossaryentry{optional.bad.access@ {\memgloterm{optional.bad.access}}{\memglodesc{(\ref {optional.bad.access})}} {\memgloref{}}|memjustarg}{716} -\glossaryentry{optional.relops@ {\memgloterm{optional.relops}}{\memglodesc{(\ref {optional.relops})}} {\memgloref{}}|memjustarg}{716} -\glossaryentry{optional.nullops@ {\memgloterm{optional.nullops}}{\memglodesc{(\ref {optional.nullops})}} {\memgloref{}}|memjustarg}{717} -\glossaryentry{optional.comp.with.t@ {\memgloterm{optional.comp.with.t}}{\memglodesc{(\ref {optional.comp.with.t})}} {\memgloref{}}|memjustarg}{717} -\glossaryentry{optional.specalg@ {\memgloterm{optional.specalg}}{\memglodesc{(\ref {optional.specalg})}} {\memgloref{}}|memjustarg}{718} -\glossaryentry{optional.hash@ {\memgloterm{optional.hash}}{\memglodesc{(\ref {optional.hash})}} {\memgloref{}}|memjustarg}{718} -\glossaryentry{variant@ {\memgloterm{variant}}{\memglodesc{(\ref {variant})}} {\memgloref{}}|memjustarg}{718} -\glossaryentry{variant.general@ {\memgloterm{variant.general}}{\memglodesc{(\ref {variant.general})}} {\memgloref{}}|memjustarg}{718} -\glossaryentry{variant.syn@ {\memgloterm{variant.syn}}{\memglodesc{(\ref {variant.syn})}} {\memgloref{}}|memjustarg}{718} -\glossaryentry{variant.variant@ {\memgloterm{variant.variant}}{\memglodesc{(\ref {variant.variant})}} {\memgloref{}}|memjustarg}{720} -\glossaryentry{variant.variant.general@ {\memgloterm{variant.variant.general}}{\memglodesc{(\ref {variant.variant.general})}} {\memgloref{}}|memjustarg}{720} -\glossaryentry{variant.ctor@ {\memgloterm{variant.ctor}}{\memglodesc{(\ref {variant.ctor})}} {\memgloref{}}|memjustarg}{721} -\glossaryentry{variant.dtor@ {\memgloterm{variant.dtor}}{\memglodesc{(\ref {variant.dtor})}} {\memgloref{}}|memjustarg}{723} -\glossaryentry{variant.assign@ {\memgloterm{variant.assign}}{\memglodesc{(\ref {variant.assign})}} {\memgloref{}}|memjustarg}{723} -\glossaryentry{variant.mod@ {\memgloterm{variant.mod}}{\memglodesc{(\ref {variant.mod})}} {\memgloref{}}|memjustarg}{725} -\glossaryentry{variant.status@ {\memgloterm{variant.status}}{\memglodesc{(\ref {variant.status})}} {\memgloref{}}|memjustarg}{725} -\glossaryentry{variant.swap@ {\memgloterm{variant.swap}}{\memglodesc{(\ref {variant.swap})}} {\memgloref{}}|memjustarg}{726} -\glossaryentry{variant.helper@ {\memgloterm{variant.helper}}{\memglodesc{(\ref {variant.helper})}} {\memgloref{}}|memjustarg}{726} -\glossaryentry{variant.get@ {\memgloterm{variant.get}}{\memglodesc{(\ref {variant.get})}} {\memgloref{}}|memjustarg}{726} -\glossaryentry{variant.relops@ {\memgloterm{variant.relops}}{\memglodesc{(\ref {variant.relops})}} {\memgloref{}}|memjustarg}{727} -\glossaryentry{variant.visit@ {\memgloterm{variant.visit}}{\memglodesc{(\ref {variant.visit})}} {\memgloref{}}|memjustarg}{728} -\glossaryentry{variant.monostate@ {\memgloterm{variant.monostate}}{\memglodesc{(\ref {variant.monostate})}} {\memgloref{}}|memjustarg}{729} -\glossaryentry{variant.monostate.relops@ {\memgloterm{variant.monostate.relops}}{\memglodesc{(\ref {variant.monostate.relops})}} {\memgloref{}}|memjustarg}{729} -\glossaryentry{variant.specalg@ {\memgloterm{variant.specalg}}{\memglodesc{(\ref {variant.specalg})}} {\memgloref{}}|memjustarg}{729} -\glossaryentry{variant.bad.access@ {\memgloterm{variant.bad.access}}{\memglodesc{(\ref {variant.bad.access})}} {\memgloref{}}|memjustarg}{729} -\glossaryentry{variant.hash@ {\memgloterm{variant.hash}}{\memglodesc{(\ref {variant.hash})}} {\memgloref{}}|memjustarg}{729} -\glossaryentry{any@ {\memgloterm{any}}{\memglodesc{(\ref {any})}} {\memgloref{}}|memjustarg}{730} -\glossaryentry{any.general@ {\memgloterm{any.general}}{\memglodesc{(\ref {any.general})}} {\memgloref{}}|memjustarg}{730} -\glossaryentry{any.synop@ {\memgloterm{any.synop}}{\memglodesc{(\ref {any.synop})}} {\memgloref{}}|memjustarg}{730} -\glossaryentry{any.bad.any.cast@ {\memgloterm{any.bad.any.cast}}{\memglodesc{(\ref {any.bad.any.cast})}} {\memgloref{}}|memjustarg}{730} -\glossaryentry{any.class@ {\memgloterm{any.class}}{\memglodesc{(\ref {any.class})}} {\memgloref{}}|memjustarg}{730} -\glossaryentry{any.class.general@ {\memgloterm{any.class.general}}{\memglodesc{(\ref {any.class.general})}} {\memgloref{}}|memjustarg}{730} -\glossaryentry{any.cons@ {\memgloterm{any.cons}}{\memglodesc{(\ref {any.cons})}} {\memgloref{}}|memjustarg}{731} -\glossaryentry{any.assign@ {\memgloterm{any.assign}}{\memglodesc{(\ref {any.assign})}} {\memgloref{}}|memjustarg}{732} -\glossaryentry{any.modifiers@ {\memgloterm{any.modifiers}}{\memglodesc{(\ref {any.modifiers})}} {\memgloref{}}|memjustarg}{733} -\glossaryentry{any.observers@ {\memgloterm{any.observers}}{\memglodesc{(\ref {any.observers})}} {\memgloref{}}|memjustarg}{733} -\glossaryentry{any.nonmembers@ {\memgloterm{any.nonmembers}}{\memglodesc{(\ref {any.nonmembers})}} {\memgloref{}}|memjustarg}{734} -\glossaryentry{expected@ {\memgloterm{expected}}{\memglodesc{(\ref {expected})}} {\memgloref{}}|memjustarg}{735} -\glossaryentry{expected.general@ {\memgloterm{expected.general}}{\memglodesc{(\ref {expected.general})}} {\memgloref{}}|memjustarg}{735} -\glossaryentry{expected.syn@ {\memgloterm{expected.syn}}{\memglodesc{(\ref {expected.syn})}} {\memgloref{}}|memjustarg}{735} -\glossaryentry{expected.unexpected@ {\memgloterm{expected.unexpected}}{\memglodesc{(\ref {expected.unexpected})}} {\memgloref{}}|memjustarg}{735} -\glossaryentry{expected.un.general@ {\memgloterm{expected.un.general}}{\memglodesc{(\ref {expected.un.general})}} {\memgloref{}}|memjustarg}{735} -\glossaryentry{expected.un.cons@ {\memgloterm{expected.un.cons}}{\memglodesc{(\ref {expected.un.cons})}} {\memgloref{}}|memjustarg}{736} -\glossaryentry{expected.un.obs@ {\memgloterm{expected.un.obs}}{\memglodesc{(\ref {expected.un.obs})}} {\memgloref{}}|memjustarg}{736} -\glossaryentry{expected.un.swap@ {\memgloterm{expected.un.swap}}{\memglodesc{(\ref {expected.un.swap})}} {\memgloref{}}|memjustarg}{736} -\glossaryentry{expected.un.eq@ {\memgloterm{expected.un.eq}}{\memglodesc{(\ref {expected.un.eq})}} {\memgloref{}}|memjustarg}{737} -\glossaryentry{expected.bad@ {\memgloterm{expected.bad}}{\memglodesc{(\ref {expected.bad})}} {\memgloref{}}|memjustarg}{737} -\glossaryentry{expected.bad.void@ {\memgloterm{expected.bad.void}}{\memglodesc{(\ref {expected.bad.void})}} {\memgloref{}}|memjustarg}{737} -\glossaryentry{expected.expected@ {\memgloterm{expected.expected}}{\memglodesc{(\ref {expected.expected})}} {\memgloref{}}|memjustarg}{738} -\glossaryentry{expected.object.general@ {\memgloterm{expected.object.general}}{\memglodesc{(\ref {expected.object.general})}} {\memgloref{}}|memjustarg}{738} -\glossaryentry{expected.object.cons@ {\memgloterm{expected.object.cons}}{\memglodesc{(\ref {expected.object.cons})}} {\memgloref{}}|memjustarg}{740} -\glossaryentry{expected.object.dtor@ {\memgloterm{expected.object.dtor}}{\memglodesc{(\ref {expected.object.dtor})}} {\memgloref{}}|memjustarg}{742} -\glossaryentry{expected.object.assign@ {\memgloterm{expected.object.assign}}{\memglodesc{(\ref {expected.object.assign})}} {\memgloref{}}|memjustarg}{742} -\glossaryentry{expected.object.swap@ {\memgloterm{expected.object.swap}}{\memglodesc{(\ref {expected.object.swap})}} {\memgloref{}}|memjustarg}{744} -\glossaryentry{expected.object.obs@ {\memgloterm{expected.object.obs}}{\memglodesc{(\ref {expected.object.obs})}} {\memgloref{}}|memjustarg}{745} -\glossaryentry{expected.object.monadic@ {\memgloterm{expected.object.monadic}}{\memglodesc{(\ref {expected.object.monadic})}} {\memgloref{}}|memjustarg}{746} -\glossaryentry{expected.object.eq@ {\memgloterm{expected.object.eq}}{\memglodesc{(\ref {expected.object.eq})}} {\memgloref{}}|memjustarg}{748} -\glossaryentry{expected.void@ {\memgloterm{expected.void}}{\memglodesc{(\ref {expected.void})}} {\memgloref{}}|memjustarg}{749} -\glossaryentry{expected.void.general@ {\memgloterm{expected.void.general}}{\memglodesc{(\ref {expected.void.general})}} {\memgloref{}}|memjustarg}{749} -\glossaryentry{expected.void.cons@ {\memgloterm{expected.void.cons}}{\memglodesc{(\ref {expected.void.cons})}} {\memgloref{}}|memjustarg}{750} -\glossaryentry{expected.void.dtor@ {\memgloterm{expected.void.dtor}}{\memglodesc{(\ref {expected.void.dtor})}} {\memgloref{}}|memjustarg}{751} -\glossaryentry{expected.void.assign@ {\memgloterm{expected.void.assign}}{\memglodesc{(\ref {expected.void.assign})}} {\memgloref{}}|memjustarg}{752} -\glossaryentry{expected.void.swap@ {\memgloterm{expected.void.swap}}{\memglodesc{(\ref {expected.void.swap})}} {\memgloref{}}|memjustarg}{752} -\glossaryentry{expected.void.obs@ {\memgloterm{expected.void.obs}}{\memglodesc{(\ref {expected.void.obs})}} {\memgloref{}}|memjustarg}{753} -\glossaryentry{expected.void.monadic@ {\memgloterm{expected.void.monadic}}{\memglodesc{(\ref {expected.void.monadic})}} {\memgloref{}}|memjustarg}{753} -\glossaryentry{expected.void.eq@ {\memgloterm{expected.void.eq}}{\memglodesc{(\ref {expected.void.eq})}} {\memgloref{}}|memjustarg}{755} -\glossaryentry{bitset@ {\memgloterm{bitset}}{\memglodesc{(\ref {bitset})}} {\memgloref{}}|memjustarg}{755} -\glossaryentry{bitset.syn@ {\memgloterm{bitset.syn}}{\memglodesc{(\ref {bitset.syn})}} {\memgloref{}}|memjustarg}{755} -\glossaryentry{template.bitset@ {\memgloterm{template.bitset}}{\memglodesc{(\ref {template.bitset})}} {\memgloref{}}|memjustarg}{756} -\glossaryentry{template.bitset.general@ {\memgloterm{template.bitset.general}}{\memglodesc{(\ref {template.bitset.general})}} {\memgloref{}}|memjustarg}{756} -\glossaryentry{bitset.cons@ {\memgloterm{bitset.cons}}{\memglodesc{(\ref {bitset.cons})}} {\memgloref{}}|memjustarg}{757} -\glossaryentry{bitset.members@ {\memgloterm{bitset.members}}{\memglodesc{(\ref {bitset.members})}} {\memgloref{}}|memjustarg}{758} -\glossaryentry{bitset.hash@ {\memgloterm{bitset.hash}}{\memglodesc{(\ref {bitset.hash})}} {\memgloref{}}|memjustarg}{760} -\glossaryentry{bitset.operators@ {\memgloterm{bitset.operators}}{\memglodesc{(\ref {bitset.operators})}} {\memgloref{}}|memjustarg}{760} -\glossaryentry{function.objects@ {\memgloterm{function.objects}}{\memglodesc{(\ref {function.objects})}} {\memgloref{}}|memjustarg}{761} -\glossaryentry{function.objects.general@ {\memgloterm{function.objects.general}}{\memglodesc{(\ref {function.objects.general})}} {\memgloref{}}|memjustarg}{761} -\glossaryentry{functional.syn@ {\memgloterm{functional.syn}}{\memglodesc{(\ref {functional.syn})}} {\memgloref{}}|memjustarg}{761} -\glossaryentry{func.def@ {\memgloterm{func.def}}{\memglodesc{(\ref {func.def})}} {\memgloref{}}|memjustarg}{764} -\glossaryentry{func.require@ {\memgloterm{func.require}}{\memglodesc{(\ref {func.require})}} {\memgloref{}}|memjustarg}{764} -\glossaryentry{func.invoke@ {\memgloterm{func.invoke}}{\memglodesc{(\ref {func.invoke})}} {\memgloref{}}|memjustarg}{765} -\glossaryentry{refwrap@ {\memgloterm{refwrap}}{\memglodesc{(\ref {refwrap})}} {\memgloref{}}|memjustarg}{766} -\glossaryentry{refwrap.general@ {\memgloterm{refwrap.general}}{\memglodesc{(\ref {refwrap.general})}} {\memgloref{}}|memjustarg}{766} -\glossaryentry{refwrap.const@ {\memgloterm{refwrap.const}}{\memglodesc{(\ref {refwrap.const})}} {\memgloref{}}|memjustarg}{766} -\glossaryentry{refwrap.assign@ {\memgloterm{refwrap.assign}}{\memglodesc{(\ref {refwrap.assign})}} {\memgloref{}}|memjustarg}{766} -\glossaryentry{refwrap.access@ {\memgloterm{refwrap.access}}{\memglodesc{(\ref {refwrap.access})}} {\memgloref{}}|memjustarg}{766} -\glossaryentry{refwrap.invoke@ {\memgloterm{refwrap.invoke}}{\memglodesc{(\ref {refwrap.invoke})}} {\memgloref{}}|memjustarg}{767} -\glossaryentry{refwrap.helpers@ {\memgloterm{refwrap.helpers}}{\memglodesc{(\ref {refwrap.helpers})}} {\memgloref{}}|memjustarg}{767} -\glossaryentry{refwrap.common.ref@ {\memgloterm{refwrap.common.ref}}{\memglodesc{(\ref {refwrap.common.ref})}} {\memgloref{}}|memjustarg}{767} -\glossaryentry{arithmetic.operations@ {\memgloterm{arithmetic.operations}}{\memglodesc{(\ref {arithmetic.operations})}} {\memgloref{}}|memjustarg}{767} -\glossaryentry{arithmetic.operations.general@ {\memgloterm{arithmetic.operations.general}}{\memglodesc{(\ref {arithmetic.operations.general})}} {\memgloref{}}|memjustarg}{767} -\glossaryentry{arithmetic.operations.plus@ {\memgloterm{arithmetic.operations.plus}}{\memglodesc{(\ref {arithmetic.operations.plus})}} {\memgloref{}}|memjustarg}{768} -\glossaryentry{arithmetic.operations.minus@ {\memgloterm{arithmetic.operations.minus}}{\memglodesc{(\ref {arithmetic.operations.minus})}} {\memgloref{}}|memjustarg}{768} -\glossaryentry{arithmetic.operations.multiplies@ {\memgloterm{arithmetic.operations.multiplies}}{\memglodesc{(\ref {arithmetic.operations.multiplies})}} {\memgloref{}}|memjustarg}{768} -\glossaryentry{arithmetic.operations.divides@ {\memgloterm{arithmetic.operations.divides}}{\memglodesc{(\ref {arithmetic.operations.divides})}} {\memgloref{}}|memjustarg}{768} -\glossaryentry{arithmetic.operations.modulus@ {\memgloterm{arithmetic.operations.modulus}}{\memglodesc{(\ref {arithmetic.operations.modulus})}} {\memgloref{}}|memjustarg}{769} -\glossaryentry{arithmetic.operations.negate@ {\memgloterm{arithmetic.operations.negate}}{\memglodesc{(\ref {arithmetic.operations.negate})}} {\memgloref{}}|memjustarg}{769} -\glossaryentry{comparisons@ {\memgloterm{comparisons}}{\memglodesc{(\ref {comparisons})}} {\memgloref{}}|memjustarg}{769} -\glossaryentry{comparisons.general@ {\memgloterm{comparisons.general}}{\memglodesc{(\ref {comparisons.general})}} {\memgloref{}}|memjustarg}{769} -\glossaryentry{comparisons.equal.to@ {\memgloterm{comparisons.equal.to}}{\memglodesc{(\ref {comparisons.equal.to})}} {\memgloref{}}|memjustarg}{770} -\glossaryentry{comparisons.not.equal.to@ {\memgloterm{comparisons.not.equal.to}}{\memglodesc{(\ref {comparisons.not.equal.to})}} {\memgloref{}}|memjustarg}{770} -\glossaryentry{comparisons.greater@ {\memgloterm{comparisons.greater}}{\memglodesc{(\ref {comparisons.greater})}} {\memgloref{}}|memjustarg}{770} -\glossaryentry{comparisons.less@ {\memgloterm{comparisons.less}}{\memglodesc{(\ref {comparisons.less})}} {\memgloref{}}|memjustarg}{771} -\glossaryentry{comparisons.greater.equal@ {\memgloterm{comparisons.greater.equal}}{\memglodesc{(\ref {comparisons.greater.equal})}} {\memgloref{}}|memjustarg}{771} -\glossaryentry{comparisons.less.equal@ {\memgloterm{comparisons.less.equal}}{\memglodesc{(\ref {comparisons.less.equal})}} {\memgloref{}}|memjustarg}{771} -\glossaryentry{comparisons.three.way@ {\memgloterm{comparisons.three.way}}{\memglodesc{(\ref {comparisons.three.way})}} {\memgloref{}}|memjustarg}{772} -\glossaryentry{range.cmp@ {\memgloterm{range.cmp}}{\memglodesc{(\ref {range.cmp})}} {\memgloref{}}|memjustarg}{772} -\glossaryentry{logical.operations@ {\memgloterm{logical.operations}}{\memglodesc{(\ref {logical.operations})}} {\memgloref{}}|memjustarg}{774} -\glossaryentry{logical.operations.general@ {\memgloterm{logical.operations.general}}{\memglodesc{(\ref {logical.operations.general})}} {\memgloref{}}|memjustarg}{774} -\glossaryentry{logical.operations.and@ {\memgloterm{logical.operations.and}}{\memglodesc{(\ref {logical.operations.and})}} {\memgloref{}}|memjustarg}{774} -\glossaryentry{logical.operations.or@ {\memgloterm{logical.operations.or}}{\memglodesc{(\ref {logical.operations.or})}} {\memgloref{}}|memjustarg}{774} -\glossaryentry{logical.operations.not@ {\memgloterm{logical.operations.not}}{\memglodesc{(\ref {logical.operations.not})}} {\memgloref{}}|memjustarg}{774} -\glossaryentry{bitwise.operations@ {\memgloterm{bitwise.operations}}{\memglodesc{(\ref {bitwise.operations})}} {\memgloref{}}|memjustarg}{775} -\glossaryentry{bitwise.operations.general@ {\memgloterm{bitwise.operations.general}}{\memglodesc{(\ref {bitwise.operations.general})}} {\memgloref{}}|memjustarg}{775} -\glossaryentry{bitwise.operations.and@ {\memgloterm{bitwise.operations.and}}{\memglodesc{(\ref {bitwise.operations.and})}} {\memgloref{}}|memjustarg}{775} -\glossaryentry{bitwise.operations.or@ {\memgloterm{bitwise.operations.or}}{\memglodesc{(\ref {bitwise.operations.or})}} {\memgloref{}}|memjustarg}{775} -\glossaryentry{bitwise.operations.xor@ {\memgloterm{bitwise.operations.xor}}{\memglodesc{(\ref {bitwise.operations.xor})}} {\memgloref{}}|memjustarg}{775} -\glossaryentry{bitwise.operations.not@ {\memgloterm{bitwise.operations.not}}{\memglodesc{(\ref {bitwise.operations.not})}} {\memgloref{}}|memjustarg}{776} -\glossaryentry{func.identity@ {\memgloterm{func.identity}}{\memglodesc{(\ref {func.identity})}} {\memgloref{}}|memjustarg}{776} -\glossaryentry{func.not.fn@ {\memgloterm{func.not.fn}}{\memglodesc{(\ref {func.not.fn})}} {\memgloref{}}|memjustarg}{776} -\glossaryentry{func.bind.partial@ {\memgloterm{func.bind.partial}}{\memglodesc{(\ref {func.bind.partial})}} {\memgloref{}}|memjustarg}{776} -\glossaryentry{func.bind@ {\memgloterm{func.bind}}{\memglodesc{(\ref {func.bind})}} {\memgloref{}}|memjustarg}{777} -\glossaryentry{func.bind.general@ {\memgloterm{func.bind.general}}{\memglodesc{(\ref {func.bind.general})}} {\memgloref{}}|memjustarg}{777} -\glossaryentry{func.bind.isbind@ {\memgloterm{func.bind.isbind}}{\memglodesc{(\ref {func.bind.isbind})}} {\memgloref{}}|memjustarg}{777} -\glossaryentry{func.bind.isplace@ {\memgloterm{func.bind.isplace}}{\memglodesc{(\ref {func.bind.isplace})}} {\memgloref{}}|memjustarg}{777} -\glossaryentry{func.bind.bind@ {\memgloterm{func.bind.bind}}{\memglodesc{(\ref {func.bind.bind})}} {\memgloref{}}|memjustarg}{777} -\glossaryentry{func.bind.place@ {\memgloterm{func.bind.place}}{\memglodesc{(\ref {func.bind.place})}} {\memgloref{}}|memjustarg}{778} -\glossaryentry{func.memfn@ {\memgloterm{func.memfn}}{\memglodesc{(\ref {func.memfn})}} {\memgloref{}}|memjustarg}{779} -\glossaryentry{func.wrap@ {\memgloterm{func.wrap}}{\memglodesc{(\ref {func.wrap})}} {\memgloref{}}|memjustarg}{779} -\glossaryentry{func.wrap.general@ {\memgloterm{func.wrap.general}}{\memglodesc{(\ref {func.wrap.general})}} {\memgloref{}}|memjustarg}{779} -\glossaryentry{func.wrap.badcall@ {\memgloterm{func.wrap.badcall}}{\memglodesc{(\ref {func.wrap.badcall})}} {\memgloref{}}|memjustarg}{779} -\glossaryentry{func.wrap.func@ {\memgloterm{func.wrap.func}}{\memglodesc{(\ref {func.wrap.func})}} {\memgloref{}}|memjustarg}{779} -\glossaryentry{func.wrap.func.general@ {\memgloterm{func.wrap.func.general}}{\memglodesc{(\ref {func.wrap.func.general})}} {\memgloref{}}|memjustarg}{779} -\glossaryentry{func.wrap.func.con@ {\memgloterm{func.wrap.func.con}}{\memglodesc{(\ref {func.wrap.func.con})}} {\memgloref{}}|memjustarg}{780} -\glossaryentry{func.wrap.func.mod@ {\memgloterm{func.wrap.func.mod}}{\memglodesc{(\ref {func.wrap.func.mod})}} {\memgloref{}}|memjustarg}{782} -\glossaryentry{func.wrap.func.cap@ {\memgloterm{func.wrap.func.cap}}{\memglodesc{(\ref {func.wrap.func.cap})}} {\memgloref{}}|memjustarg}{782} -\glossaryentry{func.wrap.func.inv@ {\memgloterm{func.wrap.func.inv}}{\memglodesc{(\ref {func.wrap.func.inv})}} {\memgloref{}}|memjustarg}{782} -\glossaryentry{func.wrap.func.targ@ {\memgloterm{func.wrap.func.targ}}{\memglodesc{(\ref {func.wrap.func.targ})}} {\memgloref{}}|memjustarg}{782} -\glossaryentry{func.wrap.func.nullptr@ {\memgloterm{func.wrap.func.nullptr}}{\memglodesc{(\ref {func.wrap.func.nullptr})}} {\memgloref{}}|memjustarg}{782} -\glossaryentry{func.wrap.func.alg@ {\memgloterm{func.wrap.func.alg}}{\memglodesc{(\ref {func.wrap.func.alg})}} {\memgloref{}}|memjustarg}{782} -\glossaryentry{func.wrap.move@ {\memgloterm{func.wrap.move}}{\memglodesc{(\ref {func.wrap.move})}} {\memgloref{}}|memjustarg}{782} -\glossaryentry{func.wrap.move.general@ {\memgloterm{func.wrap.move.general}}{\memglodesc{(\ref {func.wrap.move.general})}} {\memgloref{}}|memjustarg}{782} -\glossaryentry{func.wrap.move.class@ {\memgloterm{func.wrap.move.class}}{\memglodesc{(\ref {func.wrap.move.class})}} {\memgloref{}}|memjustarg}{782} -\glossaryentry{func.wrap.move.ctor@ {\memgloterm{func.wrap.move.ctor}}{\memglodesc{(\ref {func.wrap.move.ctor})}} {\memgloref{}}|memjustarg}{783} -\glossaryentry{func.wrap.move.inv@ {\memgloterm{func.wrap.move.inv}}{\memglodesc{(\ref {func.wrap.move.inv})}} {\memgloref{}}|memjustarg}{785} -\glossaryentry{func.wrap.move.util@ {\memgloterm{func.wrap.move.util}}{\memglodesc{(\ref {func.wrap.move.util})}} {\memgloref{}}|memjustarg}{785} -\glossaryentry{func.search@ {\memgloterm{func.search}}{\memglodesc{(\ref {func.search})}} {\memgloref{}}|memjustarg}{785} -\glossaryentry{func.search.general@ {\memgloterm{func.search.general}}{\memglodesc{(\ref {func.search.general})}} {\memgloref{}}|memjustarg}{785} -\glossaryentry{func.search.default@ {\memgloterm{func.search.default}}{\memglodesc{(\ref {func.search.default})}} {\memgloref{}}|memjustarg}{786} -\glossaryentry{func.search.bm@ {\memgloterm{func.search.bm}}{\memglodesc{(\ref {func.search.bm})}} {\memgloref{}}|memjustarg}{786} -\glossaryentry{func.search.bmh@ {\memgloterm{func.search.bmh}}{\memglodesc{(\ref {func.search.bmh})}} {\memgloref{}}|memjustarg}{787} -\glossaryentry{unord.hash@ {\memgloterm{unord.hash}}{\memglodesc{(\ref {unord.hash})}} {\memgloref{}}|memjustarg}{788} -\glossaryentry{type.index@ {\memgloterm{type.index}}{\memglodesc{(\ref {type.index})}} {\memgloref{}}|memjustarg}{789} -\glossaryentry{type.index.synopsis@ {\memgloterm{type.index.synopsis}}{\memglodesc{(\ref {type.index.synopsis})}} {\memgloref{}}|memjustarg}{789} -\glossaryentry{type.index.overview@ {\memgloterm{type.index.overview}}{\memglodesc{(\ref {type.index.overview})}} {\memgloref{}}|memjustarg}{789} -\glossaryentry{type.index.members@ {\memgloterm{type.index.members}}{\memglodesc{(\ref {type.index.members})}} {\memgloref{}}|memjustarg}{789} -\glossaryentry{type.index.hash@ {\memgloterm{type.index.hash}}{\memglodesc{(\ref {type.index.hash})}} {\memgloref{}}|memjustarg}{790} -\glossaryentry{execpol@ {\memgloterm{execpol}}{\memglodesc{(\ref {execpol})}} {\memgloref{}}|memjustarg}{790} -\glossaryentry{execpol.general@ {\memgloterm{execpol.general}}{\memglodesc{(\ref {execpol.general})}} {\memgloref{}}|memjustarg}{790} -\glossaryentry{execution.syn@ {\memgloterm{execution.syn}}{\memglodesc{(\ref {execution.syn})}} {\memgloref{}}|memjustarg}{790} -\glossaryentry{execpol.type@ {\memgloterm{execpol.type}}{\memglodesc{(\ref {execpol.type})}} {\memgloref{}}|memjustarg}{791} -\glossaryentry{execpol.seq@ {\memgloterm{execpol.seq}}{\memglodesc{(\ref {execpol.seq})}} {\memgloref{}}|memjustarg}{791} -\glossaryentry{execpol.par@ {\memgloterm{execpol.par}}{\memglodesc{(\ref {execpol.par})}} {\memgloref{}}|memjustarg}{791} -\glossaryentry{execpol.parunseq@ {\memgloterm{execpol.parunseq}}{\memglodesc{(\ref {execpol.parunseq})}} {\memgloref{}}|memjustarg}{791} -\glossaryentry{execpol.unseq@ {\memgloterm{execpol.unseq}}{\memglodesc{(\ref {execpol.unseq})}} {\memgloref{}}|memjustarg}{791} -\glossaryentry{execpol.objects@ {\memgloterm{execpol.objects}}{\memglodesc{(\ref {execpol.objects})}} {\memgloref{}}|memjustarg}{791} -\glossaryentry{charconv@ {\memgloterm{charconv}}{\memglodesc{(\ref {charconv})}} {\memgloref{}}|memjustarg}{792} -\glossaryentry{charconv.syn@ {\memgloterm{charconv.syn}}{\memglodesc{(\ref {charconv.syn})}} {\memgloref{}}|memjustarg}{792} -\glossaryentry{charconv.to.chars@ {\memgloterm{charconv.to.chars}}{\memglodesc{(\ref {charconv.to.chars})}} {\memgloref{}}|memjustarg}{792} -\glossaryentry{charconv.from.chars@ {\memgloterm{charconv.from.chars}}{\memglodesc{(\ref {charconv.from.chars})}} {\memgloref{}}|memjustarg}{793} -\glossaryentry{format@ {\memgloterm{format}}{\memglodesc{(\ref {format})}} {\memgloref{}}|memjustarg}{794} -\glossaryentry{format.syn@ {\memgloterm{format.syn}}{\memglodesc{(\ref {format.syn})}} {\memgloref{}}|memjustarg}{794} -\glossaryentry{format.string@ {\memgloterm{format.string}}{\memglodesc{(\ref {format.string})}} {\memgloref{}}|memjustarg}{796} -\glossaryentry{format.string.general@ {\memgloterm{format.string.general}}{\memglodesc{(\ref {format.string.general})}} {\memgloref{}}|memjustarg}{796} -\glossaryentry{format.string.std@ {\memgloterm{format.string.std}}{\memglodesc{(\ref {format.string.std})}} {\memgloref{}}|memjustarg}{798} -\glossaryentry{format.err.report@ {\memgloterm{format.err.report}}{\memglodesc{(\ref {format.err.report})}} {\memgloref{}}|memjustarg}{802} -\glossaryentry{format.fmt.string@ {\memgloterm{format.fmt.string}}{\memglodesc{(\ref {format.fmt.string})}} {\memgloref{}}|memjustarg}{802} -\glossaryentry{format.functions@ {\memgloterm{format.functions}}{\memglodesc{(\ref {format.functions})}} {\memgloref{}}|memjustarg}{803} -\glossaryentry{format.formatter@ {\memgloterm{format.formatter}}{\memglodesc{(\ref {format.formatter})}} {\memgloref{}}|memjustarg}{805} -\glossaryentry{formatter.requirements@ {\memgloterm{formatter.requirements}}{\memglodesc{(\ref {formatter.requirements})}} {\memgloref{}}|memjustarg}{805} -\glossaryentry{format.formattable@ {\memgloterm{format.formattable}}{\memglodesc{(\ref {format.formattable})}} {\memgloref{}}|memjustarg}{805} -\glossaryentry{format.formatter.spec@ {\memgloterm{format.formatter.spec}}{\memglodesc{(\ref {format.formatter.spec})}} {\memgloref{}}|memjustarg}{806} -\glossaryentry{format.string.escaped@ {\memgloterm{format.string.escaped}}{\memglodesc{(\ref {format.string.escaped})}} {\memgloref{}}|memjustarg}{807} -\glossaryentry{format.parse.ctx@ {\memgloterm{format.parse.ctx}}{\memglodesc{(\ref {format.parse.ctx})}} {\memgloref{}}|memjustarg}{808} -\glossaryentry{format.context@ {\memgloterm{format.context}}{\memglodesc{(\ref {format.context})}} {\memgloref{}}|memjustarg}{810} -\glossaryentry{format.range@ {\memgloterm{format.range}}{\memglodesc{(\ref {format.range})}} {\memgloref{}}|memjustarg}{811} -\glossaryentry{format.range.fmtkind@ {\memgloterm{format.range.fmtkind}}{\memglodesc{(\ref {format.range.fmtkind})}} {\memgloref{}}|memjustarg}{811} -\glossaryentry{format.range.formatter@ {\memgloterm{format.range.formatter}}{\memglodesc{(\ref {format.range.formatter})}} {\memgloref{}}|memjustarg}{811} -\glossaryentry{format.range.fmtdef@ {\memgloterm{format.range.fmtdef}}{\memglodesc{(\ref {format.range.fmtdef})}} {\memgloref{}}|memjustarg}{813} -\glossaryentry{format.range.fmtmap@ {\memgloterm{format.range.fmtmap}}{\memglodesc{(\ref {format.range.fmtmap})}} {\memgloref{}}|memjustarg}{814} -\glossaryentry{format.range.fmtset@ {\memgloterm{format.range.fmtset}}{\memglodesc{(\ref {format.range.fmtset})}} {\memgloref{}}|memjustarg}{815} -\glossaryentry{format.range.fmtstr@ {\memgloterm{format.range.fmtstr}}{\memglodesc{(\ref {format.range.fmtstr})}} {\memgloref{}}|memjustarg}{815} -\glossaryentry{format.arguments@ {\memgloterm{format.arguments}}{\memglodesc{(\ref {format.arguments})}} {\memgloref{}}|memjustarg}{816} -\glossaryentry{format.arg@ {\memgloterm{format.arg}}{\memglodesc{(\ref {format.arg})}} {\memgloref{}}|memjustarg}{816} -\glossaryentry{format.arg.store@ {\memgloterm{format.arg.store}}{\memglodesc{(\ref {format.arg.store})}} {\memgloref{}}|memjustarg}{818} -\glossaryentry{format.args@ {\memgloterm{format.args}}{\memglodesc{(\ref {format.args})}} {\memgloref{}}|memjustarg}{818} -\glossaryentry{format.tuple@ {\memgloterm{format.tuple}}{\memglodesc{(\ref {format.tuple})}} {\memgloref{}}|memjustarg}{819} -\glossaryentry{format.error@ {\memgloterm{format.error}}{\memglodesc{(\ref {format.error})}} {\memgloref{}}|memjustarg}{820} -\glossaryentry{bit@ {\memgloterm{bit}}{\memglodesc{(\ref {bit})}} {\memgloref{}}|memjustarg}{821} -\glossaryentry{bit.general@ {\memgloterm{bit.general}}{\memglodesc{(\ref {bit.general})}} {\memgloref{}}|memjustarg}{821} -\glossaryentry{bit.syn@ {\memgloterm{bit.syn}}{\memglodesc{(\ref {bit.syn})}} {\memgloref{}}|memjustarg}{821} -\glossaryentry{bit.cast@ {\memgloterm{bit.cast}}{\memglodesc{(\ref {bit.cast})}} {\memgloref{}}|memjustarg}{821} -\glossaryentry{bit.byteswap@ {\memgloterm{bit.byteswap}}{\memglodesc{(\ref {bit.byteswap})}} {\memgloref{}}|memjustarg}{822} -\glossaryentry{bit.pow.two@ {\memgloterm{bit.pow.two}}{\memglodesc{(\ref {bit.pow.two})}} {\memgloref{}}|memjustarg}{822} -\glossaryentry{bit.rotate@ {\memgloterm{bit.rotate}}{\memglodesc{(\ref {bit.rotate})}} {\memgloref{}}|memjustarg}{823} -\glossaryentry{bit.count@ {\memgloterm{bit.count}}{\memglodesc{(\ref {bit.count})}} {\memgloref{}}|memjustarg}{823} -\glossaryentry{bit.endian@ {\memgloterm{bit.endian}}{\memglodesc{(\ref {bit.endian})}} {\memgloref{}}|memjustarg}{824} -\glossaryentry{strings@ {\memgloterm{strings}}{\memglodesc{(\ref {strings})}} {\memgloref{}}|memjustarg}{825} -\glossaryentry{strings.general@ {\memgloterm{strings.general}}{\memglodesc{(\ref {strings.general})}} {\memgloref{}}|memjustarg}{825} -\glossaryentry{char.traits@ {\memgloterm{char.traits}}{\memglodesc{(\ref {char.traits})}} {\memgloref{}}|memjustarg}{825} -\glossaryentry{char.traits.general@ {\memgloterm{char.traits.general}}{\memglodesc{(\ref {char.traits.general})}} {\memgloref{}}|memjustarg}{825} -\glossaryentry{char.traits.require@ {\memgloterm{char.traits.require}}{\memglodesc{(\ref {char.traits.require})}} {\memgloref{}}|memjustarg}{825} -\glossaryentry{char.traits.typedefs@ {\memgloterm{char.traits.typedefs}}{\memglodesc{(\ref {char.traits.typedefs})}} {\memgloref{}}|memjustarg}{827} -\glossaryentry{char.traits.specializations@ {\memgloterm{char.traits.specializations}}{\memglodesc{(\ref {char.traits.specializations})}} {\memgloref{}}|memjustarg}{827} -\glossaryentry{char.traits.specializations.general@ {\memgloterm{char.traits.specializations.general}}{\memglodesc{(\ref {char.traits.specializations.general})}} {\memgloref{}}|memjustarg}{827} -\glossaryentry{char.traits.specializations.char@ {\memgloterm{char.traits.specializations.char}}{\memglodesc{(\ref {char.traits.specializations.char})}} {\memgloref{}}|memjustarg}{827} -\glossaryentry{char.traits.specializations.char8.t@ {\memgloterm{char.traits.specializations.char8.t}}{\memglodesc{(\ref {char.traits.specializations.char8.t})}} {\memgloref{}}|memjustarg}{828} -\glossaryentry{char.traits.specializations.char16.t@ {\memgloterm{char.traits.specializations.char16.t}}{\memglodesc{(\ref {char.traits.specializations.char16.t})}} {\memgloref{}}|memjustarg}{828} -\glossaryentry{char.traits.specializations.char32.t@ {\memgloterm{char.traits.specializations.char32.t}}{\memglodesc{(\ref {char.traits.specializations.char32.t})}} {\memgloref{}}|memjustarg}{829} -\glossaryentry{char.traits.specializations.wchar.t@ {\memgloterm{char.traits.specializations.wchar.t}}{\memglodesc{(\ref {char.traits.specializations.wchar.t})}} {\memgloref{}}|memjustarg}{830} -\glossaryentry{string.view@ {\memgloterm{string.view}}{\memglodesc{(\ref {string.view})}} {\memgloref{}}|memjustarg}{830} -\glossaryentry{string.view.general@ {\memgloterm{string.view.general}}{\memglodesc{(\ref {string.view.general})}} {\memgloref{}}|memjustarg}{830} -\glossaryentry{string.view.synop@ {\memgloterm{string.view.synop}}{\memglodesc{(\ref {string.view.synop})}} {\memgloref{}}|memjustarg}{830} -\glossaryentry{string.view.template@ {\memgloterm{string.view.template}}{\memglodesc{(\ref {string.view.template})}} {\memgloref{}}|memjustarg}{831} -\glossaryentry{string.view.template.general@ {\memgloterm{string.view.template.general}}{\memglodesc{(\ref {string.view.template.general})}} {\memgloref{}}|memjustarg}{831} -\glossaryentry{string.view.cons@ {\memgloterm{string.view.cons}}{\memglodesc{(\ref {string.view.cons})}} {\memgloref{}}|memjustarg}{833} -\glossaryentry{string.view.deduct@ {\memgloterm{string.view.deduct}}{\memglodesc{(\ref {string.view.deduct})}} {\memgloref{}}|memjustarg}{834} -\glossaryentry{string.view.iterators@ {\memgloterm{string.view.iterators}}{\memglodesc{(\ref {string.view.iterators})}} {\memgloref{}}|memjustarg}{834} -\glossaryentry{string.view.capacity@ {\memgloterm{string.view.capacity}}{\memglodesc{(\ref {string.view.capacity})}} {\memgloref{}}|memjustarg}{835} -\glossaryentry{string.view.access@ {\memgloterm{string.view.access}}{\memglodesc{(\ref {string.view.access})}} {\memgloref{}}|memjustarg}{835} -\glossaryentry{string.view.modifiers@ {\memgloterm{string.view.modifiers}}{\memglodesc{(\ref {string.view.modifiers})}} {\memgloref{}}|memjustarg}{836} -\glossaryentry{string.view.ops@ {\memgloterm{string.view.ops}}{\memglodesc{(\ref {string.view.ops})}} {\memgloref{}}|memjustarg}{836} -\glossaryentry{string.view.find@ {\memgloterm{string.view.find}}{\memglodesc{(\ref {string.view.find})}} {\memgloref{}}|memjustarg}{837} -\glossaryentry{string.view.comparison@ {\memgloterm{string.view.comparison}}{\memglodesc{(\ref {string.view.comparison})}} {\memgloref{}}|memjustarg}{838} -\glossaryentry{string.view.io@ {\memgloterm{string.view.io}}{\memglodesc{(\ref {string.view.io})}} {\memgloref{}}|memjustarg}{839} -\glossaryentry{string.view.hash@ {\memgloterm{string.view.hash}}{\memglodesc{(\ref {string.view.hash})}} {\memgloref{}}|memjustarg}{840} -\glossaryentry{string.view.literals@ {\memgloterm{string.view.literals}}{\memglodesc{(\ref {string.view.literals})}} {\memgloref{}}|memjustarg}{840} -\glossaryentry{string.classes@ {\memgloterm{string.classes}}{\memglodesc{(\ref {string.classes})}} {\memgloref{}}|memjustarg}{840} -\glossaryentry{string.classes.general@ {\memgloterm{string.classes.general}}{\memglodesc{(\ref {string.classes.general})}} {\memgloref{}}|memjustarg}{840} -\glossaryentry{string.syn@ {\memgloterm{string.syn}}{\memglodesc{(\ref {string.syn})}} {\memgloref{}}|memjustarg}{840} -\glossaryentry{basic.string@ {\memgloterm{basic.string}}{\memglodesc{(\ref {basic.string})}} {\memgloref{}}|memjustarg}{843} -\glossaryentry{basic.string.general@ {\memgloterm{basic.string.general}}{\memglodesc{(\ref {basic.string.general})}} {\memgloref{}}|memjustarg}{843} -\glossaryentry{string.require@ {\memgloterm{string.require}}{\memglodesc{(\ref {string.require})}} {\memgloref{}}|memjustarg}{848} -\glossaryentry{string.cons@ {\memgloterm{string.cons}}{\memglodesc{(\ref {string.cons})}} {\memgloref{}}|memjustarg}{849} -\glossaryentry{string.iterators@ {\memgloterm{string.iterators}}{\memglodesc{(\ref {string.iterators})}} {\memgloref{}}|memjustarg}{851} -\glossaryentry{string.capacity@ {\memgloterm{string.capacity}}{\memglodesc{(\ref {string.capacity})}} {\memgloref{}}|memjustarg}{852} -\glossaryentry{string.access@ {\memgloterm{string.access}}{\memglodesc{(\ref {string.access})}} {\memgloref{}}|memjustarg}{853} -\glossaryentry{string.modifiers@ {\memgloterm{string.modifiers}}{\memglodesc{(\ref {string.modifiers})}} {\memgloref{}}|memjustarg}{853} -\glossaryentry{string.op.append@ {\memgloterm{string.op.append}}{\memglodesc{(\ref {string.op.append})}} {\memgloref{}}|memjustarg}{853} -\glossaryentry{string.append@ {\memgloterm{string.append}}{\memglodesc{(\ref {string.append})}} {\memgloref{}}|memjustarg}{854} -\glossaryentry{string.assign@ {\memgloterm{string.assign}}{\memglodesc{(\ref {string.assign})}} {\memgloref{}}|memjustarg}{855} -\glossaryentry{string.insert@ {\memgloterm{string.insert}}{\memglodesc{(\ref {string.insert})}} {\memgloref{}}|memjustarg}{856} -\glossaryentry{string.erase@ {\memgloterm{string.erase}}{\memglodesc{(\ref {string.erase})}} {\memgloref{}}|memjustarg}{857} -\glossaryentry{string.replace@ {\memgloterm{string.replace}}{\memglodesc{(\ref {string.replace})}} {\memgloref{}}|memjustarg}{858} -\glossaryentry{string.copy@ {\memgloterm{string.copy}}{\memglodesc{(\ref {string.copy})}} {\memgloref{}}|memjustarg}{860} -\glossaryentry{string.swap@ {\memgloterm{string.swap}}{\memglodesc{(\ref {string.swap})}} {\memgloref{}}|memjustarg}{860} -\glossaryentry{string.ops@ {\memgloterm{string.ops}}{\memglodesc{(\ref {string.ops})}} {\memgloref{}}|memjustarg}{860} -\glossaryentry{string.accessors@ {\memgloterm{string.accessors}}{\memglodesc{(\ref {string.accessors})}} {\memgloref{}}|memjustarg}{860} -\glossaryentry{string.find@ {\memgloterm{string.find}}{\memglodesc{(\ref {string.find})}} {\memgloref{}}|memjustarg}{860} -\glossaryentry{string.substr@ {\memgloterm{string.substr}}{\memglodesc{(\ref {string.substr})}} {\memgloref{}}|memjustarg}{861} -\glossaryentry{string.compare@ {\memgloterm{string.compare}}{\memglodesc{(\ref {string.compare})}} {\memgloref{}}|memjustarg}{861} -\glossaryentry{string.starts.with@ {\memgloterm{string.starts.with}}{\memglodesc{(\ref {string.starts.with})}} {\memgloref{}}|memjustarg}{862} -\glossaryentry{string.ends.with@ {\memgloterm{string.ends.with}}{\memglodesc{(\ref {string.ends.with})}} {\memgloref{}}|memjustarg}{862} -\glossaryentry{string.contains@ {\memgloterm{string.contains}}{\memglodesc{(\ref {string.contains})}} {\memgloref{}}|memjustarg}{862} -\glossaryentry{string.nonmembers@ {\memgloterm{string.nonmembers}}{\memglodesc{(\ref {string.nonmembers})}} {\memgloref{}}|memjustarg}{863} -\glossaryentry{string.op.plus@ {\memgloterm{string.op.plus}}{\memglodesc{(\ref {string.op.plus})}} {\memgloref{}}|memjustarg}{863} -\glossaryentry{string.cmp@ {\memgloterm{string.cmp}}{\memglodesc{(\ref {string.cmp})}} {\memgloref{}}|memjustarg}{864} -\glossaryentry{string.special@ {\memgloterm{string.special}}{\memglodesc{(\ref {string.special})}} {\memgloref{}}|memjustarg}{864} -\glossaryentry{string.io@ {\memgloterm{string.io}}{\memglodesc{(\ref {string.io})}} {\memgloref{}}|memjustarg}{865} -\glossaryentry{string.erasure@ {\memgloterm{string.erasure}}{\memglodesc{(\ref {string.erasure})}} {\memgloref{}}|memjustarg}{866} -\glossaryentry{string.conversions@ {\memgloterm{string.conversions}}{\memglodesc{(\ref {string.conversions})}} {\memgloref{}}|memjustarg}{866} -\glossaryentry{basic.string.hash@ {\memgloterm{basic.string.hash}}{\memglodesc{(\ref {basic.string.hash})}} {\memgloref{}}|memjustarg}{867} -\glossaryentry{basic.string.literals@ {\memgloterm{basic.string.literals}}{\memglodesc{(\ref {basic.string.literals})}} {\memgloref{}}|memjustarg}{868} -\glossaryentry{c.strings@ {\memgloterm{c.strings}}{\memglodesc{(\ref {c.strings})}} {\memgloref{}}|memjustarg}{868} -\glossaryentry{cctype.syn@ {\memgloterm{cctype.syn}}{\memglodesc{(\ref {cctype.syn})}} {\memgloref{}}|memjustarg}{868} -\glossaryentry{cwctype.syn@ {\memgloterm{cwctype.syn}}{\memglodesc{(\ref {cwctype.syn})}} {\memgloref{}}|memjustarg}{868} -\glossaryentry{cstring.syn@ {\memgloterm{cstring.syn}}{\memglodesc{(\ref {cstring.syn})}} {\memgloref{}}|memjustarg}{869} -\glossaryentry{cwchar.syn@ {\memgloterm{cwchar.syn}}{\memglodesc{(\ref {cwchar.syn})}} {\memgloref{}}|memjustarg}{870} -\glossaryentry{cuchar.syn@ {\memgloterm{cuchar.syn}}{\memglodesc{(\ref {cuchar.syn})}} {\memgloref{}}|memjustarg}{871} -\glossaryentry{c.mb.wcs@ {\memgloterm{c.mb.wcs}}{\memglodesc{(\ref {c.mb.wcs})}} {\memgloref{}}|memjustarg}{871} -\glossaryentry{containers@ {\memgloterm{containers}}{\memglodesc{(\ref {containers})}} {\memgloref{}}|memjustarg}{873} -\glossaryentry{containers.general@ {\memgloterm{containers.general}}{\memglodesc{(\ref {containers.general})}} {\memgloref{}}|memjustarg}{873} -\glossaryentry{container.requirements@ {\memgloterm{container.requirements}}{\memglodesc{(\ref {container.requirements})}} {\memgloref{}}|memjustarg}{873} -\glossaryentry{container.requirements.pre@ {\memgloterm{container.requirements.pre}}{\memglodesc{(\ref {container.requirements.pre})}} {\memgloref{}}|memjustarg}{873} -\glossaryentry{container.gen.reqmts@ {\memgloterm{container.gen.reqmts}}{\memglodesc{(\ref {container.gen.reqmts})}} {\memgloref{}}|memjustarg}{873} -\glossaryentry{container.requirements.general@ {\memgloterm{container.requirements.general}}{\memglodesc{(\ref {container.requirements.general})}} {\memgloref{}}|memjustarg}{873} -\glossaryentry{container.reqmts@ {\memgloterm{container.reqmts}}{\memglodesc{(\ref {container.reqmts})}} {\memgloref{}}|memjustarg}{874} -\glossaryentry{container.rev.reqmts@ {\memgloterm{container.rev.reqmts}}{\memglodesc{(\ref {container.rev.reqmts})}} {\memgloref{}}|memjustarg}{877} -\glossaryentry{container.opt.reqmts@ {\memgloterm{container.opt.reqmts}}{\memglodesc{(\ref {container.opt.reqmts})}} {\memgloref{}}|memjustarg}{878} -\glossaryentry{container.alloc.reqmts@ {\memgloterm{container.alloc.reqmts}}{\memglodesc{(\ref {container.alloc.reqmts})}} {\memgloref{}}|memjustarg}{878} -\glossaryentry{container.requirements.dataraces@ {\memgloterm{container.requirements.dataraces}}{\memglodesc{(\ref {container.requirements.dataraces})}} {\memgloref{}}|memjustarg}{880} -\glossaryentry{sequence.reqmts@ {\memgloterm{sequence.reqmts}}{\memglodesc{(\ref {sequence.reqmts})}} {\memgloref{}}|memjustarg}{880} -\glossaryentry{container.node@ {\memgloterm{container.node}}{\memglodesc{(\ref {container.node})}} {\memgloref{}}|memjustarg}{886} -\glossaryentry{container.node.overview@ {\memgloterm{container.node.overview}}{\memglodesc{(\ref {container.node.overview})}} {\memgloref{}}|memjustarg}{886} -\glossaryentry{container.node.cons@ {\memgloterm{container.node.cons}}{\memglodesc{(\ref {container.node.cons})}} {\memgloref{}}|memjustarg}{887} -\glossaryentry{container.node.dtor@ {\memgloterm{container.node.dtor}}{\memglodesc{(\ref {container.node.dtor})}} {\memgloref{}}|memjustarg}{887} -\glossaryentry{container.node.observers@ {\memgloterm{container.node.observers}}{\memglodesc{(\ref {container.node.observers})}} {\memgloref{}}|memjustarg}{887} -\glossaryentry{container.node.modifiers@ {\memgloterm{container.node.modifiers}}{\memglodesc{(\ref {container.node.modifiers})}} {\memgloref{}}|memjustarg}{888} -\glossaryentry{container.insert.return@ {\memgloterm{container.insert.return}}{\memglodesc{(\ref {container.insert.return})}} {\memgloref{}}|memjustarg}{888} -\glossaryentry{associative.reqmts@ {\memgloterm{associative.reqmts}}{\memglodesc{(\ref {associative.reqmts})}} {\memgloref{}}|memjustarg}{888} -\glossaryentry{associative.reqmts.general@ {\memgloterm{associative.reqmts.general}}{\memglodesc{(\ref {associative.reqmts.general})}} {\memgloref{}}|memjustarg}{888} -\glossaryentry{associative.reqmts.except@ {\memgloterm{associative.reqmts.except}}{\memglodesc{(\ref {associative.reqmts.except})}} {\memgloref{}}|memjustarg}{897} -\glossaryentry{unord.req@ {\memgloterm{unord.req}}{\memglodesc{(\ref {unord.req})}} {\memgloref{}}|memjustarg}{897} -\glossaryentry{unord.req.general@ {\memgloterm{unord.req.general}}{\memglodesc{(\ref {unord.req.general})}} {\memgloref{}}|memjustarg}{897} -\glossaryentry{unord.req.except@ {\memgloterm{unord.req.except}}{\memglodesc{(\ref {unord.req.except})}} {\memgloref{}}|memjustarg}{908} -\glossaryentry{sequences@ {\memgloterm{sequences}}{\memglodesc{(\ref {sequences})}} {\memgloref{}}|memjustarg}{908} -\glossaryentry{sequences.general@ {\memgloterm{sequences.general}}{\memglodesc{(\ref {sequences.general})}} {\memgloref{}}|memjustarg}{908} -\glossaryentry{array.syn@ {\memgloterm{array.syn}}{\memglodesc{(\ref {array.syn})}} {\memgloref{}}|memjustarg}{908} -\glossaryentry{deque.syn@ {\memgloterm{deque.syn}}{\memglodesc{(\ref {deque.syn})}} {\memgloref{}}|memjustarg}{909} -\glossaryentry{forward.list.syn@ {\memgloterm{forward.list.syn}}{\memglodesc{(\ref {forward.list.syn})}} {\memgloref{}}|memjustarg}{909} -\glossaryentry{list.syn@ {\memgloterm{list.syn}}{\memglodesc{(\ref {list.syn})}} {\memgloref{}}|memjustarg}{910} -\glossaryentry{vector.syn@ {\memgloterm{vector.syn}}{\memglodesc{(\ref {vector.syn})}} {\memgloref{}}|memjustarg}{910} -\glossaryentry{array@ {\memgloterm{array}}{\memglodesc{(\ref {array})}} {\memgloref{}}|memjustarg}{911} -\glossaryentry{array.overview@ {\memgloterm{array.overview}}{\memglodesc{(\ref {array.overview})}} {\memgloref{}}|memjustarg}{911} -\glossaryentry{array.cons@ {\memgloterm{array.cons}}{\memglodesc{(\ref {array.cons})}} {\memgloref{}}|memjustarg}{912} -\glossaryentry{array.members@ {\memgloterm{array.members}}{\memglodesc{(\ref {array.members})}} {\memgloref{}}|memjustarg}{913} -\glossaryentry{array.special@ {\memgloterm{array.special}}{\memglodesc{(\ref {array.special})}} {\memgloref{}}|memjustarg}{913} -\glossaryentry{array.zero@ {\memgloterm{array.zero}}{\memglodesc{(\ref {array.zero})}} {\memgloref{}}|memjustarg}{913} -\glossaryentry{array.creation@ {\memgloterm{array.creation}}{\memglodesc{(\ref {array.creation})}} {\memgloref{}}|memjustarg}{913} -\glossaryentry{array.tuple@ {\memgloterm{array.tuple}}{\memglodesc{(\ref {array.tuple})}} {\memgloref{}}|memjustarg}{913} -\glossaryentry{deque@ {\memgloterm{deque}}{\memglodesc{(\ref {deque})}} {\memgloref{}}|memjustarg}{914} -\glossaryentry{deque.overview@ {\memgloterm{deque.overview}}{\memglodesc{(\ref {deque.overview})}} {\memgloref{}}|memjustarg}{914} -\glossaryentry{deque.cons@ {\memgloterm{deque.cons}}{\memglodesc{(\ref {deque.cons})}} {\memgloref{}}|memjustarg}{916} -\glossaryentry{deque.capacity@ {\memgloterm{deque.capacity}}{\memglodesc{(\ref {deque.capacity})}} {\memgloref{}}|memjustarg}{916} -\glossaryentry{deque.modifiers@ {\memgloterm{deque.modifiers}}{\memglodesc{(\ref {deque.modifiers})}} {\memgloref{}}|memjustarg}{917} -\glossaryentry{deque.erasure@ {\memgloterm{deque.erasure}}{\memglodesc{(\ref {deque.erasure})}} {\memgloref{}}|memjustarg}{918} -\glossaryentry{forward.list@ {\memgloterm{forward.list}}{\memglodesc{(\ref {forward.list})}} {\memgloref{}}|memjustarg}{918} -\glossaryentry{forward.list.overview@ {\memgloterm{forward.list.overview}}{\memglodesc{(\ref {forward.list.overview})}} {\memgloref{}}|memjustarg}{918} -\glossaryentry{forward.list.cons@ {\memgloterm{forward.list.cons}}{\memglodesc{(\ref {forward.list.cons})}} {\memgloref{}}|memjustarg}{920} -\glossaryentry{forward.list.iter@ {\memgloterm{forward.list.iter}}{\memglodesc{(\ref {forward.list.iter})}} {\memgloref{}}|memjustarg}{921} -\glossaryentry{forward.list.access@ {\memgloterm{forward.list.access}}{\memglodesc{(\ref {forward.list.access})}} {\memgloref{}}|memjustarg}{921} -\glossaryentry{forward.list.modifiers@ {\memgloterm{forward.list.modifiers}}{\memglodesc{(\ref {forward.list.modifiers})}} {\memgloref{}}|memjustarg}{921} -\glossaryentry{forward.list.ops@ {\memgloterm{forward.list.ops}}{\memglodesc{(\ref {forward.list.ops})}} {\memgloref{}}|memjustarg}{923} -\glossaryentry{forward.list.erasure@ {\memgloterm{forward.list.erasure}}{\memglodesc{(\ref {forward.list.erasure})}} {\memgloref{}}|memjustarg}{925} -\glossaryentry{list@ {\memgloterm{list}}{\memglodesc{(\ref {list})}} {\memgloref{}}|memjustarg}{925} -\glossaryentry{list.overview@ {\memgloterm{list.overview}}{\memglodesc{(\ref {list.overview})}} {\memgloref{}}|memjustarg}{925} -\glossaryentry{list.cons@ {\memgloterm{list.cons}}{\memglodesc{(\ref {list.cons})}} {\memgloref{}}|memjustarg}{927} -\glossaryentry{list.capacity@ {\memgloterm{list.capacity}}{\memglodesc{(\ref {list.capacity})}} {\memgloref{}}|memjustarg}{928} -\glossaryentry{list.modifiers@ {\memgloterm{list.modifiers}}{\memglodesc{(\ref {list.modifiers})}} {\memgloref{}}|memjustarg}{928} -\glossaryentry{list.ops@ {\memgloterm{list.ops}}{\memglodesc{(\ref {list.ops})}} {\memgloref{}}|memjustarg}{929} -\glossaryentry{list.erasure@ {\memgloterm{list.erasure}}{\memglodesc{(\ref {list.erasure})}} {\memgloref{}}|memjustarg}{931} -\glossaryentry{vector@ {\memgloterm{vector}}{\memglodesc{(\ref {vector})}} {\memgloref{}}|memjustarg}{931} -\glossaryentry{vector.overview@ {\memgloterm{vector.overview}}{\memglodesc{(\ref {vector.overview})}} {\memgloref{}}|memjustarg}{931} -\glossaryentry{vector.cons@ {\memgloterm{vector.cons}}{\memglodesc{(\ref {vector.cons})}} {\memgloref{}}|memjustarg}{933} -\glossaryentry{vector.capacity@ {\memgloterm{vector.capacity}}{\memglodesc{(\ref {vector.capacity})}} {\memgloref{}}|memjustarg}{934} -\glossaryentry{vector.data@ {\memgloterm{vector.data}}{\memglodesc{(\ref {vector.data})}} {\memgloref{}}|memjustarg}{935} -\glossaryentry{vector.modifiers@ {\memgloterm{vector.modifiers}}{\memglodesc{(\ref {vector.modifiers})}} {\memgloref{}}|memjustarg}{935} -\glossaryentry{vector.erasure@ {\memgloterm{vector.erasure}}{\memglodesc{(\ref {vector.erasure})}} {\memgloref{}}|memjustarg}{935} -\glossaryentry{vector.bool@ {\memgloterm{vector.bool}}{\memglodesc{(\ref {vector.bool})}} {\memgloref{}}|memjustarg}{936} -\glossaryentry{vector.bool.pspc@ {\memgloterm{vector.bool.pspc}}{\memglodesc{(\ref {vector.bool.pspc})}} {\memgloref{}}|memjustarg}{936} -\glossaryentry{vector.bool.fmt@ {\memgloterm{vector.bool.fmt}}{\memglodesc{(\ref {vector.bool.fmt})}} {\memgloref{}}|memjustarg}{938} -\glossaryentry{associative@ {\memgloterm{associative}}{\memglodesc{(\ref {associative})}} {\memgloref{}}|memjustarg}{939} -\glossaryentry{associative.general@ {\memgloterm{associative.general}}{\memglodesc{(\ref {associative.general})}} {\memgloref{}}|memjustarg}{939} -\glossaryentry{associative.map.syn@ {\memgloterm{associative.map.syn}}{\memglodesc{(\ref {associative.map.syn})}} {\memgloref{}}|memjustarg}{939} -\glossaryentry{associative.set.syn@ {\memgloterm{associative.set.syn}}{\memglodesc{(\ref {associative.set.syn})}} {\memgloref{}}|memjustarg}{940} -\glossaryentry{map@ {\memgloterm{map}}{\memglodesc{(\ref {map})}} {\memgloref{}}|memjustarg}{941} -\glossaryentry{map.overview@ {\memgloterm{map.overview}}{\memglodesc{(\ref {map.overview})}} {\memgloref{}}|memjustarg}{941} -\glossaryentry{map.cons@ {\memgloterm{map.cons}}{\memglodesc{(\ref {map.cons})}} {\memgloref{}}|memjustarg}{945} -\glossaryentry{map.access@ {\memgloterm{map.access}}{\memglodesc{(\ref {map.access})}} {\memgloref{}}|memjustarg}{945} -\glossaryentry{map.modifiers@ {\memgloterm{map.modifiers}}{\memglodesc{(\ref {map.modifiers})}} {\memgloref{}}|memjustarg}{945} -\glossaryentry{map.erasure@ {\memgloterm{map.erasure}}{\memglodesc{(\ref {map.erasure})}} {\memgloref{}}|memjustarg}{946} -\glossaryentry{multimap@ {\memgloterm{multimap}}{\memglodesc{(\ref {multimap})}} {\memgloref{}}|memjustarg}{947} -\glossaryentry{multimap.overview@ {\memgloterm{multimap.overview}}{\memglodesc{(\ref {multimap.overview})}} {\memgloref{}}|memjustarg}{947} -\glossaryentry{multimap.cons@ {\memgloterm{multimap.cons}}{\memglodesc{(\ref {multimap.cons})}} {\memgloref{}}|memjustarg}{950} -\glossaryentry{multimap.modifiers@ {\memgloterm{multimap.modifiers}}{\memglodesc{(\ref {multimap.modifiers})}} {\memgloref{}}|memjustarg}{950} -\glossaryentry{multimap.erasure@ {\memgloterm{multimap.erasure}}{\memglodesc{(\ref {multimap.erasure})}} {\memgloref{}}|memjustarg}{950} -\glossaryentry{set@ {\memgloterm{set}}{\memglodesc{(\ref {set})}} {\memgloref{}}|memjustarg}{951} -\glossaryentry{set.overview@ {\memgloterm{set.overview}}{\memglodesc{(\ref {set.overview})}} {\memgloref{}}|memjustarg}{951} -\glossaryentry{set.cons@ {\memgloterm{set.cons}}{\memglodesc{(\ref {set.cons})}} {\memgloref{}}|memjustarg}{954} -\glossaryentry{set.erasure@ {\memgloterm{set.erasure}}{\memglodesc{(\ref {set.erasure})}} {\memgloref{}}|memjustarg}{954} -\glossaryentry{multiset@ {\memgloterm{multiset}}{\memglodesc{(\ref {multiset})}} {\memgloref{}}|memjustarg}{954} -\glossaryentry{multiset.overview@ {\memgloterm{multiset.overview}}{\memglodesc{(\ref {multiset.overview})}} {\memgloref{}}|memjustarg}{954} -\glossaryentry{multiset.cons@ {\memgloterm{multiset.cons}}{\memglodesc{(\ref {multiset.cons})}} {\memgloref{}}|memjustarg}{957} -\glossaryentry{multiset.erasure@ {\memgloterm{multiset.erasure}}{\memglodesc{(\ref {multiset.erasure})}} {\memgloref{}}|memjustarg}{958} -\glossaryentry{unord@ {\memgloterm{unord}}{\memglodesc{(\ref {unord})}} {\memgloref{}}|memjustarg}{958} -\glossaryentry{unord.general@ {\memgloterm{unord.general}}{\memglodesc{(\ref {unord.general})}} {\memgloref{}}|memjustarg}{958} -\glossaryentry{unord.map.syn@ {\memgloterm{unord.map.syn}}{\memglodesc{(\ref {unord.map.syn})}} {\memgloref{}}|memjustarg}{958} -\glossaryentry{unord.set.syn@ {\memgloterm{unord.set.syn}}{\memglodesc{(\ref {unord.set.syn})}} {\memgloref{}}|memjustarg}{959} -\glossaryentry{unord.map@ {\memgloterm{unord.map}}{\memglodesc{(\ref {unord.map})}} {\memgloref{}}|memjustarg}{960} -\glossaryentry{unord.map.overview@ {\memgloterm{unord.map.overview}}{\memglodesc{(\ref {unord.map.overview})}} {\memgloref{}}|memjustarg}{960} -\glossaryentry{unord.map.cnstr@ {\memgloterm{unord.map.cnstr}}{\memglodesc{(\ref {unord.map.cnstr})}} {\memgloref{}}|memjustarg}{965} -\glossaryentry{unord.map.elem@ {\memgloterm{unord.map.elem}}{\memglodesc{(\ref {unord.map.elem})}} {\memgloref{}}|memjustarg}{965} -\glossaryentry{unord.map.modifiers@ {\memgloterm{unord.map.modifiers}}{\memglodesc{(\ref {unord.map.modifiers})}} {\memgloref{}}|memjustarg}{965} -\glossaryentry{unord.map.erasure@ {\memgloterm{unord.map.erasure}}{\memglodesc{(\ref {unord.map.erasure})}} {\memgloref{}}|memjustarg}{967} -\glossaryentry{unord.multimap@ {\memgloterm{unord.multimap}}{\memglodesc{(\ref {unord.multimap})}} {\memgloref{}}|memjustarg}{967} -\glossaryentry{unord.multimap.overview@ {\memgloterm{unord.multimap.overview}}{\memglodesc{(\ref {unord.multimap.overview})}} {\memgloref{}}|memjustarg}{967} -\glossaryentry{unord.multimap.cnstr@ {\memgloterm{unord.multimap.cnstr}}{\memglodesc{(\ref {unord.multimap.cnstr})}} {\memgloref{}}|memjustarg}{971} -\glossaryentry{unord.multimap.modifiers@ {\memgloterm{unord.multimap.modifiers}}{\memglodesc{(\ref {unord.multimap.modifiers})}} {\memgloref{}}|memjustarg}{972} -\glossaryentry{unord.multimap.erasure@ {\memgloterm{unord.multimap.erasure}}{\memglodesc{(\ref {unord.multimap.erasure})}} {\memgloref{}}|memjustarg}{972} -\glossaryentry{unord.set@ {\memgloterm{unord.set}}{\memglodesc{(\ref {unord.set})}} {\memgloref{}}|memjustarg}{972} -\glossaryentry{unord.set.overview@ {\memgloterm{unord.set.overview}}{\memglodesc{(\ref {unord.set.overview})}} {\memgloref{}}|memjustarg}{972} -\glossaryentry{unord.set.cnstr@ {\memgloterm{unord.set.cnstr}}{\memglodesc{(\ref {unord.set.cnstr})}} {\memgloref{}}|memjustarg}{976} -\glossaryentry{unord.set.erasure@ {\memgloterm{unord.set.erasure}}{\memglodesc{(\ref {unord.set.erasure})}} {\memgloref{}}|memjustarg}{977} -\glossaryentry{unord.multiset@ {\memgloterm{unord.multiset}}{\memglodesc{(\ref {unord.multiset})}} {\memgloref{}}|memjustarg}{977} -\glossaryentry{unord.multiset.overview@ {\memgloterm{unord.multiset.overview}}{\memglodesc{(\ref {unord.multiset.overview})}} {\memgloref{}}|memjustarg}{977} -\glossaryentry{unord.multiset.cnstr@ {\memgloterm{unord.multiset.cnstr}}{\memglodesc{(\ref {unord.multiset.cnstr})}} {\memgloref{}}|memjustarg}{981} -\glossaryentry{unord.multiset.erasure@ {\memgloterm{unord.multiset.erasure}}{\memglodesc{(\ref {unord.multiset.erasure})}} {\memgloref{}}|memjustarg}{982} -\glossaryentry{container.adaptors@ {\memgloterm{container.adaptors}}{\memglodesc{(\ref {container.adaptors})}} {\memgloref{}}|memjustarg}{982} -\glossaryentry{container.adaptors.general@ {\memgloterm{container.adaptors.general}}{\memglodesc{(\ref {container.adaptors.general})}} {\memgloref{}}|memjustarg}{982} -\glossaryentry{queue.syn@ {\memgloterm{queue.syn}}{\memglodesc{(\ref {queue.syn})}} {\memgloref{}}|memjustarg}{983} -\glossaryentry{stack.syn@ {\memgloterm{stack.syn}}{\memglodesc{(\ref {stack.syn})}} {\memgloref{}}|memjustarg}{984} -\glossaryentry{flat.map.syn@ {\memgloterm{flat.map.syn}}{\memglodesc{(\ref {flat.map.syn})}} {\memgloref{}}|memjustarg}{984} -\glossaryentry{flat.set.syn@ {\memgloterm{flat.set.syn}}{\memglodesc{(\ref {flat.set.syn})}} {\memgloref{}}|memjustarg}{985} -\glossaryentry{queue@ {\memgloterm{queue}}{\memglodesc{(\ref {queue})}} {\memgloref{}}|memjustarg}{986} -\glossaryentry{queue.defn@ {\memgloterm{queue.defn}}{\memglodesc{(\ref {queue.defn})}} {\memgloref{}}|memjustarg}{986} -\glossaryentry{queue.cons@ {\memgloterm{queue.cons}}{\memglodesc{(\ref {queue.cons})}} {\memgloref{}}|memjustarg}{987} -\glossaryentry{queue.cons.alloc@ {\memgloterm{queue.cons.alloc}}{\memglodesc{(\ref {queue.cons.alloc})}} {\memgloref{}}|memjustarg}{987} -\glossaryentry{queue.mod@ {\memgloterm{queue.mod}}{\memglodesc{(\ref {queue.mod})}} {\memgloref{}}|memjustarg}{988} -\glossaryentry{queue.ops@ {\memgloterm{queue.ops}}{\memglodesc{(\ref {queue.ops})}} {\memgloref{}}|memjustarg}{988} -\glossaryentry{queue.special@ {\memgloterm{queue.special}}{\memglodesc{(\ref {queue.special})}} {\memgloref{}}|memjustarg}{988} -\glossaryentry{priority.queue@ {\memgloterm{priority.queue}}{\memglodesc{(\ref {priority.queue})}} {\memgloref{}}|memjustarg}{988} -\glossaryentry{priqueue.overview@ {\memgloterm{priqueue.overview}}{\memglodesc{(\ref {priqueue.overview})}} {\memgloref{}}|memjustarg}{988} -\glossaryentry{priqueue.cons@ {\memgloterm{priqueue.cons}}{\memglodesc{(\ref {priqueue.cons})}} {\memgloref{}}|memjustarg}{990} -\glossaryentry{priqueue.cons.alloc@ {\memgloterm{priqueue.cons.alloc}}{\memglodesc{(\ref {priqueue.cons.alloc})}} {\memgloref{}}|memjustarg}{991} -\glossaryentry{priqueue.members@ {\memgloterm{priqueue.members}}{\memglodesc{(\ref {priqueue.members})}} {\memgloref{}}|memjustarg}{992} -\glossaryentry{priqueue.special@ {\memgloterm{priqueue.special}}{\memglodesc{(\ref {priqueue.special})}} {\memgloref{}}|memjustarg}{992} -\glossaryentry{stack@ {\memgloterm{stack}}{\memglodesc{(\ref {stack})}} {\memgloref{}}|memjustarg}{992} -\glossaryentry{stack.general@ {\memgloterm{stack.general}}{\memglodesc{(\ref {stack.general})}} {\memgloref{}}|memjustarg}{992} -\glossaryentry{stack.defn@ {\memgloterm{stack.defn}}{\memglodesc{(\ref {stack.defn})}} {\memgloref{}}|memjustarg}{993} -\glossaryentry{stack.cons@ {\memgloterm{stack.cons}}{\memglodesc{(\ref {stack.cons})}} {\memgloref{}}|memjustarg}{994} -\glossaryentry{stack.cons.alloc@ {\memgloterm{stack.cons.alloc}}{\memglodesc{(\ref {stack.cons.alloc})}} {\memgloref{}}|memjustarg}{994} -\glossaryentry{stack.mod@ {\memgloterm{stack.mod}}{\memglodesc{(\ref {stack.mod})}} {\memgloref{}}|memjustarg}{994} -\glossaryentry{stack.ops@ {\memgloterm{stack.ops}}{\memglodesc{(\ref {stack.ops})}} {\memgloref{}}|memjustarg}{995} -\glossaryentry{stack.special@ {\memgloterm{stack.special}}{\memglodesc{(\ref {stack.special})}} {\memgloref{}}|memjustarg}{995} -\glossaryentry{flat.map@ {\memgloterm{flat.map}}{\memglodesc{(\ref {flat.map})}} {\memgloref{}}|memjustarg}{995} -\glossaryentry{flat.map.overview@ {\memgloterm{flat.map.overview}}{\memglodesc{(\ref {flat.map.overview})}} {\memgloref{}}|memjustarg}{995} -\glossaryentry{flat.map.defn@ {\memgloterm{flat.map.defn}}{\memglodesc{(\ref {flat.map.defn})}} {\memgloref{}}|memjustarg}{996} -\glossaryentry{flat.map.cons@ {\memgloterm{flat.map.cons}}{\memglodesc{(\ref {flat.map.cons})}} {\memgloref{}}|memjustarg}{1001} -\glossaryentry{flat.map.capacity@ {\memgloterm{flat.map.capacity}}{\memglodesc{(\ref {flat.map.capacity})}} {\memgloref{}}|memjustarg}{1003} -\glossaryentry{flat.map.access@ {\memgloterm{flat.map.access}}{\memglodesc{(\ref {flat.map.access})}} {\memgloref{}}|memjustarg}{1003} -\glossaryentry{flat.map.modifiers@ {\memgloterm{flat.map.modifiers}}{\memglodesc{(\ref {flat.map.modifiers})}} {\memgloref{}}|memjustarg}{1003} -\glossaryentry{flat.map.erasure@ {\memgloterm{flat.map.erasure}}{\memglodesc{(\ref {flat.map.erasure})}} {\memgloref{}}|memjustarg}{1006} -\glossaryentry{flat.multimap@ {\memgloterm{flat.multimap}}{\memglodesc{(\ref {flat.multimap})}} {\memgloref{}}|memjustarg}{1007} -\glossaryentry{flat.multimap.overview@ {\memgloterm{flat.multimap.overview}}{\memglodesc{(\ref {flat.multimap.overview})}} {\memgloref{}}|memjustarg}{1007} -\glossaryentry{flat.multimap.defn@ {\memgloterm{flat.multimap.defn}}{\memglodesc{(\ref {flat.multimap.defn})}} {\memgloref{}}|memjustarg}{1008} -\glossaryentry{flat.multimap.cons@ {\memgloterm{flat.multimap.cons}}{\memglodesc{(\ref {flat.multimap.cons})}} {\memgloref{}}|memjustarg}{1012} -\glossaryentry{flat.multimap.erasure@ {\memgloterm{flat.multimap.erasure}}{\memglodesc{(\ref {flat.multimap.erasure})}} {\memgloref{}}|memjustarg}{1014} -\glossaryentry{flat.set@ {\memgloterm{flat.set}}{\memglodesc{(\ref {flat.set})}} {\memgloref{}}|memjustarg}{1014} -\glossaryentry{flat.set.overview@ {\memgloterm{flat.set.overview}}{\memglodesc{(\ref {flat.set.overview})}} {\memgloref{}}|memjustarg}{1014} -\glossaryentry{flat.set.defn@ {\memgloterm{flat.set.defn}}{\memglodesc{(\ref {flat.set.defn})}} {\memgloref{}}|memjustarg}{1015} -\glossaryentry{flat.set.cons@ {\memgloterm{flat.set.cons}}{\memglodesc{(\ref {flat.set.cons})}} {\memgloref{}}|memjustarg}{1019} -\glossaryentry{flat.set.modifiers@ {\memgloterm{flat.set.modifiers}}{\memglodesc{(\ref {flat.set.modifiers})}} {\memgloref{}}|memjustarg}{1020} -\glossaryentry{flat.set.erasure@ {\memgloterm{flat.set.erasure}}{\memglodesc{(\ref {flat.set.erasure})}} {\memgloref{}}|memjustarg}{1021} -\glossaryentry{flat.multiset@ {\memgloterm{flat.multiset}}{\memglodesc{(\ref {flat.multiset})}} {\memgloref{}}|memjustarg}{1021} -\glossaryentry{flat.multiset.overview@ {\memgloterm{flat.multiset.overview}}{\memglodesc{(\ref {flat.multiset.overview})}} {\memgloref{}}|memjustarg}{1021} -\glossaryentry{flat.multiset.defn@ {\memgloterm{flat.multiset.defn}}{\memglodesc{(\ref {flat.multiset.defn})}} {\memgloref{}}|memjustarg}{1021} -\glossaryentry{flat.multiset.cons@ {\memgloterm{flat.multiset.cons}}{\memglodesc{(\ref {flat.multiset.cons})}} {\memgloref{}}|memjustarg}{1026} -\glossaryentry{flat.multiset.modifiers@ {\memgloterm{flat.multiset.modifiers}}{\memglodesc{(\ref {flat.multiset.modifiers})}} {\memgloref{}}|memjustarg}{1027} -\glossaryentry{flat.multiset.erasure@ {\memgloterm{flat.multiset.erasure}}{\memglodesc{(\ref {flat.multiset.erasure})}} {\memgloref{}}|memjustarg}{1027} -\glossaryentry{container.adaptors.format@ {\memgloterm{container.adaptors.format}}{\memglodesc{(\ref {container.adaptors.format})}} {\memgloref{}}|memjustarg}{1027} -\glossaryentry{views@ {\memgloterm{views}}{\memglodesc{(\ref {views})}} {\memgloref{}}|memjustarg}{1028} -\glossaryentry{views.general@ {\memgloterm{views.general}}{\memglodesc{(\ref {views.general})}} {\memgloref{}}|memjustarg}{1028} -\glossaryentry{views.contiguous@ {\memgloterm{views.contiguous}}{\memglodesc{(\ref {views.contiguous})}} {\memgloref{}}|memjustarg}{1028} -\glossaryentry{span.syn@ {\memgloterm{span.syn}}{\memglodesc{(\ref {span.syn})}} {\memgloref{}}|memjustarg}{1028} -\glossaryentry{views.span@ {\memgloterm{views.span}}{\memglodesc{(\ref {views.span})}} {\memgloref{}}|memjustarg}{1029} -\glossaryentry{span.overview@ {\memgloterm{span.overview}}{\memglodesc{(\ref {span.overview})}} {\memgloref{}}|memjustarg}{1029} -\glossaryentry{span.cons@ {\memgloterm{span.cons}}{\memglodesc{(\ref {span.cons})}} {\memgloref{}}|memjustarg}{1030} -\glossaryentry{span.deduct@ {\memgloterm{span.deduct}}{\memglodesc{(\ref {span.deduct})}} {\memgloref{}}|memjustarg}{1032} -\glossaryentry{span.sub@ {\memgloterm{span.sub}}{\memglodesc{(\ref {span.sub})}} {\memgloref{}}|memjustarg}{1032} -\glossaryentry{span.obs@ {\memgloterm{span.obs}}{\memglodesc{(\ref {span.obs})}} {\memgloref{}}|memjustarg}{1033} -\glossaryentry{span.elem@ {\memgloterm{span.elem}}{\memglodesc{(\ref {span.elem})}} {\memgloref{}}|memjustarg}{1033} -\glossaryentry{span.iterators@ {\memgloterm{span.iterators}}{\memglodesc{(\ref {span.iterators})}} {\memgloref{}}|memjustarg}{1033} -\glossaryentry{span.objectrep@ {\memgloterm{span.objectrep}}{\memglodesc{(\ref {span.objectrep})}} {\memgloref{}}|memjustarg}{1034} -\glossaryentry{views.multidim@ {\memgloterm{views.multidim}}{\memglodesc{(\ref {views.multidim})}} {\memgloref{}}|memjustarg}{1034} -\glossaryentry{mdspan.overview@ {\memgloterm{mdspan.overview}}{\memglodesc{(\ref {mdspan.overview})}} {\memgloref{}}|memjustarg}{1034} -\glossaryentry{mdspan.syn@ {\memgloterm{mdspan.syn}}{\memglodesc{(\ref {mdspan.syn})}} {\memgloref{}}|memjustarg}{1034} -\glossaryentry{mdspan.extents@ {\memgloterm{mdspan.extents}}{\memglodesc{(\ref {mdspan.extents})}} {\memgloref{}}|memjustarg}{1035} -\glossaryentry{mdspan.extents.overview@ {\memgloterm{mdspan.extents.overview}}{\memglodesc{(\ref {mdspan.extents.overview})}} {\memgloref{}}|memjustarg}{1035} -\glossaryentry{mdspan.extents.expo@ {\memgloterm{mdspan.extents.expo}}{\memglodesc{(\ref {mdspan.extents.expo})}} {\memgloref{}}|memjustarg}{1036} -\glossaryentry{mdspan.extents.cons@ {\memgloterm{mdspan.extents.cons}}{\memglodesc{(\ref {mdspan.extents.cons})}} {\memgloref{}}|memjustarg}{1036} -\glossaryentry{mdspan.extents.obs@ {\memgloterm{mdspan.extents.obs}}{\memglodesc{(\ref {mdspan.extents.obs})}} {\memgloref{}}|memjustarg}{1038} -\glossaryentry{mdspan.extents.cmp@ {\memgloterm{mdspan.extents.cmp}}{\memglodesc{(\ref {mdspan.extents.cmp})}} {\memgloref{}}|memjustarg}{1038} -\glossaryentry{mdspan.extents.dextents@ {\memgloterm{mdspan.extents.dextents}}{\memglodesc{(\ref {mdspan.extents.dextents})}} {\memgloref{}}|memjustarg}{1038} -\glossaryentry{mdspan.layout@ {\memgloterm{mdspan.layout}}{\memglodesc{(\ref {mdspan.layout})}} {\memgloref{}}|memjustarg}{1038} -\glossaryentry{mdspan.layout.general@ {\memgloterm{mdspan.layout.general}}{\memglodesc{(\ref {mdspan.layout.general})}} {\memgloref{}}|memjustarg}{1038} -\glossaryentry{mdspan.layout.reqmts@ {\memgloterm{mdspan.layout.reqmts}}{\memglodesc{(\ref {mdspan.layout.reqmts})}} {\memgloref{}}|memjustarg}{1038} -\glossaryentry{mdspan.layout.policy.reqmts@ {\memgloterm{mdspan.layout.policy.reqmts}}{\memglodesc{(\ref {mdspan.layout.policy.reqmts})}} {\memgloref{}}|memjustarg}{1040} -\glossaryentry{mdspan.layout.policy.overview@ {\memgloterm{mdspan.layout.policy.overview}}{\memglodesc{(\ref {mdspan.layout.policy.overview})}} {\memgloref{}}|memjustarg}{1040} -\glossaryentry{mdspan.layout.left@ {\memgloterm{mdspan.layout.left}}{\memglodesc{(\ref {mdspan.layout.left})}} {\memgloref{}}|memjustarg}{1040} -\glossaryentry{mdspan.layout.left.overview@ {\memgloterm{mdspan.layout.left.overview}}{\memglodesc{(\ref {mdspan.layout.left.overview})}} {\memgloref{}}|memjustarg}{1040} -\glossaryentry{mdspan.layout.left.cons@ {\memgloterm{mdspan.layout.left.cons}}{\memglodesc{(\ref {mdspan.layout.left.cons})}} {\memgloref{}}|memjustarg}{1041} -\glossaryentry{mdspan.layout.left.obs@ {\memgloterm{mdspan.layout.left.obs}}{\memglodesc{(\ref {mdspan.layout.left.obs})}} {\memgloref{}}|memjustarg}{1042} -\glossaryentry{mdspan.layout.right@ {\memgloterm{mdspan.layout.right}}{\memglodesc{(\ref {mdspan.layout.right})}} {\memgloref{}}|memjustarg}{1042} -\glossaryentry{mdspan.layout.right.overview@ {\memgloterm{mdspan.layout.right.overview}}{\memglodesc{(\ref {mdspan.layout.right.overview})}} {\memgloref{}}|memjustarg}{1042} -\glossaryentry{mdspan.layout.right.cons@ {\memgloterm{mdspan.layout.right.cons}}{\memglodesc{(\ref {mdspan.layout.right.cons})}} {\memgloref{}}|memjustarg}{1043} -\glossaryentry{mdspan.layout.right.obs@ {\memgloterm{mdspan.layout.right.obs}}{\memglodesc{(\ref {mdspan.layout.right.obs})}} {\memgloref{}}|memjustarg}{1044} -\glossaryentry{mdspan.layout.stride@ {\memgloterm{mdspan.layout.stride}}{\memglodesc{(\ref {mdspan.layout.stride})}} {\memgloref{}}|memjustarg}{1044} -\glossaryentry{mdspan.layout.stride.overview@ {\memgloterm{mdspan.layout.stride.overview}}{\memglodesc{(\ref {mdspan.layout.stride.overview})}} {\memgloref{}}|memjustarg}{1044} -\glossaryentry{mdspan.layout.stride.expo@ {\memgloterm{mdspan.layout.stride.expo}}{\memglodesc{(\ref {mdspan.layout.stride.expo})}} {\memgloref{}}|memjustarg}{1045} -\glossaryentry{mdspan.layout.stride.cons@ {\memgloterm{mdspan.layout.stride.cons}}{\memglodesc{(\ref {mdspan.layout.stride.cons})}} {\memgloref{}}|memjustarg}{1046} -\glossaryentry{mdspan.layout.stride.obs@ {\memgloterm{mdspan.layout.stride.obs}}{\memglodesc{(\ref {mdspan.layout.stride.obs})}} {\memgloref{}}|memjustarg}{1047} -\glossaryentry{mdspan.accessor@ {\memgloterm{mdspan.accessor}}{\memglodesc{(\ref {mdspan.accessor})}} {\memgloref{}}|memjustarg}{1048} -\glossaryentry{mdspan.accessor.general@ {\memgloterm{mdspan.accessor.general}}{\memglodesc{(\ref {mdspan.accessor.general})}} {\memgloref{}}|memjustarg}{1048} -\glossaryentry{mdspan.accessor.reqmts@ {\memgloterm{mdspan.accessor.reqmts}}{\memglodesc{(\ref {mdspan.accessor.reqmts})}} {\memgloref{}}|memjustarg}{1048} -\glossaryentry{mdspan.accessor.default@ {\memgloterm{mdspan.accessor.default}}{\memglodesc{(\ref {mdspan.accessor.default})}} {\memgloref{}}|memjustarg}{1049} -\glossaryentry{mdspan.accessor.default.overview@ {\memgloterm{mdspan.accessor.default.overview}}{\memglodesc{(\ref {mdspan.accessor.default.overview})}} {\memgloref{}}|memjustarg}{1049} -\glossaryentry{mdspan.accessor.default.members@ {\memgloterm{mdspan.accessor.default.members}}{\memglodesc{(\ref {mdspan.accessor.default.members})}} {\memgloref{}}|memjustarg}{1049} -\glossaryentry{mdspan.mdspan@ {\memgloterm{mdspan.mdspan}}{\memglodesc{(\ref {mdspan.mdspan})}} {\memgloref{}}|memjustarg}{1049} -\glossaryentry{mdspan.mdspan.overview@ {\memgloterm{mdspan.mdspan.overview}}{\memglodesc{(\ref {mdspan.mdspan.overview})}} {\memgloref{}}|memjustarg}{1049} -\glossaryentry{mdspan.mdspan.cons@ {\memgloterm{mdspan.mdspan.cons}}{\memglodesc{(\ref {mdspan.mdspan.cons})}} {\memgloref{}}|memjustarg}{1052} -\glossaryentry{mdspan.mdspan.members@ {\memgloterm{mdspan.mdspan.members}}{\memglodesc{(\ref {mdspan.mdspan.members})}} {\memgloref{}}|memjustarg}{1054} -\glossaryentry{iterators@ {\memgloterm{iterators}}{\memglodesc{(\ref {iterators})}} {\memgloref{}}|memjustarg}{1055} -\glossaryentry{iterators.general@ {\memgloterm{iterators.general}}{\memglodesc{(\ref {iterators.general})}} {\memgloref{}}|memjustarg}{1055} -\glossaryentry{iterator.synopsis@ {\memgloterm{iterator.synopsis}}{\memglodesc{(\ref {iterator.synopsis})}} {\memgloref{}}|memjustarg}{1055} -\glossaryentry{iterator.requirements@ {\memgloterm{iterator.requirements}}{\memglodesc{(\ref {iterator.requirements})}} {\memgloref{}}|memjustarg}{1063} -\glossaryentry{iterator.requirements.general@ {\memgloterm{iterator.requirements.general}}{\memglodesc{(\ref {iterator.requirements.general})}} {\memgloref{}}|memjustarg}{1063} -\glossaryentry{iterator.assoc.types@ {\memgloterm{iterator.assoc.types}}{\memglodesc{(\ref {iterator.assoc.types})}} {\memgloref{}}|memjustarg}{1064} -\glossaryentry{incrementable.traits@ {\memgloterm{incrementable.traits}}{\memglodesc{(\ref {incrementable.traits})}} {\memgloref{}}|memjustarg}{1064} -\glossaryentry{readable.traits@ {\memgloterm{readable.traits}}{\memglodesc{(\ref {readable.traits})}} {\memgloref{}}|memjustarg}{1065} -\glossaryentry{iterator.traits@ {\memgloterm{iterator.traits}}{\memglodesc{(\ref {iterator.traits})}} {\memgloref{}}|memjustarg}{1066} -\glossaryentry{iterator.cust@ {\memgloterm{iterator.cust}}{\memglodesc{(\ref {iterator.cust})}} {\memgloref{}}|memjustarg}{1068} -\glossaryentry{iterator.cust.move@ {\memgloterm{iterator.cust.move}}{\memglodesc{(\ref {iterator.cust.move})}} {\memgloref{}}|memjustarg}{1068} -\glossaryentry{iterator.cust.swap@ {\memgloterm{iterator.cust.swap}}{\memglodesc{(\ref {iterator.cust.swap})}} {\memgloref{}}|memjustarg}{1069} -\glossaryentry{iterator.concepts@ {\memgloterm{iterator.concepts}}{\memglodesc{(\ref {iterator.concepts})}} {\memgloref{}}|memjustarg}{1069} -\glossaryentry{iterator.concepts.general@ {\memgloterm{iterator.concepts.general}}{\memglodesc{(\ref {iterator.concepts.general})}} {\memgloref{}}|memjustarg}{1069} -\glossaryentry{iterator.concept.readable@ {\memgloterm{iterator.concept.readable}}{\memglodesc{(\ref {iterator.concept.readable})}} {\memgloref{}}|memjustarg}{1070} -\glossaryentry{iterator.concept.writable@ {\memgloterm{iterator.concept.writable}}{\memglodesc{(\ref {iterator.concept.writable})}} {\memgloref{}}|memjustarg}{1070} -\glossaryentry{iterator.concept.winc@ {\memgloterm{iterator.concept.winc}}{\memglodesc{(\ref {iterator.concept.winc})}} {\memgloref{}}|memjustarg}{1071} -\glossaryentry{iterator.concept.inc@ {\memgloterm{iterator.concept.inc}}{\memglodesc{(\ref {iterator.concept.inc})}} {\memgloref{}}|memjustarg}{1072} -\glossaryentry{iterator.concept.iterator@ {\memgloterm{iterator.concept.iterator}}{\memglodesc{(\ref {iterator.concept.iterator})}} {\memgloref{}}|memjustarg}{1073} -\glossaryentry{iterator.concept.sentinel@ {\memgloterm{iterator.concept.sentinel}}{\memglodesc{(\ref {iterator.concept.sentinel})}} {\memgloref{}}|memjustarg}{1073} -\glossaryentry{iterator.concept.sizedsentinel@ {\memgloterm{iterator.concept.sizedsentinel}}{\memglodesc{(\ref {iterator.concept.sizedsentinel})}} {\memgloref{}}|memjustarg}{1073} -\glossaryentry{iterator.concept.input@ {\memgloterm{iterator.concept.input}}{\memglodesc{(\ref {iterator.concept.input})}} {\memgloref{}}|memjustarg}{1074} -\glossaryentry{iterator.concept.output@ {\memgloterm{iterator.concept.output}}{\memglodesc{(\ref {iterator.concept.output})}} {\memgloref{}}|memjustarg}{1074} -\glossaryentry{iterator.concept.forward@ {\memgloterm{iterator.concept.forward}}{\memglodesc{(\ref {iterator.concept.forward})}} {\memgloref{}}|memjustarg}{1074} -\glossaryentry{iterator.concept.bidir@ {\memgloterm{iterator.concept.bidir}}{\memglodesc{(\ref {iterator.concept.bidir})}} {\memgloref{}}|memjustarg}{1075} -\glossaryentry{iterator.concept.random.access@ {\memgloterm{iterator.concept.random.access}}{\memglodesc{(\ref {iterator.concept.random.access})}} {\memgloref{}}|memjustarg}{1075} -\glossaryentry{iterator.concept.contiguous@ {\memgloterm{iterator.concept.contiguous}}{\memglodesc{(\ref {iterator.concept.contiguous})}} {\memgloref{}}|memjustarg}{1076} -\glossaryentry{iterator.cpp17@ {\memgloterm{iterator.cpp17}}{\memglodesc{(\ref {iterator.cpp17})}} {\memgloref{}}|memjustarg}{1076} -\glossaryentry{iterator.cpp17.general@ {\memgloterm{iterator.cpp17.general}}{\memglodesc{(\ref {iterator.cpp17.general})}} {\memgloref{}}|memjustarg}{1076} -\glossaryentry{iterator.iterators@ {\memgloterm{iterator.iterators}}{\memglodesc{(\ref {iterator.iterators})}} {\memgloref{}}|memjustarg}{1076} -\glossaryentry{input.iterators@ {\memgloterm{input.iterators}}{\memglodesc{(\ref {input.iterators})}} {\memgloref{}}|memjustarg}{1076} -\glossaryentry{output.iterators@ {\memgloterm{output.iterators}}{\memglodesc{(\ref {output.iterators})}} {\memgloref{}}|memjustarg}{1078} -\glossaryentry{forward.iterators@ {\memgloterm{forward.iterators}}{\memglodesc{(\ref {forward.iterators})}} {\memgloref{}}|memjustarg}{1078} -\glossaryentry{bidirectional.iterators@ {\memgloterm{bidirectional.iterators}}{\memglodesc{(\ref {bidirectional.iterators})}} {\memgloref{}}|memjustarg}{1079} -\glossaryentry{random.access.iterators@ {\memgloterm{random.access.iterators}}{\memglodesc{(\ref {random.access.iterators})}} {\memgloref{}}|memjustarg}{1079} -\glossaryentry{indirectcallable@ {\memgloterm{indirectcallable}}{\memglodesc{(\ref {indirectcallable})}} {\memgloref{}}|memjustarg}{1080} -\glossaryentry{indirectcallable.general@ {\memgloterm{indirectcallable.general}}{\memglodesc{(\ref {indirectcallable.general})}} {\memgloref{}}|memjustarg}{1080} -\glossaryentry{indirectcallable.traits@ {\memgloterm{indirectcallable.traits}}{\memglodesc{(\ref {indirectcallable.traits})}} {\memgloref{}}|memjustarg}{1080} -\glossaryentry{indirectcallable.indirectinvocable@ {\memgloterm{indirectcallable.indirectinvocable}}{\memglodesc{(\ref {indirectcallable.indirectinvocable})}} {\memgloref{}}|memjustarg}{1081} -\glossaryentry{projected@ {\memgloterm{projected}}{\memglodesc{(\ref {projected})}} {\memgloref{}}|memjustarg}{1082} -\glossaryentry{alg.req@ {\memgloterm{alg.req}}{\memglodesc{(\ref {alg.req})}} {\memgloref{}}|memjustarg}{1082} -\glossaryentry{alg.req.general@ {\memgloterm{alg.req.general}}{\memglodesc{(\ref {alg.req.general})}} {\memgloref{}}|memjustarg}{1082} -\glossaryentry{alg.req.ind.move@ {\memgloterm{alg.req.ind.move}}{\memglodesc{(\ref {alg.req.ind.move})}} {\memgloref{}}|memjustarg}{1082} -\glossaryentry{alg.req.ind.copy@ {\memgloterm{alg.req.ind.copy}}{\memglodesc{(\ref {alg.req.ind.copy})}} {\memgloref{}}|memjustarg}{1082} -\glossaryentry{alg.req.ind.swap@ {\memgloterm{alg.req.ind.swap}}{\memglodesc{(\ref {alg.req.ind.swap})}} {\memgloref{}}|memjustarg}{1083} -\glossaryentry{alg.req.ind.cmp@ {\memgloterm{alg.req.ind.cmp}}{\memglodesc{(\ref {alg.req.ind.cmp})}} {\memgloref{}}|memjustarg}{1083} -\glossaryentry{alg.req.permutable@ {\memgloterm{alg.req.permutable}}{\memglodesc{(\ref {alg.req.permutable})}} {\memgloref{}}|memjustarg}{1083} -\glossaryentry{alg.req.mergeable@ {\memgloterm{alg.req.mergeable}}{\memglodesc{(\ref {alg.req.mergeable})}} {\memgloref{}}|memjustarg}{1083} -\glossaryentry{alg.req.sortable@ {\memgloterm{alg.req.sortable}}{\memglodesc{(\ref {alg.req.sortable})}} {\memgloref{}}|memjustarg}{1084} -\glossaryentry{iterator.primitives@ {\memgloterm{iterator.primitives}}{\memglodesc{(\ref {iterator.primitives})}} {\memgloref{}}|memjustarg}{1084} -\glossaryentry{iterator.primitives.general@ {\memgloterm{iterator.primitives.general}}{\memglodesc{(\ref {iterator.primitives.general})}} {\memgloref{}}|memjustarg}{1084} -\glossaryentry{std.iterator.tags@ {\memgloterm{std.iterator.tags}}{\memglodesc{(\ref {std.iterator.tags})}} {\memgloref{}}|memjustarg}{1084} -\glossaryentry{iterator.operations@ {\memgloterm{iterator.operations}}{\memglodesc{(\ref {iterator.operations})}} {\memgloref{}}|memjustarg}{1085} -\glossaryentry{range.iter.ops@ {\memgloterm{range.iter.ops}}{\memglodesc{(\ref {range.iter.ops})}} {\memgloref{}}|memjustarg}{1085} -\glossaryentry{range.iter.ops.general@ {\memgloterm{range.iter.ops.general}}{\memglodesc{(\ref {range.iter.ops.general})}} {\memgloref{}}|memjustarg}{1085} -\glossaryentry{range.iter.op.advance@ {\memgloterm{range.iter.op.advance}}{\memglodesc{(\ref {range.iter.op.advance})}} {\memgloref{}}|memjustarg}{1086} -\glossaryentry{range.iter.op.distance@ {\memgloterm{range.iter.op.distance}}{\memglodesc{(\ref {range.iter.op.distance})}} {\memgloref{}}|memjustarg}{1086} -\glossaryentry{range.iter.op.next@ {\memgloterm{range.iter.op.next}}{\memglodesc{(\ref {range.iter.op.next})}} {\memgloref{}}|memjustarg}{1087} -\glossaryentry{range.iter.op.prev@ {\memgloterm{range.iter.op.prev}}{\memglodesc{(\ref {range.iter.op.prev})}} {\memgloref{}}|memjustarg}{1087} -\glossaryentry{predef.iterators@ {\memgloterm{predef.iterators}}{\memglodesc{(\ref {predef.iterators})}} {\memgloref{}}|memjustarg}{1087} -\glossaryentry{reverse.iterators@ {\memgloterm{reverse.iterators}}{\memglodesc{(\ref {reverse.iterators})}} {\memgloref{}}|memjustarg}{1087} -\glossaryentry{reverse.iterators.general@ {\memgloterm{reverse.iterators.general}}{\memglodesc{(\ref {reverse.iterators.general})}} {\memgloref{}}|memjustarg}{1087} -\glossaryentry{reverse.iterator@ {\memgloterm{reverse.iterator}}{\memglodesc{(\ref {reverse.iterator})}} {\memgloref{}}|memjustarg}{1087} -\glossaryentry{reverse.iter.requirements@ {\memgloterm{reverse.iter.requirements}}{\memglodesc{(\ref {reverse.iter.requirements})}} {\memgloref{}}|memjustarg}{1088} -\glossaryentry{reverse.iter.cons@ {\memgloterm{reverse.iter.cons}}{\memglodesc{(\ref {reverse.iter.cons})}} {\memgloref{}}|memjustarg}{1088} -\glossaryentry{reverse.iter.conv@ {\memgloterm{reverse.iter.conv}}{\memglodesc{(\ref {reverse.iter.conv})}} {\memgloref{}}|memjustarg}{1089} -\glossaryentry{reverse.iter.elem@ {\memgloterm{reverse.iter.elem}}{\memglodesc{(\ref {reverse.iter.elem})}} {\memgloref{}}|memjustarg}{1089} -\glossaryentry{reverse.iter.nav@ {\memgloterm{reverse.iter.nav}}{\memglodesc{(\ref {reverse.iter.nav})}} {\memgloref{}}|memjustarg}{1089} -\glossaryentry{reverse.iter.cmp@ {\memgloterm{reverse.iter.cmp}}{\memglodesc{(\ref {reverse.iter.cmp})}} {\memgloref{}}|memjustarg}{1090} -\glossaryentry{reverse.iter.nonmember@ {\memgloterm{reverse.iter.nonmember}}{\memglodesc{(\ref {reverse.iter.nonmember})}} {\memgloref{}}|memjustarg}{1091} -\glossaryentry{insert.iterators@ {\memgloterm{insert.iterators}}{\memglodesc{(\ref {insert.iterators})}} {\memgloref{}}|memjustarg}{1091} -\glossaryentry{insert.iterators.general@ {\memgloterm{insert.iterators.general}}{\memglodesc{(\ref {insert.iterators.general})}} {\memgloref{}}|memjustarg}{1091} -\glossaryentry{back.insert.iterator@ {\memgloterm{back.insert.iterator}}{\memglodesc{(\ref {back.insert.iterator})}} {\memgloref{}}|memjustarg}{1092} -\glossaryentry{back.insert.iter.ops@ {\memgloterm{back.insert.iter.ops}}{\memglodesc{(\ref {back.insert.iter.ops})}} {\memgloref{}}|memjustarg}{1092} -\glossaryentry{back.inserter@ {\memgloterm{back.inserter}}{\memglodesc{(\ref {back.inserter})}} {\memgloref{}}|memjustarg}{1093} -\glossaryentry{front.insert.iterator@ {\memgloterm{front.insert.iterator}}{\memglodesc{(\ref {front.insert.iterator})}} {\memgloref{}}|memjustarg}{1093} -\glossaryentry{front.insert.iter.ops@ {\memgloterm{front.insert.iter.ops}}{\memglodesc{(\ref {front.insert.iter.ops})}} {\memgloref{}}|memjustarg}{1093} -\glossaryentry{front.inserter@ {\memgloterm{front.inserter}}{\memglodesc{(\ref {front.inserter})}} {\memgloref{}}|memjustarg}{1093} -\glossaryentry{insert.iterator@ {\memgloterm{insert.iterator}}{\memglodesc{(\ref {insert.iterator})}} {\memgloref{}}|memjustarg}{1094} -\glossaryentry{insert.iter.ops@ {\memgloterm{insert.iter.ops}}{\memglodesc{(\ref {insert.iter.ops})}} {\memgloref{}}|memjustarg}{1094} -\glossaryentry{inserter@ {\memgloterm{inserter}}{\memglodesc{(\ref {inserter})}} {\memgloref{}}|memjustarg}{1094} -\glossaryentry{const.iterators@ {\memgloterm{const.iterators}}{\memglodesc{(\ref {const.iterators})}} {\memgloref{}}|memjustarg}{1095} -\glossaryentry{const.iterators.general@ {\memgloterm{const.iterators.general}}{\memglodesc{(\ref {const.iterators.general})}} {\memgloref{}}|memjustarg}{1095} -\glossaryentry{const.iterators.alias@ {\memgloterm{const.iterators.alias}}{\memglodesc{(\ref {const.iterators.alias})}} {\memgloref{}}|memjustarg}{1095} -\glossaryentry{const.iterators.iterator@ {\memgloterm{const.iterators.iterator}}{\memglodesc{(\ref {const.iterators.iterator})}} {\memgloref{}}|memjustarg}{1095} -\glossaryentry{const.iterators.types@ {\memgloterm{const.iterators.types}}{\memglodesc{(\ref {const.iterators.types})}} {\memgloref{}}|memjustarg}{1097} -\glossaryentry{const.iterators.ops@ {\memgloterm{const.iterators.ops}}{\memglodesc{(\ref {const.iterators.ops})}} {\memgloref{}}|memjustarg}{1097} -\glossaryentry{move.iterators@ {\memgloterm{move.iterators}}{\memglodesc{(\ref {move.iterators})}} {\memgloref{}}|memjustarg}{1100} -\glossaryentry{move.iterators.general@ {\memgloterm{move.iterators.general}}{\memglodesc{(\ref {move.iterators.general})}} {\memgloref{}}|memjustarg}{1100} -\glossaryentry{move.iterator@ {\memgloterm{move.iterator}}{\memglodesc{(\ref {move.iterator})}} {\memgloref{}}|memjustarg}{1100} -\glossaryentry{move.iter.requirements@ {\memgloterm{move.iter.requirements}}{\memglodesc{(\ref {move.iter.requirements})}} {\memgloref{}}|memjustarg}{1101} -\glossaryentry{move.iter.cons@ {\memgloterm{move.iter.cons}}{\memglodesc{(\ref {move.iter.cons})}} {\memgloref{}}|memjustarg}{1101} -\glossaryentry{move.iter.op.conv@ {\memgloterm{move.iter.op.conv}}{\memglodesc{(\ref {move.iter.op.conv})}} {\memgloref{}}|memjustarg}{1101} -\glossaryentry{move.iter.elem@ {\memgloterm{move.iter.elem}}{\memglodesc{(\ref {move.iter.elem})}} {\memgloref{}}|memjustarg}{1102} -\glossaryentry{move.iter.nav@ {\memgloterm{move.iter.nav}}{\memglodesc{(\ref {move.iter.nav})}} {\memgloref{}}|memjustarg}{1102} -\glossaryentry{move.iter.op.comp@ {\memgloterm{move.iter.op.comp}}{\memglodesc{(\ref {move.iter.op.comp})}} {\memgloref{}}|memjustarg}{1102} -\glossaryentry{move.iter.nonmember@ {\memgloterm{move.iter.nonmember}}{\memglodesc{(\ref {move.iter.nonmember})}} {\memgloref{}}|memjustarg}{1103} -\glossaryentry{move.sentinel@ {\memgloterm{move.sentinel}}{\memglodesc{(\ref {move.sentinel})}} {\memgloref{}}|memjustarg}{1104} -\glossaryentry{move.sent.ops@ {\memgloterm{move.sent.ops}}{\memglodesc{(\ref {move.sent.ops})}} {\memgloref{}}|memjustarg}{1104} -\glossaryentry{iterators.common@ {\memgloterm{iterators.common}}{\memglodesc{(\ref {iterators.common})}} {\memgloref{}}|memjustarg}{1105} -\glossaryentry{common.iterator@ {\memgloterm{common.iterator}}{\memglodesc{(\ref {common.iterator})}} {\memgloref{}}|memjustarg}{1105} -\glossaryentry{common.iter.types@ {\memgloterm{common.iter.types}}{\memglodesc{(\ref {common.iter.types})}} {\memgloref{}}|memjustarg}{1106} -\glossaryentry{common.iter.const@ {\memgloterm{common.iter.const}}{\memglodesc{(\ref {common.iter.const})}} {\memgloref{}}|memjustarg}{1106} -\glossaryentry{common.iter.access@ {\memgloterm{common.iter.access}}{\memglodesc{(\ref {common.iter.access})}} {\memgloref{}}|memjustarg}{1107} -\glossaryentry{common.iter.nav@ {\memgloterm{common.iter.nav}}{\memglodesc{(\ref {common.iter.nav})}} {\memgloref{}}|memjustarg}{1107} -\glossaryentry{common.iter.cmp@ {\memgloterm{common.iter.cmp}}{\memglodesc{(\ref {common.iter.cmp})}} {\memgloref{}}|memjustarg}{1108} -\glossaryentry{common.iter.cust@ {\memgloterm{common.iter.cust}}{\memglodesc{(\ref {common.iter.cust})}} {\memgloref{}}|memjustarg}{1108} -\glossaryentry{default.sentinel@ {\memgloterm{default.sentinel}}{\memglodesc{(\ref {default.sentinel})}} {\memgloref{}}|memjustarg}{1109} -\glossaryentry{iterators.counted@ {\memgloterm{iterators.counted}}{\memglodesc{(\ref {iterators.counted})}} {\memgloref{}}|memjustarg}{1109} -\glossaryentry{counted.iterator@ {\memgloterm{counted.iterator}}{\memglodesc{(\ref {counted.iterator})}} {\memgloref{}}|memjustarg}{1109} -\glossaryentry{counted.iter.const@ {\memgloterm{counted.iter.const}}{\memglodesc{(\ref {counted.iter.const})}} {\memgloref{}}|memjustarg}{1110} -\glossaryentry{counted.iter.access@ {\memgloterm{counted.iter.access}}{\memglodesc{(\ref {counted.iter.access})}} {\memgloref{}}|memjustarg}{1111} -\glossaryentry{counted.iter.elem@ {\memgloterm{counted.iter.elem}}{\memglodesc{(\ref {counted.iter.elem})}} {\memgloref{}}|memjustarg}{1111} -\glossaryentry{counted.iter.nav@ {\memgloterm{counted.iter.nav}}{\memglodesc{(\ref {counted.iter.nav})}} {\memgloref{}}|memjustarg}{1111} -\glossaryentry{counted.iter.cmp@ {\memgloterm{counted.iter.cmp}}{\memglodesc{(\ref {counted.iter.cmp})}} {\memgloref{}}|memjustarg}{1113} -\glossaryentry{counted.iter.cust@ {\memgloterm{counted.iter.cust}}{\memglodesc{(\ref {counted.iter.cust})}} {\memgloref{}}|memjustarg}{1113} -\glossaryentry{unreachable.sentinel@ {\memgloterm{unreachable.sentinel}}{\memglodesc{(\ref {unreachable.sentinel})}} {\memgloref{}}|memjustarg}{1113} -\glossaryentry{stream.iterators@ {\memgloterm{stream.iterators}}{\memglodesc{(\ref {stream.iterators})}} {\memgloref{}}|memjustarg}{1114} -\glossaryentry{stream.iterators.general@ {\memgloterm{stream.iterators.general}}{\memglodesc{(\ref {stream.iterators.general})}} {\memgloref{}}|memjustarg}{1114} -\glossaryentry{istream.iterator@ {\memgloterm{istream.iterator}}{\memglodesc{(\ref {istream.iterator})}} {\memgloref{}}|memjustarg}{1114} -\glossaryentry{istream.iterator.general@ {\memgloterm{istream.iterator.general}}{\memglodesc{(\ref {istream.iterator.general})}} {\memgloref{}}|memjustarg}{1114} -\glossaryentry{istream.iterator.cons@ {\memgloterm{istream.iterator.cons}}{\memglodesc{(\ref {istream.iterator.cons})}} {\memgloref{}}|memjustarg}{1114} -\glossaryentry{istream.iterator.ops@ {\memgloterm{istream.iterator.ops}}{\memglodesc{(\ref {istream.iterator.ops})}} {\memgloref{}}|memjustarg}{1115} -\glossaryentry{ostream.iterator@ {\memgloterm{ostream.iterator}}{\memglodesc{(\ref {ostream.iterator})}} {\memgloref{}}|memjustarg}{1115} -\glossaryentry{ostream.iterator.general@ {\memgloterm{ostream.iterator.general}}{\memglodesc{(\ref {ostream.iterator.general})}} {\memgloref{}}|memjustarg}{1115} -\glossaryentry{ostream.iterator.cons.des@ {\memgloterm{ostream.iterator.cons.des}}{\memglodesc{(\ref {ostream.iterator.cons.des})}} {\memgloref{}}|memjustarg}{1116} -\glossaryentry{ostream.iterator.ops@ {\memgloterm{ostream.iterator.ops}}{\memglodesc{(\ref {ostream.iterator.ops})}} {\memgloref{}}|memjustarg}{1116} -\glossaryentry{istreambuf.iterator@ {\memgloterm{istreambuf.iterator}}{\memglodesc{(\ref {istreambuf.iterator})}} {\memgloref{}}|memjustarg}{1116} -\glossaryentry{istreambuf.iterator.general@ {\memgloterm{istreambuf.iterator.general}}{\memglodesc{(\ref {istreambuf.iterator.general})}} {\memgloref{}}|memjustarg}{1116} -\glossaryentry{istreambuf.iterator.proxy@ {\memgloterm{istreambuf.iterator.proxy}}{\memglodesc{(\ref {istreambuf.iterator.proxy})}} {\memgloref{}}|memjustarg}{1117} -\glossaryentry{istreambuf.iterator.cons@ {\memgloterm{istreambuf.iterator.cons}}{\memglodesc{(\ref {istreambuf.iterator.cons})}} {\memgloref{}}|memjustarg}{1117} -\glossaryentry{istreambuf.iterator.ops@ {\memgloterm{istreambuf.iterator.ops}}{\memglodesc{(\ref {istreambuf.iterator.ops})}} {\memgloref{}}|memjustarg}{1118} -\glossaryentry{ostreambuf.iterator@ {\memgloterm{ostreambuf.iterator}}{\memglodesc{(\ref {ostreambuf.iterator})}} {\memgloref{}}|memjustarg}{1118} -\glossaryentry{ostreambuf.iterator.general@ {\memgloterm{ostreambuf.iterator.general}}{\memglodesc{(\ref {ostreambuf.iterator.general})}} {\memgloref{}}|memjustarg}{1118} -\glossaryentry{ostreambuf.iter.cons@ {\memgloterm{ostreambuf.iter.cons}}{\memglodesc{(\ref {ostreambuf.iter.cons})}} {\memgloref{}}|memjustarg}{1119} -\glossaryentry{ostreambuf.iter.ops@ {\memgloterm{ostreambuf.iter.ops}}{\memglodesc{(\ref {ostreambuf.iter.ops})}} {\memgloref{}}|memjustarg}{1119} -\glossaryentry{iterator.range@ {\memgloterm{iterator.range}}{\memglodesc{(\ref {iterator.range})}} {\memgloref{}}|memjustarg}{1119} -\glossaryentry{ranges@ {\memgloterm{ranges}}{\memglodesc{(\ref {ranges})}} {\memgloref{}}|memjustarg}{1122} -\glossaryentry{ranges.general@ {\memgloterm{ranges.general}}{\memglodesc{(\ref {ranges.general})}} {\memgloref{}}|memjustarg}{1122} -\glossaryentry{ranges.syn@ {\memgloterm{ranges.syn}}{\memglodesc{(\ref {ranges.syn})}} {\memgloref{}}|memjustarg}{1122} -\glossaryentry{range.access@ {\memgloterm{range.access}}{\memglodesc{(\ref {range.access})}} {\memgloref{}}|memjustarg}{1131} -\glossaryentry{range.access.general@ {\memgloterm{range.access.general}}{\memglodesc{(\ref {range.access.general})}} {\memgloref{}}|memjustarg}{1131} -\glossaryentry{range.access.begin@ {\memgloterm{range.access.begin}}{\memglodesc{(\ref {range.access.begin})}} {\memgloref{}}|memjustarg}{1131} -\glossaryentry{range.access.end@ {\memgloterm{range.access.end}}{\memglodesc{(\ref {range.access.end})}} {\memgloref{}}|memjustarg}{1131} -\glossaryentry{range.access.cbegin@ {\memgloterm{range.access.cbegin}}{\memglodesc{(\ref {range.access.cbegin})}} {\memgloref{}}|memjustarg}{1132} -\glossaryentry{range.access.cend@ {\memgloterm{range.access.cend}}{\memglodesc{(\ref {range.access.cend})}} {\memgloref{}}|memjustarg}{1132} -\glossaryentry{range.access.rbegin@ {\memgloterm{range.access.rbegin}}{\memglodesc{(\ref {range.access.rbegin})}} {\memgloref{}}|memjustarg}{1132} -\glossaryentry{range.access.rend@ {\memgloterm{range.access.rend}}{\memglodesc{(\ref {range.access.rend})}} {\memgloref{}}|memjustarg}{1132} -\glossaryentry{range.access.crbegin@ {\memgloterm{range.access.crbegin}}{\memglodesc{(\ref {range.access.crbegin})}} {\memgloref{}}|memjustarg}{1133} -\glossaryentry{range.access.crend@ {\memgloterm{range.access.crend}}{\memglodesc{(\ref {range.access.crend})}} {\memgloref{}}|memjustarg}{1133} -\glossaryentry{range.prim.size@ {\memgloterm{range.prim.size}}{\memglodesc{(\ref {range.prim.size})}} {\memgloref{}}|memjustarg}{1133} -\glossaryentry{range.prim.ssize@ {\memgloterm{range.prim.ssize}}{\memglodesc{(\ref {range.prim.ssize})}} {\memgloref{}}|memjustarg}{1134} -\glossaryentry{range.prim.empty@ {\memgloterm{range.prim.empty}}{\memglodesc{(\ref {range.prim.empty})}} {\memgloref{}}|memjustarg}{1134} -\glossaryentry{range.prim.data@ {\memgloterm{range.prim.data}}{\memglodesc{(\ref {range.prim.data})}} {\memgloref{}}|memjustarg}{1134} -\glossaryentry{range.prim.cdata@ {\memgloterm{range.prim.cdata}}{\memglodesc{(\ref {range.prim.cdata})}} {\memgloref{}}|memjustarg}{1134} -\glossaryentry{range.req@ {\memgloterm{range.req}}{\memglodesc{(\ref {range.req})}} {\memgloref{}}|memjustarg}{1135} -\glossaryentry{range.req.general@ {\memgloterm{range.req.general}}{\memglodesc{(\ref {range.req.general})}} {\memgloref{}}|memjustarg}{1135} -\glossaryentry{range.range@ {\memgloterm{range.range}}{\memglodesc{(\ref {range.range})}} {\memgloref{}}|memjustarg}{1135} -\glossaryentry{range.sized@ {\memgloterm{range.sized}}{\memglodesc{(\ref {range.sized})}} {\memgloref{}}|memjustarg}{1136} -\glossaryentry{range.view@ {\memgloterm{range.view}}{\memglodesc{(\ref {range.view})}} {\memgloref{}}|memjustarg}{1136} -\glossaryentry{range.refinements@ {\memgloterm{range.refinements}}{\memglodesc{(\ref {range.refinements})}} {\memgloref{}}|memjustarg}{1137} -\glossaryentry{range.utility@ {\memgloterm{range.utility}}{\memglodesc{(\ref {range.utility})}} {\memgloref{}}|memjustarg}{1138} -\glossaryentry{range.utility.general@ {\memgloterm{range.utility.general}}{\memglodesc{(\ref {range.utility.general})}} {\memgloref{}}|memjustarg}{1138} -\glossaryentry{range.utility.helpers@ {\memgloterm{range.utility.helpers}}{\memglodesc{(\ref {range.utility.helpers})}} {\memgloref{}}|memjustarg}{1138} -\glossaryentry{view.interface@ {\memgloterm{view.interface}}{\memglodesc{(\ref {view.interface})}} {\memgloref{}}|memjustarg}{1138} -\glossaryentry{view.interface.general@ {\memgloterm{view.interface.general}}{\memglodesc{(\ref {view.interface.general})}} {\memgloref{}}|memjustarg}{1138} -\glossaryentry{view.interface.members@ {\memgloterm{view.interface.members}}{\memglodesc{(\ref {view.interface.members})}} {\memgloref{}}|memjustarg}{1140} -\glossaryentry{range.subrange@ {\memgloterm{range.subrange}}{\memglodesc{(\ref {range.subrange})}} {\memgloref{}}|memjustarg}{1140} -\glossaryentry{range.subrange.general@ {\memgloterm{range.subrange.general}}{\memglodesc{(\ref {range.subrange.general})}} {\memgloref{}}|memjustarg}{1140} -\glossaryentry{range.subrange.ctor@ {\memgloterm{range.subrange.ctor}}{\memglodesc{(\ref {range.subrange.ctor})}} {\memgloref{}}|memjustarg}{1141} -\glossaryentry{range.subrange.access@ {\memgloterm{range.subrange.access}}{\memglodesc{(\ref {range.subrange.access})}} {\memgloref{}}|memjustarg}{1142} -\glossaryentry{range.dangling@ {\memgloterm{range.dangling}}{\memglodesc{(\ref {range.dangling})}} {\memgloref{}}|memjustarg}{1143} -\glossaryentry{range.elementsof@ {\memgloterm{range.elementsof}}{\memglodesc{(\ref {range.elementsof})}} {\memgloref{}}|memjustarg}{1144} -\glossaryentry{range.utility.conv@ {\memgloterm{range.utility.conv}}{\memglodesc{(\ref {range.utility.conv})}} {\memgloref{}}|memjustarg}{1144} -\glossaryentry{range.utility.conv.general@ {\memgloterm{range.utility.conv.general}}{\memglodesc{(\ref {range.utility.conv.general})}} {\memgloref{}}|memjustarg}{1144} -\glossaryentry{range.utility.conv.to@ {\memgloterm{range.utility.conv.to}}{\memglodesc{(\ref {range.utility.conv.to})}} {\memgloref{}}|memjustarg}{1145} -\glossaryentry{range.utility.conv.adaptors@ {\memgloterm{range.utility.conv.adaptors}}{\memglodesc{(\ref {range.utility.conv.adaptors})}} {\memgloref{}}|memjustarg}{1146} -\glossaryentry{range.factories@ {\memgloterm{range.factories}}{\memglodesc{(\ref {range.factories})}} {\memgloref{}}|memjustarg}{1146} -\glossaryentry{range.factories.general@ {\memgloterm{range.factories.general}}{\memglodesc{(\ref {range.factories.general})}} {\memgloref{}}|memjustarg}{1146} -\glossaryentry{range.empty@ {\memgloterm{range.empty}}{\memglodesc{(\ref {range.empty})}} {\memgloref{}}|memjustarg}{1146} -\glossaryentry{range.empty.overview@ {\memgloterm{range.empty.overview}}{\memglodesc{(\ref {range.empty.overview})}} {\memgloref{}}|memjustarg}{1146} -\glossaryentry{range.empty.view@ {\memgloterm{range.empty.view}}{\memglodesc{(\ref {range.empty.view})}} {\memgloref{}}|memjustarg}{1146} -\glossaryentry{range.single@ {\memgloterm{range.single}}{\memglodesc{(\ref {range.single})}} {\memgloref{}}|memjustarg}{1147} -\glossaryentry{range.single.overview@ {\memgloterm{range.single.overview}}{\memglodesc{(\ref {range.single.overview})}} {\memgloref{}}|memjustarg}{1147} -\glossaryentry{range.single.view@ {\memgloterm{range.single.view}}{\memglodesc{(\ref {range.single.view})}} {\memgloref{}}|memjustarg}{1147} -\glossaryentry{range.iota@ {\memgloterm{range.iota}}{\memglodesc{(\ref {range.iota})}} {\memgloref{}}|memjustarg}{1148} -\glossaryentry{range.iota.overview@ {\memgloterm{range.iota.overview}}{\memglodesc{(\ref {range.iota.overview})}} {\memgloref{}}|memjustarg}{1148} -\glossaryentry{range.iota.view@ {\memgloterm{range.iota.view}}{\memglodesc{(\ref {range.iota.view})}} {\memgloref{}}|memjustarg}{1148} -\glossaryentry{range.iota.iterator@ {\memgloterm{range.iota.iterator}}{\memglodesc{(\ref {range.iota.iterator})}} {\memgloref{}}|memjustarg}{1150} -\glossaryentry{range.iota.sentinel@ {\memgloterm{range.iota.sentinel}}{\memglodesc{(\ref {range.iota.sentinel})}} {\memgloref{}}|memjustarg}{1153} -\glossaryentry{range.repeat@ {\memgloterm{range.repeat}}{\memglodesc{(\ref {range.repeat})}} {\memgloref{}}|memjustarg}{1154} -\glossaryentry{range.repeat.overview@ {\memgloterm{range.repeat.overview}}{\memglodesc{(\ref {range.repeat.overview})}} {\memgloref{}}|memjustarg}{1154} -\glossaryentry{range.repeat.view@ {\memgloterm{range.repeat.view}}{\memglodesc{(\ref {range.repeat.view})}} {\memgloref{}}|memjustarg}{1154} -\glossaryentry{range.repeat.iterator@ {\memgloterm{range.repeat.iterator}}{\memglodesc{(\ref {range.repeat.iterator})}} {\memgloref{}}|memjustarg}{1155} -\glossaryentry{range.istream@ {\memgloterm{range.istream}}{\memglodesc{(\ref {range.istream})}} {\memgloref{}}|memjustarg}{1157} -\glossaryentry{range.istream.overview@ {\memgloterm{range.istream.overview}}{\memglodesc{(\ref {range.istream.overview})}} {\memgloref{}}|memjustarg}{1157} -\glossaryentry{range.istream.view@ {\memgloterm{range.istream.view}}{\memglodesc{(\ref {range.istream.view})}} {\memgloref{}}|memjustarg}{1158} -\glossaryentry{range.istream.iterator@ {\memgloterm{range.istream.iterator}}{\memglodesc{(\ref {range.istream.iterator})}} {\memgloref{}}|memjustarg}{1158} -\glossaryentry{range.adaptors@ {\memgloterm{range.adaptors}}{\memglodesc{(\ref {range.adaptors})}} {\memgloref{}}|memjustarg}{1159} -\glossaryentry{range.adaptors.general@ {\memgloterm{range.adaptors.general}}{\memglodesc{(\ref {range.adaptors.general})}} {\memgloref{}}|memjustarg}{1159} -\glossaryentry{range.adaptor.object@ {\memgloterm{range.adaptor.object}}{\memglodesc{(\ref {range.adaptor.object})}} {\memgloref{}}|memjustarg}{1159} -\glossaryentry{range.move.wrap@ {\memgloterm{range.move.wrap}}{\memglodesc{(\ref {range.move.wrap})}} {\memgloref{}}|memjustarg}{1160} -\glossaryentry{range.nonprop.cache@ {\memgloterm{range.nonprop.cache}}{\memglodesc{(\ref {range.nonprop.cache})}} {\memgloref{}}|memjustarg}{1161} -\glossaryentry{range.adaptor.helpers@ {\memgloterm{range.adaptor.helpers}}{\memglodesc{(\ref {range.adaptor.helpers})}} {\memgloref{}}|memjustarg}{1162} -\glossaryentry{range.all@ {\memgloterm{range.all}}{\memglodesc{(\ref {range.all})}} {\memgloref{}}|memjustarg}{1162} -\glossaryentry{range.all.general@ {\memgloterm{range.all.general}}{\memglodesc{(\ref {range.all.general})}} {\memgloref{}}|memjustarg}{1162} -\glossaryentry{range.ref.view@ {\memgloterm{range.ref.view}}{\memglodesc{(\ref {range.ref.view})}} {\memgloref{}}|memjustarg}{1162} -\glossaryentry{range.owning.view@ {\memgloterm{range.owning.view}}{\memglodesc{(\ref {range.owning.view})}} {\memgloref{}}|memjustarg}{1163} -\glossaryentry{range.as.rvalue@ {\memgloterm{range.as.rvalue}}{\memglodesc{(\ref {range.as.rvalue})}} {\memgloref{}}|memjustarg}{1164} -\glossaryentry{range.as.rvalue.overview@ {\memgloterm{range.as.rvalue.overview}}{\memglodesc{(\ref {range.as.rvalue.overview})}} {\memgloref{}}|memjustarg}{1164} -\glossaryentry{range.as.rvalue.view@ {\memgloterm{range.as.rvalue.view}}{\memglodesc{(\ref {range.as.rvalue.view})}} {\memgloref{}}|memjustarg}{1164} -\glossaryentry{range.filter@ {\memgloterm{range.filter}}{\memglodesc{(\ref {range.filter})}} {\memgloref{}}|memjustarg}{1165} -\glossaryentry{range.filter.overview@ {\memgloterm{range.filter.overview}}{\memglodesc{(\ref {range.filter.overview})}} {\memgloref{}}|memjustarg}{1165} -\glossaryentry{range.filter.view@ {\memgloterm{range.filter.view}}{\memglodesc{(\ref {range.filter.view})}} {\memgloref{}}|memjustarg}{1165} -\glossaryentry{range.filter.iterator@ {\memgloterm{range.filter.iterator}}{\memglodesc{(\ref {range.filter.iterator})}} {\memgloref{}}|memjustarg}{1166} -\glossaryentry{range.filter.sentinel@ {\memgloterm{range.filter.sentinel}}{\memglodesc{(\ref {range.filter.sentinel})}} {\memgloref{}}|memjustarg}{1168} -\glossaryentry{range.transform@ {\memgloterm{range.transform}}{\memglodesc{(\ref {range.transform})}} {\memgloref{}}|memjustarg}{1168} -\glossaryentry{range.transform.overview@ {\memgloterm{range.transform.overview}}{\memglodesc{(\ref {range.transform.overview})}} {\memgloref{}}|memjustarg}{1168} -\glossaryentry{range.transform.view@ {\memgloterm{range.transform.view}}{\memglodesc{(\ref {range.transform.view})}} {\memgloref{}}|memjustarg}{1168} -\glossaryentry{range.transform.iterator@ {\memgloterm{range.transform.iterator}}{\memglodesc{(\ref {range.transform.iterator})}} {\memgloref{}}|memjustarg}{1170} -\glossaryentry{range.transform.sentinel@ {\memgloterm{range.transform.sentinel}}{\memglodesc{(\ref {range.transform.sentinel})}} {\memgloref{}}|memjustarg}{1173} -\glossaryentry{range.take@ {\memgloterm{range.take}}{\memglodesc{(\ref {range.take})}} {\memgloref{}}|memjustarg}{1174} -\glossaryentry{range.take.overview@ {\memgloterm{range.take.overview}}{\memglodesc{(\ref {range.take.overview})}} {\memgloref{}}|memjustarg}{1174} -\glossaryentry{range.take.view@ {\memgloterm{range.take.view}}{\memglodesc{(\ref {range.take.view})}} {\memgloref{}}|memjustarg}{1174} -\glossaryentry{range.take.sentinel@ {\memgloterm{range.take.sentinel}}{\memglodesc{(\ref {range.take.sentinel})}} {\memgloref{}}|memjustarg}{1176} -\glossaryentry{range.take.while@ {\memgloterm{range.take.while}}{\memglodesc{(\ref {range.take.while})}} {\memgloref{}}|memjustarg}{1177} -\glossaryentry{range.take.while.overview@ {\memgloterm{range.take.while.overview}}{\memglodesc{(\ref {range.take.while.overview})}} {\memgloref{}}|memjustarg}{1177} -\glossaryentry{range.take.while.view@ {\memgloterm{range.take.while.view}}{\memglodesc{(\ref {range.take.while.view})}} {\memgloref{}}|memjustarg}{1177} -\glossaryentry{range.take.while.sentinel@ {\memgloterm{range.take.while.sentinel}}{\memglodesc{(\ref {range.take.while.sentinel})}} {\memgloref{}}|memjustarg}{1178} -\glossaryentry{range.drop@ {\memgloterm{range.drop}}{\memglodesc{(\ref {range.drop})}} {\memgloref{}}|memjustarg}{1179} -\glossaryentry{range.drop.overview@ {\memgloterm{range.drop.overview}}{\memglodesc{(\ref {range.drop.overview})}} {\memgloref{}}|memjustarg}{1179} -\glossaryentry{range.drop.view@ {\memgloterm{range.drop.view}}{\memglodesc{(\ref {range.drop.view})}} {\memgloref{}}|memjustarg}{1179} -\glossaryentry{range.drop.while@ {\memgloterm{range.drop.while}}{\memglodesc{(\ref {range.drop.while})}} {\memgloref{}}|memjustarg}{1180} -\glossaryentry{range.drop.while.overview@ {\memgloterm{range.drop.while.overview}}{\memglodesc{(\ref {range.drop.while.overview})}} {\memgloref{}}|memjustarg}{1180} -\glossaryentry{range.drop.while.view@ {\memgloterm{range.drop.while.view}}{\memglodesc{(\ref {range.drop.while.view})}} {\memgloref{}}|memjustarg}{1181} -\glossaryentry{range.join@ {\memgloterm{range.join}}{\memglodesc{(\ref {range.join})}} {\memgloref{}}|memjustarg}{1181} -\glossaryentry{range.join.overview@ {\memgloterm{range.join.overview}}{\memglodesc{(\ref {range.join.overview})}} {\memgloref{}}|memjustarg}{1181} -\glossaryentry{range.join.view@ {\memgloterm{range.join.view}}{\memglodesc{(\ref {range.join.view})}} {\memgloref{}}|memjustarg}{1181} -\glossaryentry{range.join.iterator@ {\memgloterm{range.join.iterator}}{\memglodesc{(\ref {range.join.iterator})}} {\memgloref{}}|memjustarg}{1183} -\glossaryentry{range.join.sentinel@ {\memgloterm{range.join.sentinel}}{\memglodesc{(\ref {range.join.sentinel})}} {\memgloref{}}|memjustarg}{1186} -\glossaryentry{range.join.with@ {\memgloterm{range.join.with}}{\memglodesc{(\ref {range.join.with})}} {\memgloref{}}|memjustarg}{1187} -\glossaryentry{range.join.with.overview@ {\memgloterm{range.join.with.overview}}{\memglodesc{(\ref {range.join.with.overview})}} {\memgloref{}}|memjustarg}{1187} -\glossaryentry{range.join.with.view@ {\memgloterm{range.join.with.view}}{\memglodesc{(\ref {range.join.with.view})}} {\memgloref{}}|memjustarg}{1187} -\glossaryentry{range.join.with.iterator@ {\memgloterm{range.join.with.iterator}}{\memglodesc{(\ref {range.join.with.iterator})}} {\memgloref{}}|memjustarg}{1189} -\glossaryentry{range.join.with.sentinel@ {\memgloterm{range.join.with.sentinel}}{\memglodesc{(\ref {range.join.with.sentinel})}} {\memgloref{}}|memjustarg}{1192} -\glossaryentry{range.lazy.split@ {\memgloterm{range.lazy.split}}{\memglodesc{(\ref {range.lazy.split})}} {\memgloref{}}|memjustarg}{1193} -\glossaryentry{range.lazy.split.overview@ {\memgloterm{range.lazy.split.overview}}{\memglodesc{(\ref {range.lazy.split.overview})}} {\memgloref{}}|memjustarg}{1193} -\glossaryentry{range.lazy.split.view@ {\memgloterm{range.lazy.split.view}}{\memglodesc{(\ref {range.lazy.split.view})}} {\memgloref{}}|memjustarg}{1193} -\glossaryentry{range.lazy.split.outer@ {\memgloterm{range.lazy.split.outer}}{\memglodesc{(\ref {range.lazy.split.outer})}} {\memgloref{}}|memjustarg}{1195} -\glossaryentry{range.lazy.split.outer.value@ {\memgloterm{range.lazy.split.outer.value}}{\memglodesc{(\ref {range.lazy.split.outer.value})}} {\memgloref{}}|memjustarg}{1197} -\glossaryentry{range.lazy.split.inner@ {\memgloterm{range.lazy.split.inner}}{\memglodesc{(\ref {range.lazy.split.inner})}} {\memgloref{}}|memjustarg}{1197} -\glossaryentry{range.split@ {\memgloterm{range.split}}{\memglodesc{(\ref {range.split})}} {\memgloref{}}|memjustarg}{1199} -\glossaryentry{range.split.overview@ {\memgloterm{range.split.overview}}{\memglodesc{(\ref {range.split.overview})}} {\memgloref{}}|memjustarg}{1199} -\glossaryentry{range.split.view@ {\memgloterm{range.split.view}}{\memglodesc{(\ref {range.split.view})}} {\memgloref{}}|memjustarg}{1199} -\glossaryentry{range.split.iterator@ {\memgloterm{range.split.iterator}}{\memglodesc{(\ref {range.split.iterator})}} {\memgloref{}}|memjustarg}{1200} -\glossaryentry{range.split.sentinel@ {\memgloterm{range.split.sentinel}}{\memglodesc{(\ref {range.split.sentinel})}} {\memgloref{}}|memjustarg}{1201} -\glossaryentry{range.counted@ {\memgloterm{range.counted}}{\memglodesc{(\ref {range.counted})}} {\memgloref{}}|memjustarg}{1202} -\glossaryentry{range.common@ {\memgloterm{range.common}}{\memglodesc{(\ref {range.common})}} {\memgloref{}}|memjustarg}{1202} -\glossaryentry{range.common.overview@ {\memgloterm{range.common.overview}}{\memglodesc{(\ref {range.common.overview})}} {\memgloref{}}|memjustarg}{1202} -\glossaryentry{range.common.view@ {\memgloterm{range.common.view}}{\memglodesc{(\ref {range.common.view})}} {\memgloref{}}|memjustarg}{1203} -\glossaryentry{range.reverse@ {\memgloterm{range.reverse}}{\memglodesc{(\ref {range.reverse})}} {\memgloref{}}|memjustarg}{1204} -\glossaryentry{range.reverse.overview@ {\memgloterm{range.reverse.overview}}{\memglodesc{(\ref {range.reverse.overview})}} {\memgloref{}}|memjustarg}{1204} -\glossaryentry{range.reverse.view@ {\memgloterm{range.reverse.view}}{\memglodesc{(\ref {range.reverse.view})}} {\memgloref{}}|memjustarg}{1204} -\glossaryentry{range.as.const@ {\memgloterm{range.as.const}}{\memglodesc{(\ref {range.as.const})}} {\memgloref{}}|memjustarg}{1205} -\glossaryentry{range.as.const.overview@ {\memgloterm{range.as.const.overview}}{\memglodesc{(\ref {range.as.const.overview})}} {\memgloref{}}|memjustarg}{1205} -\glossaryentry{range.as.const.view@ {\memgloterm{range.as.const.view}}{\memglodesc{(\ref {range.as.const.view})}} {\memgloref{}}|memjustarg}{1205} -\glossaryentry{range.elements@ {\memgloterm{range.elements}}{\memglodesc{(\ref {range.elements})}} {\memgloref{}}|memjustarg}{1206} -\glossaryentry{range.elements.overview@ {\memgloterm{range.elements.overview}}{\memglodesc{(\ref {range.elements.overview})}} {\memgloref{}}|memjustarg}{1206} -\glossaryentry{range.elements.view@ {\memgloterm{range.elements.view}}{\memglodesc{(\ref {range.elements.view})}} {\memgloref{}}|memjustarg}{1207} -\glossaryentry{range.elements.iterator@ {\memgloterm{range.elements.iterator}}{\memglodesc{(\ref {range.elements.iterator})}} {\memgloref{}}|memjustarg}{1207} -\glossaryentry{range.elements.sentinel@ {\memgloterm{range.elements.sentinel}}{\memglodesc{(\ref {range.elements.sentinel})}} {\memgloref{}}|memjustarg}{1211} -\glossaryentry{range.enumerate@ {\memgloterm{range.enumerate}}{\memglodesc{(\ref {range.enumerate})}} {\memgloref{}}|memjustarg}{1212} -\glossaryentry{range.enumerate.overview@ {\memgloterm{range.enumerate.overview}}{\memglodesc{(\ref {range.enumerate.overview})}} {\memgloref{}}|memjustarg}{1212} -\glossaryentry{range.enumerate.view@ {\memgloterm{range.enumerate.view}}{\memglodesc{(\ref {range.enumerate.view})}} {\memgloref{}}|memjustarg}{1212} -\glossaryentry{range.enumerate.iterator@ {\memgloterm{range.enumerate.iterator}}{\memglodesc{(\ref {range.enumerate.iterator})}} {\memgloref{}}|memjustarg}{1213} -\glossaryentry{range.enumerate.sentinel@ {\memgloterm{range.enumerate.sentinel}}{\memglodesc{(\ref {range.enumerate.sentinel})}} {\memgloref{}}|memjustarg}{1215} -\glossaryentry{range.zip@ {\memgloterm{range.zip}}{\memglodesc{(\ref {range.zip})}} {\memgloref{}}|memjustarg}{1216} -\glossaryentry{range.zip.overview@ {\memgloterm{range.zip.overview}}{\memglodesc{(\ref {range.zip.overview})}} {\memgloref{}}|memjustarg}{1216} -\glossaryentry{range.zip.view@ {\memgloterm{range.zip.view}}{\memglodesc{(\ref {range.zip.view})}} {\memgloref{}}|memjustarg}{1217} -\glossaryentry{range.zip.iterator@ {\memgloterm{range.zip.iterator}}{\memglodesc{(\ref {range.zip.iterator})}} {\memgloref{}}|memjustarg}{1218} -\glossaryentry{range.zip.sentinel@ {\memgloterm{range.zip.sentinel}}{\memglodesc{(\ref {range.zip.sentinel})}} {\memgloref{}}|memjustarg}{1221} -\glossaryentry{range.zip.transform@ {\memgloterm{range.zip.transform}}{\memglodesc{(\ref {range.zip.transform})}} {\memgloref{}}|memjustarg}{1222} -\glossaryentry{range.zip.transform.overview@ {\memgloterm{range.zip.transform.overview}}{\memglodesc{(\ref {range.zip.transform.overview})}} {\memgloref{}}|memjustarg}{1222} -\glossaryentry{range.zip.transform.view@ {\memgloterm{range.zip.transform.view}}{\memglodesc{(\ref {range.zip.transform.view})}} {\memgloref{}}|memjustarg}{1223} -\glossaryentry{range.zip.transform.iterator@ {\memgloterm{range.zip.transform.iterator}}{\memglodesc{(\ref {range.zip.transform.iterator})}} {\memgloref{}}|memjustarg}{1224} -\glossaryentry{range.zip.transform.sentinel@ {\memgloterm{range.zip.transform.sentinel}}{\memglodesc{(\ref {range.zip.transform.sentinel})}} {\memgloref{}}|memjustarg}{1226} -\glossaryentry{range.adjacent@ {\memgloterm{range.adjacent}}{\memglodesc{(\ref {range.adjacent})}} {\memgloref{}}|memjustarg}{1227} -\glossaryentry{range.adjacent.overview@ {\memgloterm{range.adjacent.overview}}{\memglodesc{(\ref {range.adjacent.overview})}} {\memgloref{}}|memjustarg}{1227} -\glossaryentry{range.adjacent.view@ {\memgloterm{range.adjacent.view}}{\memglodesc{(\ref {range.adjacent.view})}} {\memgloref{}}|memjustarg}{1228} -\glossaryentry{range.adjacent.iterator@ {\memgloterm{range.adjacent.iterator}}{\memglodesc{(\ref {range.adjacent.iterator})}} {\memgloref{}}|memjustarg}{1229} -\glossaryentry{range.adjacent.sentinel@ {\memgloterm{range.adjacent.sentinel}}{\memglodesc{(\ref {range.adjacent.sentinel})}} {\memgloref{}}|memjustarg}{1232} -\glossaryentry{range.adjacent.transform@ {\memgloterm{range.adjacent.transform}}{\memglodesc{(\ref {range.adjacent.transform})}} {\memgloref{}}|memjustarg}{1233} -\glossaryentry{range.adjacent.transform.overview@ {\memgloterm{range.adjacent.transform.overview}}{\memglodesc{(\ref {range.adjacent.transform.overview})}} {\memgloref{}}|memjustarg}{1233} -\glossaryentry{range.adjacent.transform.view@ {\memgloterm{range.adjacent.transform.view}}{\memglodesc{(\ref {range.adjacent.transform.view})}} {\memgloref{}}|memjustarg}{1233} -\glossaryentry{range.adjacent.transform.iterator@ {\memgloterm{range.adjacent.transform.iterator}}{\memglodesc{(\ref {range.adjacent.transform.iterator})}} {\memgloref{}}|memjustarg}{1234} -\glossaryentry{range.adjacent.transform.sentinel@ {\memgloterm{range.adjacent.transform.sentinel}}{\memglodesc{(\ref {range.adjacent.transform.sentinel})}} {\memgloref{}}|memjustarg}{1237} -\glossaryentry{range.chunk@ {\memgloterm{range.chunk}}{\memglodesc{(\ref {range.chunk})}} {\memgloref{}}|memjustarg}{1238} -\glossaryentry{range.chunk.overview@ {\memgloterm{range.chunk.overview}}{\memglodesc{(\ref {range.chunk.overview})}} {\memgloref{}}|memjustarg}{1238} -\glossaryentry{range.chunk.view.input@ {\memgloterm{range.chunk.view.input}}{\memglodesc{(\ref {range.chunk.view.input})}} {\memgloref{}}|memjustarg}{1238} -\glossaryentry{range.chunk.outer.iter@ {\memgloterm{range.chunk.outer.iter}}{\memglodesc{(\ref {range.chunk.outer.iter})}} {\memgloref{}}|memjustarg}{1239} -\glossaryentry{range.chunk.outer.value@ {\memgloterm{range.chunk.outer.value}}{\memglodesc{(\ref {range.chunk.outer.value})}} {\memgloref{}}|memjustarg}{1240} -\glossaryentry{range.chunk.inner.iter@ {\memgloterm{range.chunk.inner.iter}}{\memglodesc{(\ref {range.chunk.inner.iter})}} {\memgloref{}}|memjustarg}{1241} -\glossaryentry{range.chunk.view.fwd@ {\memgloterm{range.chunk.view.fwd}}{\memglodesc{(\ref {range.chunk.view.fwd})}} {\memgloref{}}|memjustarg}{1242} -\glossaryentry{range.chunk.fwd.iter@ {\memgloterm{range.chunk.fwd.iter}}{\memglodesc{(\ref {range.chunk.fwd.iter})}} {\memgloref{}}|memjustarg}{1243} -\glossaryentry{range.slide@ {\memgloterm{range.slide}}{\memglodesc{(\ref {range.slide})}} {\memgloref{}}|memjustarg}{1247} -\glossaryentry{range.slide.overview@ {\memgloterm{range.slide.overview}}{\memglodesc{(\ref {range.slide.overview})}} {\memgloref{}}|memjustarg}{1247} -\glossaryentry{range.slide.view@ {\memgloterm{range.slide.view}}{\memglodesc{(\ref {range.slide.view})}} {\memgloref{}}|memjustarg}{1247} -\glossaryentry{range.slide.iterator@ {\memgloterm{range.slide.iterator}}{\memglodesc{(\ref {range.slide.iterator})}} {\memgloref{}}|memjustarg}{1248} -\glossaryentry{range.slide.sentinel@ {\memgloterm{range.slide.sentinel}}{\memglodesc{(\ref {range.slide.sentinel})}} {\memgloref{}}|memjustarg}{1252} -\glossaryentry{range.chunk.by@ {\memgloterm{range.chunk.by}}{\memglodesc{(\ref {range.chunk.by})}} {\memgloref{}}|memjustarg}{1252} -\glossaryentry{range.chunk.by.overview@ {\memgloterm{range.chunk.by.overview}}{\memglodesc{(\ref {range.chunk.by.overview})}} {\memgloref{}}|memjustarg}{1252} -\glossaryentry{range.chunk.by.view@ {\memgloterm{range.chunk.by.view}}{\memglodesc{(\ref {range.chunk.by.view})}} {\memgloref{}}|memjustarg}{1253} -\glossaryentry{range.chunk.by.iter@ {\memgloterm{range.chunk.by.iter}}{\memglodesc{(\ref {range.chunk.by.iter})}} {\memgloref{}}|memjustarg}{1254} -\glossaryentry{range.stride@ {\memgloterm{range.stride}}{\memglodesc{(\ref {range.stride})}} {\memgloref{}}|memjustarg}{1255} -\glossaryentry{range.stride.overview@ {\memgloterm{range.stride.overview}}{\memglodesc{(\ref {range.stride.overview})}} {\memgloref{}}|memjustarg}{1255} -\glossaryentry{range.stride.view@ {\memgloterm{range.stride.view}}{\memglodesc{(\ref {range.stride.view})}} {\memgloref{}}|memjustarg}{1255} -\glossaryentry{range.stride.iterator@ {\memgloterm{range.stride.iterator}}{\memglodesc{(\ref {range.stride.iterator})}} {\memgloref{}}|memjustarg}{1256} -\glossaryentry{range.cartesian@ {\memgloterm{range.cartesian}}{\memglodesc{(\ref {range.cartesian})}} {\memgloref{}}|memjustarg}{1260} -\glossaryentry{range.cartesian.overview@ {\memgloterm{range.cartesian.overview}}{\memglodesc{(\ref {range.cartesian.overview})}} {\memgloref{}}|memjustarg}{1260} -\glossaryentry{range.cartesian.view@ {\memgloterm{range.cartesian.view}}{\memglodesc{(\ref {range.cartesian.view})}} {\memgloref{}}|memjustarg}{1261} -\glossaryentry{range.cartesian.iterator@ {\memgloterm{range.cartesian.iterator}}{\memglodesc{(\ref {range.cartesian.iterator})}} {\memgloref{}}|memjustarg}{1263} -\glossaryentry{coro.generator@ {\memgloterm{coro.generator}}{\memglodesc{(\ref {coro.generator})}} {\memgloref{}}|memjustarg}{1267} -\glossaryentry{coroutine.generator.overview@ {\memgloterm{coroutine.generator.overview}}{\memglodesc{(\ref {coroutine.generator.overview})}} {\memgloref{}}|memjustarg}{1267} -\glossaryentry{generator.syn@ {\memgloterm{generator.syn}}{\memglodesc{(\ref {generator.syn})}} {\memgloref{}}|memjustarg}{1268} -\glossaryentry{coro.generator.class@ {\memgloterm{coro.generator.class}}{\memglodesc{(\ref {coro.generator.class})}} {\memgloref{}}|memjustarg}{1268} -\glossaryentry{coro.generator.members@ {\memgloterm{coro.generator.members}}{\memglodesc{(\ref {coro.generator.members})}} {\memgloref{}}|memjustarg}{1269} -\glossaryentry{coro.generator.promise@ {\memgloterm{coro.generator.promise}}{\memglodesc{(\ref {coro.generator.promise})}} {\memgloref{}}|memjustarg}{1269} -\glossaryentry{coro.generator.iterator@ {\memgloterm{coro.generator.iterator}}{\memglodesc{(\ref {coro.generator.iterator})}} {\memgloref{}}|memjustarg}{1272} -\glossaryentry{algorithms@ {\memgloterm{algorithms}}{\memglodesc{(\ref {algorithms})}} {\memgloref{}}|memjustarg}{1273} -\glossaryentry{algorithms.general@ {\memgloterm{algorithms.general}}{\memglodesc{(\ref {algorithms.general})}} {\memgloref{}}|memjustarg}{1273} -\glossaryentry{algorithms.requirements@ {\memgloterm{algorithms.requirements}}{\memglodesc{(\ref {algorithms.requirements})}} {\memgloref{}}|memjustarg}{1273} -\glossaryentry{algorithms.parallel@ {\memgloterm{algorithms.parallel}}{\memglodesc{(\ref {algorithms.parallel})}} {\memgloref{}}|memjustarg}{1275} -\glossaryentry{algorithms.parallel.defns@ {\memgloterm{algorithms.parallel.defns}}{\memglodesc{(\ref {algorithms.parallel.defns})}} {\memgloref{}}|memjustarg}{1275} -\glossaryentry{algorithms.parallel.user@ {\memgloterm{algorithms.parallel.user}}{\memglodesc{(\ref {algorithms.parallel.user})}} {\memgloref{}}|memjustarg}{1276} -\glossaryentry{algorithms.parallel.exec@ {\memgloterm{algorithms.parallel.exec}}{\memglodesc{(\ref {algorithms.parallel.exec})}} {\memgloref{}}|memjustarg}{1276} -\glossaryentry{algorithms.parallel.exceptions@ {\memgloterm{algorithms.parallel.exceptions}}{\memglodesc{(\ref {algorithms.parallel.exceptions})}} {\memgloref{}}|memjustarg}{1278} -\glossaryentry{algorithms.parallel.overloads@ {\memgloterm{algorithms.parallel.overloads}}{\memglodesc{(\ref {algorithms.parallel.overloads})}} {\memgloref{}}|memjustarg}{1278} -\glossaryentry{algorithm.syn@ {\memgloterm{algorithm.syn}}{\memglodesc{(\ref {algorithm.syn})}} {\memgloref{}}|memjustarg}{1278} -\glossaryentry{algorithms.results@ {\memgloterm{algorithms.results}}{\memglodesc{(\ref {algorithms.results})}} {\memgloref{}}|memjustarg}{1316} -\glossaryentry{alg.nonmodifying@ {\memgloterm{alg.nonmodifying}}{\memglodesc{(\ref {alg.nonmodifying})}} {\memgloref{}}|memjustarg}{1319} -\glossaryentry{alg.all.of@ {\memgloterm{alg.all.of}}{\memglodesc{(\ref {alg.all.of})}} {\memgloref{}}|memjustarg}{1319} -\glossaryentry{alg.any.of@ {\memgloterm{alg.any.of}}{\memglodesc{(\ref {alg.any.of})}} {\memgloref{}}|memjustarg}{1320} -\glossaryentry{alg.none.of@ {\memgloterm{alg.none.of}}{\memglodesc{(\ref {alg.none.of})}} {\memgloref{}}|memjustarg}{1320} -\glossaryentry{alg.contains@ {\memgloterm{alg.contains}}{\memglodesc{(\ref {alg.contains})}} {\memgloref{}}|memjustarg}{1320} -\glossaryentry{alg.foreach@ {\memgloterm{alg.foreach}}{\memglodesc{(\ref {alg.foreach})}} {\memgloref{}}|memjustarg}{1321} -\glossaryentry{alg.find@ {\memgloterm{alg.find}}{\memglodesc{(\ref {alg.find})}} {\memgloref{}}|memjustarg}{1322} -\glossaryentry{alg.find.last@ {\memgloterm{alg.find.last}}{\memglodesc{(\ref {alg.find.last})}} {\memgloref{}}|memjustarg}{1323} -\glossaryentry{alg.find.end@ {\memgloterm{alg.find.end}}{\memglodesc{(\ref {alg.find.end})}} {\memgloref{}}|memjustarg}{1324} -\glossaryentry{alg.find.first.of@ {\memgloterm{alg.find.first.of}}{\memglodesc{(\ref {alg.find.first.of})}} {\memgloref{}}|memjustarg}{1324} -\glossaryentry{alg.adjacent.find@ {\memgloterm{alg.adjacent.find}}{\memglodesc{(\ref {alg.adjacent.find})}} {\memgloref{}}|memjustarg}{1325} -\glossaryentry{alg.count@ {\memgloterm{alg.count}}{\memglodesc{(\ref {alg.count})}} {\memgloref{}}|memjustarg}{1326} -\glossaryentry{mismatch@ {\memgloterm{mismatch}}{\memglodesc{(\ref {mismatch})}} {\memgloref{}}|memjustarg}{1327} -\glossaryentry{alg.equal@ {\memgloterm{alg.equal}}{\memglodesc{(\ref {alg.equal})}} {\memgloref{}}|memjustarg}{1328} -\glossaryentry{alg.is.permutation@ {\memgloterm{alg.is.permutation}}{\memglodesc{(\ref {alg.is.permutation})}} {\memgloref{}}|memjustarg}{1329} -\glossaryentry{alg.search@ {\memgloterm{alg.search}}{\memglodesc{(\ref {alg.search})}} {\memgloref{}}|memjustarg}{1330} -\glossaryentry{alg.starts.with@ {\memgloterm{alg.starts.with}}{\memglodesc{(\ref {alg.starts.with})}} {\memgloref{}}|memjustarg}{1332} -\glossaryentry{alg.ends.with@ {\memgloterm{alg.ends.with}}{\memglodesc{(\ref {alg.ends.with})}} {\memgloref{}}|memjustarg}{1332} -\glossaryentry{alg.fold@ {\memgloterm{alg.fold}}{\memglodesc{(\ref {alg.fold})}} {\memgloref{}}|memjustarg}{1333} -\glossaryentry{alg.modifying.operations@ {\memgloterm{alg.modifying.operations}}{\memglodesc{(\ref {alg.modifying.operations})}} {\memgloref{}}|memjustarg}{1334} -\glossaryentry{alg.copy@ {\memgloterm{alg.copy}}{\memglodesc{(\ref {alg.copy})}} {\memgloref{}}|memjustarg}{1334} -\glossaryentry{alg.move@ {\memgloterm{alg.move}}{\memglodesc{(\ref {alg.move})}} {\memgloref{}}|memjustarg}{1336} -\glossaryentry{alg.swap@ {\memgloterm{alg.swap}}{\memglodesc{(\ref {alg.swap})}} {\memgloref{}}|memjustarg}{1338} -\glossaryentry{alg.transform@ {\memgloterm{alg.transform}}{\memglodesc{(\ref {alg.transform})}} {\memgloref{}}|memjustarg}{1338} -\glossaryentry{alg.replace@ {\memgloterm{alg.replace}}{\memglodesc{(\ref {alg.replace})}} {\memgloref{}}|memjustarg}{1340} -\glossaryentry{alg.fill@ {\memgloterm{alg.fill}}{\memglodesc{(\ref {alg.fill})}} {\memgloref{}}|memjustarg}{1342} -\glossaryentry{alg.generate@ {\memgloterm{alg.generate}}{\memglodesc{(\ref {alg.generate})}} {\memgloref{}}|memjustarg}{1342} -\glossaryentry{alg.remove@ {\memgloterm{alg.remove}}{\memglodesc{(\ref {alg.remove})}} {\memgloref{}}|memjustarg}{1343} -\glossaryentry{alg.unique@ {\memgloterm{alg.unique}}{\memglodesc{(\ref {alg.unique})}} {\memgloref{}}|memjustarg}{1345} -\glossaryentry{alg.reverse@ {\memgloterm{alg.reverse}}{\memglodesc{(\ref {alg.reverse})}} {\memgloref{}}|memjustarg}{1347} -\glossaryentry{alg.rotate@ {\memgloterm{alg.rotate}}{\memglodesc{(\ref {alg.rotate})}} {\memgloref{}}|memjustarg}{1347} -\glossaryentry{alg.random.sample@ {\memgloterm{alg.random.sample}}{\memglodesc{(\ref {alg.random.sample})}} {\memgloref{}}|memjustarg}{1349} -\glossaryentry{alg.random.shuffle@ {\memgloterm{alg.random.shuffle}}{\memglodesc{(\ref {alg.random.shuffle})}} {\memgloref{}}|memjustarg}{1349} -\glossaryentry{alg.shift@ {\memgloterm{alg.shift}}{\memglodesc{(\ref {alg.shift})}} {\memgloref{}}|memjustarg}{1350} -\glossaryentry{alg.sorting@ {\memgloterm{alg.sorting}}{\memglodesc{(\ref {alg.sorting})}} {\memgloref{}}|memjustarg}{1351} -\glossaryentry{alg.sorting.general@ {\memgloterm{alg.sorting.general}}{\memglodesc{(\ref {alg.sorting.general})}} {\memgloref{}}|memjustarg}{1351} -\glossaryentry{alg.sort@ {\memgloterm{alg.sort}}{\memglodesc{(\ref {alg.sort})}} {\memgloref{}}|memjustarg}{1351} -\glossaryentry{sort@ {\memgloterm{sort}}{\memglodesc{(\ref {sort})}} {\memgloref{}}|memjustarg}{1351} -\glossaryentry{stable.sort@ {\memgloterm{stable.sort}}{\memglodesc{(\ref {stable.sort})}} {\memgloref{}}|memjustarg}{1352} -\glossaryentry{partial.sort@ {\memgloterm{partial.sort}}{\memglodesc{(\ref {partial.sort})}} {\memgloref{}}|memjustarg}{1353} -\glossaryentry{partial.sort.copy@ {\memgloterm{partial.sort.copy}}{\memglodesc{(\ref {partial.sort.copy})}} {\memgloref{}}|memjustarg}{1353} -\glossaryentry{is.sorted@ {\memgloterm{is.sorted}}{\memglodesc{(\ref {is.sorted})}} {\memgloref{}}|memjustarg}{1355} -\glossaryentry{alg.nth.element@ {\memgloterm{alg.nth.element}}{\memglodesc{(\ref {alg.nth.element})}} {\memgloref{}}|memjustarg}{1356} -\glossaryentry{alg.binary.search@ {\memgloterm{alg.binary.search}}{\memglodesc{(\ref {alg.binary.search})}} {\memgloref{}}|memjustarg}{1356} -\glossaryentry{alg.binary.search.general@ {\memgloterm{alg.binary.search.general}}{\memglodesc{(\ref {alg.binary.search.general})}} {\memgloref{}}|memjustarg}{1356} -\glossaryentry{lower.bound@ {\memgloterm{lower.bound}}{\memglodesc{(\ref {lower.bound})}} {\memgloref{}}|memjustarg}{1356} -\glossaryentry{upper.bound@ {\memgloterm{upper.bound}}{\memglodesc{(\ref {upper.bound})}} {\memgloref{}}|memjustarg}{1357} -\glossaryentry{equal.range@ {\memgloterm{equal.range}}{\memglodesc{(\ref {equal.range})}} {\memgloref{}}|memjustarg}{1357} -\glossaryentry{binary.search@ {\memgloterm{binary.search}}{\memglodesc{(\ref {binary.search})}} {\memgloref{}}|memjustarg}{1358} -\glossaryentry{alg.partitions@ {\memgloterm{alg.partitions}}{\memglodesc{(\ref {alg.partitions})}} {\memgloref{}}|memjustarg}{1359} -\glossaryentry{alg.merge@ {\memgloterm{alg.merge}}{\memglodesc{(\ref {alg.merge})}} {\memgloref{}}|memjustarg}{1361} -\glossaryentry{alg.set.operations@ {\memgloterm{alg.set.operations}}{\memglodesc{(\ref {alg.set.operations})}} {\memgloref{}}|memjustarg}{1363} -\glossaryentry{alg.set.operations.general@ {\memgloterm{alg.set.operations.general}}{\memglodesc{(\ref {alg.set.operations.general})}} {\memgloref{}}|memjustarg}{1363} -\glossaryentry{includes@ {\memgloterm{includes}}{\memglodesc{(\ref {includes})}} {\memgloref{}}|memjustarg}{1363} -\glossaryentry{set.union@ {\memgloterm{set.union}}{\memglodesc{(\ref {set.union})}} {\memgloref{}}|memjustarg}{1364} -\glossaryentry{set.intersection@ {\memgloterm{set.intersection}}{\memglodesc{(\ref {set.intersection})}} {\memgloref{}}|memjustarg}{1365} -\glossaryentry{set.difference@ {\memgloterm{set.difference}}{\memglodesc{(\ref {set.difference})}} {\memgloref{}}|memjustarg}{1366} -\glossaryentry{set.symmetric.difference@ {\memgloterm{set.symmetric.difference}}{\memglodesc{(\ref {set.symmetric.difference})}} {\memgloref{}}|memjustarg}{1367} -\glossaryentry{alg.heap.operations@ {\memgloterm{alg.heap.operations}}{\memglodesc{(\ref {alg.heap.operations})}} {\memgloref{}}|memjustarg}{1368} -\glossaryentry{alg.heap.operations.general@ {\memgloterm{alg.heap.operations.general}}{\memglodesc{(\ref {alg.heap.operations.general})}} {\memgloref{}}|memjustarg}{1368} -\glossaryentry{push.heap@ {\memgloterm{push.heap}}{\memglodesc{(\ref {push.heap})}} {\memgloref{}}|memjustarg}{1368} -\glossaryentry{pop.heap@ {\memgloterm{pop.heap}}{\memglodesc{(\ref {pop.heap})}} {\memgloref{}}|memjustarg}{1368} -\glossaryentry{make.heap@ {\memgloterm{make.heap}}{\memglodesc{(\ref {make.heap})}} {\memgloref{}}|memjustarg}{1369} -\glossaryentry{sort.heap@ {\memgloterm{sort.heap}}{\memglodesc{(\ref {sort.heap})}} {\memgloref{}}|memjustarg}{1369} -\glossaryentry{is.heap@ {\memgloterm{is.heap}}{\memglodesc{(\ref {is.heap})}} {\memgloref{}}|memjustarg}{1370} -\glossaryentry{alg.min.max@ {\memgloterm{alg.min.max}}{\memglodesc{(\ref {alg.min.max})}} {\memgloref{}}|memjustarg}{1371} -\glossaryentry{alg.clamp@ {\memgloterm{alg.clamp}}{\memglodesc{(\ref {alg.clamp})}} {\memgloref{}}|memjustarg}{1374} -\glossaryentry{alg.lex.comparison@ {\memgloterm{alg.lex.comparison}}{\memglodesc{(\ref {alg.lex.comparison})}} {\memgloref{}}|memjustarg}{1375} -\glossaryentry{alg.three.way@ {\memgloterm{alg.three.way}}{\memglodesc{(\ref {alg.three.way})}} {\memgloref{}}|memjustarg}{1376} -\glossaryentry{alg.permutation.generators@ {\memgloterm{alg.permutation.generators}}{\memglodesc{(\ref {alg.permutation.generators})}} {\memgloref{}}|memjustarg}{1376} -\glossaryentry{numeric.ops.overview@ {\memgloterm{numeric.ops.overview}}{\memglodesc{(\ref {numeric.ops.overview})}} {\memgloref{}}|memjustarg}{1377} -\glossaryentry{numeric.ops@ {\memgloterm{numeric.ops}}{\memglodesc{(\ref {numeric.ops})}} {\memgloref{}}|memjustarg}{1381} -\glossaryentry{numeric.ops.general@ {\memgloterm{numeric.ops.general}}{\memglodesc{(\ref {numeric.ops.general})}} {\memgloref{}}|memjustarg}{1381} -\glossaryentry{numerics.defns@ {\memgloterm{numerics.defns}}{\memglodesc{(\ref {numerics.defns})}} {\memgloref{}}|memjustarg}{1381} -\glossaryentry{accumulate@ {\memgloterm{accumulate}}{\memglodesc{(\ref {accumulate})}} {\memgloref{}}|memjustarg}{1381} -\glossaryentry{reduce@ {\memgloterm{reduce}}{\memglodesc{(\ref {reduce})}} {\memgloref{}}|memjustarg}{1381} -\glossaryentry{inner.product@ {\memgloterm{inner.product}}{\memglodesc{(\ref {inner.product})}} {\memgloref{}}|memjustarg}{1382} -\glossaryentry{transform.reduce@ {\memgloterm{transform.reduce}}{\memglodesc{(\ref {transform.reduce})}} {\memgloref{}}|memjustarg}{1382} -\glossaryentry{partial.sum@ {\memgloterm{partial.sum}}{\memglodesc{(\ref {partial.sum})}} {\memgloref{}}|memjustarg}{1384} -\glossaryentry{exclusive.scan@ {\memgloterm{exclusive.scan}}{\memglodesc{(\ref {exclusive.scan})}} {\memgloref{}}|memjustarg}{1384} -\glossaryentry{inclusive.scan@ {\memgloterm{inclusive.scan}}{\memglodesc{(\ref {inclusive.scan})}} {\memgloref{}}|memjustarg}{1385} -\glossaryentry{transform.exclusive.scan@ {\memgloterm{transform.exclusive.scan}}{\memglodesc{(\ref {transform.exclusive.scan})}} {\memgloref{}}|memjustarg}{1386} -\glossaryentry{transform.inclusive.scan@ {\memgloterm{transform.inclusive.scan}}{\memglodesc{(\ref {transform.inclusive.scan})}} {\memgloref{}}|memjustarg}{1387} -\glossaryentry{adjacent.difference@ {\memgloterm{adjacent.difference}}{\memglodesc{(\ref {adjacent.difference})}} {\memgloref{}}|memjustarg}{1388} -\glossaryentry{numeric.iota@ {\memgloterm{numeric.iota}}{\memglodesc{(\ref {numeric.iota})}} {\memgloref{}}|memjustarg}{1389} -\glossaryentry{numeric.ops.gcd@ {\memgloterm{numeric.ops.gcd}}{\memglodesc{(\ref {numeric.ops.gcd})}} {\memgloref{}}|memjustarg}{1389} -\glossaryentry{numeric.ops.lcm@ {\memgloterm{numeric.ops.lcm}}{\memglodesc{(\ref {numeric.ops.lcm})}} {\memgloref{}}|memjustarg}{1390} -\glossaryentry{numeric.ops.midpoint@ {\memgloterm{numeric.ops.midpoint}}{\memglodesc{(\ref {numeric.ops.midpoint})}} {\memgloref{}}|memjustarg}{1390} -\glossaryentry{specialized.algorithms@ {\memgloterm{specialized.algorithms}}{\memglodesc{(\ref {specialized.algorithms})}} {\memgloref{}}|memjustarg}{1390} -\glossaryentry{specialized.algorithms.general@ {\memgloterm{specialized.algorithms.general}}{\memglodesc{(\ref {specialized.algorithms.general})}} {\memgloref{}}|memjustarg}{1390} -\glossaryentry{special.mem.concepts@ {\memgloterm{special.mem.concepts}}{\memglodesc{(\ref {special.mem.concepts})}} {\memgloref{}}|memjustarg}{1390} -\glossaryentry{uninitialized.construct.default@ {\memgloterm{uninitialized.construct.default}}{\memglodesc{(\ref {uninitialized.construct.default})}} {\memgloref{}}|memjustarg}{1391} -\glossaryentry{uninitialized.construct.value@ {\memgloterm{uninitialized.construct.value}}{\memglodesc{(\ref {uninitialized.construct.value})}} {\memgloref{}}|memjustarg}{1392} -\glossaryentry{uninitialized.copy@ {\memgloterm{uninitialized.copy}}{\memglodesc{(\ref {uninitialized.copy})}} {\memgloref{}}|memjustarg}{1392} -\glossaryentry{uninitialized.move@ {\memgloterm{uninitialized.move}}{\memglodesc{(\ref {uninitialized.move})}} {\memgloref{}}|memjustarg}{1393} -\glossaryentry{uninitialized.fill@ {\memgloterm{uninitialized.fill}}{\memglodesc{(\ref {uninitialized.fill})}} {\memgloref{}}|memjustarg}{1394} -\glossaryentry{specialized.construct@ {\memgloterm{specialized.construct}}{\memglodesc{(\ref {specialized.construct})}} {\memgloref{}}|memjustarg}{1395} -\glossaryentry{specialized.destroy@ {\memgloterm{specialized.destroy}}{\memglodesc{(\ref {specialized.destroy})}} {\memgloref{}}|memjustarg}{1395} -\glossaryentry{alg.c.library@ {\memgloterm{alg.c.library}}{\memglodesc{(\ref {alg.c.library})}} {\memgloref{}}|memjustarg}{1396} -\glossaryentry{numerics@ {\memgloterm{numerics}}{\memglodesc{(\ref {numerics})}} {\memgloref{}}|memjustarg}{1397} -\glossaryentry{numerics.general@ {\memgloterm{numerics.general}}{\memglodesc{(\ref {numerics.general})}} {\memgloref{}}|memjustarg}{1397} -\glossaryentry{numeric.requirements@ {\memgloterm{numeric.requirements}}{\memglodesc{(\ref {numeric.requirements})}} {\memgloref{}}|memjustarg}{1397} -\glossaryentry{cfenv@ {\memgloterm{cfenv}}{\memglodesc{(\ref {cfenv})}} {\memgloref{}}|memjustarg}{1397} -\glossaryentry{cfenv.syn@ {\memgloterm{cfenv.syn}}{\memglodesc{(\ref {cfenv.syn})}} {\memgloref{}}|memjustarg}{1397} -\glossaryentry{cfenv.thread@ {\memgloterm{cfenv.thread}}{\memglodesc{(\ref {cfenv.thread})}} {\memgloref{}}|memjustarg}{1398} -\glossaryentry{complex.numbers@ {\memgloterm{complex.numbers}}{\memglodesc{(\ref {complex.numbers})}} {\memgloref{}}|memjustarg}{1398} -\glossaryentry{complex.numbers.general@ {\memgloterm{complex.numbers.general}}{\memglodesc{(\ref {complex.numbers.general})}} {\memgloref{}}|memjustarg}{1398} -\glossaryentry{complex.syn@ {\memgloterm{complex.syn}}{\memglodesc{(\ref {complex.syn})}} {\memgloref{}}|memjustarg}{1398} -\glossaryentry{complex@ {\memgloterm{complex}}{\memglodesc{(\ref {complex})}} {\memgloref{}}|memjustarg}{1400} -\glossaryentry{complex.members@ {\memgloterm{complex.members}}{\memglodesc{(\ref {complex.members})}} {\memgloref{}}|memjustarg}{1400} -\glossaryentry{complex.member.ops@ {\memgloterm{complex.member.ops}}{\memglodesc{(\ref {complex.member.ops})}} {\memgloref{}}|memjustarg}{1401} -\glossaryentry{complex.ops@ {\memgloterm{complex.ops}}{\memglodesc{(\ref {complex.ops})}} {\memgloref{}}|memjustarg}{1401} -\glossaryentry{complex.value.ops@ {\memgloterm{complex.value.ops}}{\memglodesc{(\ref {complex.value.ops})}} {\memgloref{}}|memjustarg}{1402} -\glossaryentry{complex.transcendentals@ {\memgloterm{complex.transcendentals}}{\memglodesc{(\ref {complex.transcendentals})}} {\memgloref{}}|memjustarg}{1403} -\glossaryentry{cmplx.over@ {\memgloterm{cmplx.over}}{\memglodesc{(\ref {cmplx.over})}} {\memgloref{}}|memjustarg}{1404} -\glossaryentry{complex.literals@ {\memgloterm{complex.literals}}{\memglodesc{(\ref {complex.literals})}} {\memgloref{}}|memjustarg}{1404} -\glossaryentry{rand@ {\memgloterm{rand}}{\memglodesc{(\ref {rand})}} {\memgloref{}}|memjustarg}{1405} -\glossaryentry{rand.general@ {\memgloterm{rand.general}}{\memglodesc{(\ref {rand.general})}} {\memgloref{}}|memjustarg}{1405} -\glossaryentry{rand.synopsis@ {\memgloterm{rand.synopsis}}{\memglodesc{(\ref {rand.synopsis})}} {\memgloref{}}|memjustarg}{1405} -\glossaryentry{rand.req@ {\memgloterm{rand.req}}{\memglodesc{(\ref {rand.req})}} {\memgloref{}}|memjustarg}{1407} -\glossaryentry{rand.req.genl@ {\memgloterm{rand.req.genl}}{\memglodesc{(\ref {rand.req.genl})}} {\memgloref{}}|memjustarg}{1407} -\glossaryentry{rand.req.seedseq@ {\memgloterm{rand.req.seedseq}}{\memglodesc{(\ref {rand.req.seedseq})}} {\memgloref{}}|memjustarg}{1408} -\glossaryentry{rand.req.urng@ {\memgloterm{rand.req.urng}}{\memglodesc{(\ref {rand.req.urng})}} {\memgloref{}}|memjustarg}{1409} -\glossaryentry{rand.req.eng@ {\memgloterm{rand.req.eng}}{\memglodesc{(\ref {rand.req.eng})}} {\memgloref{}}|memjustarg}{1409} -\glossaryentry{rand.req.adapt@ {\memgloterm{rand.req.adapt}}{\memglodesc{(\ref {rand.req.adapt})}} {\memgloref{}}|memjustarg}{1411} -\glossaryentry{rand.req.dist@ {\memgloterm{rand.req.dist}}{\memglodesc{(\ref {rand.req.dist})}} {\memgloref{}}|memjustarg}{1412} -\glossaryentry{rand.eng@ {\memgloterm{rand.eng}}{\memglodesc{(\ref {rand.eng})}} {\memgloref{}}|memjustarg}{1414} -\glossaryentry{rand.eng.general@ {\memgloterm{rand.eng.general}}{\memglodesc{(\ref {rand.eng.general})}} {\memgloref{}}|memjustarg}{1414} -\glossaryentry{rand.eng.lcong@ {\memgloterm{rand.eng.lcong}}{\memglodesc{(\ref {rand.eng.lcong})}} {\memgloref{}}|memjustarg}{1415} -\glossaryentry{rand.eng.mers@ {\memgloterm{rand.eng.mers}}{\memglodesc{(\ref {rand.eng.mers})}} {\memgloref{}}|memjustarg}{1416} -\glossaryentry{rand.eng.sub@ {\memgloterm{rand.eng.sub}}{\memglodesc{(\ref {rand.eng.sub})}} {\memgloref{}}|memjustarg}{1417} -\glossaryentry{rand.adapt@ {\memgloterm{rand.adapt}}{\memglodesc{(\ref {rand.adapt})}} {\memgloref{}}|memjustarg}{1419} -\glossaryentry{rand.adapt.general@ {\memgloterm{rand.adapt.general}}{\memglodesc{(\ref {rand.adapt.general})}} {\memgloref{}}|memjustarg}{1419} -\glossaryentry{rand.adapt.disc@ {\memgloterm{rand.adapt.disc}}{\memglodesc{(\ref {rand.adapt.disc})}} {\memgloref{}}|memjustarg}{1419} -\glossaryentry{rand.adapt.ibits@ {\memgloterm{rand.adapt.ibits}}{\memglodesc{(\ref {rand.adapt.ibits})}} {\memgloref{}}|memjustarg}{1420} -\glossaryentry{rand.adapt.shuf@ {\memgloterm{rand.adapt.shuf}}{\memglodesc{(\ref {rand.adapt.shuf})}} {\memgloref{}}|memjustarg}{1421} -\glossaryentry{rand.predef@ {\memgloterm{rand.predef}}{\memglodesc{(\ref {rand.predef})}} {\memgloref{}}|memjustarg}{1422} -\glossaryentry{rand.device@ {\memgloterm{rand.device}}{\memglodesc{(\ref {rand.device})}} {\memgloref{}}|memjustarg}{1423} -\glossaryentry{rand.util@ {\memgloterm{rand.util}}{\memglodesc{(\ref {rand.util})}} {\memgloref{}}|memjustarg}{1424} -\glossaryentry{rand.util.seedseq@ {\memgloterm{rand.util.seedseq}}{\memglodesc{(\ref {rand.util.seedseq})}} {\memgloref{}}|memjustarg}{1424} -\glossaryentry{rand.util.canonical@ {\memgloterm{rand.util.canonical}}{\memglodesc{(\ref {rand.util.canonical})}} {\memgloref{}}|memjustarg}{1426} -\glossaryentry{rand.dist@ {\memgloterm{rand.dist}}{\memglodesc{(\ref {rand.dist})}} {\memgloref{}}|memjustarg}{1426} -\glossaryentry{rand.dist.general@ {\memgloterm{rand.dist.general}}{\memglodesc{(\ref {rand.dist.general})}} {\memgloref{}}|memjustarg}{1426} -\glossaryentry{rand.dist.uni@ {\memgloterm{rand.dist.uni}}{\memglodesc{(\ref {rand.dist.uni})}} {\memgloref{}}|memjustarg}{1426} -\glossaryentry{rand.dist.uni.int@ {\memgloterm{rand.dist.uni.int}}{\memglodesc{(\ref {rand.dist.uni.int})}} {\memgloref{}}|memjustarg}{1426} -\glossaryentry{rand.dist.uni.real@ {\memgloterm{rand.dist.uni.real}}{\memglodesc{(\ref {rand.dist.uni.real})}} {\memgloref{}}|memjustarg}{1427} -\glossaryentry{rand.dist.bern@ {\memgloterm{rand.dist.bern}}{\memglodesc{(\ref {rand.dist.bern})}} {\memgloref{}}|memjustarg}{1428} -\glossaryentry{rand.dist.bern.bernoulli@ {\memgloterm{rand.dist.bern.bernoulli}}{\memglodesc{(\ref {rand.dist.bern.bernoulli})}} {\memgloref{}}|memjustarg}{1428} -\glossaryentry{rand.dist.bern.bin@ {\memgloterm{rand.dist.bern.bin}}{\memglodesc{(\ref {rand.dist.bern.bin})}} {\memgloref{}}|memjustarg}{1429} -\glossaryentry{rand.dist.bern.geo@ {\memgloterm{rand.dist.bern.geo}}{\memglodesc{(\ref {rand.dist.bern.geo})}} {\memgloref{}}|memjustarg}{1430} -\glossaryentry{rand.dist.bern.negbin@ {\memgloterm{rand.dist.bern.negbin}}{\memglodesc{(\ref {rand.dist.bern.negbin})}} {\memgloref{}}|memjustarg}{1431} -\glossaryentry{rand.dist.pois@ {\memgloterm{rand.dist.pois}}{\memglodesc{(\ref {rand.dist.pois})}} {\memgloref{}}|memjustarg}{1432} -\glossaryentry{rand.dist.pois.poisson@ {\memgloterm{rand.dist.pois.poisson}}{\memglodesc{(\ref {rand.dist.pois.poisson})}} {\memgloref{}}|memjustarg}{1432} -\glossaryentry{rand.dist.pois.exp@ {\memgloterm{rand.dist.pois.exp}}{\memglodesc{(\ref {rand.dist.pois.exp})}} {\memgloref{}}|memjustarg}{1433} -\glossaryentry{rand.dist.pois.gamma@ {\memgloterm{rand.dist.pois.gamma}}{\memglodesc{(\ref {rand.dist.pois.gamma})}} {\memgloref{}}|memjustarg}{1434} -\glossaryentry{rand.dist.pois.weibull@ {\memgloterm{rand.dist.pois.weibull}}{\memglodesc{(\ref {rand.dist.pois.weibull})}} {\memgloref{}}|memjustarg}{1435} -\glossaryentry{rand.dist.pois.extreme@ {\memgloterm{rand.dist.pois.extreme}}{\memglodesc{(\ref {rand.dist.pois.extreme})}} {\memgloref{}}|memjustarg}{1436} -\glossaryentry{rand.dist.norm@ {\memgloterm{rand.dist.norm}}{\memglodesc{(\ref {rand.dist.norm})}} {\memgloref{}}|memjustarg}{1437} -\glossaryentry{rand.dist.norm.normal@ {\memgloterm{rand.dist.norm.normal}}{\memglodesc{(\ref {rand.dist.norm.normal})}} {\memgloref{}}|memjustarg}{1437} -\glossaryentry{rand.dist.norm.lognormal@ {\memgloterm{rand.dist.norm.lognormal}}{\memglodesc{(\ref {rand.dist.norm.lognormal})}} {\memgloref{}}|memjustarg}{1438} -\glossaryentry{rand.dist.norm.chisq@ {\memgloterm{rand.dist.norm.chisq}}{\memglodesc{(\ref {rand.dist.norm.chisq})}} {\memgloref{}}|memjustarg}{1439} -\glossaryentry{rand.dist.norm.cauchy@ {\memgloterm{rand.dist.norm.cauchy}}{\memglodesc{(\ref {rand.dist.norm.cauchy})}} {\memgloref{}}|memjustarg}{1439} -\glossaryentry{rand.dist.norm.f@ {\memgloterm{rand.dist.norm.f}}{\memglodesc{(\ref {rand.dist.norm.f})}} {\memgloref{}}|memjustarg}{1440} -\glossaryentry{rand.dist.norm.t@ {\memgloterm{rand.dist.norm.t}}{\memglodesc{(\ref {rand.dist.norm.t})}} {\memgloref{}}|memjustarg}{1441} -\glossaryentry{rand.dist.samp@ {\memgloterm{rand.dist.samp}}{\memglodesc{(\ref {rand.dist.samp})}} {\memgloref{}}|memjustarg}{1442} -\glossaryentry{rand.dist.samp.discrete@ {\memgloterm{rand.dist.samp.discrete}}{\memglodesc{(\ref {rand.dist.samp.discrete})}} {\memgloref{}}|memjustarg}{1442} -\glossaryentry{rand.dist.samp.pconst@ {\memgloterm{rand.dist.samp.pconst}}{\memglodesc{(\ref {rand.dist.samp.pconst})}} {\memgloref{}}|memjustarg}{1444} -\glossaryentry{rand.dist.samp.plinear@ {\memgloterm{rand.dist.samp.plinear}}{\memglodesc{(\ref {rand.dist.samp.plinear})}} {\memgloref{}}|memjustarg}{1445} -\glossaryentry{c.math.rand@ {\memgloterm{c.math.rand}}{\memglodesc{(\ref {c.math.rand})}} {\memgloref{}}|memjustarg}{1447} -\glossaryentry{numarray@ {\memgloterm{numarray}}{\memglodesc{(\ref {numarray})}} {\memgloref{}}|memjustarg}{1447} -\glossaryentry{valarray.syn@ {\memgloterm{valarray.syn}}{\memglodesc{(\ref {valarray.syn})}} {\memgloref{}}|memjustarg}{1447} -\glossaryentry{template.valarray@ {\memgloterm{template.valarray}}{\memglodesc{(\ref {template.valarray})}} {\memgloref{}}|memjustarg}{1450} -\glossaryentry{template.valarray.overview@ {\memgloterm{template.valarray.overview}}{\memglodesc{(\ref {template.valarray.overview})}} {\memgloref{}}|memjustarg}{1450} -\glossaryentry{valarray.cons@ {\memgloterm{valarray.cons}}{\memglodesc{(\ref {valarray.cons})}} {\memgloref{}}|memjustarg}{1452} -\glossaryentry{valarray.assign@ {\memgloterm{valarray.assign}}{\memglodesc{(\ref {valarray.assign})}} {\memgloref{}}|memjustarg}{1453} -\glossaryentry{valarray.access@ {\memgloterm{valarray.access}}{\memglodesc{(\ref {valarray.access})}} {\memgloref{}}|memjustarg}{1453} -\glossaryentry{valarray.sub@ {\memgloterm{valarray.sub}}{\memglodesc{(\ref {valarray.sub})}} {\memgloref{}}|memjustarg}{1453} -\glossaryentry{valarray.unary@ {\memgloterm{valarray.unary}}{\memglodesc{(\ref {valarray.unary})}} {\memgloref{}}|memjustarg}{1455} -\glossaryentry{valarray.cassign@ {\memgloterm{valarray.cassign}}{\memglodesc{(\ref {valarray.cassign})}} {\memgloref{}}|memjustarg}{1455} -\glossaryentry{valarray.members@ {\memgloterm{valarray.members}}{\memglodesc{(\ref {valarray.members})}} {\memgloref{}}|memjustarg}{1456} -\glossaryentry{valarray.nonmembers@ {\memgloterm{valarray.nonmembers}}{\memglodesc{(\ref {valarray.nonmembers})}} {\memgloref{}}|memjustarg}{1457} -\glossaryentry{valarray.binary@ {\memgloterm{valarray.binary}}{\memglodesc{(\ref {valarray.binary})}} {\memgloref{}}|memjustarg}{1457} -\glossaryentry{valarray.comparison@ {\memgloterm{valarray.comparison}}{\memglodesc{(\ref {valarray.comparison})}} {\memgloref{}}|memjustarg}{1458} -\glossaryentry{valarray.transcend@ {\memgloterm{valarray.transcend}}{\memglodesc{(\ref {valarray.transcend})}} {\memgloref{}}|memjustarg}{1459} -\glossaryentry{valarray.special@ {\memgloterm{valarray.special}}{\memglodesc{(\ref {valarray.special})}} {\memgloref{}}|memjustarg}{1459} -\glossaryentry{class.slice@ {\memgloterm{class.slice}}{\memglodesc{(\ref {class.slice})}} {\memgloref{}}|memjustarg}{1459} -\glossaryentry{class.slice.overview@ {\memgloterm{class.slice.overview}}{\memglodesc{(\ref {class.slice.overview})}} {\memgloref{}}|memjustarg}{1459} -\glossaryentry{cons.slice@ {\memgloterm{cons.slice}}{\memglodesc{(\ref {cons.slice})}} {\memgloref{}}|memjustarg}{1460} -\glossaryentry{slice.access@ {\memgloterm{slice.access}}{\memglodesc{(\ref {slice.access})}} {\memgloref{}}|memjustarg}{1460} -\glossaryentry{slice.ops@ {\memgloterm{slice.ops}}{\memglodesc{(\ref {slice.ops})}} {\memgloref{}}|memjustarg}{1460} -\glossaryentry{template.slice.array@ {\memgloterm{template.slice.array}}{\memglodesc{(\ref {template.slice.array})}} {\memgloref{}}|memjustarg}{1460} -\glossaryentry{template.slice.array.overview@ {\memgloterm{template.slice.array.overview}}{\memglodesc{(\ref {template.slice.array.overview})}} {\memgloref{}}|memjustarg}{1460} -\glossaryentry{slice.arr.assign@ {\memgloterm{slice.arr.assign}}{\memglodesc{(\ref {slice.arr.assign})}} {\memgloref{}}|memjustarg}{1461} -\glossaryentry{slice.arr.comp.assign@ {\memgloterm{slice.arr.comp.assign}}{\memglodesc{(\ref {slice.arr.comp.assign})}} {\memgloref{}}|memjustarg}{1461} -\glossaryentry{slice.arr.fill@ {\memgloterm{slice.arr.fill}}{\memglodesc{(\ref {slice.arr.fill})}} {\memgloref{}}|memjustarg}{1461} -\glossaryentry{class.gslice@ {\memgloterm{class.gslice}}{\memglodesc{(\ref {class.gslice})}} {\memgloref{}}|memjustarg}{1461} -\glossaryentry{class.gslice.overview@ {\memgloterm{class.gslice.overview}}{\memglodesc{(\ref {class.gslice.overview})}} {\memgloref{}}|memjustarg}{1461} -\glossaryentry{gslice.cons@ {\memgloterm{gslice.cons}}{\memglodesc{(\ref {gslice.cons})}} {\memgloref{}}|memjustarg}{1462} -\glossaryentry{gslice.access@ {\memgloterm{gslice.access}}{\memglodesc{(\ref {gslice.access})}} {\memgloref{}}|memjustarg}{1462} -\glossaryentry{template.gslice.array@ {\memgloterm{template.gslice.array}}{\memglodesc{(\ref {template.gslice.array})}} {\memgloref{}}|memjustarg}{1463} -\glossaryentry{template.gslice.array.overview@ {\memgloterm{template.gslice.array.overview}}{\memglodesc{(\ref {template.gslice.array.overview})}} {\memgloref{}}|memjustarg}{1463} -\glossaryentry{gslice.array.assign@ {\memgloterm{gslice.array.assign}}{\memglodesc{(\ref {gslice.array.assign})}} {\memgloref{}}|memjustarg}{1463} -\glossaryentry{gslice.array.comp.assign@ {\memgloterm{gslice.array.comp.assign}}{\memglodesc{(\ref {gslice.array.comp.assign})}} {\memgloref{}}|memjustarg}{1463} -\glossaryentry{gslice.array.fill@ {\memgloterm{gslice.array.fill}}{\memglodesc{(\ref {gslice.array.fill})}} {\memgloref{}}|memjustarg}{1463} -\glossaryentry{template.mask.array@ {\memgloterm{template.mask.array}}{\memglodesc{(\ref {template.mask.array})}} {\memgloref{}}|memjustarg}{1464} -\glossaryentry{template.mask.array.overview@ {\memgloterm{template.mask.array.overview}}{\memglodesc{(\ref {template.mask.array.overview})}} {\memgloref{}}|memjustarg}{1464} -\glossaryentry{mask.array.assign@ {\memgloterm{mask.array.assign}}{\memglodesc{(\ref {mask.array.assign})}} {\memgloref{}}|memjustarg}{1464} -\glossaryentry{mask.array.comp.assign@ {\memgloterm{mask.array.comp.assign}}{\memglodesc{(\ref {mask.array.comp.assign})}} {\memgloref{}}|memjustarg}{1464} -\glossaryentry{mask.array.fill@ {\memgloterm{mask.array.fill}}{\memglodesc{(\ref {mask.array.fill})}} {\memgloref{}}|memjustarg}{1464} -\glossaryentry{template.indirect.array@ {\memgloterm{template.indirect.array}}{\memglodesc{(\ref {template.indirect.array})}} {\memgloref{}}|memjustarg}{1465} -\glossaryentry{template.indirect.array.overview@ {\memgloterm{template.indirect.array.overview}}{\memglodesc{(\ref {template.indirect.array.overview})}} {\memgloref{}}|memjustarg}{1465} -\glossaryentry{indirect.array.assign@ {\memgloterm{indirect.array.assign}}{\memglodesc{(\ref {indirect.array.assign})}} {\memgloref{}}|memjustarg}{1465} -\glossaryentry{indirect.array.comp.assign@ {\memgloterm{indirect.array.comp.assign}}{\memglodesc{(\ref {indirect.array.comp.assign})}} {\memgloref{}}|memjustarg}{1465} -\glossaryentry{indirect.array.fill@ {\memgloterm{indirect.array.fill}}{\memglodesc{(\ref {indirect.array.fill})}} {\memgloref{}}|memjustarg}{1466} -\glossaryentry{valarray.range@ {\memgloterm{valarray.range}}{\memglodesc{(\ref {valarray.range})}} {\memgloref{}}|memjustarg}{1466} -\glossaryentry{c.math@ {\memgloterm{c.math}}{\memglodesc{(\ref {c.math})}} {\memgloref{}}|memjustarg}{1466} -\glossaryentry{cmath.syn@ {\memgloterm{cmath.syn}}{\memglodesc{(\ref {cmath.syn})}} {\memgloref{}}|memjustarg}{1466} -\glossaryentry{c.math.abs@ {\memgloterm{c.math.abs}}{\memglodesc{(\ref {c.math.abs})}} {\memgloref{}}|memjustarg}{1473} -\glossaryentry{c.math.hypot3@ {\memgloterm{c.math.hypot3}}{\memglodesc{(\ref {c.math.hypot3})}} {\memgloref{}}|memjustarg}{1473} -\glossaryentry{c.math.lerp@ {\memgloterm{c.math.lerp}}{\memglodesc{(\ref {c.math.lerp})}} {\memgloref{}}|memjustarg}{1473} -\glossaryentry{c.math.fpclass@ {\memgloterm{c.math.fpclass}}{\memglodesc{(\ref {c.math.fpclass})}} {\memgloref{}}|memjustarg}{1473} -\glossaryentry{sf.cmath@ {\memgloterm{sf.cmath}}{\memglodesc{(\ref {sf.cmath})}} {\memgloref{}}|memjustarg}{1473} -\glossaryentry{sf.cmath.general@ {\memgloterm{sf.cmath.general}}{\memglodesc{(\ref {sf.cmath.general})}} {\memgloref{}}|memjustarg}{1473} -\glossaryentry{sf.cmath.assoc.laguerre@ {\memgloterm{sf.cmath.assoc.laguerre}}{\memglodesc{(\ref {sf.cmath.assoc.laguerre})}} {\memgloref{}}|memjustarg}{1474} -\glossaryentry{sf.cmath.assoc.legendre@ {\memgloterm{sf.cmath.assoc.legendre}}{\memglodesc{(\ref {sf.cmath.assoc.legendre})}} {\memgloref{}}|memjustarg}{1474} -\glossaryentry{sf.cmath.beta@ {\memgloterm{sf.cmath.beta}}{\memglodesc{(\ref {sf.cmath.beta})}} {\memgloref{}}|memjustarg}{1474} -\glossaryentry{sf.cmath.comp.ellint.1@ {\memgloterm{sf.cmath.comp.ellint.1}}{\memglodesc{(\ref {sf.cmath.comp.ellint.1})}} {\memgloref{}}|memjustarg}{1474} -\glossaryentry{sf.cmath.comp.ellint.2@ {\memgloterm{sf.cmath.comp.ellint.2}}{\memglodesc{(\ref {sf.cmath.comp.ellint.2})}} {\memgloref{}}|memjustarg}{1475} -\glossaryentry{sf.cmath.comp.ellint.3@ {\memgloterm{sf.cmath.comp.ellint.3}}{\memglodesc{(\ref {sf.cmath.comp.ellint.3})}} {\memgloref{}}|memjustarg}{1475} -\glossaryentry{sf.cmath.cyl.bessel.i@ {\memgloterm{sf.cmath.cyl.bessel.i}}{\memglodesc{(\ref {sf.cmath.cyl.bessel.i})}} {\memgloref{}}|memjustarg}{1475} -\glossaryentry{sf.cmath.cyl.bessel.j@ {\memgloterm{sf.cmath.cyl.bessel.j}}{\memglodesc{(\ref {sf.cmath.cyl.bessel.j})}} {\memgloref{}}|memjustarg}{1475} -\glossaryentry{sf.cmath.cyl.bessel.k@ {\memgloterm{sf.cmath.cyl.bessel.k}}{\memglodesc{(\ref {sf.cmath.cyl.bessel.k})}} {\memgloref{}}|memjustarg}{1476} -\glossaryentry{sf.cmath.cyl.neumann@ {\memgloterm{sf.cmath.cyl.neumann}}{\memglodesc{(\ref {sf.cmath.cyl.neumann})}} {\memgloref{}}|memjustarg}{1476} -\glossaryentry{sf.cmath.ellint.1@ {\memgloterm{sf.cmath.ellint.1}}{\memglodesc{(\ref {sf.cmath.ellint.1})}} {\memgloref{}}|memjustarg}{1476} -\glossaryentry{sf.cmath.ellint.2@ {\memgloterm{sf.cmath.ellint.2}}{\memglodesc{(\ref {sf.cmath.ellint.2})}} {\memgloref{}}|memjustarg}{1476} -\glossaryentry{sf.cmath.ellint.3@ {\memgloterm{sf.cmath.ellint.3}}{\memglodesc{(\ref {sf.cmath.ellint.3})}} {\memgloref{}}|memjustarg}{1477} -\glossaryentry{sf.cmath.expint@ {\memgloterm{sf.cmath.expint}}{\memglodesc{(\ref {sf.cmath.expint})}} {\memgloref{}}|memjustarg}{1477} -\glossaryentry{sf.cmath.hermite@ {\memgloterm{sf.cmath.hermite}}{\memglodesc{(\ref {sf.cmath.hermite})}} {\memgloref{}}|memjustarg}{1477} -\glossaryentry{sf.cmath.laguerre@ {\memgloterm{sf.cmath.laguerre}}{\memglodesc{(\ref {sf.cmath.laguerre})}} {\memgloref{}}|memjustarg}{1477} -\glossaryentry{sf.cmath.legendre@ {\memgloterm{sf.cmath.legendre}}{\memglodesc{(\ref {sf.cmath.legendre})}} {\memgloref{}}|memjustarg}{1477} -\glossaryentry{sf.cmath.riemann.zeta@ {\memgloterm{sf.cmath.riemann.zeta}}{\memglodesc{(\ref {sf.cmath.riemann.zeta})}} {\memgloref{}}|memjustarg}{1478} -\glossaryentry{sf.cmath.sph.bessel@ {\memgloterm{sf.cmath.sph.bessel}}{\memglodesc{(\ref {sf.cmath.sph.bessel})}} {\memgloref{}}|memjustarg}{1478} -\glossaryentry{sf.cmath.sph.legendre@ {\memgloterm{sf.cmath.sph.legendre}}{\memglodesc{(\ref {sf.cmath.sph.legendre})}} {\memgloref{}}|memjustarg}{1478} -\glossaryentry{sf.cmath.sph.neumann@ {\memgloterm{sf.cmath.sph.neumann}}{\memglodesc{(\ref {sf.cmath.sph.neumann})}} {\memgloref{}}|memjustarg}{1478} -\glossaryentry{numbers@ {\memgloterm{numbers}}{\memglodesc{(\ref {numbers})}} {\memgloref{}}|memjustarg}{1479} -\glossaryentry{numbers.syn@ {\memgloterm{numbers.syn}}{\memglodesc{(\ref {numbers.syn})}} {\memgloref{}}|memjustarg}{1479} -\glossaryentry{math.constants@ {\memgloterm{math.constants}}{\memglodesc{(\ref {math.constants})}} {\memgloref{}}|memjustarg}{1479} -\glossaryentry{time@ {\memgloterm{time}}{\memglodesc{(\ref {time})}} {\memgloref{}}|memjustarg}{1480} -\glossaryentry{time.general@ {\memgloterm{time.general}}{\memglodesc{(\ref {time.general})}} {\memgloref{}}|memjustarg}{1480} -\glossaryentry{time.syn@ {\memgloterm{time.syn}}{\memglodesc{(\ref {time.syn})}} {\memgloref{}}|memjustarg}{1480} -\glossaryentry{time.clock.req@ {\memgloterm{time.clock.req}}{\memglodesc{(\ref {time.clock.req})}} {\memgloref{}}|memjustarg}{1494} -\glossaryentry{time.traits@ {\memgloterm{time.traits}}{\memglodesc{(\ref {time.traits})}} {\memgloref{}}|memjustarg}{1495} -\glossaryentry{time.traits.is.fp@ {\memgloterm{time.traits.is.fp}}{\memglodesc{(\ref {time.traits.is.fp})}} {\memgloref{}}|memjustarg}{1495} -\glossaryentry{time.traits.duration.values@ {\memgloterm{time.traits.duration.values}}{\memglodesc{(\ref {time.traits.duration.values})}} {\memgloref{}}|memjustarg}{1495} -\glossaryentry{time.traits.specializations@ {\memgloterm{time.traits.specializations}}{\memglodesc{(\ref {time.traits.specializations})}} {\memgloref{}}|memjustarg}{1495} -\glossaryentry{time.traits.is.clock@ {\memgloterm{time.traits.is.clock}}{\memglodesc{(\ref {time.traits.is.clock})}} {\memgloref{}}|memjustarg}{1496} -\glossaryentry{time.duration@ {\memgloterm{time.duration}}{\memglodesc{(\ref {time.duration})}} {\memgloref{}}|memjustarg}{1496} -\glossaryentry{time.duration.general@ {\memgloterm{time.duration.general}}{\memglodesc{(\ref {time.duration.general})}} {\memgloref{}}|memjustarg}{1496} -\glossaryentry{time.duration.cons@ {\memgloterm{time.duration.cons}}{\memglodesc{(\ref {time.duration.cons})}} {\memgloref{}}|memjustarg}{1497} -\glossaryentry{time.duration.observer@ {\memgloterm{time.duration.observer}}{\memglodesc{(\ref {time.duration.observer})}} {\memgloref{}}|memjustarg}{1498} -\glossaryentry{time.duration.arithmetic@ {\memgloterm{time.duration.arithmetic}}{\memglodesc{(\ref {time.duration.arithmetic})}} {\memgloref{}}|memjustarg}{1498} -\glossaryentry{time.duration.special@ {\memgloterm{time.duration.special}}{\memglodesc{(\ref {time.duration.special})}} {\memgloref{}}|memjustarg}{1498} -\glossaryentry{time.duration.nonmember@ {\memgloterm{time.duration.nonmember}}{\memglodesc{(\ref {time.duration.nonmember})}} {\memgloref{}}|memjustarg}{1499} -\glossaryentry{time.duration.comparisons@ {\memgloterm{time.duration.comparisons}}{\memglodesc{(\ref {time.duration.comparisons})}} {\memgloref{}}|memjustarg}{1500} -\glossaryentry{time.duration.cast@ {\memgloterm{time.duration.cast}}{\memglodesc{(\ref {time.duration.cast})}} {\memgloref{}}|memjustarg}{1500} -\glossaryentry{time.duration.literals@ {\memgloterm{time.duration.literals}}{\memglodesc{(\ref {time.duration.literals})}} {\memgloref{}}|memjustarg}{1501} -\glossaryentry{time.duration.alg@ {\memgloterm{time.duration.alg}}{\memglodesc{(\ref {time.duration.alg})}} {\memgloref{}}|memjustarg}{1502} -\glossaryentry{time.duration.io@ {\memgloterm{time.duration.io}}{\memglodesc{(\ref {time.duration.io})}} {\memgloref{}}|memjustarg}{1502} -\glossaryentry{time.point@ {\memgloterm{time.point}}{\memglodesc{(\ref {time.point})}} {\memgloref{}}|memjustarg}{1503} -\glossaryentry{time.point.general@ {\memgloterm{time.point.general}}{\memglodesc{(\ref {time.point.general})}} {\memgloref{}}|memjustarg}{1503} -\glossaryentry{time.point.cons@ {\memgloterm{time.point.cons}}{\memglodesc{(\ref {time.point.cons})}} {\memgloref{}}|memjustarg}{1503} -\glossaryentry{time.point.observer@ {\memgloterm{time.point.observer}}{\memglodesc{(\ref {time.point.observer})}} {\memgloref{}}|memjustarg}{1504} -\glossaryentry{time.point.arithmetic@ {\memgloterm{time.point.arithmetic}}{\memglodesc{(\ref {time.point.arithmetic})}} {\memgloref{}}|memjustarg}{1504} -\glossaryentry{time.point.special@ {\memgloterm{time.point.special}}{\memglodesc{(\ref {time.point.special})}} {\memgloref{}}|memjustarg}{1504} -\glossaryentry{time.point.nonmember@ {\memgloterm{time.point.nonmember}}{\memglodesc{(\ref {time.point.nonmember})}} {\memgloref{}}|memjustarg}{1504} -\glossaryentry{time.point.comparisons@ {\memgloterm{time.point.comparisons}}{\memglodesc{(\ref {time.point.comparisons})}} {\memgloref{}}|memjustarg}{1505} -\glossaryentry{time.point.cast@ {\memgloterm{time.point.cast}}{\memglodesc{(\ref {time.point.cast})}} {\memgloref{}}|memjustarg}{1505} -\glossaryentry{time.clock@ {\memgloterm{time.clock}}{\memglodesc{(\ref {time.clock})}} {\memgloref{}}|memjustarg}{1506} -\glossaryentry{time.clock.general@ {\memgloterm{time.clock.general}}{\memglodesc{(\ref {time.clock.general})}} {\memgloref{}}|memjustarg}{1506} -\glossaryentry{time.clock.system@ {\memgloterm{time.clock.system}}{\memglodesc{(\ref {time.clock.system})}} {\memgloref{}}|memjustarg}{1506} -\glossaryentry{time.clock.system.overview@ {\memgloterm{time.clock.system.overview}}{\memglodesc{(\ref {time.clock.system.overview})}} {\memgloref{}}|memjustarg}{1506} -\glossaryentry{time.clock.system.members@ {\memgloterm{time.clock.system.members}}{\memglodesc{(\ref {time.clock.system.members})}} {\memgloref{}}|memjustarg}{1506} -\glossaryentry{time.clock.system.nonmembers@ {\memgloterm{time.clock.system.nonmembers}}{\memglodesc{(\ref {time.clock.system.nonmembers})}} {\memgloref{}}|memjustarg}{1506} -\glossaryentry{time.clock.utc@ {\memgloterm{time.clock.utc}}{\memglodesc{(\ref {time.clock.utc})}} {\memgloref{}}|memjustarg}{1507} -\glossaryentry{time.clock.utc.overview@ {\memgloterm{time.clock.utc.overview}}{\memglodesc{(\ref {time.clock.utc.overview})}} {\memgloref{}}|memjustarg}{1507} -\glossaryentry{time.clock.utc.members@ {\memgloterm{time.clock.utc.members}}{\memglodesc{(\ref {time.clock.utc.members})}} {\memgloref{}}|memjustarg}{1508} -\glossaryentry{time.clock.utc.nonmembers@ {\memgloterm{time.clock.utc.nonmembers}}{\memglodesc{(\ref {time.clock.utc.nonmembers})}} {\memgloref{}}|memjustarg}{1508} -\glossaryentry{time.clock.tai@ {\memgloterm{time.clock.tai}}{\memglodesc{(\ref {time.clock.tai})}} {\memgloref{}}|memjustarg}{1509} -\glossaryentry{time.clock.tai.overview@ {\memgloterm{time.clock.tai.overview}}{\memglodesc{(\ref {time.clock.tai.overview})}} {\memgloref{}}|memjustarg}{1509} -\glossaryentry{time.clock.tai.members@ {\memgloterm{time.clock.tai.members}}{\memglodesc{(\ref {time.clock.tai.members})}} {\memgloref{}}|memjustarg}{1510} -\glossaryentry{time.clock.tai.nonmembers@ {\memgloterm{time.clock.tai.nonmembers}}{\memglodesc{(\ref {time.clock.tai.nonmembers})}} {\memgloref{}}|memjustarg}{1510} -\glossaryentry{time.clock.gps@ {\memgloterm{time.clock.gps}}{\memglodesc{(\ref {time.clock.gps})}} {\memgloref{}}|memjustarg}{1511} -\glossaryentry{time.clock.gps.overview@ {\memgloterm{time.clock.gps.overview}}{\memglodesc{(\ref {time.clock.gps.overview})}} {\memgloref{}}|memjustarg}{1511} -\glossaryentry{time.clock.gps.members@ {\memgloterm{time.clock.gps.members}}{\memglodesc{(\ref {time.clock.gps.members})}} {\memgloref{}}|memjustarg}{1511} -\glossaryentry{time.clock.gps.nonmembers@ {\memgloterm{time.clock.gps.nonmembers}}{\memglodesc{(\ref {time.clock.gps.nonmembers})}} {\memgloref{}}|memjustarg}{1511} -\glossaryentry{time.clock.file@ {\memgloterm{time.clock.file}}{\memglodesc{(\ref {time.clock.file})}} {\memgloref{}}|memjustarg}{1512} -\glossaryentry{time.clock.file.overview@ {\memgloterm{time.clock.file.overview}}{\memglodesc{(\ref {time.clock.file.overview})}} {\memgloref{}}|memjustarg}{1512} -\glossaryentry{time.clock.file.members@ {\memgloterm{time.clock.file.members}}{\memglodesc{(\ref {time.clock.file.members})}} {\memgloref{}}|memjustarg}{1512} -\glossaryentry{time.clock.file.nonmembers@ {\memgloterm{time.clock.file.nonmembers}}{\memglodesc{(\ref {time.clock.file.nonmembers})}} {\memgloref{}}|memjustarg}{1513} -\glossaryentry{time.clock.steady@ {\memgloterm{time.clock.steady}}{\memglodesc{(\ref {time.clock.steady})}} {\memgloref{}}|memjustarg}{1513} -\glossaryentry{time.clock.hires@ {\memgloterm{time.clock.hires}}{\memglodesc{(\ref {time.clock.hires})}} {\memgloref{}}|memjustarg}{1513} -\glossaryentry{time.clock.local@ {\memgloterm{time.clock.local}}{\memglodesc{(\ref {time.clock.local})}} {\memgloref{}}|memjustarg}{1513} -\glossaryentry{time.clock.cast@ {\memgloterm{time.clock.cast}}{\memglodesc{(\ref {time.clock.cast})}} {\memgloref{}}|memjustarg}{1514} -\glossaryentry{time.clock.conv@ {\memgloterm{time.clock.conv}}{\memglodesc{(\ref {time.clock.conv})}} {\memgloref{}}|memjustarg}{1514} -\glossaryentry{time.clock.cast.id@ {\memgloterm{time.clock.cast.id}}{\memglodesc{(\ref {time.clock.cast.id})}} {\memgloref{}}|memjustarg}{1514} -\glossaryentry{time.clock.cast.sys.utc@ {\memgloterm{time.clock.cast.sys.utc}}{\memglodesc{(\ref {time.clock.cast.sys.utc})}} {\memgloref{}}|memjustarg}{1515} -\glossaryentry{time.clock.cast.sys@ {\memgloterm{time.clock.cast.sys}}{\memglodesc{(\ref {time.clock.cast.sys})}} {\memgloref{}}|memjustarg}{1515} -\glossaryentry{time.clock.cast.utc@ {\memgloterm{time.clock.cast.utc}}{\memglodesc{(\ref {time.clock.cast.utc})}} {\memgloref{}}|memjustarg}{1516} -\glossaryentry{time.clock.cast.fn@ {\memgloterm{time.clock.cast.fn}}{\memglodesc{(\ref {time.clock.cast.fn})}} {\memgloref{}}|memjustarg}{1516} -\glossaryentry{time.cal@ {\memgloterm{time.cal}}{\memglodesc{(\ref {time.cal})}} {\memgloref{}}|memjustarg}{1517} -\glossaryentry{time.cal.general@ {\memgloterm{time.cal.general}}{\memglodesc{(\ref {time.cal.general})}} {\memgloref{}}|memjustarg}{1517} -\glossaryentry{time.cal.last@ {\memgloterm{time.cal.last}}{\memglodesc{(\ref {time.cal.last})}} {\memgloref{}}|memjustarg}{1517} -\glossaryentry{time.cal.day@ {\memgloterm{time.cal.day}}{\memglodesc{(\ref {time.cal.day})}} {\memgloref{}}|memjustarg}{1517} -\glossaryentry{time.cal.day.overview@ {\memgloterm{time.cal.day.overview}}{\memglodesc{(\ref {time.cal.day.overview})}} {\memgloref{}}|memjustarg}{1517} -\glossaryentry{time.cal.day.members@ {\memgloterm{time.cal.day.members}}{\memglodesc{(\ref {time.cal.day.members})}} {\memgloref{}}|memjustarg}{1517} -\glossaryentry{time.cal.day.nonmembers@ {\memgloterm{time.cal.day.nonmembers}}{\memglodesc{(\ref {time.cal.day.nonmembers})}} {\memgloref{}}|memjustarg}{1518} -\glossaryentry{time.cal.month@ {\memgloterm{time.cal.month}}{\memglodesc{(\ref {time.cal.month})}} {\memgloref{}}|memjustarg}{1519} -\glossaryentry{time.cal.month.overview@ {\memgloterm{time.cal.month.overview}}{\memglodesc{(\ref {time.cal.month.overview})}} {\memgloref{}}|memjustarg}{1519} -\glossaryentry{time.cal.month.members@ {\memgloterm{time.cal.month.members}}{\memglodesc{(\ref {time.cal.month.members})}} {\memgloref{}}|memjustarg}{1519} -\glossaryentry{time.cal.month.nonmembers@ {\memgloterm{time.cal.month.nonmembers}}{\memglodesc{(\ref {time.cal.month.nonmembers})}} {\memgloref{}}|memjustarg}{1520} -\glossaryentry{time.cal.year@ {\memgloterm{time.cal.year}}{\memglodesc{(\ref {time.cal.year})}} {\memgloref{}}|memjustarg}{1521} -\glossaryentry{time.cal.year.overview@ {\memgloterm{time.cal.year.overview}}{\memglodesc{(\ref {time.cal.year.overview})}} {\memgloref{}}|memjustarg}{1521} -\glossaryentry{time.cal.year.members@ {\memgloterm{time.cal.year.members}}{\memglodesc{(\ref {time.cal.year.members})}} {\memgloref{}}|memjustarg}{1521} -\glossaryentry{time.cal.year.nonmembers@ {\memgloterm{time.cal.year.nonmembers}}{\memglodesc{(\ref {time.cal.year.nonmembers})}} {\memgloref{}}|memjustarg}{1522} -\glossaryentry{time.cal.wd@ {\memgloterm{time.cal.wd}}{\memglodesc{(\ref {time.cal.wd})}} {\memgloref{}}|memjustarg}{1523} -\glossaryentry{time.cal.wd.overview@ {\memgloterm{time.cal.wd.overview}}{\memglodesc{(\ref {time.cal.wd.overview})}} {\memgloref{}}|memjustarg}{1523} -\glossaryentry{time.cal.wd.members@ {\memgloterm{time.cal.wd.members}}{\memglodesc{(\ref {time.cal.wd.members})}} {\memgloref{}}|memjustarg}{1524} -\glossaryentry{time.cal.wd.nonmembers@ {\memgloterm{time.cal.wd.nonmembers}}{\memglodesc{(\ref {time.cal.wd.nonmembers})}} {\memgloref{}}|memjustarg}{1525} -\glossaryentry{time.cal.wdidx@ {\memgloterm{time.cal.wdidx}}{\memglodesc{(\ref {time.cal.wdidx})}} {\memgloref{}}|memjustarg}{1525} -\glossaryentry{time.cal.wdidx.overview@ {\memgloterm{time.cal.wdidx.overview}}{\memglodesc{(\ref {time.cal.wdidx.overview})}} {\memgloref{}}|memjustarg}{1525} -\glossaryentry{time.cal.wdidx.members@ {\memgloterm{time.cal.wdidx.members}}{\memglodesc{(\ref {time.cal.wdidx.members})}} {\memgloref{}}|memjustarg}{1526} -\glossaryentry{time.cal.wdidx.nonmembers@ {\memgloterm{time.cal.wdidx.nonmembers}}{\memglodesc{(\ref {time.cal.wdidx.nonmembers})}} {\memgloref{}}|memjustarg}{1526} -\glossaryentry{time.cal.wdlast@ {\memgloterm{time.cal.wdlast}}{\memglodesc{(\ref {time.cal.wdlast})}} {\memgloref{}}|memjustarg}{1526} -\glossaryentry{time.cal.wdlast.overview@ {\memgloterm{time.cal.wdlast.overview}}{\memglodesc{(\ref {time.cal.wdlast.overview})}} {\memgloref{}}|memjustarg}{1526} -\glossaryentry{time.cal.wdlast.members@ {\memgloterm{time.cal.wdlast.members}}{\memglodesc{(\ref {time.cal.wdlast.members})}} {\memgloref{}}|memjustarg}{1527} -\glossaryentry{time.cal.wdlast.nonmembers@ {\memgloterm{time.cal.wdlast.nonmembers}}{\memglodesc{(\ref {time.cal.wdlast.nonmembers})}} {\memgloref{}}|memjustarg}{1527} -\glossaryentry{time.cal.md@ {\memgloterm{time.cal.md}}{\memglodesc{(\ref {time.cal.md})}} {\memgloref{}}|memjustarg}{1527} -\glossaryentry{time.cal.md.overview@ {\memgloterm{time.cal.md.overview}}{\memglodesc{(\ref {time.cal.md.overview})}} {\memgloref{}}|memjustarg}{1527} -\glossaryentry{time.cal.md.members@ {\memgloterm{time.cal.md.members}}{\memglodesc{(\ref {time.cal.md.members})}} {\memgloref{}}|memjustarg}{1527} -\glossaryentry{time.cal.md.nonmembers@ {\memgloterm{time.cal.md.nonmembers}}{\memglodesc{(\ref {time.cal.md.nonmembers})}} {\memgloref{}}|memjustarg}{1528} -\glossaryentry{time.cal.mdlast@ {\memgloterm{time.cal.mdlast}}{\memglodesc{(\ref {time.cal.mdlast})}} {\memgloref{}}|memjustarg}{1528} -\glossaryentry{time.cal.mwd@ {\memgloterm{time.cal.mwd}}{\memglodesc{(\ref {time.cal.mwd})}} {\memgloref{}}|memjustarg}{1529} -\glossaryentry{time.cal.mwd.overview@ {\memgloterm{time.cal.mwd.overview}}{\memglodesc{(\ref {time.cal.mwd.overview})}} {\memgloref{}}|memjustarg}{1529} -\glossaryentry{time.cal.mwd.members@ {\memgloterm{time.cal.mwd.members}}{\memglodesc{(\ref {time.cal.mwd.members})}} {\memgloref{}}|memjustarg}{1529} -\glossaryentry{time.cal.mwd.nonmembers@ {\memgloterm{time.cal.mwd.nonmembers}}{\memglodesc{(\ref {time.cal.mwd.nonmembers})}} {\memgloref{}}|memjustarg}{1530} -\glossaryentry{time.cal.mwdlast@ {\memgloterm{time.cal.mwdlast}}{\memglodesc{(\ref {time.cal.mwdlast})}} {\memgloref{}}|memjustarg}{1530} -\glossaryentry{time.cal.mwdlast.overview@ {\memgloterm{time.cal.mwdlast.overview}}{\memglodesc{(\ref {time.cal.mwdlast.overview})}} {\memgloref{}}|memjustarg}{1530} -\glossaryentry{time.cal.mwdlast.members@ {\memgloterm{time.cal.mwdlast.members}}{\memglodesc{(\ref {time.cal.mwdlast.members})}} {\memgloref{}}|memjustarg}{1530} -\glossaryentry{time.cal.mwdlast.nonmembers@ {\memgloterm{time.cal.mwdlast.nonmembers}}{\memglodesc{(\ref {time.cal.mwdlast.nonmembers})}} {\memgloref{}}|memjustarg}{1530} -\glossaryentry{time.cal.ym@ {\memgloterm{time.cal.ym}}{\memglodesc{(\ref {time.cal.ym})}} {\memgloref{}}|memjustarg}{1531} -\glossaryentry{time.cal.ym.overview@ {\memgloterm{time.cal.ym.overview}}{\memglodesc{(\ref {time.cal.ym.overview})}} {\memgloref{}}|memjustarg}{1531} -\glossaryentry{time.cal.ym.members@ {\memgloterm{time.cal.ym.members}}{\memglodesc{(\ref {time.cal.ym.members})}} {\memgloref{}}|memjustarg}{1531} -\glossaryentry{time.cal.ym.nonmembers@ {\memgloterm{time.cal.ym.nonmembers}}{\memglodesc{(\ref {time.cal.ym.nonmembers})}} {\memgloref{}}|memjustarg}{1532} -\glossaryentry{time.cal.ymd@ {\memgloterm{time.cal.ymd}}{\memglodesc{(\ref {time.cal.ymd})}} {\memgloref{}}|memjustarg}{1533} -\glossaryentry{time.cal.ymd.overview@ {\memgloterm{time.cal.ymd.overview}}{\memglodesc{(\ref {time.cal.ymd.overview})}} {\memgloref{}}|memjustarg}{1533} -\glossaryentry{time.cal.ymd.members@ {\memgloterm{time.cal.ymd.members}}{\memglodesc{(\ref {time.cal.ymd.members})}} {\memgloref{}}|memjustarg}{1533} -\glossaryentry{time.cal.ymd.nonmembers@ {\memgloterm{time.cal.ymd.nonmembers}}{\memglodesc{(\ref {time.cal.ymd.nonmembers})}} {\memgloref{}}|memjustarg}{1535} -\glossaryentry{time.cal.ymdlast@ {\memgloterm{time.cal.ymdlast}}{\memglodesc{(\ref {time.cal.ymdlast})}} {\memgloref{}}|memjustarg}{1536} -\glossaryentry{time.cal.ymdlast.overview@ {\memgloterm{time.cal.ymdlast.overview}}{\memglodesc{(\ref {time.cal.ymdlast.overview})}} {\memgloref{}}|memjustarg}{1536} -\glossaryentry{time.cal.ymdlast.members@ {\memgloterm{time.cal.ymdlast.members}}{\memglodesc{(\ref {time.cal.ymdlast.members})}} {\memgloref{}}|memjustarg}{1536} -\glossaryentry{time.cal.ymdlast.nonmembers@ {\memgloterm{time.cal.ymdlast.nonmembers}}{\memglodesc{(\ref {time.cal.ymdlast.nonmembers})}} {\memgloref{}}|memjustarg}{1537} -\glossaryentry{time.cal.ymwd@ {\memgloterm{time.cal.ymwd}}{\memglodesc{(\ref {time.cal.ymwd})}} {\memgloref{}}|memjustarg}{1538} -\glossaryentry{time.cal.ymwd.overview@ {\memgloterm{time.cal.ymwd.overview}}{\memglodesc{(\ref {time.cal.ymwd.overview})}} {\memgloref{}}|memjustarg}{1538} -\glossaryentry{time.cal.ymwd.members@ {\memgloterm{time.cal.ymwd.members}}{\memglodesc{(\ref {time.cal.ymwd.members})}} {\memgloref{}}|memjustarg}{1539} -\glossaryentry{time.cal.ymwd.nonmembers@ {\memgloterm{time.cal.ymwd.nonmembers}}{\memglodesc{(\ref {time.cal.ymwd.nonmembers})}} {\memgloref{}}|memjustarg}{1540} -\glossaryentry{time.cal.ymwdlast@ {\memgloterm{time.cal.ymwdlast}}{\memglodesc{(\ref {time.cal.ymwdlast})}} {\memgloref{}}|memjustarg}{1540} -\glossaryentry{time.cal.ymwdlast.overview@ {\memgloterm{time.cal.ymwdlast.overview}}{\memglodesc{(\ref {time.cal.ymwdlast.overview})}} {\memgloref{}}|memjustarg}{1540} -\glossaryentry{time.cal.ymwdlast.members@ {\memgloterm{time.cal.ymwdlast.members}}{\memglodesc{(\ref {time.cal.ymwdlast.members})}} {\memgloref{}}|memjustarg}{1541} -\glossaryentry{time.cal.ymwdlast.nonmembers@ {\memgloterm{time.cal.ymwdlast.nonmembers}}{\memglodesc{(\ref {time.cal.ymwdlast.nonmembers})}} {\memgloref{}}|memjustarg}{1542} -\glossaryentry{time.cal.operators@ {\memgloterm{time.cal.operators}}{\memglodesc{(\ref {time.cal.operators})}} {\memgloref{}}|memjustarg}{1543} -\glossaryentry{time.hms@ {\memgloterm{time.hms}}{\memglodesc{(\ref {time.hms})}} {\memgloref{}}|memjustarg}{1546} -\glossaryentry{time.hms.overview@ {\memgloterm{time.hms.overview}}{\memglodesc{(\ref {time.hms.overview})}} {\memgloref{}}|memjustarg}{1546} -\glossaryentry{time.hms.members@ {\memgloterm{time.hms.members}}{\memglodesc{(\ref {time.hms.members})}} {\memgloref{}}|memjustarg}{1546} -\glossaryentry{time.hms.nonmembers@ {\memgloterm{time.hms.nonmembers}}{\memglodesc{(\ref {time.hms.nonmembers})}} {\memgloref{}}|memjustarg}{1548} -\glossaryentry{time.12@ {\memgloterm{time.12}}{\memglodesc{(\ref {time.12})}} {\memgloref{}}|memjustarg}{1548} -\glossaryentry{time.zone@ {\memgloterm{time.zone}}{\memglodesc{(\ref {time.zone})}} {\memgloref{}}|memjustarg}{1548} -\glossaryentry{time.zone.general@ {\memgloterm{time.zone.general}}{\memglodesc{(\ref {time.zone.general})}} {\memgloref{}}|memjustarg}{1548} -\glossaryentry{time.zone.db@ {\memgloterm{time.zone.db}}{\memglodesc{(\ref {time.zone.db})}} {\memgloref{}}|memjustarg}{1548} -\glossaryentry{time.zone.db.tzdb@ {\memgloterm{time.zone.db.tzdb}}{\memglodesc{(\ref {time.zone.db.tzdb})}} {\memgloref{}}|memjustarg}{1548} -\glossaryentry{time.zone.db.list@ {\memgloterm{time.zone.db.list}}{\memglodesc{(\ref {time.zone.db.list})}} {\memgloref{}}|memjustarg}{1549} -\glossaryentry{time.zone.db.access@ {\memgloterm{time.zone.db.access}}{\memglodesc{(\ref {time.zone.db.access})}} {\memgloref{}}|memjustarg}{1550} -\glossaryentry{time.zone.db.remote@ {\memgloterm{time.zone.db.remote}}{\memglodesc{(\ref {time.zone.db.remote})}} {\memgloref{}}|memjustarg}{1550} -\glossaryentry{time.zone.exception@ {\memgloterm{time.zone.exception}}{\memglodesc{(\ref {time.zone.exception})}} {\memgloref{}}|memjustarg}{1551} -\glossaryentry{time.zone.exception.nonexist@ {\memgloterm{time.zone.exception.nonexist}}{\memglodesc{(\ref {time.zone.exception.nonexist})}} {\memgloref{}}|memjustarg}{1551} -\glossaryentry{time.zone.exception.ambig@ {\memgloterm{time.zone.exception.ambig}}{\memglodesc{(\ref {time.zone.exception.ambig})}} {\memgloref{}}|memjustarg}{1551} -\glossaryentry{time.zone.info@ {\memgloterm{time.zone.info}}{\memglodesc{(\ref {time.zone.info})}} {\memgloref{}}|memjustarg}{1552} -\glossaryentry{time.zone.info.sys@ {\memgloterm{time.zone.info.sys}}{\memglodesc{(\ref {time.zone.info.sys})}} {\memgloref{}}|memjustarg}{1552} -\glossaryentry{time.zone.info.local@ {\memgloterm{time.zone.info.local}}{\memglodesc{(\ref {time.zone.info.local})}} {\memgloref{}}|memjustarg}{1553} -\glossaryentry{time.zone.timezone@ {\memgloterm{time.zone.timezone}}{\memglodesc{(\ref {time.zone.timezone})}} {\memgloref{}}|memjustarg}{1553} -\glossaryentry{time.zone.overview@ {\memgloterm{time.zone.overview}}{\memglodesc{(\ref {time.zone.overview})}} {\memgloref{}}|memjustarg}{1553} -\glossaryentry{time.zone.members@ {\memgloterm{time.zone.members}}{\memglodesc{(\ref {time.zone.members})}} {\memgloref{}}|memjustarg}{1554} -\glossaryentry{time.zone.nonmembers@ {\memgloterm{time.zone.nonmembers}}{\memglodesc{(\ref {time.zone.nonmembers})}} {\memgloref{}}|memjustarg}{1555} -\glossaryentry{time.zone.zonedtraits@ {\memgloterm{time.zone.zonedtraits}}{\memglodesc{(\ref {time.zone.zonedtraits})}} {\memgloref{}}|memjustarg}{1555} -\glossaryentry{time.zone.zonedtime@ {\memgloterm{time.zone.zonedtime}}{\memglodesc{(\ref {time.zone.zonedtime})}} {\memgloref{}}|memjustarg}{1555} -\glossaryentry{time.zone.zonedtime.overview@ {\memgloterm{time.zone.zonedtime.overview}}{\memglodesc{(\ref {time.zone.zonedtime.overview})}} {\memgloref{}}|memjustarg}{1555} -\glossaryentry{time.zone.zonedtime.ctor@ {\memgloterm{time.zone.zonedtime.ctor}}{\memglodesc{(\ref {time.zone.zonedtime.ctor})}} {\memgloref{}}|memjustarg}{1557} -\glossaryentry{time.zone.zonedtime.members@ {\memgloterm{time.zone.zonedtime.members}}{\memglodesc{(\ref {time.zone.zonedtime.members})}} {\memgloref{}}|memjustarg}{1558} -\glossaryentry{time.zone.zonedtime.nonmembers@ {\memgloterm{time.zone.zonedtime.nonmembers}}{\memglodesc{(\ref {time.zone.zonedtime.nonmembers})}} {\memgloref{}}|memjustarg}{1559} -\glossaryentry{time.zone.leap@ {\memgloterm{time.zone.leap}}{\memglodesc{(\ref {time.zone.leap})}} {\memgloref{}}|memjustarg}{1559} -\glossaryentry{time.zone.leap.overview@ {\memgloterm{time.zone.leap.overview}}{\memglodesc{(\ref {time.zone.leap.overview})}} {\memgloref{}}|memjustarg}{1559} -\glossaryentry{time.zone.leap.members@ {\memgloterm{time.zone.leap.members}}{\memglodesc{(\ref {time.zone.leap.members})}} {\memgloref{}}|memjustarg}{1560} -\glossaryentry{time.zone.leap.nonmembers@ {\memgloterm{time.zone.leap.nonmembers}}{\memglodesc{(\ref {time.zone.leap.nonmembers})}} {\memgloref{}}|memjustarg}{1560} -\glossaryentry{time.zone.link@ {\memgloterm{time.zone.link}}{\memglodesc{(\ref {time.zone.link})}} {\memgloref{}}|memjustarg}{1561} -\glossaryentry{time.zone.link.overview@ {\memgloterm{time.zone.link.overview}}{\memglodesc{(\ref {time.zone.link.overview})}} {\memgloref{}}|memjustarg}{1561} -\glossaryentry{time.zone.link.members@ {\memgloterm{time.zone.link.members}}{\memglodesc{(\ref {time.zone.link.members})}} {\memgloref{}}|memjustarg}{1561} -\glossaryentry{time.zone.link.nonmembers@ {\memgloterm{time.zone.link.nonmembers}}{\memglodesc{(\ref {time.zone.link.nonmembers})}} {\memgloref{}}|memjustarg}{1561} -\glossaryentry{time.format@ {\memgloterm{time.format}}{\memglodesc{(\ref {time.format})}} {\memgloref{}}|memjustarg}{1561} -\glossaryentry{time.parse@ {\memgloterm{time.parse}}{\memglodesc{(\ref {time.parse})}} {\memgloref{}}|memjustarg}{1565} -\glossaryentry{ctime.syn@ {\memgloterm{ctime.syn}}{\memglodesc{(\ref {ctime.syn})}} {\memgloref{}}|memjustarg}{1569} -\glossaryentry{localization@ {\memgloterm{localization}}{\memglodesc{(\ref {localization})}} {\memgloref{}}|memjustarg}{1571} -\glossaryentry{localization.general@ {\memgloterm{localization.general}}{\memglodesc{(\ref {localization.general})}} {\memgloref{}}|memjustarg}{1571} -\glossaryentry{locale.syn@ {\memgloterm{locale.syn}}{\memglodesc{(\ref {locale.syn})}} {\memgloref{}}|memjustarg}{1571} -\glossaryentry{locales@ {\memgloterm{locales}}{\memglodesc{(\ref {locales})}} {\memgloref{}}|memjustarg}{1572} -\glossaryentry{locale@ {\memgloterm{locale}}{\memglodesc{(\ref {locale})}} {\memgloref{}}|memjustarg}{1572} -\glossaryentry{locale.general@ {\memgloterm{locale.general}}{\memglodesc{(\ref {locale.general})}} {\memgloref{}}|memjustarg}{1572} -\glossaryentry{locale.types@ {\memgloterm{locale.types}}{\memglodesc{(\ref {locale.types})}} {\memgloref{}}|memjustarg}{1574} -\glossaryentry{locale.category@ {\memgloterm{locale.category}}{\memglodesc{(\ref {locale.category})}} {\memgloref{}}|memjustarg}{1574} -\glossaryentry{locale.facet@ {\memgloterm{locale.facet}}{\memglodesc{(\ref {locale.facet})}} {\memgloref{}}|memjustarg}{1575} -\glossaryentry{locale.id@ {\memgloterm{locale.id}}{\memglodesc{(\ref {locale.id})}} {\memgloref{}}|memjustarg}{1576} -\glossaryentry{locale.cons@ {\memgloterm{locale.cons}}{\memglodesc{(\ref {locale.cons})}} {\memgloref{}}|memjustarg}{1576} -\glossaryentry{locale.members@ {\memgloterm{locale.members}}{\memglodesc{(\ref {locale.members})}} {\memgloref{}}|memjustarg}{1577} -\glossaryentry{locale.operators@ {\memgloterm{locale.operators}}{\memglodesc{(\ref {locale.operators})}} {\memgloref{}}|memjustarg}{1577} -\glossaryentry{locale.statics@ {\memgloterm{locale.statics}}{\memglodesc{(\ref {locale.statics})}} {\memgloref{}}|memjustarg}{1577} -\glossaryentry{locale.global.templates@ {\memgloterm{locale.global.templates}}{\memglodesc{(\ref {locale.global.templates})}} {\memgloref{}}|memjustarg}{1578} -\glossaryentry{locale.convenience@ {\memgloterm{locale.convenience}}{\memglodesc{(\ref {locale.convenience})}} {\memgloref{}}|memjustarg}{1578} -\glossaryentry{classification@ {\memgloterm{classification}}{\memglodesc{(\ref {classification})}} {\memgloref{}}|memjustarg}{1578} -\glossaryentry{conversions.character@ {\memgloterm{conversions.character}}{\memglodesc{(\ref {conversions.character})}} {\memgloref{}}|memjustarg}{1578} -\glossaryentry{locale.categories@ {\memgloterm{locale.categories}}{\memglodesc{(\ref {locale.categories})}} {\memgloref{}}|memjustarg}{1578} -\glossaryentry{locale.categories.general@ {\memgloterm{locale.categories.general}}{\memglodesc{(\ref {locale.categories.general})}} {\memgloref{}}|memjustarg}{1578} -\glossaryentry{category.ctype@ {\memgloterm{category.ctype}}{\memglodesc{(\ref {category.ctype})}} {\memgloref{}}|memjustarg}{1579} -\glossaryentry{category.ctype.general@ {\memgloterm{category.ctype.general}}{\memglodesc{(\ref {category.ctype.general})}} {\memgloref{}}|memjustarg}{1579} -\glossaryentry{locale.ctype@ {\memgloterm{locale.ctype}}{\memglodesc{(\ref {locale.ctype})}} {\memgloref{}}|memjustarg}{1579} -\glossaryentry{locale.ctype.general@ {\memgloterm{locale.ctype.general}}{\memglodesc{(\ref {locale.ctype.general})}} {\memgloref{}}|memjustarg}{1579} -\glossaryentry{locale.ctype.members@ {\memgloterm{locale.ctype.members}}{\memglodesc{(\ref {locale.ctype.members})}} {\memgloref{}}|memjustarg}{1580} -\glossaryentry{locale.ctype.virtuals@ {\memgloterm{locale.ctype.virtuals}}{\memglodesc{(\ref {locale.ctype.virtuals})}} {\memgloref{}}|memjustarg}{1580} -\glossaryentry{locale.ctype.byname@ {\memgloterm{locale.ctype.byname}}{\memglodesc{(\ref {locale.ctype.byname})}} {\memgloref{}}|memjustarg}{1581} -\glossaryentry{facet.ctype.special@ {\memgloterm{facet.ctype.special}}{\memglodesc{(\ref {facet.ctype.special})}} {\memgloref{}}|memjustarg}{1582} -\glossaryentry{facet.ctype.special.general@ {\memgloterm{facet.ctype.special.general}}{\memglodesc{(\ref {facet.ctype.special.general})}} {\memgloref{}}|memjustarg}{1582} -\glossaryentry{facet.ctype.char.dtor@ {\memgloterm{facet.ctype.char.dtor}}{\memglodesc{(\ref {facet.ctype.char.dtor})}} {\memgloref{}}|memjustarg}{1582} -\glossaryentry{facet.ctype.char.members@ {\memgloterm{facet.ctype.char.members}}{\memglodesc{(\ref {facet.ctype.char.members})}} {\memgloref{}}|memjustarg}{1583} -\glossaryentry{facet.ctype.char.statics@ {\memgloterm{facet.ctype.char.statics}}{\memglodesc{(\ref {facet.ctype.char.statics})}} {\memgloref{}}|memjustarg}{1583} -\glossaryentry{facet.ctype.char.virtuals@ {\memgloterm{facet.ctype.char.virtuals}}{\memglodesc{(\ref {facet.ctype.char.virtuals})}} {\memgloref{}}|memjustarg}{1583} -\glossaryentry{locale.codecvt@ {\memgloterm{locale.codecvt}}{\memglodesc{(\ref {locale.codecvt})}} {\memgloref{}}|memjustarg}{1584} -\glossaryentry{locale.codecvt.general@ {\memgloterm{locale.codecvt.general}}{\memglodesc{(\ref {locale.codecvt.general})}} {\memgloref{}}|memjustarg}{1584} -\glossaryentry{locale.codecvt.members@ {\memgloterm{locale.codecvt.members}}{\memglodesc{(\ref {locale.codecvt.members})}} {\memgloref{}}|memjustarg}{1585} -\glossaryentry{locale.codecvt.virtuals@ {\memgloterm{locale.codecvt.virtuals}}{\memglodesc{(\ref {locale.codecvt.virtuals})}} {\memgloref{}}|memjustarg}{1585} -\glossaryentry{locale.codecvt.byname@ {\memgloterm{locale.codecvt.byname}}{\memglodesc{(\ref {locale.codecvt.byname})}} {\memgloref{}}|memjustarg}{1587} -\glossaryentry{category.numeric@ {\memgloterm{category.numeric}}{\memglodesc{(\ref {category.numeric})}} {\memgloref{}}|memjustarg}{1587} -\glossaryentry{category.numeric.general@ {\memgloterm{category.numeric.general}}{\memglodesc{(\ref {category.numeric.general})}} {\memgloref{}}|memjustarg}{1587} -\glossaryentry{locale.num.get@ {\memgloterm{locale.num.get}}{\memglodesc{(\ref {locale.num.get})}} {\memgloref{}}|memjustarg}{1588} -\glossaryentry{locale.num.get.general@ {\memgloterm{locale.num.get.general}}{\memglodesc{(\ref {locale.num.get.general})}} {\memgloref{}}|memjustarg}{1588} -\glossaryentry{facet.num.get.members@ {\memgloterm{facet.num.get.members}}{\memglodesc{(\ref {facet.num.get.members})}} {\memgloref{}}|memjustarg}{1589} -\glossaryentry{facet.num.get.virtuals@ {\memgloterm{facet.num.get.virtuals}}{\memglodesc{(\ref {facet.num.get.virtuals})}} {\memgloref{}}|memjustarg}{1589} -\glossaryentry{locale.nm.put@ {\memgloterm{locale.nm.put}}{\memglodesc{(\ref {locale.nm.put})}} {\memgloref{}}|memjustarg}{1592} -\glossaryentry{locale.nm.put.general@ {\memgloterm{locale.nm.put.general}}{\memglodesc{(\ref {locale.nm.put.general})}} {\memgloref{}}|memjustarg}{1592} -\glossaryentry{facet.num.put.members@ {\memgloterm{facet.num.put.members}}{\memglodesc{(\ref {facet.num.put.members})}} {\memgloref{}}|memjustarg}{1592} -\glossaryentry{facet.num.put.virtuals@ {\memgloterm{facet.num.put.virtuals}}{\memglodesc{(\ref {facet.num.put.virtuals})}} {\memgloref{}}|memjustarg}{1592} -\glossaryentry{facet.numpunct@ {\memgloterm{facet.numpunct}}{\memglodesc{(\ref {facet.numpunct})}} {\memgloref{}}|memjustarg}{1595} -\glossaryentry{locale.numpunct@ {\memgloterm{locale.numpunct}}{\memglodesc{(\ref {locale.numpunct})}} {\memgloref{}}|memjustarg}{1595} -\glossaryentry{locale.numpunct.general@ {\memgloterm{locale.numpunct.general}}{\memglodesc{(\ref {locale.numpunct.general})}} {\memgloref{}}|memjustarg}{1595} -\glossaryentry{facet.numpunct.members@ {\memgloterm{facet.numpunct.members}}{\memglodesc{(\ref {facet.numpunct.members})}} {\memgloref{}}|memjustarg}{1596} -\glossaryentry{facet.numpunct.virtuals@ {\memgloterm{facet.numpunct.virtuals}}{\memglodesc{(\ref {facet.numpunct.virtuals})}} {\memgloref{}}|memjustarg}{1596} -\glossaryentry{locale.numpunct.byname@ {\memgloterm{locale.numpunct.byname}}{\memglodesc{(\ref {locale.numpunct.byname})}} {\memgloref{}}|memjustarg}{1596} -\glossaryentry{category.collate@ {\memgloterm{category.collate}}{\memglodesc{(\ref {category.collate})}} {\memgloref{}}|memjustarg}{1597} -\glossaryentry{locale.collate@ {\memgloterm{locale.collate}}{\memglodesc{(\ref {locale.collate})}} {\memgloref{}}|memjustarg}{1597} -\glossaryentry{locale.collate.general@ {\memgloterm{locale.collate.general}}{\memglodesc{(\ref {locale.collate.general})}} {\memgloref{}}|memjustarg}{1597} -\glossaryentry{locale.collate.members@ {\memgloterm{locale.collate.members}}{\memglodesc{(\ref {locale.collate.members})}} {\memgloref{}}|memjustarg}{1597} -\glossaryentry{locale.collate.virtuals@ {\memgloterm{locale.collate.virtuals}}{\memglodesc{(\ref {locale.collate.virtuals})}} {\memgloref{}}|memjustarg}{1597} -\glossaryentry{locale.collate.byname@ {\memgloterm{locale.collate.byname}}{\memglodesc{(\ref {locale.collate.byname})}} {\memgloref{}}|memjustarg}{1598} -\glossaryentry{category.time@ {\memgloterm{category.time}}{\memglodesc{(\ref {category.time})}} {\memgloref{}}|memjustarg}{1598} -\glossaryentry{category.time.general@ {\memgloterm{category.time.general}}{\memglodesc{(\ref {category.time.general})}} {\memgloref{}}|memjustarg}{1598} -\glossaryentry{locale.time.get@ {\memgloterm{locale.time.get}}{\memglodesc{(\ref {locale.time.get})}} {\memgloref{}}|memjustarg}{1598} -\glossaryentry{locale.time.get.general@ {\memgloterm{locale.time.get.general}}{\memglodesc{(\ref {locale.time.get.general})}} {\memgloref{}}|memjustarg}{1598} -\glossaryentry{locale.time.get.members@ {\memgloterm{locale.time.get.members}}{\memglodesc{(\ref {locale.time.get.members})}} {\memgloref{}}|memjustarg}{1599} -\glossaryentry{locale.time.get.virtuals@ {\memgloterm{locale.time.get.virtuals}}{\memglodesc{(\ref {locale.time.get.virtuals})}} {\memgloref{}}|memjustarg}{1600} -\glossaryentry{locale.time.get.byname@ {\memgloterm{locale.time.get.byname}}{\memglodesc{(\ref {locale.time.get.byname})}} {\memgloref{}}|memjustarg}{1601} -\glossaryentry{locale.time.put@ {\memgloterm{locale.time.put}}{\memglodesc{(\ref {locale.time.put})}} {\memgloref{}}|memjustarg}{1602} -\glossaryentry{locale.time.put.members@ {\memgloterm{locale.time.put.members}}{\memglodesc{(\ref {locale.time.put.members})}} {\memgloref{}}|memjustarg}{1602} -\glossaryentry{locale.time.put.virtuals@ {\memgloterm{locale.time.put.virtuals}}{\memglodesc{(\ref {locale.time.put.virtuals})}} {\memgloref{}}|memjustarg}{1603} -\glossaryentry{locale.time.put.byname@ {\memgloterm{locale.time.put.byname}}{\memglodesc{(\ref {locale.time.put.byname})}} {\memgloref{}}|memjustarg}{1603} -\glossaryentry{category.monetary@ {\memgloterm{category.monetary}}{\memglodesc{(\ref {category.monetary})}} {\memgloref{}}|memjustarg}{1603} -\glossaryentry{category.monetary.general@ {\memgloterm{category.monetary.general}}{\memglodesc{(\ref {category.monetary.general})}} {\memgloref{}}|memjustarg}{1603} -\glossaryentry{locale.money.get@ {\memgloterm{locale.money.get}}{\memglodesc{(\ref {locale.money.get})}} {\memgloref{}}|memjustarg}{1603} -\glossaryentry{locale.money.get.members@ {\memgloterm{locale.money.get.members}}{\memglodesc{(\ref {locale.money.get.members})}} {\memgloref{}}|memjustarg}{1604} -\glossaryentry{locale.money.get.virtuals@ {\memgloterm{locale.money.get.virtuals}}{\memglodesc{(\ref {locale.money.get.virtuals})}} {\memgloref{}}|memjustarg}{1604} -\glossaryentry{locale.money.put@ {\memgloterm{locale.money.put}}{\memglodesc{(\ref {locale.money.put})}} {\memgloref{}}|memjustarg}{1605} -\glossaryentry{locale.money.put.members@ {\memgloterm{locale.money.put.members}}{\memglodesc{(\ref {locale.money.put.members})}} {\memgloref{}}|memjustarg}{1605} -\glossaryentry{locale.money.put.virtuals@ {\memgloterm{locale.money.put.virtuals}}{\memglodesc{(\ref {locale.money.put.virtuals})}} {\memgloref{}}|memjustarg}{1605} -\glossaryentry{locale.moneypunct@ {\memgloterm{locale.moneypunct}}{\memglodesc{(\ref {locale.moneypunct})}} {\memgloref{}}|memjustarg}{1606} -\glossaryentry{locale.moneypunct.general@ {\memgloterm{locale.moneypunct.general}}{\memglodesc{(\ref {locale.moneypunct.general})}} {\memgloref{}}|memjustarg}{1606} -\glossaryentry{locale.moneypunct.members@ {\memgloterm{locale.moneypunct.members}}{\memglodesc{(\ref {locale.moneypunct.members})}} {\memgloref{}}|memjustarg}{1607} -\glossaryentry{locale.moneypunct.virtuals@ {\memgloterm{locale.moneypunct.virtuals}}{\memglodesc{(\ref {locale.moneypunct.virtuals})}} {\memgloref{}}|memjustarg}{1607} -\glossaryentry{locale.moneypunct.byname@ {\memgloterm{locale.moneypunct.byname}}{\memglodesc{(\ref {locale.moneypunct.byname})}} {\memgloref{}}|memjustarg}{1608} -\glossaryentry{category.messages@ {\memgloterm{category.messages}}{\memglodesc{(\ref {category.messages})}} {\memgloref{}}|memjustarg}{1608} -\glossaryentry{category.messages.general@ {\memgloterm{category.messages.general}}{\memglodesc{(\ref {category.messages.general})}} {\memgloref{}}|memjustarg}{1608} -\glossaryentry{locale.messages@ {\memgloterm{locale.messages}}{\memglodesc{(\ref {locale.messages})}} {\memgloref{}}|memjustarg}{1609} -\glossaryentry{locale.messages.general@ {\memgloterm{locale.messages.general}}{\memglodesc{(\ref {locale.messages.general})}} {\memgloref{}}|memjustarg}{1609} -\glossaryentry{locale.messages.members@ {\memgloterm{locale.messages.members}}{\memglodesc{(\ref {locale.messages.members})}} {\memgloref{}}|memjustarg}{1609} -\glossaryentry{locale.messages.virtuals@ {\memgloterm{locale.messages.virtuals}}{\memglodesc{(\ref {locale.messages.virtuals})}} {\memgloref{}}|memjustarg}{1609} -\glossaryentry{locale.messages.byname@ {\memgloterm{locale.messages.byname}}{\memglodesc{(\ref {locale.messages.byname})}} {\memgloref{}}|memjustarg}{1610} -\glossaryentry{c.locales@ {\memgloterm{c.locales}}{\memglodesc{(\ref {c.locales})}} {\memgloref{}}|memjustarg}{1610} -\glossaryentry{clocale.syn@ {\memgloterm{clocale.syn}}{\memglodesc{(\ref {clocale.syn})}} {\memgloref{}}|memjustarg}{1610} -\glossaryentry{clocale.data.races@ {\memgloterm{clocale.data.races}}{\memglodesc{(\ref {clocale.data.races})}} {\memgloref{}}|memjustarg}{1610} -\glossaryentry{input.output@ {\memgloterm{input.output}}{\memglodesc{(\ref {input.output})}} {\memgloref{}}|memjustarg}{1611} -\glossaryentry{input.output.general@ {\memgloterm{input.output.general}}{\memglodesc{(\ref {input.output.general})}} {\memgloref{}}|memjustarg}{1611} -\glossaryentry{iostreams.requirements@ {\memgloterm{iostreams.requirements}}{\memglodesc{(\ref {iostreams.requirements})}} {\memgloref{}}|memjustarg}{1611} -\glossaryentry{iostream.limits.imbue@ {\memgloterm{iostream.limits.imbue}}{\memglodesc{(\ref {iostream.limits.imbue})}} {\memgloref{}}|memjustarg}{1611} -\glossaryentry{stream.types@ {\memgloterm{stream.types}}{\memglodesc{(\ref {stream.types})}} {\memgloref{}}|memjustarg}{1611} -\glossaryentry{iostreams.limits.pos@ {\memgloterm{iostreams.limits.pos}}{\memglodesc{(\ref {iostreams.limits.pos})}} {\memgloref{}}|memjustarg}{1611} -\glossaryentry{iostreams.threadsafety@ {\memgloterm{iostreams.threadsafety}}{\memglodesc{(\ref {iostreams.threadsafety})}} {\memgloref{}}|memjustarg}{1612} -\glossaryentry{iostream.forward@ {\memgloterm{iostream.forward}}{\memglodesc{(\ref {iostream.forward})}} {\memgloref{}}|memjustarg}{1612} -\glossaryentry{iosfwd.syn@ {\memgloterm{iosfwd.syn}}{\memglodesc{(\ref {iosfwd.syn})}} {\memgloref{}}|memjustarg}{1612} -\glossaryentry{iostream.forward.overview@ {\memgloterm{iostream.forward.overview}}{\memglodesc{(\ref {iostream.forward.overview})}} {\memgloref{}}|memjustarg}{1614} -\glossaryentry{iostream.objects@ {\memgloterm{iostream.objects}}{\memglodesc{(\ref {iostream.objects})}} {\memgloref{}}|memjustarg}{1614} -\glossaryentry{iostream.syn@ {\memgloterm{iostream.syn}}{\memglodesc{(\ref {iostream.syn})}} {\memgloref{}}|memjustarg}{1614} -\glossaryentry{iostream.objects.overview@ {\memgloterm{iostream.objects.overview}}{\memglodesc{(\ref {iostream.objects.overview})}} {\memgloref{}}|memjustarg}{1614} -\glossaryentry{narrow.stream.objects@ {\memgloterm{narrow.stream.objects}}{\memglodesc{(\ref {narrow.stream.objects})}} {\memgloref{}}|memjustarg}{1615} -\glossaryentry{wide.stream.objects@ {\memgloterm{wide.stream.objects}}{\memglodesc{(\ref {wide.stream.objects})}} {\memgloref{}}|memjustarg}{1615} -\glossaryentry{iostreams.base@ {\memgloterm{iostreams.base}}{\memglodesc{(\ref {iostreams.base})}} {\memgloref{}}|memjustarg}{1616} -\glossaryentry{ios.syn@ {\memgloterm{ios.syn}}{\memglodesc{(\ref {ios.syn})}} {\memgloref{}}|memjustarg}{1616} -\glossaryentry{ios.base@ {\memgloterm{ios.base}}{\memglodesc{(\ref {ios.base})}} {\memgloref{}}|memjustarg}{1617} -\glossaryentry{ios.base.general@ {\memgloterm{ios.base.general}}{\memglodesc{(\ref {ios.base.general})}} {\memgloref{}}|memjustarg}{1617} -\glossaryentry{ios.types@ {\memgloterm{ios.types}}{\memglodesc{(\ref {ios.types})}} {\memgloref{}}|memjustarg}{1619} -\glossaryentry{ios.failure@ {\memgloterm{ios.failure}}{\memglodesc{(\ref {ios.failure})}} {\memgloref{}}|memjustarg}{1619} -\glossaryentry{ios.fmtflags@ {\memgloterm{ios.fmtflags}}{\memglodesc{(\ref {ios.fmtflags})}} {\memgloref{}}|memjustarg}{1619} -\glossaryentry{ios.iostate@ {\memgloterm{ios.iostate}}{\memglodesc{(\ref {ios.iostate})}} {\memgloref{}}|memjustarg}{1619} -\glossaryentry{ios.openmode@ {\memgloterm{ios.openmode}}{\memglodesc{(\ref {ios.openmode})}} {\memgloref{}}|memjustarg}{1619} -\glossaryentry{ios.seekdir@ {\memgloterm{ios.seekdir}}{\memglodesc{(\ref {ios.seekdir})}} {\memgloref{}}|memjustarg}{1619} -\glossaryentry{ios.init@ {\memgloterm{ios.init}}{\memglodesc{(\ref {ios.init})}} {\memgloref{}}|memjustarg}{1621} -\glossaryentry{fmtflags.state@ {\memgloterm{fmtflags.state}}{\memglodesc{(\ref {fmtflags.state})}} {\memgloref{}}|memjustarg}{1621} -\glossaryentry{ios.base.locales@ {\memgloterm{ios.base.locales}}{\memglodesc{(\ref {ios.base.locales})}} {\memgloref{}}|memjustarg}{1622} -\glossaryentry{ios.members.static@ {\memgloterm{ios.members.static}}{\memglodesc{(\ref {ios.members.static})}} {\memgloref{}}|memjustarg}{1622} -\glossaryentry{ios.base.storage@ {\memgloterm{ios.base.storage}}{\memglodesc{(\ref {ios.base.storage})}} {\memgloref{}}|memjustarg}{1622} -\glossaryentry{ios.base.callback@ {\memgloterm{ios.base.callback}}{\memglodesc{(\ref {ios.base.callback})}} {\memgloref{}}|memjustarg}{1623} -\glossaryentry{ios.base.cons@ {\memgloterm{ios.base.cons}}{\memglodesc{(\ref {ios.base.cons})}} {\memgloref{}}|memjustarg}{1623} -\glossaryentry{fpos@ {\memgloterm{fpos}}{\memglodesc{(\ref {fpos})}} {\memgloref{}}|memjustarg}{1623} -\glossaryentry{fpos.members@ {\memgloterm{fpos.members}}{\memglodesc{(\ref {fpos.members})}} {\memgloref{}}|memjustarg}{1624} -\glossaryentry{fpos.operations@ {\memgloterm{fpos.operations}}{\memglodesc{(\ref {fpos.operations})}} {\memgloref{}}|memjustarg}{1624} -\glossaryentry{ios@ {\memgloterm{ios}}{\memglodesc{(\ref {ios})}} {\memgloref{}}|memjustarg}{1625} -\glossaryentry{ios.overview@ {\memgloterm{ios.overview}}{\memglodesc{(\ref {ios.overview})}} {\memgloref{}}|memjustarg}{1625} -\glossaryentry{basic.ios.cons@ {\memgloterm{basic.ios.cons}}{\memglodesc{(\ref {basic.ios.cons})}} {\memgloref{}}|memjustarg}{1626} -\glossaryentry{basic.ios.members@ {\memgloterm{basic.ios.members}}{\memglodesc{(\ref {basic.ios.members})}} {\memgloref{}}|memjustarg}{1626} -\glossaryentry{iostate.flags@ {\memgloterm{iostate.flags}}{\memglodesc{(\ref {iostate.flags})}} {\memgloref{}}|memjustarg}{1628} -\glossaryentry{std.ios.manip@ {\memgloterm{std.ios.manip}}{\memglodesc{(\ref {std.ios.manip})}} {\memgloref{}}|memjustarg}{1629} -\glossaryentry{fmtflags.manip@ {\memgloterm{fmtflags.manip}}{\memglodesc{(\ref {fmtflags.manip})}} {\memgloref{}}|memjustarg}{1629} -\glossaryentry{adjustfield.manip@ {\memgloterm{adjustfield.manip}}{\memglodesc{(\ref {adjustfield.manip})}} {\memgloref{}}|memjustarg}{1630} -\glossaryentry{basefield.manip@ {\memgloterm{basefield.manip}}{\memglodesc{(\ref {basefield.manip})}} {\memgloref{}}|memjustarg}{1630} -\glossaryentry{floatfield.manip@ {\memgloterm{floatfield.manip}}{\memglodesc{(\ref {floatfield.manip})}} {\memgloref{}}|memjustarg}{1630} -\glossaryentry{error.reporting@ {\memgloterm{error.reporting}}{\memglodesc{(\ref {error.reporting})}} {\memgloref{}}|memjustarg}{1631} -\glossaryentry{stream.buffers@ {\memgloterm{stream.buffers}}{\memglodesc{(\ref {stream.buffers})}} {\memgloref{}}|memjustarg}{1631} -\glossaryentry{streambuf.syn@ {\memgloterm{streambuf.syn}}{\memglodesc{(\ref {streambuf.syn})}} {\memgloref{}}|memjustarg}{1631} -\glossaryentry{streambuf.reqts@ {\memgloterm{streambuf.reqts}}{\memglodesc{(\ref {streambuf.reqts})}} {\memgloref{}}|memjustarg}{1631} -\glossaryentry{streambuf@ {\memgloterm{streambuf}}{\memglodesc{(\ref {streambuf})}} {\memgloref{}}|memjustarg}{1632} -\glossaryentry{streambuf.general@ {\memgloterm{streambuf.general}}{\memglodesc{(\ref {streambuf.general})}} {\memgloref{}}|memjustarg}{1632} -\glossaryentry{streambuf.cons@ {\memgloterm{streambuf.cons}}{\memglodesc{(\ref {streambuf.cons})}} {\memgloref{}}|memjustarg}{1633} -\glossaryentry{streambuf.members@ {\memgloterm{streambuf.members}}{\memglodesc{(\ref {streambuf.members})}} {\memgloref{}}|memjustarg}{1634} -\glossaryentry{streambuf.locales@ {\memgloterm{streambuf.locales}}{\memglodesc{(\ref {streambuf.locales})}} {\memgloref{}}|memjustarg}{1634} -\glossaryentry{streambuf.buffer@ {\memgloterm{streambuf.buffer}}{\memglodesc{(\ref {streambuf.buffer})}} {\memgloref{}}|memjustarg}{1634} -\glossaryentry{streambuf.pub.get@ {\memgloterm{streambuf.pub.get}}{\memglodesc{(\ref {streambuf.pub.get})}} {\memgloref{}}|memjustarg}{1634} -\glossaryentry{streambuf.pub.pback@ {\memgloterm{streambuf.pub.pback}}{\memglodesc{(\ref {streambuf.pub.pback})}} {\memgloref{}}|memjustarg}{1635} -\glossaryentry{streambuf.pub.put@ {\memgloterm{streambuf.pub.put}}{\memglodesc{(\ref {streambuf.pub.put})}} {\memgloref{}}|memjustarg}{1635} -\glossaryentry{streambuf.protected@ {\memgloterm{streambuf.protected}}{\memglodesc{(\ref {streambuf.protected})}} {\memgloref{}}|memjustarg}{1635} -\glossaryentry{streambuf.assign@ {\memgloterm{streambuf.assign}}{\memglodesc{(\ref {streambuf.assign})}} {\memgloref{}}|memjustarg}{1635} -\glossaryentry{streambuf.get.area@ {\memgloterm{streambuf.get.area}}{\memglodesc{(\ref {streambuf.get.area})}} {\memgloref{}}|memjustarg}{1636} -\glossaryentry{streambuf.put.area@ {\memgloterm{streambuf.put.area}}{\memglodesc{(\ref {streambuf.put.area})}} {\memgloref{}}|memjustarg}{1636} -\glossaryentry{streambuf.virtuals@ {\memgloterm{streambuf.virtuals}}{\memglodesc{(\ref {streambuf.virtuals})}} {\memgloref{}}|memjustarg}{1636} -\glossaryentry{streambuf.virt.locales@ {\memgloterm{streambuf.virt.locales}}{\memglodesc{(\ref {streambuf.virt.locales})}} {\memgloref{}}|memjustarg}{1636} -\glossaryentry{streambuf.virt.buffer@ {\memgloterm{streambuf.virt.buffer}}{\memglodesc{(\ref {streambuf.virt.buffer})}} {\memgloref{}}|memjustarg}{1636} -\glossaryentry{streambuf.virt.get@ {\memgloterm{streambuf.virt.get}}{\memglodesc{(\ref {streambuf.virt.get})}} {\memgloref{}}|memjustarg}{1637} -\glossaryentry{streambuf.virt.pback@ {\memgloterm{streambuf.virt.pback}}{\memglodesc{(\ref {streambuf.virt.pback})}} {\memgloref{}}|memjustarg}{1638} -\glossaryentry{streambuf.virt.put@ {\memgloterm{streambuf.virt.put}}{\memglodesc{(\ref {streambuf.virt.put})}} {\memgloref{}}|memjustarg}{1638} -\glossaryentry{iostream.format@ {\memgloterm{iostream.format}}{\memglodesc{(\ref {iostream.format})}} {\memgloref{}}|memjustarg}{1639} -\glossaryentry{istream.syn@ {\memgloterm{istream.syn}}{\memglodesc{(\ref {istream.syn})}} {\memgloref{}}|memjustarg}{1639} -\glossaryentry{ostream.syn@ {\memgloterm{ostream.syn}}{\memglodesc{(\ref {ostream.syn})}} {\memgloref{}}|memjustarg}{1639} -\glossaryentry{iomanip.syn@ {\memgloterm{iomanip.syn}}{\memglodesc{(\ref {iomanip.syn})}} {\memgloref{}}|memjustarg}{1640} -\glossaryentry{print.syn@ {\memgloterm{print.syn}}{\memglodesc{(\ref {print.syn})}} {\memgloref{}}|memjustarg}{1640} -\glossaryentry{input.streams@ {\memgloterm{input.streams}}{\memglodesc{(\ref {input.streams})}} {\memgloref{}}|memjustarg}{1641} -\glossaryentry{input.streams.general@ {\memgloterm{input.streams.general}}{\memglodesc{(\ref {input.streams.general})}} {\memgloref{}}|memjustarg}{1641} -\glossaryentry{istream@ {\memgloterm{istream}}{\memglodesc{(\ref {istream})}} {\memgloref{}}|memjustarg}{1641} -\glossaryentry{istream.general@ {\memgloterm{istream.general}}{\memglodesc{(\ref {istream.general})}} {\memgloref{}}|memjustarg}{1641} -\glossaryentry{istream.cons@ {\memgloterm{istream.cons}}{\memglodesc{(\ref {istream.cons})}} {\memgloref{}}|memjustarg}{1642} -\glossaryentry{istream.assign@ {\memgloterm{istream.assign}}{\memglodesc{(\ref {istream.assign})}} {\memgloref{}}|memjustarg}{1643} -\glossaryentry{istream.sentry@ {\memgloterm{istream.sentry}}{\memglodesc{(\ref {istream.sentry})}} {\memgloref{}}|memjustarg}{1643} -\glossaryentry{istream.formatted@ {\memgloterm{istream.formatted}}{\memglodesc{(\ref {istream.formatted})}} {\memgloref{}}|memjustarg}{1644} -\glossaryentry{istream.formatted.reqmts@ {\memgloterm{istream.formatted.reqmts}}{\memglodesc{(\ref {istream.formatted.reqmts})}} {\memgloref{}}|memjustarg}{1644} -\glossaryentry{istream.formatted.arithmetic@ {\memgloterm{istream.formatted.arithmetic}}{\memglodesc{(\ref {istream.formatted.arithmetic})}} {\memgloref{}}|memjustarg}{1644} -\glossaryentry{istream.extractors@ {\memgloterm{istream.extractors}}{\memglodesc{(\ref {istream.extractors})}} {\memgloref{}}|memjustarg}{1645} -\glossaryentry{istream.unformatted@ {\memgloterm{istream.unformatted}}{\memglodesc{(\ref {istream.unformatted})}} {\memgloref{}}|memjustarg}{1646} -\glossaryentry{istream.manip@ {\memgloterm{istream.manip}}{\memglodesc{(\ref {istream.manip})}} {\memgloref{}}|memjustarg}{1650} -\glossaryentry{istream.rvalue@ {\memgloterm{istream.rvalue}}{\memglodesc{(\ref {istream.rvalue})}} {\memgloref{}}|memjustarg}{1651} -\glossaryentry{iostreamclass@ {\memgloterm{iostreamclass}}{\memglodesc{(\ref {iostreamclass})}} {\memgloref{}}|memjustarg}{1651} -\glossaryentry{iostreamclass.general@ {\memgloterm{iostreamclass.general}}{\memglodesc{(\ref {iostreamclass.general})}} {\memgloref{}}|memjustarg}{1651} -\glossaryentry{iostream.cons@ {\memgloterm{iostream.cons}}{\memglodesc{(\ref {iostream.cons})}} {\memgloref{}}|memjustarg}{1651} -\glossaryentry{iostream.dest@ {\memgloterm{iostream.dest}}{\memglodesc{(\ref {iostream.dest})}} {\memgloref{}}|memjustarg}{1651} -\glossaryentry{iostream.assign@ {\memgloterm{iostream.assign}}{\memglodesc{(\ref {iostream.assign})}} {\memgloref{}}|memjustarg}{1652} -\glossaryentry{output.streams@ {\memgloterm{output.streams}}{\memglodesc{(\ref {output.streams})}} {\memgloref{}}|memjustarg}{1652} -\glossaryentry{output.streams.general@ {\memgloterm{output.streams.general}}{\memglodesc{(\ref {output.streams.general})}} {\memgloref{}}|memjustarg}{1652} -\glossaryentry{ostream@ {\memgloterm{ostream}}{\memglodesc{(\ref {ostream})}} {\memgloref{}}|memjustarg}{1652} -\glossaryentry{ostream.general@ {\memgloterm{ostream.general}}{\memglodesc{(\ref {ostream.general})}} {\memgloref{}}|memjustarg}{1652} -\glossaryentry{ostream.cons@ {\memgloterm{ostream.cons}}{\memglodesc{(\ref {ostream.cons})}} {\memgloref{}}|memjustarg}{1654} -\glossaryentry{ostream.assign@ {\memgloterm{ostream.assign}}{\memglodesc{(\ref {ostream.assign})}} {\memgloref{}}|memjustarg}{1654} -\glossaryentry{ostream.sentry@ {\memgloterm{ostream.sentry}}{\memglodesc{(\ref {ostream.sentry})}} {\memgloref{}}|memjustarg}{1654} -\glossaryentry{ostream.seeks@ {\memgloterm{ostream.seeks}}{\memglodesc{(\ref {ostream.seeks})}} {\memgloref{}}|memjustarg}{1655} -\glossaryentry{ostream.formatted@ {\memgloterm{ostream.formatted}}{\memglodesc{(\ref {ostream.formatted})}} {\memgloref{}}|memjustarg}{1655} -\glossaryentry{ostream.formatted.reqmts@ {\memgloterm{ostream.formatted.reqmts}}{\memglodesc{(\ref {ostream.formatted.reqmts})}} {\memgloref{}}|memjustarg}{1655} -\glossaryentry{ostream.inserters.arithmetic@ {\memgloterm{ostream.inserters.arithmetic}}{\memglodesc{(\ref {ostream.inserters.arithmetic})}} {\memgloref{}}|memjustarg}{1656} -\glossaryentry{ostream.inserters@ {\memgloterm{ostream.inserters}}{\memglodesc{(\ref {ostream.inserters})}} {\memgloref{}}|memjustarg}{1657} -\glossaryentry{ostream.inserters.character@ {\memgloterm{ostream.inserters.character}}{\memglodesc{(\ref {ostream.inserters.character})}} {\memgloref{}}|memjustarg}{1658} -\glossaryentry{ostream.formatted.print@ {\memgloterm{ostream.formatted.print}}{\memglodesc{(\ref {ostream.formatted.print})}} {\memgloref{}}|memjustarg}{1659} -\glossaryentry{ostream.unformatted@ {\memgloterm{ostream.unformatted}}{\memglodesc{(\ref {ostream.unformatted})}} {\memgloref{}}|memjustarg}{1659} -\glossaryentry{ostream.manip@ {\memgloterm{ostream.manip}}{\memglodesc{(\ref {ostream.manip})}} {\memgloref{}}|memjustarg}{1660} -\glossaryentry{ostream.rvalue@ {\memgloterm{ostream.rvalue}}{\memglodesc{(\ref {ostream.rvalue})}} {\memgloref{}}|memjustarg}{1660} -\glossaryentry{std.manip@ {\memgloterm{std.manip}}{\memglodesc{(\ref {std.manip})}} {\memgloref{}}|memjustarg}{1661} -\glossaryentry{ext.manip@ {\memgloterm{ext.manip}}{\memglodesc{(\ref {ext.manip})}} {\memgloref{}}|memjustarg}{1662} -\glossaryentry{quoted.manip@ {\memgloterm{quoted.manip}}{\memglodesc{(\ref {quoted.manip})}} {\memgloref{}}|memjustarg}{1664} -\glossaryentry{print.fun@ {\memgloterm{print.fun}}{\memglodesc{(\ref {print.fun})}} {\memgloref{}}|memjustarg}{1665} -\glossaryentry{string.streams@ {\memgloterm{string.streams}}{\memglodesc{(\ref {string.streams})}} {\memgloref{}}|memjustarg}{1666} -\glossaryentry{sstream.syn@ {\memgloterm{sstream.syn}}{\memglodesc{(\ref {sstream.syn})}} {\memgloref{}}|memjustarg}{1666} -\glossaryentry{stringbuf@ {\memgloterm{stringbuf}}{\memglodesc{(\ref {stringbuf})}} {\memgloref{}}|memjustarg}{1667} -\glossaryentry{stringbuf.general@ {\memgloterm{stringbuf.general}}{\memglodesc{(\ref {stringbuf.general})}} {\memgloref{}}|memjustarg}{1667} -\glossaryentry{stringbuf.cons@ {\memgloterm{stringbuf.cons}}{\memglodesc{(\ref {stringbuf.cons})}} {\memgloref{}}|memjustarg}{1668} -\glossaryentry{stringbuf.assign@ {\memgloterm{stringbuf.assign}}{\memglodesc{(\ref {stringbuf.assign})}} {\memgloref{}}|memjustarg}{1669} -\glossaryentry{stringbuf.members@ {\memgloterm{stringbuf.members}}{\memglodesc{(\ref {stringbuf.members})}} {\memgloref{}}|memjustarg}{1670} -\glossaryentry{stringbuf.virtuals@ {\memgloterm{stringbuf.virtuals}}{\memglodesc{(\ref {stringbuf.virtuals})}} {\memgloref{}}|memjustarg}{1671} -\glossaryentry{istringstream@ {\memgloterm{istringstream}}{\memglodesc{(\ref {istringstream})}} {\memgloref{}}|memjustarg}{1672} -\glossaryentry{istringstream.general@ {\memgloterm{istringstream.general}}{\memglodesc{(\ref {istringstream.general})}} {\memgloref{}}|memjustarg}{1672} -\glossaryentry{istringstream.cons@ {\memgloterm{istringstream.cons}}{\memglodesc{(\ref {istringstream.cons})}} {\memgloref{}}|memjustarg}{1674} -\glossaryentry{istringstream.swap@ {\memgloterm{istringstream.swap}}{\memglodesc{(\ref {istringstream.swap})}} {\memgloref{}}|memjustarg}{1674} -\glossaryentry{istringstream.members@ {\memgloterm{istringstream.members}}{\memglodesc{(\ref {istringstream.members})}} {\memgloref{}}|memjustarg}{1674} -\glossaryentry{ostringstream@ {\memgloterm{ostringstream}}{\memglodesc{(\ref {ostringstream})}} {\memgloref{}}|memjustarg}{1675} -\glossaryentry{ostringstream.general@ {\memgloterm{ostringstream.general}}{\memglodesc{(\ref {ostringstream.general})}} {\memgloref{}}|memjustarg}{1675} -\glossaryentry{ostringstream.cons@ {\memgloterm{ostringstream.cons}}{\memglodesc{(\ref {ostringstream.cons})}} {\memgloref{}}|memjustarg}{1676} -\glossaryentry{ostringstream.swap@ {\memgloterm{ostringstream.swap}}{\memglodesc{(\ref {ostringstream.swap})}} {\memgloref{}}|memjustarg}{1677} -\glossaryentry{ostringstream.members@ {\memgloterm{ostringstream.members}}{\memglodesc{(\ref {ostringstream.members})}} {\memgloref{}}|memjustarg}{1677} -\glossaryentry{stringstream@ {\memgloterm{stringstream}}{\memglodesc{(\ref {stringstream})}} {\memgloref{}}|memjustarg}{1677} -\glossaryentry{stringstream.general@ {\memgloterm{stringstream.general}}{\memglodesc{(\ref {stringstream.general})}} {\memgloref{}}|memjustarg}{1677} -\glossaryentry{stringstream.cons@ {\memgloterm{stringstream.cons}}{\memglodesc{(\ref {stringstream.cons})}} {\memgloref{}}|memjustarg}{1679} -\glossaryentry{stringstream.swap@ {\memgloterm{stringstream.swap}}{\memglodesc{(\ref {stringstream.swap})}} {\memgloref{}}|memjustarg}{1679} -\glossaryentry{stringstream.members@ {\memgloterm{stringstream.members}}{\memglodesc{(\ref {stringstream.members})}} {\memgloref{}}|memjustarg}{1679} -\glossaryentry{span.streams@ {\memgloterm{span.streams}}{\memglodesc{(\ref {span.streams})}} {\memgloref{}}|memjustarg}{1680} -\glossaryentry{span.streams.overview@ {\memgloterm{span.streams.overview}}{\memglodesc{(\ref {span.streams.overview})}} {\memgloref{}}|memjustarg}{1680} -\glossaryentry{spanstream.syn@ {\memgloterm{spanstream.syn}}{\memglodesc{(\ref {spanstream.syn})}} {\memgloref{}}|memjustarg}{1680} -\glossaryentry{spanbuf@ {\memgloterm{spanbuf}}{\memglodesc{(\ref {spanbuf})}} {\memgloref{}}|memjustarg}{1681} -\glossaryentry{spanbuf.general@ {\memgloterm{spanbuf.general}}{\memglodesc{(\ref {spanbuf.general})}} {\memgloref{}}|memjustarg}{1681} -\glossaryentry{spanbuf.cons@ {\memgloterm{spanbuf.cons}}{\memglodesc{(\ref {spanbuf.cons})}} {\memgloref{}}|memjustarg}{1682} -\glossaryentry{spanbuf.assign@ {\memgloterm{spanbuf.assign}}{\memglodesc{(\ref {spanbuf.assign})}} {\memgloref{}}|memjustarg}{1682} -\glossaryentry{spanbuf.members@ {\memgloterm{spanbuf.members}}{\memglodesc{(\ref {spanbuf.members})}} {\memgloref{}}|memjustarg}{1682} -\glossaryentry{spanbuf.virtuals@ {\memgloterm{spanbuf.virtuals}}{\memglodesc{(\ref {spanbuf.virtuals})}} {\memgloref{}}|memjustarg}{1683} -\glossaryentry{ispanstream@ {\memgloterm{ispanstream}}{\memglodesc{(\ref {ispanstream})}} {\memgloref{}}|memjustarg}{1683} -\glossaryentry{ispanstream.general@ {\memgloterm{ispanstream.general}}{\memglodesc{(\ref {ispanstream.general})}} {\memgloref{}}|memjustarg}{1683} -\glossaryentry{ispanstream.cons@ {\memgloterm{ispanstream.cons}}{\memglodesc{(\ref {ispanstream.cons})}} {\memgloref{}}|memjustarg}{1684} -\glossaryentry{ispanstream.swap@ {\memgloterm{ispanstream.swap}}{\memglodesc{(\ref {ispanstream.swap})}} {\memgloref{}}|memjustarg}{1684} -\glossaryentry{ispanstream.members@ {\memgloterm{ispanstream.members}}{\memglodesc{(\ref {ispanstream.members})}} {\memgloref{}}|memjustarg}{1684} -\glossaryentry{ospanstream@ {\memgloterm{ospanstream}}{\memglodesc{(\ref {ospanstream})}} {\memgloref{}}|memjustarg}{1685} -\glossaryentry{ospanstream.general@ {\memgloterm{ospanstream.general}}{\memglodesc{(\ref {ospanstream.general})}} {\memgloref{}}|memjustarg}{1685} -\glossaryentry{ospanstream.cons@ {\memgloterm{ospanstream.cons}}{\memglodesc{(\ref {ospanstream.cons})}} {\memgloref{}}|memjustarg}{1685} -\glossaryentry{ospanstream.swap@ {\memgloterm{ospanstream.swap}}{\memglodesc{(\ref {ospanstream.swap})}} {\memgloref{}}|memjustarg}{1686} -\glossaryentry{ospanstream.members@ {\memgloterm{ospanstream.members}}{\memglodesc{(\ref {ospanstream.members})}} {\memgloref{}}|memjustarg}{1686} -\glossaryentry{spanstream@ {\memgloterm{spanstream}}{\memglodesc{(\ref {spanstream})}} {\memgloref{}}|memjustarg}{1686} -\glossaryentry{spanstream.general@ {\memgloterm{spanstream.general}}{\memglodesc{(\ref {spanstream.general})}} {\memgloref{}}|memjustarg}{1686} -\glossaryentry{spanstream.cons@ {\memgloterm{spanstream.cons}}{\memglodesc{(\ref {spanstream.cons})}} {\memgloref{}}|memjustarg}{1687} -\glossaryentry{spanstream.swap@ {\memgloterm{spanstream.swap}}{\memglodesc{(\ref {spanstream.swap})}} {\memgloref{}}|memjustarg}{1687} -\glossaryentry{spanstream.members@ {\memgloterm{spanstream.members}}{\memglodesc{(\ref {spanstream.members})}} {\memgloref{}}|memjustarg}{1687} -\glossaryentry{file.streams@ {\memgloterm{file.streams}}{\memglodesc{(\ref {file.streams})}} {\memgloref{}}|memjustarg}{1687} -\glossaryentry{fstream.syn@ {\memgloterm{fstream.syn}}{\memglodesc{(\ref {fstream.syn})}} {\memgloref{}}|memjustarg}{1687} -\glossaryentry{filebuf@ {\memgloterm{filebuf}}{\memglodesc{(\ref {filebuf})}} {\memgloref{}}|memjustarg}{1688} -\glossaryentry{filebuf.general@ {\memgloterm{filebuf.general}}{\memglodesc{(\ref {filebuf.general})}} {\memgloref{}}|memjustarg}{1688} -\glossaryentry{filebuf.cons@ {\memgloterm{filebuf.cons}}{\memglodesc{(\ref {filebuf.cons})}} {\memgloref{}}|memjustarg}{1689} -\glossaryentry{filebuf.assign@ {\memgloterm{filebuf.assign}}{\memglodesc{(\ref {filebuf.assign})}} {\memgloref{}}|memjustarg}{1690} -\glossaryentry{filebuf.members@ {\memgloterm{filebuf.members}}{\memglodesc{(\ref {filebuf.members})}} {\memgloref{}}|memjustarg}{1690} -\glossaryentry{filebuf.virtuals@ {\memgloterm{filebuf.virtuals}}{\memglodesc{(\ref {filebuf.virtuals})}} {\memgloref{}}|memjustarg}{1691} -\glossaryentry{ifstream@ {\memgloterm{ifstream}}{\memglodesc{(\ref {ifstream})}} {\memgloref{}}|memjustarg}{1693} -\glossaryentry{ifstream.general@ {\memgloterm{ifstream.general}}{\memglodesc{(\ref {ifstream.general})}} {\memgloref{}}|memjustarg}{1693} -\glossaryentry{ifstream.cons@ {\memgloterm{ifstream.cons}}{\memglodesc{(\ref {ifstream.cons})}} {\memgloref{}}|memjustarg}{1694} -\glossaryentry{ifstream.swap@ {\memgloterm{ifstream.swap}}{\memglodesc{(\ref {ifstream.swap})}} {\memgloref{}}|memjustarg}{1695} -\glossaryentry{ifstream.members@ {\memgloterm{ifstream.members}}{\memglodesc{(\ref {ifstream.members})}} {\memgloref{}}|memjustarg}{1695} -\glossaryentry{ofstream@ {\memgloterm{ofstream}}{\memglodesc{(\ref {ofstream})}} {\memgloref{}}|memjustarg}{1695} -\glossaryentry{ofstream.general@ {\memgloterm{ofstream.general}}{\memglodesc{(\ref {ofstream.general})}} {\memgloref{}}|memjustarg}{1695} -\glossaryentry{ofstream.cons@ {\memgloterm{ofstream.cons}}{\memglodesc{(\ref {ofstream.cons})}} {\memgloref{}}|memjustarg}{1696} -\glossaryentry{ofstream.swap@ {\memgloterm{ofstream.swap}}{\memglodesc{(\ref {ofstream.swap})}} {\memgloref{}}|memjustarg}{1697} -\glossaryentry{ofstream.members@ {\memgloterm{ofstream.members}}{\memglodesc{(\ref {ofstream.members})}} {\memgloref{}}|memjustarg}{1697} -\glossaryentry{fstream@ {\memgloterm{fstream}}{\memglodesc{(\ref {fstream})}} {\memgloref{}}|memjustarg}{1697} -\glossaryentry{fstream.general@ {\memgloterm{fstream.general}}{\memglodesc{(\ref {fstream.general})}} {\memgloref{}}|memjustarg}{1697} -\glossaryentry{fstream.cons@ {\memgloterm{fstream.cons}}{\memglodesc{(\ref {fstream.cons})}} {\memgloref{}}|memjustarg}{1698} -\glossaryentry{fstream.swap@ {\memgloterm{fstream.swap}}{\memglodesc{(\ref {fstream.swap})}} {\memgloref{}}|memjustarg}{1699} -\glossaryentry{fstream.members@ {\memgloterm{fstream.members}}{\memglodesc{(\ref {fstream.members})}} {\memgloref{}}|memjustarg}{1699} -\glossaryentry{syncstream@ {\memgloterm{syncstream}}{\memglodesc{(\ref {syncstream})}} {\memgloref{}}|memjustarg}{1699} -\glossaryentry{syncstream.syn@ {\memgloterm{syncstream.syn}}{\memglodesc{(\ref {syncstream.syn})}} {\memgloref{}}|memjustarg}{1699} -\glossaryentry{syncstream.syncbuf@ {\memgloterm{syncstream.syncbuf}}{\memglodesc{(\ref {syncstream.syncbuf})}} {\memgloref{}}|memjustarg}{1700} -\glossaryentry{syncstream.syncbuf.overview@ {\memgloterm{syncstream.syncbuf.overview}}{\memglodesc{(\ref {syncstream.syncbuf.overview})}} {\memgloref{}}|memjustarg}{1700} -\glossaryentry{syncstream.syncbuf.cons@ {\memgloterm{syncstream.syncbuf.cons}}{\memglodesc{(\ref {syncstream.syncbuf.cons})}} {\memgloref{}}|memjustarg}{1700} -\glossaryentry{syncstream.syncbuf.assign@ {\memgloterm{syncstream.syncbuf.assign}}{\memglodesc{(\ref {syncstream.syncbuf.assign})}} {\memgloref{}}|memjustarg}{1701} -\glossaryentry{syncstream.syncbuf.members@ {\memgloterm{syncstream.syncbuf.members}}{\memglodesc{(\ref {syncstream.syncbuf.members})}} {\memgloref{}}|memjustarg}{1701} -\glossaryentry{syncstream.syncbuf.virtuals@ {\memgloterm{syncstream.syncbuf.virtuals}}{\memglodesc{(\ref {syncstream.syncbuf.virtuals})}} {\memgloref{}}|memjustarg}{1702} -\glossaryentry{syncstream.syncbuf.special@ {\memgloterm{syncstream.syncbuf.special}}{\memglodesc{(\ref {syncstream.syncbuf.special})}} {\memgloref{}}|memjustarg}{1702} -\glossaryentry{syncstream.osyncstream@ {\memgloterm{syncstream.osyncstream}}{\memglodesc{(\ref {syncstream.osyncstream})}} {\memgloref{}}|memjustarg}{1702} -\glossaryentry{syncstream.osyncstream.overview@ {\memgloterm{syncstream.osyncstream.overview}}{\memglodesc{(\ref {syncstream.osyncstream.overview})}} {\memgloref{}}|memjustarg}{1702} -\glossaryentry{syncstream.osyncstream.cons@ {\memgloterm{syncstream.osyncstream.cons}}{\memglodesc{(\ref {syncstream.osyncstream.cons})}} {\memgloref{}}|memjustarg}{1703} -\glossaryentry{syncstream.osyncstream.members@ {\memgloterm{syncstream.osyncstream.members}}{\memglodesc{(\ref {syncstream.osyncstream.members})}} {\memgloref{}}|memjustarg}{1703} -\glossaryentry{filesystems@ {\memgloterm{filesystems}}{\memglodesc{(\ref {filesystems})}} {\memgloref{}}|memjustarg}{1704} -\glossaryentry{fs.general@ {\memgloterm{fs.general}}{\memglodesc{(\ref {fs.general})}} {\memgloref{}}|memjustarg}{1704} -\glossaryentry{fs.conformance@ {\memgloterm{fs.conformance}}{\memglodesc{(\ref {fs.conformance})}} {\memgloref{}}|memjustarg}{1704} -\glossaryentry{fs.conformance.general@ {\memgloterm{fs.conformance.general}}{\memglodesc{(\ref {fs.conformance.general})}} {\memgloref{}}|memjustarg}{1704} -\glossaryentry{fs.conform.9945@ {\memgloterm{fs.conform.9945}}{\memglodesc{(\ref {fs.conform.9945})}} {\memgloref{}}|memjustarg}{1704} -\glossaryentry{fs.conform.os@ {\memgloterm{fs.conform.os}}{\memglodesc{(\ref {fs.conform.os})}} {\memgloref{}}|memjustarg}{1705} -\glossaryentry{fs.race.behavior@ {\memgloterm{fs.race.behavior}}{\memglodesc{(\ref {fs.race.behavior})}} {\memgloref{}}|memjustarg}{1705} -\glossaryentry{fs.req@ {\memgloterm{fs.req}}{\memglodesc{(\ref {fs.req})}} {\memgloref{}}|memjustarg}{1705} -\glossaryentry{fs.filesystem.syn@ {\memgloterm{fs.filesystem.syn}}{\memglodesc{(\ref {fs.filesystem.syn})}} {\memgloref{}}|memjustarg}{1705} -\glossaryentry{fs.err.report@ {\memgloterm{fs.err.report}}{\memglodesc{(\ref {fs.err.report})}} {\memgloref{}}|memjustarg}{1709} -\glossaryentry{fs.class.path@ {\memgloterm{fs.class.path}}{\memglodesc{(\ref {fs.class.path})}} {\memgloref{}}|memjustarg}{1709} -\glossaryentry{fs.class.path.general@ {\memgloterm{fs.class.path.general}}{\memglodesc{(\ref {fs.class.path.general})}} {\memgloref{}}|memjustarg}{1709} -\glossaryentry{fs.path.generic@ {\memgloterm{fs.path.generic}}{\memglodesc{(\ref {fs.path.generic})}} {\memgloref{}}|memjustarg}{1712} -\glossaryentry{fs.path.cvt@ {\memgloterm{fs.path.cvt}}{\memglodesc{(\ref {fs.path.cvt})}} {\memgloref{}}|memjustarg}{1714} -\glossaryentry{fs.path.fmt.cvt@ {\memgloterm{fs.path.fmt.cvt}}{\memglodesc{(\ref {fs.path.fmt.cvt})}} {\memgloref{}}|memjustarg}{1714} -\glossaryentry{fs.path.type.cvt@ {\memgloterm{fs.path.type.cvt}}{\memglodesc{(\ref {fs.path.type.cvt})}} {\memgloref{}}|memjustarg}{1714} -\glossaryentry{fs.path.req@ {\memgloterm{fs.path.req}}{\memglodesc{(\ref {fs.path.req})}} {\memgloref{}}|memjustarg}{1715} -\glossaryentry{fs.path.member@ {\memgloterm{fs.path.member}}{\memglodesc{(\ref {fs.path.member})}} {\memgloref{}}|memjustarg}{1715} -\glossaryentry{fs.path.construct@ {\memgloterm{fs.path.construct}}{\memglodesc{(\ref {fs.path.construct})}} {\memgloref{}}|memjustarg}{1715} -\glossaryentry{fs.path.assign@ {\memgloterm{fs.path.assign}}{\memglodesc{(\ref {fs.path.assign})}} {\memgloref{}}|memjustarg}{1716} -\glossaryentry{fs.path.append@ {\memgloterm{fs.path.append}}{\memglodesc{(\ref {fs.path.append})}} {\memgloref{}}|memjustarg}{1717} -\glossaryentry{fs.path.concat@ {\memgloterm{fs.path.concat}}{\memglodesc{(\ref {fs.path.concat})}} {\memgloref{}}|memjustarg}{1717} -\glossaryentry{fs.path.modifiers@ {\memgloterm{fs.path.modifiers}}{\memglodesc{(\ref {fs.path.modifiers})}} {\memgloref{}}|memjustarg}{1718} -\glossaryentry{fs.path.native.obs@ {\memgloterm{fs.path.native.obs}}{\memglodesc{(\ref {fs.path.native.obs})}} {\memgloref{}}|memjustarg}{1719} -\glossaryentry{fs.path.generic.obs@ {\memgloterm{fs.path.generic.obs}}{\memglodesc{(\ref {fs.path.generic.obs})}} {\memgloref{}}|memjustarg}{1719} -\glossaryentry{fs.path.compare@ {\memgloterm{fs.path.compare}}{\memglodesc{(\ref {fs.path.compare})}} {\memgloref{}}|memjustarg}{1720} -\glossaryentry{fs.path.decompose@ {\memgloterm{fs.path.decompose}}{\memglodesc{(\ref {fs.path.decompose})}} {\memgloref{}}|memjustarg}{1720} -\glossaryentry{fs.path.query@ {\memgloterm{fs.path.query}}{\memglodesc{(\ref {fs.path.query})}} {\memgloref{}}|memjustarg}{1721} -\glossaryentry{fs.path.gen@ {\memgloterm{fs.path.gen}}{\memglodesc{(\ref {fs.path.gen})}} {\memgloref{}}|memjustarg}{1722} -\glossaryentry{fs.path.itr@ {\memgloterm{fs.path.itr}}{\memglodesc{(\ref {fs.path.itr})}} {\memgloref{}}|memjustarg}{1723} -\glossaryentry{fs.path.io@ {\memgloterm{fs.path.io}}{\memglodesc{(\ref {fs.path.io})}} {\memgloref{}}|memjustarg}{1723} -\glossaryentry{fs.path.nonmember@ {\memgloterm{fs.path.nonmember}}{\memglodesc{(\ref {fs.path.nonmember})}} {\memgloref{}}|memjustarg}{1724} -\glossaryentry{fs.path.hash@ {\memgloterm{fs.path.hash}}{\memglodesc{(\ref {fs.path.hash})}} {\memgloref{}}|memjustarg}{1724} -\glossaryentry{fs.class.filesystem.error@ {\memgloterm{fs.class.filesystem.error}}{\memglodesc{(\ref {fs.class.filesystem.error})}} {\memgloref{}}|memjustarg}{1724} -\glossaryentry{fs.class.filesystem.error.general@ {\memgloterm{fs.class.filesystem.error.general}}{\memglodesc{(\ref {fs.class.filesystem.error.general})}} {\memgloref{}}|memjustarg}{1724} -\glossaryentry{fs.filesystem.error.members@ {\memgloterm{fs.filesystem.error.members}}{\memglodesc{(\ref {fs.filesystem.error.members})}} {\memgloref{}}|memjustarg}{1724} -\glossaryentry{fs.enum@ {\memgloterm{fs.enum}}{\memglodesc{(\ref {fs.enum})}} {\memgloref{}}|memjustarg}{1725} -\glossaryentry{fs.enum.path.format@ {\memgloterm{fs.enum.path.format}}{\memglodesc{(\ref {fs.enum.path.format})}} {\memgloref{}}|memjustarg}{1725} -\glossaryentry{fs.enum.file.type@ {\memgloterm{fs.enum.file.type}}{\memglodesc{(\ref {fs.enum.file.type})}} {\memgloref{}}|memjustarg}{1725} -\glossaryentry{fs.enum.copy.opts@ {\memgloterm{fs.enum.copy.opts}}{\memglodesc{(\ref {fs.enum.copy.opts})}} {\memgloref{}}|memjustarg}{1726} -\glossaryentry{fs.enum.perms@ {\memgloterm{fs.enum.perms}}{\memglodesc{(\ref {fs.enum.perms})}} {\memgloref{}}|memjustarg}{1727} -\glossaryentry{fs.enum.perm.opts@ {\memgloterm{fs.enum.perm.opts}}{\memglodesc{(\ref {fs.enum.perm.opts})}} {\memgloref{}}|memjustarg}{1727} -\glossaryentry{fs.enum.dir.opts@ {\memgloterm{fs.enum.dir.opts}}{\memglodesc{(\ref {fs.enum.dir.opts})}} {\memgloref{}}|memjustarg}{1727} -\glossaryentry{fs.class.file.status@ {\memgloterm{fs.class.file.status}}{\memglodesc{(\ref {fs.class.file.status})}} {\memgloref{}}|memjustarg}{1728} -\glossaryentry{fs.class.file.status.general@ {\memgloterm{fs.class.file.status.general}}{\memglodesc{(\ref {fs.class.file.status.general})}} {\memgloref{}}|memjustarg}{1728} -\glossaryentry{fs.file.status.cons@ {\memgloterm{fs.file.status.cons}}{\memglodesc{(\ref {fs.file.status.cons})}} {\memgloref{}}|memjustarg}{1728} -\glossaryentry{fs.file.status.obs@ {\memgloterm{fs.file.status.obs}}{\memglodesc{(\ref {fs.file.status.obs})}} {\memgloref{}}|memjustarg}{1728} -\glossaryentry{fs.file.status.mods@ {\memgloterm{fs.file.status.mods}}{\memglodesc{(\ref {fs.file.status.mods})}} {\memgloref{}}|memjustarg}{1728} -\glossaryentry{fs.class.directory.entry@ {\memgloterm{fs.class.directory.entry}}{\memglodesc{(\ref {fs.class.directory.entry})}} {\memgloref{}}|memjustarg}{1729} -\glossaryentry{fs.class.directory.entry.general@ {\memgloterm{fs.class.directory.entry.general}}{\memglodesc{(\ref {fs.class.directory.entry.general})}} {\memgloref{}}|memjustarg}{1729} -\glossaryentry{fs.dir.entry.cons@ {\memgloterm{fs.dir.entry.cons}}{\memglodesc{(\ref {fs.dir.entry.cons})}} {\memgloref{}}|memjustarg}{1730} -\glossaryentry{fs.dir.entry.mods@ {\memgloterm{fs.dir.entry.mods}}{\memglodesc{(\ref {fs.dir.entry.mods})}} {\memgloref{}}|memjustarg}{1730} -\glossaryentry{fs.dir.entry.obs@ {\memgloterm{fs.dir.entry.obs}}{\memglodesc{(\ref {fs.dir.entry.obs})}} {\memgloref{}}|memjustarg}{1731} -\glossaryentry{fs.dir.entry.io@ {\memgloterm{fs.dir.entry.io}}{\memglodesc{(\ref {fs.dir.entry.io})}} {\memgloref{}}|memjustarg}{1732} -\glossaryentry{fs.class.directory.iterator@ {\memgloterm{fs.class.directory.iterator}}{\memglodesc{(\ref {fs.class.directory.iterator})}} {\memgloref{}}|memjustarg}{1733} -\glossaryentry{fs.class.directory.iterator.general@ {\memgloterm{fs.class.directory.iterator.general}}{\memglodesc{(\ref {fs.class.directory.iterator.general})}} {\memgloref{}}|memjustarg}{1733} -\glossaryentry{fs.dir.itr.members@ {\memgloterm{fs.dir.itr.members}}{\memglodesc{(\ref {fs.dir.itr.members})}} {\memgloref{}}|memjustarg}{1734} -\glossaryentry{fs.dir.itr.nonmembers@ {\memgloterm{fs.dir.itr.nonmembers}}{\memglodesc{(\ref {fs.dir.itr.nonmembers})}} {\memgloref{}}|memjustarg}{1734} -\glossaryentry{fs.class.rec.dir.itr@ {\memgloterm{fs.class.rec.dir.itr}}{\memglodesc{(\ref {fs.class.rec.dir.itr})}} {\memgloref{}}|memjustarg}{1735} -\glossaryentry{fs.class.rec.dir.itr.general@ {\memgloterm{fs.class.rec.dir.itr.general}}{\memglodesc{(\ref {fs.class.rec.dir.itr.general})}} {\memgloref{}}|memjustarg}{1735} -\glossaryentry{fs.rec.dir.itr.members@ {\memgloterm{fs.rec.dir.itr.members}}{\memglodesc{(\ref {fs.rec.dir.itr.members})}} {\memgloref{}}|memjustarg}{1736} -\glossaryentry{fs.rec.dir.itr.nonmembers@ {\memgloterm{fs.rec.dir.itr.nonmembers}}{\memglodesc{(\ref {fs.rec.dir.itr.nonmembers})}} {\memgloref{}}|memjustarg}{1737} -\glossaryentry{fs.op.funcs@ {\memgloterm{fs.op.funcs}}{\memglodesc{(\ref {fs.op.funcs})}} {\memgloref{}}|memjustarg}{1737} -\glossaryentry{fs.op.funcs.general@ {\memgloterm{fs.op.funcs.general}}{\memglodesc{(\ref {fs.op.funcs.general})}} {\memgloref{}}|memjustarg}{1737} -\glossaryentry{fs.op.absolute@ {\memgloterm{fs.op.absolute}}{\memglodesc{(\ref {fs.op.absolute})}} {\memgloref{}}|memjustarg}{1737} -\glossaryentry{fs.op.canonical@ {\memgloterm{fs.op.canonical}}{\memglodesc{(\ref {fs.op.canonical})}} {\memgloref{}}|memjustarg}{1738} -\glossaryentry{fs.op.copy@ {\memgloterm{fs.op.copy}}{\memglodesc{(\ref {fs.op.copy})}} {\memgloref{}}|memjustarg}{1738} -\glossaryentry{fs.op.copy.file@ {\memgloterm{fs.op.copy.file}}{\memglodesc{(\ref {fs.op.copy.file})}} {\memgloref{}}|memjustarg}{1740} -\glossaryentry{fs.op.copy.symlink@ {\memgloterm{fs.op.copy.symlink}}{\memglodesc{(\ref {fs.op.copy.symlink})}} {\memgloref{}}|memjustarg}{1740} -\glossaryentry{fs.op.create.directories@ {\memgloterm{fs.op.create.directories}}{\memglodesc{(\ref {fs.op.create.directories})}} {\memgloref{}}|memjustarg}{1741} -\glossaryentry{fs.op.create.directory@ {\memgloterm{fs.op.create.directory}}{\memglodesc{(\ref {fs.op.create.directory})}} {\memgloref{}}|memjustarg}{1741} -\glossaryentry{fs.op.create.dir.symlk@ {\memgloterm{fs.op.create.dir.symlk}}{\memglodesc{(\ref {fs.op.create.dir.symlk})}} {\memgloref{}}|memjustarg}{1741} -\glossaryentry{fs.op.create.hard.lk@ {\memgloterm{fs.op.create.hard.lk}}{\memglodesc{(\ref {fs.op.create.hard.lk})}} {\memgloref{}}|memjustarg}{1742} -\glossaryentry{fs.op.create.symlink@ {\memgloterm{fs.op.create.symlink}}{\memglodesc{(\ref {fs.op.create.symlink})}} {\memgloref{}}|memjustarg}{1742} -\glossaryentry{fs.op.current.path@ {\memgloterm{fs.op.current.path}}{\memglodesc{(\ref {fs.op.current.path})}} {\memgloref{}}|memjustarg}{1742} -\glossaryentry{fs.op.equivalent@ {\memgloterm{fs.op.equivalent}}{\memglodesc{(\ref {fs.op.equivalent})}} {\memgloref{}}|memjustarg}{1742} -\glossaryentry{fs.op.exists@ {\memgloterm{fs.op.exists}}{\memglodesc{(\ref {fs.op.exists})}} {\memgloref{}}|memjustarg}{1743} -\glossaryentry{fs.op.file.size@ {\memgloterm{fs.op.file.size}}{\memglodesc{(\ref {fs.op.file.size})}} {\memgloref{}}|memjustarg}{1743} -\glossaryentry{fs.op.hard.lk.ct@ {\memgloterm{fs.op.hard.lk.ct}}{\memglodesc{(\ref {fs.op.hard.lk.ct})}} {\memgloref{}}|memjustarg}{1743} -\glossaryentry{fs.op.is.block.file@ {\memgloterm{fs.op.is.block.file}}{\memglodesc{(\ref {fs.op.is.block.file})}} {\memgloref{}}|memjustarg}{1743} -\glossaryentry{fs.op.is.char.file@ {\memgloterm{fs.op.is.char.file}}{\memglodesc{(\ref {fs.op.is.char.file})}} {\memgloref{}}|memjustarg}{1743} -\glossaryentry{fs.op.is.directory@ {\memgloterm{fs.op.is.directory}}{\memglodesc{(\ref {fs.op.is.directory})}} {\memgloref{}}|memjustarg}{1744} -\glossaryentry{fs.op.is.empty@ {\memgloterm{fs.op.is.empty}}{\memglodesc{(\ref {fs.op.is.empty})}} {\memgloref{}}|memjustarg}{1744} -\glossaryentry{fs.op.is.fifo@ {\memgloterm{fs.op.is.fifo}}{\memglodesc{(\ref {fs.op.is.fifo})}} {\memgloref{}}|memjustarg}{1744} -\glossaryentry{fs.op.is.other@ {\memgloterm{fs.op.is.other}}{\memglodesc{(\ref {fs.op.is.other})}} {\memgloref{}}|memjustarg}{1744} -\glossaryentry{fs.op.is.regular.file@ {\memgloterm{fs.op.is.regular.file}}{\memglodesc{(\ref {fs.op.is.regular.file})}} {\memgloref{}}|memjustarg}{1745} -\glossaryentry{fs.op.is.socket@ {\memgloterm{fs.op.is.socket}}{\memglodesc{(\ref {fs.op.is.socket})}} {\memgloref{}}|memjustarg}{1745} -\glossaryentry{fs.op.is.symlink@ {\memgloterm{fs.op.is.symlink}}{\memglodesc{(\ref {fs.op.is.symlink})}} {\memgloref{}}|memjustarg}{1745} -\glossaryentry{fs.op.last.write.time@ {\memgloterm{fs.op.last.write.time}}{\memglodesc{(\ref {fs.op.last.write.time})}} {\memgloref{}}|memjustarg}{1745} -\glossaryentry{fs.op.permissions@ {\memgloterm{fs.op.permissions}}{\memglodesc{(\ref {fs.op.permissions})}} {\memgloref{}}|memjustarg}{1746} -\glossaryentry{fs.op.proximate@ {\memgloterm{fs.op.proximate}}{\memglodesc{(\ref {fs.op.proximate})}} {\memgloref{}}|memjustarg}{1746} -\glossaryentry{fs.op.read.symlink@ {\memgloterm{fs.op.read.symlink}}{\memglodesc{(\ref {fs.op.read.symlink})}} {\memgloref{}}|memjustarg}{1746} -\glossaryentry{fs.op.relative@ {\memgloterm{fs.op.relative}}{\memglodesc{(\ref {fs.op.relative})}} {\memgloref{}}|memjustarg}{1746} -\glossaryentry{fs.op.remove@ {\memgloterm{fs.op.remove}}{\memglodesc{(\ref {fs.op.remove})}} {\memgloref{}}|memjustarg}{1747} -\glossaryentry{fs.op.remove.all@ {\memgloterm{fs.op.remove.all}}{\memglodesc{(\ref {fs.op.remove.all})}} {\memgloref{}}|memjustarg}{1747} -\glossaryentry{fs.op.rename@ {\memgloterm{fs.op.rename}}{\memglodesc{(\ref {fs.op.rename})}} {\memgloref{}}|memjustarg}{1747} -\glossaryentry{fs.op.resize.file@ {\memgloterm{fs.op.resize.file}}{\memglodesc{(\ref {fs.op.resize.file})}} {\memgloref{}}|memjustarg}{1747} -\glossaryentry{fs.op.space@ {\memgloterm{fs.op.space}}{\memglodesc{(\ref {fs.op.space})}} {\memgloref{}}|memjustarg}{1747} -\glossaryentry{fs.op.status@ {\memgloterm{fs.op.status}}{\memglodesc{(\ref {fs.op.status})}} {\memgloref{}}|memjustarg}{1748} -\glossaryentry{fs.op.status.known@ {\memgloterm{fs.op.status.known}}{\memglodesc{(\ref {fs.op.status.known})}} {\memgloref{}}|memjustarg}{1749} -\glossaryentry{fs.op.symlink.status@ {\memgloterm{fs.op.symlink.status}}{\memglodesc{(\ref {fs.op.symlink.status})}} {\memgloref{}}|memjustarg}{1749} -\glossaryentry{fs.op.temp.dir.path@ {\memgloterm{fs.op.temp.dir.path}}{\memglodesc{(\ref {fs.op.temp.dir.path})}} {\memgloref{}}|memjustarg}{1749} -\glossaryentry{fs.op.weakly.canonical@ {\memgloterm{fs.op.weakly.canonical}}{\memglodesc{(\ref {fs.op.weakly.canonical})}} {\memgloref{}}|memjustarg}{1749} -\glossaryentry{c.files@ {\memgloterm{c.files}}{\memglodesc{(\ref {c.files})}} {\memgloref{}}|memjustarg}{1750} -\glossaryentry{cstdio.syn@ {\memgloterm{cstdio.syn}}{\memglodesc{(\ref {cstdio.syn})}} {\memgloref{}}|memjustarg}{1750} -\glossaryentry{cinttypes.syn@ {\memgloterm{cinttypes.syn}}{\memglodesc{(\ref {cinttypes.syn})}} {\memgloref{}}|memjustarg}{1751} -\glossaryentry{re@ {\memgloterm{re}}{\memglodesc{(\ref {re})}} {\memgloref{}}|memjustarg}{1753} -\glossaryentry{re.general@ {\memgloterm{re.general}}{\memglodesc{(\ref {re.general})}} {\memgloref{}}|memjustarg}{1753} -\glossaryentry{re.req@ {\memgloterm{re.req}}{\memglodesc{(\ref {re.req})}} {\memgloref{}}|memjustarg}{1753} -\glossaryentry{re.syn@ {\memgloterm{re.syn}}{\memglodesc{(\ref {re.syn})}} {\memgloref{}}|memjustarg}{1755} -\glossaryentry{re.const@ {\memgloterm{re.const}}{\memglodesc{(\ref {re.const})}} {\memgloref{}}|memjustarg}{1759} -\glossaryentry{re.const.general@ {\memgloterm{re.const.general}}{\memglodesc{(\ref {re.const.general})}} {\memgloref{}}|memjustarg}{1759} -\glossaryentry{re.synopt@ {\memgloterm{re.synopt}}{\memglodesc{(\ref {re.synopt})}} {\memgloref{}}|memjustarg}{1759} -\glossaryentry{re.matchflag@ {\memgloterm{re.matchflag}}{\memglodesc{(\ref {re.matchflag})}} {\memgloref{}}|memjustarg}{1759} -\glossaryentry{re.err@ {\memgloterm{re.err}}{\memglodesc{(\ref {re.err})}} {\memgloref{}}|memjustarg}{1761} -\glossaryentry{re.badexp@ {\memgloterm{re.badexp}}{\memglodesc{(\ref {re.badexp})}} {\memgloref{}}|memjustarg}{1761} -\glossaryentry{re.traits@ {\memgloterm{re.traits}}{\memglodesc{(\ref {re.traits})}} {\memgloref{}}|memjustarg}{1762} -\glossaryentry{re.regex@ {\memgloterm{re.regex}}{\memglodesc{(\ref {re.regex})}} {\memgloref{}}|memjustarg}{1764} -\glossaryentry{re.regex.general@ {\memgloterm{re.regex.general}}{\memglodesc{(\ref {re.regex.general})}} {\memgloref{}}|memjustarg}{1764} -\glossaryentry{re.regex.construct@ {\memgloterm{re.regex.construct}}{\memglodesc{(\ref {re.regex.construct})}} {\memgloref{}}|memjustarg}{1766} -\glossaryentry{re.regex.assign@ {\memgloterm{re.regex.assign}}{\memglodesc{(\ref {re.regex.assign})}} {\memgloref{}}|memjustarg}{1767} -\glossaryentry{re.regex.operations@ {\memgloterm{re.regex.operations}}{\memglodesc{(\ref {re.regex.operations})}} {\memgloref{}}|memjustarg}{1768} -\glossaryentry{re.regex.locale@ {\memgloterm{re.regex.locale}}{\memglodesc{(\ref {re.regex.locale})}} {\memgloref{}}|memjustarg}{1768} -\glossaryentry{re.regex.swap@ {\memgloterm{re.regex.swap}}{\memglodesc{(\ref {re.regex.swap})}} {\memgloref{}}|memjustarg}{1768} -\glossaryentry{re.regex.nonmemb@ {\memgloterm{re.regex.nonmemb}}{\memglodesc{(\ref {re.regex.nonmemb})}} {\memgloref{}}|memjustarg}{1768} -\glossaryentry{re.submatch@ {\memgloterm{re.submatch}}{\memglodesc{(\ref {re.submatch})}} {\memgloref{}}|memjustarg}{1768} -\glossaryentry{re.submatch.general@ {\memgloterm{re.submatch.general}}{\memglodesc{(\ref {re.submatch.general})}} {\memgloref{}}|memjustarg}{1768} -\glossaryentry{re.submatch.members@ {\memgloterm{re.submatch.members}}{\memglodesc{(\ref {re.submatch.members})}} {\memgloref{}}|memjustarg}{1769} -\glossaryentry{re.submatch.op@ {\memgloterm{re.submatch.op}}{\memglodesc{(\ref {re.submatch.op})}} {\memgloref{}}|memjustarg}{1769} -\glossaryentry{re.results@ {\memgloterm{re.results}}{\memglodesc{(\ref {re.results})}} {\memgloref{}}|memjustarg}{1770} -\glossaryentry{re.results.general@ {\memgloterm{re.results.general}}{\memglodesc{(\ref {re.results.general})}} {\memgloref{}}|memjustarg}{1770} -\glossaryentry{re.results.const@ {\memgloterm{re.results.const}}{\memglodesc{(\ref {re.results.const})}} {\memgloref{}}|memjustarg}{1772} -\glossaryentry{re.results.state@ {\memgloterm{re.results.state}}{\memglodesc{(\ref {re.results.state})}} {\memgloref{}}|memjustarg}{1772} -\glossaryentry{re.results.size@ {\memgloterm{re.results.size}}{\memglodesc{(\ref {re.results.size})}} {\memgloref{}}|memjustarg}{1773} -\glossaryentry{re.results.acc@ {\memgloterm{re.results.acc}}{\memglodesc{(\ref {re.results.acc})}} {\memgloref{}}|memjustarg}{1773} -\glossaryentry{re.results.form@ {\memgloterm{re.results.form}}{\memglodesc{(\ref {re.results.form})}} {\memgloref{}}|memjustarg}{1774} -\glossaryentry{re.results.all@ {\memgloterm{re.results.all}}{\memglodesc{(\ref {re.results.all})}} {\memgloref{}}|memjustarg}{1775} -\glossaryentry{re.results.swap@ {\memgloterm{re.results.swap}}{\memglodesc{(\ref {re.results.swap})}} {\memgloref{}}|memjustarg}{1775} -\glossaryentry{re.results.nonmember@ {\memgloterm{re.results.nonmember}}{\memglodesc{(\ref {re.results.nonmember})}} {\memgloref{}}|memjustarg}{1775} -\glossaryentry{re.alg@ {\memgloterm{re.alg}}{\memglodesc{(\ref {re.alg})}} {\memgloref{}}|memjustarg}{1775} -\glossaryentry{re.except@ {\memgloterm{re.except}}{\memglodesc{(\ref {re.except})}} {\memgloref{}}|memjustarg}{1775} -\glossaryentry{re.alg.match@ {\memgloterm{re.alg.match}}{\memglodesc{(\ref {re.alg.match})}} {\memgloref{}}|memjustarg}{1775} -\glossaryentry{re.alg.search@ {\memgloterm{re.alg.search}}{\memglodesc{(\ref {re.alg.search})}} {\memgloref{}}|memjustarg}{1777} -\glossaryentry{re.alg.replace@ {\memgloterm{re.alg.replace}}{\memglodesc{(\ref {re.alg.replace})}} {\memgloref{}}|memjustarg}{1778} -\glossaryentry{re.iter@ {\memgloterm{re.iter}}{\memglodesc{(\ref {re.iter})}} {\memgloref{}}|memjustarg}{1779} -\glossaryentry{re.regiter@ {\memgloterm{re.regiter}}{\memglodesc{(\ref {re.regiter})}} {\memgloref{}}|memjustarg}{1779} -\glossaryentry{re.regiter.general@ {\memgloterm{re.regiter.general}}{\memglodesc{(\ref {re.regiter.general})}} {\memgloref{}}|memjustarg}{1779} -\glossaryentry{re.regiter.cnstr@ {\memgloterm{re.regiter.cnstr}}{\memglodesc{(\ref {re.regiter.cnstr})}} {\memgloref{}}|memjustarg}{1780} -\glossaryentry{re.regiter.comp@ {\memgloterm{re.regiter.comp}}{\memglodesc{(\ref {re.regiter.comp})}} {\memgloref{}}|memjustarg}{1780} -\glossaryentry{re.regiter.deref@ {\memgloterm{re.regiter.deref}}{\memglodesc{(\ref {re.regiter.deref})}} {\memgloref{}}|memjustarg}{1781} -\glossaryentry{re.regiter.incr@ {\memgloterm{re.regiter.incr}}{\memglodesc{(\ref {re.regiter.incr})}} {\memgloref{}}|memjustarg}{1781} -\glossaryentry{re.tokiter@ {\memgloterm{re.tokiter}}{\memglodesc{(\ref {re.tokiter})}} {\memgloref{}}|memjustarg}{1781} -\glossaryentry{re.tokiter.general@ {\memgloterm{re.tokiter.general}}{\memglodesc{(\ref {re.tokiter.general})}} {\memgloref{}}|memjustarg}{1781} -\glossaryentry{re.tokiter.cnstr@ {\memgloterm{re.tokiter.cnstr}}{\memglodesc{(\ref {re.tokiter.cnstr})}} {\memgloref{}}|memjustarg}{1783} -\glossaryentry{re.tokiter.comp@ {\memgloterm{re.tokiter.comp}}{\memglodesc{(\ref {re.tokiter.comp})}} {\memgloref{}}|memjustarg}{1784} -\glossaryentry{re.tokiter.deref@ {\memgloterm{re.tokiter.deref}}{\memglodesc{(\ref {re.tokiter.deref})}} {\memgloref{}}|memjustarg}{1784} -\glossaryentry{re.tokiter.incr@ {\memgloterm{re.tokiter.incr}}{\memglodesc{(\ref {re.tokiter.incr})}} {\memgloref{}}|memjustarg}{1784} -\glossaryentry{re.grammar@ {\memgloterm{re.grammar}}{\memglodesc{(\ref {re.grammar})}} {\memgloref{}}|memjustarg}{1785} -\glossaryentry{thread@ {\memgloterm{thread}}{\memglodesc{(\ref {thread})}} {\memgloref{}}|memjustarg}{1787} -\glossaryentry{thread.general@ {\memgloterm{thread.general}}{\memglodesc{(\ref {thread.general})}} {\memgloref{}}|memjustarg}{1787} -\glossaryentry{thread.req@ {\memgloterm{thread.req}}{\memglodesc{(\ref {thread.req})}} {\memgloref{}}|memjustarg}{1787} -\glossaryentry{thread.req.paramname@ {\memgloterm{thread.req.paramname}}{\memglodesc{(\ref {thread.req.paramname})}} {\memgloref{}}|memjustarg}{1787} -\glossaryentry{thread.req.exception@ {\memgloterm{thread.req.exception}}{\memglodesc{(\ref {thread.req.exception})}} {\memgloref{}}|memjustarg}{1787} -\glossaryentry{thread.req.native@ {\memgloterm{thread.req.native}}{\memglodesc{(\ref {thread.req.native})}} {\memgloref{}}|memjustarg}{1787} -\glossaryentry{thread.req.timing@ {\memgloterm{thread.req.timing}}{\memglodesc{(\ref {thread.req.timing})}} {\memgloref{}}|memjustarg}{1787} -\glossaryentry{thread.req.lockable@ {\memgloterm{thread.req.lockable}}{\memglodesc{(\ref {thread.req.lockable})}} {\memgloref{}}|memjustarg}{1788} -\glossaryentry{thread.req.lockable.general@ {\memgloterm{thread.req.lockable.general}}{\memglodesc{(\ref {thread.req.lockable.general})}} {\memgloref{}}|memjustarg}{1788} -\glossaryentry{thread.req.lockable.basic@ {\memgloterm{thread.req.lockable.basic}}{\memglodesc{(\ref {thread.req.lockable.basic})}} {\memgloref{}}|memjustarg}{1789} -\glossaryentry{thread.req.lockable.req@ {\memgloterm{thread.req.lockable.req}}{\memglodesc{(\ref {thread.req.lockable.req})}} {\memgloref{}}|memjustarg}{1789} -\glossaryentry{thread.req.lockable.timed@ {\memgloterm{thread.req.lockable.timed}}{\memglodesc{(\ref {thread.req.lockable.timed})}} {\memgloref{}}|memjustarg}{1789} -\glossaryentry{thread.req.lockable.shared@ {\memgloterm{thread.req.lockable.shared}}{\memglodesc{(\ref {thread.req.lockable.shared})}} {\memgloref{}}|memjustarg}{1790} -\glossaryentry{thread.req.lockable.shared.timed@ {\memgloterm{thread.req.lockable.shared.timed}}{\memglodesc{(\ref {thread.req.lockable.shared.timed})}} {\memgloref{}}|memjustarg}{1790} -\glossaryentry{thread.stoptoken@ {\memgloterm{thread.stoptoken}}{\memglodesc{(\ref {thread.stoptoken})}} {\memgloref{}}|memjustarg}{1790} -\glossaryentry{thread.stoptoken.intro@ {\memgloterm{thread.stoptoken.intro}}{\memglodesc{(\ref {thread.stoptoken.intro})}} {\memgloref{}}|memjustarg}{1790} -\glossaryentry{thread.stoptoken.syn@ {\memgloterm{thread.stoptoken.syn}}{\memglodesc{(\ref {thread.stoptoken.syn})}} {\memgloref{}}|memjustarg}{1791} -\glossaryentry{stoptoken@ {\memgloterm{stoptoken}}{\memglodesc{(\ref {stoptoken})}} {\memgloref{}}|memjustarg}{1791} -\glossaryentry{stoptoken.general@ {\memgloterm{stoptoken.general}}{\memglodesc{(\ref {stoptoken.general})}} {\memgloref{}}|memjustarg}{1791} -\glossaryentry{stoptoken.cons@ {\memgloterm{stoptoken.cons}}{\memglodesc{(\ref {stoptoken.cons})}} {\memgloref{}}|memjustarg}{1791} -\glossaryentry{stoptoken.mem@ {\memgloterm{stoptoken.mem}}{\memglodesc{(\ref {stoptoken.mem})}} {\memgloref{}}|memjustarg}{1792} -\glossaryentry{stoptoken.nonmembers@ {\memgloterm{stoptoken.nonmembers}}{\memglodesc{(\ref {stoptoken.nonmembers})}} {\memgloref{}}|memjustarg}{1792} -\glossaryentry{stopsource@ {\memgloterm{stopsource}}{\memglodesc{(\ref {stopsource})}} {\memgloref{}}|memjustarg}{1792} -\glossaryentry{stopsource.general@ {\memgloterm{stopsource.general}}{\memglodesc{(\ref {stopsource.general})}} {\memgloref{}}|memjustarg}{1792} -\glossaryentry{stopsource.cons@ {\memgloterm{stopsource.cons}}{\memglodesc{(\ref {stopsource.cons})}} {\memgloref{}}|memjustarg}{1793} -\glossaryentry{stopsource.mem@ {\memgloterm{stopsource.mem}}{\memglodesc{(\ref {stopsource.mem})}} {\memgloref{}}|memjustarg}{1794} -\glossaryentry{stopsource.nonmembers@ {\memgloterm{stopsource.nonmembers}}{\memglodesc{(\ref {stopsource.nonmembers})}} {\memgloref{}}|memjustarg}{1794} -\glossaryentry{stopcallback@ {\memgloterm{stopcallback}}{\memglodesc{(\ref {stopcallback})}} {\memgloref{}}|memjustarg}{1794} -\glossaryentry{stopcallback.general@ {\memgloterm{stopcallback.general}}{\memglodesc{(\ref {stopcallback.general})}} {\memgloref{}}|memjustarg}{1794} -\glossaryentry{stopcallback.cons@ {\memgloterm{stopcallback.cons}}{\memglodesc{(\ref {stopcallback.cons})}} {\memgloref{}}|memjustarg}{1795} -\glossaryentry{thread.threads@ {\memgloterm{thread.threads}}{\memglodesc{(\ref {thread.threads})}} {\memgloref{}}|memjustarg}{1795} -\glossaryentry{thread.threads.general@ {\memgloterm{thread.threads.general}}{\memglodesc{(\ref {thread.threads.general})}} {\memgloref{}}|memjustarg}{1795} -\glossaryentry{thread.syn@ {\memgloterm{thread.syn}}{\memglodesc{(\ref {thread.syn})}} {\memgloref{}}|memjustarg}{1795} -\glossaryentry{thread.thread.class@ {\memgloterm{thread.thread.class}}{\memglodesc{(\ref {thread.thread.class})}} {\memgloref{}}|memjustarg}{1796} -\glossaryentry{thread.thread.class.general@ {\memgloterm{thread.thread.class.general}}{\memglodesc{(\ref {thread.thread.class.general})}} {\memgloref{}}|memjustarg}{1796} -\glossaryentry{thread.thread.id@ {\memgloterm{thread.thread.id}}{\memglodesc{(\ref {thread.thread.id})}} {\memgloref{}}|memjustarg}{1796} -\glossaryentry{thread.thread.constr@ {\memgloterm{thread.thread.constr}}{\memglodesc{(\ref {thread.thread.constr})}} {\memgloref{}}|memjustarg}{1797} -\glossaryentry{thread.thread.destr@ {\memgloterm{thread.thread.destr}}{\memglodesc{(\ref {thread.thread.destr})}} {\memgloref{}}|memjustarg}{1798} -\glossaryentry{thread.thread.assign@ {\memgloterm{thread.thread.assign}}{\memglodesc{(\ref {thread.thread.assign})}} {\memgloref{}}|memjustarg}{1798} -\glossaryentry{thread.thread.member@ {\memgloterm{thread.thread.member}}{\memglodesc{(\ref {thread.thread.member})}} {\memgloref{}}|memjustarg}{1798} -\glossaryentry{thread.thread.static@ {\memgloterm{thread.thread.static}}{\memglodesc{(\ref {thread.thread.static})}} {\memgloref{}}|memjustarg}{1799} -\glossaryentry{thread.thread.algorithm@ {\memgloterm{thread.thread.algorithm}}{\memglodesc{(\ref {thread.thread.algorithm})}} {\memgloref{}}|memjustarg}{1799} -\glossaryentry{thread.jthread.class@ {\memgloterm{thread.jthread.class}}{\memglodesc{(\ref {thread.jthread.class})}} {\memgloref{}}|memjustarg}{1799} -\glossaryentry{thread.jthread.class.general@ {\memgloterm{thread.jthread.class.general}}{\memglodesc{(\ref {thread.jthread.class.general})}} {\memgloref{}}|memjustarg}{1799} -\glossaryentry{thread.jthread.cons@ {\memgloterm{thread.jthread.cons}}{\memglodesc{(\ref {thread.jthread.cons})}} {\memgloref{}}|memjustarg}{1800} -\glossaryentry{thread.jthread.mem@ {\memgloterm{thread.jthread.mem}}{\memglodesc{(\ref {thread.jthread.mem})}} {\memgloref{}}|memjustarg}{1801} -\glossaryentry{thread.jthread.stop@ {\memgloterm{thread.jthread.stop}}{\memglodesc{(\ref {thread.jthread.stop})}} {\memgloref{}}|memjustarg}{1802} -\glossaryentry{thread.jthread.special@ {\memgloterm{thread.jthread.special}}{\memglodesc{(\ref {thread.jthread.special})}} {\memgloref{}}|memjustarg}{1802} -\glossaryentry{thread.jthread.static@ {\memgloterm{thread.jthread.static}}{\memglodesc{(\ref {thread.jthread.static})}} {\memgloref{}}|memjustarg}{1802} -\glossaryentry{thread.thread.this@ {\memgloterm{thread.thread.this}}{\memglodesc{(\ref {thread.thread.this})}} {\memgloref{}}|memjustarg}{1802} -\glossaryentry{atomics@ {\memgloterm{atomics}}{\memglodesc{(\ref {atomics})}} {\memgloref{}}|memjustarg}{1803} -\glossaryentry{atomics.general@ {\memgloterm{atomics.general}}{\memglodesc{(\ref {atomics.general})}} {\memgloref{}}|memjustarg}{1803} -\glossaryentry{atomics.syn@ {\memgloterm{atomics.syn}}{\memglodesc{(\ref {atomics.syn})}} {\memgloref{}}|memjustarg}{1803} -\glossaryentry{atomics.alias@ {\memgloterm{atomics.alias}}{\memglodesc{(\ref {atomics.alias})}} {\memgloref{}}|memjustarg}{1807} -\glossaryentry{atomics.order@ {\memgloterm{atomics.order}}{\memglodesc{(\ref {atomics.order})}} {\memgloref{}}|memjustarg}{1807} -\glossaryentry{atomics.lockfree@ {\memgloterm{atomics.lockfree}}{\memglodesc{(\ref {atomics.lockfree})}} {\memgloref{}}|memjustarg}{1809} -\glossaryentry{atomics.wait@ {\memgloterm{atomics.wait}}{\memglodesc{(\ref {atomics.wait})}} {\memgloref{}}|memjustarg}{1809} -\glossaryentry{atomics.ref.generic@ {\memgloterm{atomics.ref.generic}}{\memglodesc{(\ref {atomics.ref.generic})}} {\memgloref{}}|memjustarg}{1810} -\glossaryentry{atomics.ref.generic.general@ {\memgloterm{atomics.ref.generic.general}}{\memglodesc{(\ref {atomics.ref.generic.general})}} {\memgloref{}}|memjustarg}{1810} -\glossaryentry{atomics.ref.ops@ {\memgloterm{atomics.ref.ops}}{\memglodesc{(\ref {atomics.ref.ops})}} {\memgloref{}}|memjustarg}{1811} -\glossaryentry{atomics.ref.int@ {\memgloterm{atomics.ref.int}}{\memglodesc{(\ref {atomics.ref.int})}} {\memgloref{}}|memjustarg}{1813} -\glossaryentry{atomics.ref.float@ {\memgloterm{atomics.ref.float}}{\memglodesc{(\ref {atomics.ref.float})}} {\memgloref{}}|memjustarg}{1814} -\glossaryentry{atomics.ref.pointer@ {\memgloterm{atomics.ref.pointer}}{\memglodesc{(\ref {atomics.ref.pointer})}} {\memgloref{}}|memjustarg}{1815} -\glossaryentry{atomics.ref.memop@ {\memgloterm{atomics.ref.memop}}{\memglodesc{(\ref {atomics.ref.memop})}} {\memgloref{}}|memjustarg}{1816} -\glossaryentry{atomics.types.generic@ {\memgloterm{atomics.types.generic}}{\memglodesc{(\ref {atomics.types.generic})}} {\memgloref{}}|memjustarg}{1816} -\glossaryentry{atomics.types.generic.general@ {\memgloterm{atomics.types.generic.general}}{\memglodesc{(\ref {atomics.types.generic.general})}} {\memgloref{}}|memjustarg}{1816} -\glossaryentry{atomics.types.operations@ {\memgloterm{atomics.types.operations}}{\memglodesc{(\ref {atomics.types.operations})}} {\memgloref{}}|memjustarg}{1817} -\glossaryentry{atomics.types.int@ {\memgloterm{atomics.types.int}}{\memglodesc{(\ref {atomics.types.int})}} {\memgloref{}}|memjustarg}{1821} -\glossaryentry{atomics.types.float@ {\memgloterm{atomics.types.float}}{\memglodesc{(\ref {atomics.types.float})}} {\memgloref{}}|memjustarg}{1823} -\glossaryentry{atomics.types.pointer@ {\memgloterm{atomics.types.pointer}}{\memglodesc{(\ref {atomics.types.pointer})}} {\memgloref{}}|memjustarg}{1825} -\glossaryentry{atomics.types.memop@ {\memgloterm{atomics.types.memop}}{\memglodesc{(\ref {atomics.types.memop})}} {\memgloref{}}|memjustarg}{1826} -\glossaryentry{util.smartptr.atomic@ {\memgloterm{util.smartptr.atomic}}{\memglodesc{(\ref {util.smartptr.atomic})}} {\memgloref{}}|memjustarg}{1827} -\glossaryentry{util.smartptr.atomic.general@ {\memgloterm{util.smartptr.atomic.general}}{\memglodesc{(\ref {util.smartptr.atomic.general})}} {\memgloref{}}|memjustarg}{1827} -\glossaryentry{util.smartptr.atomic.shared@ {\memgloterm{util.smartptr.atomic.shared}}{\memglodesc{(\ref {util.smartptr.atomic.shared})}} {\memgloref{}}|memjustarg}{1827} -\glossaryentry{util.smartptr.atomic.weak@ {\memgloterm{util.smartptr.atomic.weak}}{\memglodesc{(\ref {util.smartptr.atomic.weak})}} {\memgloref{}}|memjustarg}{1829} -\glossaryentry{atomics.nonmembers@ {\memgloterm{atomics.nonmembers}}{\memglodesc{(\ref {atomics.nonmembers})}} {\memgloref{}}|memjustarg}{1832} -\glossaryentry{atomics.flag@ {\memgloterm{atomics.flag}}{\memglodesc{(\ref {atomics.flag})}} {\memgloref{}}|memjustarg}{1832} -\glossaryentry{atomics.fences@ {\memgloterm{atomics.fences}}{\memglodesc{(\ref {atomics.fences})}} {\memgloref{}}|memjustarg}{1834} -\glossaryentry{stdatomic.h.syn@ {\memgloterm{stdatomic.h.syn}}{\memglodesc{(\ref {stdatomic.h.syn})}} {\memgloref{}}|memjustarg}{1834} -\glossaryentry{thread.mutex@ {\memgloterm{thread.mutex}}{\memglodesc{(\ref {thread.mutex})}} {\memgloref{}}|memjustarg}{1836} -\glossaryentry{thread.mutex.general@ {\memgloterm{thread.mutex.general}}{\memglodesc{(\ref {thread.mutex.general})}} {\memgloref{}}|memjustarg}{1836} -\glossaryentry{mutex.syn@ {\memgloterm{mutex.syn}}{\memglodesc{(\ref {mutex.syn})}} {\memgloref{}}|memjustarg}{1836} -\glossaryentry{shared.mutex.syn@ {\memgloterm{shared.mutex.syn}}{\memglodesc{(\ref {shared.mutex.syn})}} {\memgloref{}}|memjustarg}{1837} -\glossaryentry{thread.mutex.requirements@ {\memgloterm{thread.mutex.requirements}}{\memglodesc{(\ref {thread.mutex.requirements})}} {\memgloref{}}|memjustarg}{1837} -\glossaryentry{thread.mutex.requirements.general@ {\memgloterm{thread.mutex.requirements.general}}{\memglodesc{(\ref {thread.mutex.requirements.general})}} {\memgloref{}}|memjustarg}{1837} -\glossaryentry{thread.mutex.requirements.mutex@ {\memgloterm{thread.mutex.requirements.mutex}}{\memglodesc{(\ref {thread.mutex.requirements.mutex})}} {\memgloref{}}|memjustarg}{1837} -\glossaryentry{thread.mutex.requirements.mutex.general@ {\memgloterm{thread.mutex.requirements.mutex.general}}{\memglodesc{(\ref {thread.mutex.requirements.mutex.general})}} {\memgloref{}}|memjustarg}{1837} -\glossaryentry{thread.mutex.class@ {\memgloterm{thread.mutex.class}}{\memglodesc{(\ref {thread.mutex.class})}} {\memgloref{}}|memjustarg}{1838} -\glossaryentry{thread.mutex.recursive@ {\memgloterm{thread.mutex.recursive}}{\memglodesc{(\ref {thread.mutex.recursive})}} {\memgloref{}}|memjustarg}{1839} -\glossaryentry{thread.timedmutex.requirements@ {\memgloterm{thread.timedmutex.requirements}}{\memglodesc{(\ref {thread.timedmutex.requirements})}} {\memgloref{}}|memjustarg}{1839} -\glossaryentry{thread.timedmutex.requirements.general@ {\memgloterm{thread.timedmutex.requirements.general}}{\memglodesc{(\ref {thread.timedmutex.requirements.general})}} {\memgloref{}}|memjustarg}{1839} -\glossaryentry{thread.timedmutex.class@ {\memgloterm{thread.timedmutex.class}}{\memglodesc{(\ref {thread.timedmutex.class})}} {\memgloref{}}|memjustarg}{1840} -\glossaryentry{thread.timedmutex.recursive@ {\memgloterm{thread.timedmutex.recursive}}{\memglodesc{(\ref {thread.timedmutex.recursive})}} {\memgloref{}}|memjustarg}{1841} -\glossaryentry{thread.sharedmutex.requirements@ {\memgloterm{thread.sharedmutex.requirements}}{\memglodesc{(\ref {thread.sharedmutex.requirements})}} {\memgloref{}}|memjustarg}{1841} -\glossaryentry{thread.sharedmutex.requirements.general@ {\memgloterm{thread.sharedmutex.requirements.general}}{\memglodesc{(\ref {thread.sharedmutex.requirements.general})}} {\memgloref{}}|memjustarg}{1841} -\glossaryentry{thread.sharedmutex.class@ {\memgloterm{thread.sharedmutex.class}}{\memglodesc{(\ref {thread.sharedmutex.class})}} {\memgloref{}}|memjustarg}{1842} -\glossaryentry{thread.sharedtimedmutex.requirements@ {\memgloterm{thread.sharedtimedmutex.requirements}}{\memglodesc{(\ref {thread.sharedtimedmutex.requirements})}} {\memgloref{}}|memjustarg}{1843} -\glossaryentry{thread.sharedtimedmutex.requirements.general@ {\memgloterm{thread.sharedtimedmutex.requirements.general}}{\memglodesc{(\ref {thread.sharedtimedmutex.requirements.general})}} {\memgloref{}}|memjustarg}{1843} -\glossaryentry{thread.sharedtimedmutex.class@ {\memgloterm{thread.sharedtimedmutex.class}}{\memglodesc{(\ref {thread.sharedtimedmutex.class})}} {\memgloref{}}|memjustarg}{1844} -\glossaryentry{thread.lock@ {\memgloterm{thread.lock}}{\memglodesc{(\ref {thread.lock})}} {\memgloref{}}|memjustarg}{1844} -\glossaryentry{thread.lock.general@ {\memgloterm{thread.lock.general}}{\memglodesc{(\ref {thread.lock.general})}} {\memgloref{}}|memjustarg}{1844} -\glossaryentry{thread.lock.guard@ {\memgloterm{thread.lock.guard}}{\memglodesc{(\ref {thread.lock.guard})}} {\memgloref{}}|memjustarg}{1845} -\glossaryentry{thread.lock.scoped@ {\memgloterm{thread.lock.scoped}}{\memglodesc{(\ref {thread.lock.scoped})}} {\memgloref{}}|memjustarg}{1845} -\glossaryentry{thread.lock.unique@ {\memgloterm{thread.lock.unique}}{\memglodesc{(\ref {thread.lock.unique})}} {\memgloref{}}|memjustarg}{1846} -\glossaryentry{thread.lock.unique.general@ {\memgloterm{thread.lock.unique.general}}{\memglodesc{(\ref {thread.lock.unique.general})}} {\memgloref{}}|memjustarg}{1846} -\glossaryentry{thread.lock.unique.cons@ {\memgloterm{thread.lock.unique.cons}}{\memglodesc{(\ref {thread.lock.unique.cons})}} {\memgloref{}}|memjustarg}{1847} -\glossaryentry{thread.lock.unique.locking@ {\memgloterm{thread.lock.unique.locking}}{\memglodesc{(\ref {thread.lock.unique.locking})}} {\memgloref{}}|memjustarg}{1848} -\glossaryentry{thread.lock.unique.mod@ {\memgloterm{thread.lock.unique.mod}}{\memglodesc{(\ref {thread.lock.unique.mod})}} {\memgloref{}}|memjustarg}{1849} -\glossaryentry{thread.lock.unique.obs@ {\memgloterm{thread.lock.unique.obs}}{\memglodesc{(\ref {thread.lock.unique.obs})}} {\memgloref{}}|memjustarg}{1849} -\glossaryentry{thread.lock.shared@ {\memgloterm{thread.lock.shared}}{\memglodesc{(\ref {thread.lock.shared})}} {\memgloref{}}|memjustarg}{1849} -\glossaryentry{thread.lock.shared.general@ {\memgloterm{thread.lock.shared.general}}{\memglodesc{(\ref {thread.lock.shared.general})}} {\memgloref{}}|memjustarg}{1849} -\glossaryentry{thread.lock.shared.cons@ {\memgloterm{thread.lock.shared.cons}}{\memglodesc{(\ref {thread.lock.shared.cons})}} {\memgloref{}}|memjustarg}{1850} -\glossaryentry{thread.lock.shared.locking@ {\memgloterm{thread.lock.shared.locking}}{\memglodesc{(\ref {thread.lock.shared.locking})}} {\memgloref{}}|memjustarg}{1851} -\glossaryentry{thread.lock.shared.mod@ {\memgloterm{thread.lock.shared.mod}}{\memglodesc{(\ref {thread.lock.shared.mod})}} {\memgloref{}}|memjustarg}{1852} -\glossaryentry{thread.lock.shared.obs@ {\memgloterm{thread.lock.shared.obs}}{\memglodesc{(\ref {thread.lock.shared.obs})}} {\memgloref{}}|memjustarg}{1853} -\glossaryentry{thread.lock.algorithm@ {\memgloterm{thread.lock.algorithm}}{\memglodesc{(\ref {thread.lock.algorithm})}} {\memgloref{}}|memjustarg}{1853} -\glossaryentry{thread.once@ {\memgloterm{thread.once}}{\memglodesc{(\ref {thread.once})}} {\memgloref{}}|memjustarg}{1853} -\glossaryentry{thread.once.onceflag@ {\memgloterm{thread.once.onceflag}}{\memglodesc{(\ref {thread.once.onceflag})}} {\memgloref{}}|memjustarg}{1853} -\glossaryentry{thread.once.callonce@ {\memgloterm{thread.once.callonce}}{\memglodesc{(\ref {thread.once.callonce})}} {\memgloref{}}|memjustarg}{1854} -\glossaryentry{thread.condition@ {\memgloterm{thread.condition}}{\memglodesc{(\ref {thread.condition})}} {\memgloref{}}|memjustarg}{1854} -\glossaryentry{thread.condition.general@ {\memgloterm{thread.condition.general}}{\memglodesc{(\ref {thread.condition.general})}} {\memgloref{}}|memjustarg}{1854} -\glossaryentry{condition.variable.syn@ {\memgloterm{condition.variable.syn}}{\memglodesc{(\ref {condition.variable.syn})}} {\memgloref{}}|memjustarg}{1855} -\glossaryentry{thread.condition.nonmember@ {\memgloterm{thread.condition.nonmember}}{\memglodesc{(\ref {thread.condition.nonmember})}} {\memgloref{}}|memjustarg}{1855} -\glossaryentry{thread.condition.condvar@ {\memgloterm{thread.condition.condvar}}{\memglodesc{(\ref {thread.condition.condvar})}} {\memgloref{}}|memjustarg}{1855} -\glossaryentry{thread.condition.condvarany@ {\memgloterm{thread.condition.condvarany}}{\memglodesc{(\ref {thread.condition.condvarany})}} {\memgloref{}}|memjustarg}{1858} -\glossaryentry{thread.condition.condvarany.general@ {\memgloterm{thread.condition.condvarany.general}}{\memglodesc{(\ref {thread.condition.condvarany.general})}} {\memgloref{}}|memjustarg}{1858} -\glossaryentry{thread.condvarany.wait@ {\memgloterm{thread.condvarany.wait}}{\memglodesc{(\ref {thread.condvarany.wait})}} {\memgloref{}}|memjustarg}{1859} -\glossaryentry{thread.condvarany.intwait@ {\memgloterm{thread.condvarany.intwait}}{\memglodesc{(\ref {thread.condvarany.intwait})}} {\memgloref{}}|memjustarg}{1861} -\glossaryentry{thread.sema@ {\memgloterm{thread.sema}}{\memglodesc{(\ref {thread.sema})}} {\memgloref{}}|memjustarg}{1862} -\glossaryentry{thread.sema.general@ {\memgloterm{thread.sema.general}}{\memglodesc{(\ref {thread.sema.general})}} {\memgloref{}}|memjustarg}{1862} -\glossaryentry{semaphore.syn@ {\memgloterm{semaphore.syn}}{\memglodesc{(\ref {semaphore.syn})}} {\memgloref{}}|memjustarg}{1862} -\glossaryentry{thread.sema.cnt@ {\memgloterm{thread.sema.cnt}}{\memglodesc{(\ref {thread.sema.cnt})}} {\memgloref{}}|memjustarg}{1862} -\glossaryentry{thread.coord@ {\memgloterm{thread.coord}}{\memglodesc{(\ref {thread.coord})}} {\memgloref{}}|memjustarg}{1863} -\glossaryentry{thread.coord.general@ {\memgloterm{thread.coord.general}}{\memglodesc{(\ref {thread.coord.general})}} {\memgloref{}}|memjustarg}{1863} -\glossaryentry{thread.latch@ {\memgloterm{thread.latch}}{\memglodesc{(\ref {thread.latch})}} {\memgloref{}}|memjustarg}{1863} -\glossaryentry{thread.latch.general@ {\memgloterm{thread.latch.general}}{\memglodesc{(\ref {thread.latch.general})}} {\memgloref{}}|memjustarg}{1863} -\glossaryentry{latch.syn@ {\memgloterm{latch.syn}}{\memglodesc{(\ref {latch.syn})}} {\memgloref{}}|memjustarg}{1864} -\glossaryentry{thread.latch.class@ {\memgloterm{thread.latch.class}}{\memglodesc{(\ref {thread.latch.class})}} {\memgloref{}}|memjustarg}{1864} -\glossaryentry{thread.barrier@ {\memgloterm{thread.barrier}}{\memglodesc{(\ref {thread.barrier})}} {\memgloref{}}|memjustarg}{1865} -\glossaryentry{thread.barrier.general@ {\memgloterm{thread.barrier.general}}{\memglodesc{(\ref {thread.barrier.general})}} {\memgloref{}}|memjustarg}{1865} -\glossaryentry{barrier.syn@ {\memgloterm{barrier.syn}}{\memglodesc{(\ref {barrier.syn})}} {\memgloref{}}|memjustarg}{1865} -\glossaryentry{thread.barrier.class@ {\memgloterm{thread.barrier.class}}{\memglodesc{(\ref {thread.barrier.class})}} {\memgloref{}}|memjustarg}{1865} -\glossaryentry{futures@ {\memgloterm{futures}}{\memglodesc{(\ref {futures})}} {\memgloref{}}|memjustarg}{1867} -\glossaryentry{futures.overview@ {\memgloterm{futures.overview}}{\memglodesc{(\ref {futures.overview})}} {\memgloref{}}|memjustarg}{1867} -\glossaryentry{future.syn@ {\memgloterm{future.syn}}{\memglodesc{(\ref {future.syn})}} {\memgloref{}}|memjustarg}{1867} -\glossaryentry{futures.errors@ {\memgloterm{futures.errors}}{\memglodesc{(\ref {futures.errors})}} {\memgloref{}}|memjustarg}{1868} -\glossaryentry{futures.future.error@ {\memgloterm{futures.future.error}}{\memglodesc{(\ref {futures.future.error})}} {\memgloref{}}|memjustarg}{1868} -\glossaryentry{futures.state@ {\memgloterm{futures.state}}{\memglodesc{(\ref {futures.state})}} {\memgloref{}}|memjustarg}{1869} -\glossaryentry{futures.promise@ {\memgloterm{futures.promise}}{\memglodesc{(\ref {futures.promise})}} {\memgloref{}}|memjustarg}{1870} -\glossaryentry{futures.unique.future@ {\memgloterm{futures.unique.future}}{\memglodesc{(\ref {futures.unique.future})}} {\memgloref{}}|memjustarg}{1872} -\glossaryentry{futures.shared.future@ {\memgloterm{futures.shared.future}}{\memglodesc{(\ref {futures.shared.future})}} {\memgloref{}}|memjustarg}{1874} -\glossaryentry{futures.async@ {\memgloterm{futures.async}}{\memglodesc{(\ref {futures.async})}} {\memgloref{}}|memjustarg}{1877} -\glossaryentry{futures.task@ {\memgloterm{futures.task}}{\memglodesc{(\ref {futures.task})}} {\memgloref{}}|memjustarg}{1878} -\glossaryentry{futures.task.general@ {\memgloterm{futures.task.general}}{\memglodesc{(\ref {futures.task.general})}} {\memgloref{}}|memjustarg}{1878} -\glossaryentry{futures.task.members@ {\memgloterm{futures.task.members}}{\memglodesc{(\ref {futures.task.members})}} {\memgloref{}}|memjustarg}{1879} -\glossaryentry{futures.task.nonmembers@ {\memgloterm{futures.task.nonmembers}}{\memglodesc{(\ref {futures.task.nonmembers})}} {\memgloref{}}|memjustarg}{1880} -\glossaryentry{gram@ {\memgloterm{gram}}{\memglodesc{(\ref {gram})}} {\memgloref{}}|memjustarg}{1881} -\glossaryentry{gram.general@ {\memgloterm{gram.general}}{\memglodesc{(\ref {gram.general})}} {\memgloref{}}|memjustarg}{1881} -\glossaryentry{gram.key@ {\memgloterm{gram.key}}{\memglodesc{(\ref {gram.key})}} {\memgloref{}}|memjustarg}{1881} -\glossaryentry{gram.lex@ {\memgloterm{gram.lex}}{\memglodesc{(\ref {gram.lex})}} {\memgloref{}}|memjustarg}{1881} -\glossaryentry{gram.basic@ {\memgloterm{gram.basic}}{\memglodesc{(\ref {gram.basic})}} {\memgloref{}}|memjustarg}{1886} -\glossaryentry{gram.expr@ {\memgloterm{gram.expr}}{\memglodesc{(\ref {gram.expr})}} {\memgloref{}}|memjustarg}{1886} -\glossaryentry{gram.stmt@ {\memgloterm{gram.stmt}}{\memglodesc{(\ref {gram.stmt})}} {\memgloref{}}|memjustarg}{1890} -\glossaryentry{gram.dcl@ {\memgloterm{gram.dcl}}{\memglodesc{(\ref {gram.dcl})}} {\memgloref{}}|memjustarg}{1891} -\glossaryentry{gram.module@ {\memgloterm{gram.module}}{\memglodesc{(\ref {gram.module})}} {\memgloref{}}|memjustarg}{1897} -\glossaryentry{gram.class@ {\memgloterm{gram.class}}{\memglodesc{(\ref {gram.class})}} {\memgloref{}}|memjustarg}{1898} -\glossaryentry{gram.over@ {\memgloterm{gram.over}}{\memglodesc{(\ref {gram.over})}} {\memgloref{}}|memjustarg}{1899} -\glossaryentry{gram.temp@ {\memgloterm{gram.temp}}{\memglodesc{(\ref {gram.temp})}} {\memgloref{}}|memjustarg}{1899} -\glossaryentry{gram.except@ {\memgloterm{gram.except}}{\memglodesc{(\ref {gram.except})}} {\memgloref{}}|memjustarg}{1900} -\glossaryentry{gram.cpp@ {\memgloterm{gram.cpp}}{\memglodesc{(\ref {gram.cpp})}} {\memgloref{}}|memjustarg}{1901} -\glossaryentry{implimits@ {\memgloterm{implimits}}{\memglodesc{(\ref {implimits})}} {\memgloref{}}|memjustarg}{1903} -\glossaryentry{diff@ {\memgloterm{diff}}{\memglodesc{(\ref {diff})}} {\memgloref{}}|memjustarg}{1905} -\glossaryentry{diff.cpp20@ {\memgloterm{diff.cpp20}}{\memglodesc{(\ref {diff.cpp20})}} {\memgloref{}}|memjustarg}{1905} -\glossaryentry{diff.cpp20.general@ {\memgloterm{diff.cpp20.general}}{\memglodesc{(\ref {diff.cpp20.general})}} {\memgloref{}}|memjustarg}{1905} -\glossaryentry{diff.cpp20.lex@ {\memgloterm{diff.cpp20.lex}}{\memglodesc{(\ref {diff.cpp20.lex})}} {\memgloref{}}|memjustarg}{1905} -\glossaryentry{diff.cpp20.expr@ {\memgloterm{diff.cpp20.expr}}{\memglodesc{(\ref {diff.cpp20.expr})}} {\memgloref{}}|memjustarg}{1905} -\glossaryentry{diff.cpp20.stmt@ {\memgloterm{diff.cpp20.stmt}}{\memglodesc{(\ref {diff.cpp20.stmt})}} {\memgloref{}}|memjustarg}{1905} -\glossaryentry{diff.cpp20.dcl@ {\memgloterm{diff.cpp20.dcl}}{\memglodesc{(\ref {diff.cpp20.dcl})}} {\memgloref{}}|memjustarg}{1906} -\glossaryentry{diff.cpp20.temp@ {\memgloterm{diff.cpp20.temp}}{\memglodesc{(\ref {diff.cpp20.temp})}} {\memgloref{}}|memjustarg}{1906} -\glossaryentry{diff.cpp20.library@ {\memgloterm{diff.cpp20.library}}{\memglodesc{(\ref {diff.cpp20.library})}} {\memgloref{}}|memjustarg}{1906} -\glossaryentry{diff.cpp20.concepts@ {\memgloterm{diff.cpp20.concepts}}{\memglodesc{(\ref {diff.cpp20.concepts})}} {\memgloref{}}|memjustarg}{1906} -\glossaryentry{diff.cpp20.memory@ {\memgloterm{diff.cpp20.memory}}{\memglodesc{(\ref {diff.cpp20.memory})}} {\memgloref{}}|memjustarg}{1907} -\glossaryentry{diff.cpp20.utilities@ {\memgloterm{diff.cpp20.utilities}}{\memglodesc{(\ref {diff.cpp20.utilities})}} {\memgloref{}}|memjustarg}{1907} -\glossaryentry{diff.cpp20.strings@ {\memgloterm{diff.cpp20.strings}}{\memglodesc{(\ref {diff.cpp20.strings})}} {\memgloref{}}|memjustarg}{1907} -\glossaryentry{diff.cpp20.containers@ {\memgloterm{diff.cpp20.containers}}{\memglodesc{(\ref {diff.cpp20.containers})}} {\memgloref{}}|memjustarg}{1908} -\glossaryentry{diff.cpp20.thread@ {\memgloterm{diff.cpp20.thread}}{\memglodesc{(\ref {diff.cpp20.thread})}} {\memgloref{}}|memjustarg}{1908} -\glossaryentry{diff.cpp17@ {\memgloterm{diff.cpp17}}{\memglodesc{(\ref {diff.cpp17})}} {\memgloref{}}|memjustarg}{1908} -\glossaryentry{diff.cpp17.general@ {\memgloterm{diff.cpp17.general}}{\memglodesc{(\ref {diff.cpp17.general})}} {\memgloref{}}|memjustarg}{1908} -\glossaryentry{diff.cpp17.lex@ {\memgloterm{diff.cpp17.lex}}{\memglodesc{(\ref {diff.cpp17.lex})}} {\memgloref{}}|memjustarg}{1908} -\glossaryentry{diff.cpp17.basic@ {\memgloterm{diff.cpp17.basic}}{\memglodesc{(\ref {diff.cpp17.basic})}} {\memgloref{}}|memjustarg}{1910} -\glossaryentry{diff.cpp17.expr@ {\memgloterm{diff.cpp17.expr}}{\memglodesc{(\ref {diff.cpp17.expr})}} {\memgloref{}}|memjustarg}{1910} -\glossaryentry{diff.cpp17.dcl.dcl@ {\memgloterm{diff.cpp17.dcl.dcl}}{\memglodesc{(\ref {diff.cpp17.dcl.dcl})}} {\memgloref{}}|memjustarg}{1910} -\glossaryentry{diff.cpp17.class@ {\memgloterm{diff.cpp17.class}}{\memglodesc{(\ref {diff.cpp17.class})}} {\memgloref{}}|memjustarg}{1911} -\glossaryentry{diff.cpp17.over@ {\memgloterm{diff.cpp17.over}}{\memglodesc{(\ref {diff.cpp17.over})}} {\memgloref{}}|memjustarg}{1912} -\glossaryentry{diff.cpp17.temp@ {\memgloterm{diff.cpp17.temp}}{\memglodesc{(\ref {diff.cpp17.temp})}} {\memgloref{}}|memjustarg}{1913} -\glossaryentry{diff.cpp17.except@ {\memgloterm{diff.cpp17.except}}{\memglodesc{(\ref {diff.cpp17.except})}} {\memgloref{}}|memjustarg}{1913} -\glossaryentry{diff.cpp17.library@ {\memgloterm{diff.cpp17.library}}{\memglodesc{(\ref {diff.cpp17.library})}} {\memgloref{}}|memjustarg}{1913} -\glossaryentry{diff.cpp17.containers@ {\memgloterm{diff.cpp17.containers}}{\memglodesc{(\ref {diff.cpp17.containers})}} {\memgloref{}}|memjustarg}{1914} -\glossaryentry{diff.cpp17.iterators@ {\memgloterm{diff.cpp17.iterators}}{\memglodesc{(\ref {diff.cpp17.iterators})}} {\memgloref{}}|memjustarg}{1914} -\glossaryentry{diff.cpp17.alg.reqs@ {\memgloterm{diff.cpp17.alg.reqs}}{\memglodesc{(\ref {diff.cpp17.alg.reqs})}} {\memgloref{}}|memjustarg}{1914} -\glossaryentry{diff.cpp17.input.output@ {\memgloterm{diff.cpp17.input.output}}{\memglodesc{(\ref {diff.cpp17.input.output})}} {\memgloref{}}|memjustarg}{1914} -\glossaryentry{diff.cpp17.depr@ {\memgloterm{diff.cpp17.depr}}{\memglodesc{(\ref {diff.cpp17.depr})}} {\memgloref{}}|memjustarg}{1915} -\glossaryentry{diff.cpp14@ {\memgloterm{diff.cpp14}}{\memglodesc{(\ref {diff.cpp14})}} {\memgloref{}}|memjustarg}{1916} -\glossaryentry{diff.cpp14.general@ {\memgloterm{diff.cpp14.general}}{\memglodesc{(\ref {diff.cpp14.general})}} {\memgloref{}}|memjustarg}{1916} -\glossaryentry{diff.cpp14.lex@ {\memgloterm{diff.cpp14.lex}}{\memglodesc{(\ref {diff.cpp14.lex})}} {\memgloref{}}|memjustarg}{1916} -\glossaryentry{diff.cpp14.expr@ {\memgloterm{diff.cpp14.expr}}{\memglodesc{(\ref {diff.cpp14.expr})}} {\memgloref{}}|memjustarg}{1916} -\glossaryentry{diff.cpp14.dcl.dcl@ {\memgloterm{diff.cpp14.dcl.dcl}}{\memglodesc{(\ref {diff.cpp14.dcl.dcl})}} {\memgloref{}}|memjustarg}{1916} -\glossaryentry{diff.cpp14.class@ {\memgloterm{diff.cpp14.class}}{\memglodesc{(\ref {diff.cpp14.class})}} {\memgloref{}}|memjustarg}{1917} -\glossaryentry{diff.cpp14.temp@ {\memgloterm{diff.cpp14.temp}}{\memglodesc{(\ref {diff.cpp14.temp})}} {\memgloref{}}|memjustarg}{1917} -\glossaryentry{diff.cpp14.except@ {\memgloterm{diff.cpp14.except}}{\memglodesc{(\ref {diff.cpp14.except})}} {\memgloref{}}|memjustarg}{1918} -\glossaryentry{diff.cpp14.library@ {\memgloterm{diff.cpp14.library}}{\memglodesc{(\ref {diff.cpp14.library})}} {\memgloref{}}|memjustarg}{1918} -\glossaryentry{diff.cpp14.utilities@ {\memgloterm{diff.cpp14.utilities}}{\memglodesc{(\ref {diff.cpp14.utilities})}} {\memgloref{}}|memjustarg}{1918} -\glossaryentry{diff.cpp14.string@ {\memgloterm{diff.cpp14.string}}{\memglodesc{(\ref {diff.cpp14.string})}} {\memgloref{}}|memjustarg}{1918} -\glossaryentry{diff.cpp14.containers@ {\memgloterm{diff.cpp14.containers}}{\memglodesc{(\ref {diff.cpp14.containers})}} {\memgloref{}}|memjustarg}{1919} -\glossaryentry{diff.cpp14.depr@ {\memgloterm{diff.cpp14.depr}}{\memglodesc{(\ref {diff.cpp14.depr})}} {\memgloref{}}|memjustarg}{1919} -\glossaryentry{diff.cpp11@ {\memgloterm{diff.cpp11}}{\memglodesc{(\ref {diff.cpp11})}} {\memgloref{}}|memjustarg}{1919} -\glossaryentry{diff.cpp11.general@ {\memgloterm{diff.cpp11.general}}{\memglodesc{(\ref {diff.cpp11.general})}} {\memgloref{}}|memjustarg}{1919} -\glossaryentry{diff.cpp11.lex@ {\memgloterm{diff.cpp11.lex}}{\memglodesc{(\ref {diff.cpp11.lex})}} {\memgloref{}}|memjustarg}{1919} -\glossaryentry{diff.cpp11.basic@ {\memgloterm{diff.cpp11.basic}}{\memglodesc{(\ref {diff.cpp11.basic})}} {\memgloref{}}|memjustarg}{1920} -\glossaryentry{diff.cpp11.expr@ {\memgloterm{diff.cpp11.expr}}{\memglodesc{(\ref {diff.cpp11.expr})}} {\memgloref{}}|memjustarg}{1920} -\glossaryentry{diff.cpp11.dcl.dcl@ {\memgloterm{diff.cpp11.dcl.dcl}}{\memglodesc{(\ref {diff.cpp11.dcl.dcl})}} {\memgloref{}}|memjustarg}{1920} -\glossaryentry{diff.cpp11.library@ {\memgloterm{diff.cpp11.library}}{\memglodesc{(\ref {diff.cpp11.library})}} {\memgloref{}}|memjustarg}{1921} -\glossaryentry{diff.cpp11.input.output@ {\memgloterm{diff.cpp11.input.output}}{\memglodesc{(\ref {diff.cpp11.input.output})}} {\memgloref{}}|memjustarg}{1921} -\glossaryentry{diff.cpp03@ {\memgloterm{diff.cpp03}}{\memglodesc{(\ref {diff.cpp03})}} {\memgloref{}}|memjustarg}{1921} -\glossaryentry{diff.cpp03.general@ {\memgloterm{diff.cpp03.general}}{\memglodesc{(\ref {diff.cpp03.general})}} {\memgloref{}}|memjustarg}{1921} -\glossaryentry{diff.cpp03.lex@ {\memgloterm{diff.cpp03.lex}}{\memglodesc{(\ref {diff.cpp03.lex})}} {\memgloref{}}|memjustarg}{1921} -\glossaryentry{diff.cpp03.expr@ {\memgloterm{diff.cpp03.expr}}{\memglodesc{(\ref {diff.cpp03.expr})}} {\memgloref{}}|memjustarg}{1922} -\glossaryentry{diff.cpp03.dcl.dcl@ {\memgloterm{diff.cpp03.dcl.dcl}}{\memglodesc{(\ref {diff.cpp03.dcl.dcl})}} {\memgloref{}}|memjustarg}{1922} -\glossaryentry{diff.cpp03.class@ {\memgloterm{diff.cpp03.class}}{\memglodesc{(\ref {diff.cpp03.class})}} {\memgloref{}}|memjustarg}{1922} -\glossaryentry{diff.cpp03.temp@ {\memgloterm{diff.cpp03.temp}}{\memglodesc{(\ref {diff.cpp03.temp})}} {\memgloref{}}|memjustarg}{1923} -\glossaryentry{diff.cpp03.library@ {\memgloterm{diff.cpp03.library}}{\memglodesc{(\ref {diff.cpp03.library})}} {\memgloref{}}|memjustarg}{1923} -\glossaryentry{diff.cpp03.language.support@ {\memgloterm{diff.cpp03.language.support}}{\memglodesc{(\ref {diff.cpp03.language.support})}} {\memgloref{}}|memjustarg}{1924} -\glossaryentry{diff.cpp03.diagnostics@ {\memgloterm{diff.cpp03.diagnostics}}{\memglodesc{(\ref {diff.cpp03.diagnostics})}} {\memgloref{}}|memjustarg}{1924} -\glossaryentry{diff.cpp03.utilities@ {\memgloterm{diff.cpp03.utilities}}{\memglodesc{(\ref {diff.cpp03.utilities})}} {\memgloref{}}|memjustarg}{1924} -\glossaryentry{diff.cpp03.strings@ {\memgloterm{diff.cpp03.strings}}{\memglodesc{(\ref {diff.cpp03.strings})}} {\memgloref{}}|memjustarg}{1924} -\glossaryentry{diff.cpp03.containers@ {\memgloterm{diff.cpp03.containers}}{\memglodesc{(\ref {diff.cpp03.containers})}} {\memgloref{}}|memjustarg}{1924} -\glossaryentry{diff.cpp03.algorithms@ {\memgloterm{diff.cpp03.algorithms}}{\memglodesc{(\ref {diff.cpp03.algorithms})}} {\memgloref{}}|memjustarg}{1925} -\glossaryentry{diff.cpp03.numerics@ {\memgloterm{diff.cpp03.numerics}}{\memglodesc{(\ref {diff.cpp03.numerics})}} {\memgloref{}}|memjustarg}{1925} -\glossaryentry{diff.cpp03.locale@ {\memgloterm{diff.cpp03.locale}}{\memglodesc{(\ref {diff.cpp03.locale})}} {\memgloref{}}|memjustarg}{1925} -\glossaryentry{diff.cpp03.input.output@ {\memgloterm{diff.cpp03.input.output}}{\memglodesc{(\ref {diff.cpp03.input.output})}} {\memgloref{}}|memjustarg}{1926} -\glossaryentry{diff.iso@ {\memgloterm{diff.iso}}{\memglodesc{(\ref {diff.iso})}} {\memgloref{}}|memjustarg}{1926} -\glossaryentry{diff.iso.general@ {\memgloterm{diff.iso.general}}{\memglodesc{(\ref {diff.iso.general})}} {\memgloref{}}|memjustarg}{1926} -\glossaryentry{diff.lex@ {\memgloterm{diff.lex}}{\memglodesc{(\ref {diff.lex})}} {\memgloref{}}|memjustarg}{1926} -\glossaryentry{diff.basic@ {\memgloterm{diff.basic}}{\memglodesc{(\ref {diff.basic})}} {\memgloref{}}|memjustarg}{1927} -\glossaryentry{diff.expr@ {\memgloterm{diff.expr}}{\memglodesc{(\ref {diff.expr})}} {\memgloref{}}|memjustarg}{1928} -\glossaryentry{diff.stat@ {\memgloterm{diff.stat}}{\memglodesc{(\ref {diff.stat})}} {\memgloref{}}|memjustarg}{1929} -\glossaryentry{diff.dcl@ {\memgloterm{diff.dcl}}{\memglodesc{(\ref {diff.dcl})}} {\memgloref{}}|memjustarg}{1929} -\glossaryentry{diff.class@ {\memgloterm{diff.class}}{\memglodesc{(\ref {diff.class})}} {\memgloref{}}|memjustarg}{1932} -\glossaryentry{diff.cpp@ {\memgloterm{diff.cpp}}{\memglodesc{(\ref {diff.cpp})}} {\memgloref{}}|memjustarg}{1934} -\glossaryentry{diff.library@ {\memgloterm{diff.library}}{\memglodesc{(\ref {diff.library})}} {\memgloref{}}|memjustarg}{1934} -\glossaryentry{diff.library.general@ {\memgloterm{diff.library.general}}{\memglodesc{(\ref {diff.library.general})}} {\memgloref{}}|memjustarg}{1934} -\glossaryentry{diff.mods.to.headers@ {\memgloterm{diff.mods.to.headers}}{\memglodesc{(\ref {diff.mods.to.headers})}} {\memgloref{}}|memjustarg}{1934} -\glossaryentry{diff.mods.to.definitions@ {\memgloterm{diff.mods.to.definitions}}{\memglodesc{(\ref {diff.mods.to.definitions})}} {\memgloref{}}|memjustarg}{1934} -\glossaryentry{diff.char16@ {\memgloterm{diff.char16}}{\memglodesc{(\ref {diff.char16})}} {\memgloref{}}|memjustarg}{1934} -\glossaryentry{diff.wchar.t@ {\memgloterm{diff.wchar.t}}{\memglodesc{(\ref {diff.wchar.t})}} {\memgloref{}}|memjustarg}{1934} -\glossaryentry{diff.header.assert.h@ {\memgloterm{diff.header.assert.h}}{\memglodesc{(\ref {diff.header.assert.h})}} {\memgloref{}}|memjustarg}{1935} -\glossaryentry{diff.header.iso646.h@ {\memgloterm{diff.header.iso646.h}}{\memglodesc{(\ref {diff.header.iso646.h})}} {\memgloref{}}|memjustarg}{1935} -\glossaryentry{diff.header.stdalign.h@ {\memgloterm{diff.header.stdalign.h}}{\memglodesc{(\ref {diff.header.stdalign.h})}} {\memgloref{}}|memjustarg}{1935} -\glossaryentry{diff.header.stdbool.h@ {\memgloterm{diff.header.stdbool.h}}{\memglodesc{(\ref {diff.header.stdbool.h})}} {\memgloref{}}|memjustarg}{1935} -\glossaryentry{diff.null@ {\memgloterm{diff.null}}{\memglodesc{(\ref {diff.null})}} {\memgloref{}}|memjustarg}{1935} -\glossaryentry{diff.mods.to.declarations@ {\memgloterm{diff.mods.to.declarations}}{\memglodesc{(\ref {diff.mods.to.declarations})}} {\memgloref{}}|memjustarg}{1935} -\glossaryentry{diff.mods.to.behavior@ {\memgloterm{diff.mods.to.behavior}}{\memglodesc{(\ref {diff.mods.to.behavior})}} {\memgloref{}}|memjustarg}{1935} -\glossaryentry{diff.mods.to.behavior.general@ {\memgloterm{diff.mods.to.behavior.general}}{\memglodesc{(\ref {diff.mods.to.behavior.general})}} {\memgloref{}}|memjustarg}{1935} -\glossaryentry{diff.offsetof@ {\memgloterm{diff.offsetof}}{\memglodesc{(\ref {diff.offsetof})}} {\memgloref{}}|memjustarg}{1936} -\glossaryentry{diff.malloc@ {\memgloterm{diff.malloc}}{\memglodesc{(\ref {diff.malloc})}} {\memgloref{}}|memjustarg}{1936} -\glossaryentry{depr@ {\memgloterm{depr}}{\memglodesc{(\ref {depr})}} {\memgloref{}}|memjustarg}{1937} -\glossaryentry{depr.general@ {\memgloterm{depr.general}}{\memglodesc{(\ref {depr.general})}} {\memgloref{}}|memjustarg}{1937} -\glossaryentry{depr.arith.conv.enum@ {\memgloterm{depr.arith.conv.enum}}{\memglodesc{(\ref {depr.arith.conv.enum})}} {\memgloref{}}|memjustarg}{1937} -\glossaryentry{depr.capture.this@ {\memgloterm{depr.capture.this}}{\memglodesc{(\ref {depr.capture.this})}} {\memgloref{}}|memjustarg}{1937} -\glossaryentry{depr.array.comp@ {\memgloterm{depr.array.comp}}{\memglodesc{(\ref {depr.array.comp})}} {\memgloref{}}|memjustarg}{1937} -\glossaryentry{depr.volatile.type@ {\memgloterm{depr.volatile.type}}{\memglodesc{(\ref {depr.volatile.type})}} {\memgloref{}}|memjustarg}{1937} -\glossaryentry{depr.static.constexpr@ {\memgloterm{depr.static.constexpr}}{\memglodesc{(\ref {depr.static.constexpr})}} {\memgloref{}}|memjustarg}{1938} -\glossaryentry{depr.local@ {\memgloterm{depr.local}}{\memglodesc{(\ref {depr.local})}} {\memgloref{}}|memjustarg}{1938} -\glossaryentry{depr.impldec@ {\memgloterm{depr.impldec}}{\memglodesc{(\ref {depr.impldec})}} {\memgloref{}}|memjustarg}{1939} -\glossaryentry{depr.lit@ {\memgloterm{depr.lit}}{\memglodesc{(\ref {depr.lit})}} {\memgloref{}}|memjustarg}{1939} -\glossaryentry{depr.template.template@ {\memgloterm{depr.template.template}}{\memglodesc{(\ref {depr.template.template})}} {\memgloref{}}|memjustarg}{1939} -\glossaryentry{depr.res.on.required@ {\memgloterm{depr.res.on.required}}{\memglodesc{(\ref {depr.res.on.required})}} {\memgloref{}}|memjustarg}{1939} -\glossaryentry{depr.numeric.limits.has.denorm@ {\memgloterm{depr.numeric.limits.has.denorm}}{\memglodesc{(\ref {depr.numeric.limits.has.denorm})}} {\memgloref{}}|memjustarg}{1939} -\glossaryentry{depr.c.macros@ {\memgloterm{depr.c.macros}}{\memglodesc{(\ref {depr.c.macros})}} {\memgloref{}}|memjustarg}{1939} -\glossaryentry{depr.relops@ {\memgloterm{depr.relops}}{\memglodesc{(\ref {depr.relops})}} {\memgloref{}}|memjustarg}{1939} -\glossaryentry{depr.str.strstreams@ {\memgloterm{depr.str.strstreams}}{\memglodesc{(\ref {depr.str.strstreams})}} {\memgloref{}}|memjustarg}{1940} -\glossaryentry{depr.strstream.syn@ {\memgloterm{depr.strstream.syn}}{\memglodesc{(\ref {depr.strstream.syn})}} {\memgloref{}}|memjustarg}{1940} -\glossaryentry{depr.strstreambuf@ {\memgloterm{depr.strstreambuf}}{\memglodesc{(\ref {depr.strstreambuf})}} {\memgloref{}}|memjustarg}{1940} -\glossaryentry{depr.strstreambuf.general@ {\memgloterm{depr.strstreambuf.general}}{\memglodesc{(\ref {depr.strstreambuf.general})}} {\memgloref{}}|memjustarg}{1940} -\glossaryentry{depr.strstreambuf.cons@ {\memgloterm{depr.strstreambuf.cons}}{\memglodesc{(\ref {depr.strstreambuf.cons})}} {\memgloref{}}|memjustarg}{1941} -\glossaryentry{depr.strstreambuf.members@ {\memgloterm{depr.strstreambuf.members}}{\memglodesc{(\ref {depr.strstreambuf.members})}} {\memgloref{}}|memjustarg}{1942} -\glossaryentry{depr.strstreambuf.virtuals@ {\memgloterm{depr.strstreambuf.virtuals}}{\memglodesc{(\ref {depr.strstreambuf.virtuals})}} {\memgloref{}}|memjustarg}{1943} -\glossaryentry{depr.istrstream@ {\memgloterm{depr.istrstream}}{\memglodesc{(\ref {depr.istrstream})}} {\memgloref{}}|memjustarg}{1945} -\glossaryentry{depr.istrstream.general@ {\memgloterm{depr.istrstream.general}}{\memglodesc{(\ref {depr.istrstream.general})}} {\memgloref{}}|memjustarg}{1945} -\glossaryentry{depr.istrstream.cons@ {\memgloterm{depr.istrstream.cons}}{\memglodesc{(\ref {depr.istrstream.cons})}} {\memgloref{}}|memjustarg}{1945} -\glossaryentry{depr.istrstream.members@ {\memgloterm{depr.istrstream.members}}{\memglodesc{(\ref {depr.istrstream.members})}} {\memgloref{}}|memjustarg}{1945} -\glossaryentry{depr.ostrstream@ {\memgloterm{depr.ostrstream}}{\memglodesc{(\ref {depr.ostrstream})}} {\memgloref{}}|memjustarg}{1945} -\glossaryentry{depr.ostrstream.general@ {\memgloterm{depr.ostrstream.general}}{\memglodesc{(\ref {depr.ostrstream.general})}} {\memgloref{}}|memjustarg}{1945} -\glossaryentry{depr.ostrstream.cons@ {\memgloterm{depr.ostrstream.cons}}{\memglodesc{(\ref {depr.ostrstream.cons})}} {\memgloref{}}|memjustarg}{1946} -\glossaryentry{depr.ostrstream.members@ {\memgloterm{depr.ostrstream.members}}{\memglodesc{(\ref {depr.ostrstream.members})}} {\memgloref{}}|memjustarg}{1946} -\glossaryentry{depr.strstream@ {\memgloterm{depr.strstream}}{\memglodesc{(\ref {depr.strstream})}} {\memgloref{}}|memjustarg}{1946} -\glossaryentry{depr.strstream.general@ {\memgloterm{depr.strstream.general}}{\memglodesc{(\ref {depr.strstream.general})}} {\memgloref{}}|memjustarg}{1946} -\glossaryentry{depr.strstream.cons@ {\memgloterm{depr.strstream.cons}}{\memglodesc{(\ref {depr.strstream.cons})}} {\memgloref{}}|memjustarg}{1947} -\glossaryentry{depr.strstream.dest@ {\memgloterm{depr.strstream.dest}}{\memglodesc{(\ref {depr.strstream.dest})}} {\memgloref{}}|memjustarg}{1947} -\glossaryentry{depr.strstream.oper@ {\memgloterm{depr.strstream.oper}}{\memglodesc{(\ref {depr.strstream.oper})}} {\memgloref{}}|memjustarg}{1947} -\glossaryentry{depr.cerrno@ {\memgloterm{depr.cerrno}}{\memglodesc{(\ref {depr.cerrno})}} {\memgloref{}}|memjustarg}{1947} -\glossaryentry{depr.default.allocator@ {\memgloterm{depr.default.allocator}}{\memglodesc{(\ref {depr.default.allocator})}} {\memgloref{}}|memjustarg}{1948} -\glossaryentry{depr.mem.poly.allocator.mem@ {\memgloterm{depr.mem.poly.allocator.mem}}{\memglodesc{(\ref {depr.mem.poly.allocator.mem})}} {\memgloref{}}|memjustarg}{1948} -\glossaryentry{depr.meta.types@ {\memgloterm{depr.meta.types}}{\memglodesc{(\ref {depr.meta.types})}} {\memgloref{}}|memjustarg}{1948} -\glossaryentry{depr.tuple@ {\memgloterm{depr.tuple}}{\memglodesc{(\ref {depr.tuple})}} {\memgloref{}}|memjustarg}{1949} -\glossaryentry{depr.variant@ {\memgloterm{depr.variant}}{\memglodesc{(\ref {depr.variant})}} {\memgloref{}}|memjustarg}{1950} -\glossaryentry{depr.iterator@ {\memgloterm{depr.iterator}}{\memglodesc{(\ref {depr.iterator})}} {\memgloref{}}|memjustarg}{1950} -\glossaryentry{depr.move.iter.elem@ {\memgloterm{depr.move.iter.elem}}{\memglodesc{(\ref {depr.move.iter.elem})}} {\memgloref{}}|memjustarg}{1950} -\glossaryentry{depr.util.smartptr.shared.atomic@ {\memgloterm{depr.util.smartptr.shared.atomic}}{\memglodesc{(\ref {depr.util.smartptr.shared.atomic})}} {\memgloref{}}|memjustarg}{1951} -\glossaryentry{depr.string.capacity@ {\memgloterm{depr.string.capacity}}{\memglodesc{(\ref {depr.string.capacity})}} {\memgloref{}}|memjustarg}{1953} -\glossaryentry{depr.locale.stdcvt@ {\memgloterm{depr.locale.stdcvt}}{\memglodesc{(\ref {depr.locale.stdcvt})}} {\memgloref{}}|memjustarg}{1953} -\glossaryentry{depr.locale.stdcvt.general@ {\memgloterm{depr.locale.stdcvt.general}}{\memglodesc{(\ref {depr.locale.stdcvt.general})}} {\memgloref{}}|memjustarg}{1953} -\glossaryentry{depr.codecvt.syn@ {\memgloterm{depr.codecvt.syn}}{\memglodesc{(\ref {depr.codecvt.syn})}} {\memgloref{}}|memjustarg}{1953} -\glossaryentry{depr.locale.stdcvt.req@ {\memgloterm{depr.locale.stdcvt.req}}{\memglodesc{(\ref {depr.locale.stdcvt.req})}} {\memgloref{}}|memjustarg}{1954} -\glossaryentry{depr.conversions@ {\memgloterm{depr.conversions}}{\memglodesc{(\ref {depr.conversions})}} {\memgloref{}}|memjustarg}{1954} -\glossaryentry{depr.conversions.general@ {\memgloterm{depr.conversions.general}}{\memglodesc{(\ref {depr.conversions.general})}} {\memgloref{}}|memjustarg}{1954} -\glossaryentry{depr.conversions.string@ {\memgloterm{depr.conversions.string}}{\memglodesc{(\ref {depr.conversions.string})}} {\memgloref{}}|memjustarg}{1954} -\glossaryentry{depr.conversions.buffer@ {\memgloterm{depr.conversions.buffer}}{\memglodesc{(\ref {depr.conversions.buffer})}} {\memgloref{}}|memjustarg}{1956} -\glossaryentry{depr.locale.category@ {\memgloterm{depr.locale.category}}{\memglodesc{(\ref {depr.locale.category})}} {\memgloref{}}|memjustarg}{1958} -\glossaryentry{depr.fs.path.factory@ {\memgloterm{depr.fs.path.factory}}{\memglodesc{(\ref {depr.fs.path.factory})}} {\memgloref{}}|memjustarg}{1958} -\glossaryentry{depr.atomics@ {\memgloterm{depr.atomics}}{\memglodesc{(\ref {depr.atomics})}} {\memgloref{}}|memjustarg}{1958} -\glossaryentry{depr.atomics.general@ {\memgloterm{depr.atomics.general}}{\memglodesc{(\ref {depr.atomics.general})}} {\memgloref{}}|memjustarg}{1958} -\glossaryentry{depr.atomics.volatile@ {\memgloterm{depr.atomics.volatile}}{\memglodesc{(\ref {depr.atomics.volatile})}} {\memgloref{}}|memjustarg}{1959} -\glossaryentry{depr.atomics.nonmembers@ {\memgloterm{depr.atomics.nonmembers}}{\memglodesc{(\ref {depr.atomics.nonmembers})}} {\memgloref{}}|memjustarg}{1959} -\glossaryentry{depr.atomics.types.operations@ {\memgloterm{depr.atomics.types.operations}}{\memglodesc{(\ref {depr.atomics.types.operations})}} {\memgloref{}}|memjustarg}{1959} -\glossaryentry{uaxid@ {\memgloterm{uaxid}}{\memglodesc{(\ref {uaxid})}} {\memgloref{}}|memjustarg}{1960} -\glossaryentry{uaxid.general@ {\memgloterm{uaxid.general}}{\memglodesc{(\ref {uaxid.general})}} {\memgloref{}}|memjustarg}{1960} -\glossaryentry{uaxid.def@ {\memgloterm{uaxid.def}}{\memglodesc{(\ref {uaxid.def})}} {\memgloref{}}|memjustarg}{1960} -\glossaryentry{uaxid.def.general@ {\memgloterm{uaxid.def.general}}{\memglodesc{(\ref {uaxid.def.general})}} {\memgloref{}}|memjustarg}{1960} -\glossaryentry{uaxid.def.rfmt@ {\memgloterm{uaxid.def.rfmt}}{\memglodesc{(\ref {uaxid.def.rfmt})}} {\memgloref{}}|memjustarg}{1960} -\glossaryentry{uaxid.def.stable@ {\memgloterm{uaxid.def.stable}}{\memglodesc{(\ref {uaxid.def.stable})}} {\memgloref{}}|memjustarg}{1960} -\glossaryentry{uaxid.immutable@ {\memgloterm{uaxid.immutable}}{\memglodesc{(\ref {uaxid.immutable})}} {\memgloref{}}|memjustarg}{1960} -\glossaryentry{uaxid.pattern@ {\memgloterm{uaxid.pattern}}{\memglodesc{(\ref {uaxid.pattern})}} {\memgloref{}}|memjustarg}{1960} -\glossaryentry{uaxid.eqn@ {\memgloterm{uaxid.eqn}}{\memglodesc{(\ref {uaxid.eqn})}} {\memgloref{}}|memjustarg}{1961} -\glossaryentry{uaxid.eqci@ {\memgloterm{uaxid.eqci}}{\memglodesc{(\ref {uaxid.eqci})}} {\memgloref{}}|memjustarg}{1961} -\glossaryentry{uaxid.filter@ {\memgloterm{uaxid.filter}}{\memglodesc{(\ref {uaxid.filter})}} {\memgloref{}}|memjustarg}{1961} -\glossaryentry{uaxid.filterci@ {\memgloterm{uaxid.filterci}}{\memglodesc{(\ref {uaxid.filterci})}} {\memgloref{}}|memjustarg}{1961} -\glossaryentry{uaxid.hashtag@ {\memgloterm{uaxid.hashtag}}{\memglodesc{(\ref {uaxid.hashtag})}} {\memgloref{}}|memjustarg}{1961} +accumulate +adjacent.difference +adjustfield.manip +alg.adjacent.find +alg.all.of +alg.all_of +alg.any.of +alg.any_of +alg.binary.search +alg.c.library +alg.clamp +alg.copy +alg.count +alg.equal +alg.fill +alg.find +alg.find.end +alg.find.first.of +alg.foreach +alg.generate +alg.heap.operations +alg.is.permutation +alg.is_permutation +alg.lex.comparison +alg.merge +alg.min.max +alg.modifying.operations +alg.move +alg.none.of +alg.none_of +alg.nonmodifying +alg.nth.element +alg.partitions +alg.permutation.generators +alg.random.sample +alg.random.shuffle +alg.remove +alg.replace +alg.req +alg.req.general +alg.req.ind.cmp +alg.req.ind.copy +alg.req.ind.move +alg.req.ind.swap +alg.req.mergeable +alg.req.permutable +alg.req.sortable +alg.reverse +alg.rotate +alg.search +alg.set.operations +alg.shift +alg.sort +alg.sorting +alg.swap +alg.three.way +alg.transform +alg.unique +algorithm.stable +algorithm.syn +algorithms +algorithms.general +algorithms.parallel +algorithms.parallel.defns +algorithms.parallel.exceptions +algorithms.parallel.exec +algorithms.parallel.overloads +algorithms.parallel.user +algorithms.requirements +algorithms.results +alloc.errors +allocator.adaptor +allocator.adaptor.cnstr +allocator.adaptor.members +allocator.adaptor.syn +allocator.adaptor.types +allocator.globals +allocator.members +allocator.requirements +allocator.requirements.completeness +allocator.tag +allocator.traits +allocator.traits.members +allocator.traits.types +allocator.uses +allocator.uses.construction +allocator.uses.trait +alt.headers +any +any.assign +any.bad.any.cast +any.bad_any_cast +any.class +any.cons +any.modifiers +any.nonmembers +any.observers +any.synop +arithmetic.operations +arithmetic.operations.divides +arithmetic.operations.minus +arithmetic.operations.modulus +arithmetic.operations.multiplies +arithmetic.operations.negate +arithmetic.operations.plus +array +array.cons +array.creation +array.data +array.fill +array.members +array.overview +array.size +array.special +array.swap +array.syn +array.tuple +array.zero +assertions +assertions.assert +associative +associative.general +associative.map.syn +associative.reqmts +associative.reqmts.except +associative.set.syn +atomics +atomics.alias +atomics.fences +atomics.flag +atomics.general +atomics.lockfree +atomics.nonmembers +atomics.order +atomics.ref.float +atomics.ref.generic +atomics.ref.int +atomics.ref.memop +atomics.ref.ops +atomics.ref.pointer +atomics.syn +atomics.types.float +atomics.types.generic +atomics.types.int +atomics.types.memop +atomics.types.operations +atomics.types.pointer +atomics.wait +back.insert.iter.cons +back.insert.iter.op* +back.insert.iter.op++ +back.insert.iter.op= +back.insert.iter.ops +back.insert.iterator +back.inserter +bad.alloc +bad.cast +bad.exception +bad.typeid +barrier.syn +basefield.manip +basic +basic.align +basic.compound +basic.def +basic.def.odr +basic.exec +basic.fundamental +basic.funscope +basic.indet +basic.ios.cons +basic.ios.members +basic.life +basic.link +basic.lookup +basic.lookup.argdep +basic.lookup.classref +basic.lookup.elab +basic.lookup.qual +basic.lookup.udir +basic.lookup.unqual +basic.lval +basic.memobj +basic.namespace +basic.pre +basic.scope +basic.scope.block +basic.scope.class +basic.scope.declarative +basic.scope.enum +basic.scope.hiding +basic.scope.namespace +basic.scope.param +basic.scope.pdecl +basic.scope.proto +basic.scope.temp +basic.start +basic.start.dynamic +basic.start.main +basic.start.static +basic.start.term +basic.stc +basic.stc.auto +basic.stc.dynamic +basic.stc.dynamic.allocation +basic.stc.dynamic.deallocation +basic.stc.dynamic.safety +basic.stc.inherit +basic.stc.static +basic.stc.thread +basic.string +basic.string.hash +basic.string.literals +basic.type.qualifier +basic.types +bidirectional.iterators +binary.search +bit +bit.cast +bit.count +bit.endian +bit.general +bit.pow.two +bit.rotate +bit.syn +bitmask.types +bitset +bitset.cons +bitset.hash +bitset.members +bitset.operators +bitset.syn +bitwise.operations +bitwise.operations.and +bitwise.operations.not +bitwise.operations.or +bitwise.operations.xor +byte.strings +c.files +c.locales +c.malloc +c.math +c.math.abs +c.math.fpclass +c.math.hypot3 +c.math.lerp +c.math.rand +c.mb.wcs +c.strings +cassert.syn +category.collate +category.ctype +category.messages +category.monetary +category.numeric +category.time +cctype.syn +cerrno.syn +cfenv +cfenv.syn +cfloat.syn +char.traits +char.traits.require +char.traits.specializations +char.traits.specializations.char +char.traits.specializations.char16.t +char.traits.specializations.char16_t +char.traits.specializations.char32.t +char.traits.specializations.char32_t +char.traits.specializations.char8.t +char.traits.specializations.wchar.t +char.traits.typedefs +character.seq +charconv +charconv.from.chars +charconv.syn +charconv.to.chars +cinttypes.syn +class +class.abstract +class.access +class.access.base +class.access.nest +class.access.spec +class.access.virt +class.base.init +class.bit +class.cdtor +class.compare +class.compare.default +class.compare.secondary +class.conv +class.conv.ctor +class.conv.fct +class.copy +class.copy.assign +class.copy.ctor +class.copy.elision +class.ctor +class.default.ctor +class.derived +class.dtor +class.eq +class.expl.init +class.free +class.friend +class.gslice +class.gslice.overview +class.inhctor.init +class.init +class.local +class.mem +class.member.lookup +class.mfct +class.mfct.non-static +class.mfct.non-static.general +class.mi +class.name +class.nest +class.nested.type +class.paths +class.pre +class.prop +class.protected +class.qual +class.slice +class.slice.overview +class.spaceship +class.static +class.static.data +class.static.mfct +class.temporary +class.this +class.union +class.union.anon +class.virtual +classification +climits.syn +clocale.syn +cmath.syn +cmp +cmp.alg +cmp.categories +cmp.categories.pre +cmp.common +cmp.concept +cmp.partialord +cmp.result +cmp.strongord +cmp.weakord +cmplx.over +common.iter.access +common.iter.cmp +common.iter.const +common.iter.cust +common.iter.nav +common.iter.types +common.iterator +compare.syn +comparisons +comparisons.equal.to +comparisons.equal_to +comparisons.greater +comparisons.greater.equal +comparisons.greater_equal +comparisons.less +comparisons.less.equal +comparisons.less_equal +comparisons.not.equal.to +comparisons.not_equal_to +comparisons.three.way +complex +complex.literals +complex.member.ops +complex.members +complex.numbers +complex.ops +complex.special +complex.syn +complex.transcendentals +complex.value.ops +compliance +concept.assignable +concept.booleantestable +concept.common +concept.commonref +concept.constructible +concept.convertible +concept.copyconstructible +concept.default.init +concept.derived +concept.destructible +concept.equalitycomparable +concept.equiv +concept.invocable +concept.moveconstructible +concept.predicate +concept.regularinvocable +concept.relation +concept.same +concept.strictweakorder +concept.swappable +concept.totallyordered +concepts +concepts.arithmetic +concepts.callable +concepts.callable.general +concepts.compare +concepts.compare.general +concepts.equality +concepts.general +concepts.lang +concepts.lang.general +concepts.object +concepts.syn +condition.variable.syn +condition_variable.syn +conforming +conforming.overview +cons.slice +constexpr.functions +constraints +constraints.overview +container.adaptors +container.adaptors.general +container.gen.reqmts +container.insert.return +container.node +container.node.cons +container.node.dtor +container.node.modifiers +container.node.observers +container.node.overview +container.requirements +container.requirements.dataraces +container.requirements.general +containers +containers.general +contents +conv +conv.array +conv.bool +conv.double +conv.fctptr +conv.fpint +conv.fpprom +conv.func +conv.integral +conv.lval +conv.mem +conv.prom +conv.ptr +conv.qual +conv.rank +conv.rval +conventions +conversions +conversions.character +coroutine.handle +coroutine.handle.compare +coroutine.handle.con +coroutine.handle.export.import +coroutine.handle.hash +coroutine.handle.noop +coroutine.handle.noop.address +coroutine.handle.noop.observers +coroutine.handle.noop.promise +coroutine.handle.noop.resumption +coroutine.handle.observers +coroutine.handle.promise +coroutine.handle.resumption +coroutine.noop +coroutine.noop.coroutine +coroutine.promise.noop +coroutine.syn +coroutine.traits +coroutine.traits.primary +coroutine.trivial.awaitables +counted.iter.access +counted.iter.cmp +counted.iter.const +counted.iter.cust +counted.iter.elem +counted.iter.nav +counted.iterator +cpp +cpp.concat +cpp.cond +cpp.error +cpp.import +cpp.include +cpp.line +cpp.module +cpp.null +cpp.pragma +cpp.pragma.op +cpp.pre +cpp.predefined +cpp.replace +cpp.rescan +cpp.scope +cpp.stringize +cpp.subst +csetjmp.syn +csignal.syn +cstdarg.syn +cstddef.syn +cstdint +cstdint.general +cstdint.syn +cstdio.syn +cstdlib.syn +cstring.syn +ctime.syn +cuchar.syn +customization.point.object +cwchar.syn +cwctype.syn +dcl.align +dcl.ambig.res +dcl.array +dcl.asm +dcl.attr +dcl.attr.depend +dcl.attr.deprecated +dcl.attr.fallthrough +dcl.attr.grammar +dcl.attr.likelihood +dcl.attr.nodiscard +dcl.attr.noreturn +dcl.attr.nouniqueaddr +dcl.attr.unused +dcl.constexpr +dcl.constinit +dcl.dcl +dcl.decl +dcl.enum +dcl.fct +dcl.fct.def +dcl.fct.def.coroutine +dcl.fct.def.default +dcl.fct.def.delete +dcl.fct.def.general +dcl.fct.default +dcl.fct.spec +dcl.friend +dcl.init +dcl.init.aggr +dcl.init.list +dcl.init.ref +dcl.init.string +dcl.inline +dcl.link +dcl.meaning +dcl.mptr +dcl.name +dcl.pre +dcl.ptr +dcl.ref +dcl.spec +dcl.spec.auto +dcl.stc +dcl.struct.bind +dcl.type +dcl.type.auto.deduct +dcl.type.class.deduct +dcl.type.cv +dcl.type.decltype +dcl.type.elab +dcl.type.simple +dcl.typedef +declval +default.allocator +default.sentinels +definitions +defns.access +defns.arbitrary.stream +defns.argument +defns.argument.macro +defns.argument.templ +defns.argument.throw +defns.block +defns.block.stmt +defns.character +defns.character.container +defns.comparison +defns.component +defns.cond.supp +defns.const.subexpr +defns.deadlock +defns.default.behavior.func +defns.default.behavior.impl +defns.diagnostic +defns.direct-non-list-init +defns.dynamic.type +defns.dynamic.type.prvalue +defns.expression-equivalent +defns.handler +defns.ill.formed +defns.impl.defined +defns.impl.limits +defns.iostream.templates +defns.locale.specific +defns.modifier +defns.move.assign +defns.move.constr +defns.multibyte +defns.ntcts +defns.observer +defns.order.ptr +defns.parameter +defns.parameter.macro +defns.parameter.templ +defns.prog.def.spec +defns.prog.def.type +defns.projection +defns.referenceable +defns.regex.collating.element +defns.regex.finite.state.machine +defns.regex.format.specifier +defns.regex.matched +defns.regex.primary.equivalence.class +defns.regex.regular.expression +defns.regex.subexpression +defns.replacement +defns.repositional.stream +defns.required.behavior +defns.reserved.function +defns.signature +defns.signature.friend +defns.signature.member +defns.signature.member.spec +defns.signature.member.templ +defns.signature.spec +defns.signature.templ +defns.signature.templ.friend +defns.stable +defns.static.type +defns.traits +defns.unblock +defns.undefined +defns.unspecified +defns.valid +defns.well.formed +denorm.style +depr +depr.arith.conv.enum +depr.array.comp +depr.atomics +depr.atomics.flag +depr.atomics.nonmembers +depr.atomics.types.operations +depr.atomics.volatile +depr.c.headers +depr.c.headers.general +depr.c.headers.other +depr.capture.this +depr.ccomplex.syn +depr.codecvt.syn +depr.comma.subscript +depr.complex.h.syn +depr.conversions +depr.conversions.buffer +depr.conversions.general +depr.conversions.string +depr.cpp.headers +depr.cstdalign.syn +depr.cstdbool.syn +depr.ctgmath.syn +depr.default.allocator +depr.default.allocator +depr.except.spec +depr.fs.path.factory +depr.func.adaptor.binding +depr.func.adaptor.typedefs +depr.impldec +depr.iso646.h.syn +depr.istrstream +depr.istrstream.cons +depr.istrstream.general +depr.istrstream.members +depr.iterator.basic +depr.iterator.primitives +depr.local +depr.locale.category +depr.locale.stdcvt +depr.locale.stdcvt.general +depr.locale.stdcvt.req +depr.mem.poly.allocator.mem +depr.meta.types +depr.move.iter.elem +depr.negators +depr.ostrstream +depr.ostrstream.cons +depr.ostrstream.general +depr.ostrstream.members +depr.relops +depr.res.on.required +depr.static.constexpr +depr.static_constexpr +depr.stdalign.h.syn +depr.stdbool.h.syn +depr.storage.iterator +depr.str.strstreams +depr.string.capacity +depr.strstream +depr.strstream.cons +depr.strstream.dest +depr.strstream.general +depr.strstream.oper +depr.strstream.syn +depr.strstreambuf +depr.strstreambuf.cons +depr.strstreambuf.general +depr.strstreambuf.members +depr.strstreambuf.virtuals +depr.temporary.buffer +depr.tgmath.h.syn +depr.tuple +depr.uncaught +depr.util.smartptr.shared.atomic +depr.util.smartptr.shared.obs +depr.variant +depr.volatile.type +depr.weak.result_type +deque +deque.capacity +deque.cons +deque.erasure +deque.modifiers +deque.overview +deque.special +deque.syn +derivation +derived.classes +description +diagnostics +diagnostics.general +diff +diff.basic +diff.char16 +diff.class +diff.conv +diff.cpp +diff.cpp03 +diff.cpp03.algorithms +diff.cpp03.class +diff.cpp03.containers +diff.cpp03.conv +diff.cpp03.dcl.dcl +diff.cpp03.dcl.decl +diff.cpp03.diagnostics +diff.cpp03.expr +diff.cpp03.input.output +diff.cpp03.language.support +diff.cpp03.lex +diff.cpp03.library +diff.cpp03.numerics +diff.cpp03.special +diff.cpp03.strings +diff.cpp03.temp +diff.cpp03.utilities +diff.cpp11 +diff.cpp11.basic +diff.cpp11.dcl.dcl +diff.cpp11.dcl.decl +diff.cpp11.expr +diff.cpp11.input.output +diff.cpp11.lex +diff.cpp11.library +diff.cpp14 +diff.cpp14.class +diff.cpp14.containers +diff.cpp14.dcl.dcl +diff.cpp14.decl +diff.cpp14.depr +diff.cpp14.except +diff.cpp14.expr +diff.cpp14.lex +diff.cpp14.library +diff.cpp14.special +diff.cpp14.string +diff.cpp14.temp +diff.cpp14.utilities +diff.cpp17 +diff.cpp17.alg.reqs +diff.cpp17.basic +diff.cpp17.class +diff.cpp17.containers +diff.cpp17.dcl.dcl +diff.cpp17.depr +diff.cpp17.except +diff.cpp17.expr +diff.cpp17.input.output +diff.cpp17.iterators +diff.cpp17.lex +diff.cpp17.library +diff.cpp17.over +diff.cpp17.temp +diff.dcl +diff.decl +diff.expr +diff.header.assert.h +diff.header.iso646.h +diff.header.stdalign.h +diff.header.stdbool.h +diff.iso +diff.lex +diff.library +diff.malloc +diff.mods.to.behavior +diff.mods.to.declarations +diff.mods.to.definitions +diff.mods.to.headers +diff.null +diff.offsetof +diff.special +diff.stat +diff.wchar.t +domain.error +enum +enum.udecl +enumerated.types +equal.range +errno +error.reporting +except +except.ctor +except.handle +except.nested +except.pre +except.spec +except.special +except.terminate +except.throw +except.uncaught +exception +exception.syn +exception.terminate +exclusive.scan +execpol +execpol.general +execpol.objects +execpol.par +execpol.parunseq +execpol.seq +execpol.type +execpol.unseq +execution.syn +expos.only.func +expos.only.types +expr +expr.add +expr.alignof +expr.arith.conv +expr.ass +expr.await +expr.bit.and +expr.call +expr.cast +expr.comma +expr.compound +expr.cond +expr.const +expr.const.cast +expr.context +expr.delete +expr.dynamic.cast +expr.eq +expr.log.and +expr.log.or +expr.mptr.oper +expr.mul +expr.new +expr.or +expr.post +expr.post.incr +expr.pre +expr.pre.incr +expr.prim +expr.prim.fold +expr.prim.id +expr.prim.id.dtor +expr.prim.id.qual +expr.prim.id.unqual +expr.prim.lambda +expr.prim.lambda.capture +expr.prim.lambda.closure +expr.prim.literal +expr.prim.paren +expr.prim.req +expr.prim.req.compound +expr.prim.req.nested +expr.prim.req.simple +expr.prim.req.type +expr.prim.this +expr.prop +expr.pseudo +expr.ref +expr.reinterpret.cast +expr.rel +expr.shift +expr.sizeof +expr.spaceship +expr.static.cast +expr.sub +expr.throw +expr.type +expr.type.conv +expr.typeid +expr.unary +expr.unary.noexcept +expr.unary.op +expr.xor +expr.yield +ext.manip +extern.names +extern.types +facet.ctype.char.dtor +facet.ctype.char.members +facet.ctype.char.statics +facet.ctype.char.virtuals +facet.ctype.special +facet.num.get.members +facet.num.get.virtuals +facet.num.put.members +facet.num.put.virtuals +facet.numpunct +facet.numpunct.members +facet.numpunct.virtuals +facets.examples +file.streams +filebuf +filebuf.assign +filebuf.cons +filebuf.members +filebuf.virtuals +filesystems +floatfield.manip +fmtflags.manip +fmtflags.state +format +format.arg +format.arg.store +format.args +format.arguments +format.context +format.err.report +format.error +format.formatter +format.formatter.spec +format.functions +format.parse.ctx +format.string +format.string.general +format.string.std +format.syn +formatter.requirements +forward +forward.iterators +forward.list.erasure +forward.list.syn +forward_list.syn +forwardlist +forwardlist.access +forwardlist.cons +forwardlist.iter +forwardlist.modifiers +forwardlist.ops +forwardlist.overview +forwardlist.spec +fp.style +fpos +fpos.members +fpos.operations +front.insert.iter.cons +front.insert.iter.op* +front.insert.iter.op++ +front.insert.iter.op= +front.insert.iter.ops +front.insert.iterator +front.inserter +fs.class.directory.entry +fs.class.directory.iterator +fs.class.directory_entry +fs.class.directory_iterator +fs.class.file.status +fs.class.file_status +fs.class.filesystem.error +fs.class.filesystem_error +fs.class.path +fs.class.rec.dir.itr +fs.conform.9945 +fs.conform.os +fs.conformance +fs.definitions +fs.dir.entry.cons +fs.dir.entry.mods +fs.dir.entry.obs +fs.dir.itr.members +fs.dir.itr.nonmembers +fs.enum +fs.enum.copy.opts +fs.enum.dir.opts +fs.enum.file.type +fs.enum.file_type +fs.enum.path.format +fs.enum.perm.opts +fs.enum.perms +fs.err.report +fs.file.status.cons +fs.file.status.mods +fs.file.status.obs +fs.file_status.cons +fs.file_status.mods +fs.file_status.obs +fs.filesystem.error.members +fs.filesystem.syn +fs.filesystem_error.members +fs.general +fs.norm.ref +fs.op.absolute +fs.op.canonical +fs.op.copy +fs.op.copy.file +fs.op.copy.symlink +fs.op.copy_file +fs.op.copy_symlink +fs.op.create.dir.symlk +fs.op.create.directories +fs.op.create.directory +fs.op.create.hard.lk +fs.op.create.symlink +fs.op.create_dir_symlk +fs.op.create_directories +fs.op.create_directory +fs.op.create_hard_lk +fs.op.create_symlink +fs.op.current.path +fs.op.current_path +fs.op.equivalent +fs.op.exists +fs.op.file.size +fs.op.file_size +fs.op.funcs +fs.op.hard.lk.ct +fs.op.hard_lk_ct +fs.op.is.block.file +fs.op.is.char.file +fs.op.is.directory +fs.op.is.empty +fs.op.is.fifo +fs.op.is.other +fs.op.is.regular.file +fs.op.is.socket +fs.op.is.symlink +fs.op.is_block_file +fs.op.is_char_file +fs.op.is_directory +fs.op.is_empty +fs.op.is_fifo +fs.op.is_other +fs.op.is_regular_file +fs.op.is_socket +fs.op.is_symlink +fs.op.last.write.time +fs.op.last_write_time +fs.op.permissions +fs.op.proximate +fs.op.read.symlink +fs.op.read_symlink +fs.op.relative +fs.op.remove +fs.op.remove.all +fs.op.remove_all +fs.op.rename +fs.op.resize.file +fs.op.resize_file +fs.op.space +fs.op.status +fs.op.status.known +fs.op.status_known +fs.op.symlink.status +fs.op.symlink_status +fs.op.temp.dir.path +fs.op.temp_dir_path +fs.op.weakly.canonical +fs.op.weakly_canonical +fs.path.append +fs.path.assign +fs.path.compare +fs.path.concat +fs.path.construct +fs.path.cvt +fs.path.decompose +fs.path.factory +fs.path.fmt.cvt +fs.path.gen +fs.path.generic +fs.path.generic.obs +fs.path.io +fs.path.itr +fs.path.member +fs.path.modifiers +fs.path.native.obs +fs.path.nonmember +fs.path.query +fs.path.req +fs.path.type.cvt +fs.race.behavior +fs.rec.dir.itr.members +fs.rec.dir.itr.nonmembers +fs.req +fs.req.general +fs.req.namespace +fstream +fstream.assign +fstream.cons +fstream.members +fstream.syn +func.bind +func.bind.bind +func.bind.front +func.bind.isbind +func.bind.isplace +func.bind.place +func.def +func.identity +func.invoke +func.memfn +func.not.fn +func.not_fn +func.require +func.search +func.search.bm +func.search.bmh +func.search.default +func.wrap +func.wrap.badcall +func.wrap.badcall.const +func.wrap.func +func.wrap.func.alg +func.wrap.func.cap +func.wrap.func.con +func.wrap.func.inv +func.wrap.func.mod +func.wrap.func.nullptr +func.wrap.func.targ +function.objects +functional.syn +functions.within.classes +future.syn +futures +futures.async +futures.errors +futures.future.error +futures.future_error +futures.overview +futures.promise +futures.shared.future +futures.shared_future +futures.state +futures.task +futures.task.members +futures.task.nonmembers +futures.unique.future +futures.unique_future +get.new.handler +get.terminate +global.functions +gram +gram.basic +gram.class +gram.cpp +gram.dcl +gram.decl +gram.derived +gram.except +gram.expr +gram.key +gram.lex +gram.module +gram.over +gram.special +gram.stmt +gram.temp +gslice.access +gslice.array.assign +gslice.array.comp.assign +gslice.array.fill +gslice.cons +handler.functions +hardware.interference +hash.requirements +headers +hidden.friends +ifstream +ifstream.assign +ifstream.cons +ifstream.members +implimits +includes +inclusive.scan +incrementable.traits +indirect.array.assign +indirect.array.comp.assign +indirect.array.fill +indirectcallable +indirectcallable.general +indirectcallable.indirectinvocable +initializer.list.syn +initializer_list.syn +inner.product +input.iterators +input.output +input.output.general +input.streams +insert.iter.cons +insert.iter.op* +insert.iter.op++ +insert.iter.op= +insert.iter.ops +insert.iterator +insert.iterators +inserter +intro +intro.abstract +intro.ack +intro.compliance +intro.defs +intro.execution +intro.memory +intro.multithread +intro.object +intro.progress +intro.races +intro.refs +intro.scope +intro.structure +intseq +intseq.general +intseq.intseq +intseq.make +invalid.argument +iomanip.syn +ios +ios.base +ios.base.callback +ios.base.cons +ios.base.locales +ios.base.storage +ios.failure +ios.fmtflags +ios.init +ios.iostate +ios.members.static +ios.openmode +ios.overview +ios.seekdir +ios.syn +ios.types +ios::Init +ios::failure +ios::fmtflags +ios::iostate +ios::openmode +ios::seekdir +iosfwd.syn +iostate.flags +iostream.assign +iostream.cons +iostream.dest +iostream.format +iostream.forward +iostream.forward.overview +iostream.limits.imbue +iostream.objects +iostream.objects.overview +iostream.syn +iostreamclass +iostreams.base +iostreams.limits.pos +iostreams.requirements +iostreams.threadsafety +is.heap +is.sorted +istream +istream.assign +istream.cons +istream.extractors +istream.formatted +istream.formatted.arithmetic +istream.formatted.reqmts +istream.iterator +istream.iterator.cons +istream.iterator.ops +istream.manip +istream.rvalue +istream.sentry +istream.syn +istream.unformatted +istream::sentry +istreambuf.iterator +istreambuf.iterator.cons +istreambuf.iterator.ops +istreambuf.iterator.proxy +istringstream +istringstream.assign +istringstream.cons +istringstream.members +iterator.assoc.types +iterator.concept.bidir +iterator.concept.contiguous +iterator.concept.forward +iterator.concept.inc +iterator.concept.input +iterator.concept.iterator +iterator.concept.output +iterator.concept.random.access +iterator.concept.readable +iterator.concept.sentinel +iterator.concept.sizedsentinel +iterator.concept.winc +iterator.concept.writable +iterator.concepts +iterator.concepts.general +iterator.container +iterator.cpp17 +iterator.cust +iterator.cust.move +iterator.cust.swap +iterator.iterators +iterator.operations +iterator.primitives +iterator.range +iterator.requirements +iterator.requirements.general +iterator.synopsis +iterator.traits +iterators +iterators.common +iterators.counted +iterators.general +language.support +latch.syn +length.error +lex +lex.bool +lex.ccon +lex.charset +lex.comment +lex.digraph +lex.ext +lex.fcon +lex.header +lex.icon +lex.key +lex.literal +lex.literal.kinds +lex.name +lex.nullptr +lex.operators +lex.phases +lex.ppnumber +lex.pptoken +lex.separate +lex.string +lex.token +lib.types.movedfrom +library +library.c +library.general +limits.syn +list +list.capacity +list.cons +list.erasure +list.modifiers +list.ops +list.overview +list.special +list.syn +locale +locale.categories +locale.category +locale.codecvt +locale.codecvt.byname +locale.codecvt.members +locale.codecvt.virtuals +locale.collate +locale.collate.byname +locale.collate.members +locale.collate.virtuals +locale.cons +locale.convenience +locale.ctype +locale.ctype.byname +locale.ctype.members +locale.ctype.virtuals +locale.facet +locale.global.templates +locale.id +locale.members +locale.messages +locale.messages.byname +locale.messages.members +locale.messages.virtuals +locale.money.get +locale.money.get.members +locale.money.get.virtuals +locale.money.put +locale.money.put.members +locale.money.put.virtuals +locale.moneypunct +locale.moneypunct.byname +locale.moneypunct.members +locale.moneypunct.virtuals +locale.nm.put +locale.num.get +locale.numpunct +locale.numpunct.byname +locale.operators +locale.statics +locale.syn +locale.time.get +locale.time.get.byname +locale.time.get.members +locale.time.get.virtuals +locale.time.put +locale.time.put.byname +locale.time.put.members +locale.time.put.virtuals +locale.types +locales +localization +localization.general +logic.error +logical.operations +logical.operations.and +logical.operations.not +logical.operations.or +lower.bound +macro.names +make.heap +map +map.access +map.cons +map.erasure +map.modifiers +map.overview +map.special +mask.array.assign +mask.array.comp.assign +mask.array.fill +math.constants +mem.poly.allocator.class +mem.poly.allocator.ctor +mem.poly.allocator.eq +mem.poly.allocator.mem +mem.res +mem.res.class +mem.res.eq +mem.res.global +mem.res.monotonic.buffer +mem.res.monotonic.buffer.ctor +mem.res.monotonic.buffer.mem +mem.res.pool +mem.res.pool.ctor +mem.res.pool.mem +mem.res.pool.options +mem.res.pool.overview +mem.res.private +mem.res.public +mem.res.syn +member.functions +memory +memory.general +memory.syn +meta +meta.const.eval +meta.help +meta.logical +meta.member +meta.rel +meta.rqmts +meta.trans +meta.trans.arr +meta.trans.cv +meta.trans.other +meta.trans.ptr +meta.trans.ref +meta.trans.sign +meta.type.synop +meta.unary +meta.unary.cat +meta.unary.comp +meta.unary.prop +meta.unary.prop.query +mismatch +module +module.context +module.global.frag +module.import +module.interface +module.private.frag +module.reach +module.unit +move.iter.cons +move.iter.elem +move.iter.nav +move.iter.nonmember +move.iter.op.+ +move.iter.op.+= +move.iter.op.- +move.iter.op.-= +move.iter.op.comp +move.iter.op.const +move.iter.op.conv +move.iter.op.decr +move.iter.op.incr +move.iter.op.index +move.iter.op.ref +move.iter.op.star +move.iter.op= +move.iter.ops +move.iter.requirements +move.iterator +move.iterators +move.sent.ops +move.sentinel +multibyte.strings +multimap +multimap.cons +multimap.erasure +multimap.modifiers +multimap.overview +multimap.special +multiset +multiset.cons +multiset.erasure +multiset.overview +multiset.special +mutex.syn +namespace.alias +namespace.constraints +namespace.def +namespace.future +namespace.memdef +namespace.posix +namespace.qual +namespace.std +namespace.udecl +namespace.udir +namespace.unnamed +narrow.stream.objects +new.badlength +new.delete +new.delete.array +new.delete.dataraces +new.delete.placement +new.delete.single +new.handler +new.syn +nullablepointer.requirements +numarray +numbers +numbers.syn +numeric.iota +numeric.limits +numeric.limits.members +numeric.ops +numeric.ops.gcd +numeric.ops.lcm +numeric.ops.midpoint +numeric.ops.overview +numeric.requirements +numeric.special +numerics +numerics.defns +numerics.general +objects.within.classes +ofstream +ofstream.assign +ofstream.cons +ofstream.members +operators +optional +optional.assign +optional.bad.access +optional.comp.with.t +optional.comp_with_t +optional.ctor +optional.dtor +optional.general +optional.hash +optional.mod +optional.nullops +optional.nullopt +optional.observe +optional.optional +optional.relops +optional.specalg +optional.swap +optional.syn +organization +ostream +ostream.assign +ostream.cons +ostream.formatted +ostream.formatted.reqmts +ostream.inserters +ostream.inserters.arithmetic +ostream.inserters.character +ostream.iterator +ostream.iterator.cons.des +ostream.iterator.ops +ostream.manip +ostream.rvalue +ostream.seeks +ostream.sentry +ostream.syn +ostream.unformatted +ostream::sentry +ostreambuf.iter.cons +ostreambuf.iter.ops +ostreambuf.iterator +ostringstream +ostringstream.assign +ostringstream.cons +ostringstream.members +out.of.range +output.iterators +output.streams +over +over.ass +over.best.ics +over.binary +over.built +over.call +over.call.func +over.call.object +over.dcl +over.ics.ellipsis +over.ics.list +over.ics.rank +over.ics.ref +over.ics.scs +over.ics.user +over.inc +over.literal +over.load +over.match +over.match.best +over.match.call +over.match.class.deduct +over.match.conv +over.match.copy +over.match.ctor +over.match.funcs +over.match.list +over.match.oper +over.match.ref +over.match.viable +over.oper +over.over +over.pre +over.ref +over.sub +over.unary +overflow.error +pair.astuple +pair.piecewise +pairs +pairs.general +pairs.pair +pairs.spec +partial.sort +partial.sort.copy +partial.sum +pointer.conversion +pointer.traits +pointer.traits.functions +pointer.traits.optmem +pointer.traits.types +pop.heap +predef.iterators +priority.queue +priqueue.cons +priqueue.cons.alloc +priqueue.members +priqueue.overview +priqueue.special +projected +propagation +protection.within.classes +ptr.align +ptr.launder +push.heap +queue +queue.cons +queue.cons.alloc +queue.defn +queue.ops +queue.special +queue.syn +quoted.manip +rand +rand.adapt +rand.adapt.disc +rand.adapt.general +rand.adapt.ibits +rand.adapt.shuf +rand.device +rand.dist +rand.dist.bern +rand.dist.bern.bernoulli +rand.dist.bern.bin +rand.dist.bern.geo +rand.dist.bern.negbin +rand.dist.general +rand.dist.norm +rand.dist.norm.cauchy +rand.dist.norm.chisq +rand.dist.norm.f +rand.dist.norm.lognormal +rand.dist.norm.normal +rand.dist.norm.t +rand.dist.pois +rand.dist.pois.exp +rand.dist.pois.extreme +rand.dist.pois.gamma +rand.dist.pois.poisson +rand.dist.pois.weibull +rand.dist.samp +rand.dist.samp.discrete +rand.dist.samp.pconst +rand.dist.samp.plinear +rand.dist.uni +rand.dist.uni.int +rand.dist.uni.real +rand.eng +rand.eng.lcong +rand.eng.mers +rand.eng.sub +rand.predef +rand.req +rand.req.adapt +rand.req.dist +rand.req.eng +rand.req.genl +rand.req.seedseq +rand.req.urng +rand.synopsis +rand.util +rand.util.canonical +rand.util.seedseq +random.access.iterators +range.access +range.access.begin +range.access.cbegin +range.access.cend +range.access.crbegin +range.access.crend +range.access.end +range.access.rbegin +range.access.rend +range.adaptor.object +range.adaptors +range.all +range.cmp +range.common +range.common.overview +range.common.view +range.counted +range.dangling +range.drop +range.drop.overview +range.drop.view +range.drop.while +range.drop.while.overview +range.drop.while.view +range.elements +range.elements.iterator +range.elements.overview +range.elements.sentinel +range.elements.view +range.empty +range.empty.overview +range.empty.view +range.error +range.factories +range.filter +range.filter.iterator +range.filter.overview +range.filter.sentinel +range.filter.view +range.iota +range.iota.iterator +range.iota.overview +range.iota.sentinel +range.iota.view +range.istream +range.istream.iterator +range.istream.overview +range.istream.view +range.iter.op.advance +range.iter.op.distance +range.iter.op.next +range.iter.op.prev +range.iter.ops +range.join +range.join.iterator +range.join.overview +range.join.sentinel +range.join.view +range.prim.cdata +range.prim.data +range.prim.empty +range.prim.size +range.prim.ssize +range.range +range.ref.view +range.refinements +range.req +range.req.general +range.reverse +range.reverse.overview +range.reverse.view +range.semi.wrap +range.single +range.single.overview +range.single.view +range.sized +range.split +range.split.inner +range.split.outer +range.split.outer.value +range.split.overview +range.split.view +range.subrange +range.subrange.access +range.subrange.ctor +range.take +range.take.overview +range.take.sentinel +range.take.view +range.take.while +range.take.while.overview +range.take.while.sentinel +range.take.while.view +range.transform +range.transform.iterator +range.transform.overview +range.transform.sentinel +range.transform.view +range.utility +range.utility.helpers +range.view +ranges +ranges.general +ranges.syn +ratio +ratio.arithmetic +ratio.comparison +ratio.general +ratio.ratio +ratio.si +ratio.syn +re +re.alg +re.alg.match +re.alg.replace +re.alg.search +re.badexp +re.const +re.def +re.err +re.except +re.general +re.grammar +re.iter +re.matchflag +re.regex +re.regex.assign +re.regex.const +re.regex.construct +re.regex.locale +re.regex.nmswap +re.regex.nonmemb +re.regex.operations +re.regex.swap +re.regiter +re.regiter.cnstr +re.regiter.comp +re.regiter.deref +re.regiter.incr +re.req +re.results +re.results.acc +re.results.all +re.results.const +re.results.form +re.results.nonmember +re.results.size +re.results.state +re.results.swap +re.submatch +re.submatch.members +re.submatch.op +re.syn +re.synopt +re.tokiter +re.tokiter.cnstr +re.tokiter.comp +re.tokiter.deref +re.tokiter.incr +re.traits +readable.traits +reduce +reentrancy +refwrap +refwrap.access +refwrap.assign +refwrap.const +refwrap.helpers +refwrap.invoke +replacement.functions +requirements +res.on.arguments +res.on.data.races +res.on.exception.handling +res.on.expects +res.on.functions +res.on.headers +res.on.macro.definitions +res.on.objects +res.on.pointer.storage +res.on.required +res.on.requirements +reserved.names +reverse.iter.cmp +reverse.iter.cons +reverse.iter.conv +reverse.iter.elem +reverse.iter.make +reverse.iter.nav +reverse.iter.nonmember +reverse.iter.op"!= +reverse.iter.op+ +reverse.iter.op++ +reverse.iter.op+= +reverse.iter.op- +reverse.iter.op-- +reverse.iter.op-= +reverse.iter.op.star +reverse.iter.op< +reverse.iter.op<= +reverse.iter.op= +reverse.iter.op== +reverse.iter.op> +reverse.iter.op>= +reverse.iter.opdiff +reverse.iter.opindex +reverse.iter.opref +reverse.iter.ops +reverse.iter.opsum +reverse.iter.requirements +reverse.iterator +reverse.iterators +round.style +runtime.error +scoped.adaptor.operators +semaphore.syn +sequence.reqmts +sequences +sequences.general +set +set.cons +set.difference +set.erasure +set.intersection +set.new.handler +set.overview +set.special +set.symmetric.difference +set.terminate +set.union +sf.cmath +sf.cmath.assoc.laguerre +sf.cmath.assoc.legendre +sf.cmath.assoc_laguerre +sf.cmath.assoc_legendre +sf.cmath.beta +sf.cmath.comp.ellint.1 +sf.cmath.comp.ellint.2 +sf.cmath.comp.ellint.3 +sf.cmath.comp_ellint_1 +sf.cmath.comp_ellint_2 +sf.cmath.comp_ellint_3 +sf.cmath.cyl.bessel.i +sf.cmath.cyl.bessel.j +sf.cmath.cyl.bessel.k +sf.cmath.cyl.neumann +sf.cmath.cyl_bessel_i +sf.cmath.cyl_bessel_j +sf.cmath.cyl_bessel_k +sf.cmath.cyl_neumann +sf.cmath.ellint.1 +sf.cmath.ellint.2 +sf.cmath.ellint.3 +sf.cmath.ellint_1 +sf.cmath.ellint_2 +sf.cmath.ellint_3 +sf.cmath.expint +sf.cmath.hermite +sf.cmath.laguerre +sf.cmath.legendre +sf.cmath.riemann.zeta +sf.cmath.riemann_zeta +sf.cmath.sph.bessel +sf.cmath.sph.legendre +sf.cmath.sph.neumann +sf.cmath.sph_bessel +sf.cmath.sph_legendre +sf.cmath.sph_neumann +shared.mutex.syn +shared_mutex.syn +slice.access +slice.arr.assign +slice.arr.comp.assign +slice.arr.fill +slice.ops +smartptr +sort +sort.heap +source.location.syn +span.cons +span.deduct +span.elem +span.iterators +span.objectrep +span.obs +span.overview +span.sub +span.syn +special +special.mem.concepts +specialized.addressof +specialized.algorithms +specialized.construct +specialized.destroy +sstream.syn +stable.sort +stack +stack.cons +stack.cons.alloc +stack.defn +stack.ops +stack.special +stack.syn +std.exceptions +std.ios.manip +std.iterator.tags +std.manip +stdexcept.syn +stmt.ambig +stmt.block +stmt.break +stmt.cont +stmt.dcl +stmt.do +stmt.expr +stmt.for +stmt.goto +stmt.if +stmt.iter +stmt.jump +stmt.label +stmt.pre +stmt.ranged +stmt.return +stmt.return.coroutine +stmt.select +stmt.stmt +stmt.switch +stmt.while +stopcallback +stopcallback.cons +stopsource +stopsource.cons +stopsource.mem +stopsource.nonmembers +stoptoken +stoptoken.cons +stoptoken.mem +stoptoken.nonmembers +stream.buffers +stream.iterators +stream.types +streambuf +streambuf.assign +streambuf.buffer +streambuf.cons +streambuf.get.area +streambuf.locales +streambuf.members +streambuf.protected +streambuf.pub.get +streambuf.pub.pback +streambuf.pub.put +streambuf.put.area +streambuf.reqts +streambuf.syn +streambuf.virt.buffer +streambuf.virt.get +streambuf.virt.locales +streambuf.virt.pback +streambuf.virt.put +streambuf.virtuals +string.access +string.accessors +string.append +string.assign +string.capacity +string.classes +string.cmp +string.compare +string.cons +string.conversions +string.copy +string.ends.with +string.erase +string.erasure +string.find +string.find.first.not.of +string.find.first.of +string.find.last.not.of +string.find.last.of +string.insert +string.io +string.iterators +string.modifiers +string.nonmembers +string.op"!= +string.op+ +string.op+= +string.op.append +string.op.plus +string.op< +string.op<= +string.op> +string.op>= +string.operator== +string.ops +string.replace +string.require +string.rfind +string.special +string.starts.with +string.streams +string.substr +string.swap +string.syn +string.view +string.view.access +string.view.capacity +string.view.comparison +string.view.cons +string.view.deduct +string.view.find +string.view.hash +string.view.io +string.view.iterators +string.view.literals +string.view.modifiers +string.view.ops +string.view.synop +string.view.template +stringbuf +stringbuf.assign +stringbuf.cons +stringbuf.members +stringbuf.virtuals +strings +strings.general +stringstream +stringstream.assign +stringstream.cons +stringstream.members +structure +structure.elements +structure.requirements +structure.see.also +structure.specifications +structure.summary +support +support.coroutine +support.dynamic +support.exception +support.general +support.initlist +support.initlist.access +support.initlist.cons +support.initlist.range +support.limits +support.limits.general +support.rtti +support.runtime +support.signal +support.srcloc +support.srcloc.class +support.srcloc.cons +support.srcloc.obs +support.start.term +support.types +support.types.byteops +support.types.layout +support.types.nullptr +swappable.requirements +syncstream +syncstream.osyncstream +syncstream.osyncstream.cons +syncstream.osyncstream.members +syncstream.osyncstream.overview +syncstream.syn +syncstream.syncbuf +syncstream.syncbuf.assign +syncstream.syncbuf.cons +syncstream.syncbuf.members +syncstream.syncbuf.overview +syncstream.syncbuf.special +syncstream.syncbuf.virtuals +syntax +syserr +syserr.compare +syserr.errcat +syserr.errcat.derived +syserr.errcat.nonvirtuals +syserr.errcat.objects +syserr.errcat.overview +syserr.errcat.virtuals +syserr.errcode +syserr.errcode.constructors +syserr.errcode.modifiers +syserr.errcode.nonmembers +syserr.errcode.observers +syserr.errcode.overview +syserr.errcondition +syserr.errcondition.constructors +syserr.errcondition.modifiers +syserr.errcondition.nonmembers +syserr.errcondition.observers +syserr.errcondition.overview +syserr.hash +syserr.syserr +syserr.syserr.members +syserr.syserr.overview +system.error.syn +system_error.syn +temp +temp.alias +temp.arg +temp.arg.explicit +temp.arg.nontype +temp.arg.template +temp.arg.type +temp.class +temp.class.order +temp.class.spec +temp.class.spec.general +temp.class.spec.match +temp.class.spec.mfunc +temp.concept +temp.constr +temp.constr.atomic +temp.constr.constr +temp.constr.decl +temp.constr.normal +temp.constr.op +temp.constr.order +temp.decls +temp.deduct +temp.deduct.call +temp.deduct.conv +temp.deduct.decl +temp.deduct.funcaddr +temp.deduct.guide +temp.deduct.partial +temp.deduct.type +temp.dep +temp.dep.candidate +temp.dep.constexpr +temp.dep.expr +temp.dep.res +temp.dep.temp +temp.dep.type +temp.expl.spec +temp.explicit +temp.fct +temp.fct.spec +temp.friend +temp.func.order +temp.inject +temp.inst +temp.local +temp.mem +temp.mem.class +temp.mem.enum +temp.mem.func +temp.names +temp.nondep +temp.over +temp.over.link +temp.param +temp.point +temp.pre +temp.res +temp.spec +temp.static +temp.type +temp.variadic +template.bitset +template.gslice.array +template.gslice.array.overview +template.indirect.array +template.indirect.array.overview +template.mask.array +template.mask.array.overview +template.slice.array +template.slice.array.overview +template.valarray +template.valarray.overview +terminate +terminate.handler +thread +thread.barrier +thread.barrier.class +thread.condition +thread.condition.condvar +thread.condition.condvarany +thread.condition.nonmember +thread.condvarany.intwait +thread.condvarany.wait +thread.coord +thread.decaycopy +thread.general +thread.jthread.class +thread.jthread.cons +thread.jthread.mem +thread.jthread.special +thread.jthread.static +thread.jthread.stop +thread.latch +thread.latch.class +thread.lock +thread.lock.algorithm +thread.lock.guard +thread.lock.scoped +thread.lock.shared +thread.lock.shared.cons +thread.lock.shared.locking +thread.lock.shared.mod +thread.lock.shared.obs +thread.lock.unique +thread.lock.unique.cons +thread.lock.unique.locking +thread.lock.unique.mod +thread.lock.unique.obs +thread.mutex +thread.mutex.class +thread.mutex.recursive +thread.mutex.requirements +thread.mutex.requirements.general +thread.mutex.requirements.mutex +thread.once +thread.once.callonce +thread.once.onceflag +thread.req +thread.req.exception +thread.req.lockable +thread.req.lockable.basic +thread.req.lockable.general +thread.req.lockable.req +thread.req.lockable.timed +thread.req.native +thread.req.paramname +thread.req.timing +thread.sema +thread.sema.cnt +thread.sharedmutex.class +thread.sharedmutex.requirements +thread.sharedtimedmutex.class +thread.sharedtimedmutex.requirements +thread.stoptoken +thread.stoptoken.intro +thread.stoptoken.syn +thread.syn +thread.thread.algorithm +thread.thread.assign +thread.thread.class +thread.thread.constr +thread.thread.destr +thread.thread.id +thread.thread.member +thread.thread.static +thread.thread.this +thread.threads +thread.timedmutex.class +thread.timedmutex.recursive +thread.timedmutex.requirements +time +time.12 +time.cal +time.cal.day +time.cal.day.members +time.cal.day.nonmembers +time.cal.day.overview +time.cal.general +time.cal.last +time.cal.md +time.cal.md.members +time.cal.md.nonmembers +time.cal.md.overview +time.cal.mdlast +time.cal.month +time.cal.month.members +time.cal.month.nonmembers +time.cal.month.overview +time.cal.mwd +time.cal.mwd.members +time.cal.mwd.nonmembers +time.cal.mwd.overview +time.cal.mwdlast +time.cal.mwdlast.members +time.cal.mwdlast.nonmembers +time.cal.mwdlast.overview +time.cal.operators +time.cal.wd +time.cal.wd.members +time.cal.wd.nonmembers +time.cal.wd.overview +time.cal.wdidx +time.cal.wdidx.members +time.cal.wdidx.nonmembers +time.cal.wdidx.overview +time.cal.wdlast +time.cal.wdlast.members +time.cal.wdlast.nonmembers +time.cal.wdlast.overview +time.cal.year +time.cal.year.members +time.cal.year.nonmembers +time.cal.year.overview +time.cal.ym +time.cal.ym.members +time.cal.ym.nonmembers +time.cal.ym.overview +time.cal.ymd +time.cal.ymd.members +time.cal.ymd.nonmembers +time.cal.ymd.overview +time.cal.ymdlast +time.cal.ymdlast.members +time.cal.ymdlast.nonmembers +time.cal.ymdlast.overview +time.cal.ymwd +time.cal.ymwd.members +time.cal.ymwd.nonmembers +time.cal.ymwd.overview +time.cal.ymwdlast +time.cal.ymwdlast.members +time.cal.ymwdlast.nonmembers +time.cal.ymwdlast.overview +time.clock +time.clock.cast +time.clock.cast.fn +time.clock.cast.id +time.clock.cast.sys +time.clock.cast.sys.utc +time.clock.cast.utc +time.clock.conv +time.clock.file +time.clock.file.members +time.clock.file.nonmembers +time.clock.file.overview +time.clock.gps +time.clock.gps.members +time.clock.gps.nonmembers +time.clock.gps.overview +time.clock.hires +time.clock.local +time.clock.req +time.clock.steady +time.clock.system +time.clock.system.members +time.clock.system.nonmembers +time.clock.system.overview +time.clock.tai +time.clock.tai.members +time.clock.tai.nonmembers +time.clock.tai.overview +time.clock.utc +time.clock.utc.members +time.clock.utc.nonmembers +time.clock.utc.overview +time.duration +time.duration.alg +time.duration.arithmetic +time.duration.cast +time.duration.comparisons +time.duration.cons +time.duration.io +time.duration.literals +time.duration.nonmember +time.duration.observer +time.duration.special +time.format +time.general +time.hms +time.hms.members +time.hms.nonmembers +time.hms.overview +time.parse +time.point +time.point.arithmetic +time.point.cast +time.point.comparisons +time.point.cons +time.point.nonmember +time.point.observer +time.point.special +time.syn +time.traits +time.traits.duration.values +time.traits.duration_values +time.traits.is.clock +time.traits.is.fp +time.traits.is_fp +time.traits.specializations +time.zone +time.zone.db +time.zone.db.access +time.zone.db.list +time.zone.db.remote +time.zone.db.tzdb +time.zone.exception +time.zone.exception.ambig +time.zone.exception.nonexist +time.zone.general +time.zone.info +time.zone.info.local +time.zone.info.sys +time.zone.leap +time.zone.leap.members +time.zone.leap.nonmembers +time.zone.leap.overview +time.zone.link +time.zone.link.members +time.zone.link.nonmembers +time.zone.link.overview +time.zone.members +time.zone.nonmembers +time.zone.overview +time.zone.timezone +time.zone.zonedtime +time.zone.zonedtime.ctor +time.zone.zonedtime.members +time.zone.zonedtime.nonmembers +time.zone.zonedtime.overview +time.zone.zonedtraits +transform.exclusive.scan +transform.inclusive.scan +transform.reduce +tuple +tuple.apply +tuple.assign +tuple.cnstr +tuple.creation +tuple.elem +tuple.general +tuple.helper +tuple.rel +tuple.special +tuple.swap +tuple.syn +tuple.traits +tuple.tuple +type.descriptions +type.descriptions.general +type.index +type.index.hash +type.index.members +type.index.overview +type.index.synopsis +type.info +typeinfo.syn +uaxid.def.rfmt +uncaught.exceptions +underflow.error +uninitialized.construct.default +uninitialized.construct.value +uninitialized.copy +uninitialized.fill +uninitialized.move +unique.ptr +unique.ptr.create +unique.ptr.dltr +unique.ptr.dltr.dflt +unique.ptr.dltr.dflt1 +unique.ptr.dltr.general +unique.ptr.io +unique.ptr.runtime +unique.ptr.runtime.asgn +unique.ptr.runtime.ctor +unique.ptr.runtime.modifiers +unique.ptr.runtime.observers +unique.ptr.single +unique.ptr.single.asgn +unique.ptr.single.ctor +unique.ptr.single.dtor +unique.ptr.single.modifiers +unique.ptr.single.observers +unique.ptr.special +unord +unord.general +unord.hash +unord.map +unord.map.cnstr +unord.map.elem +unord.map.erasure +unord.map.modifiers +unord.map.overview +unord.map.swap +unord.map.syn +unord.multimap +unord.multimap.cnstr +unord.multimap.erasure +unord.multimap.modifiers +unord.multimap.overview +unord.multimap.swap +unord.multiset +unord.multiset.cnstr +unord.multiset.erasure +unord.multiset.overview +unord.multiset.swap +unord.req +unord.req.except +unord.set +unord.set.cnstr +unord.set.erasure +unord.set.overview +unord.set.swap +unord.set.syn +unreachable.sentinel +unreachable.sentinels +upper.bound +using +using.headers +using.linkage +using.overview +usrlit.suffix +util.dynamic.safety +util.smartptr +util.smartptr.atomic +util.smartptr.atomic.shared +util.smartptr.atomic.weak +util.smartptr.enab +util.smartptr.getdeleter +util.smartptr.hash +util.smartptr.ownerless +util.smartptr.shared +util.smartptr.shared.assign +util.smartptr.shared.atomic +util.smartptr.shared.cast +util.smartptr.shared.cmp +util.smartptr.shared.const +util.smartptr.shared.create +util.smartptr.shared.dest +util.smartptr.shared.io +util.smartptr.shared.mod +util.smartptr.shared.obs +util.smartptr.shared.spec +util.smartptr.weak +util.smartptr.weak.assign +util.smartptr.weak.bad +util.smartptr.weak.const +util.smartptr.weak.dest +util.smartptr.weak.mod +util.smartptr.weak.obs +util.smartptr.weak.spec +utilities +utilities.general +utility +utility.arg.requirements +utility.as.const +utility.as_const +utility.exchange +utility.from.chars +utility.intcmp +utility.requirements +utility.swap +utility.syn +utility.to.chars +utility.unreachable +valarray.access +valarray.assign +valarray.binary +valarray.cassign +valarray.comparison +valarray.cons +valarray.members +valarray.nonmembers +valarray.range +valarray.special +valarray.sub +valarray.syn +valarray.transcend +valarray.unary +value.error.codes +variant +variant.assign +variant.bad.access +variant.ctor +variant.dtor +variant.general +variant.get +variant.hash +variant.helper +variant.mod +variant.monostate +variant.monostate.relops +variant.relops +variant.specalg +variant.status +variant.swap +variant.syn +variant.traits +variant.variant +variant.visit +vector +vector.bool +vector.capacity +vector.cons +vector.data +vector.erasure +vector.modifiers +vector.overview +vector.special +vector.syn +version.syn +view.interface +view.interface.members +views +views.general +views.span +wide.stream.objects +zombie.names diff --git a/tools/check-output.sh b/tools/check-output.sh index 867e38e661..a28d236e0c 100755 --- a/tools/check-output.sh +++ b/tools/check-output.sh @@ -36,7 +36,7 @@ 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.*\..//' | + sed 's/}//g' | sed 's/^tab://;s/fig://;s/eq://;s/idx.*\..//' | grep -v '^[a-z.0-9]*$' | sed 's/^\(.*\)$/bad label \1/' | fail || failed=1 @@ -48,9 +48,15 @@ cat std-grammarindex.ind | sed 's/^\(.*\)$/grammar non-terminal \1 has no definition/' | fail || failed=1 +# Find header index entries missing a definition +cat std-headerindex.ind | + awk 'BEGIN { def=1 } /^ .item/ { if (def==0) { gsub("[{},]", "", item); print item } i=NF; while (i > 0 && $i !~ "<[a-z_.]*>") { --i; } item=$i; def=0; next } /hyperindexformat/ { def=1 }' | + sed 's/^\(.*\)$/header \1 has no definition/' | + fail || failed=1 + # Find concept index entries missing a definition cat std-conceptindex.ind | - sed 's/.hyperindexformat/\nhyperindexformat/;s/.hyperpage/hyperpage/' | + sed 's/.hyperindexformat/\nhyperindexformat/;s/.hyperpage/\nhyperpage/g' | awk 'BEGIN { def=1 } /^ .item/ { if (def==0) { gsub("[{},]", "", item); print item } item=$NF; def=0; next } /hyperindexformat/ { def=1 }' | sed 's/^\(.*\)$/concept \1 has no definition/' | fail || failed=1 @@ -58,13 +64,21 @@ cat std-conceptindex.ind | # Find undecorated concept names in code blocks patt="`cat std-conceptindex.ind | sed 's/.hyperindexformat/\nhyperindexformat/;s/.hyperpage/\nhyperpage/' | - sed -n 's/^ .item.*{\([-a-z_]*\)}.*$/\1/p'`" + sed -n 's/^ .item.*{\([-a-z_]*\)}.*$/\1/p;s/^ .item.*frenchspacing \([a-z_]*\)}.*$/\1/p'`" patt="`echo $patt | sed 's/ /\\\\|/g'`" # $patt contains all concept names, separated by \| to use as a sed regex for f in *.tex; do - sed -n 's,//.*$,,;s/%.*$//;s/"[^"]*"/""/;/begin{codeblock\(tu\)\?}/,/end{codeblock\(tu\)\?}/{/[^-_{a-z\]\('"$patt"'\)[^-_}a-z();]/{=;p;};}' $f | + # handle codeblock + sed -n 's,//.*$,,;s/%.*$//;s/"[^"]*"/""/;/begin{codeblock\(tu\)\?}/,/end{codeblock\(tu\)\?}/{/[^-_a-z\]\('"$patt"'\)[^-_}a-z0-9();,]/{=;p;};}' $f | + # prefix output with filename and line + sed '/^[0-9]\+$/{N;s/\n/:/;}' | sed "s/.*/$f:&/" | + grep -v "@.seebelow" | + sed "s/\$/ -- concept name without markup/" | + fail || failed=1 + # handle itemdecl + sed -n 's,//.*$,,;s/%.*$//;s/"[^"]*"/""/;/begin{itemdecl}/,/end{itemdecl}/{/[^-_a-z]\('"$patt"'\)[^-_a-z();,]/{/concept{[a-z_-]*}/d;=;p;};}' $f | # prefix output with filename and line sed '/^[0-9]\+$/{N;s/\n/:/;}' | sed "s/.*/$f:&/" | grep -v "@.seebelow" | @@ -72,12 +86,12 @@ for f in *.tex; do fail || failed=1 done -# Cross references since the previous standard. -# Note: xrefprev should be a copy of the previous standard's xrefindex.glo. -function indexentries() { sed 's,\\glossaryentry{\(.*\)@.*,\1,' "$1" | LANG=C sort; } +# Cross references since C++17. +# Note: xrefprev should contain a sorted list of C++17 labels. +function indexentries() { sed 's,\\glossaryentry{\(.*\)@.*,\1,' "$1" | LC_ALL=C sort; } function removals() { diff -u "$1" "$2" | grep '^-' | grep -v '^---' | sed 's/^-//'; } function difference() { diff -u "$1" "$2" | grep '^[-+]' | grep -v '^\(---\|+++\)'; } -XREFDELTA="$(difference <(indexentries xrefdelta.glo) <(removals <(indexentries xrefprev) <(indexentries xrefindex.glo)))" +XREFDELTA="$(difference <(indexentries xrefdelta.glo) <(removals xrefprev <(indexentries xrefindex.glo)))" if [ -n "$XREFDELTA" ]; then echo "incorrect entries in xrefdelta.tex:" >&2 echo "$XREFDELTA" | sed 's,^-,spurious ,; s,^+,missing ,;' >&2 diff --git a/tools/check-source.sh b/tools/check-source.sh index 5ddbdf9dfc..0babcd2af8 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 threads.tex" +texlibdesc="support.tex concepts.tex diagnostics.tex memory.tex meta.tex utilities.tex containers.tex iterators.tex ranges.tex algorithms.tex strings.tex text.tex numerics.tex time.tex iostreams.tex threads.tex exec.tex" texlib="lib-intro.tex $texlibdesc" # Filter that reformats the error message as a "workflow command", @@ -22,6 +22,9 @@ function fail() { } +# We require GNU tools. +sed --version | grep -Fqe "GNU sed" || { echo "sed is not GNU sed"; exit 1; } + # Find non-ASCII (Unicode) characters in the source LC_ALL=C grep -ne '[^ -~ ]' *.tex | fail 'non-ASCII character' || failed=1 @@ -94,9 +97,17 @@ 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 -- "--" | +grep -n '.(\\ref{' $texfiles | grep -v -- "--" | fail 'use \\iref instead of (\\ref' || failed=1 +# \iref cannot be at the start of a line +grep -n '^\\iref' $texfiles | + fail '\\iref must be flush against the preceding word, not at the start of a line' || failed=1 + +# \iref cannot be preceded by space +grep -n ' \\iref' $texfiles | + fail '\\iref must not be preceded by space' || failed=1 + # Use \xrefc instead of "ISO C x.y.z" grep -n "^ISO C [0-9]*\." $texfiles | fail 'use \\xrefc instead' || failed=1 @@ -140,6 +151,9 @@ done | grep -F -ne ') const&' $texlib | fail 'no space between cv-qualifier and ref-qualifier' || failed=1 +grep -n '\\\(def\)\?\(lib\|expos\)concept{[a-z0-9_-]*[^a-z0-9_}-][a-z0-9_-]*}' $texlib | + fail 'bad concept name' || 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 @@ -170,7 +184,7 @@ for f in $texfiles; do sed '/^[0-9]\+$/{N;s/\n/:/;}' | sed "s/.*/$f:&/" | awk '{ match($0,"^[-a-z0-9]*[.]tex:[0-9]*:"); n=match(substr($0,RLENGTH+1),"[ ;]//"); if (n % 4 != 0) print "comment starts in column " n ": " $0; }' done | - fail "comment not aligned" || failed=1 + fail "comment not aligned to multiple of 4" || failed=1 # Deleted special member function with a parameter name. grep -n "&[ 0-9a-z_]\+) = delete" $texfiles | @@ -245,7 +259,7 @@ done | fail 'subclause without siblings' || failed=1 for f in $texlibdesc; do sed -n '/begin{itemdescr}/,/end{itemdescr}/{=;p;}' < $f | sed '/^[0-9]\+$/{N;s/\n/:/;}' | sed "s/.*/$f:&/" | - awk -F: '$3 ~ /^\\pnum/ { seenpnum=1; next } $3 ~ /^\\index/ { next } $3 ~ /^\\(constraints|mandates|expects|effects|sync|ensures|returns|throws|complexity|remarks|errors|recommended)/ { if(seenpnum == 0) { print $0 } } { seenpnum=0 }' + awk -F: '$3 ~ /^\\pnum/ { seenpnum=1; next } $3 ~ /^\\index/ { next } $3 ~ /^\\(constraints|mandates|constantwhen|expects|hardexpects|effects|sync|ensures|returns|throws|complexity|remarks|errors|recommended)/ { if(seenpnum == 0) { print $0 } } { seenpnum=0 }' done | fail '\\pnum missing' || failed=1 diff --git a/tools/gitconfig.sh b/tools/gitconfig.sh index 9a6d697447..b0488b1b9e 100755 --- a/tools/gitconfig.sh +++ b/tools/gitconfig.sh @@ -1,3 +1,16 @@ #!/bin/sh git config diff.orderFile .gitorder git config diff.c++draft.xfuncname '\\rSec[0-9]+(\[.*\])\{' + +precommit="$(git rev-parse --git-dir)/hooks/pre-commit" + +test -f "${precommit}" && exit +read -p "Install 'make check' pre-commit hook? [Y/n] " hook +if [ -z "${hook}" -o "${hook}" = "y" -o "${hook}" = "Y" ]; then + cat < "${precommit}" +#!/bin/sh +cd \$(git rev-parse --show-toplevel)/source +make check +EOF + chmod +x "${precommit}" +fi diff --git a/tools/sections.cpp b/tools/sections.cpp index 0c658ea2da..b18d9a24e5 100644 --- a/tools/sections.cpp +++ b/tools/sections.cpp @@ -132,7 +132,7 @@ int main(int argc, char** argv) try { process(argv[1]); - } catch (std::exception e) { + } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return 1; }